bcsfe 3.1.0__tar.gz → 3.2.0b2__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 (181) hide show
  1. {bcsfe-3.1.0/src/bcsfe.egg-info → bcsfe-3.2.0b2}/PKG-INFO +4 -2
  2. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/README.md +3 -1
  3. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/__init__.py +1 -1
  4. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/__main__.py +3 -1
  5. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/color.py +4 -14
  6. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/dialog_creator.py +6 -2
  7. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/edits/basic_items.py +6 -0
  8. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/edits/cat_editor.py +0 -1
  9. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/edits/event_tickets.py +2 -1
  10. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/edits/map.py +5 -1
  11. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/feature_handler.py +10 -2
  12. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/save_management.py +90 -27
  13. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/__init__.py +20 -2
  14. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/__init__.py +2 -0
  15. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/cat.py +2 -30
  16. bcsfe-3.2.0b2/src/bcsfe/core/game/catbase/gambling.py +111 -0
  17. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/enigma.py +5 -0
  18. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/gauntlets.py +4 -0
  19. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/map_names.py +56 -18
  20. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/outbreaks.py +2 -10
  21. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/story.py +1 -1
  22. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/zero_legends.py +16 -3
  23. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/bc_csv.py +1 -1
  24. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/config.py +5 -6
  25. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/path.py +2 -6
  26. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/save.py +32 -155
  27. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/server/game_data_getter.py +92 -108
  28. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/server/updater.py +1 -2
  29. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/core/main.properties +4 -1
  30. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/core/save.properties +13 -3
  31. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/core/server.properties +4 -0
  32. bcsfe-3.2.0b2/src/bcsfe/files/locales/en/edits/gambling.properties +3 -0
  33. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/items.properties +3 -0
  34. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/map.properties +3 -1
  35. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/treasures.properties +2 -2
  36. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/core/main.properties +3 -0
  37. bcsfe-3.2.0b2/src/bcsfe/files/locales/vi/edits/gambling.properties +3 -0
  38. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/items.properties +4 -1
  39. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/map.properties +4 -0
  40. {bcsfe-3.1.0 → bcsfe-3.2.0b2/src/bcsfe.egg-info}/PKG-INFO +4 -2
  41. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe.egg-info/SOURCES.txt +3 -0
  42. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/LICENSE +0 -0
  43. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/MANIFEST.in +0 -0
  44. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/pyproject.toml +0 -0
  45. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/setup.cfg +0 -0
  46. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/setup.py +0 -0
  47. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/__init__.py +0 -0
  48. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/edits/__init__.py +0 -0
  49. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/edits/aku_realm.py +0 -0
  50. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/edits/clear_tutorial.py +0 -0
  51. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/edits/enemy_editor.py +0 -0
  52. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/edits/fixes.py +0 -0
  53. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/edits/max_all.py +0 -0
  54. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/edits/rare_ticket_trade.py +0 -0
  55. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/file_dialog.py +0 -0
  56. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/main.py +0 -0
  57. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/cli/server_cli.py +0 -0
  58. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/country_code.py +0 -0
  59. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/crypto.py +0 -0
  60. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/__init__.py +0 -0
  61. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/battle/__init__.py +0 -0
  62. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/battle/battle_items.py +0 -0
  63. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/battle/cleared_slots.py +0 -0
  64. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/battle/enemy.py +0 -0
  65. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/battle/slots.py +0 -0
  66. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/beacon_base.py +0 -0
  67. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/drop_chara.py +0 -0
  68. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/gatya.py +0 -0
  69. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/gatya_item.py +0 -0
  70. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/item_pack.py +0 -0
  71. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/login_bonuses.py +0 -0
  72. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/matatabi.py +0 -0
  73. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/medals.py +0 -0
  74. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/mission.py +0 -0
  75. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/my_sale.py +0 -0
  76. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/nyanko_club.py +0 -0
  77. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/officer_pass.py +0 -0
  78. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/playtime.py +0 -0
  79. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/powerup.py +0 -0
  80. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/scheme_items.py +0 -0
  81. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/special_skill.py +0 -0
  82. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/stamp.py +0 -0
  83. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/talent_orbs.py +0 -0
  84. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/unlock_popups.py +0 -0
  85. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/upgrade.py +0 -0
  86. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/catbase/user_rank_rewards.py +0 -0
  87. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/gamoto/__init__.py +0 -0
  88. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/gamoto/base_materials.py +0 -0
  89. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/gamoto/cat_shrine.py +0 -0
  90. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/gamoto/catamins.py +0 -0
  91. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/gamoto/gamatoto.py +0 -0
  92. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/gamoto/ototo.py +0 -0
  93. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/localizable.py +0 -0
  94. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/__init__.py +0 -0
  95. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/aku.py +0 -0
  96. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/challenge.py +0 -0
  97. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/chapters.py +0 -0
  98. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/dojo.py +0 -0
  99. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/event.py +0 -0
  100. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/ex_stage.py +0 -0
  101. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/item_reward_stage.py +0 -0
  102. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/legend_quest.py +0 -0
  103. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/map_reset.py +0 -0
  104. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/timed_score.py +0 -0
  105. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/tower.py +0 -0
  106. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game/map/uncanny.py +0 -0
  107. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/game_version.py +0 -0
  108. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/__init__.py +0 -0
  109. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/adb_handler.py +0 -0
  110. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/command.py +0 -0
  111. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/data.py +0 -0
  112. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/git_handler.py +0 -0
  113. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/json_file.py +0 -0
  114. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/root_handler.py +0 -0
  115. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/thread_helper.py +0 -0
  116. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/waydroid.py +0 -0
  117. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/io/yaml.py +0 -0
  118. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/locale_handler.py +0 -0
  119. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/log.py +0 -0
  120. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/max_value_helper.py +0 -0
  121. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/server/__init__.py +0 -0
  122. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/server/client_info.py +0 -0
  123. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/server/event_data.py +0 -0
  124. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/server/headers.py +0 -0
  125. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/server/managed_item.py +0 -0
  126. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/server/request.py +0 -0
  127. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/server/server_handler.py +0 -0
  128. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/core/theme_handler.py +0 -0
  129. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/core/config.properties +0 -0
  130. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/core/files.properties +0 -0
  131. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/core/input.properties +0 -0
  132. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/core/locale.properties +0 -0
  133. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/core/theme.properties +0 -0
  134. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/core/updater.properties +0 -0
  135. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/bannable_items.properties +0 -0
  136. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/cats.properties +0 -0
  137. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/enemy.properties +0 -0
  138. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/fixes.properties +0 -0
  139. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/gamototo.properties +0 -0
  140. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/gatya.properties +0 -0
  141. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/gold_pass.properties +0 -0
  142. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/medals.properties +0 -0
  143. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/missions.properties +0 -0
  144. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/playtime.properties +0 -0
  145. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/scheme_items.properties +0 -0
  146. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/special_skills.properties +0 -0
  147. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/talent_orbs.properties +0 -0
  148. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/en/edits/user_rank.properties +0 -0
  149. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/core/config.properties +0 -0
  150. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/core/files.properties +0 -0
  151. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/core/input.properties +0 -0
  152. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/core/locale.properties +0 -0
  153. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/core/save.properties +0 -0
  154. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/core/server.properties +0 -0
  155. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/core/theme.properties +0 -0
  156. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/core/updater.properties +0 -0
  157. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/bannable_items.properties +0 -0
  158. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/cats.properties +0 -0
  159. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/enemy.properties +0 -0
  160. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/fixes.properties +0 -0
  161. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/gamototo.properties +0 -0
  162. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/gatya.properties +0 -0
  163. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/gold_pass.properties +0 -0
  164. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/medals.properties +0 -0
  165. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/missions.properties +0 -0
  166. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/playtime.properties +0 -0
  167. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/scheme_items.properties +0 -0
  168. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/special_skills.properties +0 -0
  169. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/talent_orbs.properties +0 -0
  170. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/treasures.properties +0 -0
  171. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/edits/user_rank.properties +0 -0
  172. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/locales/vi/metadata.json +0 -0
  173. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/max_values.json +0 -0
  174. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/themes/default.json +0 -0
  175. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/files/themes/discord.json +0 -0
  176. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe/py.typed +0 -0
  177. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe.egg-info/dependency_links.txt +0 -0
  178. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe.egg-info/entry_points.txt +0 -0
  179. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe.egg-info/requires.txt +0 -0
  180. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/src/bcsfe.egg-info/top_level.txt +0 -0
  181. {bcsfe-3.1.0 → bcsfe-3.2.0b2}/tests/test_parse.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bcsfe
