├── requirements.txt ├── docs ├── guide1.png ├── guide2.png └── game_setting.png ├── templates ├── BP_CHEST.png ├── BP_REWARD.png ├── DAILY_BP.png ├── DORM_GOLD.png ├── GOTO_EVENT.png ├── GOTO_GIFT.png ├── GOTO_SHARE.png ├── LITE_FLAG.png ├── LOGIN_FLAG.png ├── MAIL_FLAG.png ├── MAIN_FLAG.png ├── QUICK_LITE.png ├── SHARE_ITEM.png ├── SHOP_FLAG.png ├── ABYSS_SETTLE.png ├── ARMADA_FLAG.png ├── BP_SHOP_TAB.png ├── DORM_STAMINA.png ├── ERRANDS_FLAG.png ├── GOTO_ATTACK.png ├── GOTO_BP_SHOP.png ├── HOME_BUTTON.png ├── LITE_BUTTON.png ├── LOGIN_CLICK.png ├── LOGIN_UPDATE.png ├── NOTICE_CLOSE.png ├── NOTICE_FLAG.png ├── NO_MORE_MAIL.png ├── POPUP_MARGIN.png ├── QUICK_CLAIM.png ├── QUICK_ERRAND.png ├── SHARE_BUTTON.png ├── WEEKLY_SHARE.png ├── BP_CHEST_CLAIM.png ├── BP_CHEST_TEXT.png ├── BP_MISSIONS_TAB.png ├── BP_REWARDS_TAB.png ├── BUY_HOMO_CHEST.png ├── CLAIM_STAMINA.png ├── COMMISSION_BUY.png ├── COMMISSION_FLAG.png ├── COMMISSION_LACK.png ├── COMMISSION_MAX.png ├── COMMISSION_PUT.png ├── CONFIRM_BUTTON.png ├── DORM_GOTO_SHOP.png ├── DOWNLOAD_DONE.png ├── ERRAND_CANCEL.png ├── ERRAND_DISABLE.png ├── EXPEDITION_FLAG.png ├── FRAG_GOTO_MATL.png ├── GOTO_BP_REWARD.png ├── GOTO_CHALLENGE.png ├── GOTO_RECOMMEND.png ├── MAIN_GOTO_DORM.png ├── MAIN_GOTO_MAIL.png ├── MAIN_GOTO_MALL.png ├── MATL_GOTO_FRAG.png ├── NEW_HOME_BUTTON.png ├── NEW_ITEM_POPUP.png ├── POPUP_BP_CLAIM.png ├── POPUP_BP_FLAG.png ├── QUICK_DISPATCH.png ├── RETURN_BUTTON.png ├── REWARD_BP_LEVEL.png ├── 7DAY_REWARD_CLAIM.png ├── ARMADA_REWARD_TAB.png ├── BATTLE_ATTACK_TAB.png ├── BATTLE_EVENT_TAB.png ├── BATTLE_GOTO_LITE.png ├── BP_REWARD_CONFIRM.png ├── COMMISSION_ACCEPT.png ├── COMMISSION_COUNT.png ├── COMMISSION_SUBMIT.png ├── CONTRIBUTION_FULL.png ├── CURRENT_BP_LEVEL.png ├── DAILY_REWARD_100.png ├── DAILY_REWARD_200.png ├── DAILY_REWARD_300.png ├── DAILY_REWARD_450.png ├── DAILY_REWARD_600.png ├── DORM_GOTO_ERRANDS.png ├── DOWNLOAD_CONFIRM.png ├── ERRAND_S+_CONFIRM.png ├── EXPEDITION_CANCEL.png ├── GOTO_BP_MISSIONS.png ├── GOTO_WEEKLY_GIFT.png ├── MAIL_QUICK_CLAIM.png ├── MAIN_GOTO_ARMADA.png ├── MAIN_GOTO_BATTLE.png ├── POPUP_EVENT_FLAG.png ├── QUICK_EXPEDITION.png ├── 7DAY_REWARD_CONFIRM.png ├── ARMADA_REWARD_CLAIM.png ├── ARMADA_REWARD_FLAG.png ├── BATTLE_CHALLENGE_TAB.png ├── BATTLE_RECOMMEND_TAB.png ├── COMMISSION_REQUEST.png ├── CONTRIBUTION_CLAIMED.png ├── CONTRIBUTION_REWARD.png ├── DORM_STAMINA_CLOSE.png ├── DORM_STAMINA_SURPLUS.png ├── ERRAND_REWARD_CLAIM.png ├── ERRAND_REWARD_DONE.png ├── EXPEDITION_COMPLETED.png ├── EXPEDITION_DISPATCH.png ├── EXPEDITION_FRAG_TAB.png ├── EXPEDITION_MATL_TAB.png ├── HOMO_CHEST_CONFIRM.png ├── MAIN_GOTO_MISSIONS.png ├── MONTHLY_CARD_CLAIM.png ├── QUICK_ERRAND_CONFIRM.png ├── SIGNIN_REWARD_CLAIM.png ├── ARMADA_GOTO_COMMISSION.png ├── COMMISSION_GOTO_REWARD.png ├── COMMISSION_SUBMIT_LACK.png ├── DORM_GOTO_EXPEDITIONS.png ├── MONTHLY_CARD_500_CLAIM.png ├── MONTHLY_CARD_500_FLAG.png ├── SIGNIN_REWARD_CONFIRM.png ├── ARMADA_CONTRIBUTION_FLAG.png ├── ARMADA_GOTO_CONTRIBUTION.png ├── COMMISSION_REQUEST_FLAG.png ├── COMMISSION_SUBMIT_CONFIRM.png └── EXPEDITION_NOT_AVAILABLE.png ├── config ├── default.json ├── i18n │ └── 中文.json └── template.json ├── tasks ├── mail.py ├── sweep.py ├── dorm_bonus.py ├── errand.py ├── expedition.py ├── base │ ├── switch.py │ ├── popup.py │ └── page.py ├── mission.py ├── login.py ├── armada.py └── weekly_reward.py ├── LICENSE ├── README.md ├── .gitignore ├── main.py └── config.py /requirements.txt: -------------------------------------------------------------------------------- 1 | zafkiel==0.3.3 2 | pydantic==2.9.1 3 | numpy==1.26.4 -------------------------------------------------------------------------------- /docs/guide1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/docs/guide1.png -------------------------------------------------------------------------------- /docs/guide2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/docs/guide2.png -------------------------------------------------------------------------------- /docs/game_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/docs/game_setting.png -------------------------------------------------------------------------------- /templates/BP_CHEST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BP_CHEST.png -------------------------------------------------------------------------------- /templates/BP_REWARD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BP_REWARD.png -------------------------------------------------------------------------------- /templates/DAILY_BP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DAILY_BP.png -------------------------------------------------------------------------------- /templates/DORM_GOLD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DORM_GOLD.png -------------------------------------------------------------------------------- /templates/GOTO_EVENT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/GOTO_EVENT.png -------------------------------------------------------------------------------- /templates/GOTO_GIFT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/GOTO_GIFT.png -------------------------------------------------------------------------------- /templates/GOTO_SHARE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/GOTO_SHARE.png -------------------------------------------------------------------------------- /templates/LITE_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/LITE_FLAG.png -------------------------------------------------------------------------------- /templates/LOGIN_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/LOGIN_FLAG.png -------------------------------------------------------------------------------- /templates/MAIL_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MAIL_FLAG.png -------------------------------------------------------------------------------- /templates/MAIN_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MAIN_FLAG.png -------------------------------------------------------------------------------- /templates/QUICK_LITE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/QUICK_LITE.png -------------------------------------------------------------------------------- /templates/SHARE_ITEM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/SHARE_ITEM.png -------------------------------------------------------------------------------- /templates/SHOP_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/SHOP_FLAG.png -------------------------------------------------------------------------------- /templates/ABYSS_SETTLE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ABYSS_SETTLE.png -------------------------------------------------------------------------------- /templates/ARMADA_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ARMADA_FLAG.png -------------------------------------------------------------------------------- /templates/BP_SHOP_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BP_SHOP_TAB.png -------------------------------------------------------------------------------- /templates/DORM_STAMINA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DORM_STAMINA.png -------------------------------------------------------------------------------- /templates/ERRANDS_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ERRANDS_FLAG.png -------------------------------------------------------------------------------- /templates/GOTO_ATTACK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/GOTO_ATTACK.png -------------------------------------------------------------------------------- /templates/GOTO_BP_SHOP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/GOTO_BP_SHOP.png -------------------------------------------------------------------------------- /templates/HOME_BUTTON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/HOME_BUTTON.png -------------------------------------------------------------------------------- /templates/LITE_BUTTON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/LITE_BUTTON.png -------------------------------------------------------------------------------- /templates/LOGIN_CLICK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/LOGIN_CLICK.png -------------------------------------------------------------------------------- /templates/LOGIN_UPDATE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/LOGIN_UPDATE.png -------------------------------------------------------------------------------- /templates/NOTICE_CLOSE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/NOTICE_CLOSE.png -------------------------------------------------------------------------------- /templates/NOTICE_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/NOTICE_FLAG.png -------------------------------------------------------------------------------- /templates/NO_MORE_MAIL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/NO_MORE_MAIL.png -------------------------------------------------------------------------------- /templates/POPUP_MARGIN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/POPUP_MARGIN.png -------------------------------------------------------------------------------- /templates/QUICK_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/QUICK_CLAIM.png -------------------------------------------------------------------------------- /templates/QUICK_ERRAND.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/QUICK_ERRAND.png -------------------------------------------------------------------------------- /templates/SHARE_BUTTON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/SHARE_BUTTON.png -------------------------------------------------------------------------------- /templates/WEEKLY_SHARE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/WEEKLY_SHARE.png -------------------------------------------------------------------------------- /templates/BP_CHEST_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BP_CHEST_CLAIM.png -------------------------------------------------------------------------------- /templates/BP_CHEST_TEXT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BP_CHEST_TEXT.png -------------------------------------------------------------------------------- /templates/BP_MISSIONS_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BP_MISSIONS_TAB.png -------------------------------------------------------------------------------- /templates/BP_REWARDS_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BP_REWARDS_TAB.png -------------------------------------------------------------------------------- /templates/BUY_HOMO_CHEST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BUY_HOMO_CHEST.png -------------------------------------------------------------------------------- /templates/CLAIM_STAMINA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/CLAIM_STAMINA.png -------------------------------------------------------------------------------- /templates/COMMISSION_BUY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_BUY.png -------------------------------------------------------------------------------- /templates/COMMISSION_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_FLAG.png -------------------------------------------------------------------------------- /templates/COMMISSION_LACK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_LACK.png -------------------------------------------------------------------------------- /templates/COMMISSION_MAX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_MAX.png -------------------------------------------------------------------------------- /templates/COMMISSION_PUT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_PUT.png -------------------------------------------------------------------------------- /templates/CONFIRM_BUTTON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/CONFIRM_BUTTON.png -------------------------------------------------------------------------------- /templates/DORM_GOTO_SHOP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DORM_GOTO_SHOP.png -------------------------------------------------------------------------------- /templates/DOWNLOAD_DONE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DOWNLOAD_DONE.png -------------------------------------------------------------------------------- /templates/ERRAND_CANCEL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ERRAND_CANCEL.png -------------------------------------------------------------------------------- /templates/ERRAND_DISABLE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ERRAND_DISABLE.png -------------------------------------------------------------------------------- /templates/EXPEDITION_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/EXPEDITION_FLAG.png -------------------------------------------------------------------------------- /templates/FRAG_GOTO_MATL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/FRAG_GOTO_MATL.png -------------------------------------------------------------------------------- /templates/GOTO_BP_REWARD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/GOTO_BP_REWARD.png -------------------------------------------------------------------------------- /templates/GOTO_CHALLENGE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/GOTO_CHALLENGE.png -------------------------------------------------------------------------------- /templates/GOTO_RECOMMEND.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/GOTO_RECOMMEND.png -------------------------------------------------------------------------------- /templates/MAIN_GOTO_DORM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MAIN_GOTO_DORM.png -------------------------------------------------------------------------------- /templates/MAIN_GOTO_MAIL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MAIN_GOTO_MAIL.png -------------------------------------------------------------------------------- /templates/MAIN_GOTO_MALL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MAIN_GOTO_MALL.png -------------------------------------------------------------------------------- /templates/MATL_GOTO_FRAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MATL_GOTO_FRAG.png -------------------------------------------------------------------------------- /templates/NEW_HOME_BUTTON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/NEW_HOME_BUTTON.png -------------------------------------------------------------------------------- /templates/NEW_ITEM_POPUP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/NEW_ITEM_POPUP.png -------------------------------------------------------------------------------- /templates/POPUP_BP_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/POPUP_BP_CLAIM.png -------------------------------------------------------------------------------- /templates/POPUP_BP_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/POPUP_BP_FLAG.png -------------------------------------------------------------------------------- /templates/QUICK_DISPATCH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/QUICK_DISPATCH.png -------------------------------------------------------------------------------- /templates/RETURN_BUTTON.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/RETURN_BUTTON.png -------------------------------------------------------------------------------- /templates/REWARD_BP_LEVEL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/REWARD_BP_LEVEL.png -------------------------------------------------------------------------------- /templates/7DAY_REWARD_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/7DAY_REWARD_CLAIM.png -------------------------------------------------------------------------------- /templates/ARMADA_REWARD_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ARMADA_REWARD_TAB.png -------------------------------------------------------------------------------- /templates/BATTLE_ATTACK_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BATTLE_ATTACK_TAB.png -------------------------------------------------------------------------------- /templates/BATTLE_EVENT_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BATTLE_EVENT_TAB.png -------------------------------------------------------------------------------- /templates/BATTLE_GOTO_LITE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BATTLE_GOTO_LITE.png -------------------------------------------------------------------------------- /templates/BP_REWARD_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BP_REWARD_CONFIRM.png -------------------------------------------------------------------------------- /templates/COMMISSION_ACCEPT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_ACCEPT.png -------------------------------------------------------------------------------- /templates/COMMISSION_COUNT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_COUNT.png -------------------------------------------------------------------------------- /templates/COMMISSION_SUBMIT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_SUBMIT.png -------------------------------------------------------------------------------- /templates/CONTRIBUTION_FULL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/CONTRIBUTION_FULL.png -------------------------------------------------------------------------------- /templates/CURRENT_BP_LEVEL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/CURRENT_BP_LEVEL.png -------------------------------------------------------------------------------- /templates/DAILY_REWARD_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DAILY_REWARD_100.png -------------------------------------------------------------------------------- /templates/DAILY_REWARD_200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DAILY_REWARD_200.png -------------------------------------------------------------------------------- /templates/DAILY_REWARD_300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DAILY_REWARD_300.png -------------------------------------------------------------------------------- /templates/DAILY_REWARD_450.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DAILY_REWARD_450.png -------------------------------------------------------------------------------- /templates/DAILY_REWARD_600.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DAILY_REWARD_600.png -------------------------------------------------------------------------------- /templates/DORM_GOTO_ERRANDS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DORM_GOTO_ERRANDS.png -------------------------------------------------------------------------------- /templates/DOWNLOAD_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DOWNLOAD_CONFIRM.png -------------------------------------------------------------------------------- /templates/ERRAND_S+_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ERRAND_S+_CONFIRM.png -------------------------------------------------------------------------------- /templates/EXPEDITION_CANCEL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/EXPEDITION_CANCEL.png -------------------------------------------------------------------------------- /templates/GOTO_BP_MISSIONS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/GOTO_BP_MISSIONS.png -------------------------------------------------------------------------------- /templates/GOTO_WEEKLY_GIFT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/GOTO_WEEKLY_GIFT.png -------------------------------------------------------------------------------- /templates/MAIL_QUICK_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MAIL_QUICK_CLAIM.png -------------------------------------------------------------------------------- /templates/MAIN_GOTO_ARMADA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MAIN_GOTO_ARMADA.png -------------------------------------------------------------------------------- /templates/MAIN_GOTO_BATTLE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MAIN_GOTO_BATTLE.png -------------------------------------------------------------------------------- /templates/POPUP_EVENT_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/POPUP_EVENT_FLAG.png -------------------------------------------------------------------------------- /templates/QUICK_EXPEDITION.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/QUICK_EXPEDITION.png -------------------------------------------------------------------------------- /templates/7DAY_REWARD_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/7DAY_REWARD_CONFIRM.png -------------------------------------------------------------------------------- /templates/ARMADA_REWARD_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ARMADA_REWARD_CLAIM.png -------------------------------------------------------------------------------- /templates/ARMADA_REWARD_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ARMADA_REWARD_FLAG.png -------------------------------------------------------------------------------- /templates/BATTLE_CHALLENGE_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BATTLE_CHALLENGE_TAB.png -------------------------------------------------------------------------------- /templates/BATTLE_RECOMMEND_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/BATTLE_RECOMMEND_TAB.png -------------------------------------------------------------------------------- /templates/COMMISSION_REQUEST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_REQUEST.png -------------------------------------------------------------------------------- /templates/CONTRIBUTION_CLAIMED.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/CONTRIBUTION_CLAIMED.png -------------------------------------------------------------------------------- /templates/CONTRIBUTION_REWARD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/CONTRIBUTION_REWARD.png -------------------------------------------------------------------------------- /templates/DORM_STAMINA_CLOSE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DORM_STAMINA_CLOSE.png -------------------------------------------------------------------------------- /templates/DORM_STAMINA_SURPLUS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DORM_STAMINA_SURPLUS.png -------------------------------------------------------------------------------- /templates/ERRAND_REWARD_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ERRAND_REWARD_CLAIM.png -------------------------------------------------------------------------------- /templates/ERRAND_REWARD_DONE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ERRAND_REWARD_DONE.png -------------------------------------------------------------------------------- /templates/EXPEDITION_COMPLETED.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/EXPEDITION_COMPLETED.png -------------------------------------------------------------------------------- /templates/EXPEDITION_DISPATCH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/EXPEDITION_DISPATCH.png -------------------------------------------------------------------------------- /templates/EXPEDITION_FRAG_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/EXPEDITION_FRAG_TAB.png -------------------------------------------------------------------------------- /templates/EXPEDITION_MATL_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/EXPEDITION_MATL_TAB.png -------------------------------------------------------------------------------- /templates/HOMO_CHEST_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/HOMO_CHEST_CONFIRM.png -------------------------------------------------------------------------------- /templates/MAIN_GOTO_MISSIONS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MAIN_GOTO_MISSIONS.png -------------------------------------------------------------------------------- /templates/MONTHLY_CARD_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MONTHLY_CARD_CLAIM.png -------------------------------------------------------------------------------- /templates/QUICK_ERRAND_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/QUICK_ERRAND_CONFIRM.png -------------------------------------------------------------------------------- /templates/SIGNIN_REWARD_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/SIGNIN_REWARD_CLAIM.png -------------------------------------------------------------------------------- /templates/ARMADA_GOTO_COMMISSION.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ARMADA_GOTO_COMMISSION.png -------------------------------------------------------------------------------- /templates/COMMISSION_GOTO_REWARD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_GOTO_REWARD.png -------------------------------------------------------------------------------- /templates/COMMISSION_SUBMIT_LACK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_SUBMIT_LACK.png -------------------------------------------------------------------------------- /templates/DORM_GOTO_EXPEDITIONS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/DORM_GOTO_EXPEDITIONS.png -------------------------------------------------------------------------------- /templates/MONTHLY_CARD_500_CLAIM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MONTHLY_CARD_500_CLAIM.png -------------------------------------------------------------------------------- /templates/MONTHLY_CARD_500_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/MONTHLY_CARD_500_FLAG.png -------------------------------------------------------------------------------- /templates/SIGNIN_REWARD_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/SIGNIN_REWARD_CONFIRM.png -------------------------------------------------------------------------------- /templates/ARMADA_CONTRIBUTION_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ARMADA_CONTRIBUTION_FLAG.png -------------------------------------------------------------------------------- /templates/ARMADA_GOTO_CONTRIBUTION.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/ARMADA_GOTO_CONTRIBUTION.png -------------------------------------------------------------------------------- /templates/COMMISSION_REQUEST_FLAG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_REQUEST_FLAG.png -------------------------------------------------------------------------------- /templates/COMMISSION_SUBMIT_CONFIRM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/COMMISSION_SUBMIT_CONFIRM.png -------------------------------------------------------------------------------- /templates/EXPEDITION_NOT_AVAILABLE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Aues6uen11Z/HonkaiHelper/HEAD/templates/EXPEDITION_NOT_AVAILABLE.png -------------------------------------------------------------------------------- /config/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "Project": { 3 | "General": { 4 | "Game": { 5 | "game_path": "G:\\miHoYo Launcher\\games\\Honkai Impact 3rd Game\\BH3.exe", 6 | "log_retain": "1week", 7 | "keep_foreground": true 8 | } 9 | } 10 | }, 11 | "Daily": { 12 | "Login": { 13 | "Login": { 14 | "confirm_time": "3" 15 | } 16 | } 17 | }, 18 | "Weekly": { 19 | "WeeklyReward": { 20 | "WeeklyEvent": { 21 | "share": true, 22 | "share_time": 0, 23 | "homo_chest": true, 24 | "homo_chest_time": 0, 25 | "bp_chest": true, 26 | "bp_chest_time": 0, 27 | "armada_contribution": true, 28 | "armada_contribution_time": 0 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /tasks/mail.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, logger, Timer, exists, find_click 2 | from zafkiel.exception import LoopError 3 | from zafkiel.ocr import Keyword 4 | from zafkiel.ui import UI 5 | 6 | from config import Config 7 | from tasks.base.page import page_mail, TPL_CONFIRM_BUTTON 8 | 9 | 10 | class Mail(UI): 11 | def __init__(self, config: Config = None): 12 | self.config = config 13 | 14 | def run(self): 15 | self.ui_ensure(page_mail) 16 | 17 | loop_timer = Timer(0, 10).start() 18 | while True: 19 | if loop_timer.reached(): 20 | raise LoopError('The operation has looped too many times') 21 | 22 | if exists(Template(r"NO_MORE_MAIL.png", (-0.449, -0.154), Keyword('已读'))): 23 | logger.info('Mail claim completed') 24 | break 25 | 26 | if find_click(Template(r"MAIL_QUICK_CLAIM.png", (0.42, 0.245), Keyword('一键领取'), rgb=True)): 27 | continue 28 | if find_click(TPL_CONFIRM_BUTTON): 29 | continue 30 | 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Aues6uen11Z 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tasks/sweep.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, logger, Timer, find_click, exists 2 | from zafkiel.exception import LoopError 3 | from zafkiel.ocr import Keyword 4 | from zafkiel.ui import UI 5 | 6 | from config import Config 7 | from tasks.base.page import page_battle, page_lite, TPL_CONFIRM_BUTTON 8 | from tasks.base.switch import TPL_BATTLE_ATTACK_TAB 9 | 10 | 11 | class Sweep(UI): 12 | def __init__(self, config: Config = None): 13 | self.config = config 14 | 15 | def run(self): 16 | self.ui_ensure(page_battle, TPL_BATTLE_ATTACK_TAB) 17 | self.ui_goto(page_lite) 18 | 19 | if not exists(Template(r"QUICK_LITE.png", (0.41, 0.241), Keyword('一键减负'))): 20 | logger.info('Material sweep already completed') 21 | return 22 | 23 | loop_timer = Timer(0, 10).start() 24 | while True: 25 | if loop_timer.reached(): 26 | raise LoopError('The operation has looped too many times') 27 | 28 | find_click(Template(r"QUICK_LITE.png", (0.41, 0.241), Keyword('一键减负'))) 29 | find_click(Template(r"LITE_BUTTON.png", (0.0, 0.133), Keyword('减负'))) 30 | if find_click(TPL_CONFIRM_BUTTON): 31 | logger.info('Material sweep completed') 32 | break 33 | 34 | -------------------------------------------------------------------------------- /tasks/dorm_bonus.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, logger, find_click, screenshot 2 | from zafkiel.ocr import Digit 3 | from zafkiel.ui import UI 4 | 5 | from config import Config 6 | from tasks.base.page import page_dorm 7 | 8 | 9 | class DormBonus(UI): 10 | def __init__(self, config: Config = None): 11 | self.config = config 12 | 13 | def claim_stamina(self): 14 | logger.info('Start claiming dorm stamina') 15 | self.ui_ensure(page_dorm) 16 | if find_click(Template(r"DORM_STAMINA.png", (-0.34, -0.059))): 17 | # 取存储的体力 18 | ocr = Digit(Template(r"DORM_STAMINA_SURPLUS.png", (-0.025, 0.077))) 19 | if ocr.ocr_single_line(screenshot()) > 0: 20 | find_click(Template(r"CLAIM_STAMINA.png", (0.092, 0.156)), times=2) 21 | logger.info('Dorm stamina claim completed') 22 | return 23 | find_click(Template(r"DORM_STAMINA_CLOSE.png", (0.349, -0.181))) 24 | 25 | def claim_gold(self): 26 | logger.info('Start claiming dorm gold') 27 | self.ui_ensure(page_dorm) 28 | if find_click(Template(r"DORM_GOLD.png", (-0.216, -0.071)), times=2): 29 | logger.info('Dorm gold claim completed') 30 | 31 | def run(self): 32 | self.claim_gold() 33 | self.claim_stamina() 34 | -------------------------------------------------------------------------------- /tasks/errand.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, logger, Timer, find_click, exists 2 | from zafkiel.exception import LoopError 3 | from zafkiel.ocr import Keyword 4 | from zafkiel.ui import UI 5 | 6 | from config import Config 7 | from tasks.base.page import TPL_RETURN_BUTTON, page_errands, TPL_CONFIRM_BUTTON 8 | 9 | 10 | class Errand(UI): 11 | def __init__(self, config: Config = None): 12 | self.config = config 13 | 14 | @staticmethod 15 | def dispatch(): 16 | loop_timer = Timer(0, 10).start() 17 | while True: 18 | if loop_timer.reached(): 19 | raise LoopError('The operation has looped too many times') 20 | 21 | find_click(Template(r"QUICK_ERRAND.png", (0.283, 0.251), Keyword('一键打工'))) 22 | 23 | if find_click(Template(r"QUICK_ERRAND_CONFIRM.png", (0.141, 0.204), Keyword('一键打工'), rgb=True)): 24 | if not find_click(Template(r"ERRAND_S+_CONFIRM.png", (0.136, 0.117), Keyword('确定')), times=2): 25 | find_click(TPL_RETURN_BUTTON) 26 | logger.info('Errand dispatch completed') 27 | break 28 | if exists(Template(r"ERRAND_DISABLE.png", (0.141, 0.203), rgb=True)): 29 | find_click(Template(r"ERRAND_CANCEL.png", (-0.141, 0.204), Keyword('取消'))) 30 | logger.info('No place available for dispatch') 31 | break 32 | 33 | @staticmethod 34 | def claim_rewards(): 35 | loop_timer = Timer(0, 10).start() 36 | while True: 37 | if exists(Template(r"ERRAND_REWARD_DONE.png", (0.42, 0.249), rgb=True)): 38 | logger.info('Errand rewards claim completed') 39 | break 40 | 41 | if loop_timer.reached(): 42 | raise LoopError('The operation has looped too many times') 43 | 44 | find_click(Template(r"ERRAND_REWARD_CLAIM.png", (0.419, 0.25), Keyword('领取奖励'), rgb=True)) 45 | find_click(TPL_CONFIRM_BUTTON) 46 | 47 | def run(self): 48 | self.ui_ensure(page_errands) 49 | self.claim_rewards() 50 | self.dispatch() 51 | 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HonkaiHelper 2 | 基于图色识别和OCR的PC端崩坏3自动化脚本,先别退坑,刷刷日常凑登录天数吧~ 3 | 4 | 5 | 6 | ✨顺便看看如何使用DaCapo接管米家全家桶日常:[赛博代肝从开机到关机](https://github.com/Aues6uen11Z/DaCapo/blob/master/docs/%E8%B5%9B%E5%8D%9A%E4%BB%A3%E8%82%9D%E4%BB%8E%E5%BC%80%E6%9C%BA%E5%88%B0%E5%85%B3%E6%9C%BA.md) 7 | 8 | ## 功能 9 | 10 | - 挂远征、家园打工 11 | - 材料活动一键减负 12 | - 领家园金币、凭证奖励、邮件、每日活跃奖励 13 | - 提交舰团委托、领舰团奖励 14 | 15 | ## 前置准备 16 | 17 | 1. 设置-辅助-显示菜单提示:关 18 | ![](./docs/game_setting.png) 19 | 2. 设置-画质-分辨率:任意16:9的分辨率,但求稳请使用1280×720或2560×1440 20 | 21 | ## 使用方法 22 | 23 | ### 一键包 24 | 25 | 图形化一键包现已发布,无需配置python环境,支持自动更新,欢迎[下载体验](https://github.com/Aues6uen11Z/HonkaiHelper/releases)。所用的图形化界面[DaCapo](https://github.com/Aues6uen11Z/DaCapo)与本项目完全独立,是一个通用脚本管理器,如果你有其他脚本想放上来,可以自行查看README了解用法。 26 | 27 | 解压后点击DaCapo.exe启动程序,更新后修改游戏路径,然后回到主页点击按钮即可开始。 28 | 29 | ![](./docs/guide1.png) 30 | 31 | ![](./docs/guide2.png) 32 | 33 | ### 手动导入 34 | 35 | 下载并打开DaCapo,点击左下角齿轮图标,在“创建新实例”一栏选择从远程创建,填写以下内容并点击创建: 36 | 37 | - 实例名称:随意 38 | - 模板名称:随意 39 | - 仓库地址:`https://gitee.com/aues6uen11z/HonkaiHelper` 40 | - 本地路径:`repos` 41 | - 分支:留空不填 42 | - 模板路径:`config` 43 | 44 | ### 从源码构建 45 | 46 | 1. 克隆本项目或直接下载压缩包并解压 47 | ```shell 48 | git clone https://github.com/Aues6uen11Z/HonkaiHelper.git 49 | ``` 50 | 51 | 2. 准备Python环境,建议使用conda的新虚拟环境 52 | 53 | ```shell 54 | # 安装完anaconda或miniconda后进入shell 55 | # 理论上支持3.6以上任意版本,但目前只测试了3.9-3.11 56 | conda create -n zafkiel python==3.9.18 57 | conda activate zafkiel 58 | ``` 59 | 60 | 3. 在该环境内安装依赖包 61 | 62 | ```shell 63 | pip install -r requirements.txt 64 | ``` 65 | 66 | 4. 到项目根目录下的config/default.json修改游戏启动路径 67 | 5. 在项目根目录运行main.py 68 | 69 | ```shell 70 | cd 你的存储路径/HonkaiHelper 71 | python main.py 72 | ``` 73 | 74 | ## 注意事项 75 | 76 | 1. 项目更新有时会涉及到依赖更新,若从源码运行,使用时请确保你的zafkiel版本与requirements.txt一致。 77 | 78 | ```shell 79 | # 在你的虚拟环境内 80 | pip install --upgrade zafkiel 81 | ``` 82 | 83 | 2. 目前新版本尚未开发完全,不能保证在每一个人的电脑上都完美运行,出现问题可以在issue中提出,记得附上日志(注意**是.log文件,不是log.txt**) 84 | 85 | 3. Gitee仓库仅用作同步,不要在那里开issue 86 | 87 | ## Todo 88 | 89 | - [ ] 常用功能 90 | - [x] 图形化界面 91 | - [ ] 安卓模拟器支持 92 | - [ ] 改进日志和网页报告 93 | 94 | ## 开发 95 | 96 | 新版本使用了[Zafkiel](https://github.com/Aues6uen11Z/Zafkiel)库,结合了[Airtest](https://github.com/AirtestProject/Airtest)和[StarRailCopilot](https://github.com/LmeSzinc/StarRailCopilot)的一些优点,欢迎尝试。 97 | -------------------------------------------------------------------------------- /tasks/expedition.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, Timer, logger, find_click, exists 2 | from zafkiel.exception import LoopError 3 | from zafkiel.ocr import Ocr, Keyword 4 | from zafkiel.ui import UI 5 | 6 | from config import Config 7 | from tasks.base.page import page_expeditions, TPL_CONFIRM_BUTTON 8 | from tasks.base.switch import TPL_EXPEDITION_MATL_TAB, TPL_EXPEDITION_FRAG_TAB 9 | 10 | 11 | class Expeditions(UI): 12 | def __init__(self, config: Config = None): 13 | self.config = config 14 | 15 | # 远征派遣 16 | @staticmethod 17 | def dispatch(): 18 | loop_timer = Timer(0, 10).start() 19 | while True: 20 | if loop_timer.reached(): 21 | raise LoopError('The operation has looped too many times') 22 | 23 | find_click(Template(r"QUICK_EXPEDITION.png", (0.409, 0.237), Keyword('一键远征'))) 24 | if exists(Template(r"EXPEDITION_NOT_AVAILABLE.png", (0.209, -0.045), Keyword('次数不足'), ocr_mode=1)): 25 | find_click(Template(r"EXPEDITION_CANCEL.png", (-0.141, 0.205), Keyword('取消派遣'))) 26 | break 27 | if find_click(Template(r"EXPEDITION_DISPATCH.png", (0.14, 0.205), Keyword('远征派遣')), times=2): 28 | if find_click(Template(r"CLAIM_STAMINA.png", (0.092, 0.156), Keyword('取出体力')), times=2): 29 | find_click(Template(r"EXPEDITION_DISPATCH.png", (0.14, 0.205), Keyword('远征派遣')), times=2) 30 | logger.info('Expedition dispatch completed') 31 | break 32 | 33 | # 领前一天远征奖励 TODO: 记录远征类型 34 | def claim_rewards(self): 35 | TPL_EXPEDITION_COMPLETED = Template(r"EXPEDITION_COMPLETED.png", (0.237, -0.09), Keyword('完成远征')) 36 | if not exists(TPL_EXPEDITION_COMPLETED, timeout=1): 37 | current_state = self.ui_get_current_state(self.ui_get_current_page().switch) 38 | another_state = TPL_EXPEDITION_MATL_TAB if current_state == TPL_EXPEDITION_FRAG_TAB.name \ 39 | else TPL_EXPEDITION_FRAG_TAB 40 | self.ui_goto(page_expeditions, another_state) 41 | if find_click(TPL_EXPEDITION_COMPLETED): 42 | find_click(TPL_CONFIRM_BUTTON) 43 | logger.info('Expedition rewards claim completed') 44 | 45 | def run(self): 46 | self.ui_ensure(page_expeditions) 47 | self.claim_rewards() 48 | self.dispatch() 49 | -------------------------------------------------------------------------------- /tasks/base/switch.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template 2 | from zafkiel.ocr import Keyword 3 | from zafkiel.ui import Switch 4 | 5 | # BP任务界面 6 | TPL_BP_MISSIONS_TAB = Template(r"BP_MISSIONS_TAB.png", (-0.227, 0.257)) 7 | TPL_BP_REWARDS_TAB = Template(r"BP_REWARDS_TAB.png", (-0.273, -0.044)) 8 | TPL_BP_SHOP_TAB = Template(r"BP_SHOP_TAB.png", (-0.391, 0.034), Keyword('作战工坊')) 9 | TPL_GOTO_BP_MISSIONS = Template(r"GOTO_BP_MISSIONS.png", (-0.417, -0.171), Keyword('作战任务')) 10 | TPL_GOTO_BP_REWARDS = Template(r"GOTO_BP_REWARD.png", (-0.419, 0.008), Keyword('作战奖励')) 11 | TPL_GOTO_BP_SHOP = Template(r"GOTO_BP_SHOP.png", (-0.418, -0.029), Keyword('作战商店')) 12 | 13 | switch_missions = Switch('switch_missions', is_selector=True) 14 | switch_missions.add_state('BP_MISSIONS_TAB', TPL_BP_MISSIONS_TAB, TPL_GOTO_BP_MISSIONS) 15 | switch_missions.add_state('BP_REWARDS_TAB', TPL_BP_REWARDS_TAB, TPL_GOTO_BP_REWARDS) 16 | switch_missions.add_state('BP_SHOP_TAB', TPL_BP_SHOP_TAB, TPL_GOTO_BP_SHOP) 17 | 18 | 19 | # 远征界面 20 | TPL_EXPEDITION_FRAG_TAB = Template(r"EXPEDITION_FRAG_TAB.png", (0.369, -0.196), rgb=True) 21 | TPL_EXPEDITION_MATL_TAB = Template(r"EXPEDITION_MATL_TAB.png", (0.37, -0.135), rgb=True) 22 | TPL_MATL_GOTO_FRAG = Template(r"MATL_GOTO_FRAG.png", (0.369, -0.197), rgb=True) 23 | TPL_FRAG_GOTO_MATL = Template(r"FRAG_GOTO_MATL.png", (0.369, -0.136), rgb=True) 24 | 25 | switch_expeditions = Switch('switch_expeditions', is_selector=True) 26 | switch_expeditions.add_state('EXPEDITION_FRAG_TAB', TPL_EXPEDITION_FRAG_TAB, TPL_MATL_GOTO_FRAG) 27 | switch_expeditions.add_state('EXPEDITION_MATL_TAB', TPL_EXPEDITION_MATL_TAB, TPL_FRAG_GOTO_MATL) 28 | 29 | 30 | # 作战界面 31 | TPL_BATTLE_RECOMMEND_TAB = Template(r"BATTLE_RECOMMEND_TAB.png", (-0.257, -0.2), rgb=True) 32 | TPL_BATTLE_ATTACK_TAB = Template(r"BATTLE_ATTACK_TAB.png", (-0.12, -0.201), rgb=True) 33 | TPL_BATTLE_CHALLENGE_TAB = Template(r"BATTLE_CHALLENGE_TAB.png", (0.023, -0.2), rgb=True) 34 | TPL_BATTLE_EVENT_TAB = Template(r"BATTLE_EVENT_TAB.png", (0.16, -0.199), rgb=True) 35 | TPL_GOTO_RECOMMEND = Template(r"GOTO_RECOMMEND.png", (-0.192, -0.202), Keyword('推荐')) 36 | TPL_GOTO_ATTACK = Template(r"GOTO_ATTACK.png", (-0.072, -0.202), Keyword('出击')) 37 | TPL_GOTO_CHALLENGE = Template(r"GOTO_CHALLENGE.png", (0.066, -0.202), Keyword('挑战')) 38 | TPL_GOTO_EVENT = Template(r"GOTO_EVENT.png", (0.199, -0.202), Keyword('活动')) 39 | 40 | switch_battle = Switch('switch_battle', is_selector=True) 41 | switch_battle.add_state('BATTLE_RECOMMEND_TAB', TPL_BATTLE_RECOMMEND_TAB, TPL_GOTO_RECOMMEND) 42 | switch_battle.add_state('BATTLE_ATTACK_TAB', TPL_BATTLE_ATTACK_TAB, TPL_GOTO_ATTACK) 43 | switch_battle.add_state('BATTLE_CHALLENGE_TAB', TPL_BATTLE_CHALLENGE_TAB, TPL_GOTO_CHALLENGE) 44 | switch_battle.add_state('BATTLE_EVENT_TAB', TPL_BATTLE_EVENT_TAB, TPL_GOTO_EVENT) 45 | -------------------------------------------------------------------------------- /tasks/mission.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, logger, screenshot, touch, find_click 2 | from zafkiel.ocr import Digit, Keyword 3 | from zafkiel.ui import UI 4 | 5 | from config import Config 6 | from tasks.base.page import page_missions, TPL_CONFIRM_BUTTON, TPL_NEW_ITEM 7 | from tasks.base.popup import popup_list, popup_handler 8 | from tasks.base.switch import TPL_BP_MISSIONS_TAB, TPL_BP_REWARDS_TAB 9 | 10 | 11 | class Missions(UI): 12 | def __init__(self, config: Config = None): 13 | self.config = config 14 | 15 | def claim_bp_rewards(self): 16 | self.ui_goto(page_missions, TPL_BP_REWARDS_TAB) 17 | 18 | # 领凭证奖励 19 | screen = screenshot() 20 | ocr_current_level = Digit(Template(r"CURRENT_BP_LEVEL.png", (-0.29, -0.178))) 21 | current_level = ocr_current_level.ocr_single_line(screen) 22 | logger.info(f'Current BP level: {current_level}') 23 | 24 | ocr_reward_level = Digit(Template(r"REWARD_BP_LEVEL.png", (-0.182, -0.13))) 25 | reward_level = ocr_reward_level.ocr_single_line(screen) 26 | logger.info(f'BP reward level: {reward_level}') 27 | 28 | # TODO:65级以后右端顶到头,领取位置变了 29 | if current_level >= reward_level: 30 | if touch(Template(r"BP_REWARD.png", (-0.179, -0.054)), blind=True): 31 | popup_handler.handle_bp_reward() 32 | find_click(Template(r"BP_REWARD_CONFIRM.png", (0.141, 0.173))) 33 | logger.info('BP rewards claim completed') 34 | 35 | def claim_daily_rewards(self): 36 | self.ui_goto(page_missions, TPL_BP_MISSIONS_TAB) 37 | if find_click(Template(r"QUICK_CLAIM.png", (0.418, -0.187), Keyword('一键领取'), rgb=True, ocr_mode=1)): 38 | find_click(TPL_CONFIRM_BUTTON) 39 | logger.info('Daily rewards claim completed') 40 | 41 | ocr = Digit(Template(r"DAILY_BP.png", (-0.273, 0.231))) 42 | daily_bp = ocr.ocr_single_line(screenshot()) 43 | logger.info(f'Daily BP: {daily_bp}') 44 | click = False 45 | if daily_bp >= 600: 46 | click = find_click(Template(r"DAILY_REWARD_600.png", (0.449, 0.241))) 47 | elif daily_bp >= 450: 48 | click = find_click(Template(r"DAILY_REWARD_450.png", (0.312, 0.241))) 49 | elif daily_bp >= 300: 50 | click = find_click(Template(r"DAILY_REWARD_300.png", (0.175, 0.241))) 51 | elif daily_bp >= 200: 52 | click = find_click(Template(r"DAILY_REWARD_200.png", (0.037, 0.241))) 53 | elif daily_bp >= 100: 54 | click = find_click(Template(r"DAILY_REWARD_100.png", (-0.1, 0.241))) 55 | if click: 56 | find_click(TPL_CONFIRM_BUTTON) 57 | 58 | def run(self): 59 | # self.get_popup_list(popup_list) 60 | self.ui_ensure(page_missions) 61 | self.claim_daily_rewards() 62 | self.claim_bp_rewards() 63 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Python template 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | cover/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | .pybuilder/ 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | # For a library or package, you might want to ignore these files since the code is 88 | # intended to run in multiple environments; otherwise, check them in: 89 | # .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 99 | __pypackages__/ 100 | 101 | # Celery stuff 102 | celerybeat-schedule 103 | celerybeat.pid 104 | 105 | # SageMath parsed files 106 | *.sage.py 107 | 108 | # Environments 109 | .env 110 | .venv 111 | env/ 112 | venv/ 113 | ENV/ 114 | env.bak/ 115 | venv.bak/ 116 | 117 | # Spyder project settings 118 | .spyderproject 119 | .spyproject 120 | 121 | # Rope project settings 122 | .ropeproject 123 | 124 | # mkdocs documentation 125 | /site 126 | 127 | # mypy 128 | .mypy_cache/ 129 | .dmypy.json 130 | dmypy.json 131 | 132 | # Pyre type checker 133 | .pyre/ 134 | 135 | # pytype static type analyzer 136 | .pytype/ 137 | 138 | # Cython debug symbols 139 | cython_debug/ 140 | 141 | .idea/ 142 | log/ 143 | test.py 144 | tasks/**/*.png 145 | abyss/ 146 | config/config.json 147 | tools/ 148 | .vscode/ 149 | *.exe -------------------------------------------------------------------------------- /tasks/base/popup.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, find_click, touch, exists, sleep 2 | from zafkiel.decorator import run_until_true 3 | from zafkiel.ocr import Keyword 4 | 5 | from tasks.base.page import TPL_CONFIRM_BUTTON 6 | 7 | 8 | class PopupHandler: 9 | # 凭证奖励弹窗 10 | @run_until_true 11 | def handle_bp_reward(self): 12 | rec_template = Template(r"POPUP_BP_FLAG.png", (-0.137, 0.218), Keyword('升级凭证')) 13 | touch_template = Template(r"POPUP_BP_CLAIM.png", (0.137, 0.218), Keyword('领取奖励')) 14 | if find_click(rec_template, timeout=0, touch_template=touch_template): 15 | return find_click(TPL_CONFIRM_BUTTON) 16 | 17 | # 活动通知弹窗 18 | @staticmethod 19 | def handle_login_event(): 20 | rec_template = Template(r"POPUP_EVENT_FLAG.png", (0.0, 0.24)) 21 | touch_template = Template(r"POPUP_MARGIN.png", (0.467, -0.252)) 22 | return find_click(rec_template, timeout=0, touch_template=touch_template, blind=True) 23 | 24 | # 不定时的七日登录奖励 25 | @run_until_true 26 | def handle_7day_reward(self): 27 | if find_click(Template(r"7DAY_REWARD_CLAIM.png", (0.084, 0.234)), timeout=0): 28 | # if find_click(Template(r"7DAY_REWARD_CONFIRM.png", (-0.001, 0.145)), timeout=3): 29 | if find_click(TPL_CONFIRM_BUTTON, timeout=3): 30 | return True 31 | return False 32 | 33 | # 每日签到奖励 34 | @run_until_true 35 | def handle_signin_reward(self): 36 | if find_click(Template(r"SIGNIN_REWARD_CLAIM.png", (0.083, 0.248)), timeout=0): 37 | if find_click(Template(r"SIGNIN_REWARD_CONFIRM.png", (-0.001, 0.134)), timeout=3): 38 | return True 39 | return False 40 | 41 | # 游戏公告,最近好像不弹了 42 | # @run_until_true 43 | # def handle_notice(self): 44 | # rec_template = Template(r"assets/NOTICE_FLAG.png", record_pos=(-0.391, -0.194), resolution=(1280, 720), 45 | # rgb=True) 46 | # touch_template = Template(r"assets/NOTICE_CLOSE.png", record_pos=(0.431, -0.22), resolution=(1280, 720)) 47 | # return find_click(rec_template, timeout=0.5, touch_template=touch_template) 48 | 49 | # 深渊结算弹窗 50 | @run_until_true 51 | def handle_abyss_settle(self): 52 | if exists(Template(r"ABYSS_SETTLE.png", (0.019, 0.147), Keyword('结算奖励'), local_search=False, ocr_mode=1)): 53 | sleep(0.5) 54 | touch(Template(r"POPUP_MARGIN.png", (0.467, -0.252)), blind=True) 55 | return True 56 | return False 57 | 58 | # 月卡奖励 59 | @run_until_true 60 | def handle_monthly_card(self): 61 | if find_click(Template(r"MONTHLY_CARD_CLAIM.png", (0.082, 0.234)), timeout=0): 62 | if find_click(TPL_CONFIRM_BUTTON, timeout=3): 63 | return True 64 | elif find_click(Template(r"MONTHLY_CARD_500_FLAG.png", (0.088, 0.244), Keyword('水晶'), ocr_mode=1), 65 | Template(r"MONTHLY_CARD_500_CLAIM.png", (0.446, 0.121)), 66 | timeout=0, blind=True): 67 | if find_click(TPL_CONFIRM_BUTTON, timeout=3): 68 | return True 69 | return False 70 | 71 | 72 | popup_handler = PopupHandler() 73 | popup_list = [popup_handler.handle_login_event, popup_handler.handle_7day_reward, popup_handler.handle_signin_reward, 74 | popup_handler.handle_abyss_settle, popup_handler.handle_bp_reward, popup_handler.handle_monthly_card] 75 | -------------------------------------------------------------------------------- /config/i18n/中文.json: -------------------------------------------------------------------------------- 1 | { 2 | "Project": { 3 | "tasks": { 4 | "General": { 5 | "groups": { 6 | "Game": { 7 | "name": "游戏设置", 8 | "help": "", 9 | "items": { 10 | "game_path": { 11 | "name": "游戏路径", 12 | "help": "游戏本体而非启动器路径,例如“G:\\Honkai Impact 3\\Games\\BH3.exe”" 13 | }, 14 | "log_retain": { 15 | "name": "日志保留时间", 16 | "help": "", 17 | "options": { 18 | "1day": "1天", 19 | "3days": "3天", 20 | "1week": "1周", 21 | "1month": "1月" 22 | } 23 | }, 24 | "keep_foreground": { 25 | "name": "保持前台运行", 26 | "help": "有后台程序抢窗口时开启" 27 | } 28 | } 29 | } 30 | } 31 | } 32 | } 33 | }, 34 | "Daily": { 35 | "name": "日常", 36 | "tasks": { 37 | "Login": { 38 | "name": "启动游戏", 39 | "groups": { 40 | "Login": { 41 | "name": "登录", 42 | "help": "", 43 | "items": { 44 | "confirm_time": { 45 | "name": "确认时间", 46 | "help": "主页面出现多久视为登录成功\n网络较差可以适当延长此时间,防止卡在弹窗界面" 47 | } 48 | } 49 | } 50 | } 51 | }, 52 | "Logout": { 53 | "name": "退出游戏", 54 | "groups": {} 55 | }, 56 | "Mission1": { 57 | "name": "活跃奖励1", 58 | "groups": {} 59 | }, 60 | "Mission2": { 61 | "name": "活跃奖励2", 62 | "groups": {} 63 | }, 64 | "Sweep": { 65 | "name": "减负", 66 | "groups": {} 67 | }, 68 | "Mail": { 69 | "name": "邮件", 70 | "groups": {} 71 | }, 72 | "DormBonus": { 73 | "name": "宿舍奖励", 74 | "groups": {} 75 | }, 76 | "Expedition": { 77 | "name": "远征", 78 | "groups": {} 79 | }, 80 | "Errand": { 81 | "name": "打工", 82 | "groups": {} 83 | }, 84 | "Armada": { 85 | "name": "舰团奖励", 86 | "groups": {} 87 | } 88 | } 89 | }, 90 | "Weekly": { 91 | "name": "周常", 92 | "tasks": { 93 | "WeeklyReward": { 94 | "name": "周常奖励", 95 | "groups": { 96 | "WeeklyEvent": { 97 | "name": "奖励事件", 98 | "help": "", 99 | "items": { 100 | "share": { 101 | "name": "每周分享", 102 | "help": "需安排在活跃奖励2之后,否则不会运行" 103 | }, 104 | "share_time": { 105 | "name": "share_time", 106 | "help": "" 107 | }, 108 | "homo_chest": { 109 | "name": "吼姆秘宝", 110 | "help": "" 111 | }, 112 | "homo_chest_time": { 113 | "name": "homo_chest_time", 114 | "help": "" 115 | }, 116 | "bp_chest": { 117 | "name": "历练值宝箱", 118 | "help": "" 119 | }, 120 | "bp_chest_time": { 121 | "name": "bp_chest_time", 122 | "help": "" 123 | }, 124 | "armada_contribution": { 125 | "name": "舰团贡献奖励", 126 | "help": "" 127 | }, 128 | "armada_contribution_time": { 129 | "name": "armada_contribution_time", 130 | "help": "" 131 | } 132 | } 133 | } 134 | } 135 | } 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /tasks/login.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import shutil 3 | import time 4 | from pathlib import Path 5 | import subprocess 6 | 7 | from zafkiel import ( 8 | Template, 9 | logger, 10 | wait, 11 | touch, 12 | stop_app, 13 | auto_setup, 14 | sleep, 15 | exists, 16 | find_click, 17 | ) 18 | from zafkiel.ocr import Keyword 19 | from zafkiel.ui import UI 20 | 21 | from config import Config 22 | from tasks.base.popup import popup_list, popup_handler 23 | from tasks.base.page import page_main 24 | 25 | 26 | class Login(UI): 27 | def __init__(self, config: Config): 28 | self.config = config 29 | 30 | def manage_log(self): 31 | log_retain_map = { 32 | "1day": 1, 33 | "3days": 3, 34 | "1week": 7, 35 | "1month": 30, 36 | } 37 | retain_days = log_retain_map.get( 38 | self.config.data["Project"]["General"]["Game"]["log_retain"], 7 39 | ) 40 | 41 | current_time = time.time() 42 | log_path = Path("./log") 43 | 44 | for log_dir in log_path.iterdir(): 45 | create_time = log_dir.stat().st_ctime 46 | age_in_days = (current_time - create_time) / (24 * 3600) 47 | 48 | if age_in_days > retain_days: 49 | try: 50 | logger.info(f"Deleting old log directory: {log_dir}") 51 | shutil.rmtree(log_dir) 52 | except Exception as e: 53 | logger.error(f"Failed to delete {log_dir}: {e}") 54 | 55 | def handle_app_login(self): 56 | wait( 57 | Template(r"LOGIN_FLAG.png", (0.406, 0.233), rgb=True), 58 | timeout=1200, 59 | interval=3, 60 | interval_func=self.check_update, 61 | ) 62 | touch(Template(r"LOGIN_CLICK.png", (-0.002, -0.031)), times=2, blind=True) 63 | 64 | try: 65 | confirm_time = float( 66 | self.config.data["Daily"]["Login"]["Login"]["confirm_time"] 67 | ) 68 | if confirm_time < 3.0: 69 | confirm_time = 3.0 70 | logger.warning( 71 | "Confirm time was less than 3.0, setting to minimum value of 3.0" 72 | ) 73 | except: 74 | confirm_time = 3.0 75 | logger.warning("Invalid confirm_time in config, using default value of 3.0") 76 | 77 | while True: 78 | if self.ui_additional(): 79 | continue 80 | if popup_handler.handle_abyss_settle(): 81 | continue 82 | if self.ui_page_appear(page_main): 83 | sleep(confirm_time) 84 | if not self.ui_ensure(page_main): 85 | logger.info("Game login successful") 86 | break 87 | 88 | return True 89 | 90 | def app_stop(self): 91 | stop_app() 92 | 93 | def app_start(self): 94 | subprocess.Popen([self.config.data["Project"]["General"]["Game"]["game_path"]]) 95 | sleep(15) 96 | 97 | date = datetime.datetime.now().strftime("%Y-%m-%d") 98 | auto_setup( 99 | str(Path.cwd()), 100 | logdir=f"./log/{date}/report", 101 | devices=[ 102 | "WindowsPlatform:///?title=崩坏3", 103 | ], 104 | ) 105 | self.manage_log() 106 | self.get_popup_list(popup_list) 107 | self.handle_app_login() 108 | 109 | def app_restart(self): 110 | self.app_stop() 111 | self.app_start() 112 | self.handle_app_login() 113 | 114 | @staticmethod 115 | def check_update(): 116 | if exists(Template(r"LOGIN_UPDATE.png", (0.002, -0.129))): 117 | find_click(Template(r"DOWNLOAD_CONFIRM.png", (0.0, 0.116))) 118 | logger.info("Game updating") 119 | if find_click( 120 | Template(r"DOWNLOAD_DONE.png", (0.0, 0.048), Keyword("确定")), 121 | timeout=1200, 122 | ): 123 | logger.info("Game update completed") 124 | -------------------------------------------------------------------------------- /tasks/armada.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template, logger, Timer, exists, find_click, touch, screenshot, sleep 2 | from zafkiel.decorator import run_until_true 3 | from zafkiel.exception import LoopError 4 | from zafkiel.ocr import DigitCounter, Keyword 5 | from zafkiel.ui import UI 6 | 7 | from config import Config 8 | from tasks.base.page import TPL_RETURN_BUTTON, page_armada, page_commission, page_armada_rewards, TPL_CONFIRM_BUTTON 9 | 10 | 11 | class Armada(UI): 12 | def __init__(self, config: Config = None): 13 | self.config = config 14 | 15 | def claim_rewards(self): 16 | logger.info('Start claiming armada rewards') 17 | self.ui_goto(page_commission) 18 | loop_timer = Timer(0, 10).start() 19 | while True: 20 | if loop_timer.reached(): 21 | raise LoopError('The operation has looped too many times') 22 | 23 | if not exists(Template(r"ARMADA_REWARD_TAB.png", (0.38, -0.128))): 24 | logger.info('Armada reward claim completed') 25 | break 26 | 27 | self.ui_goto(page_armada_rewards) 28 | find_click(Template(r"ARMADA_REWARD_CLAIM.png", (0.212, 0.225), Keyword('领取'))) 29 | find_click(TPL_CONFIRM_BUTTON) 30 | 31 | @staticmethod 32 | def _handel_lack(): 33 | logger.info('Handling lack of commission materials') 34 | loop_timer = Timer(0, 10).start() 35 | while True: 36 | if loop_timer.reached(): 37 | raise LoopError('The operation has looped too many times') 38 | 39 | if exists(Template(r"COMMISSION_SUBMIT.png", (0.237, 0.224), Keyword('提交'), rgb=True)): 40 | break 41 | 42 | if find_click(Template(r"COMMISSION_MAX.png", (0.002, 0.161), Keyword('最大'))): 43 | find_click(Template(r"COMMISSION_BUY.png", (0.275, 0.162), Keyword('购买')), times=2) 44 | continue 45 | 46 | touch(Template(r"COMMISSION_LACK.png", (-0.398, -0.103)), blind=True) 47 | 48 | @run_until_true 49 | def _apply_new(self): 50 | logger.info('Applying for new commission') 51 | ocr = DigitCounter(Template(r"COMMISSION_REQUEST.png", (-0.36, 0.225))) 52 | if ocr.ocr_single_line(screenshot())[0] == 0: 53 | find_click(Template(r"COMMISSION_REQUEST.png", (-0.36, 0.225)), blind=True) 54 | page_flag = Template(r"COMMISSION_REQUEST_FLAG.png", (-0.378, -0.18), Keyword('委托申请次数')) 55 | if find_click(page_flag, 56 | Template(r"COMMISSION_ACCEPT.png", (0.375, -0.079), Keyword('接受')), 57 | times=2): 58 | find_click(page_flag, TPL_RETURN_BUTTON, timeout=0) 59 | logger.info('New commission request completed') 60 | sleep(0.5) 61 | return True 62 | return False 63 | 64 | def commission(self): 65 | logger.info('Start commission process') 66 | self.ui_goto(page_commission) 67 | ocr = DigitCounter(Template(r"COMMISSION_COUNT.png", (0.43, 0.242))) 68 | 69 | loop_timer = Timer(0, 30).start() 70 | while True: 71 | if loop_timer.reached(): 72 | raise LoopError('The operation has looped too many times') 73 | 74 | if ocr.ocr_single_line(screenshot())[0] == 0: 75 | logger.info('Commissions submit completed') 76 | break 77 | 78 | if self._apply_new(): 79 | continue 80 | 81 | if find_click(Template(r"COMMISSION_SUBMIT.png", (0.237, 0.224), Keyword('提交'), rgb=True), 82 | timeout=0): 83 | continue 84 | if exists(Template(r"COMMISSION_SUBMIT_LACK.png", (0.237, 0.225), Keyword('提交'), rgb=True)): 85 | logger.info('Insufficient commission materials, suggest to buy in advance to speed up') 86 | self._handel_lack() 87 | find_click(Template(r"COMMISSION_SUBMIT_CONFIRM.png", (0.135, 0.159), Keyword('提交委托')), 88 | timeout=0) 89 | find_click(Template(r"COMMISSION_PUT.png", (0.0, 0.137), Keyword('放入舰团奖励池')), 90 | times=2, timeout=0) 91 | 92 | def run(self): 93 | self.ui_ensure(page_armada) 94 | self.claim_rewards() 95 | self.commission() 96 | -------------------------------------------------------------------------------- /tasks/base/page.py: -------------------------------------------------------------------------------- 1 | from zafkiel import Template 2 | from zafkiel.ocr import Keyword 3 | from zafkiel.ui import Page 4 | 5 | from tasks.base.switch import switch_missions, switch_expeditions, TPL_GOTO_ATTACK, switch_battle 6 | 7 | TPL_RETURN_BUTTON = Template(r"RETURN_BUTTON.png", (-0.444, -0.256), Keyword('返回')) 8 | TPL_HOME_BUTTON = Template(r"HOME_BUTTON.png", (-0.298, -0.257), Keyword('主菜单')) 9 | TPL_CONFIRM_BUTTON = Template(r"CONFIRM_BUTTON.png", (0.0, 0.144), Keyword('确定')) 10 | TPL_NEW_ITEM = Template(r"NEW_ITEM_POPUP.png", (0.289, -0.01)) 11 | 12 | # 主界面 13 | page_main = Page(Template(r"MAIN_FLAG.png", (0.281, 0.043), rgb=True)) 14 | 15 | # 家园界面 16 | page_dorm = Page(Template(r"DORM_STAMINA.png", (-0.34, -0.059))) 17 | page_dorm.link(TPL_RETURN_BUTTON, 18 | destination=page_main) 19 | page_main.link(Template(r"MAIN_GOTO_DORM.png", (0.354, 0.244), Keyword('家园')), 20 | destination=page_dorm) 21 | 22 | # 舰团界面 23 | page_armada = Page(Template(r"ARMADA_FLAG.png", (0.113, 0.076))) 24 | page_armada.link(TPL_RETURN_BUTTON, 25 | destination=page_main) 26 | page_main.link(Template(r"MAIN_GOTO_ARMADA.png", (0.195, 0.244), Keyword('舰团')), 27 | destination=page_armada) 28 | 29 | # 舰团委托界面 30 | page_commission = Page(Template(r"COMMISSION_FLAG.png", (-0.392, -0.183), Keyword('回收委托'))) 31 | page_commission.link(TPL_RETURN_BUTTON, 32 | destination=page_armada) 33 | page_commission.link(TPL_HOME_BUTTON, 34 | destination=page_main) 35 | page_armada.link(Template(r"ARMADA_GOTO_COMMISSION.png", (-0.113, 0.227), Keyword('委托回收'), local_search=False, ocr_mode=1), 36 | destination=page_commission) 37 | 38 | # 舰团奖池界面 39 | page_armada_rewards = Page(Template(r"ARMADA_REWARD_FLAG.png", (-0.394, -0.184), Keyword('舰团奖池'))) 40 | page_armada_rewards.link(TPL_RETURN_BUTTON, 41 | destination=page_armada) 42 | page_armada_rewards.link(TPL_HOME_BUTTON, 43 | destination=page_main) 44 | page_commission.link(Template(r"COMMISSION_GOTO_REWARD.png", (0.439, -0.104), Keyword('舰团奖池')), 45 | destination=page_armada_rewards) 46 | 47 | # 舰团贡献界面 48 | page_armada_contribution = Page(Template(r"ARMADA_CONTRIBUTION_FLAG.png", (-0.395, -0.184), Keyword('舰团贡献'))) 49 | page_armada_contribution.link(TPL_RETURN_BUTTON, 50 | destination=page_armada) 51 | page_armada_contribution.link(TPL_HOME_BUTTON, 52 | destination=page_main) 53 | page_armada.link(Template(r"ARMADA_GOTO_CONTRIBUTION.png", (0.232, 0.23), Keyword('舰团贡献'), local_search=False, ocr_mode=1), 54 | destination=page_armada_contribution) 55 | 56 | # BP任务界面 57 | page_missions = Page(Template(r"GOTO_BP_MISSIONS.png", (-0.417, -0.171), Keyword('作战任务')), 58 | switch=switch_missions) 59 | page_missions.link(TPL_RETURN_BUTTON, 60 | destination=page_main) 61 | page_main.link(Template(r"MAIN_GOTO_MISSIONS.png", (-0.453, -0.186)), 62 | destination=page_missions) 63 | 64 | # 邮件界面 65 | page_mail = Page(Template(r"MAIL_FLAG.png", (-0.456, 0.23), Keyword('邮件数'))) 66 | page_mail.link(TPL_RETURN_BUTTON, 67 | destination=page_main) 68 | page_main.link(Template(r"MAIN_GOTO_MAIL.png", (-0.421, -0.029)), 69 | destination=page_mail) 70 | 71 | # 远征界面 72 | page_expeditions = Page(Template(r"EXPEDITION_FLAG.png", (-0.363, -0.183), Keyword('今日远征可用体力')), 73 | switch=switch_expeditions) 74 | page_expeditions.link(TPL_RETURN_BUTTON, 75 | destination=page_dorm) 76 | page_expeditions.link(TPL_HOME_BUTTON, 77 | destination=page_main) 78 | page_dorm.link(Template(r"DORM_GOTO_EXPEDITIONS.png", (0.155, 0.237), Keyword('远征')), 79 | destination=page_expeditions) 80 | 81 | # 远征派遣界面 82 | page_dispatch = Page(Template(r"QUICK_DISPATCH.png", (0.119, 0.227), Keyword('一键派遣'))) 83 | page_dispatch.link(TPL_RETURN_BUTTON, 84 | destination=page_expeditions) 85 | page_dispatch.link(TPL_HOME_BUTTON, 86 | destination=page_main) 87 | 88 | # 打工界面 89 | page_errands = Page(Template(r"ERRANDS_FLAG.png", (-0.077, -0.258), rgb=True)) 90 | page_errands.link(TPL_RETURN_BUTTON, 91 | destination=page_dorm) 92 | page_dorm.link(Template(r"DORM_GOTO_ERRANDS.png", (0.277, 0.235), Keyword('打工')), 93 | destination=page_errands) 94 | 95 | # 商店界面 96 | page_shop = Page(Template(r"SHOP_FLAG.png", (-0.474, -0.191))) 97 | page_shop.link(TPL_RETURN_BUTTON, 98 | destination=page_dorm) 99 | page_shop.link(TPL_HOME_BUTTON, 100 | destination=page_main) 101 | page_dorm.link(Template(r"DORM_GOTO_SHOP.png", (0.422, 0.237), Keyword('商店')), 102 | destination=page_shop) 103 | 104 | # 出击界面 105 | page_battle = Page(TPL_GOTO_ATTACK, 106 | switch=switch_battle) 107 | page_battle.link(Template(r"NEW_HOME_BUTTON.png", (-0.343, -0.252)), 108 | destination=page_main) 109 | page_main.link(Template(r"MAIN_GOTO_BATTLE.png", (0.421, -0.004), Keyword('出击')), 110 | destination=page_battle) 111 | 112 | # 材料活动界面 113 | page_lite = Page(Template(r"LITE_FLAG.png", (-0.001, -0.195), Keyword('材料活动'))) 114 | page_lite.link(TPL_RETURN_BUTTON, 115 | destination=page_battle) 116 | page_lite.link(TPL_HOME_BUTTON, 117 | destination=page_main) 118 | page_battle.link(Template(r"BATTLE_GOTO_LITE.png", (0.114, 0.147)), 119 | destination=page_lite) 120 | -------------------------------------------------------------------------------- /tasks/weekly_reward.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import time 3 | 4 | from zafkiel import Template, exists, find_click, touch, logger 5 | from zafkiel.ocr import Keyword 6 | from zafkiel.ui import UI 7 | 8 | from config import Config 9 | from tasks.base.page import ( 10 | TPL_RETURN_BUTTON, 11 | page_missions, 12 | TPL_CONFIRM_BUTTON, 13 | page_main, 14 | TPL_NEW_ITEM, 15 | page_armada_contribution, 16 | ) 17 | from tasks.base.popup import popup_handler 18 | from tasks.base.switch import TPL_BP_MISSIONS_TAB, TPL_BP_REWARDS_TAB 19 | 20 | 21 | class WeeklyReward(UI): 22 | def __init__(self, config: Config): 23 | self.config = config 24 | 25 | now = datetime.datetime.now() 26 | monday = now - datetime.timedelta(days=now.weekday()) 27 | self.monday_4am = monday.replace( 28 | hour=4, minute=0, second=0, microsecond=0 29 | ).timestamp() 30 | 31 | def share(self): 32 | if not self.config.data["Weekly"]["WeeklyReward"]["WeeklyEvent"]["share"]: 33 | return 34 | 35 | if ( 36 | self.config.data["Weekly"]["WeeklyReward"]["WeeklyEvent"]["share_time"] 37 | > self.monday_4am 38 | ): 39 | logger.info("Weekly sharing already completed") 40 | return 41 | 42 | self.ui_ensure(page_missions, TPL_BP_MISSIONS_TAB) 43 | if exists(Template(r"WEEKLY_SHARE.png", (-0.196, -0.134), Keyword("每周分享"))): 44 | find_click(Template(r"GOTO_SHARE.png", (0.013, -0.083), Keyword("前往"))) 45 | touch(Template(r"SHARE_ITEM.png", (-0.199, -0.095)), blind=True) 46 | find_click(Template(r"SHARE_BUTTON.png", (-0.35, 0.222)), times=2) 47 | find_click(TPL_RETURN_BUTTON) 48 | logger.info("Weekly sharing completed") 49 | else: 50 | # 若已经手动完成 51 | logger.info("Weekly sharing already completed") 52 | self.config.update( 53 | "Weekly", "WeeklyReward", "WeeklyEvent", "share_time", time.time() 54 | ) 55 | 56 | def homo_chest(self): 57 | if not self.config.data["Weekly"]["WeeklyReward"]["WeeklyEvent"]["homo_chest"]: 58 | return 59 | 60 | if ( 61 | self.config.data["Weekly"]["WeeklyReward"]["WeeklyEvent"]["homo_chest_time"] 62 | > self.monday_4am 63 | ): 64 | logger.info("Weekly homo chest already claimed") 65 | return 66 | 67 | self.ui_ensure(page_main) 68 | find_click(Template(r"MAIN_GOTO_MALL.png", (-0.423, 0.076))) 69 | find_click(Template(r"GOTO_GIFT.png", (-0.355, -0.123), Keyword("礼包"))) 70 | find_click(Template(r"GOTO_WEEKLY_GIFT.png", (-0.355, -0.005), Keyword("周期"))) 71 | if find_click( 72 | Template(r"BUY_HOMO_CHEST.png", (-0.207, 0.041), Keyword("免费")) 73 | ): 74 | find_click( 75 | Template(r"HOMO_CHEST_CONFIRM.png", (-0.002, 0.18), Keyword("免费")) 76 | ) 77 | find_click(TPL_CONFIRM_BUTTON) 78 | logger.info("Weekly homo chest claim completed") 79 | else: 80 | logger.info("Weekly homo chest already claimed") 81 | self.config.update( 82 | "Weekly", "WeeklyReward", "WeeklyEvent", "homo_chest_time", time.time() 83 | ) 84 | find_click(TPL_RETURN_BUTTON) 85 | 86 | def bp_chest(self): 87 | if not self.config.data["Weekly"]["WeeklyReward"]["WeeklyEvent"]["bp_chest"]: 88 | return 89 | 90 | if ( 91 | self.config.data["Weekly"]["WeeklyReward"]["WeeklyEvent"]["bp_chest_time"] 92 | > self.monday_4am 93 | ): 94 | logger.info("Weekly bp chest already claimed") 95 | return 96 | 97 | self.ui_ensure(page_missions, TPL_BP_REWARDS_TAB) 98 | if find_click( 99 | Template(r"BP_CHEST_TEXT.png", (0.411, 0.197), Keyword("作战历练箱")), 100 | Template(r"BP_CHEST.png", (0.334, 0.203)), 101 | blind=True, 102 | ): 103 | find_click(TPL_NEW_ITEM, timeout=2) 104 | find_click(TPL_CONFIRM_BUTTON) 105 | popup_handler.handle_bp_reward() 106 | logger.info("Weekly bp chest claim completed") 107 | else: 108 | logger.info("Weekly bp chest already claimed") 109 | self.config.update( 110 | "Weekly", "WeeklyReward", "WeeklyEvent", "bp_chest_time", time.time() 111 | ) 112 | 113 | def armada_contribution_reward(self): 114 | if not self.config.data["Weekly"]["WeeklyReward"]["WeeklyEvent"][ 115 | "armada_contribution" 116 | ]: 117 | return 118 | 119 | if ( 120 | self.config.data["Weekly"]["WeeklyReward"]["WeeklyEvent"][ 121 | "armada_contribution_time" 122 | ] 123 | > self.monday_4am 124 | ): 125 | logger.info("Armada contribution reward already claimed") 126 | return 127 | 128 | self.ui_ensure(page_armada_contribution) 129 | if exists(Template(r"CONTRIBUTION_FULL.png", (-0.325, -0.123))): 130 | find_click(Template(r"CONTRIBUTION_REWARD.png", (-0.442, -0.122))) 131 | find_click(TPL_CONFIRM_BUTTON) 132 | self.config.update( 133 | "Weekly", 134 | "WeeklyReward", 135 | "WeeklyEvent", 136 | "armada_contribution_time", 137 | time.time(), 138 | ) 139 | logger.info("Armada contribution reward claim completed") 140 | elif exists(Template(r"CONTRIBUTION_CLAIMED.png", (-0.324, -0.122))): 141 | self.config.update( 142 | "Weekly", 143 | "WeeklyReward", 144 | "WeeklyEvent", 145 | "armada_contribution_time", 146 | time.time(), 147 | ) 148 | logger.info("Armada contribution reward already claimed") 149 | else: 150 | logger.info("Armada contribution reward not available") 151 | 152 | def run(self): 153 | self.share() 154 | self.homo_chest() 155 | self.bp_chest() 156 | self.armada_contribution_reward() 157 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import ctypes 3 | import datetime 4 | import sys 5 | from pathlib import Path 6 | 7 | from loguru import logger 8 | from zafkiel import simple_report, auto_setup 9 | from zafkiel import Config as Zconfig 10 | from zafkiel.ui import UI 11 | 12 | from config import Config 13 | from tasks.armada import Armada 14 | from tasks.base.popup import popup_list 15 | from tasks.dorm_bonus import DormBonus 16 | from tasks.errand import Errand 17 | from tasks.expedition import Expeditions 18 | from tasks.login import Login 19 | from tasks.mail import Mail 20 | from tasks.mission import Missions 21 | from tasks.sweep import Sweep 22 | from tasks.weekly_reward import WeeklyReward 23 | 24 | logger.remove() 25 | logger.add( 26 | sys.stdout, 27 | level="INFO", 28 | format="{time:HH:mm:ss} | " 29 | "{level: <7} | " 30 | "{message}", 31 | ) 32 | date = datetime.datetime.now().strftime("%Y-%m-%d") 33 | logger.add( 34 | f"./log/{date}/{date}.log", 35 | level="DEBUG", 36 | format="{time:HH:mm:ss} | " 37 | "{level: <7} | " 38 | "{message}", 39 | ) 40 | 41 | 42 | def all_tasks(config): 43 | try: 44 | # 日常 45 | Login(config).app_start() 46 | Missions(config).run() 47 | DormBonus(config).claim_stamina() 48 | DormBonus(config).claim_gold() 49 | Errand(config).run() 50 | Expeditions(config).run() 51 | Armada(config).run() 52 | Sweep(config).run() 53 | Missions(config).run() 54 | Mail(config).run() 55 | WeeklyReward(config).run() 56 | 57 | # 结束游戏进程 58 | Login(config).app_stop() 59 | 60 | except Exception as e: 61 | logger.exception(e) 62 | raise 63 | 64 | finally: 65 | simple_report( 66 | __file__, 67 | log_path=Path(f"./log/{date}/report").resolve(), 68 | output=f"./log/{date}/report.html", 69 | ) 70 | 71 | 72 | def single_task(config, task): 73 | max_retries = 3 74 | retry_count = 0 75 | 76 | while retry_count < max_retries: 77 | try: 78 | if task != "login": 79 | auto_setup( 80 | str(Path.cwd()), 81 | logdir=f"./log/{date}/report", 82 | devices=[ 83 | "WindowsPlatform:///?title=崩坏3", 84 | ], 85 | ) 86 | UI().get_popup_list(popup_list) 87 | 88 | if task == "armada": 89 | Armada(config).run() 90 | elif task == "dorm_bonus": 91 | DormBonus(config).run() 92 | elif task == "errand": 93 | Errand(config).run() 94 | elif task == "expedition": 95 | Expeditions(config).run() 96 | elif task == "login": 97 | Login(config).app_start() 98 | elif task == "logout": 99 | Login(config).app_stop() 100 | simple_report( 101 | __file__, 102 | log_path=Path(f"./log/{date}/report").resolve(), 103 | output=f"./log/{date}/report.html", 104 | ) 105 | elif task == "mail": 106 | Mail(config).run() 107 | elif task == "mission": 108 | Missions(config).run() 109 | elif task == "sweep": 110 | Sweep(config).run() 111 | elif task == "weekly_reward": 112 | WeeklyReward(config).run() 113 | 114 | break 115 | 116 | except Exception as e: 117 | if "!_src.empty()" in str(e): 118 | retry_count += 1 119 | logger.warning(f"Screen capture failed (attempt {retry_count}/{max_retries}), retrying...") 120 | if retry_count >= max_retries: 121 | logger.error(f"Failed to execute task '{task}' after {max_retries} attempts due to screen capture issues") 122 | simple_report( 123 | __file__, 124 | log_path=Path(f"./log/{date}/report").resolve(), 125 | output=f"./log/{date}/report.html", 126 | ) 127 | raise 128 | else: 129 | simple_report( 130 | __file__, 131 | log_path=Path(f"./log/{date}/report").resolve(), 132 | output=f"./log/{date}/report.html", 133 | ) 134 | logger.error(e) 135 | raise 136 | 137 | 138 | def main(): 139 | parser = argparse.ArgumentParser() 140 | parser.add_argument( 141 | "--task", 142 | "-t", 143 | choices=[ 144 | "armada", 145 | "dorm_bonus", 146 | "errand", 147 | "expedition", 148 | "login", 149 | "logout", 150 | "mail", 151 | "mission", 152 | "sweep", 153 | "weekly_reward", 154 | ], 155 | help='Task name, one of "armada, dorm_bonus, errand, expedition, login, logout, mail, ' 156 | 'mission, sweep, weekly_reward"', 157 | ) 158 | parser.add_argument("--config_path", "-c", default="./config/config.json") 159 | args = parser.parse_args() 160 | 161 | if args.task: 162 | config_path = Path(args.config_path).resolve() 163 | if not config_path.exists(): 164 | logger.error(f"{config_path} not found") 165 | return 166 | config = Config(config_path) 167 | Zconfig.KEEP_FOREGROUND = config.data["Project"]["General"]["Game"]["keep_foreground"] 168 | single_task(config, args.task) 169 | else: 170 | config = Config("./config/default.json") 171 | Zconfig.KEEP_FOREGROUND = config.data["Project"]["General"]["Game"]["keep_foreground"] 172 | all_tasks(config) 173 | 174 | 175 | if __name__ == "__main__": 176 | # 以管理员身份运行 177 | if ctypes.windll.shell32.IsUserAnAdmin(): 178 | main() 179 | else: 180 | ctypes.windll.shell32.ShellExecuteW( 181 | None, "runas", sys.executable, __file__, None, 1 182 | ) 183 | -------------------------------------------------------------------------------- /config/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "Project": { 3 | "General": { 4 | "_Base": { 5 | "language": { 6 | "type": "input", 7 | "value": "中文", 8 | "option": [], 9 | "hidden": false, 10 | "help": "", 11 | "disabled": false 12 | }, 13 | "work_dir": { 14 | "type": "input", 15 | "value": "./repos/HonkaiHelper", 16 | "option": [], 17 | "hidden": false, 18 | "help": "", 19 | "disabled": true 20 | }, 21 | "background": { 22 | "type": "input", 23 | "value": false, 24 | "option": [], 25 | "hidden": false, 26 | "help": "", 27 | "disabled": true 28 | }, 29 | "config_path": { 30 | "type": "input", 31 | "value": "./repos/HonkaiHelper/config/config.json", 32 | "option": [], 33 | "hidden": false, 34 | "help": "", 35 | "disabled": true 36 | }, 37 | "log_path": { 38 | "type": "input", 39 | "value": "./log", 40 | "option": [], 41 | "hidden": false, 42 | "help": "", 43 | "disabled": true 44 | } 45 | }, 46 | "Game": { 47 | "game_path": { 48 | "type": "file", 49 | "value": "", 50 | "option": [], 51 | "hidden": false, 52 | "help": "", 53 | "disabled": false 54 | }, 55 | "log_retain": { 56 | "type": "select", 57 | "value": "1week", 58 | "option": [ 59 | "1day", 60 | "3days", 61 | "1week", 62 | "1month" 63 | ], 64 | "hidden": false, 65 | "help": "", 66 | "disabled": false 67 | }, 68 | "keep_foreground": { 69 | "type": "checkbox", 70 | "value": false, 71 | "option": [], 72 | "hidden": false, 73 | "help": "", 74 | "disabled": false 75 | } 76 | } 77 | }, 78 | "Update": { 79 | "_Base": { 80 | "env_name": { 81 | "type": "input", 82 | "value": "zafkiel", 83 | "option": [], 84 | "hidden": false, 85 | "help": "", 86 | "disabled": false 87 | }, 88 | "python_version": { 89 | "type": "input", 90 | "value": "3.11", 91 | "option": [], 92 | "hidden": false, 93 | "help": "", 94 | "disabled": false 95 | } 96 | } 97 | } 98 | }, 99 | "Daily": { 100 | "Login": { 101 | "_Base": { 102 | "priority": { 103 | "type": "input", 104 | "value": 31.0, 105 | "option": [], 106 | "hidden": false, 107 | "help": "", 108 | "disabled": true 109 | }, 110 | "command": { 111 | "type": "input", 112 | "value": "py main.py -t login", 113 | "option": [], 114 | "hidden": false, 115 | "help": "", 116 | "disabled": true 117 | } 118 | }, 119 | "Login": { 120 | "confirm_time": { 121 | "type": "input", 122 | "value": 3.0, 123 | "option": [], 124 | "hidden": false, 125 | "help": "", 126 | "disabled": false 127 | } 128 | } 129 | }, 130 | "Logout": { 131 | "_Base": { 132 | "priority": { 133 | "type": "input", 134 | "value": 0.0, 135 | "option": [], 136 | "hidden": false, 137 | "help": "", 138 | "disabled": true 139 | }, 140 | "command": { 141 | "type": "input", 142 | "value": "py main.py -t logout", 143 | "option": [], 144 | "hidden": false, 145 | "help": "", 146 | "disabled": true 147 | } 148 | } 149 | }, 150 | "Mission1": { 151 | "_Base": { 152 | "priority": { 153 | "type": "input", 154 | "value": 6.0, 155 | "option": [], 156 | "hidden": false, 157 | "help": "", 158 | "disabled": true 159 | }, 160 | "command": { 161 | "type": "input", 162 | "value": "py main.py -t mission", 163 | "option": [], 164 | "hidden": false, 165 | "help": "", 166 | "disabled": true 167 | } 168 | } 169 | }, 170 | "Mission2": { 171 | "_Base": { 172 | "priority": { 173 | "type": "input", 174 | "value": 2.0, 175 | "option": [], 176 | "hidden": false, 177 | "help": "", 178 | "disabled": true 179 | }, 180 | "command": { 181 | "type": "input", 182 | "value": "py main.py -t mission", 183 | "option": [], 184 | "hidden": false, 185 | "help": "", 186 | "disabled": true 187 | } 188 | } 189 | }, 190 | "Sweep": { 191 | "_Base": { 192 | "priority": { 193 | "type": "input", 194 | "value": 3.0, 195 | "option": [], 196 | "hidden": false, 197 | "help": "", 198 | "disabled": false 199 | }, 200 | "command": { 201 | "type": "input", 202 | "value": "py main.py -t sweep", 203 | "option": [], 204 | "hidden": false, 205 | "help": "", 206 | "disabled": true 207 | } 208 | } 209 | }, 210 | "Mail": { 211 | "_Base": { 212 | "priority": { 213 | "type": "input", 214 | "value": 4.0, 215 | "option": [], 216 | "hidden": false, 217 | "help": "", 218 | "disabled": false 219 | }, 220 | "command": { 221 | "type": "input", 222 | "value": "py main.py -t mail", 223 | "option": [], 224 | "hidden": false, 225 | "help": "", 226 | "disabled": true 227 | } 228 | } 229 | }, 230 | "DormBonus": { 231 | "_Base": { 232 | "priority": { 233 | "type": "input", 234 | "value": 5.0, 235 | "option": [], 236 | "hidden": false, 237 | "help": "", 238 | "disabled": false 239 | }, 240 | "command": { 241 | "type": "input", 242 | "value": "py main.py -t dorm_bonus", 243 | "option": [], 244 | "hidden": false, 245 | "help": "", 246 | "disabled": true 247 | } 248 | } 249 | }, 250 | "Expedition": { 251 | "_Base": { 252 | "priority": { 253 | "type": "input", 254 | "value": 5.0, 255 | "option": [], 256 | "hidden": false, 257 | "help": "", 258 | "disabled": false 259 | }, 260 | "command": { 261 | "type": "input", 262 | "value": "py main.py -t expedition", 263 | "option": [], 264 | "hidden": false, 265 | "help": "", 266 | "disabled": true 267 | } 268 | } 269 | }, 270 | "Errand": { 271 | "_Base": { 272 | "priority": { 273 | "type": "input", 274 | "value": 5.0, 275 | "option": [], 276 | "hidden": false, 277 | "help": "", 278 | "disabled": false 279 | }, 280 | "command": { 281 | "type": "input", 282 | "value": "py main.py -t errand", 283 | "option": [], 284 | "hidden": false, 285 | "help": "", 286 | "disabled": true 287 | } 288 | } 289 | }, 290 | "Armada": { 291 | "_Base": { 292 | "priority": { 293 | "type": "input", 294 | "value": 4.0, 295 | "option": [], 296 | "hidden": false, 297 | "help": "", 298 | "disabled": false 299 | }, 300 | "command": { 301 | "type": "input", 302 | "value": "py main.py -t armada", 303 | "option": [], 304 | "hidden": false, 305 | "help": "", 306 | "disabled": true 307 | } 308 | } 309 | } 310 | }, 311 | "Weekly": { 312 | "WeeklyReward": { 313 | "_Base": { 314 | "priority": { 315 | "type": "input", 316 | "value": 1.0, 317 | "option": [], 318 | "hidden": false, 319 | "help": "", 320 | "disabled": false 321 | }, 322 | "command": { 323 | "type": "input", 324 | "value": "py main.py -t weekly_reward", 325 | "option": [], 326 | "hidden": false, 327 | "help": "", 328 | "disabled": true 329 | } 330 | }, 331 | "WeeklyEvent": { 332 | "share": { 333 | "type": "checkbox", 334 | "value": true, 335 | "option": [], 336 | "hidden": false, 337 | "help": "", 338 | "disabled": false 339 | }, 340 | "share_time": { 341 | "type": "input", 342 | "value": 0.0, 343 | "option": [], 344 | "hidden": true, 345 | "help": "", 346 | "disabled": false 347 | }, 348 | "homo_chest": { 349 | "type": "checkbox", 350 | "value": true, 351 | "option": [], 352 | "hidden": false, 353 | "help": "", 354 | "disabled": false 355 | }, 356 | "homo_chest_time": { 357 | "type": "input", 358 | "value": 0.0, 359 | "option": [], 360 | "hidden": true, 361 | "help": "", 362 | "disabled": false 363 | }, 364 | "bp_chest": { 365 | "type": "checkbox", 366 | "value": true, 367 | "option": [], 368 | "hidden": false, 369 | "help": "", 370 | "disabled": false 371 | }, 372 | "bp_chest_time": { 373 | "type": "input", 374 | "value": 0.0, 375 | "option": [], 376 | "hidden": true, 377 | "help": "", 378 | "disabled": false 379 | }, 380 | "armada_contribution": { 381 | "type": "checkbox", 382 | "value": true, 383 | "option": [], 384 | "hidden": false, 385 | "help": "", 386 | "disabled": false 387 | }, 388 | "armada_contribution_time": { 389 | "type": "input", 390 | "value": 0.0, 391 | "option": [], 392 | "hidden": true, 393 | "help": "", 394 | "disabled": false 395 | } 396 | } 397 | } 398 | } 399 | } -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | import json 2 | from pathlib import Path 3 | from typing import Literal, List, Union 4 | 5 | from pydantic import BaseModel, Field 6 | 7 | 8 | class Item(BaseModel): 9 | """ 10 | Minimum setting 11 | """ 12 | type: Literal['input', 'select', 'checkbox', 'folder', 'file', 'priority'] = 'input' 13 | value: Union[str, bool, float] 14 | option: List[str] = [] 15 | hidden: bool = False 16 | help: str = '' 17 | disabled: bool = False 18 | 19 | model_config = { 20 | 'populate_by_name': True, 21 | } 22 | 23 | def __init__(self, value=None, **data): 24 | if value is not None and not isinstance(value, dict): 25 | data['value'] = value 26 | super().__init__(**data) 27 | 28 | 29 | class GroupCustomBase(BaseModel): 30 | """ 31 | Basic settings for every task 32 | """ 33 | # active: Item = Item(type='checkbox', value=True) 34 | priority: Item = Item(type='priority', value=0) 35 | command: Item = Item('') 36 | 37 | 38 | # 以下是实际设置内容 39 | # 任务级别 40 | class TaskGeneral(BaseModel): 41 | class GroupGeneralBase(BaseModel): 42 | """ 43 | General settings for the project 44 | """ 45 | language: Item = Item('中文') 46 | work_dir: Item = Item('./repos/HonkaiHelper', disabled=True) 47 | background: Item = Item(value=False, disabled=True) 48 | config_path: Item = Item('./repos/HonkaiHelper/config/config.json', disabled=True) 49 | log_path: Item = Item('./log', disabled=True) 50 | 51 | class GroupGame(BaseModel): 52 | game_path: Item = Item(type='file', value='') 53 | log_retain: Item = Item(type='select', value='1week', option=['1day', '3days', '1week', '1month']) 54 | keep_foreground: Item = Item(type='checkbox', value=False) 55 | 56 | Base: GroupGeneralBase = Field(GroupGeneralBase(), alias='_Base') 57 | Game: GroupGame = GroupGame() 58 | 59 | 60 | class TaskUpdate(BaseModel): 61 | class GroupUpdatelBase(BaseModel): 62 | """ 63 | General settings for the project 64 | """ 65 | env_name: Item = Item('zafkiel') 66 | python_version: Item = Item('3.11') 67 | 68 | Base: GroupUpdatelBase = Field(GroupUpdatelBase(), alias='_Base') 69 | 70 | 71 | class TaskArmada(BaseModel): 72 | Base: GroupCustomBase = Field(GroupCustomBase( 73 | command=Item('py main.py -t armada', disabled=True), priority=Item(4) 74 | ), alias='_Base') 75 | 76 | 77 | class TaskDormBonus(BaseModel): 78 | Base: GroupCustomBase = Field(GroupCustomBase( 79 | command=Item('py main.py -t dorm_bonus', disabled=True), priority=Item(5) 80 | ), alias='_Base') 81 | 82 | 83 | class TaskErrand(BaseModel): 84 | Base: GroupCustomBase = Field(GroupCustomBase( 85 | command=Item('py main.py -t errand', disabled=True), priority=Item(5) 86 | ), alias='_Base') 87 | 88 | 89 | class TaskExpedition(BaseModel): 90 | Base: GroupCustomBase = Field(GroupCustomBase( 91 | command=Item('py main.py -t expedition', disabled=True), priority=Item(5) 92 | ), alias='_Base') 93 | 94 | 95 | class TaskLogin(BaseModel): 96 | class GroupLogin(BaseModel): 97 | confirm_time: Item = Item(type='input', value=3) 98 | 99 | Base: GroupCustomBase = Field(GroupCustomBase( 100 | command=Item('py main.py -t login', disabled=True), priority=Item(value=31, disabled=True) 101 | ), alias='_Base') 102 | Login: GroupLogin = GroupLogin() 103 | 104 | 105 | class TaskLogout(BaseModel): 106 | Base: GroupCustomBase = Field(GroupCustomBase( 107 | command=Item('py main.py -t logout', disabled=True), priority=Item(value=0, disabled=True) 108 | ), alias='_Base') 109 | 110 | 111 | class TaskMail(BaseModel): 112 | Base: GroupCustomBase = Field(GroupCustomBase( 113 | command=Item('py main.py -t mail', disabled=True), priority=Item(value=4) 114 | ), alias='_Base') 115 | 116 | 117 | class TaskMission1(BaseModel): 118 | Base: GroupCustomBase = Field(GroupCustomBase( 119 | command=Item('py main.py -t mission', disabled=True), priority=Item(value=6, disabled=True) 120 | ), alias='_Base') 121 | 122 | 123 | class TaskMission2(BaseModel): 124 | Base: GroupCustomBase = Field(GroupCustomBase( 125 | command=Item('py main.py -t mission', disabled=True), priority=Item(value=2, disabled=True) 126 | ), alias='_Base') 127 | 128 | 129 | class TaskSweep(BaseModel): 130 | Base: GroupCustomBase = Field(GroupCustomBase( 131 | command=Item('py main.py -t sweep', disabled=True), priority=Item(3) 132 | ), alias='_Base') 133 | 134 | 135 | class TaskWeeklyReward(BaseModel): 136 | class GroupWeeklyEvent(BaseModel): 137 | share: Item = Item(type='checkbox', value=True) 138 | share_time: Item = Item(type='input', value=0.0, hidden=True) 139 | 140 | homo_chest: Item = Item(type='checkbox', value=True) 141 | homo_chest_time: Item = Item(type='input', value=0.0, hidden=True) 142 | 143 | bp_chest: Item = Item(type='checkbox', value=True) 144 | bp_chest_time: Item = Item(type='input', value=0.0, hidden=True) 145 | 146 | armada_contribution: Item = Item(type='checkbox', value=True) 147 | armada_contribution_time: Item = Item(type='input', value=0.0, hidden=True) 148 | 149 | Base: GroupCustomBase = Field(GroupCustomBase( 150 | command=Item('py main.py -t weekly_reward', disabled=True), priority=Item(1) 151 | ), alias='_Base') 152 | WeeklyEvent: GroupWeeklyEvent = GroupWeeklyEvent() 153 | 154 | 155 | # 任务组级别 156 | class MenuProject(BaseModel): 157 | General: TaskGeneral = TaskGeneral() 158 | Update: TaskUpdate = TaskUpdate() 159 | 160 | 161 | class MenuDaily(BaseModel): 162 | Login: TaskLogin = TaskLogin() 163 | Logout: TaskLogout = TaskLogout() 164 | Mission1: TaskMission1 = TaskMission1() 165 | Mission2: TaskMission2 = TaskMission2() 166 | Sweep: TaskSweep = TaskSweep() 167 | Mail: TaskMail = TaskMail() 168 | DormBonus: TaskDormBonus = TaskDormBonus() 169 | Expedition: TaskExpedition = TaskExpedition() 170 | Errand: TaskErrand = TaskErrand() 171 | Armada: TaskArmada = TaskArmada() 172 | 173 | 174 | class MenuWeekly(BaseModel): 175 | WeeklyReward: TaskWeeklyReward = TaskWeeklyReward() 176 | 177 | 178 | # 项目级别 179 | class UIContent(BaseModel): 180 | Project: MenuProject = MenuProject() 181 | Daily: MenuDaily = MenuDaily() 182 | Weekly: MenuWeekly = MenuWeekly() 183 | 184 | 185 | def gen_i18n(lang: str): 186 | import anyconfig 187 | 188 | trans_path = f"./config/i18n/{lang}.json" 189 | template_path = "./config/template.json" 190 | 191 | trans = { 192 | "Project": { 193 | "tasks": { 194 | "General": { 195 | "groups": {} 196 | } 197 | } 198 | } 199 | } 200 | with open(template_path, 'r', encoding='utf-8') as f: 201 | tpl = anyconfig.load(f) 202 | 203 | for menu_name, menu_conf in tpl.items(): 204 | if menu_name == "Project": 205 | if "General" in menu_conf.keys(): 206 | 207 | group_trans = trans["Project"]["tasks"]["General"]["groups"] 208 | for group_name, group_conf in menu_conf["General"].items(): 209 | if group_name == "_Base": 210 | continue 211 | group_trans[group_name] = { 212 | "name": group_name, 213 | "help": group_conf.get("_help", {}).get("value", ""), 214 | "items": {} 215 | } 216 | 217 | item_trans = group_trans[group_name]["items"] 218 | for item_name, item_conf in group_conf.items(): 219 | if item_name == "_help": 220 | continue 221 | item_trans[item_name] = { 222 | "name": item_name, 223 | "help": item_conf.get("help", ""), 224 | } 225 | for option_name in item_conf.get("option", []): 226 | item_trans[item_name].setdefault("options", {})[option_name] = option_name 227 | else: 228 | trans[menu_name] = { 229 | "name": menu_name, 230 | "tasks": {} 231 | } 232 | 233 | task_trans = trans[menu_name]["tasks"] 234 | for task_name, task_conf in menu_conf.items(): 235 | task_trans[task_name] = { 236 | "name": task_name, 237 | "groups": {} 238 | } 239 | 240 | group_trans = task_trans[task_name]["groups"] 241 | for group_name, group_conf in task_conf.items(): 242 | if group_name == "_Base": 243 | continue 244 | group_trans[group_name] = { 245 | "name": group_name, 246 | "help": group_conf.get("_help", {}).get("value", ""), 247 | "items": {} 248 | } 249 | 250 | item_trans = group_trans[group_name]["items"] 251 | for item_name, item_conf in group_conf.items(): 252 | if item_name == "_help": 253 | continue 254 | item_trans[item_name] = { 255 | "name": item_name, 256 | "help": item_conf.get("help", "") 257 | } 258 | for option_name in item_conf.get("option", []): 259 | item_trans[item_name].setdefault("options", {})[option_name] = option_name 260 | 261 | if Path(trans_path).exists(): 262 | with open(trans_path, 'r', encoding='utf-8') as f: 263 | old_trans = anyconfig.load(f) 264 | anyconfig.merge(trans, old_trans) 265 | 266 | with open(trans_path, 'w', encoding='utf-8') as f: 267 | anyconfig.dump(trans, f, ensure_ascii=False, indent=2, allow_unicode=True) 268 | 269 | 270 | 271 | def export() -> None: 272 | args = UIContent() 273 | with open('config/template.json', 'w', encoding='utf-8') as f: 274 | f.write(args.model_dump_json(indent=2, by_alias=True)) 275 | 276 | 277 | class Config: 278 | def __init__(self, config_path): 279 | self.config_path = config_path 280 | with open('config/template.json', 'r', encoding='utf-8') as f: 281 | args = json.load(f) 282 | with open(config_path, 'r', encoding='utf-8') as f: 283 | self.data = json.load(f) 284 | 285 | # 只是为了校验数据 286 | for menu, tasks in args.items(): 287 | for task, groups in tasks.items(): 288 | for group, items in groups.items(): 289 | if group == '_Base': 290 | continue 291 | for item, info in items.items(): 292 | info['value'] = self.data[menu][task][group][item] 293 | UIContent.model_validate(args) 294 | 295 | def update(self, menu, task, group, item, value): 296 | self.data[menu][task][group][item] = value 297 | with open(self.config_path, 'w') as f: 298 | json.dump(self.data, f, ensure_ascii=False, indent=2) 299 | 300 | 301 | if __name__ == '__main__': 302 | export() 303 | gen_i18n('中文') 304 | --------------------------------------------------------------------------------