heroes-renaissance/lib/h3m.py

604 lines
31 KiB
Python
Raw Normal View History

2008-11-23 20:07:47 +00:00
#!/usr/bin/env python
"""
heroes renaissance
copyright 2008 - Johannes 'josch' Schauer <j.schauer@email.de>
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 pyglet
def extract(filename):
h3m_data = gzip.open(filename)
map_data = {}
#read general info
(map_data["version"], ) = struct.unpack("<I", h3m_data.read(4))
if map_data["version"] != 0x1C:
return
(map_data["hero_present"], map_data["map_size"], map_data["underworld"],
) = struct.unpack("<BIB", h3m_data.read(6))
(name_length, ) = struct.unpack("<I", h3m_data.read(4))
map_data["map_name"] = h3m_data.read(name_length)
(desc_length, ) = struct.unpack("<I", h3m_data.read(4))
map_data["map_desc"] = h3m_data.read(desc_length)
(map_data["difficulty"], map_data["level_limit"],
) = struct.unpack("<BB", h3m_data.read(2))
#player info
for color in ("Red", "Blue", "Tan", "Green", "Orange", "Purple", "Teal", "Pink"):
map_data[color] = {}
(map_data[color]["is_human"], map_data[color]["is_computer"],
map_data[color]["behaviour"], map_data[color]["isCityTypesOpt"],
map_data[color]["cityTypes"], map_data[color]["randomCity"],
) = struct.unpack("<BBBBHB", h3m_data.read(7))
(main_city, ) = struct.unpack("<B", h3m_data.read(1))
if main_city:
map_data[color]["main_city"] = {}
(map_data[color]["main_city"]["generate_hero"],
map_data[color]["main_city"]["type"],
) = struct.unpack("<BB", h3m_data.read(2))
map_data[color]["main_city"]["coords"] = struct.unpack("<BBB", h3m_data.read(3))
(map_data[color]["random_hero"], map_data[color]["hero_type"],
) = struct.unpack("<BB", h3m_data.read(2))
if map_data[color]["hero_type"] != 0xFF:
(map_data[color]["hero_portrait"], ) = struct.unpack("<B", h3m_data.read(1))
(name_length, ) = struct.unpack("<I", h3m_data.read(4))
map_data[color]["hero_name"] = h3m_data.read(name_length)
h3m_data.read(1) #junk
(map_data[color]["heroes_count"], ) = struct.unpack("<I", h3m_data.read(4))
if map_data[color]["heroes_count"] > 0:
map_data[color]["heroes"] = {}
2008-11-24 08:29:06 +00:00
for i in range(map_data[color]["heroes_count"]):
2008-11-23 20:07:47 +00:00
(map_data[color]["heroes"]["portrait"], ) = struct.unpack("<B", h3m_data.read(1))
(name_length, ) = struct.unpack("<I", h3m_data.read(4))
map_data[color]["heroes"]["name"] = h3m_data.read(name_length)
#special victory condition
(map_data["victory_conditions"], ) = struct.unpack("<B", h3m_data.read(1))
if map_data["victory_conditions"] != 0xFF:
map_data["victory_conditions"] = {"id":map_data["victory_conditions"]}
(map_data["victory_conditions"]["canStandardEnd"], ) = struct.unpack("<B", h3m_data.read(1))
(map_data["victory_conditions"]["canComputer"], ) = struct.unpack("<B", h3m_data.read(1))
if map_data["victory_conditions"]["id"] == 0x00:
(map_data["victory_conditions"]["artID"], ) = struct.unpack("<B", h3m_data.read(1))
elif map_data["victory_conditions"]["id"] == 0x01:
(map_data["victory_conditions"]["creatureID"], ) = struct.unpack("<B", h3m_data.read(1))
(map_data["victory_conditions"]["creatureCount"], ) = struct.unpack("<H", h3m_data.read(2))
elif map_data["victory_conditions"]["id"] == 0x02:
(map_data["victory_conditions"]["resID"], ) = struct.unpack("<B", h3m_data.read(1))
(map_data["victory_conditions"]["resCount"], ) = struct.unpack("<I", h3m_data.read(4))
elif map_data["victory_conditions"]["id"] == 0x03:
raise NotImplementedError
elif map_data["victory_conditions"]["id"] in (0x04, 0x05, 0x06, 0x07):
(map_data["victory_conditions"]["x"], ) = struct.unpack("<B", h3m_data.read(1))
(map_data["victory_conditions"]["y"], ) = struct.unpack("<B", h3m_data.read(1))
(map_data["victory_conditions"]["z"], ) = struct.unpack("<B", h3m_data.read(1))
elif map_data["victory_conditions"]["id"] in (0x08, 0x09):
pass
elif map_data["victory_conditions"]["id"] == 0x0A:
raise NotImplementedError
else:
raise NotImplementedError
#special loss condition
(map_data["loss_conditions"], ) = struct.unpack("<B", h3m_data.read(1))
if map_data["loss_conditions"] != 0xFF:
map_data["loss_conditions"] = {"id":map_data["loss_conditions"]}
if map_data["loss_conditions"]["id"] in (0x00, 0x01):
(map_data["loss_conditions"]["x"], ) = struct.unpack("<B", h3m_data.read(1))
(map_data["loss_conditions"]["y"], ) = struct.unpack("<B", h3m_data.read(1))
(map_data["loss_conditions"]["z"], ) = struct.unpack("<B", h3m_data.read(1))
elif map_data["loss_conditions"]["id"] == 0x02:
#to be researched
struct.unpack("<B", h3m_data.read(1))
struct.unpack("<B", h3m_data.read(1))
elif map_data["loss_conditions"]["id"] == 0x03:
(map_data["loss_conditions"]["days"], ) = struct.unpack("<H", h3m_data.read(1))
else:
raise NotImplementedError
#Teams
(map_data["commands_count"], ) = struct.unpack("<B", h3m_data.read(1))
if map_data["commands_count"] > 0:
map_data["commands"] = struct.unpack("<8B", h3m_data.read(8))
#Free Heroes
h3m_data.read(20) #free heroes
h3m_data.read(4) #junk
(map_data["heroes_count"], ) = struct.unpack("<B", h3m_data.read(1))
if map_data["heroes_count"] > 0:
map_data["free_heroes"] = []
2008-11-24 08:29:06 +00:00
for i in range(map_data["heroes_count"]):
2008-11-23 20:07:47 +00:00
(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})
h3m_data.read(31) #junk
#artefacts
h3m_data.read(18)
#spells
h3m_data.read(9)
#sec skillz
h3m_data.read(4)
#rumors
(map_data["rumor_count"], ) = struct.unpack("<I", h3m_data.read(4))
if map_data["rumor_count"] > 0:
map_data["rumors"] = []
2008-11-24 08:29:06 +00:00
for i in range(map_data["rumor_count"]):
2008-11-23 20:07:47 +00:00
(name_length, ) = struct.unpack("<I", h3m_data.read(4))
rumor_name = h3m_data.read(name_length)
(text_length, ) = struct.unpack("<I", h3m_data.read(4))
rumor_text = h3m_data.read(text_length)
map_data["rumors"].append({"name":rumor_name, "text":rumor_text})
#hero options
2008-11-24 08:29:06 +00:00
for i in range(156):
2008-11-23 20:07:47 +00:00
(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:
2008-11-25 14:45:41 +00:00
(skills_count, ) = struct.unpack("<I", h3m_data.read(4))
2008-11-24 08:29:06 +00:00
for i in range(skills_count):
2008-11-23 20:07:47 +00:00
(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))
2008-11-24 08:29:06 +00:00
map_data["upper_terrain"] = [[] for i in range(map_data["map_size"])]
2008-11-23 20:07:47 +00:00
#read upper world
2008-11-24 08:29:06 +00:00
for i in range(map_data["map_size"]**2):
2008-11-23 20:07:47 +00:00
x = i%map_data["map_size"]
y = (i-x)/map_data["map_size"]
map_data["upper_terrain"][y].append(struct.unpack("<7B", h3m_data.read(7)))
#read underworld
if map_data["underworld"]:
2008-11-24 08:29:06 +00:00
map_data["lower_terrain"] = [[] for i in range(map_data["map_size"])]
for i in range(map_data["map_size"]**2):
2008-11-23 20:07:47 +00:00
x = i%map_data["map_size"]
y = (i-x)/map_data["map_size"]
map_data["lower_terrain"][y].append(struct.unpack("<7B", h3m_data.read(7)))
(map_data["object_count"], ) = struct.unpack("<I", h3m_data.read(4))
map_data["objects"] = []
2008-11-24 08:29:06 +00:00
for i in range(map_data["object_count"]):
2008-11-23 20:07:47 +00:00
(length, ) = struct.unpack("<I", h3m_data.read(4))
filename = h3m_data.read(length)
2008-11-27 03:08:17 +00:00
#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
passability = struct.unpack("<6B", h3m_data.read(6)) #passability
passability = frozenset([(8-x,6-y) for x in range(8)
for y, p in enumerate(passability)
if not (p >> x) & 1])
2008-11-23 20:07:47 +00:00
h3m_data.read(6) #actions
h3m_data.read(2) #landscape
h3m_data.read(2) #land_edit_groups
(obj_class, ) = struct.unpack("<I", h3m_data.read(4)) #class
(obj_number, ) = struct.unpack("<I", h3m_data.read(4)) #number
(obj_group, ) = struct.unpack("<B", h3m_data.read(1)) #group
(overlay, ) = struct.unpack("<B", h3m_data.read(1)) #isOverlay
2008-11-23 20:07:47 +00:00
h3m_data.read(16) #junk
map_data["objects"].append({"filename":filename.lower(), "class":obj_class,
"number":obj_number, "group":obj_group, "overlay":overlay})
2008-11-23 20:07:47 +00:00
(map_data["tunedobj_count"], ) = struct.unpack("<I", h3m_data.read(4))
map_data["tunedobj"] = []
2008-11-24 08:29:06 +00:00
for i in range(map_data["tunedobj_count"]):
2008-11-23 20:07:47 +00:00
(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
2008-11-24 08:29:06 +00:00
#if junk != "\x00\x00\x00\x00\x00":
# for c in junk:
# print("%02d"%ord(c), end=' ')
# break
2008-11-23 20:07:47 +00:00
#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:
2008-11-24 08:29:06 +00:00
for i in range(7):
2008-11-23 20:07:47 +00:00
(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))
2008-11-24 08:29:06 +00:00
for i in range(skills_count):
2008-11-23 20:07:47 +00:00
(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:
2008-11-24 08:29:06 +00:00
for i in range(7):
2008-11-23 20:07:47 +00:00
(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:
2008-11-24 08:29:06 +00:00
for i in range(knapsack_count):
2008-11-23 20:07:47 +00:00
(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:
2008-11-24 08:29:06 +00:00
for i in range(7):
2008-11-23 20:07:47 +00:00
(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:
2008-11-24 08:29:06 +00:00
for i in range(7):
2008-11-23 20:07:47 +00:00
(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:
2008-11-24 08:29:06 +00:00
for i in range(eventQuantity):
2008-11-23 20:07:47 +00:00
(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:
2008-11-24 08:29:06 +00:00
for i in range(7):
2008-11-23 20:07:47 +00:00
(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))
2008-11-24 08:29:06 +00:00
for i in range(7):
2008-11-23 20:07:47 +00:00
(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))
2008-11-24 08:29:06 +00:00
for i in range(art_quantity):
2008-11-23 20:07:47 +00:00
(art, ) = struct.unpack("<H", h3m_data.read(2))
elif quest == 0x06:
(creatures_quantity, ) = struct.unpack("<B", h3m_data.read(1))
2008-11-24 08:29:06 +00:00
for i in range(creatures_quantity):
2008-11-23 20:07:47 +00:00
(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
(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))
2008-11-24 08:29:06 +00:00
for i in range(art_quantity):
2008-11-23 20:07:47 +00:00
(art, ) = struct.unpack("<H", h3m_data.read(2))
elif quest == 0x06:
(creatures_quantity, ) = struct.unpack("<B", h3m_data.read(1))
2008-11-24 08:29:06 +00:00
for i in range(creatures_quantity):
2008-11-23 20:07:47 +00:00
(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
2008-11-28 09:59:02 +00:00
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)
2008-11-23 20:07:47 +00:00
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:
2008-11-24 08:29:06 +00:00
for i in range(7):
2008-11-23 20:07:47 +00:00
(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:
2008-11-24 08:29:06 +00:00
for i in range(secSkills):
2008-11-23 20:07:47 +00:00
(skill_id, skill_lvl) = struct.unpack("<BB", h3m_data.read(2))
(artefacts, ) = struct.unpack("<B", h3m_data.read(1))
if artefacts > 0:
2008-11-24 08:29:06 +00:00
for i in range(artefacts):
2008-11-23 20:07:47 +00:00
(artID, ) = struct.unpack("<H", h3m_data.read(2))
(spells, ) = struct.unpack("<B", h3m_data.read(1))
if spells > 0:
2008-11-24 08:29:06 +00:00
for i in range(spells):
2008-11-23 20:07:47 +00:00
(spellID, ) = struct.unpack("<B", h3m_data.read(1))
(monsters, ) = struct.unpack("<B", h3m_data.read(1))
if monsters > 0:
2008-11-24 08:29:06 +00:00
for i in range(monsters):
2008-11-23 20:07:47 +00:00
(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:
2008-11-24 08:29:06 +00:00
for i in range(7):
2008-11-23 20:07:47 +00:00
(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:
2008-11-24 08:29:06 +00:00
for i in range(secSkills):
2008-11-23 20:07:47 +00:00
(skill_id, skill_lvl) = struct.unpack("<BB", h3m_data.read(2))
(artefacts, ) = struct.unpack("<B", h3m_data.read(1))
if artefacts > 0:
2008-11-24 08:29:06 +00:00
for i in range(artefacts):
2008-11-23 20:07:47 +00:00
(artID, ) = struct.unpack("<H", h3m_data.read(2))
(spells, ) = struct.unpack("<B", h3m_data.read(1))
if spells > 0:
2008-11-24 08:29:06 +00:00
for i in range(spells):
2008-11-23 20:07:47 +00:00
(spellID, ) = struct.unpack("<B", h3m_data.read(1))
(monsters, ) = struct.unpack("<B", h3m_data.read(1))
if monsters > 0:
2008-11-24 08:29:06 +00:00
for i in range(monsters):
2008-11-23 20:07:47 +00:00
(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))
2008-11-24 08:29:06 +00:00
for i in range(gevents_count):
2008-11-23 20:07:47 +00:00
(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:
2008-11-24 08:29:06 +00:00
print("d'ough...'")
2008-11-23 20:07:47 +00:00
h3m_data.read(124) #junk
return map_data