3
- Version: 3.1.0
3
+ Version: 3.2.0b2
4
4
  Summary: A save file editor for The Battle Cats
5
5
  Author: fieryhenry
6
6
  License-Expression: GPL-3.0-or-later
@@ -368,10 +368,12 @@ Alternatively you can use pip directly, although it won't auto-update with the l
368
368
  git commits.
369
369
 
370
370
  ```sh
371
- py -m pip install git+https://codeberg.org/fieryhenry/BCSFE-Python.git
371
+ py -m pip install -U git+https://codeberg.org/fieryhenry/BCSFE-Python.git
372
372
  py -m bcsfe
373
373
  ```
374
374
 
375
+ Again, you might need change `py` for `python` or `python3`
376
+
375
377
  If you want to use the editor again all you need to do is run the `py -m bcsfe` command
376
378
 
377
379
  ## Documentation
@@ -339,10 +339,12 @@ Alternatively you can use pip directly, although it won't auto-update with the l
339
339
  git commits.
340
340
 
341
341
  ```sh
342
- py -m pip install git+https://codeberg.org/fieryhenry/BCSFE-Python.git
342
+ py -m pip install -U git+https://codeberg.org/fieryhenry/BCSFE-Python.git
343
343
  py -m bcsfe
344
344
  ```
