arkparse 0.2.2__tar.gz → 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. {arkparse-0.2.2 → arkparse-0.2.3}/.gitignore +1 -0
  2. {arkparse-0.2.2 → arkparse-0.2.3}/PKG-INFO +1 -1
  3. {arkparse-0.2.2 → arkparse-0.2.3}/pyproject.toml +1 -1
  4. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/api/base_api.py +29 -5
  5. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/api/dino_api.py +14 -15
  6. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/api/player_api.py +8 -2
  7. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/api/structure_api.py +38 -46
  8. arkparse-0.2.3/src/arkparse/assets/RAGNAROK.PNG +0 -0
  9. arkparse-0.2.3/src/arkparse/assets/THE_ISLAND.PNG +0 -0
  10. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/classes/dinos.py +48 -7
  11. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/bases/base.py +3 -0
  12. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/dinos/dino.py +18 -3
  13. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/dinos/dino_ai_controller.py +1 -1
  14. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/dinos/stats.py +61 -0
  15. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/dinos/tamed_dino.py +38 -7
  16. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/misc/__parsed_object_base.py +11 -0
  17. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/misc/dino_owner.py +9 -5
  18. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/misc/inventory.py +0 -1
  19. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/structures/structure_with_inventory.py +11 -6
  20. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_property_insertor.py +24 -1
  21. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/actor_transform.py +12 -0
  22. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_rotator.py +12 -5
  23. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/saves/asa_save.py +7 -1
  24. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/utils/heatmap_visualization.py +6 -4
  25. arkparse-0.2.2/src/arkparse/assets/RAGNAROK.PNG +0 -0
  26. {arkparse-0.2.2 → arkparse-0.2.3}/LICENSE +0 -0
  27. {arkparse-0.2.2 → arkparse-0.2.3}/README.md +0 -0
  28. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/__init__.py +0 -0
  29. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/api/__init__.py +0 -0
  30. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/api/equipment_api.py +0 -0
  31. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/api/general_api.py +0 -0
  32. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/api/json_api.py +0 -0
  33. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/api/rcon_api.py +0 -0
  34. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/api/stackable_api.py +0 -0
  35. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/ark_tribe.py +0 -0
  36. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/ABERRATION.PNG +0 -0
  37. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/__init__.py +0 -0
  38. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/heavy_inventory +0 -0
  39. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/tamable_dinos.txt +0 -0
  40. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/armor +0 -0
  41. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/armor_bp +0 -0
  42. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/armor_bp_n.json +0 -0
  43. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/armor_n.json +0 -0
  44. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/saddle +0 -0
  45. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/saddle_bp +0 -0
  46. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/saddle_bp_n.json +0 -0
  47. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/saddle_n.json +0 -0
  48. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/shield +0 -0
  49. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/shield_bp +0 -0
  50. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/shield_bp_n.json +0 -0
  51. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/shield_n.json +0 -0
  52. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/weapon +0 -0
  53. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/weapon_bp +0 -0
  54. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/weapon_bp_n.json +0 -0
  55. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/equipment/weapon_n.json +0 -0
  56. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/inventory/with_item_n.json +0 -0
  57. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/stackable/stackable +0 -0
  58. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/assets/templates/stackable/stackable_n.json +0 -0
  59. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/classes/__init__.py +0 -0
  60. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/classes/consumables.py +0 -0
  61. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/classes/equipment.py +0 -0
  62. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/classes/placed_structures.py +0 -0
  63. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/classes/player.py +0 -0
  64. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/classes/resources.py +0 -0
  65. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/enums/__init__.py +0 -0
  66. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/enums/ark_dino_trait.py +0 -0
  67. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/enums/ark_enum.py +0 -0
  68. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/enums/ark_equipment_stat.py +0 -0
  69. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/enums/ark_item_quality.py +0 -0
  70. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/enums/ark_map.py +0 -0
  71. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/enums/ark_stat.py +0 -0
  72. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/ftp/__init__.py +0 -0
  73. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/ftp/ark_ftp_client.py +0 -0
  74. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/helpers/dino/is_wild_tamed.py +0 -0
  75. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/logging/__init__.py +0 -0
  76. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/logging/ark_save_logger.py +0 -0
  77. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/__init__.py +0 -0
  78. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/ark_game_object.py +0 -0
  79. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/cryopods/cryopod.py +0 -0
  80. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/dinos/__init__.py +0 -0
  81. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/dinos/baby.py +0 -0
  82. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/dinos/tamed_baby.py +0 -0
  83. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/equipment/__armor_defaults.py +0 -0
  84. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/equipment/__equipment.py +0 -0
  85. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/equipment/__equipment_with_armor.py +0 -0
  86. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/equipment/__equipment_with_durability.py +0 -0
  87. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/equipment/__init__.py +0 -0
  88. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/equipment/armor.py +0 -0
  89. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/equipment/saddle.py +0 -0
  90. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/equipment/shield.py +0 -0
  91. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/equipment/weapon.py +0 -0
  92. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/misc/inventory_item.py +0 -0
  93. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/misc/object_crafter.py +0 -0
  94. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/misc/object_owner.py +0 -0
  95. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/stackables/__init__.py +0 -0
  96. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/stackables/_stackable.py +0 -0
  97. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/stackables/ammo.py +0 -0
  98. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/stackables/resource.py +0 -0
  99. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/structures/__init__.py +0 -0
  100. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/object_model/structures/structure.py +0 -0
  101. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/__init__.py +0 -0
  102. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_base_value_parser.py +0 -0
  103. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_base_value_validator.py +0 -0
  104. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_binary_reader_base.py +0 -0
  105. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_byte_operator.py +0 -0
  106. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/__init__.py +0 -0
  107. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/_property_insertor.py +0 -0
  108. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/_property_parser.py +0 -0
  109. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/_property_replacer.py +0 -0
  110. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/ark_binary_parser.py +0 -0
  111. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/ark_property.py +0 -0
  112. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/ark_value_type.py +0 -0
  113. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/struct/__init__.py +0 -0
  114. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_dino_ancestor_entry.py +0 -0
  115. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_item_net_id.py +0 -0
  116. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_my_persistent_buff_datas.py +0 -0
  117. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_object_property.py +0 -0
  118. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_struct_type.py +0 -0
  119. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_tracked_actor_id_category_pair_with_bool.py +0 -0
  120. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_unique_net_id_repl.py +0 -0
  121. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_vector.py +0 -0
  122. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_legacy_parsing/struct/ark_vector_bool_pair.py +0 -0
  123. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_property_parser.py +0 -0
  124. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/_property_replacer.py +0 -0
  125. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/ark_archive.py +0 -0
  126. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/ark_binary_parser.py +0 -0
  127. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/ark_object.py +0 -0
  128. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/ark_property.py +0 -0
  129. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/ark_property_container.py +0 -0
  130. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/ark_set.py +0 -0
  131. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/ark_value_type.py +0 -0
  132. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/array_property.py +0 -0
  133. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/game_object_reader_configuration.py +0 -0
  134. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/__init__.py +0 -0
  135. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_color.py +0 -0
  136. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_crafting_resource_requirement.py +0 -0
  137. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_custom_item_data.py +0 -0
  138. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_dino_ancestor_entry.py +0 -0
  139. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_gacha_resource_struct.py +0 -0
  140. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_gene_trait_struct.py +0 -0
  141. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_gigantoraptor_bonded_struct.py +0 -0
  142. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_int_point.py +0 -0
  143. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_item_net_id.py +0 -0
  144. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_key_value_pair.py +0 -0
  145. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_linear_color.py +0 -0
  146. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_my_persistent_buff_datas.py +0 -0
  147. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_object_property.py +0 -0
  148. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_player_death_reason.py +0 -0
  149. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_primal_saddle_structure.py +0 -0
  150. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_quat.py +0 -0
  151. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_server_custom_folder.py +0 -0
  152. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_struct_type.py +0 -0
  153. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_tracked_actor_id_category_pair_with_bool.py +0 -0
  154. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_unique_net_id_repl.py +0 -0
  155. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_vector.py +0 -0
  156. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/ark_vector_bool_pair.py +0 -0
  157. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/object_reference.py +0 -0
  158. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/parsing/struct/unknown_struct.py +0 -0
  159. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/player/ark_character_config.py +0 -0
  160. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/player/ark_character_stats.py +0 -0
  161. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/player/ark_persistent_buff_data.py +0 -0
  162. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/player/ark_player.py +0 -0
  163. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/saves/__init__.py +0 -0
  164. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/saves/header_location.py +0 -0
  165. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/saves/save_context.py +0 -0
  166. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/utils/__init__.py +0 -0
  167. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/utils/import_file.py +0 -0
  168. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/utils/json_utils.py +0 -0
  169. {arkparse-0.2.2 → arkparse-0.2.3}/src/arkparse/utils/temp_files.py +0 -0
