initial commit
This commit is contained in:
commit
1f5fffe76a
4 changed files with 1402 additions and 0 deletions
26
bf.py
Executable file
26
bf.py
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
class bf(object):
|
||||||
|
def __init__(self,value=0):
|
||||||
|
self._d = value
|
||||||
|
|
||||||
|
def __getitem__(self, index):
|
||||||
|
return (self._d >> index) & 1
|
||||||
|
|
||||||
|
def __setitem__(self,index,value):
|
||||||
|
value = (value&1L)<<index
|
||||||
|
mask = (1L)<<index
|
||||||
|
self._d = (self._d & ~mask) | value
|
||||||
|
|
||||||
|
def __getslice__(self, start, end):
|
||||||
|
mask = 2L**(end - start) -1
|
||||||
|
return (self._d >> start) & mask
|
||||||
|
|
||||||
|
def __setslice__(self, start, end, value):
|
||||||
|
mask = 2L**(end - start) -1
|
||||||
|
value = (value & mask) << start
|
||||||
|
mask = mask << start
|
||||||
|
self._d = (self._d & ~mask) | value
|
||||||
|
return (self._d >> start) & mask
|
||||||
|
|
||||||
|
def __int__(self):
|
||||||
|
return self._d
|
802
h3m.py
Executable file
802
h3m.py
Executable file
|
@ -0,0 +1,802 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
copyright 2008 - Johannes 'josch' Schauer <j.schauer@email.de>
|
||||||
|
copyright 2010 - Remigiusz 'Enleth' Marcinkiewicz <enleth@enleth.com>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import gzip
|
||||||
|
import struct
|
||||||
|
import chardet
|
||||||
|
import binascii
|
||||||
|
#from guess_language import guessLanguage
|
||||||
|
from lxml import etree
|
||||||
|
from lxml import objectify
|
||||||
|
from bf import bf
|
||||||
|
from h3m_ids import *
|
||||||
|
|
||||||
|
def edet(string):
|
||||||
|
e = chardet.detect(string)
|
||||||
|
if e["encoding"] in h3m_encoding_quirks:
|
||||||
|
e["encoding"] = h3m_encoding_quirks[e["encoding"]]
|
||||||
|
return e
|
||||||
|
|
||||||
|
def extract(filename):
|
||||||
|
h3m_data = gzip.open(filename)
|
||||||
|
r = lambda s: struct.unpack(s,h3m_data.read(struct.calcsize(s)))
|
||||||
|
E = objectify.ElementMaker(annotate=False)
|
||||||
|
|
||||||
|
try:
|
||||||
|
vver = h3m_versions[r("<I")[0]]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError("Invalid game version or not a HoMM 3 map")
|
||||||
|
|
||||||
|
if vver == "WoG":
|
||||||
|
raise NotImplementedError("WoG maps not supported yet")
|
||||||
|
|
||||||
|
(vhas_players, vsize, vunderground) = r("<BIB");
|
||||||
|
if vunderground not in [0,1]:
|
||||||
|
raise ValueError("Underground specifier not in [0,1]")
|
||||||
|
vunderground = str(bool(vunderground))
|
||||||
|
m = E.map(version=vver,size=str(vsize),underground=vunderground)
|
||||||
|
m.append(E.conversion_metadata())
|
||||||
|
|
||||||
|
(vlength, ) = r("<I")
|
||||||
|
if vlength>30:
|
||||||
|
raise ValueError("Map name longer than 30 characters, possibly an invalid file")
|
||||||
|
vname = h3m_data.read(vlength)
|
||||||
|
enc = edet(vname)
|
||||||
|
vname = vname.decode(enc["encoding"])
|
||||||
|
m.append(E.name(vname))
|
||||||
|
m.conversion_metadata.append(E.encoding(enc["encoding"],entity="/map/name[0]",confidence=str(enc["confidence"])))
|
||||||
|
|
||||||
|
(vlength, ) = r("<I")
|
||||||
|
vdesc = h3m_data.read(vlength)
|
||||||
|
enc = edet(vdesc)
|
||||||
|
vdesc = vdesc.decode(enc["encoding"])
|
||||||
|
m.append(E.description(vdesc))
|
||||||
|
m.conversion_metadata.append(E.encoding(enc["encoding"],entity="/map/description[0]",confidence=str(enc["confidence"])))
|
||||||
|
|
||||||
|
try:
|
||||||
|
vdifficulty = h3m_diffictulties[r("<B")[0]]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError("Invalid map difficulty value")
|
||||||
|
m.append(E.difficulty(vdifficulty))
|
||||||
|
|
||||||
|
if m.xpath("/map/@version")[0] in ["AB", "SoD", "WoG"]:
|
||||||
|
(vmax_level,) = r("<B")
|
||||||
|
if vmax_level==0:
|
||||||
|
vmax_level = "Unspecified"
|
||||||
|
else:
|
||||||
|
vmax_level = "Unspecified"
|
||||||
|
m.append(E.max_level(vmax_level))
|
||||||
|
|
||||||
|
m.append(E.players())
|
||||||
|
|
||||||
|
#player info
|
||||||
|
for pnum in h3m_player_colors:
|
||||||
|
(vis_human, vis_computer) = r("<BB")
|
||||||
|
if vis_human not in [0,1] or vis_computer not in [0,1]:
|
||||||
|
raise ValueError("Invalid player type specifiers %#04x and %#04x" % (vis_human, vis_computer))
|
||||||
|
if vis_human == 0 and vis_computer == 0:
|
||||||
|
#player is disabled, skipping garbage
|
||||||
|
if m.xpath("/map/@version")[0] == "RoE":
|
||||||
|
h3m_data.read(6)
|
||||||
|
elif m.xpath("/map/@version")[0] == "AB":
|
||||||
|
h3m_data.read(12)
|
||||||
|
elif m.xpath("/map/@version")[0] in ["SoD", "WoG"]:
|
||||||
|
h3m_data.read(13)
|
||||||
|
m.players.append(E.player(color=h3m_player_colors[pnum],type="Disabled"))
|
||||||
|
continue
|
||||||
|
|
||||||
|
if vis_human == 1 and vis_computer == 1:
|
||||||
|
player_type = "Both"
|
||||||
|
elif vis_human == 1:
|
||||||
|
player_type = "Human"
|
||||||
|
else:
|
||||||
|
player_type = "Computer"
|
||||||
|
player = E.player(color=h3m_player_colors[pnum],type=player_type)
|
||||||
|
|
||||||
|
try:
|
||||||
|
vai_type = h3m_ai_types[r("<B")[0]]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError("Invalid AI type")
|
||||||
|
|
||||||
|
player.append(E.ai(vai_type))
|
||||||
|
|
||||||
|
if m.xpath("/map/@version")[0] in ["SoD", "WoG"]:
|
||||||
|
(venforce_alignment,) = r("<B")
|
||||||
|
if venforce_alignment not in [0,1]:
|
||||||
|
raise ValueError("Invalid alignment enforcement specifier %#04x" % venforce_alignment)
|
||||||
|
venforce_alignment = str(bool(venforce_alignment))
|
||||||
|
|
||||||
|
else:
|
||||||
|
venforce_alignment = "Unspecified"
|
||||||
|
|
||||||
|
valignments = bf(r("<B")[0])
|
||||||
|
|
||||||
|
if m.xpath("/map/@version")[0] in ["AB", "SoD", "WoG"]:
|
||||||
|
(vconflux,) = r("<B")
|
||||||
|
if vconflux not in [0,1]:
|
||||||
|
raise ValueError("Invalid Conflux specifier %#04x" % vconflux)
|
||||||
|
if vconflux == 1:
|
||||||
|
valignments[8] = 1
|
||||||
|
|
||||||
|
(vrandom_alignment,) = r("<B")
|
||||||
|
if vrandom_alignment not in [0,1]:
|
||||||
|
raise ValueError("Invalid random alignment specifier %#04x" % vrandom_alignment)
|
||||||
|
if vrandom_alignment == 1:
|
||||||
|
valignments[9] = 1
|
||||||
|
|
||||||
|
alignments = set()
|
||||||
|
for i in range(0,10):
|
||||||
|
if valignments[i] == 1:
|
||||||
|
alignments.add(h3m_alignments[i+1])
|
||||||
|
|
||||||
|
player.append(E.alignment(', '.join(alignments),enforced=venforce_alignment))
|
||||||
|
|
||||||
|
(vmain_town,) = r("<B")
|
||||||
|
if vmain_town not in [0,1]:
|
||||||
|
raise ValueError("Invalid main town specifier %#04x" % vmain_town)
|
||||||
|
if vmain_town:
|
||||||
|
if m.xpath("/map/@version")[0] in ["AB", "SoD", "WoG"]:
|
||||||
|
(vmain_town_generate_hero, vmain_town_unknown1) = r("<BB")
|
||||||
|
vmain_town_unknown1 = ("%#04x" % vmain_town_unknown1)
|
||||||
|
m.conversion_metadata.append(E.unknown1(vmain_town_unknown1,player_color=h3m_player_colors[pnum]))
|
||||||
|
if vmain_town_generate_hero not in [0,1]:
|
||||||
|
raise ValueError("Invalid main town hero generation specifier %#04x" % vmain_town_generate_hero)
|
||||||
|
vmain_town_generate_hero = str(bool(vmain_town_generate_hero))
|
||||||
|
else:
|
||||||
|
vmain_town_generate_hero = "Unspecified"
|
||||||
|
vmain_town_unknown1 = "Unspecified"
|
||||||
|
vcoords = r("<BBB")
|
||||||
|
|
||||||
|
player.append(E.main_town("%d,%d,%d" % vcoords, generate_hero=vmain_town_generate_hero, unknown1=vmain_town_unknown1))
|
||||||
|
|
||||||
|
(vgenerate_random_hero, vmain_hero) = r("<BB");
|
||||||
|
if vgenerate_random_hero not in [0,1]:
|
||||||
|
raise ValueError("Invalid random hero generation specifier %#04x" % vgenerate_random_hero)
|
||||||
|
vgenerate_random_hero = str(bool(vgenerate_random_hero))
|
||||||
|
player.append(E.generate_random_hero(vgenerate_random_hero))
|
||||||
|
|
||||||
|
if vmain_hero != 0xFF:
|
||||||
|
(vmain_hero_portrait, ) = r("<B")
|
||||||
|
if vmain_hero_portrait == 0xFF:
|
||||||
|
vmain_hero_portrait = "Standard"
|
||||||
|
else:
|
||||||
|
vmain_hero_portrait = str(vmain_hero_portrait)
|
||||||
|
(vlength, ) = r("<I")
|
||||||
|
vmain_hero_name = h3m_data.read(vlength)
|
||||||
|
player.append(E.main_hero(str(vmain_hero),portrait=vmain_hero_portrait,name=vmain_hero_name))
|
||||||
|
|
||||||
|
if m.xpath("/map/@version")[0] in ["AB", "SoD", "WoG"]:
|
||||||
|
(vhero_placeholders,vheroes_count) = r("<BI")
|
||||||
|
player.append(E.hero_placeholders(vhero_placeholders));
|
||||||
|
if vheroes_count > 0:
|
||||||
|
player.append(E.heroes())
|
||||||
|
for i in range(vheroes_count):
|
||||||
|
(vhero_portrait, ) = r("<B")
|
||||||
|
if vhero_portrait == 0xFF:
|
||||||
|
vhero_portrait = "Standard"
|
||||||
|
else:
|
||||||
|
vhero_portrait = str(vhero_portrait)
|
||||||
|
(vlength, ) = r("<I")
|
||||||
|
vhero_name = h3m_data.read(vlength)
|
||||||
|
player.heroes.append(E.hero(portrait=vhero_portrait,name=vhero_name))
|
||||||
|
|
||||||
|
m.players.append(player)
|
||||||
|
|
||||||
|
#special victory condition
|
||||||
|
(vvictory_condition,) = r("<B")
|
||||||
|
try:
|
||||||
|
vvictory_condition = h3m_victory_conditions[vvictory_condition]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError("Invalid special victory condition %#04x" % vvictory_condition)
|
||||||
|
|
||||||
|
if vvictory_condition != "None":
|
||||||
|
(vvictory_allow_normal, vvictory_apply_to_computer) = r("<BB")
|
||||||
|
if vvictory_allow_normal not in [0,1]:
|
||||||
|
raise ValueError("Invalid normal victory specifier %#04x" % vvictory_allow_normal)
|
||||||
|
if vvictory_apply_to_computer not in [0,1]:
|
||||||
|
raise ValueError("Invalid special victory for computer specifier %#04x" % vvictory_apply_to_computer)
|
||||||
|
vvictory_allow_normal = str(bool(vvictory_allow_normal))
|
||||||
|
vvictory_apply_to_computer = str(bool(vvictory_apply_to_computer))
|
||||||
|
m.append(E.special_victory_condition(type=vvictory_condition, allow_normal=vvictory_allow_normal, apply_to_computer=vvictory_apply_to_computer))
|
||||||
|
|
||||||
|
if vvictory_condition == "Acquire artifact":
|
||||||
|
(vvictory_artifact_id,) = r("<B")
|
||||||
|
try:
|
||||||
|
vvictory_artifact_id = h3m_artifact_types[vvictory_artifact_id]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError("Invalid special victory artifact id %#04x" % vvictory_artifact_id)
|
||||||
|
m.special_victory_condition.append(E.artifact(vvictory_artifact_id))
|
||||||
|
|
||||||
|
if m.xpath("/map/@version")[0] in ["AB", "SoD", "WoG"]:
|
||||||
|
(vvictory_artifact_unknown2,) = r("<B")
|
||||||
|
vvictory_artifact_unknown2 = ("%#04x" % vvictory_artifact_unknown2)
|
||||||
|
m.special_victory_condition.append(E.unknown2(vvictory_artifact_unknown2))
|
||||||
|
m.conversion_metadata.append(E.unknown2(vvictory_artifact_unknown2))
|
||||||
|
elif vvictory_condition == "Accumulate creatures":
|
||||||
|
(vvictory_creature_id,vvictory_creature_quantity) = r("<BI")
|
||||||
|
try:
|
||||||
|
vvictory_creature_id = h3m_creature_types[vvictory_creature_id]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError("Invalid special victory creature id %#04x" % vvictory_creature_id)
|
||||||
|
m.special_victory_condition.append(E.creature(vvictory_creature_id,quantity=str(vvictory_creature_quantity)))
|
||||||
|
elif vvictory_condition == "Accumulate resources":
|
||||||
|
(vvictory_resource_type, vvictory_resource_quantity) = r("<BI")
|
||||||
|
try:
|
||||||
|
vvictory_resource_type = h3m_resource_types[vvictory_resource_type]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError("Invalid special victory resource type %#04x" % vvictory_resource_type)
|
||||||
|
m.special_victory_condition.append(E.resource(vvictory_resource_type,quantity=str(vvictory_resource_quantity)))
|
||||||
|
elif vvictory_condition == "Upgrade town":
|
||||||
|
raise NotImplementedError
|
||||||
|
elif vvictory_condition in ("Build Grail", "Defeat hero", "Capture town", "Defeat monster"):
|
||||||
|
vcoords = r("<BBB")
|
||||||
|
m.special_victory_condition.append(E.location("%d,%d,%d" % vcoords))
|
||||||
|
elif vvictory_condition in ("Flag all dwellings", "Flag all mines"):
|
||||||
|
pass
|
||||||
|
elif vvictory_condition == "Transport artifact":
|
||||||
|
raise NotImplementedError
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
#special loss condition
|
||||||
|
(vloss_condition,) = r("<B")
|
||||||
|
try:
|
||||||
|
vloss_condition = h3m_loss_conditions[vloss_condition]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError("Invalid special loss condition %#04x" % vloss_condition)
|
||||||
|
|
||||||
|
if vloss_condition != "None":
|
||||||
|
m.append(E.special_loss_condition(type=vloss_condition))
|
||||||
|
if vloss_condition in ("Lose town", "Lose hero"):
|
||||||
|
vcoords = r("<BBB")
|
||||||
|
m.special_loss_condition.append(E.location("%d,%d,%d" % vcoords))
|
||||||
|
elif vloss_condition == "Time limit":
|
||||||
|
(vloss_days,) = r("<H")
|
||||||
|
m.special_loss_condition.append(E.days(str(vloss_days)))
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
#Teams
|
||||||
|
(vteam_count, ) = r("<B")
|
||||||
|
if vteam_count > 0:
|
||||||
|
#print dict(zip(range(0,8),r("<8B")))
|
||||||
|
vteams = r("<8B")
|
||||||
|
for pnum in range(0,8):
|
||||||
|
if m.xpath("/map/players/player[@color=$color]/@type",color=h3m_player_colors[pnum])[0] != "Disabled":
|
||||||
|
m.xpath("/map/players/player[@color=$color]",color=h3m_player_colors[pnum])[0].append(E.team(str(vteams[pnum])))
|
||||||
|
|
||||||
|
#guess_str = m.xpath("/map/name")[0].text + ' ' + m.xpath("/map/description")[0].text
|
||||||
|
#print guessLanguage(guess_str)
|
||||||
|
|
||||||
|
if m.xpath("/map/@version")[0] == "RoE":
|
||||||
|
vavailable_heroes = r("<16s")[0]
|
||||||
|
else:
|
||||||
|
vavailable_heroes = r("<20s")[0]
|
||||||
|
vunknown3 = "0x"+binascii.hexlify(r("<4s")[0])
|
||||||
|
m.conversion_metadata.append(E.unknown3(vunknown3))
|
||||||
|
|
||||||
|
if m.xpath("/map/@version")[0] in ["SoD", "WoG"]:
|
||||||
|
(vdisposed_heroes,) = r("<B")
|
||||||
|
if vdisposed_heroes != 0:
|
||||||
|
raise NotImplementedError("Disposed heroes not implemented")
|
||||||
|
|
||||||
|
vunknown4 = "0x"+binascii.hexlify(r("<31s")[0])
|
||||||
|
m.conversion_metadata.append(E.unknown4(vunknown4))
|
||||||
|
|
||||||
|
if m.xpath("/map/@version")[0] == "AB":
|
||||||
|
vavailable_artifacts = r("<17s")[0]
|
||||||
|
elif m.xpath("/map/@version")[0] in ["SoD", "WoG"]:
|
||||||
|
vavailable_artifacts = r("<18s")[0]
|
||||||
|
|
||||||
|
if m.xpath("/map/@version")[0] in ["SoD", "WoG"]:
|
||||||
|
vavailable_spells = r("<9s")[0]
|
||||||
|
|
||||||
|
if m.xpath("/map/@version")[0] in ["SoD", "WoG"]:
|
||||||
|
vavailable_skills = r("<4s")[0]
|
||||||
|
|
||||||
|
(vrumors_count,) = r("<B");
|
||||||
|
vunknown5 = "0x"+binascii.hexlify(r("<3s")[0])
|
||||||
|
m.conversion_metadata.append(E.unknown5(vunknown5))
|
||||||
|
for rnum in range(vrumors_count):
|
||||||
|
(vlength, ) = r("<I")
|
||||||
|
vrumor_name = h3m_data.read(vlength)
|
||||||
|
enc = edet(vrumor_name)
|
||||||
|
vrumor_name = vrumor_name.decode(enc["encoding"])
|
||||||
|
#m.conversion_metadata.append(E.encoding(enc["encoding"],entity="/map/rumor[@name='']",confidence=str(enc["confidence"])))
|
||||||
|
(vlength, ) = r("<I")
|
||||||
|
vrumor_text = h3m_data.read(vlength)
|
||||||
|
enc = edet(vrumor_text)
|
||||||
|
vrumor_text = vrumor_text.decode(enc["encoding"])
|
||||||
|
m.append(E.rumor(vrumor_text,name=vrumor_name))
|
||||||
|
#m.conversion_metadata.append(E.encoding(enc["encoding"],entity="/map/description[0]",confidence=str(enc["confidence"])))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#(map_data["heroes_count"], ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#if map_data["heroes_count"] > 0:
|
||||||
|
#map_data["free_heroes"] = []
|
||||||
|
#for i in range(map_data["heroes_count"]):
|
||||||
|
#(hero_id, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#(hero_portrait, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#(name_length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
#hero_name = h3m_data.read(name_length)
|
||||||
|
#(hero_players, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#map_data["free_heroes"].append({"id": hero_id, "portrait":hero_portrait, "name":hero_name, "players":hero_players})
|
||||||
|
|
||||||
|
#hero options
|
||||||
|
#for i in range(156):
|
||||||
|
#(hero_enable, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#if hero_enable == 1:
|
||||||
|
#(isExp, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#if isExp == 0x01:
|
||||||
|
#(exp, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
#(isSecSkill, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#if isSecSkill == 0x01:
|
||||||
|
#(skills_count, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
#for i in range(skills_count):
|
||||||
|
#(skill_id, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#(skill_lvl, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#(isArtifact, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#if isArtifact == 0x01:
|
||||||
|
#raise NotImplementedError
|
||||||
|
#(isBiography, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#if isBiography == 0x01:
|
||||||
|
#(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
#biography = h3m_data.read(length)
|
||||||
|
#(gender, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#(isSpells, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#if isSpells == 0x01:
|
||||||
|
#spells = struct.unpack("<9B", h3m_data.read(9))
|
||||||
|
#(isPrimarySkills, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
#if isPrimarySkills == 0x01:
|
||||||
|
#(attack, defense, power, knowledge) = struct.unpack("<4B", h3m_data.read(4))
|
||||||
|
|
||||||
|
if m.xpath("/map/@version")[0] in ["SoD", "WoG"]:
|
||||||
|
vunknown6 = "0x"+binascii.hexlify(r("<156s")[0])
|
||||||
|
m.conversion_metadata.append(E.unknown6(vunknown6))
|
||||||
|
|
||||||
|
|
||||||
|
map_size = int(m.xpath("/map/@size")[0])
|
||||||
|
upper_terrain = [[] for i in range(map_size)]
|
||||||
|
#read upper world
|
||||||
|
for i in range(map_size**2):
|
||||||
|
x = i%map_size
|
||||||
|
y = (i-x)/map_size
|
||||||
|
upper_terrain[y].append(r("<7B"))
|
||||||
|
|
||||||
|
#read underworld
|
||||||
|
if m.xpath("/map/@underground")[0] == "True":
|
||||||
|
lower_terrain = [[] for i in range(map_size)]
|
||||||
|
for i in range(map_size**2):
|
||||||
|
x = i%map_size
|
||||||
|
y = (i-x)/map_size
|
||||||
|
lower_terrain[y].append(r("<7B"))
|
||||||
|
|
||||||
|
|
||||||
|
(vdef_count, ) = r("<I")
|
||||||
|
print vdef_count
|
||||||
|
defs = []
|
||||||
|
for i in range(vdef_count):
|
||||||
|
(vlength, ) = r("<I")
|
||||||
|
vdef_filename = h3m_data.read(vlength)
|
||||||
|
#the biggest object is 8x6 tiles big - this is an array that maps
|
||||||
|
#passability to each of this tiles with bits 1 passable, 0 not passable
|
||||||
|
#we store a set with all not passable tiles
|
||||||
|
print vdef_filename
|
||||||
|
vdef_passability = r("<6B") #passability
|
||||||
|
vdef_passability = frozenset([(8-x,6-y) for x in range(8)
|
||||||
|
for y, p in enumerate(vdef_passability)
|
||||||
|
if not (p >> x) & 1])
|
||||||
|
vdef_accessibility = r("<6B") #passability
|
||||||
|
vdef_accessibility = frozenset([(8-x,6-y) for x in range(8)
|
||||||
|
for y, p in enumerate(vdef_accessibility)
|
||||||
|
if not (p >> x) & 1])
|
||||||
|
h3m_data.read(2) #landscape
|
||||||
|
h3m_data.read(2) #land_edit_groups
|
||||||
|
(vdef_type,vdef_subtype,vdef_groups,vdef_underlay ) = r("<IIBB")
|
||||||
|
h3m_data.read(16) #junk
|
||||||
|
|
||||||
|
return m
|
||||||
|
(vobj_count, ) = r("<I")
|
||||||
|
|
||||||
|
map_data["tunedobj"] = []
|
||||||
|
for i in range(map_data["tunedobj_count"]):
|
||||||
|
(x, y, z) = struct.unpack("<3B", h3m_data.read(3))
|
||||||
|
(object_id, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
#print x,y,z,object_id,
|
||||||
|
junk = h3m_data.read(5) #junk
|
||||||
|
#if junk != "\x00\x00\x00\x00\x00":
|
||||||
|
# for c in junk:
|
||||||
|
# print("%02d"%ord(c), end=' ')
|
||||||
|
# break
|
||||||
|
#print i, map_data["objects"][object_id]["filename"],
|
||||||
|
#print map_data["objects"][object_id]["class"]
|
||||||
|
|
||||||
|
map_data["tunedobj"].append({"id":object_id, "x":x, "y":y, "z":z})
|
||||||
|
|
||||||
|
if object_id in (0,1):
|
||||||
|
pass
|
||||||
|
elif map_data["objects"][object_id]["class"] == 53:
|
||||||
|
if map_data["objects"][object_id]["number"] == 7:
|
||||||
|
h3m_data.read(4)
|
||||||
|
else:
|
||||||
|
h3m_data.read(4)
|
||||||
|
elif map_data["objects"][object_id]["class"] in (76, 79):
|
||||||
|
(isText, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isText == 0x01:
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
text = h3m_data.read(length)
|
||||||
|
(isGuards, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isGuards == 0x01:
|
||||||
|
for i in range(7):
|
||||||
|
(guard_id, guard_count) = struct.unpack("<HH", h3m_data.read(4))
|
||||||
|
h3m_data.read(4) #junk
|
||||||
|
(quantity, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
h3m_data.read(4) #junk
|
||||||
|
elif map_data["objects"][object_id]["class"] in (34, 70, 62):
|
||||||
|
(hero_id, color, hero) = struct.unpack("<IBB", h3m_data.read(6))
|
||||||
|
(isName, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isName == 0x01:
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
name = h3m_data.read(length)
|
||||||
|
(isExp, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isExp == 0x01:
|
||||||
|
(exp, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
(isPortrait, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isPortrait == 0x01:
|
||||||
|
(portrait, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(isSecSkill, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isSecSkill == 0x01:
|
||||||
|
(skills_count, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
for i in range(skills_count):
|
||||||
|
(skill_id, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(skill_lvl, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(isCreature, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isCreature == 0x01:
|
||||||
|
for i in range(7):
|
||||||
|
(guard_id, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
(guard_count, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
(creaturesFormation, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(isArtifact, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isArtifact == 0x01:
|
||||||
|
(headID, shouldersID, neckID, rightHandID, leftHandID,
|
||||||
|
trunkID, rightRingID, leftRingID, legsID, misc1ID, misc2ID,
|
||||||
|
misc3ID, misc4ID, machine1ID, machine2ID, machine3ID,
|
||||||
|
machine4ID, magicbook, misc5ID) \
|
||||||
|
= struct.unpack("<19H", h3m_data.read(38))
|
||||||
|
(knapsack_count, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
if knapsack_count > 0:
|
||||||
|
for i in range(knapsack_count):
|
||||||
|
(knapsackID, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
(zoneRadius, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(isBiography, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isBiography == 0x01:
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
biography = h3m_data.read(length)
|
||||||
|
(gender, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(isSpells, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isSpells == 0x01:
|
||||||
|
spells = struct.unpack("<9B", h3m_data.read(9))
|
||||||
|
(isPrimarySkills, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isPrimarySkills == 0x01:
|
||||||
|
(attack, defense, power, knowledge) = struct.unpack("<4B", h3m_data.read(4))
|
||||||
|
h3m_data.read(16) #unknown
|
||||||
|
elif map_data["objects"][object_id]["class"] in (17, 20, 42):
|
||||||
|
(owner, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif map_data["objects"][object_id]["class"] == 93:
|
||||||
|
(isText, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isText == 0x01:
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
text = h3m_data.read(length)
|
||||||
|
(isGuards, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isGuards == 0x01:
|
||||||
|
for i in range(7):
|
||||||
|
(guard_id, guard_count) = struct.unpack("<HH", h3m_data.read(4))
|
||||||
|
h3m_data.read(4) #junk
|
||||||
|
(spell_id, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif map_data["objects"][object_id]["class"] == 216:
|
||||||
|
(owner, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
(junk, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
if junk == 0x00:
|
||||||
|
(towns, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
(minlevel, maxlevel, ) = struct.unpack("<2B", h3m_data.read(2))
|
||||||
|
elif map_data["objects"][object_id]["class"] in (54, 71, 72, 73, 74, 75, 162, 163, 164):
|
||||||
|
(monster_id, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
(monster_count, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
(mood, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(isTreasureOrText, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isTreasureOrText == 0x01:
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
text = h3m_data.read(length)
|
||||||
|
(wood, mercury, ore, sulfur, crystal, gem, gold, artefactID) \
|
||||||
|
= struct.unpack("<7IH", h3m_data.read(30))
|
||||||
|
(mosterNeverRunAway, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(monsterDontGrowUp, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
h3m_data.read(2) #junk
|
||||||
|
elif map_data["objects"][object_id]["class"] in (98, 77):
|
||||||
|
h3m_data.read(4) #junk
|
||||||
|
(owner, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(isName, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isName == 0x01:
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
name = h3m_data.read(length)
|
||||||
|
(isGuard, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isGuard == 0x01:
|
||||||
|
for i in range(7):
|
||||||
|
(guard_id, guard_count) = struct.unpack("<HH", h3m_data.read(4))
|
||||||
|
(formation, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(isBuildings, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isBuildings == 0x01:
|
||||||
|
build = struct.unpack("6B", h3m_data.read(6))
|
||||||
|
active = struct.unpack("6B", h3m_data.read(6))
|
||||||
|
else:
|
||||||
|
(isFort, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
mustSpells = struct.unpack("<9B", h3m_data.read(9))
|
||||||
|
canSpells = struct.unpack("<9B", h3m_data.read(9))
|
||||||
|
(eventQuantity, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
if eventQuantity > 0:
|
||||||
|
for i in range(eventQuantity):
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
event_name = h3m_data.read(length)
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
event_text = h3m_data.read(length)
|
||||||
|
(wood, mercury, ore, sulfur, crystal, gem, gold,
|
||||||
|
players_affected, human_affected, ai_affected,
|
||||||
|
day_of_first_event, event_iteration) \
|
||||||
|
= struct.unpack("<7I3B2H", h3m_data.read(35))
|
||||||
|
h3m_data.read(16) #junk
|
||||||
|
buildings = struct.unpack("<6B", h3m_data.read(6))
|
||||||
|
creatures = struct.unpack("<7H", h3m_data.read(14))
|
||||||
|
h3m_data.read(4) #junk
|
||||||
|
h3m_data.read(4) #junk
|
||||||
|
elif map_data["objects"][object_id]["class"] in (5, 65, 66, 67, 68, 69):
|
||||||
|
(isText, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isText == 0x01:
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
text = h3m_data.read(length)
|
||||||
|
(isGuards, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isGuards == 0x01:
|
||||||
|
for i in range(7):
|
||||||
|
(guard_id, guard_count) = struct.unpack("<HH", h3m_data.read(4))
|
||||||
|
h3m_data.read(4) #junk
|
||||||
|
elif map_data["objects"][object_id]["class"] in (33, 219):
|
||||||
|
(color, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
for i in range(7):
|
||||||
|
(guard_id, guard_count) = struct.unpack("<HH", h3m_data.read(4))
|
||||||
|
(undeleteSoldiers, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
h3m_data.read(8)
|
||||||
|
elif map_data["objects"][object_id]["class"] == 87:
|
||||||
|
(owner, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif map_data["objects"][object_id]["class"] == 83:
|
||||||
|
(quest, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
|
||||||
|
if quest == 0x00:
|
||||||
|
pass
|
||||||
|
elif quest == 0x01:
|
||||||
|
(level, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif quest == 0x02:
|
||||||
|
(offence, defence, power, knowledge) = struct.unpack("4B", h3m_data.read(4))
|
||||||
|
elif quest == 0x03:
|
||||||
|
(hero_id, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif quest == 0x04:
|
||||||
|
(monster_id, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif quest == 0x05:
|
||||||
|
(art_quantity, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
for i in range(art_quantity):
|
||||||
|
(art, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
elif quest == 0x06:
|
||||||
|
(creatures_quantity, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
for i in range(creatures_quantity):
|
||||||
|
(guard_id, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
(guard_count, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
elif quest == 0x07:
|
||||||
|
resources = struct.unpack("7I", h3m_data.read(28))
|
||||||
|
elif quest == 0x08:
|
||||||
|
(hero_id, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
elif quest == 0x09:
|
||||||
|
(player, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
if quest:
|
||||||
|
(time_limit, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
quest_begin = h3m_data.read(length)
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
quest_running = h3m_data.read(length)
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
quest_end = h3m_data.read(length)
|
||||||
|
|
||||||
|
(reward, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if reward == 0x00:
|
||||||
|
pass
|
||||||
|
elif reward == 0x01:
|
||||||
|
(exp, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif reward == 0x02:
|
||||||
|
(spell_points, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif reward == 0x03:
|
||||||
|
(morale, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
elif reward == 0x04:
|
||||||
|
(lucky, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
elif reward == 0x05:
|
||||||
|
(resID, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(res_quantity, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif reward == 0x06:
|
||||||
|
(priSkillID, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(priSkillBonus, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
elif reward == 0x07:
|
||||||
|
(secSkillID, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(secSkillBonus, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
elif reward == 0x08:
|
||||||
|
(artID, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
elif reward == 0x09:
|
||||||
|
(spellID, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
elif reward == 0x0A:
|
||||||
|
(creatureID, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
(creatureQuantity, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
h3m_data.read(2) #junk
|
||||||
|
elif map_data["objects"][object_id]["class"] in (91, 59):
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
text = h3m_data.read(length)
|
||||||
|
h3m_data.read(4) #junk
|
||||||
|
elif map_data["objects"][object_id]["class"] == 113:
|
||||||
|
(secSkills, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif map_data["objects"][object_id]["class"] in (88, 89, 90):
|
||||||
|
(spellID, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif map_data["objects"][object_id]["class"] == 215:
|
||||||
|
(quest, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
|
||||||
|
if quest == 0x00:
|
||||||
|
pass
|
||||||
|
elif quest == 0x01:
|
||||||
|
(level, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif quest == 0x02:
|
||||||
|
(offence, defence, power, knowledge) = struct.unpack("4B", h3m_data.read(4))
|
||||||
|
elif quest == 0x03:
|
||||||
|
(hero_id, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif quest == 0x04:
|
||||||
|
(monster_id, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
elif quest == 0x05:
|
||||||
|
(art_quantity, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
for i in range(art_quantity):
|
||||||
|
(art, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
elif quest == 0x06:
|
||||||
|
(creatures_quantity, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
for i in range(creatures_quantity):
|
||||||
|
(guard_id, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
(guard_count, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
elif quest == 0x07:
|
||||||
|
resources = struct.unpack("7I", h3m_data.read(28))
|
||||||
|
elif quest == 0x08:
|
||||||
|
(hero_id, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
elif quest == 0x09:
|
||||||
|
(player, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
if quest:
|
||||||
|
(time_limit, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
quest_begin = h3m_data.read(length)
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
quest_running = h3m_data.read(length)
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
quest_end = h3m_data.read(length)
|
||||||
|
elif map_data["objects"][object_id]["class"] == 36:
|
||||||
|
(radius, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
h3m_data.read(3) #junk
|
||||||
|
elif map_data["objects"][object_id]["class"] == 220:
|
||||||
|
(resources, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
h3m_data.read(3) #junk
|
||||||
|
elif map_data["objects"][object_id]["class"] == 217:
|
||||||
|
(owner, towns) = struct.unpack("<II", h3m_data.read(8))
|
||||||
|
if towns==0x00:
|
||||||
|
(towns,) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
elif map_data["objects"][object_id]["class"] == 218:
|
||||||
|
(owner, minlvl, maxlvl) = struct.unpack("<IBB", h3m_data.read(6))
|
||||||
|
elif map_data["objects"][object_id]["class"] == 81:
|
||||||
|
(bonus_type, primaryID) = struct.unpack("<BI", h3m_data.read(5))
|
||||||
|
h3m_data.read(3) #junk
|
||||||
|
elif map_data["objects"][object_id]["class"] == 6:
|
||||||
|
(isText, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isText == 0x01:
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
text = h3m_data.read(length)
|
||||||
|
(isGuards, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isGuards == 0x01:
|
||||||
|
for i in range(7):
|
||||||
|
(guard_id, guard_count) = struct.unpack("<HH", h3m_data.read(4))
|
||||||
|
h3m_data.read(4) #junk
|
||||||
|
(exp, spell_points, morals, luck, wood, mercury, ore, sulfur,
|
||||||
|
crystal, gem, gold, offence, defence, power, knowledge) = \
|
||||||
|
struct.unpack("<IIBBIIIIIIIBBBB", h3m_data.read(42))
|
||||||
|
(secSkills, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if secSkills > 0:
|
||||||
|
for i in range(secSkills):
|
||||||
|
(skill_id, skill_lvl) = struct.unpack("<BB", h3m_data.read(2))
|
||||||
|
(artefacts, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if artefacts > 0:
|
||||||
|
for i in range(artefacts):
|
||||||
|
(artID, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
(spells, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if spells > 0:
|
||||||
|
for i in range(spells):
|
||||||
|
(spellID, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(monsters, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if monsters > 0:
|
||||||
|
for i in range(monsters):
|
||||||
|
(guard_id, guard_count) = struct.unpack("<HH", h3m_data.read(4))
|
||||||
|
h3m_data.read(8) #junk
|
||||||
|
elif map_data["objects"][object_id]["class"] == 26:
|
||||||
|
(isText, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isText == 0x01:
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
text = h3m_data.read(length)
|
||||||
|
(isGuards, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if isGuards == 0x01:
|
||||||
|
for i in range(7):
|
||||||
|
(guard_id, guard_count) = struct.unpack("<HH", h3m_data.read(4))
|
||||||
|
h3m_data.read(4) #junk
|
||||||
|
(exp, spell_points, morals, luck, wood, mercury, ore, sulfur,
|
||||||
|
crystal, gem, gold, offence, defence, power, knowledge) = \
|
||||||
|
struct.unpack("<IIBBIIIIIIIBBBB", h3m_data.read(42))
|
||||||
|
(secSkills, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if secSkills > 0:
|
||||||
|
for i in range(secSkills):
|
||||||
|
(skill_id, skill_lvl) = struct.unpack("<BB", h3m_data.read(2))
|
||||||
|
(artefacts, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if artefacts > 0:
|
||||||
|
for i in range(artefacts):
|
||||||
|
(artID, ) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
(spells, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if spells > 0:
|
||||||
|
for i in range(spells):
|
||||||
|
(spellID, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(monsters, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
if monsters > 0:
|
||||||
|
for i in range(monsters):
|
||||||
|
(guard_id, guard_count) = struct.unpack("<HH", h3m_data.read(4))
|
||||||
|
h3m_data.read(8) #junk
|
||||||
|
(players, isAICan, disableAfterFirstDay) = struct.unpack("<BBB", h3m_data.read(3))
|
||||||
|
h3m_data.read(4) #junk
|
||||||
|
|
||||||
|
try:
|
||||||
|
(gevents_count, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
for i in range(gevents_count):
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
name = h3m_data.read(length)
|
||||||
|
(length, ) = struct.unpack("<I", h3m_data.read(4))
|
||||||
|
text = h3m_data.read(length)
|
||||||
|
h3m_data.read(7*4) #resources
|
||||||
|
(players_affected, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(human_affected, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(ai_affected, ) = struct.unpack("<B", h3m_data.read(1))
|
||||||
|
(day_of_first_event,) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
(event_iteration,) = struct.unpack("<H", h3m_data.read(2))
|
||||||
|
h3m_data.read(16) #junk
|
||||||
|
except:
|
||||||
|
print("d'ough...'")
|
||||||
|
|
||||||
|
h3m_data.read(124) #junk
|
||||||
|
|
||||||
|
return map_data
|
563
h3m_ids.py
Executable file
563
h3m_ids.py
Executable file
|
@ -0,0 +1,563 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
h3m_versions = {0x0E:"RoE", 0x15:"AB", 0x1C:"SoD", 0x33:"WoG"}
|
||||||
|
h3m_diffictulties = {0:"Easy", 1:"Normal", 2:"Hard", 3:"Expert", 4:"Impossible"}
|
||||||
|
h3m_player_colors = {0:"Red", 1:"Blue", 2:"Tan", 3:"Green", 4:"Orange", 5:"Purple", 6:"Teal", 7:"Pink"}
|
||||||
|
h3m_encoding_quirks = {"ISO-8859-2":"Windows-1250"}
|
||||||
|
h3m_ai_types = {0:"Random", 1:"Warrior", 2:"Builder", 3:"Explorer"}
|
||||||
|
h3m_alignments = {1:"Castle", 2:"Rampart", 3:"Tower", 4:"Inferno", 5:"Necropolis", 6:"Dungeon", 7:"Stronghold", 8:"Fortress", 9:"Conflux", 10:"Random"}
|
||||||
|
h3m_victory_conditions = {0:"Acquire artifact", 1:"Accumulate creatures", 2:"Accumulate resources", 3:"Upgrade town", 4:"Build Grail", 5:"Defeat hero", 6:"Capture town", 7:"Defeat monster", 8:"Flag all dwellings", 9:"Flag all mines", 10:"Transport artifact", 0xFF:"None"}
|
||||||
|
h3m_loss_conditions = {0:"Lose town", 1:"Lose hero", 2:"Time limit", 0xFF:"None"}
|
||||||
|
h3m_resource_types = {0:"Wood", 1:"Mercury", 2:"Ore", 3:"Sulfur", 4:"Crystal", 5:"Gems", 6:"Gold"}
|
||||||
|
h3m_terrain_types = {0:"Dirt", 1:"Desert", 2:"Grassland", 3:"Snow", 4:"Swamp", 5:"Rough", 6:"Subterraean", 7:"Lava", 8:"Water", 9:"Rock"}
|
||||||
|
|
||||||
|
h3m_hero_types = {
|
||||||
|
# Knights
|
||||||
|
0:"Orrin",
|
||||||
|
1:"Valeska",
|
||||||
|
2:"Edric",
|
||||||
|
3:"Sylvia",
|
||||||
|
4:"Lord Haart",
|
||||||
|
5:"Sorsha",
|
||||||
|
6:"Christian",
|
||||||
|
7:"Tyris",
|
||||||
|
# Clerics
|
||||||
|
8:"Rion",
|
||||||
|
9:"Adela",
|
||||||
|
10:"Cuthbert",
|
||||||
|
11:"Adelaide",
|
||||||
|
12:"Ingham",
|
||||||
|
13:"Sanya",
|
||||||
|
14:"Loynis",
|
||||||
|
15:"Caitlin",
|
||||||
|
# Rangers
|
||||||
|
16:"Mephala",
|
||||||
|
17:"Ufretin",
|
||||||
|
18:"Jenova",
|
||||||
|
19:"Ryland",
|
||||||
|
20:"Thorgrim",
|
||||||
|
21:"Ivor",
|
||||||
|
22:"Clancy",
|
||||||
|
23:"Kyrre",
|
||||||
|
# Druids
|
||||||
|
24:"Coronius",
|
||||||
|
25:"Uland",
|
||||||
|
26:"Elleshar",
|
||||||
|
27:"Gem",
|
||||||
|
28:"Malcom",
|
||||||
|
29:"Melodia",
|
||||||
|
30:"Alagar",
|
||||||
|
31:"Aeris",
|
||||||
|
# Alchemists
|
||||||
|
32:"Piquedram",
|
||||||
|
33:"Thane",
|
||||||
|
34:"Josephine",
|
||||||
|
35:"Neela",
|
||||||
|
36:"Torosar",
|
||||||
|
37:"Fafner",
|
||||||
|
38:"Rissa",
|
||||||
|
39:"Iona",
|
||||||
|
# Wizards
|
||||||
|
40:"Astral",
|
||||||
|
41:"Halon",
|
||||||
|
42:"Serena",
|
||||||
|
43:"Daremyth",
|
||||||
|
44:"Theodorus",
|
||||||
|
45:"Solmyr",
|
||||||
|
46:"Cyra",
|
||||||
|
47:"Aine",
|
||||||
|
# Demoniacs
|
||||||
|
48:"Fiona",
|
||||||
|
49:"Rashka",
|
||||||
|
50:"Marius",
|
||||||
|
51:"Ignatius",
|
||||||
|
52:"Octavia",
|
||||||
|
53:"Calh",
|
||||||
|
54:"Pyre",
|
||||||
|
55:"Nymus",
|
||||||
|
# Heretics
|
||||||
|
56:"Ayden",
|
||||||
|
57:"Xyron",
|
||||||
|
58:"Axsis",
|
||||||
|
59:"Olema",
|
||||||
|
60:"Calid",
|
||||||
|
61:"Ash",
|
||||||
|
62:"Zydar",
|
||||||
|
63:"Xarfax",
|
||||||
|
# Death Knights
|
||||||
|
64:"Straker",
|
||||||
|
65:"Vokial",
|
||||||
|
66:"Moandor",
|
||||||
|
67:"Charna",
|
||||||
|
68:"Tamika",
|
||||||
|
69:"Isra",
|
||||||
|
70:"Clavius",
|
||||||
|
71:"Galthran",
|
||||||
|
# Necromancers
|
||||||
|
72:"Septienna",
|
||||||
|
73:"Aislinn",
|
||||||
|
74:"Sandro",
|
||||||
|
75:"Nimbus",
|
||||||
|
76:"Thant",
|
||||||
|
77:"Xsi",
|
||||||
|
78:"Vidomina",
|
||||||
|
79:"Nagash",
|
||||||
|
# Overlords
|
||||||
|
80:"Lorelei",
|
||||||
|
81:"Arlach",
|
||||||
|
82:"Dace",
|
||||||
|
83:"Ajit",
|
||||||
|
84:"Damacon",
|
||||||
|
85:"Gunnar",
|
||||||
|
86:"Synca",
|
||||||
|
87:"Shakti",
|
||||||
|
# Warlocks
|
||||||
|
88:"Alamar",
|
||||||
|
89:"Jaegar",
|
||||||
|
90:"Malekith",
|
||||||
|
91:"Jeddite",
|
||||||
|
92:"Geon",
|
||||||
|
93:"Deemer",
|
||||||
|
94:"Sephinroth",
|
||||||
|
95:"Darkstorn",
|
||||||
|
# Barbarians
|
||||||
|
96:"Yog",
|
||||||
|
97:"Gurnisson",
|
||||||
|
98:"Jabarkas",
|
||||||
|
99:"Shiva",
|
||||||
|
100:"Gretchin",
|
||||||
|
101:"Krellion",
|
||||||
|
102:"Crag Hack",
|
||||||
|
103:"Tyraxor",
|
||||||
|
# Battle Mages
|
||||||
|
104:"Gird",
|
||||||
|
105:"Vey",
|
||||||
|
106:"Dessa",
|
||||||
|
107:"Terek",
|
||||||
|
108:"Zubin",
|
||||||
|
109:"Gundula",
|
||||||
|
110:"Oris",
|
||||||
|
111:"Saurug",
|
||||||
|
# Beastmasters
|
||||||
|
112:"Bron",
|
||||||
|
113:"Drakon",
|
||||||
|
114:"Wystan",
|
||||||
|
115:"Tazar",
|
||||||
|
116:"Alkin",
|
||||||
|
117:"Korbac",
|
||||||
|
118:"Gerwulf",
|
||||||
|
119:"Broghild",
|
||||||
|
# Witches
|
||||||
|
120:"Mirlanda",
|
||||||
|
121:"Rosic",
|
||||||
|
122:"Voy",
|
||||||
|
123:"Verdish",
|
||||||
|
124:"Merist",
|
||||||
|
125:"Styg",
|
||||||
|
126:"Andra",
|
||||||
|
127:"Tiva",
|
||||||
|
# Planeswalkers
|
||||||
|
128:"Pasis",
|
||||||
|
129:"Thunar",
|
||||||
|
130:"Ignissa",
|
||||||
|
131:"Lacus",
|
||||||
|
132:"Monere",
|
||||||
|
133:"Erdamon",
|
||||||
|
134:"Fiur",
|
||||||
|
135:"Kalt",
|
||||||
|
# Elementalists
|
||||||
|
136:"Luna",
|
||||||
|
137:"Brissa",
|
||||||
|
138:"Ciele",
|
||||||
|
139:"Labetha",
|
||||||
|
140:"Inteus",
|
||||||
|
141:"Aenain",
|
||||||
|
142:"Gelare",
|
||||||
|
143:"Grindan",
|
||||||
|
# Extension Heroes
|
||||||
|
144:"Sir Mullich",
|
||||||
|
145:"Adrienne",
|
||||||
|
146:"Catherine",
|
||||||
|
147:"Dracon",
|
||||||
|
148:"Gelu",
|
||||||
|
149:"Kilgor",
|
||||||
|
150:"Lord Haart",
|
||||||
|
151:"Mutare",
|
||||||
|
152:"Roland",
|
||||||
|
153:"Mutare Drake",
|
||||||
|
154:"Boragus",
|
||||||
|
155:"Xeron"}
|
||||||
|
|
||||||
|
|
||||||
|
h3m_artifact_types = {
|
||||||
|
0:"Spell book",
|
||||||
|
1:"Spell Scroll",
|
||||||
|
2:"Grail",
|
||||||
|
3:"Catapult",
|
||||||
|
4:"Ballista",
|
||||||
|
5:"Ammo Cart",
|
||||||
|
6:"First Aid Tent",
|
||||||
|
7:"Centaur Axe",
|
||||||
|
8:"Blackshard of the Dead Knight",
|
||||||
|
9:"Greater Gnoll's Flail",
|
||||||
|
10:"Ogre's Club of Havoc",
|
||||||
|
11:"Sword of Hellfire",
|
||||||
|
12:"Titan's Gladius",
|
||||||
|
13:"Shield of the Dwarven Lords",
|
||||||
|
14:"Shield of the Yawning Dead",
|
||||||
|
15:"Buckler of the Gnoll King",
|
||||||
|
16:"Targ of the Rampaging Ogre",
|
||||||
|
17:"Shield of the Damned",
|
||||||
|
18:"Sentinel's Shield",
|
||||||
|
19:"Helm of the Alabaster Unicorn",
|
||||||
|
20:"Skull Helmet",
|
||||||
|
21:"Helm of Chaos",
|
||||||
|
22:"Crown of the Supreme Magi",
|
||||||
|
23:"Hellstorm Helmet",
|
||||||
|
24:"Thunder Helmet",
|
||||||
|
25:"Breastplate of Petrified Wood",
|
||||||
|
26:"Rib Cage",
|
||||||
|
27:"Scales of the Greater Basilisk",
|
||||||
|
28:"Tunic of the Cyclops King",
|
||||||
|
29:"Breastplate of Brimstone",
|
||||||
|
30:"Titan's Cuirass",
|
||||||
|
31:"Armor of Wonder",
|
||||||
|
32:"Sandals of the Saint",
|
||||||
|
33:"Celestial Necklace of Bliss",
|
||||||
|
34:"Lion's Shield of Courage",
|
||||||
|
35:"Sword of Judgement",
|
||||||
|
36:"Helm of Heavenly Enlightenment",
|
||||||
|
37:"Quiet Eye of the Dragon",
|
||||||
|
38:"Red Dragon Flame Tongue",
|
||||||
|
39:"Dragon Scale Shield",
|
||||||
|
40:"Dragon Scale Armor",
|
||||||
|
41:"Dragonbone Greaves",
|
||||||
|
42:"Dragon Wing Tabard",
|
||||||
|
43:"Necklace of Dragonteeth",
|
||||||
|
44:"Crown of Dragontooth",
|
||||||
|
45:"Still Eye of the Dragon",
|
||||||
|
46:"Clover of Fortune",
|
||||||
|
47:"Cards of Prophecy",
|
||||||
|
48:"Ladybird of Luck",
|
||||||
|
49:"Badge of Courage",
|
||||||
|
50:"Crest of Valor",
|
||||||
|
51:"Glyph of Gallantry",
|
||||||
|
52:"Speculum",
|
||||||
|
53:"Spyglass",
|
||||||
|
54:"Amulet of the Undertaker",
|
||||||
|
55:"Vampire's Cowl",
|
||||||
|
56:"Dead Man's Boots",
|
||||||
|
57:"Garniture of Interference",
|
||||||
|
58:"Surcoat of Counterpoise",
|
||||||
|
59:"Boots of Polarity",
|
||||||
|
60:"Bow of Elven Cherrywood",
|
||||||
|
61:"Bowstring of the Unicorn's Mane",
|
||||||
|
62:"Angel Feather Arrows",
|
||||||
|
63:"Bird of Perception",
|
||||||
|
64:"Stoic Watchman",
|
||||||
|
65:"Emblem of Cognizance",
|
||||||
|
66:"Statesman's Medal",
|
||||||
|
67:"Diplomat's Ring",
|
||||||
|
68:"Ambassador's Sash",
|
||||||
|
69:"Ring of the Wayfarer",
|
||||||
|
70:"Equestrian's Gloves",
|
||||||
|
71:"Necklace of Ocean Guidance",
|
||||||
|
72:"Angel Wings",
|
||||||
|
73:"Charm of Mana",
|
||||||
|
74:"Talisman of Mana",
|
||||||
|
75:"Mystic Orb of Mana",
|
||||||
|
76:"Collar of Conjuring",
|
||||||
|
77:"Ring of Conjuring",
|
||||||
|
78:"Cape of Conjuring",
|
||||||
|
79:"Orb of the Firmament",
|
||||||
|
80:"Orb of Silt",
|
||||||
|
81:"Orb of Tempestuous Fire",
|
||||||
|
82:"Orb of Driving Rain",
|
||||||
|
83:"Recanter's Cloak",
|
||||||
|
84:"Spirit of Oppression",
|
||||||
|
85:"Hourglass of the Evil Hour",
|
||||||
|
86:"Tome of Fire Magic",
|
||||||
|
87:"Tome of Air Magic",
|
||||||
|
88:"Tome of Water Magic",
|
||||||
|
89:"Tome of Earth Magic",
|
||||||
|
90:"Boots of Levitation",
|
||||||
|
91:"Golden Bow",
|
||||||
|
92:"Sphere of Permanence",
|
||||||
|
93:"Orb of Vulnerability",
|
||||||
|
94:"Ring of Vitality",
|
||||||
|
95:"Ring of Life",
|
||||||
|
96:"Vial of Lifeblood",
|
||||||
|
97:"Necklace of Swiftness",
|
||||||
|
98:"Boots of Speed",
|
||||||
|
99:"Cape of Velocity",
|
||||||
|
100:"Pendant of Dispassion",
|
||||||
|
101:"Pendant of Second Sight",
|
||||||
|
102:"Pendant of Holiness",
|
||||||
|
103:"Pendant of Life",
|
||||||
|
104:"Pendant of Death",
|
||||||
|
105:"Pendant of Free Will",
|
||||||
|
106:"Pendant of Negativity",
|
||||||
|
107:"Pendant of Total Recall",
|
||||||
|
108:"Pendant of Courage",
|
||||||
|
109:"Everflowing Crystal Cloak",
|
||||||
|
110:"Ring of Infinite Gems",
|
||||||
|
111:"Everpouring Vial of Mercury",
|
||||||
|
112:"Inexhaustible Cart of Ore",
|
||||||
|
113:"Eversmoking Ring of Sulfur",
|
||||||
|
114:"Inexhaustible Cart of Lumber",
|
||||||
|
115:"Endless Sack of Gold",
|
||||||
|
116:"Endless Bag of Gold",
|
||||||
|
117:"Endless Purse of Gold",
|
||||||
|
118:"Legs of Legion",
|
||||||
|
119:"Loins of Legion",
|
||||||
|
120:"Torso of Legion",
|
||||||
|
121:"Arms of Legion",
|
||||||
|
122:"Head of Legion",
|
||||||
|
123:"Sea Captain's Hat",
|
||||||
|
124:"Spellbinder's Hat",
|
||||||
|
125:"Shackles of War",
|
||||||
|
126:"Orb of Inhibition",
|
||||||
|
127:"Vial of Dragon Blood",
|
||||||
|
128:"Armageddon's Blade",
|
||||||
|
129:"Angelic Alliance",
|
||||||
|
130:"Cloak of the Undead King",
|
||||||
|
131:"Elixir of Life",
|
||||||
|
132:"Armor of the Damned",
|
||||||
|
133:"Statue of Legion",
|
||||||
|
134:"Power of the Dragon Father",
|
||||||
|
135:"Titan's Thunder",
|
||||||
|
136:"Admiral's Hat",
|
||||||
|
137:"Bow of the Sharpshooter",
|
||||||
|
138:"Wizard's Well",
|
||||||
|
139:"Ring of the Magi",
|
||||||
|
140:"Cornucopia",
|
||||||
|
141:"Magic Wand", # WoG artifact
|
||||||
|
142:"Gold Tower Arrow", # WoG artifact
|
||||||
|
143:"Monster's Power", # WoG artifact
|
||||||
|
144:"Highlighted Slot", # Not an actual artifact, internal use only
|
||||||
|
145:"Artifact Lock", # Not an actual artifact, internal use only
|
||||||
|
146:"Axe of Smashing", # WoG Commander artifact
|
||||||
|
147:"Mithril Mail", # WoG Commander artifact
|
||||||
|
148:"Sword of Sharpness", # WoG Commander artifact
|
||||||
|
149:"Helm of Immortality", # WoG Commander artifact
|
||||||
|
150:"Pendant of Sorcery", # WoG Commander artifact
|
||||||
|
151:"Boots of Haste", # WoG Commander artifact
|
||||||
|
152:"Bow of Seeking", # WoG Commander artifact
|
||||||
|
153:"Dragon Eye Ring", # WoG Commander artifact
|
||||||
|
154:"Hardened Shield", # WoG Commander artifact
|
||||||
|
155:"Slava's Ring of Power", # WoG Commander artifact
|
||||||
|
156:"Warlord's banner", # WoG artifact
|
||||||
|
157:"Crimson Shield of Retribution", # WoG artifact
|
||||||
|
158:"Barbarian Lord's Axe of Ferocity", # WoG artifact
|
||||||
|
159:"Dragonheart", # WoG artifact
|
||||||
|
160:"Gate Key", # WoG artifact
|
||||||
|
161:"Blank Helmet", # Blank artifact
|
||||||
|
162:"Blank Sword", # Blank artifact
|
||||||
|
163:"Blank Shield", # Blank artifact
|
||||||
|
164:"Blank Horned Ring", # Blank artifact
|
||||||
|
165:"Blank Gemmed Ring", # Blank artifact
|
||||||
|
166:"Blank Neck Broach", # Blank artifact
|
||||||
|
167:"Blank Armor", # Blank artifact
|
||||||
|
168:"Blank Surcoat", # Blank artifact
|
||||||
|
169:"Blank Boots", # Blank artifact
|
||||||
|
170:"Blank Horn"} # Blank artifact
|
||||||
|
|
||||||
|
|
||||||
|
h3m_creature_types = {
|
||||||
|
0:"Pikeman",
|
||||||
|
1:"Halberdier",
|
||||||
|
2:"Archer",
|
||||||
|
3:"Marksman",
|
||||||
|
4:"Griffin",
|
||||||
|
5:"Royal Griffin",
|
||||||
|
6:"Swordsman",
|
||||||
|
7:"Crusader",
|
||||||
|
8:"Monk",
|
||||||
|
9:"Zealot",
|
||||||
|
10:"Cavalier",
|
||||||
|
11:"Champion",
|
||||||
|
12:"Angel",
|
||||||
|
13:"Archangel",
|
||||||
|
14:"Centaur",
|
||||||
|
15:"Centaur Captain",
|
||||||
|
16:"Dwarf",
|
||||||
|
17:"Battle Dwarf",
|
||||||
|
18:"Wood Elf",
|
||||||
|
19:"Grand Elf",
|
||||||
|
20:"Pegasus",
|
||||||
|
21:"Silver Pegasus",
|
||||||
|
22:"Dendroid Guard",
|
||||||
|
23:"Dendroid Soldier",
|
||||||
|
24:"Unicorn",
|
||||||
|
25:"War Unicorn",
|
||||||
|
26:"Green Dragon",
|
||||||
|
27:"Gold Dragon",
|
||||||
|
28:"Gremlin",
|
||||||
|
29:"Master Gremlin",
|
||||||
|
30:"Stone Gargoyle",
|
||||||
|
31:"Obsidian Gargoyle",
|
||||||
|
32:"Stone Golem",
|
||||||
|
33:"Iron Golem",
|
||||||
|
34:"Mage",
|
||||||
|
35:"Arch Mage",
|
||||||
|
36:"Genie",
|
||||||
|
37:"Master Genie",
|
||||||
|
38:"Naga",
|
||||||
|
39:"Naga Queen",
|
||||||
|
40:"Giant",
|
||||||
|
41:"Titan",
|
||||||
|
42:"Imp",
|
||||||
|
43:"Familiar",
|
||||||
|
44:"Gog",
|
||||||
|
45:"Magog",
|
||||||
|
46:"Hell Hound",
|
||||||
|
47:"Cerberus",
|
||||||
|
48:"Demon",
|
||||||
|
49:"Horned Demon",
|
||||||
|
50:"Pit Fiend",
|
||||||
|
51:"Pit Lord",
|
||||||
|
52:"Efreeti",
|
||||||
|
53:"Efreet Sultan",
|
||||||
|
54:"Devil",
|
||||||
|
55:"Arch Devil",
|
||||||
|
56:"Skeleton",
|
||||||
|
57:"Skeleton Warrior",
|
||||||
|
58:"Walking Dead",
|
||||||
|
59:"Zombie",
|
||||||
|
60:"Wight",
|
||||||
|
61:"Wraith",
|
||||||
|
62:"Vampire",
|
||||||
|
63:"Vampire Lord",
|
||||||
|
64:"Lich",
|
||||||
|
65:"Power Lich",
|
||||||
|
66:"Black Knight",
|
||||||
|
67:"Dread Knight",
|
||||||
|
68:"Bone Dragon",
|
||||||
|
69:"Ghost Dragon",
|
||||||
|
70:"Troglodyte",
|
||||||
|
71:"Infernal Troglodyte",
|
||||||
|
72:"Harpy",
|
||||||
|
73:"Harpy Hag",
|
||||||
|
74:"Beholder",
|
||||||
|
75:"Evil Eye",
|
||||||
|
76:"Medusa",
|
||||||
|
77:"Medusa Queen",
|
||||||
|
78:"Minotaur",
|
||||||
|
79:"Minotaur King",
|
||||||
|
80:"Manticore",
|
||||||
|
81:"Scorpicore",
|
||||||
|
82:"Red Dragon",
|
||||||
|
83:"Black Dragon",
|
||||||
|
84:"Goblin",
|
||||||
|
85:"Hobgoblin",
|
||||||
|
86:"Wolf Rider",
|
||||||
|
87:"Wolf Raider",
|
||||||
|
88:"Orc",
|
||||||
|
89:"Orc Chieftain",
|
||||||
|
90:"Ogre",
|
||||||
|
91:"Ogre Mage",
|
||||||
|
92:"Roc",
|
||||||
|
93:"Thunderbird",
|
||||||
|
94:"Cyclops",
|
||||||
|
95:"Cyclops King",
|
||||||
|
96:"Behemoth",
|
||||||
|
97:"Ancient Behemoth",
|
||||||
|
98:"Gnoll",
|
||||||
|
99:"Gnoll Marauder",
|
||||||
|
100:"Lizardman",
|
||||||
|
101:"Lizard Warrior",
|
||||||
|
102:"Gorgon",
|
||||||
|
103:"Mighty Gorgon",
|
||||||
|
104:"Serpent Fly",
|
||||||
|
105:"Dragon Fly",
|
||||||
|
106:"Basilisk",
|
||||||
|
107:"Greater Basilisk",
|
||||||
|
108:"Wyvern",
|
||||||
|
109:"Wyvern Monarch",
|
||||||
|
110:"Hydra",
|
||||||
|
111:"Chaos Hydra",
|
||||||
|
112:"Air Elemental",
|
||||||
|
113:"Earth Elemental",
|
||||||
|
114:"Fire Elemental",
|
||||||
|
115:"Water Elemental",
|
||||||
|
116:"Gold Golem",
|
||||||
|
117:"Diamond Golem",
|
||||||
|
118:"Pixie",
|
||||||
|
119:"Sprite",
|
||||||
|
120:"Psychic Elemental",
|
||||||
|
121:"Magic Elemental",
|
||||||
|
122:"NOT USED (attacker)",
|
||||||
|
123:"Ice Elemental",
|
||||||
|
124:"NOT USED (defender)",
|
||||||
|
125:"Magma Elemental",
|
||||||
|
126:"NOT USED (3)",
|
||||||
|
127:"Storm Elemental",
|
||||||
|
128:"NOT USED (4)",
|
||||||
|
129:"Energy Elemental",
|
||||||
|
130:"Firebird",
|
||||||
|
131:"Phoenix",
|
||||||
|
132:"Azure Dragon",
|
||||||
|
133:"Crystal Dragon",
|
||||||
|
134:"Faerie Dragon",
|
||||||
|
135:"Rust Dragon",
|
||||||
|
136:"Enchanter",
|
||||||
|
137:"Sharpshooter",
|
||||||
|
138:"Halfling",
|
||||||
|
139:"Peasant",
|
||||||
|
140:"Boar",
|
||||||
|
141:"Mummy",
|
||||||
|
142:"Nomad",
|
||||||
|
143:"Rogue",
|
||||||
|
144:"Troll",
|
||||||
|
145:"Catapult (specialty X1)",
|
||||||
|
146:"Ballista (specialty X1)",
|
||||||
|
147:"First Aid Tent (specialty X1)",
|
||||||
|
148:"Ammo Cart (specialty X1)",
|
||||||
|
149:"Arrow Towers (specialty X1)",
|
||||||
|
150:"Supreme Archangel",
|
||||||
|
151:"Diamond Dragon",
|
||||||
|
152:"Lord of Thunder",
|
||||||
|
153:"Antichrist",
|
||||||
|
154:"Blood Dragon",
|
||||||
|
155:"Darkness Dragon",
|
||||||
|
156:"Ghost Behemoth",
|
||||||
|
157:"Hell Hydra",
|
||||||
|
158:"Sacred Phoenix",
|
||||||
|
159:"Ghost",
|
||||||
|
160:"Emissary of War",
|
||||||
|
161:"Emissary of Peace",
|
||||||
|
162:"Emissary of Mana",
|
||||||
|
163:"Emissary of Lore",
|
||||||
|
164:"Fire Messenger",
|
||||||
|
165:"Earth Messenger",
|
||||||
|
166:"Air Messenger",
|
||||||
|
167:"Water Messenger",
|
||||||
|
168:"Gorynych",
|
||||||
|
169:"War zealot",
|
||||||
|
170:"Arctic Sharpshooter",
|
||||||
|
171:"Lava Sharpshooter",
|
||||||
|
172:"Nightmare",
|
||||||
|
173:"Santa Gremlin",
|
||||||
|
174:"Paladin (attacker)",
|
||||||
|
175:"Hierophant (attacker)",
|
||||||
|
176:"Temple Guardian (attacker)",
|
||||||
|
177:"Succubus (attacker)",
|
||||||
|
178:"Soul Eater (attacker)",
|
||||||
|
179:"Brute (attacker)",
|
||||||
|
180:"Ogre Leader (attacker)",
|
||||||
|
181:"Shaman (attacker)",
|
||||||
|
182:"Astral Spirit (attacker)",
|
||||||
|
183:"Paladin (defender)",
|
||||||
|
184:"Hierophant (defender)",
|
||||||
|
185:"Temple Guardian (defender)",
|
||||||
|
186:"Succubus (defender)",
|
||||||
|
187:"Soul Eater (defender)",
|
||||||
|
188:"Brute (defender)",
|
||||||
|
189:"Ogre Leader (defender)",
|
||||||
|
190:"Shaman (defender)",
|
||||||
|
191:"Astral Spirit (defender)",
|
||||||
|
192:"Sylvan Centaur",
|
||||||
|
193:"Sorceress",
|
||||||
|
194:"Werewolf",
|
||||||
|
195:"Hell Steed",
|
||||||
|
196:"Dracolich"}
|
11
mapread.py
Executable file
11
mapread.py
Executable file
|
@ -0,0 +1,11 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import h3m
|
||||||
|
from lxml import etree
|
||||||
|
import sys
|
||||||
|
#from guess_language import guessLanguage
|
||||||
|
|
||||||
|
map = h3m.extract(sys.argv[1])
|
||||||
|
#print guessLanguage(map["map_desc"])
|
||||||
|
|
||||||
|
print etree.tostring(map,pretty_print=True,xml_declaration=True,encoding="UTF-8")
|
Loading…
Reference in a new issue