345
345
 
346
+ Again, you might need change `py` for `python` or `python3`
347
+
346
348
  If you want to use the editor again all you need to do is run the `py -m bcsfe` command
347
349
 
348
350
  ## Documentation
@@ -1,4 +1,4 @@
1
- __version__ = "3.1.0"
1
+ __version__ = "3.2.0b2"
2
2
 
3
3
  from bcsfe import core, cli
4
4
 
@@ -52,7 +52,9 @@ def main():
52
52
  cli.main.Main.leave()
53
53
  except Exception as e:
54
54
  tb = traceback.format_exc()
55
- cli.color.ColoredText.localize("error", error=e, traceback=tb)
55
+ cli.color.ColoredText.localize(
56
+ "error", error=e, version=bcsfe.__version__, traceback=tb
57
+ )
56
58
  try:
57
59
  cli.main.Main.exit_editor()
58
60
  except Exception:
@@ -113,13 +113,9 @@ class ColoredText:
113
113
  print(colored.stylize(text, fg), end="") # type: ignore
114
114
 
115
115
  @staticmethod
116
- def localize(
117
- string: str, escape: bool = True, **kwargs: Any
118
- ) -> ColoredText:
116
+ def localize(string: str, escape: bool = True, **kwargs: Any) -> ColoredText:
119
117
  return ColoredText(
120
- core.core_data.local_manager.get_key(
121
- string, escape=escape, **kwargs
122
- )
118
+ core.core_data.local_manager.get_key(string, escape=escape, **kwargs)
123
119
  )
124
120
 
125
121
  def parse(self, txt: str) -> list[tuple[str, str]]:
@@ -134,11 +130,7 @@ class ColoredText:
134
130
  special_chars = core.LocalManager.get_special_chars()
135
131
  while i < len(txt):
136
132
  char = txt[i]
137
- if (
138
- char == "\\"
139
- and i + 1 < len(txt)
140
- and txt[i + 1] in special_chars
141
- ):
133
+ if char == "\\" and i + 1 < len(txt) and txt[i + 1] in special_chars:
142
134
  i += 1
143
135
  char = txt[i]
144
136
  text += char
@@ -183,7 +175,5 @@ class ColoredInput:
183
175
  return input()
184
176
 
185
177
  def localize(self, string: str, escape: bool = True, **kwargs: Any) -> str:
186
- text = core.core_data.local_manager.get_key(
187
- string, escape=escape, **kwargs
188
- )
178
+ text = core.core_data.local_manager.get_key(string, escape=escape, **kwargs)
189
179
  return self.get(text)
@@ -327,7 +327,7 @@ class ChoiceInput:
327
327
  dialog = core.core_data.local_manager.get_key(key).format(
328
328
  min=self.get_min_value(), max=self.get_max_value()
329
329
  )
330
- usr_input = color.ColoredInput().get(dialog).split(" ")
330
+ usr_input = color.ColoredInput().get(dialog).strip().split(" ")
331
331
  int_vals: list[int] = []
332
332
  for inp in usr_input:
333
333
  try:
@@ -689,7 +689,11 @@ class YesNoInput:
689
689
 
690
690
  if usr_input == core.core_data.local_manager.get_key("quit_key"):
691
691
  return None
692
- return usr_input == core.core_data.local_manager.get_key("yes_key")
692
+ return (
693
+ usr_input == core.core_data.local_manager.get_key("yes_key")
694
+ or usr_input.lower().strip()
695
+ == core.core_data.local_manager.get_key("yes").lower().strip()
696
+ )
693
697
 
694
698
 
695
699
  class DialogBuilder:
@@ -12,6 +12,12 @@ class BasicItems:
12
12
  return core.core_data.local_manager.get_key(key)
13
13
  return name.strip()
14
14
 
15
+ @staticmethod
16
+ def reset_golden_cat_cpus(save_file: core.SaveFile):
17
+ save_file.golden_cpu_count = 0
18
+
19
+ color.ColoredText.localize("reset_golden_cat_cpus_success")
20
+
15
21
  @staticmethod
16
22
  def edit_catfood(save_file: core.SaveFile):