@@ -85,6 +85,7 @@ ipython_config.py
85
85
 
86
86
  **/binary-reader/**
87
87
  src/binary_reader/
88
+ tests/temp**
88
89
 
89
90
  # pyenv
90
91
  # For a library or package, you might want to ignore these files since the code is
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arkparse
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: A package to parse and modify ark save files
5
5
  Project-URL: Homepage, https://github.com/VincentHenauGithub/ark-save-parser
6
6
  Author-email: Vincent Henau <vincent.henau.github@gmail.com>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "arkparse"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  dependencies = [
9
9
  "pytz>=2025.2",
10
10
  "rcon>=2.4.9",
@@ -15,6 +15,7 @@ from arkparse.parsing.struct import ActorTransform
15
15
  from arkparse.parsing import ArkBinaryParser
16
16
  from arkparse.object_model import ArkGameObject
17
17
  from arkparse.utils import ImportFile
18
+ from arkparse.logging import ArkSaveLogger
18
19
 
19
20
  class BaseApi(StructureApi):
20
21
  def __init__(self, save, map: ArkMap):
@@ -33,8 +34,8 @@ class BaseApi(StructureApi):
33
34
  closest_dist = dist
34
35
 
35
36
  return closest
36
-
37
- def get_base_at(self, coords: MapCoords, radius: float = 0.3, owner_tribe_id = None) -> Base:
37
+
38
+ def get_base_at(self, coords: MapCoords, radius: float = 0.3, owner_tribe_id = None, keystone: Structure = None) -> Base:
38
39
  structures = self.get_at_location(self.map, coords, radius)
39
40
  if structures is None or len(structures) == 0:
40
41
  return None
@@ -50,10 +51,9 @@ class BaseApi(StructureApi):
50
51
  if owner_tribe_id is not None:
51
52
  all_structures = {k: v for k, v in all_structures.items() if v.owner.tribe_id == owner_tribe_id}
52
53
 
53
- keystone = self.__get_closest_to(all_structures, coords)
54
-
54
+ if keystone is None:
55
+ keystone = self.__get_closest_to(all_structures, coords)
55
56
  keystone_owner = keystone.owner if keystone is not None else None
56
-
57
57
  filtered_structures = {k: v for k, v in all_structures.items() if v.owner == keystone_owner}
58
58
 
59
59
  return Base(keystone.object.uuid, filtered_structures) if keystone is not None else None
@@ -168,6 +168,30 @@ class BaseApi(StructureApi):
168
168
  base.move_to(location, self.save)
169
169
 
170
170
  return base
171
+
172
+ def get_all_bases(self, only_connected: bool = False, radius: float = 0.3) -> List[Base]:
173
+ all_bases: List[Base] = []
174
+ all_structures: Dict[UUID, Structure] = super().get_all()
175
+ visited_structures: List[UUID] = []
176
+
177
+ for key, structure in all_structures.items():
178
+ base = None
179
+ if key in visited_structures:
180
+ continue
181
+
182
+ if only_connected:
183
+ connected = self.get_connected_structures({key: structure})
184
+ base = Base(structure.uuid, connected)
185
+ all_bases.append(base)
186
+ else:
187
+ base = self.get_base_at(structure.location.as_map_coords(self.map), radius, structure.owner.tribe_id, structure)
188
+
189
+ for structure in base.structures.values():
190
+ visited_structures.append(structure.uuid)
191
+
192
+ ArkSaveLogger.api_log(f"Parsed base at {"Unknown" if base.location is None else base.keystone.location.as_map_coords(self.map)} with {len(base.structures)} structures, owner: {base.owner}")
193
+
194
+ return all_bases
171
195
 
172
196
 
173
197
 
@@ -131,7 +131,7 @@ class DinoApi:
131
131
  continue
132
132
  ArkSaveLogger.set_log_level(ArkSaveLogger.LogTypes.PARSER, True)
133
133
  parser = ArkBinaryParser(self.save.get_game_obj_binary(obj.uuid), self.save.save_context)
134
- cryopod = Cryopod(obj.uuid, parser)
134
+ cryopod = Cryopod(obj.uuid, save=self.save)
135
135
  ArkSaveLogger.set_log_level(ArkSaveLogger.LogTypes.PARSER, False)
136
136
  ArkSaveLogger.error_log(f"Error parsing cryopod {obj.uuid}: {e}")
137
137
 
@@ -391,15 +391,15 @@ class DinoApi:
391
391
  return np.array(heatmap)
392
392
 
393
393
 
394
- def get_best_dino_for_stat(self, classes: List[str] = None, stat: ArkStat = None, only_tamed: bool = False, only_untamed: bool = False, base_stat: bool = False, mutated_stat=False) -> (Dino, int, ArkStat):
394
+ def get_best_dino_for_stat(self, classes: List[str] = None, stat: ArkStat = None, only_tamed: bool = False, only_untamed: bool = False, base_stat: bool = False, mutated_stat=False, level_upper_bound=None) -> (Dino, int, ArkStat):
395
395
  if only_tamed and only_untamed:
396
396
  raise ValueError("Cannot specify both only_tamed and only_untamed")
397
397
 
398
398
  if mutated_stat and base_stat:
399
399
  raise ValueError("Cannot specify both base_stat and base_mutated_stat")
400
400
 
401
- if classes is not None:
402
- dinos = self.get_all_filtered(class_names=classes, include_cryopodded=True)
401
+ if classes is not None or level_upper_bound is not None:
402
+ dinos = self.get_all_filtered(class_names=classes, include_cryopodded=True, level_upper_bound=level_upper_bound)
403
403
  else:
404
404
  dinos = self.get_all()
405
405
 
@@ -450,8 +450,8 @@ class DinoApi:
450
450
  if file_path.name.endswith(".bin") or file_path.name.startswith("loc_"):
451
451
  out.append(ImportFile(str(file_path)))
452
452
  return out
453
-
454
- def import_dino(self, path: Path, location: ActorTransform = None) -> Dino:
453
+
454
+ def import_dino(self, path: Path, location: ActorTransform = None) -> Dino | TamedDino:
455
455
  uuid_translation_map = {}
456
456
 
457
457
  def replace_uuids(uuid_map: Dict[UUID, UUID], bytes_: bytes):
@@ -494,6 +494,7 @@ class DinoApi:
494
494
  ArkSaveLogger.api_log(f"Added inventory item {item.uuid} to DB")
495
495
 
496
496
  # Get inventory and add to DB
497
+ inventory = None
497
498
  for file in files:
498
499
  if file.type == "inv":
499
500
  new_uuid = uuid_translation_map[file.uuid]
@@ -515,8 +516,6 @@ class DinoApi:
515
516
  self.save.add_obj_to_db(new_uuid, parser.byte_buffer)
516
517
  stats = DinoStats(uuid=new_uuid, save=self.save)
517
518
  stats.reidentify(new_uuid)
518
- stats.binary.replace_boolean(stats.object.find_property("bServerFirstInitialized"), False)
519
- self.save.modify_game_obj(stats.object.uuid, stats.binary.byte_buffer)
520
519
  ArkSaveLogger.api_log(f"Added dino stats {stats.uuid} to DB")
521
520
 
522
521
  # Get AI controller and add to DB
@@ -546,16 +545,16 @@ class DinoApi:
546
545
  if location is not None:
547
546
  dino.set_location(location)
548
547
 
549
- dino.binary.replace_boolean(dino.object.find_property("bServerInitializedDino"), False)
550
- # dino.binary.replace_boolean(dino.object.find_property("bSavedWhenStasised"), False)
551
- # dino.binary.replace_u32(dino.object.find_property("TamingTeamID"), 1466169314)
552
- # dino.binary.replace_u32(dino.object.find_property("TargetingTeam"), 1466169314)
553
- # dino.binary.replace_u32(dino.object.find_property("OwningPlayerID"), 290175622)
554
- dino.update_binary()
555
-
556
548
  ArkSaveLogger.api_log(f"Replacing name \"{dino.stats.object.names[1]}\" with \"{dino.object.names[0]}\"")
557
549
  dino.stats.replace_name_at_index_with(1, dino.object.names[0])
558
550
  dino.stats.update_binary()
551
+
552
+ if inventory is not None:
553
+ ArkSaveLogger.api_log(f"Replacing inventory name \"{inventory.object.names[1]}\" with \"{dino.object.names[0]}\"")
554
+ inventory.replace_name_at_index_with(1, dino.object.names[0])
555
+ inventory.update_binary()
556
+ dino: TamedDino = TamedDino(uuid=new_uuid, save=self.save)
557
+ return dino
559
558
 
560
559
  return dino
561
560
 
@@ -125,7 +125,7 @@ class PlayerApi:
125
125
  OBJECT = 0
126
126
  DINO = 1
127
127
 
128
- def __init__(self, save: AsaSave, ignore_error: bool = False):
128
+ def __init__(self, save: AsaSave, ignore_error: bool = False, no_pawns: bool = False):
129
129
  self.players: List[ArkPlayer] = []
130
130
  self.tribes: List[ArkTribe] = []
131
131
  self.tribe_to_player_map: Dict[int, List[ArkPlayer]] = {}
@@ -141,7 +141,7 @@ class PlayerApi:
141
141
  ArkSaveLogger.api_log("Profile data not found in save, checking database")
142
142
  self.from_store = False
143
143
 
144
- if self.save is not None:
144
+ if self.save is not None and not no_pawns:
145
145
  ArkSaveLogger.api_log(f"Retrieving player pawns")
146
146
  self.__init_pawns()
147
147
 
@@ -326,6 +326,12 @@ class PlayerApi:
326
326
  dict[p.id_] = p.stats.experience
327
327
 
328
328
  return self.__calc_stat(xp, stat_type) if not as_dict else dict
329
+
330
+ def get_tribe(self, tribe_id: int):
331
+ for t in self.tribes:
332
+ if t.tribe_id == tribe_id:
333
+ return t
334
+ return None
329
335
 
330
336
  def get_player_with(self, stat: int, stat_type: int = StatType.HIGHEST):
331
337
  istat = self.__get_stat(stat)
@@ -2,7 +2,7 @@ from typing import Dict, Union, List
2
2
  from uuid import UUID
3
3
 
4
4
  from arkparse.saves.asa_save import AsaSave
5
- from arkparse.parsing import GameObjectReaderConfiguration, ArkBinaryParser
5
+ from arkparse.parsing import GameObjectReaderConfiguration
6
6
  from arkparse.ftp.ark_ftp_client import ArkFtpClient
7
7
  from arkparse.utils import TEMP_FILES_DIR
8
8
 
@@ -11,6 +11,7 @@ from arkparse.object_model.misc.object_owner import ObjectOwner
11
11
  from arkparse.object_model.structures import Structure, StructureWithInventory
12
12
  from arkparse.parsing.struct.actor_transform import MapCoords
13
13
  from arkparse.enums.ark_map import ArkMap
14
+ from arkparse.logging import ArkSaveLogger
14
15
 
15
16
  class StructureApi:
16
17
  def __init__(self, save: AsaSave):
@@ -21,52 +22,42 @@ class StructureApi:
21
22
  def get_all_objects(self, config: GameObjectReaderConfiguration = None) -> Dict[UUID, ArkGameObject]:
22
23
  if config is None:
23
24
  reader_config = GameObjectReaderConfiguration(
24
- blueprint_name_filter=lambda name: name is not None and "/Structures" in name and not "PrimalItemStructure_" in name
25
+ blueprint_name_filter=lambda name: name is not None \
26
+ and "/Structures" in name \
27
+ and not "PrimalItemStructure_" in name \
28
+ and not "/Skins/" in name \
29
+ and not "PrimalInventory" in name \
30
+ and not "Tileset" in name \
31
+ and not "PrimalItemStructureSkin" in name
32
+ and not "PrimalItemResource" in name \
33
+ and not "/TrainCarts/" in name \
25
34
  )
26
35
  else:
27
36
  reader_config = config
28
37
 
29
38
  objects = self.save.get_game_objects(reader_config)
30
39
 
31
- # for key, obj in objects.items():
32
- # print(obj.blueprint)
33
-
34
40
  return objects
35
-
36
- def _parse_single_structure(self, obj: ArkGameObject) -> Union[Structure, StructureWithInventory]:
41
+
42
+ def _parse_single_structure(self, obj: ArkGameObject, bypass_inventory: bool = True) -> Union[Structure, StructureWithInventory]:
37
43
  if obj.uuid in self.parsed_structures.keys():
38
44
  return self.parsed_structures[obj.uuid]
39
45
 
40
46
  if obj.get_property_value("MaxItemCount") is not None or (obj.get_property_value("MyInventoryComponent") is not None and obj.get_property_value("CurrentItemCount") is not None):
41
- structure = StructureWithInventory(obj.uuid, self.save)
42
- else:
43
- structure = Structure(obj.uuid, self.save)
44
-
45
- for key, loc in self.save.save_context.actor_transforms.items():
46
- if key == obj.uuid:
47
- structure.set_actor_transform(loc)
48
- break
49
-
50
- self.parsed_structures[obj.uuid] = structure
51
-
52
- return structure
53
-
54
- def _parse_single_structure_fast(self, obj: ArkGameObject, parser: ArkBinaryParser = None) -> Union[Structure | StructureWithInventory]:
55
- """Same as _parse_single_structure, but does not parse Inventory and does not store in cache."""
56
-
57
- if obj.get_property_value("MaxItemCount") is not None or (obj.get_property_value("MyInventoryComponent") is not None and obj.get_property_value("CurrentItemCount") is not None):
58
- structure = StructureWithInventory(obj.uuid, self.save, bypass_inventory=True)
47
+ structure = StructureWithInventory(obj.uuid, self.save, bypass_inventory=bypass_inventory)
59
48
  else:
60
49
  structure = Structure(obj.uuid, self.save)
61
50
 
62
51
  if obj.uuid in self.save.save_context.actor_transforms:
63
52
  structure.set_actor_transform(self.save.save_context.actor_transforms[obj.uuid])
64
53
 
54
+ self.parsed_structures[obj.uuid] = structure
55
+
65
56
  return structure
66
57
 
67
- def get_all(self, config: GameObjectReaderConfiguration = None) -> Dict[UUID, Union[Structure, StructureWithInventory]]:
58
+ def get_all(self, config: GameObjectReaderConfiguration = None, bypass_inventory: bool = True) -> Dict[UUID, Union[Structure, StructureWithInventory]]:
68
59
 
69
- if self.retrieved_all:
60
+ if self.retrieved_all and config is None:
70
61
  return self.parsed_structures
71
62
 
72
63
  objects = self.get_all_objects(config)
@@ -78,8 +69,12 @@ class StructureApi:
78
69
  if obj is None:
79
70
  print(f"Object is None for {key}")
80
71
  continue
72
+
73
+ if obj.get_property_value("StructureID") is None:
74
+ ArkSaveLogger.warning_log(f"Object {obj.uuid} ({obj.blueprint}) is not a structure, skipping")
75
+ continue
81
76
 
82
- structure = self._parse_single_structure(obj)
77
+ structure = self._parse_single_structure(obj, bypass_inventory)
83
78
 
84
79
  structures[obj.uuid] = structure
85
80
 
@@ -88,23 +83,10 @@ class StructureApi:
88
83
 
89
84
  return structures
90
85
 
91
- def get_all_fast(self, config: GameObjectReaderConfiguration = None) -> List[Structure | StructureWithInventory]:
92
- """Same as get_all, but uses fast parsing and does not store in cache."""
93
-
94
- objects = self.get_all_objects(config)
95
-
96
- structures = []
97
-
98
- for obj in objects.values():
99
- if obj is None:
100
- continue
101
- structure = self._parse_single_structure_fast(obj)
102
- structures.append(structure)
103
-
104
- return structures
105
-
106
86
  def get_by_id(self, id: UUID) -> Union[Structure, StructureWithInventory]:
107
87
  obj = self.save.get_game_object_by_id(id)
88
+ if obj is None:
89
+ return None
108
90
  return self._parse_single_structure(obj)
109
91
 
110
92
  def get_at_location(self, map: ArkMap, coords: MapCoords, radius: float = 0.3, classes: List[str] = None) -> Dict[UUID, Union[Structure, StructureWithInventory]]:
@@ -158,11 +140,16 @@ class StructureApi:
158
140
  blueprint_name_filter=lambda name: name in blueprints
159
141
  )
160
142
 
143
+ ArkSaveLogger.api_log(f"Getting structures by class filter: {blueprints}")
144
+
161
145
  structures = self.get_all(config)
162
146
 
163
147
  for key, obj in structures.items():
164
148
  result[key] = obj
165
149
 
150
+ # for key, obj in structures.items():
151
+ # print(obj.blueprint)
152
+
166
153
  return result
167
154
 
168
155
  def filter_by_owner(self, structures: Dict[UUID, Union[Structure, StructureWithInventory]], owner: ObjectOwner = None, owner_tribe_id: int = None, invert: bool = False) -> Dict[UUID, Union[Structure, StructureWithInventory]]:
@@ -193,16 +180,21 @@ class StructureApi:
193
180
  def get_connected_structures(self, structures: Dict[UUID, Union[Structure, StructureWithInventory]]) -> Dict[UUID, Union[Structure, StructureWithInventory]]:
194
181
  result = structures.copy()
195
182
  new_found = True
183
+ ignore = []
196
184
 
197
185
  while new_found:
198
186
  new_found = False
199
187
  new_result = result.copy()
200
- for key, s in result.items():
188
+ for _, s in result.items():
201
189
  for uuid in s.linked_structure_uuids:
202
- if uuid not in new_result.keys():
190
+ if uuid not in new_result.keys() and uuid not in ignore:
203
191
  new_found = True
204
192
  obj = self.get_by_id(uuid)
205
- new_result[uuid] = obj
193
+ if obj is not None:
194
+ new_result[uuid] = obj
195
+ else:
196
+ ignore.append(uuid)
197
+ ArkSaveLogger.api_log(f"Could not find linked structure {uuid}, ignoring")
206
198
  result = new_result
207
199
 
208
200
  return result
@@ -58,7 +58,12 @@ class Abberant:
58
58
  equus, manta, araneo, electrophorus, moschops, diplodocus, megalania,
59
59
  ovis, paraceratherium, sarco, dimorphodon, fasolasuchus, gigantoraptor,
60
60
  trilobite, sabertooth_salmon, meganeura]
61
-
61
+
62
+ class PaleoAlphas:
63
+ alpha_rex = "/PA_EVO_Pack_01/Dinos/EVO_Rex/Alpha/EVO_Alpha_Rex_Character_BP.EVO_Alpha_Rex_Character_BP_C"
64
+
65
+ all_bps = [alpha_rex]
66
+
62
67
  class Alphas:
63
68
  alpha_reaper_king = "/Game/Aberration/Dinos/Nameless/MegaXenomorph_Character_BP_Male_Surface.MegaXenomorph_Character_BP_Male_Surface_C"
64
69
  alpha_karkinos = "/Game/Aberration/Dinos/Crab/MegaCrab_Character_BP.MegaCrab_Character_BP_C"
@@ -71,12 +76,15 @@ class Alphas:
71
76
  alpha_rex = "/Game/PrimalEarth/Dinos/Rex/MegaRex_Character_BP.MegaRex_Character_BP_C"
72
77
  alpha_tuso = "/Game/PrimalEarth/Dinos/Tusoteuthis/Mega_Tusoteuthis_Character_BP.Mega_Tusoteuthis_Character_BP_C"
73
78
  alpha_leedsichthys = "/Game/PrimalEarth/Dinos/Leedsichthys/Alpha_Leedsichthys_Character_BP.Alpha_Leedsichthys_Character_BP_C"
79
+ alpha_fire_wyvern = "/Game/ScorchedEarth/Dinos/Wyvern/MegaWyvern_Character_BP_Fire.MegaWyvern_Character_BP_Fire_C"
80
+
81
+ paleo = PaleoAlphas()
74
82
 
75
83
  all_bps = [
76
84
  alpha_reaper_king, alpha_karkinos, alpha_basilisk,
77
85
  alpha_carnotaurus, alpha_megalodon, alpha_mosasaurus, alpha_raptor,
78
- alpha_deathworm, alpha_rex, alpha_tuso, alpha_leedsichthys
79
- ]
86
+ alpha_deathworm, alpha_rex, alpha_tuso, alpha_leedsichthys, alpha_fire_wyvern
87
+ ] + paleo.all_bps
80
88
 
81
89
  class Flyers:
82
90
  class Wyverns:
@@ -169,6 +177,12 @@ class Corrupted:
169
177
  all_bps = [ arthropluera, carno, chalicotherium, dilo, giganotosaurus,
170
178
  reaper_king, paraceratherium, ptero, raptor, alpha_rex,
171
179
  rex, rock_drake, spino, stego, trike, wyvern ]
180
+
181
+ class event:
182
+ dodo_rex = "/Game/PrimalEarth/Dinos/DodoRex/DodoRex_Character_BP.DodoRex_Character_BP_C"
183
+ dodo_wyvern = "/Game/ScorchedEarth/Dinos/DodoWyvern/DodoWyvern_Character_BP.DodoWyvern_Character_BP_C"
184
+
185
+ all_bps = [dodo_rex, dodo_wyvern]
172
186
 
173
187
  class NonTameable:
174
188
  lamprey = "/Game/Aberration/Dinos/Lamprey/Lamprey_Character.Lamprey_Character_C"
@@ -199,6 +213,7 @@ class NonTameable:
199
213
  yeti = "/Game/PrimalEarth/Dinos/Bigfoot/Yeti_Character_BP.Yeti_Character_BP_C"
200
214
  corrupted = Corrupted()
201
215
  alpha = Alphas()
216
+ event = event()
202
217
 
203
218
  all_bps = [
204
219
  lamprey, lightbug, meganeura, surface_reaper, surface_nameless
@@ -207,7 +222,31 @@ class NonTameable:
207
222
  sabertooth_salmon, trilobite, death_worm, jugbug_oil, jugbug_water,
208
223
  enforcer, scout, defence_unit, polar_bear, iceworm, tek_giga,
209
224
  leedsichthys, yeti
210
- ] + corrupted.all_bps + alpha.all_bps
225
+ ] + corrupted.all_bps + alpha.all_bps + event.all_bps
226
+
227
+ class Paleo:
228
+ yuti = "/PA_Ascension/Dinos/GreaterYuty/Paleo_Yutyrannus_Character_BP.Paleo_Yutyrannus_Character_BP_C"
229
+ fasola = "/PA_Ascension/Dinos/PaleoFasola/Paleo_Fasola_Character_BP.Paleo_Fasola_Character_BP_C"
230
+ gigantoraptor = "/PA_Ascension/Dinos/PaleoGigantoraptor/Paleo_Gigantoraptor_Character_BP.Paleo_Gigantoraptor_Character_BP_C"
231
+ kentro = "/PA_Ascension/Dinos/PaleoKentro/Paleo_Kentro_Character_BP.Paleo_Kentro_Character_BP_C"
232
+ megalosaur = "/PA_Ascension/Dinos/PaleoMegalosaur/Paleo_Megalosaurus_Character_BP.Paleo_Megalosaurus_Character_BP_C"
233
+ moschops = "/PA_Ascension/Dinos/PaleoMoschops/Paleo_Moschops_Character_BP.Paleo_Moschops_Character_BP_C"
234
+ purlovia = "/PA_Ascension/Dinos/PaleoPurlovia/Paleo_Purlovia_Character_BP.Paleo_Purlovia_Character_BP_C"
235
+ raptor = "/PA_Ascension/Dinos/PaleoRaptor/Paleo_Raptor_Character_BP.Paleo_Raptor_Character_BP_C"
236
+ sarco = "/PA_Ascension/Dinos/PaleoSarco/Paleo_Sarco_Character_BP.Paleo_Sarco_Character_BP_C"
237
+ spino = "/PA_Ascension/Dinos/PaleoSpino/Paleo_Spino_Character_BP.Paleo_Spino_Character_BP_C"
238
+ stego = "/PA_Ascension/Dinos/PaleoStego/Paleo_Stego_Character_BP.Paleo_Stego_Character_BP_C"
239
+ thyla = "/PA_Ascension/Dinos/PaleoThyla/Paleo_Thylacoleo_Character_BP.Paleo_Thylacoleo_Character_BP_C"
240
+ trike = "/PA_Ascension/Dinos/PaleoTrike/Paleo_Trike_Character_BP.Paleo_Trike_Character_BP_C"
241
+ giga = "/PA_EVO_Pack_01/Dinos/EVO_Giga/EVO_Giga_Character_BP.EVO_Giga_Character_BP_C"
242
+ rex = "/PA_EVO_Pack_01/Dinos/EVO_Rex/EVO_Rex_Character_BP.EVO_Rex_Character_BP_C"
243
+ legacy_rex = "/PA_EVO_Pack_01/Dinos/EVO_Rex/Legacy/EVO_Legacy_Rex_Character_BP.EVO_Legacy_Rex_Character_BP_C"
244
+ rex = "/PA_EVO_Pack_01/Dinos/EVO_Rex/Paleo/EVO_Paleo_Rex_Character_BP.EVO_Paleo_Rex_Character_BP_C"
245
+ mosa = "/PA_EVO_Pack_02/Dinos/EVO_Mosa/Paleo/EVO_Paleo_Mosa_Character_BP.EVO_Paleo_Mosa_Character_BP_C"
246
+
247
+ all_bps = [yuti, fasola, gigantoraptor, kentro, megalosaur, moschops,
248
+ purlovia, raptor, sarco, spino, stego, thyla, trike,
249
+ giga, rex, legacy_rex, rex, mosa]
211
250
 
212
251
  class Dinos:
213
252
  # Aberrant Dinos
@@ -219,7 +258,7 @@ class Dinos:
219
258
  cosmo = "/Game/Packs/Steampunk/Dinos/JumpingSpider/JumpingSpider_Character_BP.JumpingSpider_Character_BP_C"
220
259
  karkinos = "/Game/Aberration/Dinos/Crab/Crab_Character_BP.Crab_Character_BP_C"
221
260
  yi_ling = "/Game/ASA/Dinos/YiLing/YiLing_Character_BP.YiLing_Character_BP_C"
222
- stegosaurus_duplicate = "/Game/PrimalEarth/Dinos/Stego/Stego_Character_BP.Stego_Character_BP_C"
261
+ stegosaurus = "/Game/PrimalEarth/Dinos/Stego/Stego_Character_BP.Stego_Character_BP_C"
223
262
  giant_bison = "/Game/ASA/Dinos/Bison/Bison_Character_BP.Bison_Character_BP_C"
224
263
  ceratosaurus = "/Game/ASA/Dinos/Ceratosaurus/Dinos/Ceratosaurus_Character_BP_ASA.Ceratosaurus_Character_BP_ASA_C"
225
264
  deinosuchus = "/Game/ASA/Dinos/Deinosuchus/DeinosuchusASA_Character_BP.DeinosuchusASA_Character_BP_C"
@@ -326,6 +365,7 @@ class Dinos:
326
365
  rubble_golem = "/Game/ScorchedEarth/Dinos/RockGolem/RubbleGolem_Character_BP.RubbleGolem_Character_BP_C"
327
366
 
328
367
  abberant = Abberant()
368
+ paleo = Paleo()
329
369
  flyers = Flyers()
330
370
  dlc_dinos = DlcDinos()
331
371
  shoulder_pets = ShoulderPets()
@@ -333,7 +373,7 @@ class Dinos:
333
373
 
334
374
  all_bps = [
335
375
  roll_rat, rock_drake, basilisk, ravager, reaper_queen, cosmo,
336
- karkinos, yi_ling, stegosaurus_duplicate, giant_bison, ceratosaurus,
376
+ karkinos, yi_ling, stegosaurus, giant_bison, ceratosaurus,
337
377
  deinosuchus, deinotherium, fasolasuchus, gigantoraptor, xiphactinus,
338
378
  tamed_reaper_king, achatina, allosaurus, anglerfish, ankylosaurus,
339
379
  arthropleura, baryonix, basilosaurus, onyc, castoroides,
@@ -359,4 +399,5 @@ class Dinos:
359
399
  velonosaur, yutyrannus, tek_parasaur, queen_bee,
360
400
  rubble_golem
361
401
  ] + abberant.all_bps + flyers.all_bps + \
362
- dlc_dinos.all_bps + shoulder_pets.all_bps + non_tameable.all_bps
402
+ dlc_dinos.all_bps + shoulder_pets.all_bps + non_tameable.all_bps + \
403
+ paleo.all_bps
@@ -46,6 +46,9 @@ class Base:
46
46
  average_z = 0
47
47
 
48
48
  for _, structure in self.structures.items():
49
+ if structure.location is None:
50
+ ArkSaveLogger.warning_log(f"Structure {structure.uuid} has no location: {structure.location}")
51
+ continue
49
52
  average_x += structure.location.x
50
53
  average_y += structure.location.y
51
54
  average_z += structure.location.z
@@ -22,6 +22,7 @@ class Dino(ParsedObjectBase):
22
22
 
23
23
  is_female: bool = False
24
24
  is_cryopodded: bool = False
25
+ is_dead: bool = False
25
26
 
26
27
  ai_controller: DinoAiController = None
27
28
 
@@ -38,6 +39,7 @@ class Dino(ParsedObjectBase):
38
39
  self.id1 = self.object.get_property_value("DinoID1")
39
40
  self.id2 = self.object.get_property_value("DinoID2")
40
41
  self.gene_traits = self.object.get_array_property_value("GeneTraits")
42
+ self.is_dead = self.object.get_property_value("bIsDead", False)
41
43
  self.location = ActorTransform(vector=self.object.get_property_value("SavedBaseWorldLocation"))
42
44
 
43
45
  def __init__(self, uuid: UUID = None, save: AsaSave = None):
@@ -48,8 +50,9 @@ class Dino(ParsedObjectBase):
48
50
  self.stats = DinoStats(UUID(stat_uuid), save=save)
49
51
 
50
52
  if save is not None and self.object.get_property_value("Owner") is not None:
51
- ai_uuid = self.object.get_property_value("Owner").value
52
- self.ai_controller = DinoAiController(UUID(ai_uuid), save=save)
53
+ if self.save.is_in_db(UUID(self.object.get_property_value("Owner").value)):
54
+ ai_uuid = self.object.get_property_value("Owner").value
55
+ self.ai_controller = DinoAiController(UUID(ai_uuid), save=save)
53
56
 
54
57
  def __str__(self) -> str:
55
58
  return "Dino(type={}, lv={})".format(self.get_short_name(), self.stats.current_level)
@@ -223,7 +226,8 @@ class Dino(ParsedObjectBase):
223
226
  def store_binary(self, path, name = None, prefix = "obj_", no_suffix=False):
224
227
  loc_name = name if name is not None else str(self.object.uuid)
225
228
  self.stats.store_binary(path, name, prefix="status_", no_suffix=no_suffix)
226
- self.ai_controller.store_binary(path, name, prefix="ai_", no_suffix=no_suffix)
229
+ if self.ai_controller is not None:
230
+ self.ai_controller.store_binary(path, name, prefix="ai_", no_suffix=no_suffix)
227
231
  self.location.store_json(path, loc_name)
228
232
  return super().store_binary(path, name, prefix=prefix, no_suffix=no_suffix)
229
233
 
@@ -241,6 +245,17 @@ class Dino(ParsedObjectBase):
241
245
  self.update_binary()
242
246
  self.location = location
243
247
 
248
+ def heal(self):
249
+ self.stats.heal()
250
+
251
+ def disable_wandering(self):
252
+ """
253
+ Disables the wandering behavior of the dino.
254
+ """
255
+ if self.object.has_property("bEnableTamedWandering"):
256
+ self.binary.replace_boolean(self.object.find_property("bEnableTamedWandering"), False)
257
+ self.update_binary()
258
+
244
259
  def reidentify(self, new_uuid: UUID = None, update=True):
245
260
  new_id_1 = random.randint(0, 2**32 - 1)
246
261
  new_id_2 = random.randint(0, 2**32 - 1)
@@ -10,7 +10,7 @@ class DinoAiController(ParsedObjectBase):
10
10
  def __init_props__(self):
11
11
  super().__init_props__()
12
12
 
13
- self.targeting_team = self.object.get_property_value("TargetingTeam")
13
+ self.targeting_team = self.object.get_property_value("TargetingTeam", 0)
14
14
 
15
15
  def __init__(self, uuid: UUID = None, save: AsaSave = None):
16
16
  super().__init__(uuid, save=save)
@@ -56,6 +56,12 @@ class StatPoints:
56
56
  return self.health + self.stamina + self.torpidity + self.oxygen + self.food + \
57
57
  self.water + self.temperature + self.weight + self.melee_damage + \
58
58
  self.movement_speed + self.fortitude + self.crafting_speed + (1 if self.type == "NumberOfLevelUpPointsApplied" else 0)
59
+
60
+ def set_stat(self, stat: ArkStat, value: int):
61
+ if stat.value not in STAT_POSITION_MAP:
62
+ raise ValueError(f"Invalid stat: {stat}")
63
+
64
+ setattr(self, STAT_POSITION_MAP[stat.value], value)
59
65
 
60
66
  def __str__(self):
61
67
  stats = [
@@ -250,3 +256,58 @@ class DinoStats(ParsedObjectBase):
250
256
  self.binary.replace_boolean(prop, False)
251
257
 
252
258
  self.update_binary()
259
+
260
+ def heal(self):
261
+ prop = self.object.find_property("CurrentStatusValues", ArkStat.HEALTH.value)
262
+ if prop is not None:
263
+ # Set health to a hugely high value, effectively healing the dino since it is capped at max health which is not directly retrievable
264
+ self.binary.replace_float(prop, 999999999999999999999)
265
+ self.update_binary()
266
+
267
+ def set_levels(self, levels: int, stat: ArkStat):
268
+ prop = self.object.find_property("NumberOfLevelUpPointsApplied", stat.value)
269
+ if prop is not None:
270
+ self.binary.replace_byte_property(prop, levels)
271
+ else:
272
+ raise ValueError(f"Property 'NumberOfLevelUpPointsApplied' for stat {stat} not found in object {self.object.uuid}")
273
+
274
+ self.update_binary()
275
+
276
+ def set_tamed_levels(self, levels: int, stat: ArkStat):
277
+ self.added_stat_points.set_stat(stat, levels)
278
+
279
+ prop = self.object.find_property("NumberOfLevelUpPointsAppliedTamed", stat.value)
280
+ if prop is not None:
281
+ self.binary.replace_byte_property(prop, levels)
282
+ else:
283
+ first_index_before = None
284
+ first_index_after = None
285
+ for i in range(stat.value):
286
+ index = stat.value - i - 1
287
+ prop = self.object.find_property("NumberOfLevelUpPointsAppliedTamed", index)
288
+
289
+ if prop is not None:
290
+ first_index_before = index
291
+ break
292
+
293
+ for i in range(stat.value, 12):
294
+ index = i
295
+ prop = self.object.find_property("NumberOfLevelUpPointsAppliedTamed", index)
296
+
297
+ if prop is not None:
298
+ first_index_after = index
299
+ break
300
+
301
+ if first_index_before is None and first_index_after is None:
302
+ raise ValueError(f"Cannot insert if no other stats are present for stat {stat} in object {self.object.uuid}")
303
+
304
+ if first_index_before is not None:
305
+ prop_before = self.object.find_property("NumberOfLevelUpPointsAppliedTamed", first_index_before)
306
+ self.binary.insert_byte_property(prop_before.value_position + 1 ,"NumberOfLevelUpPointsAppliedTamed", levels, stat.value)
307
+ elif first_index_after is not None:
308
+ prop_after = self.object.find_property("NumberOfLevelUpPointsAppliedTamed", first_index_after)
309
+ self.binary.insert_byte_property(prop_after.name_position, "NumberOfLevelUpPointsAppliedTamed", levels, stat.value)
310
+
311
+ self.update_object()
312
+
313
+ self.update_binary()