bcsfe 3.2.0b3__tar.gz → 3.2.1__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.
- {bcsfe-3.2.0b3/src/bcsfe.egg-info → bcsfe-3.2.1}/PKG-INFO +10 -9
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/README.md +9 -8
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/__init__.py +1 -1
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/dialog_creator.py +5 -7
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/edits/basic_items.py +7 -1
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/edits/map.py +11 -1
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/feature_handler.py +1 -0
- bcsfe-3.2.1/src/bcsfe/core/game/battle/battle_items.py +297 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/path.py +7 -3
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/save.py +2 -36
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/server/game_data_getter.py +7 -5
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/items.properties +9 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/core/input.properties +3 -1
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/core/main.properties +0 -1
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/core/save.properties +8 -1
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/core/server.properties +4 -1
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/cats.properties +40 -28
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/map.properties +0 -41
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/treasures.properties +2 -2
- {bcsfe-3.2.0b3 → bcsfe-3.2.1/src/bcsfe.egg-info}/PKG-INFO +10 -9
- bcsfe-3.2.0b3/src/bcsfe/core/game/battle/battle_items.py +0 -127
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/LICENSE +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/MANIFEST.in +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/pyproject.toml +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/setup.cfg +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/setup.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/__main__.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/__init__.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/color.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/edits/__init__.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/edits/aku_realm.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/edits/cat_editor.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/edits/clear_tutorial.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/edits/enemy_editor.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/edits/event_tickets.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/edits/fixes.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/edits/max_all.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/edits/rare_ticket_trade.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/edits/storage.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/file_dialog.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/main.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/save_management.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/cli/server_cli.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/__init__.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/country_code.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/crypto.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/__init__.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/battle/__init__.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/battle/cleared_slots.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/battle/enemy.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/battle/slots.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/__init__.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/beacon_base.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/cat.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/drop_chara.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/gambling.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/gatya.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/gatya_item.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/item_pack.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/login_bonuses.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/matatabi.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/medals.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/mission.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/my_sale.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/nyanko_club.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/officer_pass.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/playtime.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/powerup.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/scheme_items.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/special_skill.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/stamp.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/talent_orbs.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/unlock_popups.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/upgrade.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/catbase/user_rank_rewards.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/gamoto/__init__.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/gamoto/base_materials.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/gamoto/cat_shrine.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/gamoto/catamins.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/gamoto/gamatoto.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/gamoto/ototo.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/localizable.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/__init__.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/aku.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/challenge.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/chapters.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/dojo.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/enigma.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/event.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/ex_stage.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/gauntlets.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/item_reward_stage.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/legend_quest.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/map_names.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/map_reset.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/outbreaks.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/story.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/timed_score.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/tower.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/uncanny.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game/map/zero_legends.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/game_version.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/__init__.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/adb_handler.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/bc_csv.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/command.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/config.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/data.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/git_handler.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/json_file.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/root_handler.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/thread_helper.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/waydroid.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/io/yaml.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/locale_handler.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/log.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/max_value_helper.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/server/__init__.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/server/client_info.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/server/event_data.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/server/headers.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/server/managed_item.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/server/request.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/server/server_handler.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/server/updater.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/core/theme_handler.py +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/core/config.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/core/files.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/core/input.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/core/locale.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/core/main.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/core/save.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/core/server.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/core/theme.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/core/updater.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/bannable_items.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/cats.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/enemy.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/fixes.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/gambling.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/gamototo.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/gatya.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/gold_pass.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/map.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/medals.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/missions.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/playtime.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/scheme_items.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/special_skills.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/talent_orbs.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/treasures.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/en/edits/user_rank.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/core/config.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/core/files.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/core/locale.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/core/theme.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/core/updater.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/bannable_items.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/enemy.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/fixes.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/gambling.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/gamototo.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/gatya.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/gold_pass.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/items.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/medals.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/missions.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/playtime.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/scheme_items.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/special_skills.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/talent_orbs.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/edits/user_rank.properties +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/locales/vi/metadata.json +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/max_values.json +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/themes/default.json +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/files/themes/discord.json +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe/py.typed +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe.egg-info/SOURCES.txt +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe.egg-info/dependency_links.txt +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe.egg-info/entry_points.txt +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe.egg-info/requires.txt +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/src/bcsfe.egg-info/top_level.txt +0 -0
- {bcsfe-3.2.0b3 → bcsfe-3.2.1}/tests/test_parse.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bcsfe
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.1
|
|
4
4
|
Summary: A save file editor for The Battle Cats
|
|
5
5
|
Author: fieryhenry
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
@@ -298,13 +298,16 @@ pip uninstall bcsfe
|
|
|
298
298
|
```
|
|
299
299
|
## Terms of Use
|
|
300
300
|
|
|
301
|
+
I don't like that I have to have Terms of use but these terms are designed to prevent scams and the
|
|
302
|
+
exploitation of users.
|
|
303
|
+
|
|
301
304
|
By using the editor you agree to the following:
|
|
302
305
|
|
|
303
306
|
If you are using the editor to run a paid service that profits off of the editor
|
|
304
307
|
(e.g a service to provide people with hacked accounts, or a paid discord bot to edit people's accounts,
|
|
305
308
|
etc) you must make it very clear that you are using this save editor.
|
|
306
309
|
|
|
307
|
-
This should be done by linking this
|
|
310
|
+
This should be done by linking this Codeberg page, and explicitly stating that the tool you are
|
|
308
311
|
using is available for free and that they don't need to use your service to hack their account.
|
|
309
312
|
|
|
310
313
|
This information needs to be visible and something the customer agrees to **before** any payment is made.
|
|
@@ -318,8 +321,6 @@ the editor under the hood as long as you abide by the [License](#license). Basic
|
|
|
318
321
|
distributing a program which uses the editor, you need to license your own program under the GPL
|
|
319
322
|
or a compatible license (basically make it open source / free software too).
|
|
320
323
|
|
|
321
|
-
These terms are designed to prevent scams and the exploitation of users.
|
|
322
|
-
|
|
323
324
|
Also if you **are** profiting from the editor, it would be greatly appreciated if you could
|
|
324
325
|
give back something and support me.
|
|
325
326
|
|
|
@@ -429,13 +430,13 @@ You'll need to collect the catfood in-game after each clear though
|
|
|
429
430
|
|
|
430
431
|
### Install from source
|
|
431
432
|
|
|
432
|
-
If you want the latest features then you can install the editor from the
|
|
433
|
+
If you want the latest features then you can install the editor from the git repo.
|
|
433
434
|
|
|
434
435
|
1. Download git:
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
436
|
+
- Windows: [Git](https://git-scm.com/downloads)
|
|
437
|
+
- Linux: (use package manager, e.g `sudo apt-get install git` or `sudo pacman -S git`)
|
|
438
|
+
- Android: Termux: `pkg install git`
|
|
439
|
+
- iOS: a-Shell should already include it
|
|
439
440
|
|
|
440
441
|
2. Run the following commands: (You may have to replace `py` with `python` or `python3`)
|
|
441
442
|
|
|
@@ -269,13 +269,16 @@ pip uninstall bcsfe
|
|
|
269
269
|
```
|
|
270
270
|
## Terms of Use
|
|
271
271
|
|
|
272
|
+
I don't like that I have to have Terms of use but these terms are designed to prevent scams and the
|
|
273
|
+
exploitation of users.
|
|
274
|
+
|
|
272
275
|
By using the editor you agree to the following:
|
|
273
276
|
|
|
274
277
|
If you are using the editor to run a paid service that profits off of the editor
|
|
275
278
|
(e.g a service to provide people with hacked accounts, or a paid discord bot to edit people's accounts,
|
|
276
279
|
etc) you must make it very clear that you are using this save editor.
|
|
277
280
|
|
|
278
|
-
This should be done by linking this
|
|
281
|
+
This should be done by linking this Codeberg page, and explicitly stating that the tool you are
|
|
279
282
|
using is available for free and that they don't need to use your service to hack their account.
|
|
280
283
|
|
|
281
284
|
This information needs to be visible and something the customer agrees to **before** any payment is made.
|
|
@@ -289,8 +292,6 @@ the editor under the hood as long as you abide by the [License](#license). Basic
|
|
|
289
292
|
distributing a program which uses the editor, you need to license your own program under the GPL
|
|
290
293
|
or a compatible license (basically make it open source / free software too).
|
|
291
294
|
|
|
292
|
-
These terms are designed to prevent scams and the exploitation of users.
|
|
293
|
-
|
|
294
295
|
Also if you **are** profiting from the editor, it would be greatly appreciated if you could
|
|
295
296
|
give back something and support me.
|
|
296
297
|
|
|
@@ -400,13 +401,13 @@ You'll need to collect the catfood in-game after each clear though
|
|
|
400
401
|
|
|
401
402
|
### Install from source
|
|
402
403
|
|
|
403
|
-
If you want the latest features then you can install the editor from the
|
|
404
|
+
If you want the latest features then you can install the editor from the git repo.
|
|
404
405
|
|
|
405
406
|
1. Download git:
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
407
|
+
- Windows: [Git](https://git-scm.com/downloads)
|
|
408
|
+
- Linux: (use package manager, e.g `sudo apt-get install git` or `sudo pacman -S git`)
|
|
409
|
+
- Android: Termux: `pkg install git`
|
|
410
|
+
- iOS: a-Shell should already include it
|
|
410
411
|
|
|
411
412
|
2. Run the following commands: (You may have to replace `py` with `python` or `python3`)
|
|
412
413
|
|
|
@@ -150,7 +150,7 @@ class ListOutput:
|
|
|
150
150
|
def __init__(
|
|
151
151
|
self,
|
|
152
152
|
strings: list[str],
|
|
153
|
-
ints: list[int],
|
|
153
|
+
ints: list[int] | list[str],
|
|
154
154
|
dialog: str | None = None,
|
|
155
155
|
perameters: dict[str, Any] | None = None,
|
|
156
156
|
start_index: int = 1,
|
|
@@ -210,7 +210,7 @@ class ChoiceInput:
|
|
|
210
210
|
self,
|
|
211
211
|
items: list[str],
|
|
212
212
|
strings: list[str],
|
|
213
|
-
ints: list[int],
|
|
213
|
+
ints: list[int] | list[str],
|
|
214
214
|
perameters: dict[str, int | str],
|
|
215
215
|
dialog: str,
|
|
216
216
|
single_choice: bool = False,
|
|
@@ -233,7 +233,7 @@ class ChoiceInput:
|
|
|
233
233
|
@staticmethod
|
|
234
234
|
def from_reduced(
|
|
235
235
|
items: list[str],
|
|
236
|
-
ints: list[int] | None = None,
|
|
236
|
+
ints: list[int] | list[str] | None = None,
|
|
237
237
|
perameters: dict[str, int | str] | None = None,
|
|
238
238
|
dialog: str | None = None,
|
|
239
239
|
single_choice: bool = False,
|
|
@@ -482,7 +482,7 @@ class MultiEditor:
|
|
|
482
482
|
choices, all_at_once = ChoiceInput(
|
|
483
483
|
self.items,
|
|
484
484
|
self.strings,
|
|
485
|
-
self.ints or [],
|
|
485
|
+
self.ints or [], # type: ignore
|
|
486
486
|
self.perameters,
|
|
487
487
|
"select_edit",
|
|
488
488
|
).get()
|
|
@@ -588,9 +588,7 @@ class SingleEditor:
|
|
|
588
588
|
self.signed = signed
|
|
589
589
|
|
|
590
590
|
def edit(self, escape_text: bool = True) -> int:
|
|
591
|
-
max_value = self.max_value
|
|
592
|
-
if max_value is None:
|
|
593
|
-
max_value = IntInput.get_max_value(max_value, self.signed)
|
|
591
|
+
max_value = IntInput.get_max_value(self.max_value, self.signed)
|
|
594
592
|
if self.max_value is None:
|
|
595
593
|
dialog = "input_non_max"
|
|
596
594
|
elif self.min_value != 0:
|
|
@@ -165,6 +165,8 @@ class BasicItems:
|
|
|
165
165
|
core.core_data.max_value_manager.get("platinum_tickets")
|
|
166
166
|
- platinum_ticket_amount
|
|
167
167
|
) * 10 + 9
|
|
168
|
+
|
|
169
|
+
max_value = max(0, max_value)
|
|
168
170
|
save_file.platinum_shards = dialog_creator.SingleEditor(
|
|
169
171
|
BasicItems.get_name(name, "platinum_shards"),
|
|
170
172
|
save_file.platinum_shards,
|
|
@@ -193,6 +195,10 @@ class BasicItems:
|
|
|
193
195
|
def edit_battle_items(save_file: core.SaveFile):
|
|
194
196
|
save_file.battle_items.edit(save_file)
|
|
195
197
|
|
|
198
|
+
@staticmethod
|
|
199
|
+
def edit_battle_items_endless(save_file: core.SaveFile):
|
|
200
|
+
save_file.battle_items.edit_endless_items(save_file)
|
|
201
|
+
|
|
196
202
|
@staticmethod
|
|
197
203
|
def edit_catamins(save_file: core.SaveFile):
|
|
198
204
|
names_o = core.core_data.get_gatya_item_names(save_file)
|
|
@@ -249,7 +255,7 @@ class BasicItems:
|
|
|
249
255
|
if items is None:
|
|
250
256
|
return
|
|
251
257
|
names: list[str] = []
|
|
252
|
-
for item in items:
|
|
258
|
+
for item in items[: len(save_file.treasure_chests)]:
|
|
253
259
|
name = names_o.get_name(item.id)
|
|
254
260
|
if name is None:
|
|
255
261
|
name = core.core_data.local_manager.get_key(
|
|
@@ -12,6 +12,12 @@ ChaptersType = Union[
|
|
|
12
12
|
]
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
def get_total_maps(chapters: ChaptersType) -> int:
|
|
16
|
+
if isinstance(chapters, core.EventChapters):
|
|
17
|
+
return chapters.get_lengths()[1]
|
|
18
|
+
return len(chapters.chapters)
|
|
19
|
+
|
|
20
|
+
|
|
15
21
|
def unclear_stage(
|
|
16
22
|
chapters: ChaptersType,
|
|
17
23
|
map: int,
|
|
@@ -98,7 +104,11 @@ def edit_chapters(
|
|
|
98
104
|
map_names = core.MapNames(
|
|
99
105
|
save_file, letter_code, no_r_prefix=no_r_prefix, base_index=base_index
|
|
100
106
|
)
|
|
101
|
-
names =
|
|
107
|
+
names: dict[int, str | None] = {}
|
|
108
|
+
for id, name in map_names.map_names.items():
|
|
109
|
+
if id >= get_total_maps(chapters):
|
|
110
|
+
continue
|
|
111
|
+
names[id] = name
|
|
102
112
|
|
|
103
113
|
choice = dialog_creator.ChoiceInput.from_reduced(
|
|
104
114
|
["clear_stages", "unclear_stages"],
|
|
@@ -58,6 +58,7 @@ class FeatureHandler:
|
|
|
58
58
|
"np": edits.basic_items.BasicItems.edit_np,
|
|
59
59
|
"leadership": edits.basic_items.BasicItems.edit_leadership,
|
|
60
60
|
"battle_items": edits.basic_items.BasicItems.edit_battle_items,
|
|
61
|
+
"battle_items_endless": edits.basic_items.BasicItems.edit_battle_items_endless,
|
|
61
62
|
"catseyes": edits.basic_items.BasicItems.edit_catseyes,
|
|
62
63
|
"catfruit": edits.basic_items.BasicItems.edit_catfruit,
|
|
63
64
|
"talent_orbs": core.game.catbase.talent_orbs.SaveOrbs.edit_talent_orbs,
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
from math import inf
|
|
5
|
+
from typing import Any
|
|
6
|
+
from bcsfe import core
|
|
7
|
+
from bcsfe.cli import dialog_creator, color
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class EndlessItem:
|
|
11
|
+
def __init__(
|
|
12
|
+
self, active: bool, unknown: bool, amount: int, start: float, end: float
|
|
13
|
+
):
|
|
14
|
+
self.active = active
|
|
15
|
+
self.unknown = unknown
|
|
16
|
+
self.amount = amount
|
|
17
|
+
self.start = start
|
|
18
|
+
self.end = end
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def init() -> EndlessItem:
|
|
22
|
+
return EndlessItem(False, False, 0, 0, 0)
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def read(stream: core.Data) -> EndlessItem:
|
|
26
|
+
return EndlessItem(
|
|
27
|
+
stream.read_bool(),
|
|
28
|
+
stream.read_bool(),
|
|
29
|
+
stream.read_byte(),
|
|
30
|
+
stream.read_double(),
|
|
31
|
+
stream.read_double(),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def write(self, stream: core.Data):
|
|
35
|
+
stream.write_bool(self.active)
|
|
36
|
+
stream.write_bool(self.unknown)
|
|
37
|
+
stream.write_byte(self.amount)
|
|
38
|
+
stream.write_double(self.start)
|
|
39
|
+
stream.write_double(self.end)
|
|
40
|
+
|
|
41
|
+
def serialize(self) -> dict[str, Any]:
|
|
42
|
+
return {
|
|
43
|
+
"active": self.active,
|
|
44
|
+
"unknown": self.unknown,
|
|
45
|
+
"amount": self.amount,
|
|
46
|
+
"start": self.start,
|
|
47
|
+
"end": self.end,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def deserialize(data: dict[str, Any]) -> EndlessItem:
|
|
52
|
+
return EndlessItem(
|
|
53
|
+
data.get("active", False),
|
|
54
|
+
data.get("unknown", False),
|
|
55
|
+
data.get("amount", 0),
|
|
56
|
+
data.get("start", 0.0),
|
|
57
|
+
data.get("end", 0.0),
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def get_endless_duration(self) -> datetime.timedelta | None:
|
|
61
|
+
if not self.active:
|
|
62
|
+
return datetime.timedelta()
|
|
63
|
+
|
|
64
|
+
if self.end == inf:
|
|
65
|
+
return None
|
|
66
|
+
|
|
67
|
+
return datetime.timedelta(
|
|
68
|
+
seconds=self.end - self.start + (self.amount * 3 * 60 * 60)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
def get_endless_duration_formatted(self) -> str:
|
|
72
|
+
duration = self.get_endless_duration()
|
|
73
|
+
|
|
74
|
+
if duration is None:
|
|
75
|
+
return core.localize("infinity_duration")
|
|
76
|
+
|
|
77
|
+
days = duration.days
|
|
78
|
+
hours, rem = divmod(duration.seconds, 3600)
|
|
79
|
+
minutes, seconds = divmod(rem, 60)
|
|
80
|
+
|
|
81
|
+
return core.localize(
|
|
82
|
+
"duration", days=days, hours=hours, minutes=minutes, seconds=seconds
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
def set_duration_mins(self, mins: float, amount: int):
|
|
86
|
+
self.active = True
|
|
87
|
+
self.unknown = True
|
|
88
|
+
self.amount = amount
|
|
89
|
+
self.start = datetime.datetime.now(datetime.timezone.utc).timestamp()
|
|
90
|
+
self.end = self.start + mins * 60
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class BattleItem:
|
|
94
|
+
def __init__(self, amount: int):
|
|
95
|
+
self.amount = amount
|
|
96
|
+
self.locked = False
|
|
97
|
+
|
|
98
|
+
self.endless_item = EndlessItem.init()
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
def init() -> BattleItem:
|
|
102
|
+
return BattleItem(0)
|
|
103
|
+
|
|
104
|
+
@staticmethod
|
|
105
|
+
def read_amount(stream: core.Data) -> BattleItem:
|
|
106
|
+
return BattleItem(stream.read_int())
|
|
107
|
+
|
|
108
|
+
def write_amount(self, stream: core.Data):
|
|
109
|
+
stream.write_int(self.amount)
|
|
110
|
+
|
|
111
|
+
def read_locked(self, stream: core.Data):
|
|
112
|
+
self.locked = stream.read_bool()
|
|
113
|
+
|
|
114
|
+
def write_locked(self, stream: core.Data):
|
|
115
|
+
stream.write_bool(self.locked)
|
|
116
|
+
|
|
117
|
+
def read_endless_items(self, stream: core.Data):
|
|
118
|
+
self.endless_item = EndlessItem.read(stream)
|
|
119
|
+
|
|
120
|
+
def write_endless_items(self, stream: core.Data):
|
|
121
|
+
self.endless_item.write(stream)
|
|
122
|
+
|
|
123
|
+
def serialize(self) -> dict[str, Any]:
|
|
124
|
+
return {
|
|
125
|
+
"amount": self.amount,
|
|
126
|
+
"locked": self.locked,
|
|
127
|
+
"endless": self.endless_item.serialize(),
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@staticmethod
|
|
131
|
+
def deserialize(data: dict[str, Any]) -> BattleItem:
|
|
132
|
+
battle_item = BattleItem(data.get("amount", 0))
|
|
133
|
+
battle_item.locked = data.get("locked", False)
|
|
134
|
+
battle_item.endless_item = EndlessItem.deserialize(data.get("endless", {}))
|
|
135
|
+
return battle_item
|
|
136
|
+
|
|
137
|
+
def __repr__(self):
|
|
138
|
+
try:
|
|
139
|
+
return f"BattleItem({self.amount}, {self.locked}, {self.endless_item})"
|
|
140
|
+
except AttributeError:
|
|
141
|
+
return f"BattleItem({self.amount}, {self.endless_item})"
|
|
142
|
+
|
|
143
|
+
def __str__(self):
|
|
144
|
+
return self.__repr__()
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class BattleItems:
|
|
148
|
+
def __init__(self, items: list[BattleItem]):
|
|
149
|
+
self.items = items
|
|
150
|
+
self.lock_item = False
|
|
151
|
+
|
|
152
|
+
@staticmethod
|
|
153
|
+
def init() -> BattleItems:
|
|
154
|
+
return BattleItems([BattleItem.init() for _ in range(6)])
|
|
155
|
+
|
|
156
|
+
@staticmethod
|
|
157
|
+
def read_items(stream: core.Data) -> BattleItems:
|
|
158
|
+
total_items = 6
|
|
159
|
+
items = [BattleItem.read_amount(stream) for _ in range(total_items)]
|
|
160
|
+
return BattleItems(items)
|
|
161
|
+
|
|
162
|
+
def write_items(self, stream: core.Data):
|
|
163
|
+
for item in self.items:
|
|
164
|
+
item.write_amount(stream)
|
|
165
|
+
|
|
166
|
+
def read_locked_items(self, stream: core.Data):
|
|
167
|
+
self.lock_item = stream.read_bool()
|
|
168
|
+
for item in self.items:
|
|
169
|
+
item.read_locked(stream)
|
|
170
|
+
|
|
171
|
+
def write_locked_items(self, stream: core.Data):
|
|
172
|
+
stream.write_bool(self.lock_item)
|
|
173
|
+
for item in self.items:
|
|
174
|
+
item.write_locked(stream)
|
|
175
|
+
|
|
176
|
+
def read_endless_items(self, stream: core.Data):
|
|
177
|
+
for i in range(6):
|
|
178
|
+
if i >= len(self.items):
|
|
179
|
+
_ = EndlessItem.read(stream) # ensure we still read 6 items
|
|
180
|
+
else:
|
|
181
|
+
item = self.items[i]
|
|
182
|
+
item.read_endless_items(stream)
|
|
183
|
+
|
|
184
|
+
def write_endless_items(self, stream: core.Data):
|
|
185
|
+
for i in range(6):
|
|
186
|
+
if i >= len(self.items):
|
|
187
|
+
EndlessItem.init().write(stream) # ensure we still write 6 items
|
|
188
|
+
else:
|
|
189
|
+
item = self.items[i]
|
|
190
|
+
item.write_endless_items(stream)
|
|
191
|
+
|
|
192
|
+
def serialize(self) -> dict[str, Any]:
|
|
193
|
+
return {
|
|
194
|
+
"items": [item.serialize() for item in self.items],
|
|
195
|
+
"lock_item": self.lock_item,
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@staticmethod
|
|
199
|
+
def deserialize(data: dict[str, Any]) -> BattleItems:
|
|
200
|
+
battle_items = BattleItems(
|
|
201
|
+
[BattleItem.deserialize(item) for item in data.get("items", [])]
|
|
202
|
+
)
|
|
203
|
+
battle_items.lock_item = data.get("lock_item", False)
|
|
204
|
+
return battle_items
|
|
205
|
+
|
|
206
|
+
def __repr__(self):
|
|
207
|
+
return f"BattleItems({self.items})"
|
|
208
|
+
|
|
209
|
+
def __str__(self):
|
|
210
|
+
return f"BattleItems({self.items})"
|
|
211
|
+
|
|
212
|
+
def get_names(self, save_file: core.SaveFile) -> list[str] | None:
|
|
213
|
+
names = core.core_data.get_gatya_item_names(save_file).names
|
|
214
|
+
if names is None:
|
|
215
|
+
return None
|
|
216
|
+
items = core.core_data.get_gatya_item_buy(save_file).get_by_category(3)
|
|
217
|
+
if items is None:
|
|
218
|
+
return None
|
|
219
|
+
|
|
220
|
+
names = [names[item.id] for item in items]
|
|
221
|
+
return names
|
|
222
|
+
|
|
223
|
+
def edit(self, save_file: core.SaveFile):
|
|
224
|
+
group_name = save_file.get_localizable().get("shop_category1")
|
|
225
|
+
if group_name is None:
|
|
226
|
+
group_name = core.core_data.local_manager.get_key("battle_items")
|
|
227
|
+
item_names = self.get_names(save_file)
|
|
228
|
+
if item_names is None:
|
|
229
|
+
return
|
|
230
|
+
current_values = [item.amount for item in self.items]
|
|
231
|
+
values = dialog_creator.MultiEditor.from_reduced(
|
|
232
|
+
group_name,
|
|
233
|
+
item_names,
|
|
234
|
+
current_values,
|
|
235
|
+
core.core_data.max_value_manager.get("battle_items"),
|
|
236
|
+
).edit()
|
|
237
|
+
for i, value in enumerate(values):
|
|
238
|
+
self.items[i].amount = value
|
|
239
|
+
|
|
240
|
+
def edit_endless_items(self, save_file: core.SaveFile):
|
|
241
|
+
item_names = self.get_names(save_file)
|
|
242
|
+
if item_names is None:
|
|
243
|
+
return
|
|
244
|
+
|
|
245
|
+
current_values = [
|
|
246
|
+
item.endless_item.get_endless_duration_formatted() for item in self.items
|
|
247
|
+
]
|
|
248
|
+
|
|
249
|
+
(options, all_at_once) = dialog_creator.ChoiceInput.from_reduced(
|
|
250
|
+
[core.localize("endless_item_item", item=item) for item in item_names],
|
|
251
|
+
current_values,
|
|
252
|
+
localize_options=False,
|
|
253
|
+
dialog="select_option",
|
|
254
|
+
).multiple_choice(False)
|
|
255
|
+
|
|
256
|
+
if options is None:
|
|
257
|
+
return
|
|
258
|
+
|
|
259
|
+
infinity_str = core.localize("infinity")
|
|
260
|
+
|
|
261
|
+
if all_at_once:
|
|
262
|
+
val = dialog_creator.StringInput().get_input_locale_while(
|
|
263
|
+
"enter_duration_minutes", {}
|
|
264
|
+
)
|
|
265
|
+
if val is None:
|
|
266
|
+
return
|
|
267
|
+
|
|
268
|
+
if val.lower() == infinity_str.lower():
|
|
269
|
+
val = inf
|
|
270
|
+
else:
|
|
271
|
+
try:
|
|
272
|
+
val = float(val)
|
|
273
|
+
except ValueError:
|
|
274
|
+
return
|
|
275
|
+
|
|
276
|
+
for item in self.items:
|
|
277
|
+
item.endless_item.set_duration_mins(val, 0)
|
|
278
|
+
else:
|
|
279
|
+
for opt in options:
|
|
280
|
+
val = dialog_creator.StringInput().get_input_locale_while(
|
|
281
|
+
"enter_duration_minutes_item", {"item": item_names[opt]}
|
|
282
|
+
)
|
|
283
|
+
if val is None:
|
|
284
|
+
return
|
|
285
|
+
|
|
286
|
+
if val.lower() == infinity_str.lower():
|
|
287
|
+
val = inf
|
|
288
|
+
else:
|
|
289
|
+
try:
|
|
290
|
+
val = float(val)
|
|
291
|
+
except ValueError:
|
|
292
|
+
color.ColoredText.localize("invalid_minute_count")
|
|
293
|
+
continue
|
|
294
|
+
|
|
295
|
+
self.items[opt].endless_item.set_duration_mins(val, 0)
|
|
296
|
+
|
|
297
|
+
color.ColoredText.localize("endless_items_success")
|
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
import glob
|
|
3
3
|
import os
|
|
4
4
|
import shutil
|
|
5
|
-
import typing
|
|
6
5
|
|
|
7
6
|
from bcsfe import core
|
|
8
7
|
import re
|
|
@@ -88,12 +87,17 @@ class Path:
|
|
|
88
87
|
path.generate_dirs()
|
|
89
88
|
return path
|
|
90
89
|
|
|
90
|
+
def is_empty(self) -> bool:
|
|
91
|
+
return self.path == ""
|
|
92
|
+
|
|
91
93
|
def generate_dirs(self: Path) -> Path:
|
|
94
|
+
if self.is_empty():
|
|
95
|
+
return self
|
|
92
96
|
if not self.exists():
|
|
93
97
|
try:
|
|
94
98
|
self.__make_dirs()
|
|
95
|
-
except OSError:
|
|
96
|
-
|
|
99
|
+
except OSError as e:
|
|
100
|
+
print(e, self)
|
|
97
101
|
return self
|
|
98
102
|
|
|
99
103
|
def create(self) -> Path:
|
|
@@ -794,15 +794,7 @@ class SaveFile:
|
|
|
794
794
|
assert self.data.read_int() == 100100
|
|
795
795
|
|
|
796
796
|
if self.game_version >= 100300:
|
|
797
|
-
self.
|
|
798
|
-
length = 6
|
|
799
|
-
for _ in range(length):
|
|
800
|
-
b1 = self.data.read_bool()
|
|
801
|
-
b2 = self.data.read_bool()
|
|
802
|
-
i1 = self.data.read_byte()
|
|
803
|
-
f1 = self.data.read_double()
|
|
804
|
-
f2 = self.data.read_double()
|
|
805
|
-
self.utl2.append((b1, b2, i1, f1, f2))
|
|
797
|
+
self.battle_items.read_endless_items(self.data)
|
|
806
798
|
|
|
807
799
|
assert self.data.read_int() == 100300
|
|
808
800
|
|
|
@@ -1881,30 +1873,7 @@ class SaveFile:
|
|
|
1881
1873
|
self.data.write_int(100100)
|
|
1882
1874
|
|
|
1883
1875
|
if self.game_version >= 100300:
|
|
1884
|
-
|
|
1885
|
-
try:
|
|
1886
|
-
item = self.utl2[i]
|
|
1887
|
-
except IndexError:
|
|
1888
|
-
item = (False, False, 0, 0.0, 0.0)
|
|
1889
|
-
|
|
1890
|
-
tuple_len = len(item)
|
|
1891
|
-
b1, b2, i1, f1, f2 = False, False, 0, 0.0, 0.0
|
|
1892
|
-
if tuple_len >= 1:
|
|
1893
|
-
b1 = item[0]
|
|
1894
|
-
if tuple_len >= 2:
|
|
1895
|
-
b2 = item[1]
|
|
1896
|
-
if tuple_len >= 3:
|
|
1897
|
-
i1 = item[2]
|
|
1898
|
-
if tuple_len >= 4:
|
|
1899
|
-
f1 = item[3]
|
|
1900
|
-
if tuple_len >= 5:
|
|
1901
|
-
f2 = item[4]
|
|
1902
|
-
|
|
1903
|
-
self.data.write_bool(b1)
|
|
1904
|
-
self.data.write_bool(b2)
|
|
1905
|
-
self.data.write_byte(i1)
|
|
1906
|
-
self.data.write_double(f1)
|
|
1907
|
-
self.data.write_double(f2)
|
|
1876
|
+
self.battle_items.write_endless_items(self.data)
|
|
1908
1877
|
|
|
1909
1878
|
self.data.write_int(100300)
|
|
1910
1879
|
|
|
@@ -2504,7 +2473,6 @@ class SaveFile:
|
|
|
2504
2473
|
"ud8": self.ud8,
|
|
2505
2474
|
"ud9": self.ud9,
|
|
2506
2475
|
"date_int": self.date_int,
|
|
2507
|
-
"utl2": self.utl2,
|
|
2508
2476
|
"event_capsules_2": self.event_capsules_2,
|
|
2509
2477
|
"two_battle_lines": self.two_battle_lines,
|
|
2510
2478
|
"ud10": self.ud10,
|
|
@@ -2884,7 +2852,6 @@ class SaveFile:
|
|
|
2884
2852
|
save_file.ud8 = data.get("ud8", 0.0)
|
|
2885
2853
|
save_file.ud9 = data.get("ud9", 0.0)
|
|
2886
2854
|
save_file.date_int = data.get("date_int", 0)
|
|
2887
|
-
save_file.utl2 = data.get("utl2", [(False, False, 0, 0.0, 0.0)] * 6)
|
|
2888
2855
|
save_file.event_capsules_2 = data.get("event_capsules_2", [])
|
|
2889
2856
|
save_file.two_battle_lines = data.get("two_battle_lines", False)
|
|
2890
2857
|
save_file.ud10 = data.get("ud10", 0.0)
|
|
@@ -3205,7 +3172,6 @@ class SaveFile:
|
|
|
3205
3172
|
self.ushl6 = []
|
|
3206
3173
|
|
|
3207
3174
|
self.utl1 = []
|
|
3208
|
-
self.utl2 = [(False, False, 0, 0.0, 0.0)] * 6
|
|
3209
3175
|
self.utl3 = []
|
|
3210
3176
|
self.utl4 = []
|
|
3211
3177
|
|
|
@@ -141,6 +141,8 @@ class GameDataGetter:
|
|
|
141
141
|
|
|
142
142
|
archive.extractall(outdir.path)
|
|
143
143
|
|
|
144
|
+
outdir.add("downloaded").write(core.Data())
|
|
145
|
+
|
|
144
146
|
return True
|
|
145
147
|
|
|
146
148
|
def get_version_path(self) -> core.Path | None:
|
|
@@ -150,11 +152,11 @@ class GameDataGetter:
|
|
|
150
152
|
GameDataGetter.get_game_data_dir().add(self.cc.get_code()).add(self.version)
|
|
151
153
|
).generate_dirs()
|
|
152
154
|
|
|
153
|
-
def
|
|
155
|
+
def has_downloaded(self) -> bool:
|
|
154
156
|
path = self.get_version_path()
|
|
155
157
|
if path is None:
|
|
156
158
|
return False
|
|
157
|
-
return
|
|
159
|
+
return path.add("downloaded").exists()
|
|
158
160
|
|
|
159
161
|
def get_file(self, pack_name: str, file_name: str) -> core.Data | bool:
|
|
160
162
|
path = self.get_file_path(pack_name, file_name)
|
|
@@ -164,7 +166,7 @@ class GameDataGetter:
|
|
|
164
166
|
if path.exists():
|
|
165
167
|
return path.read()
|
|
166
168
|
else:
|
|
167
|
-
if self.
|
|
169
|
+
if self.has_downloaded():
|
|
168
170
|
return True
|
|
169
171
|
if self.download_version_data() is None:
|
|
170
172
|
return False
|
|
@@ -175,7 +177,7 @@ class GameDataGetter:
|
|
|
175
177
|
|
|
176
178
|
if path.exists():
|
|
177
179
|
return path.read()
|
|
178
|
-
return self.
|
|
180
|
+
return self.has_downloaded()
|
|
179
181
|
|
|
180
182
|
def save_file(self, pack_name: str, file_name: str) -> core.Data | bool:
|
|
181
183
|
pack_name = self.get_packname(pack_name)
|
|
@@ -243,7 +245,7 @@ class GameDataGetter:
|
|
|
243
245
|
self.print_no_file(pack_name, file_name)
|
|
244
246
|
return None
|
|
245
247
|
|
|
246
|
-
if display_text and not self.
|
|
248
|
+
if display_text and not self.has_downloaded():
|
|
247
249
|
color.ColoredText.localize(
|
|
248
250
|
"downloading",
|
|
249
251
|
file_name=file_name,
|
|
@@ -27,6 +27,15 @@ np=NP
|
|
|
27
27
|
leadership=Leadership
|
|
28
28
|
catseyes=Catseyes
|
|
29
29
|
battle_items=Battle Items
|
|
30
|
+
duration=<@t>{days}</t> days, <@t>{hours}</t> hours, <@t>{minutes}</> minutes, <@t>{seconds}</> seconds
|
|
31
|
+
endless_item_item=<@s>{item}</> : <@s>{int}</>
|
|
32
|
+
endless_items_success=<@su>Successfully edited endless items</>
|
|
33
|
+
invalid_minute_count=<@e>Invalid minute amount</>
|
|
34
|
+
enter_duration_minutes=Enter the duration in minutes for the endless items to last for (if you enter <@t>infinity</> the items last forever):
|
|
35
|
+
infinity_duration=<@t>infinity</>
|
|
36
|
+
infinity=Infinity
|
|
37
|
+
enter_duration_minutes_item=Enter the duration in minutes for the endless <@t>{item}</> to last for (if you enter <@t>infinity</> the items last forever):
|
|
38
|
+
battle_items_endless=Endless Battle Items
|
|
30
39
|
talent_orbs=Talent Orbs
|
|
31
40
|
scheme_items=Scheme Items
|
|
32
41
|
labyrinth_medals=Labyrinth Medals
|