17
23
  should_exit = not dialog_creator.YesNoInput().get_input_once("catfood_warning")
@@ -48,7 +48,6 @@ class CatEditor:
48
48
  if len(current_cats) > 50:
49
49
  color.ColoredText.localize("total_selected_cats", total=len(current_cats))
50
50
  else:
51
- self.save_file.cats.bulk_download_names(self.save_file, current_cats)
52
51
  for cat in current_cats:
53
52
  names = cat.get_names_cls(self.save_file)
54
53
  if not names:
@@ -20,7 +20,8 @@ class EventTickets:
20
20
  )
21
21
 
22
22
  cli.color.ColoredText.localize("downloading_gatya_data")
23
- gatya_event_data = core.ServerHandler(self.save_file).download_gatya_data()
23
+ temp_save_file = core.SaveFile(cc=save_file.cc, gv=save_file.game_version)
24
+ gatya_event_data = core.ServerHandler(temp_save_file).download_gatya_data()
24
25
 
25
26
  if gatya_event_data is None:
26
27
  cli.color.ColoredText.localize("download_gatya_data_fail")
@@ -92,8 +92,12 @@ def edit_chapters(
92
92
  chapters: ChaptersType,
93
93
  letter_code: str,
94
94
  type: int | None = None,
95
+ no_r_prefix: bool = False,
96
+ base_index: int | None = None,
95
97
  ) -> dict[int, bool] | None:
96
- map_names = core.MapNames(save_file, letter_code)
98
+ map_names = core.MapNames(
99
+ save_file, letter_code, no_r_prefix=no_r_prefix, base_index=base_index
100
+ )
97
101
  names = map_names.map_names
98
102
 
99
103
  choice = dialog_creator.ChoiceInput.from_reduced(
@@ -36,9 +36,11 @@ class FeatureHandler:
36
36
  "waydroid_push_rerun": save_management.SaveManagement.waydroid_push_rerun,
37
37
  "adb_push": save_management.SaveManagement.adb_push,
38
38
  "adb_push_rerun": save_management.SaveManagement.adb_push_rerun,
39
+ "root_push": save_management.SaveManagement.root_push,
40
+ "root_push_rerun": save_management.SaveManagement.root_push_rerun,
39
41
  "export_save": save_management.SaveManagement.export_save,
40
42
  "load_save": save_management.SaveManagement.load_save,
41
- "init_save": save_management.SaveManagement.init_save,
43
+ # "init_save": save_management.SaveManagement.init_save,
42
44
  "convert_region": save_management.SaveManagement.convert_save_cc,
43
45
  "convert_version": save_management.SaveManagement.convert_save_gv,
44
46
  },
@@ -63,6 +65,7 @@ class FeatureHandler:
63
65
  "100_million_tickets": edits.basic_items.BasicItems.edit_100_million_ticket,
64
66
  "event_tickets": edits.event_tickets.EventTickets.edit,
65
67
  "treasure_chests": edits.basic_items.BasicItems.edit_treasure_chests,
68
+ "reset_golden_cat_cpus": edits.basic_items.BasicItems.reset_golden_cat_cpus,
66
69
  },
67
70
  "cats_special_skills": cat_features,
68
71
  "levels": {
@@ -70,7 +73,8 @@ class FeatureHandler:
70
73
  "clear_story": core.game.map.story.StoryChapters.clear_story,
71
74
  "challenge_score": core.game.map.challenge.edit_challenge_score,
72
75
  "dojo_score": core.game.map.dojo.edit_dojo_score,
73
- "enigma": core.game.map.enigma.edit_enigma,
76
+ "add_enigma_stages": core.game.map.enigma.edit_enigma,
77
+ "clear_enigma_stages": core.game.map.gauntlets.GauntletChapters.edit_enigma_stages,
74
78
  "unlock_aku_realm": edits.aku_realm.unlock_aku_realm,
75
79
  "story_treasures": core.game.map.story.StoryChapters.edit_treasures,
76
80
  "outbreaks": core.game.map.outbreaks.Outbreaks.edit_outbreaks,
@@ -88,6 +92,7 @@ class FeatureHandler:
88
92
  "legend_quest": core.game.map.legend_quest.LegendQuestChapters.edit_legend_quest,
89
93
  "towers": core.game.map.tower.TowerChapters.edit_towers,
90
94
  "zero_legends": core.game.map.zero_legends.ZeroLegendsChapters.edit_zero_legends,
95
+ "dojo_catclaw_championships": core.game.map.zero_legends.ZeroLegendsChapters.edit_catclaw_championships,
91
96
  },
92
97
  "gamototo": {
93
98
  "engineers": edits.basic_items.BasicItems.edit_engineers,
@@ -117,6 +122,7 @@ class FeatureHandler:
117
122
  },
