Read client signed int32 fields as signed
Add ResStream.read_long/write_long and use them for every CObjects field the client loads with ResStream_ReadInt32 (sb.exe 0x7E1700) as a value: rank info, attribute/skill/resource amounts, requirements, door/deed/container/key fields, natural attacks, hardpoints, sound event types and sparse VAL_LONG (LoadSaveBehavior<long>). Hash/enum fields, list counts and flag words keep unsigned reads. The binary is unchanged; JSON now shows e.g. -1 instead of 4294967295 (rank_hirelings, rank_rank) and -10 instead of 4294967286 (attr_adj). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6a8598f33f
commit
0adbfe0d99
14 files changed
+190
-182
No files matched your search
@@ -13,12 +13,12 @@ from arcane.util import ResStream
|
||||
|
||||
class RankInfo:
|
||||
def load_binary(self, stream: ResStream):
|
||||
self.rank_hirelings = stream.read_dword()
|
||||
self.rank_shrines = stream.read_dword()
|
||||
self.rank_spires = stream.read_dword()
|
||||
self.rank_barracks = stream.read_dword()
|
||||
self.rank_rank = stream.read_dword()
|
||||
self.rank_health = stream.read_dword()
|
||||
self.rank_hirelings = stream.read_long()
|
||||
self.rank_shrines = stream.read_long()
|
||||
self.rank_spires = stream.read_long()
|
||||
self.rank_barracks = stream.read_long()
|
||||
self.rank_rank = stream.read_long()
|
||||
self.rank_health = stream.read_long()
|
||||
self.rank_automatic = stream.read_bool()
|
||||
self.rank_energy_k1 = stream.read_float()
|
||||
self.rank_energy_k2 = stream.read_float()
|
||||
@@ -35,17 +35,17 @@ class RankInfo:
|
||||
self.rank_placement_limit = [
|
||||
[
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
] for _ in range(num_placement_limits)
|
||||
]
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
stream.write_dword(self.rank_hirelings)
|
||||
stream.write_dword(self.rank_shrines)
|
||||
stream.write_dword(self.rank_spires)
|
||||
stream.write_dword(self.rank_barracks)
|
||||
stream.write_dword(self.rank_rank)
|
||||
stream.write_dword(self.rank_health)
|
||||
stream.write_long(self.rank_hirelings)
|
||||
stream.write_long(self.rank_shrines)
|
||||
stream.write_long(self.rank_spires)
|
||||
stream.write_long(self.rank_barracks)
|
||||
stream.write_long(self.rank_rank)
|
||||
stream.write_long(self.rank_health)
|
||||
stream.write_bool(self.rank_automatic)
|
||||
stream.write_float(self.rank_energy_k1)
|
||||
stream.write_float(self.rank_energy_k2)
|
||||
@@ -58,7 +58,7 @@ class RankInfo:
|
||||
stream.write_dword(len(self.rank_placement_limit))
|
||||
for placement in self.rank_placement_limit:
|
||||
stream.write_dword(placement[0])
|
||||
stream.write_dword(placement[1])
|
||||
stream.write_long(placement[1])
|
||||
|
||||
def load_json(self, data):
|
||||
self.rank_hirelings = data['rank_hirelings']
|
||||
@@ -95,11 +95,11 @@ class RankInfo:
|
||||
|
||||
class ArcCityAssetTemplate():
|
||||
def load_binary(self, stream: ResStream):
|
||||
self.template_max_ranks = stream.read_dword()
|
||||
self.template_start_rank = stream.read_dword()
|
||||
self.template_asset_type = stream.read_dword()
|
||||
self.template_trade_icon = stream.read_dword()
|
||||
self.template_landmark = stream.read_dword()
|
||||
self.template_max_ranks = stream.read_long()
|
||||
self.template_start_rank = stream.read_long()
|
||||
self.template_asset_type = stream.read_long()
|
||||
self.template_trade_icon = stream.read_long()
|
||||
self.template_landmark = stream.read_long()
|
||||
self.template_is_maintenance = stream.read_bool()
|
||||
self.template_has_keys = stream.read_bool()
|
||||
self.template_use_hardpoints = stream.read_bool()
|
||||
@@ -148,19 +148,19 @@ class ArcCityAssetTemplate():
|
||||
self.template_embed_template.load_binary(stream)
|
||||
num_creators = stream.read_dword()
|
||||
self.template_creator = [
|
||||
stream.read_dword() for _ in range(num_creators)
|
||||
stream.read_long() for _ in range(num_creators)
|
||||
]
|
||||
num_terrains = stream.read_dword()
|
||||
self.template_terrain = [
|
||||
stream.read_dword() for _ in range(num_terrains)
|
||||
stream.read_long() for _ in range(num_terrains)
|
||||
]
|
||||
num_valid_npc_types = stream.read_dword()
|
||||
self.template_valid_npc_type = [
|
||||
stream.read_dword() for _ in range(num_valid_npc_types)
|
||||
stream.read_long() for _ in range(num_valid_npc_types)
|
||||
]
|
||||
num_valid_npc_cat = stream.read_dword()
|
||||
self.template_valid_npc_cat = [
|
||||
stream.read_dword() for _ in range(num_valid_npc_cat)
|
||||
stream.read_long() for _ in range(num_valid_npc_cat)
|
||||
]
|
||||
num_rank_info = stream.read_dword()
|
||||
self.template_rank_info = [RankInfo() for _ in range(num_rank_info)]
|
||||
@@ -169,15 +169,15 @@ class ArcCityAssetTemplate():
|
||||
num_cap_info = stream.read_dword()
|
||||
self.template_cap_info = [
|
||||
[
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
stream.read_long(),
|
||||
stream.read_qword(),
|
||||
] for _ in range(num_cap_info)
|
||||
]
|
||||
num_event_rules = stream.read_dword()
|
||||
self.template_event_rules = [
|
||||
[
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
stream.read_dword(),
|
||||
] for _ in range(num_event_rules)
|
||||
]
|
||||
@@ -198,18 +198,18 @@ class ArcCityAssetTemplate():
|
||||
self.template_resource_limit = [
|
||||
[
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
stream.read_long(),
|
||||
] for _ in range(num_resource_limit)
|
||||
]
|
||||
self.template_unknown = stream.read_dword()
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
stream.write_dword(self.template_max_ranks)
|
||||
stream.write_dword(self.template_start_rank)
|
||||
stream.write_dword(self.template_asset_type)
|
||||
stream.write_dword(self.template_trade_icon)
|
||||
stream.write_dword(self.template_landmark)
|
||||
stream.write_long(self.template_max_ranks)
|
||||
stream.write_long(self.template_start_rank)
|
||||
stream.write_long(self.template_asset_type)
|
||||
stream.write_long(self.template_trade_icon)
|
||||
stream.write_long(self.template_landmark)
|
||||
stream.write_bool(self.template_is_maintenance)
|
||||
stream.write_bool(self.template_has_keys)
|
||||
stream.write_bool(self.template_use_hardpoints)
|
||||
@@ -243,27 +243,27 @@ class ArcCityAssetTemplate():
|
||||
self.template_embed_template.save_binary(stream)
|
||||
stream.write_dword(len(self.template_creator))
|
||||
for creator in self.template_creator:
|
||||
stream.write_dword(creator)
|
||||
stream.write_long(creator)
|
||||
stream.write_dword(len(self.template_terrain))
|
||||
for terrain in self.template_terrain:
|
||||
stream.write_dword(terrain)
|
||||
stream.write_long(terrain)
|
||||
stream.write_dword(len(self.template_valid_npc_type))
|
||||
for npc_type in self.template_valid_npc_type:
|
||||
stream.write_dword(npc_type)
|
||||
stream.write_long(npc_type)
|
||||
stream.write_dword(len(self.template_valid_npc_cat))
|
||||
for npc_cat in self.template_valid_npc_cat:
|
||||
stream.write_dword(npc_cat)
|
||||
stream.write_long(npc_cat)
|
||||
stream.write_dword(len(self.template_rank_info))
|
||||
for rank_info in self.template_rank_info:
|
||||
rank_info.save_binary(stream)
|
||||
stream.write_dword(len(self.template_cap_info))
|
||||
for cap in self.template_cap_info:
|
||||
stream.write_dword(cap[0])
|
||||
stream.write_dword(cap[1])
|
||||
stream.write_long(cap[0])
|
||||
stream.write_long(cap[1])
|
||||
stream.write_qword(cap[2])
|
||||
stream.write_dword(len(self.template_event_rules))
|
||||
for event in self.template_event_rules:
|
||||
stream.write_dword(event[0])
|
||||
stream.write_long(event[0])
|
||||
stream.write_dword(event[1])
|
||||
stream.write_dword(len(self.template_architecture))
|
||||
for arch in self.template_architecture:
|
||||
@@ -277,8 +277,8 @@ class ArcCityAssetTemplate():
|
||||
stream.write_dword(len(self.template_resource_limit))
|
||||
for resource in self.template_resource_limit:
|
||||
stream.write_dword(resource[0])
|
||||
stream.write_dword(resource[1])
|
||||
stream.write_dword(resource[2])
|
||||
stream.write_long(resource[1])
|
||||
stream.write_long(resource[2])
|
||||
stream.write_dword(self.template_unknown)
|
||||
|
||||
def load_json(self, data):
|
||||
|
||||
@@ -25,7 +25,7 @@ class ArcCombatObj(ArcObj):
|
||||
self.combat_powers = [
|
||||
[
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
] for _ in range(num_powers)
|
||||
]
|
||||
|
||||
@@ -38,7 +38,7 @@ class ArcCombatObj(ArcObj):
|
||||
stream.write_dword(len(self.combat_powers))
|
||||
for power in self.combat_powers:
|
||||
stream.write_dword(power[0])
|
||||
stream.write_dword(power[1])
|
||||
stream.write_long(power[1])
|
||||
|
||||
def load_json(self, data):
|
||||
super().load_json(data)
|
||||
|
||||
@@ -14,13 +14,13 @@ from .common.Inventory import Inventory
|
||||
class ArcContainerObject(ArcItem):
|
||||
def load_binary(self, stream: ResStream):
|
||||
super().load_binary(stream)
|
||||
self.container_open = stream.read_dword()
|
||||
self.container_locked = stream.read_dword()
|
||||
self.container_locked_rank = stream.read_dword()
|
||||
self.container_barred = stream.read_dword()
|
||||
self.container_barred_rank = stream.read_dword()
|
||||
self.container_trapped = stream.read_dword()
|
||||
self.container_trappe_rank = stream.read_dword()
|
||||
self.container_open = stream.read_long()
|
||||
self.container_locked = stream.read_long()
|
||||
self.container_locked_rank = stream.read_long()
|
||||
self.container_barred = stream.read_long()
|
||||
self.container_barred_rank = stream.read_long()
|
||||
self.container_trapped = stream.read_long()
|
||||
self.container_trappe_rank = stream.read_long()
|
||||
num_contents = stream.read_dword()
|
||||
self.container_inventory_contents = [Inventory() for _ in range(num_contents)]
|
||||
for content in self.container_inventory_contents:
|
||||
@@ -28,13 +28,13 @@ class ArcContainerObject(ArcItem):
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
super().save_binary(stream)
|
||||
stream.write_dword(self.container_open)
|
||||
stream.write_dword(self.container_locked)
|
||||
stream.write_dword(self.container_locked_rank)
|
||||
stream.write_dword(self.container_barred)
|
||||
stream.write_dword(self.container_barred_rank)
|
||||
stream.write_dword(self.container_trapped)
|
||||
stream.write_dword(self.container_trappe_rank)
|
||||
stream.write_long(self.container_open)
|
||||
stream.write_long(self.container_locked)
|
||||
stream.write_long(self.container_locked_rank)
|
||||
stream.write_long(self.container_barred)
|
||||
stream.write_long(self.container_barred_rank)
|
||||
stream.write_long(self.container_trapped)
|
||||
stream.write_long(self.container_trappe_rank)
|
||||
stream.write_dword(len(self.container_inventory_contents))
|
||||
for content in self.container_inventory_contents:
|
||||
content.save_binary(stream)
|
||||
|
||||
@@ -13,12 +13,12 @@ from .ArcItem import ArcItem
|
||||
class ArcDeed(ArcItem):
|
||||
def load_binary(self, stream: ResStream):
|
||||
super().load_binary(stream)
|
||||
self.deed_type = stream.read_dword()
|
||||
self.deed_type = stream.read_long()
|
||||
self.deed_furniture_id = stream.read_qword()
|
||||
self.deed_target_id = stream.read_qword()
|
||||
self.deed_employment = stream.read_dword()
|
||||
self.deed_start_rank = stream.read_dword()
|
||||
self.deed_name_lookup = stream.read_dword()
|
||||
self.deed_employment = stream.read_long()
|
||||
self.deed_start_rank = stream.read_long()
|
||||
self.deed_name_lookup = stream.read_long()
|
||||
self.deed_indoors = stream.read_bool()
|
||||
self.deed_is_fortress = stream.read_bool()
|
||||
self.deed_namelookup_val = stream.read_float()
|
||||
@@ -33,12 +33,12 @@ class ArcDeed(ArcItem):
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
super().save_binary(stream)
|
||||
stream.write_dword(self.deed_type)
|
||||
stream.write_long(self.deed_type)
|
||||
stream.write_qword(self.deed_furniture_id)
|
||||
stream.write_qword(self.deed_target_id)
|
||||
stream.write_dword(self.deed_employment)
|
||||
stream.write_dword(self.deed_start_rank)
|
||||
stream.write_dword(self.deed_name_lookup)
|
||||
stream.write_long(self.deed_employment)
|
||||
stream.write_long(self.deed_start_rank)
|
||||
stream.write_long(self.deed_name_lookup)
|
||||
stream.write_bool(self.deed_indoors)
|
||||
stream.write_bool(self.deed_is_fortress)
|
||||
stream.write_float(self.deed_namelookup_val)
|
||||
|
||||
@@ -15,9 +15,9 @@ from arcane.util import ResStream
|
||||
class ArcDoorObject():
|
||||
def load_binary(self, stream: ResStream):
|
||||
self.door_id = stream.read_qword()
|
||||
self.door_type = stream.read_dword()
|
||||
self.door_movement_axis = stream.read_dword()
|
||||
self.door_swing_direction = stream.read_dword()
|
||||
self.door_type = stream.read_long()
|
||||
self.door_movement_axis = stream.read_long()
|
||||
self.door_swing_direction = stream.read_long()
|
||||
self.door_min_time_to_stay_open = stream.read_float()
|
||||
self.door_max_time_to_stay_open = stream.read_float()
|
||||
self.door_swing_time = stream.read_float()
|
||||
@@ -26,16 +26,16 @@ class ArcDoorObject():
|
||||
self.door_slide_direction = stream.read_tuple()
|
||||
self.door_slide_start = stream.read_tuple()
|
||||
self.door_slide_end = stream.read_tuple()
|
||||
self.door_locked = stream.read_dword()
|
||||
self.door_locked = stream.read_long()
|
||||
self.door_linked_to = stream.read_qword()
|
||||
self.door_key = stream.read_qword()
|
||||
self.door_sound_event = stream.read_qword()
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
stream.write_qword(self.door_id)
|
||||
stream.write_dword(self.door_type)
|
||||
stream.write_dword(self.door_movement_axis)
|
||||
stream.write_dword(self.door_swing_direction)
|
||||
stream.write_long(self.door_type)
|
||||
stream.write_long(self.door_movement_axis)
|
||||
stream.write_long(self.door_swing_direction)
|
||||
stream.write_float(self.door_min_time_to_stay_open)
|
||||
stream.write_float(self.door_max_time_to_stay_open)
|
||||
stream.write_float(self.door_swing_time)
|
||||
@@ -44,7 +44,7 @@ class ArcDoorObject():
|
||||
stream.write_tuple(self.door_slide_direction)
|
||||
stream.write_tuple(self.door_slide_start)
|
||||
stream.write_tuple(self.door_slide_end)
|
||||
stream.write_dword(self.door_locked)
|
||||
stream.write_long(self.door_locked)
|
||||
stream.write_qword(self.door_linked_to)
|
||||
stream.write_qword(self.door_key)
|
||||
stream.write_qword(self.door_sound_event)
|
||||
|
||||
@@ -15,14 +15,14 @@ class ArcDungeonUnitObject(ArcStructureObject):
|
||||
super().load_binary(stream)
|
||||
num_connectables = stream.read_dword()
|
||||
self.dungeon_connectable_edges = [
|
||||
stream.read_dword() for _ in range(num_connectables)
|
||||
stream.read_long() for _ in range(num_connectables)
|
||||
]
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
super().save_binary(stream)
|
||||
stream.write_dword(len(self.dungeon_connectable_edges))
|
||||
for edge in self.dungeon_connectable_edges:
|
||||
stream.write_dword(edge)
|
||||
stream.write_long(edge)
|
||||
|
||||
def load_json(self, data):
|
||||
super().load_json(data)
|
||||
|
||||
@@ -20,14 +20,14 @@ from .common.Race import RaceRequired
|
||||
|
||||
class Damage:
|
||||
def load_binary(self, stream: ResStream):
|
||||
self.damage_type = stream.read_dword()
|
||||
self.damage_min = stream.read_dword()
|
||||
self.damage_max = stream.read_dword()
|
||||
self.damage_type = stream.read_long()
|
||||
self.damage_min = stream.read_long()
|
||||
self.damage_max = stream.read_long()
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
stream.write_dword(self.damage_type)
|
||||
stream.write_dword(self.damage_min)
|
||||
stream.write_dword(self.damage_max)
|
||||
stream.write_long(self.damage_type)
|
||||
stream.write_long(self.damage_min)
|
||||
stream.write_long(self.damage_max)
|
||||
|
||||
def load_json(self, data):
|
||||
self.damage_type = STRING_TO_DAMAGE[data['damage_type']]
|
||||
@@ -45,11 +45,11 @@ class Damage:
|
||||
class Offerings:
|
||||
def load_binary(self, stream: ResStream):
|
||||
self.offering_type = stream.read_string()
|
||||
self.offering_value = stream.read_dword()
|
||||
self.offering_value = stream.read_long()
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
stream.write_string(self.offering_type)
|
||||
stream.write_dword(self.offering_value)
|
||||
stream.write_long(self.offering_value)
|
||||
|
||||
def load_json(self, data):
|
||||
self.offering_type = data['offering_type']
|
||||
@@ -68,7 +68,7 @@ class Weapon:
|
||||
self.weapon_max_range = stream.read_float()
|
||||
self.weapon_projectile_id = stream.read_qword()
|
||||
self.weapon_projectile_speed = stream.read_float()
|
||||
self.weapon_combat_idle_anim = stream.read_dword()
|
||||
self.weapon_combat_idle_anim = stream.read_long()
|
||||
num_damages = stream.read_dword()
|
||||
self.weapon_damage = [Damage() for _ in range(num_damages)]
|
||||
for damage in self.weapon_damage:
|
||||
@@ -76,15 +76,15 @@ class Weapon:
|
||||
num_right_anims = stream.read_dword()
|
||||
self.weapon_attack_anim_right = [
|
||||
[
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
stream.read_long(),
|
||||
] for _ in range(num_right_anims)
|
||||
]
|
||||
num_left_anims = stream.read_dword()
|
||||
self.weapon_attack_anim_left = [
|
||||
[
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
stream.read_long(),
|
||||
] for _ in range(num_left_anims)
|
||||
]
|
||||
|
||||
@@ -93,18 +93,18 @@ class Weapon:
|
||||
stream.write_float(self.weapon_max_range)
|
||||
stream.write_qword(self.weapon_projectile_id)
|
||||
stream.write_float(self.weapon_projectile_speed)
|
||||
stream.write_dword(self.weapon_combat_idle_anim)
|
||||
stream.write_long(self.weapon_combat_idle_anim)
|
||||
stream.write_dword(len(self.weapon_damage))
|
||||
for damage in self.weapon_damage:
|
||||
damage.save_binary(stream)
|
||||
stream.write_dword(len(self.weapon_attack_anim_right))
|
||||
for anim in self.weapon_attack_anim_right:
|
||||
stream.write_dword(anim[0])
|
||||
stream.write_dword(anim[1])
|
||||
stream.write_long(anim[0])
|
||||
stream.write_long(anim[1])
|
||||
stream.write_dword(len(self.weapon_attack_anim_left))
|
||||
for anim in self.weapon_attack_anim_left:
|
||||
stream.write_dword(anim[0])
|
||||
stream.write_dword(anim[1])
|
||||
stream.write_long(anim[0])
|
||||
stream.write_long(anim[1])
|
||||
|
||||
def load_json(self, data):
|
||||
self.weapon_wepspeed = data['weapon_wepspeed']
|
||||
@@ -138,14 +138,14 @@ class Weapon:
|
||||
class ArcItem(ArcCombatObj):
|
||||
def load_binary(self, stream: ResStream):
|
||||
super().load_binary(stream)
|
||||
self.item_type = stream.read_dword()
|
||||
self.item_eq_slots_value = stream.read_dword()
|
||||
self.item_eq_slots_or = stream.read_dword()
|
||||
self.item_eq_slots_and = stream.read_dword()
|
||||
self.item_type = stream.read_long()
|
||||
self.item_eq_slots_value = stream.read_long()
|
||||
self.item_eq_slots_or = stream.read_long()
|
||||
self.item_eq_slots_and = stream.read_long()
|
||||
self.item_eq_slots_type = stream.read_bool()
|
||||
self.item_takeable = stream.read_bool()
|
||||
self.item_value = stream.read_dword()
|
||||
self.item_wt = stream.read_dword()
|
||||
self.item_value = stream.read_long()
|
||||
self.item_wt = stream.read_long()
|
||||
self.item_passive_defense_mod = stream.read_float()
|
||||
self.item_base_name = stream.read_string()
|
||||
self.item_dsc = stream.read_string()
|
||||
@@ -153,7 +153,7 @@ class ArcItem(ArcCombatObj):
|
||||
self.item_health_full = stream.read_float()
|
||||
self.item_skill_used = stream.read_dword()
|
||||
self.item_skill_mastery_used = stream.read_dword()
|
||||
self.item_parry_anim_id = stream.read_dword()
|
||||
self.item_parry_anim_id = stream.read_long()
|
||||
num_adjustments = stream.read_dword()
|
||||
self.item_offering_info = [Offerings() for _ in range(num_adjustments)]
|
||||
for offering in self.item_offering_info:
|
||||
@@ -167,11 +167,11 @@ class ArcItem(ArcCombatObj):
|
||||
|
||||
if self.item_type == ITEM_TYPE_ARMOR:
|
||||
self.item_bulk_factor = stream.read_float()
|
||||
self.item_defense_rating = stream.read_dword()
|
||||
self.item_defense_rating = stream.read_long()
|
||||
self.item_flags = stream.read_dword()
|
||||
self.item_use_flags = stream.read_dword()
|
||||
self.item_post_item_id = stream.read_qword()
|
||||
self.item_initial_charges = stream.read_dword()
|
||||
self.item_initial_charges = stream.read_long()
|
||||
self.item_book_arcana = stream.read_dword()
|
||||
num_skills = stream.read_dword()
|
||||
self.item_skill_req = [SkillLevel() for _ in range(num_skills)]
|
||||
@@ -187,15 +187,15 @@ class ArcItem(ArcCombatObj):
|
||||
self.item_attr_req = [AttributeValue() for _ in range(num_attrs)]
|
||||
for attr in self.item_attr_req:
|
||||
attr.load_binary(stream)
|
||||
self.item_level_req = stream.read_dword()
|
||||
self.item_rank_req = stream.read_dword()
|
||||
self.item_sex_req = stream.read_dword()
|
||||
self.item_level_req = stream.read_long()
|
||||
self.item_rank_req = stream.read_long()
|
||||
self.item_sex_req = stream.read_long()
|
||||
num_user_actions = stream.read_dword()
|
||||
self.item_user_power_action = [
|
||||
[
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
stream.read_long(),
|
||||
] for _ in range(num_user_actions)
|
||||
]
|
||||
num_power_grants = stream.read_dword()
|
||||
@@ -209,7 +209,7 @@ class ArcItem(ArcCombatObj):
|
||||
|
||||
self.item_sheathable = stream.read_bool()
|
||||
if self.item_sheathable:
|
||||
self.item_sheath_slot = stream.read_dword()
|
||||
self.item_sheath_slot = stream.read_long()
|
||||
self.item_sheath_offset = stream.read_tuple()
|
||||
self.item_sheath_rotation = stream.read_tuple()
|
||||
|
||||
@@ -227,19 +227,19 @@ class ArcItem(ArcCombatObj):
|
||||
self.item_resource_costs = [ResourceInfo() for _ in range(num_costs)]
|
||||
for res in self.item_resource_costs:
|
||||
res.load_binary(stream)
|
||||
self.item_bane_rank = stream.read_dword()
|
||||
self.item_bane_rank = stream.read_long()
|
||||
self.item_ignore_saved_actions = stream.read_bool()
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
super().save_binary(stream)
|
||||
stream.write_dword(self.item_type)
|
||||
stream.write_dword(self.item_eq_slots_value)
|
||||
stream.write_dword(self.item_eq_slots_or)
|
||||
stream.write_dword(self.item_eq_slots_and)
|
||||
stream.write_long(self.item_type)
|
||||
stream.write_long(self.item_eq_slots_value)
|
||||
stream.write_long(self.item_eq_slots_or)
|
||||
stream.write_long(self.item_eq_slots_and)
|
||||
stream.write_bool(self.item_eq_slots_type)
|
||||
stream.write_bool(self.item_takeable)
|
||||
stream.write_dword(self.item_value)
|
||||
stream.write_dword(self.item_wt)
|
||||
stream.write_long(self.item_value)
|
||||
stream.write_long(self.item_wt)
|
||||
stream.write_float(self.item_passive_defense_mod)
|
||||
stream.write_string(self.item_base_name)
|
||||
stream.write_string(self.item_dsc)
|
||||
@@ -247,7 +247,7 @@ class ArcItem(ArcCombatObj):
|
||||
stream.write_float(self.item_health_full)
|
||||
stream.write_dword(self.item_skill_used)
|
||||
stream.write_dword(self.item_skill_mastery_used)
|
||||
stream.write_dword(self.item_parry_anim_id)
|
||||
stream.write_long(self.item_parry_anim_id)
|
||||
stream.write_dword(len(self.item_offering_info))
|
||||
for offering in self.item_offering_info:
|
||||
offering.save_binary(stream)
|
||||
@@ -257,11 +257,11 @@ class ArcItem(ArcCombatObj):
|
||||
stream.write_dword(self.item_secondary_attr)
|
||||
if self.item_type == ITEM_TYPE_ARMOR:
|
||||
stream.write_float(self.item_bulk_factor)
|
||||
stream.write_dword(self.item_defense_rating)
|
||||
stream.write_long(self.item_defense_rating)
|
||||
stream.write_dword(self.item_flags)
|
||||
stream.write_dword(self.item_use_flags)
|
||||
stream.write_qword(self.item_post_item_id)
|
||||
stream.write_dword(self.item_initial_charges)
|
||||
stream.write_long(self.item_initial_charges)
|
||||
stream.write_dword(self.item_book_arcana)
|
||||
stream.write_dword(len(self.item_skill_req))
|
||||
for skill in self.item_skill_req:
|
||||
@@ -272,14 +272,14 @@ class ArcItem(ArcCombatObj):
|
||||
stream.write_dword(len(self.item_attr_req))
|
||||
for attr in self.item_attr_req:
|
||||
attr.save_binary(stream)
|
||||
stream.write_dword(self.item_level_req)
|
||||
stream.write_dword(self.item_rank_req)
|
||||
stream.write_dword(self.item_sex_req)
|
||||
stream.write_long(self.item_level_req)
|
||||
stream.write_long(self.item_rank_req)
|
||||
stream.write_long(self.item_sex_req)
|
||||
stream.write_dword(len(self.item_user_power_action))
|
||||
for power in self.item_user_power_action:
|
||||
stream.write_dword(power[0])
|
||||
stream.write_dword(power[1])
|
||||
stream.write_dword(power[2])
|
||||
stream.write_long(power[1])
|
||||
stream.write_long(power[2])
|
||||
stream.write_dword(len(self.item_power_grant))
|
||||
for action in self.item_power_grant:
|
||||
action.save_binary(stream)
|
||||
@@ -288,7 +288,7 @@ class ArcItem(ArcCombatObj):
|
||||
grant.save_binary(stream)
|
||||
stream.write_bool(self.item_sheathable)
|
||||
if self.item_sheathable:
|
||||
stream.write_dword(self.item_sheath_slot)
|
||||
stream.write_long(self.item_sheath_slot)
|
||||
stream.write_tuple(self.item_sheath_offset)
|
||||
stream.write_tuple(self.item_sheath_rotation)
|
||||
stream.write_bool(self.item_has_stub)
|
||||
@@ -301,7 +301,7 @@ class ArcItem(ArcCombatObj):
|
||||
stream.write_dword(len(self.item_resource_costs))
|
||||
for res in self.item_resource_costs:
|
||||
res.save_binary(stream)
|
||||
stream.write_dword(self.item_bane_rank)
|
||||
stream.write_long(self.item_bane_rank)
|
||||
stream.write_bool(self.item_ignore_saved_actions)
|
||||
|
||||
def load_json(self, data):
|
||||
|
||||
@@ -16,14 +16,14 @@ class ArcKey(ArcItem):
|
||||
self.key_keyval = stream.read_qword()
|
||||
self.key_keyval2 = stream.read_qword()
|
||||
self.key_keyval3 = stream.read_qword()
|
||||
self.key_setting = stream.read_dword()
|
||||
self.key_setting = stream.read_long()
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
super().save_binary(stream)
|
||||
stream.write_qword(self.key_keyval)
|
||||
stream.write_qword(self.key_keyval2)
|
||||
stream.write_qword(self.key_keyval3)
|
||||
stream.write_dword(self.key_setting)
|
||||
stream.write_long(self.key_setting)
|
||||
|
||||
def load_json(self, data):
|
||||
super().load_json(data)
|
||||
|
||||
@@ -16,11 +16,11 @@ from .common.SparseData import SparseData
|
||||
|
||||
class SoundEvent:
|
||||
def load_binary(self, stream: ResStream):
|
||||
self.sound_type = stream.read_dword()
|
||||
self.sound_type = stream.read_long()
|
||||
self.sound_event = stream.read_qword()
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
stream.write_dword(self.sound_type)
|
||||
stream.write_long(self.sound_type)
|
||||
stream.write_qword(self.sound_event)
|
||||
|
||||
def load_json(self, data):
|
||||
@@ -55,8 +55,8 @@ class ArcObj:
|
||||
num_hard_points = stream.read_dword()
|
||||
self.obj_arc_hardpoint_list = [
|
||||
[
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
stream.read_long(),
|
||||
[stream.read_float() for _ in range(10)]
|
||||
] for _ in range(num_hard_points)
|
||||
]
|
||||
@@ -84,8 +84,8 @@ class ArcObj:
|
||||
sound_event.save_binary(stream)
|
||||
stream.write_dword(len(self.obj_arc_hardpoint_list))
|
||||
for n, m, points in self.obj_arc_hardpoint_list:
|
||||
stream.write_dword(n)
|
||||
stream.write_dword(m)
|
||||
stream.write_long(n)
|
||||
stream.write_long(m)
|
||||
for i in range(10):
|
||||
stream.write_float(points[i])
|
||||
self.obj_sparse_data.save_binary(stream)
|
||||
|
||||
@@ -48,8 +48,8 @@ class SkillAdjust:
|
||||
num_adjusts = stream.read_dword()
|
||||
self.skill_adjusts = [
|
||||
[
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
stream.read_long(),
|
||||
] for _ in range(num_adjusts)
|
||||
]
|
||||
|
||||
@@ -57,8 +57,8 @@ class SkillAdjust:
|
||||
stream.write_dword(self.skill_type)
|
||||
stream.write_dword(len(self.skill_adjusts))
|
||||
for skill in self.skill_adjusts:
|
||||
stream.write_dword(skill[0])
|
||||
stream.write_dword(skill[1])
|
||||
stream.write_long(skill[0])
|
||||
stream.write_long(skill[1])
|
||||
|
||||
def load_json(self, data):
|
||||
self.skill_type = string_to_hash(data['skill_type'])
|
||||
@@ -98,23 +98,23 @@ class BodyPart:
|
||||
class ArcRune(ArcItem):
|
||||
def load_binary(self, stream: ResStream):
|
||||
super().load_binary(stream)
|
||||
self.rune_type = stream.read_dword()
|
||||
self.rune_type = stream.read_long()
|
||||
self.rune_sub_type = stream.read_dword()
|
||||
self.rune_is_standard_character_creation = stream.read_bool()
|
||||
self.rune_creation_cost = stream.read_dword()
|
||||
self.rune_rank = stream.read_dword()
|
||||
self.rune_pracs_per_level = stream.read_dword()
|
||||
self.rune_creation_cost = stream.read_long()
|
||||
self.rune_rank = stream.read_long()
|
||||
self.rune_pracs_per_level = stream.read_long()
|
||||
self.rune_exp_req_to_level = stream.read_float()
|
||||
self.rune_sex = stream.read_dword()
|
||||
self.rune_sex = stream.read_long()
|
||||
self.rune_class_icon = stream.read_qword()
|
||||
self.rune_health = stream.read_dword()
|
||||
self.rune_mana = stream.read_dword()
|
||||
self.rune_stamina = stream.read_dword()
|
||||
self.rune_health = stream.read_long()
|
||||
self.rune_mana = stream.read_long()
|
||||
self.rune_stamina = stream.read_long()
|
||||
self.rune_min_damage = stream.read_float()
|
||||
self.rune_max_damage = stream.read_float()
|
||||
self.rune_attack = stream.read_dword()
|
||||
self.rune_defense = stream.read_dword()
|
||||
self.rune_level = stream.read_dword()
|
||||
self.rune_attack = stream.read_long()
|
||||
self.rune_defense = stream.read_long()
|
||||
self.rune_level = stream.read_long()
|
||||
self.rune_speed = [
|
||||
stream.read_float() for _ in range(7)
|
||||
]
|
||||
@@ -142,7 +142,7 @@ class ArcRune(ArcItem):
|
||||
]
|
||||
num_genders = stream.read_dword()
|
||||
self.rune_enemy_gender = [
|
||||
stream.read_dword() for _ in range(num_genders)
|
||||
stream.read_long() for _ in range(num_genders)
|
||||
]
|
||||
num_skill_grants = stream.read_dword()
|
||||
self.rune_skill_grant = [SkillGrant() for _ in range(num_skill_grants)]
|
||||
@@ -165,14 +165,14 @@ class ArcRune(ArcItem):
|
||||
[
|
||||
stream.read_float(),
|
||||
stream.read_float(),
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
stream.read_long(),
|
||||
stream.read_qword(),
|
||||
stream.read_float(),
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
stream.read_long(),
|
||||
stream.read_long(),
|
||||
stream.read_long(),
|
||||
] for _ in range(num_natural_attacks)
|
||||
]
|
||||
num_enchants = stream.read_dword()
|
||||
@@ -210,23 +210,23 @@ class ArcRune(ArcItem):
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
super().save_binary(stream)
|
||||
stream.write_dword(self.rune_type)
|
||||
stream.write_long(self.rune_type)
|
||||
stream.write_dword(self.rune_sub_type)
|
||||
stream.write_bool(self.rune_is_standard_character_creation)
|
||||
stream.write_dword(self.rune_creation_cost)
|
||||
stream.write_dword(self.rune_rank)
|
||||
stream.write_dword(self.rune_pracs_per_level)
|
||||
stream.write_long(self.rune_creation_cost)
|
||||
stream.write_long(self.rune_rank)
|
||||
stream.write_long(self.rune_pracs_per_level)
|
||||
stream.write_float(self.rune_exp_req_to_level)
|
||||
stream.write_dword(self.rune_sex)
|
||||
stream.write_long(self.rune_sex)
|
||||
stream.write_qword(self.rune_class_icon)
|
||||
stream.write_dword(self.rune_health)
|
||||
stream.write_dword(self.rune_mana)
|
||||
stream.write_dword(self.rune_stamina)
|
||||
stream.write_long(self.rune_health)
|
||||
stream.write_long(self.rune_mana)
|
||||
stream.write_long(self.rune_stamina)
|
||||
stream.write_float(self.rune_min_damage)
|
||||
stream.write_float(self.rune_max_damage)
|
||||
stream.write_dword(self.rune_attack)
|
||||
stream.write_dword(self.rune_defense)
|
||||
stream.write_dword(self.rune_level)
|
||||
stream.write_long(self.rune_attack)
|
||||
stream.write_long(self.rune_defense)
|
||||
stream.write_long(self.rune_level)
|
||||
for i in range(7):
|
||||
stream.write_float(self.rune_speed[i])
|
||||
self.rune_group.save_binary(stream)
|
||||
@@ -248,7 +248,7 @@ class ArcRune(ArcItem):
|
||||
stream.write_dword(monster)
|
||||
stream.write_dword(len(self.rune_enemy_gender))
|
||||
for gender in self.rune_enemy_gender:
|
||||
stream.write_dword(gender)
|
||||
stream.write_long(gender)
|
||||
stream.write_dword(len(self.rune_skill_grant))
|
||||
for grant in self.rune_skill_grant:
|
||||
grant.save_binary(stream)
|
||||
@@ -265,14 +265,14 @@ class ArcRune(ArcItem):
|
||||
for attack in self.rune_naturalattacks:
|
||||
stream.write_float(attack[0])
|
||||
stream.write_float(attack[1])
|
||||
stream.write_dword(attack[2])
|
||||
stream.write_dword(attack[3])
|
||||
stream.write_long(attack[2])
|
||||
stream.write_long(attack[3])
|
||||
stream.write_qword(attack[4])
|
||||
stream.write_float(attack[5])
|
||||
stream.write_dword(attack[6])
|
||||
stream.write_dword(attack[7])
|
||||
stream.write_dword(attack[8])
|
||||
stream.write_dword(attack[9])
|
||||
stream.write_long(attack[6])
|
||||
stream.write_long(attack[7])
|
||||
stream.write_long(attack[8])
|
||||
stream.write_long(attack[9])
|
||||
stream.write_dword(len(self.rune_enchantment_type))
|
||||
for enchantment in self.rune_enchantment_type:
|
||||
stream.write_dword(enchantment)
|
||||
|
||||
@@ -20,9 +20,9 @@ class Sound:
|
||||
self.sound_max_dist = stream.read_float()
|
||||
self.sound_dist = stream.read_bool()
|
||||
self.sound_loop = stream.read_bool()
|
||||
self.sound_chance = stream.read_dword()
|
||||
self.sound_chance = stream.read_long()
|
||||
self.sound_interval = stream.read_float()
|
||||
self.sound_reserved = stream.read_dword()
|
||||
self.sound_reserved = stream.read_long()
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
stream.write_qword(self.sound_0)
|
||||
@@ -31,9 +31,9 @@ class Sound:
|
||||
stream.write_float(self.sound_max_dist)
|
||||
stream.write_bool(self.sound_dist)
|
||||
stream.write_bool(self.sound_loop)
|
||||
stream.write_dword(self.sound_chance)
|
||||
stream.write_long(self.sound_chance)
|
||||
stream.write_float(self.sound_interval)
|
||||
stream.write_dword(self.sound_reserved)
|
||||
stream.write_long(self.sound_reserved)
|
||||
|
||||
def load_json(self, data):
|
||||
self.sound_0 = data['sound_0']
|
||||
|
||||
@@ -30,7 +30,7 @@ class Inventory:
|
||||
elif self.inventory_type == INVENTORY_TYPE_BOOTYTABLE:
|
||||
self.inventory_table = [
|
||||
stream.read_float(),
|
||||
stream.read_dword(),
|
||||
stream.read_long(),
|
||||
]
|
||||
|
||||
def save_binary(self, stream: ResStream):
|
||||
@@ -44,7 +44,7 @@ class Inventory:
|
||||
stream.write_qword(self.inventory_items[1])
|
||||
elif self.inventory_type == INVENTORY_TYPE_BOOTYTABLE:
|
||||
stream.write_float(self.inventory_table[0])
|
||||
stream.write_dword(self.inventory_table[1])
|
||||
stream.write_long(self.inventory_table[1])
|
||||
|
||||
def load_json(self, data):
|
||||
self.inventory_type = STRING_TO_INVENTORY_TYPE[data['type']]
|
||||
|
||||
@@ -23,7 +23,7 @@ class SparseData:
|
||||
value = None
|
||||
|
||||
if sparse_type == SPARSE_VAL_LONG:
|
||||
value = stream.read_dword()
|
||||
value = stream.read_long()
|
||||
|
||||
elif sparse_type == SPARSE_VAL_FLOAT:
|
||||
value = stream.read_float()
|
||||
@@ -65,7 +65,7 @@ class SparseData:
|
||||
|
||||
sparse_type = SPARSE_TAG_TO_SPARSE_TYPE[tag]
|
||||
if sparse_type == SPARSE_VAL_LONG:
|
||||
stream.write_dword(value)
|
||||
stream.write_long(value)
|
||||
|
||||
elif sparse_type == SPARSE_VAL_FLOAT:
|
||||
stream.write_float(value)
|
||||
|
||||
@@ -30,6 +30,10 @@ class ResStream:
|
||||
data = self.buffer.read(4)
|
||||
return struct.unpack('<I', data)[0]
|
||||
|
||||
def read_long(self):
|
||||
data = self.buffer.read(4)
|
||||
return struct.unpack('<i', data)[0]
|
||||
|
||||
def read_qword(self):
|
||||
dwords = struct.unpack('<II', self.buffer.read(8))
|
||||
buffer = struct.pack('<II', dwords[1], dwords[0])
|
||||
@@ -72,6 +76,10 @@ class ResStream:
|
||||
data = struct.pack('<I', value)
|
||||
self.buffer.write(data)
|
||||
|
||||
def write_long(self, value):
|
||||
data = struct.pack('<i', value)
|
||||
self.buffer.write(data)
|
||||
|
||||
def write_qword(self, value):
|
||||
qword = struct.pack('<Q', value)
|
||||
dwords = [
|
||||
|
||||
Reference in new issue
Block a user