SoD_Randomizer
Tavern Dweller
|
posted March 28, 2021 07:36 PM |
|
|
Randomizer for H3 SoD made in Python
Hello! I made a simple randomizer for H3 SoD (mostly for fun and not for a serious playing). It changes the monsters in all cities to a new random monsters (excluding neutral creatures). It also changes the alignments of creatures, so for example if creature is moved from Necropolis to Castle, its native terrain is now grass and not dirt! It's also seen as a Castle creature for morale calulation.
It's an alpha version, so it doesn't change heroes' starting armies. Also monsters in creatures dwellings at map will remain the same.
Download: [url=https://drive.google.com/file/d/1RGUHpGI3oTQxNTczOWVD_MGlFGwr8KZb/]https://drive.google.com/file/d/1RGUHpGI3oTQxNTczOWVD_MGlFGwr8KZb/[/url]
Installation:
1: Unpack and copy files from H3Randomizer folder into your H3 folder
2. Run H3Randomize.exe to randomize creatures in towns
3. Run H3Randomizer.exe and play
Warning! If you want to randomize creatures again, you need to close your game, run H3Randomize.exe again, and then reopen your game (H3Randomizer.exe)
Source:
Quote: from random import randrange
monsters_id = {"l1": [0x00, 0x0E, 0x1C, 0x2A, 0x38, 0x46, 0x54, 0x62, 0x76],
"l2": [0x02, 0x10, 0x1E, 0x2C, 0x3A, 0x48, 0x56, 0x64, 0x70],
"l3": [0x04, 0x12, 0x20, 0x2E, 0x3C, 0x4A, 0x58, 0x68, 0x73],
"l4": [0x06, 0x14, 0x22, 0x30, 0x3E, 0x4C, 0x5A, 0x6A, 0x72],
"l5": [0x08, 0x16, 0x24, 0x32, 0x40, 0x4E, 0x5C, 0x66, 0x71],
"l6": [0x0A, 0x18, 0x26, 0x34, 0x42, 0x50, 0x5E, 0x6C, 0x78],
"l7": [0x0C, 0x1A, 0x28, 0x36, 0x44, 0x52, 0x60, 0x6E, 0x82]} #no neutrals
m_alignments = {0x00: 0, 0x0E: 1, 0x1C : 2, 0x2A: 3, 0x38 :4, 0x46: 5, 0x54: 6, 0x62: 7, 0x76: 8,
0x02: 0, 0x10: 1, 0x1E: 2, 0x2C: 3, 0x3A: 4, 0x48: 5, 0x56: 6, 0x64: 7, 0x70: 8,
0x04: 0, 0x12: 1, 0x20: 2, 0x2E: 3, 0x3C: 4, 0x4A: 5, 0x58: 6, 0x68: 7, 0x73: 8,
0x06: 0, 0x14: 1, 0x22: 2, 0x30: 3, 0x3E: 4, 0x4C: 5, 0x5A: 6, 0x6A: 7, 0x72: 8,
0x08: 0, 0x16: 1, 0x24: 2, 0x32: 3, 0x40: 4, 0x4E: 5, 0x5C: 6, 0x66: 7, 0x71: 8,
0x0A: 0, 0x18: 1, 0x26: 2, 0x34: 3, 0x42: 4, 0x50: 5, 0x5E: 6, 0x6C: 7, 0x78: 8,
0x0C: 0, 0x1A: 1, 0x28: 2, 0x36: 3, 0x44: 4, 0x52: 5, 0x60: 6, 0x6E: 7, 0x82: 8}
hordes_lvls = {"1": 3, "2": [2, 5], "3": 2, "4": [1, 3], "5": 1, "6": 1, "7": 1, "8": 1, "9": 1} # 1- Castle, 9 - Conflux
number_of_hordes = [1, 2, 1, 2, 1, 1, 1, 1, 1]
hordes_offsets = {"1": 0x289800, "2": [0x289820, 0x289830], "3": 0x289840, "4": [0x289860, 0x289870], "5": 0x289880, "6": 0x2898A0, "7": 0x2898C0, "8": 0x2898E0, "9": 0x289900}
alignments_b_overwrite = []
hordes_b_to_overwrite = []
bytes_to_overwrite = []
def randomize_creatures():
faction_num = 1 #1 - Castle, 9 - Cofnlux
for i in range(9):
lvl = 1
faction = []
for i in range(len(monsters_id)):
index = randrange(len(monsters_id["l" + str(lvl)]))
byte = monsters_id["l" + str(lvl)][index]
del monsters_id["l" + str(lvl)][index]
bytes_to_overwrite.append(byte)
for i in range(3):
bytes_to_overwrite.append(0x00)
faction.append(byte)
update_hordes(faction_num, lvl, byte)
m_alignments[byte] = faction_num - 1
lvl += 1
for i in range(7): #upgraded creatures
if faction[0] == 0x70: #Air Elemental
bytes_to_overwrite.append(0x7F)
elif faction[0] == 0x73: #Water Elemental
bytes_to_overwrite.append(0x7B)
elif faction[0] == 0x72: #Fire Elemental
bytes_to_overwrite.append(0x81)
elif faction[0] == 0x71: #Earth Elemental
bytes_to_overwrite.append(0x7D)
else:
bytes_to_overwrite.append(faction[0] + 0x01)
del faction[0]
for i in range(3):
bytes_to_overwrite.append(0x00)
faction_num += 1
def update_hordes(f, c_lvl, c_id): #faction_number, creature lvl, creature id
if number_of_hordes[f-1] == 1:
if hordes_lvls[str(f)] == c_lvl:
hordes_b_to_overwrite.append(c_id)
else:
index = 0
for i in hordes_lvls[str(f)]:
if index + 1 == c_lvl:
hordes_b_to_overwrite.append(c_id)
def update_heroes_straring_armies():
#not done yet
pass
def update_creatures_alignments():
non_standard_monsters = [0x66, 0x68, 0x6A, 0x6C, 0x6E] #some fortress creatures
conflux_monsters = [0x70, 0x71, 0x72, 0x73, 0x76, 0x76, 0x78, 0x78, 0x72, 0x73, 0x70, 0x71, 0x82, 0x82]
index = 0
for i in m_alignments:
if index <= 0x64:
for i in range(2):
alignments_b_overwrite.append(m_alignments[index])
index += 2
elif index > 0x64:
for i in non_standard_monsters:
for a in range(2):
alignments_b_overwrite.append(m_alignments)
for i in conflux_monsters:
alignments_b_overwrite.append(m_alignments)
randomize_creatures()
update_creatures_alignments()
with open(r"H3Randomizer.exe", 'r+b') as f:
f.seek(0x2757BC)
f.write(bytearray(bytes_to_overwrite))
index = 1
for i in hordes_b_to_overwrite:
if number_of_hordes[index-1] == 1:
f.seek(hordes_offsets[str(index)])
byte = hordes_b_to_overwrite[0]
f.write(bytes([byte]))
del hordes_b_to_overwrite[0]
index += 1
else:
n_index = 0
for i in range(2):
f.seek(hordes_offsets[str(index)][n_index])
byte = hordes_b_to_overwrite[0]
f.write(bytes([byte]))
del hordes_b_to_overwrite[0]
n_index += 1
index += 1
f_num = 0
for i in range(8):
index = 0
for i in range(14):
f.seek(0x2713C0 + (index * 0x74) + (f_num * 0x658))
f.write(bytes([alignments_b_overwrite[0]]))
del alignments_b_overwrite[0]
index += 1
f_num += 1
#Conflux creatures:
c = [0x274680, 0x2746F4, 0x274768, 0x2747DC, 0x274938, 0x2749AC, 0x274A20, 0x274A94, 0x274B7C, 0x274C64, 0x274D4C, 0x274E34, 0x274EA8, 0x274F1C]
# Air, Earth, Fire, Pixie, Sprite, Psychic, Magic, Energy, Ice, Storm, Magma, Firebird, Phoenix
index = 0
for i in c:
f.seek(c[index])
f.write(bytes([alignments_b_overwrite[0]]))
del alignments_b_overwrite[0]
index += 1
|
|