118
123
  "other": {
119
124
  "unlocked_slots": edits.basic_items.BasicItems.edit_unlocked_slots,
125
+ "reset_gambling_events": core.GamblingEvent.reset_events,
120
126
  "restart_pack": edits.basic_items.BasicItems.set_restart_pack,
121
127
  "special_skills": edits.basic_items.BasicItems.edit_special_skills,
122
128
  "playtime": core.game.catbase.playtime.edit,
@@ -229,6 +235,8 @@ class FeatureHandler:
229
235
 
230
236
  else:
231
237
  feats = self.search_features(usr_input)
238
+ if not feats:
239
+ color.ColoredText.localize("no_feature_with_name", name=usr_input)
232
240
  kv_map = list(feats.items())
233
241
  kv_map.sort(key=lambda v: v[1], reverse=True)
234
242
  selected_features = [v[0] for v in kv_map]
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
  from bcsfe import core
3
+ import bcsfe
3
4
  from bcsfe.core import io
4
5
  from bcsfe.cli import main, color, dialog_creator, server_cli
5
6
  from bcsfe.core.country_code import CountryCode
@@ -196,6 +197,43 @@ class SaveManagement:
196
197
 
197
198
  return adb_handler
198
199
 
200
+ @staticmethod
201
+ def root_push(save_file: core.SaveFile) -> core.RootHandler | None:
202
+ """Push the save file to the device.
203
+
204
+ Args:
205
+ save_file (core.SaveFile): The save file to push.
206
+
207
+ Returns:
208
+ core.AdbHandler: The AdbHandler instance.
209
+ """
210
+ SaveManagement.save_save(save_file)
211
+ root_handler = core.RootHandler()
212
+ if not root_handler.is_android():
213
+ color.ColoredText.localize("root_push_not_android_error")
214
+ return None
215
+ if not root_handler.is_rooted():
216
+ color.ColoredText.localize("not_rooted_error")
217
+ return None
218
+ if save_file.used_storage and save_file.package_name is not None:
219
+ root_handler.set_package_name(save_file.package_name)
220
+ else:
221
+ packages = root_handler.get_battlecats_packages()
222
+ package_name = SaveManagement.select_package_name(packages)
223
+ if package_name is None:
224
+ color.ColoredText.localize("no_package_name_error")
225
+ return root_handler
226
+ root_handler.set_package_name(package_name)
227
+ if save_file.save_path is None:
228
+ return root_handler
229
+ result = root_handler.load_battlecats_save(save_file.save_path)
230
+ if result.success:
231
+ color.ColoredText.localize("root_push_success")
232
+ else:
233
+ color.ColoredText.localize("root_push_fail", error=result.result)
234
+
235
+ return root_handler
236
+
199
237
  @staticmethod
200
238
  def adb_push_rerun(save_file: core.SaveFile):
201
239
  """Push the save file to the device and rerun the game.
@@ -214,6 +252,24 @@ class SaveManagement:
214
252
  else:
215
253
  color.ColoredText.localize("adb_rerun_fail", error=result.result)
216
254
 
255
+ @staticmethod
256
+ def root_push_rerun(save_file: core.SaveFile):
257
+ """Push the save file to the device and rerun the game.
258
+
259
+ Args:
260
+ save_file (core.SaveFile): The save file to push.
261
+ """
262
+ root_handler = SaveManagement.root_push(save_file)
263
+ if not root_handler:
264
+ return
265
+ if root_handler.package_name is None:
266
+ return
267
+ result = root_handler.rerun_game()
268
+ if result.success:
269
+ color.ColoredText.localize("root_rerun_success")
270
+ else:
271
+ color.ColoredText.localize("root_rerun_fail", error=result.result)
272
+
217
273
  @staticmethod
218
274
  def export_save(save_file: core.SaveFile):
219
275
  """Export the save file to a json file.
@@ -302,7 +358,7 @@ class SaveManagement:
302
358
  "load_from_documents",
303
359
  "adb_pull_save",
304
360
  "load_save_data_json",
305
- "create_new_save",
361
+ # "create_new_save",
306
362
  ]
307
363
  if starting_options:
308
364
  options.append("edit_config")
@@ -407,32 +463,32 @@ class SaveManagement:
407
463
  save_path, cc = data
408
464
  else:
409
465
  save_path = None
410
- elif choice == 5:
411
- color.ColoredText.localize("create_new_save_warning")
412
- cc = core.CountryCode.select()
413
- if cc is None:
414
- return None, False
415
- try:
416
- gv = core.GameVersion.from_string(
417
- color.ColoredInput().localize(
418
- "game_version_dialog",
419
- )
420
- )
421
- except ValueError:
422
- color.ColoredText.localize("invalid_game_version")
423
- return None, False
424
- save = core.SaveFile(cc=cc, gv=gv, load=False)
425
- save_path = main.Main.save_save_dialog(save)
426
- if save_path is None:
427
- return None, False
428
- save.to_file(save_path)
429
- color.ColoredText.localize("create_new_save_success")
430
-
431
- elif choice == 6 and starting_options:
466
+ # elif choice == 5:
467
+ # color.ColoredText.localize("create_new_save_warning")
468
+ # cc = core.CountryCode.select()
469
+ # if cc is None:
470
+ # return None, False
471
+ # try:
472
+ # gv = core.GameVersion.from_string(
473
+ # color.ColoredInput().localize(
474
+ # "game_version_dialog",
475
+ # )
476
+ # )
477
+ # except ValueError:
478
+ # color.ColoredText.localize("invalid_game_version")
479
+ # return None, False
480
+ # save = core.SaveFile(cc=cc, gv=gv, load=False)
481
+ # save_path = main.Main.save_save_dialog(save)
482
+ # if save_path is None:
483
+ # return None, False
484
+ # save.to_file(save_path)
485
+ # color.ColoredText.localize("create_new_save_success")
486
+
487
+ elif choice == 5 and starting_options:
432
488
  core.core_data.config.edit_config()
433
- elif choice == 7 and starting_options:
489
+ elif choice == 6 and starting_options:
434
490
  core.update_external_content()
435
- elif choice == 8 and starting_options:
491
+ elif choice == 7 and starting_options:
436
492
  main.Main.exit_editor(check_temp=False)
437
493
 
438
494
  if save_path is None or not save_path.exists():
@@ -465,12 +521,16 @@ class SaveManagement:
465
521
  save_file = core.SaveFile(save_path.read(), cc)
466
522
  except Exception:
467
523
  tb = core.core_data.logger.get_traceback()
468
- color.ColoredText.localize("parse_save_error", error=tb)
524
+ color.ColoredText.localize(
525
+ "parse_save_error", error=tb, version=bcsfe.__version__
526
+ )
469
527
  return None
470
528
 
471
529
  except Exception:
472
530
  tb = core.core_data.logger.get_traceback()
473
- color.ColoredText.localize("parse_save_error", error=tb)
531
+ color.ColoredText.localize(
532
+ "parse_save_error", error=tb, version=bcsfe.__version__
533
+ )
474
534
  return None
475
535
 
476
536
  save_file.save_path = save_path
@@ -503,6 +563,7 @@ class SaveManagement:
503
563
  if new_save_file is None:
504
564
  return stop
505
565
  save_file.load_save_file(new_save_file)
566
+ core.core_data.init_data()
506
567
  color.ColoredText.localize("load_save_success")
507
568
  return False
508
569
 
@@ -515,6 +576,7 @@ class SaveManagement:
515
576
  return
516
577
  save_file.set_cc(cc)
517
578
  core.ServerHandler(save_file).create_new_account()
579
+ core.core_data.init_data()
518
580
  color.ColoredText.localize("country_code_set", cc=cc)
519
581
 
520
582
  @staticmethod
@@ -530,4 +592,5 @@ class SaveManagement:
530
592
  color.ColoredText.localize("invalid_game_version")
531
593
  return
532
594
  save_file.set_gv(gv)
595
+ core.core_data.init_data()
533
596
  color.ColoredText.localize("game_version_set", version=gv.to_string())
@@ -4,7 +4,7 @@ from typing import Any
4
4
  from requests.exceptions import ConnectionError
5
5
  from requests import Response
6
6
  from json.decoder import JSONDecodeError
7
- from bcsfe.cli import color
7
+ from bcsfe.cli import color, dialog_creator
8
8
 
9
9
  from bcsfe.core import (
10
10
  country_code,
@@ -30,7 +30,14 @@ from bcsfe.core.game.battle.enemy import (
30
30
  EnemyDictionary,
31
31
  )
32
32
  from bcsfe.core.game.catbase.beacon_base import BeaconEventListScene
33
- from bcsfe.core.game.catbase.cat import Cat, Cats, UnitBuy, TalentData
33
+ from bcsfe.core.game.catbase.cat import (
34
+ Cat,
35
+ Cats,
36
+ UnitBuy,
37
+ TalentData,
38
+ NyankoPictureBook,
39
+ )
40
+ from bcsfe.core.game.catbase.gambling import GamblingEvent
34
41
  from bcsfe.core.game.catbase.gatya import (
35
42
  Gatya,
36
43
  GatyaInfos,
@@ -307,6 +314,14 @@ def update_external_content(_: Any = None):
307
314
  ExternalLocaleManager.update_all_external_locales()
308
315
  core_data.init_data()
309
316
 
317
+ clear_game_data = dialog_creator.YesNoInput().get_input_once("clear_game_data_q")
318
+ if clear_game_data is None:
319
+ return
320
+
321
+ if clear_game_data:
322
+ GameDataGetter.delete_old_versions(0)
323
+ color.ColoredText.localize("cleared_game_data")
324
+
310
325
 
311
326
  def print_no_internet():
312
327
  color.ColoredText.localize("no_internet")
@@ -368,4 +383,7 @@ __all__ = [
368
383
  "GatyaDataOptionSet",
369
384
  "GatyaDataOption",
370
385
  "MaxValueType",
386
+ "GamblingEvent",
387
+ "UnitBuy",
388
+ "NyankoPictureBook",
371
389
  ]
@@ -21,6 +21,7 @@ from bcsfe.core.game.catbase import (
21
21
  powerup,
22
22
  drop_chara,
23
23
  playtime,
24
+ gambling,
24
25
  )
25
26
 
26
27
  __all__ = [
@@ -46,4 +47,5 @@ __all__ = [
46
47
  "powerup",
47
48
  "drop_chara",
48
49
  "playtime",
50
+ "gambling",
49
51
  ]
@@ -227,7 +227,7 @@ class TalentData:
227
227
  talent_data_cat = self.get_cat_skill(cat.id)
228
228
  if talent_data_cat is None or cat.talents is None:
229
229
  return None
230
- save_talent_data = cat.talents
230
+ # save_talent_data = cat.talents
231
231
  talent_names: list[str] = []
232
232
  max_levels: list[int] = []
233
233
  current_levels: list[int] = []
@@ -836,7 +836,6 @@ class Cats:
836
836
  self.unit_limit: UnitLimit | None = None
837
837
  self.nyanko_picture_book: NyankoPictureBook | None = None
838
838
  self.talent_data: TalentData | None = None
839
- self.bulk_downloaded = False
840
839
 
841
840
  def get_all_cats(self) -> list[Cat]:
842
841
  return self.cats
@@ -882,7 +881,7 @@ class Cats:
882
881
 
883
882
  def get_non_gacha_cats(self, save_file: core.SaveFile) -> list[Cat]:
884
883
  unitbuy = self.read_unitbuy(save_file)
885
- cats = []
884
+ cats: list[Cat] = []
886
885
  for cat in self.cats:
887
886
  unit_buy_data = unitbuy.get_unit_buy(cat.id)
888
887
  if unit_buy_data is None:
@@ -922,7 +921,6 @@ class Cats:
922
921
  save_file: core.SaveFile,
923
922
  search_name: str,
924
923
  ) -> list[Cat]:
925
- self.bulk_download_names(save_file)
926
924
  cats: list[Cat] = []
927
925
  for cat in self.cats:
928
926
  names = cat.get_names_cls(save_file)
@@ -934,32 +932,6 @@ class Cats:
934
932
  break
935
933
  return cats
936
934
 
937
- def bulk_download_names(
938
- self, save_file: core.SaveFile, current_cats: list[core.Cat] | None = None
939
- ):
940
- if self.bulk_downloaded and current_cats is None:
941
- return
942
- file_names: list[str] = []
943
- gdg = core.core_data.get_game_data_getter(save_file)
944
- if current_cats is None:
945
- cats = self.cats
946
- else:
947
- cats = current_cats
948
- for cat in cats:
949
- if cat.names is None:
950
- file_name = f"Unit_Explanation{cat.id + 1}_{core.core_data.get_lang(save_file)}.csv"
951
- if gdg.is_downloaded("resLocal", file_name):
952
- continue
953
- file_names.append(file_name)
954
-
955
- if len(file_names) > 50:
956
- gdg.save_all_cat_names_fast()
957
-
958
- core.core_data.get_game_data_getter(save_file).download_all(
959
- "resLocal", file_names
960
- )
961
- self.bulk_downloaded = current_cats is None
962
-
963
935
  def get_cats_obtainable(self, save_file: core.SaveFile) -> list[Cat] | None:
964
936
  nyanko_picture_book = self.read_nyanko_picture_book(save_file)
965
937
  obtainable_cats = nyanko_picture_book.get_obtainable_cats()
@@ -0,0 +1,111 @@
1
+ from __future__ import annotations
2
+ from bcsfe import core
3
+ from typing import Any
4
+
5
+ from bcsfe.cli import color
6
+
7
+
8
+ class GamblingEvent:
9
+ def __init__(
10
+ self,
11
+ completed: dict[int, bool],
12
+ values: dict[int, dict[int, int]],
13
+ start_times: dict[int, int | float],
14
+ ):
15
+ self.completed = completed
16
+ self.values = values
17
+ self.start_times = start_times
18
+
19
+ @staticmethod
20
+ def init() -> GamblingEvent:
21
+ return GamblingEvent({}, {}, {})
22
+
23
+ @staticmethod
24
+ def read(data: core.Data, game_version: core.GameVersion) -> GamblingEvent:
25
+ total = data.read_short()
26
+ completed: dict[int, bool] = {}
27
+
28
+ for _ in range(total):
29
+ key = data.read_short()
30
+ completed[key] = data.read_bool()
31
+
32
+ total = data.read_short()
33
+ values: dict[int, dict[int, int]] = {}
34
+
35
+ for _ in range(total):
36
+ key = data.read_short()
37
+ if key not in values:
38
+ values[key] = {}
39
+
40
+ total2 = data.read_short()
41
+ for _ in range(total2):
42
+ key2 = data.read_short()
43
+
44
+ values[key][key2] = data.read_short()
45
+
46
+ total = data.read_short()
47
+ start_times: dict[int, int | float] = {}
48
+
49
+ for _ in range(total):
50
+ key = data.read_short()
51
+
52
+ if game_version < 90100:
53
+ value = data.read_double()
54
+ else:
55
+ value = data.read_int()
56
+
57
+ start_times[key] = value
58
+
59
+ return GamblingEvent(completed, values, start_times)
60
+
61
+ def write(self, data: core.Data, game_version: core.GameVersion):
62
+ data.write_short(len(self.completed))
63
+ data.write_short_bool_dict(self.completed, write_length=False)
64
+
65
+ data.write_short(len(self.values))
66
+
67
+ for key, value in self.values.items():
68
+ data.write_short(key)
69
+ data.write_short(len(value))
70
+
71
+ for key2, value2 in value.items():
72
+ data.write_short(key2)
73
+ data.write_short(value2)
74
+
75
+ data.write_short(len(self.start_times))
76
+ for key, value in self.start_times.items():
77
+ data.write_short(key)
78
+
79
+ # this is a bad conversion, since float is timestamp i assume and int as the date as YYYMMDD. FIXME
80
+ if game_version < 90100:
81
+ data.write_double(float(value))
82
+ else:
83
+ data.write_int(int(value))
84
+
85
+ def serialize(self) -> dict[str, Any]:
86
+ return {
87
+ "completed": self.completed,
88
+ "values": self.values,
89
+ "start_times": self.start_times,
90
+ }
91
+
92
+ @staticmethod
93
+ def deserialize(data: dict[str, Any]) -> GamblingEvent:
94
+ return GamblingEvent(
95
+ data.get("completed", {}),
96
+ data.get("values", {}),
97
+ data.get("start_times", {}),
98
+ )
99
+
100
+ def reset(self):
101
+ self.completed = {}
102
+ self.values = {}
103
+ # TODO: check start times
104
+ self.start_times = {}
105
+
106
+ @staticmethod
107
+ def reset_events(save_file: core.SaveFile):
108
+ save_file.wildcat_slots.reset()
109
+ color.ColoredText.localize("reset_wildcat_slots")
110
+ save_file.cat_scratcher.reset()
111
+ color.ColoredText.localize("reset_cat_scratcher")
@@ -195,6 +195,9 @@ class Enigma:
195
195
  if wipe is None:
196
196
  return
197
197
  if wipe:
198
+ for stage in self.stages:
199
+ id = stage.stage_id
200
+ save_file.event_stages.chapter_completion_count[id] = 0
198
201
  self.stages = []
199
202
 
200
203
  ids, _ = dialog_creator.ChoiceInput(
@@ -209,6 +212,8 @@ class Enigma:
209
212
 
210
213
  for enigma_id in ids:
211
214
  abs_id = enigma_id + base_level
215
+ save_file.event_stages.chapter_completion_count[abs_id] = 0
216
+ # TODO: level? they can go much higher than 3... not sure it really matters though
212
217
  stage = Stage(3, abs_id, 2, int(time.time()))
213
218
  self.stages.append(stage)
214
219
 
@@ -334,6 +334,10 @@ class GauntletChapters:
334
334
  gauntlets = save_file.behemoth_culling
335
335
  gauntlets.edit_chapters(save_file, "Q")
336
336
 
337
+ @staticmethod
338
+ def edit_enigma_stages(save_file: core.SaveFile):
339
+ save_file.enigma_clears.edit_chapters(save_file, "H")
340
+
337
341
  def edit_chapters(self, save_file: core.SaveFile, letter_code: str):
338
342
  edits.map.edit_chapters(save_file, self, letter_code)
339
343