diff --git a/MCE Manager.py b/MCE Manager.py index efec62e..cbb71e0 100644 --- a/MCE Manager.py +++ b/MCE Manager.py @@ -8,6 +8,7 @@ from MCE.custom_widgets.ctk_timeentry import CTkTimeEntry from MCE.custom_widgets.ctk_integerspinbox import CTkIntegerSpinbox from MCE.custom_widgets.ctk_templatedialog import CTkTemplateDialog from MCE.custom_widgets.ctk_notification import CTkNotification +from MCE.custom_widgets.ctk_add_button import CTkAddButton from MCE.utils import Linker, Config from filelock import FileLock, Timeout import threading @@ -117,7 +118,7 @@ class MCE_Manager(customtkinter.CTk): # Helper method to create Mission Tabview with Template and Queue Tabs def create_mission_tabview(self): - self.mission_tabview = customtkinter.CTkTabview(self, height=500) + self.mission_tabview = customtkinter.CTkTabview(self) self.mission_tabview.grid(row=17, column=0, columnspan=3, padx=20) self.tab_template = self.mission_tabview.add('Template') @@ -134,11 +135,11 @@ class MCE_Manager(customtkinter.CTk): self.template_labels.grid(row=0, column=0, sticky="ew") self.mode_label = customtkinter.CTkLabel(self.template_labels, text="Mode:", font=customtkinter.CTkFont(underline=True)) - self.mode_tooltip = CTkToolTip(self.mode_label, message="N:Mission Normal\nH:Mission Hard\nE:Event Quest\nBD:Commissions EXP\nIR:Commissions Credits\n") + self.mode_tooltip = CTkToolTip(self.mode_label, message="N : Mission Normal\nH : Mission Hard\nE : Event Quest\nXP : Commissions EXP\nCR : Commissions Credits\n", justify=tk.LEFT) self.mode_label.grid(row=1, column=0, padx=(130, 0), pady=5) self.stage_label = customtkinter.CTkLabel(self.template_labels, text="Stage:", font=customtkinter.CTkFont(underline=True)) - self.stage_tooltip = CTkToolTip(self.stage_label, message="Valid format for Mission: 1-1\nValid format for Commissions/Event: 01") + self.stage_tooltip = CTkToolTip(self.stage_label, message="Valid format\nMission: 1-1, 3-A\nCommissions & Event: 01", justify=tk.LEFT) self.stage_label.grid(row=1, column=1, padx=(40, 20), pady=5) self.run_times_label = customtkinter.CTkLabel(self.template_labels, text="Number of Sweeps:", font=customtkinter.CTkFont(underline=True)) @@ -151,7 +152,8 @@ class MCE_Manager(customtkinter.CTk): self.highlight_label = customtkinter.CTkLabel(self.template_buttons_frame, text="*You can double click an entry and press up or down arrow to change its position", font=customtkinter.CTkFont(family="Inter", size=12)) self.highlight_label.grid(row=0, column=0, columnspan=3) - self.add_button = customtkinter.CTkButton(self.template_buttons_frame , text="Add", command=lambda queue=queue: self.add_frame(queue=queue)) + self.add_button = CTkAddButton(master=self.template_buttons_frame) + self.add_button.button.configure(command=lambda queue=queue, button=self.add_button.button: self.add_frame(queue=queue, button=button)) self.add_button.grid(row=1, column=0, padx=5, pady=5) # Clear button to clear all frames @@ -166,10 +168,10 @@ class MCE_Manager(customtkinter.CTk): # Helper method to create Template Frame and Queue Frame def create_template_and_queue_frames(self): - self.template_frame = customtkinter.CTkScrollableFrame(self.tab_template, width=400, height=350) + self.template_frame = customtkinter.CTkScrollableFrame(self.tab_template, width=435, height=350) self.template_frame.grid(row=1, column=0, sticky="nsew") - self.queue_frame = customtkinter.CTkScrollableFrame(self.tab_queue, width=400, height=350) + self.queue_frame = customtkinter.CTkScrollableFrame(self.tab_queue, width=435, height=350) self.queue_frame.grid(row=1, column=0, sticky="nsew") # Helper method to create Lists to Store Frame Widgets @@ -211,7 +213,7 @@ class MCE_Manager(customtkinter.CTk): self.template_optionmenu.set(self.previous_selected) return elif template_name in self.templates_list: - CTkMessagebox(title="Error", message="Name is invalid.", icon="cancel") + CTkMessagebox(title="Error", message="Name is invalid.", icon="MCE\icons\cancel.png") self.template_optionmenu.set(self.previous_selected) return else: @@ -232,7 +234,7 @@ class MCE_Manager(customtkinter.CTk): def delete_template(self): msg = CTkMessagebox(title="Template Deletetion", message=f"Are you sure you want to delete Template {self.previous_selected}?", - icon="question", option_1="No", option_2="Yes") + icon="MCE\icons\question.png", option_1="No", option_2="Yes") response = msg.get() if response=="Yes": if len(self.templates) != 1: @@ -250,18 +252,19 @@ class MCE_Manager(customtkinter.CTk): self.template_optionmenu.configure(values=self.templates_list) self.template_optionmenu.set(self.preferred_template) else: - CTkMessagebox(title="Error", message="At least one template must exist!!!", icon="cancel") + CTkMessagebox(title="Error", message="At least one template must exist!!!", icon="MCE\icons\cancel.png") return # Function to add a frame with widgets - def add_frame(self, inner_list=None, queue=False, state="normal"): + def add_frame(self, inner_list=None, queue=False, state="normal", button=None): + position = button.cget("text") if button else "Add Down" frames = self.queue_frames if queue else self.template_frames parent_frame = self.queue_frame if queue else self.template_frame row_index = len(frames) + 1 # Calculate the row for the new frame # Create a frame frame = tk.Frame(parent_frame, bg="gray17") frame.grid(row=row_index, column=0, columnspan=4, padx=10, pady=10, sticky="w") - frames.append(frame) + frames.append(frame) if position == "Add Down" else frames.insert(0, frame) # "Up" button to move the frame up up_button = customtkinter.CTkButton(frame, text="Up", width=5, command=lambda f=frame, queue=queue: self.move_frame_up(f, queue), state=state) up_button.grid(row=0, column=0, padx=5, pady=5, sticky="w") @@ -269,7 +272,7 @@ class MCE_Manager(customtkinter.CTk): down_button = customtkinter.CTkButton(frame, text="Down", width=5, command=lambda f=frame, queue=queue: self.move_frame_down(f, queue), state=state) down_button.grid(row=0, column=1, padx=5, pady=5, sticky="w") # Dropdown menu for mode - mode_optionmenu = customtkinter.CTkOptionMenu(frame, width=60, values=["N", "H", "E", "BD", "IR"], state=state) + mode_optionmenu = customtkinter.CTkOptionMenu(frame, width=60, values=["N", "H", "E", "XP", "CR"], state=state) mode_optionmenu.set(inner_list[0] if inner_list else "N") mode_optionmenu.grid(row=0, column=2, padx=5, pady=5, sticky="w") # Entry widget for stage @@ -288,7 +291,9 @@ class MCE_Manager(customtkinter.CTk): delete_button = customtkinter.CTkButton(frame, text="Delete", width=5, command=lambda f=frame, queue=queue: self.delete_frame(f, queue), state=state) delete_button.grid(row=0, column=5, padx=5, pady=5, sticky="w") - frame.bind("", lambda event, f=frame: self.highlight_frame(f)) + frame.bind("", lambda event, f=frame: self.highlight_frame(f)) + if position == "Add Up": + self.update_frame_positions(queue=queue) # Function to clear all frames def clear_frames(self, queue=False): @@ -306,7 +311,7 @@ class MCE_Manager(customtkinter.CTk): mode_optionmenu = frame.winfo_children()[2] stage_entry = frame.winfo_children()[3] if not self.check_entry(mode_optionmenu, stage_entry): - CTkMessagebox(title="Error", message="Configuration not saved. Some entries are incomplete or have incorect input.", icon="cancel") + CTkMessagebox(title="Error", message="Configuration not saved. Some entries are incomplete or have incorect input.", icon="MCE\icons\cancel.png") return mode = frame.winfo_children()[2].get() stage = frame.winfo_children()[3].get().strip() diff --git a/MCE/custom_widgets/ctk_add_button.py b/MCE/custom_widgets/ctk_add_button.py new file mode 100644 index 0000000..f589ea8 --- /dev/null +++ b/MCE/custom_widgets/ctk_add_button.py @@ -0,0 +1,19 @@ +import customtkinter + +class CTkAddButton(customtkinter.CTkFrame): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.button = customtkinter.CTkButton(self, text="Add Down", corner_radius=0, width=120) + self.button.grid(row=0, column=0) + self.option_menu = customtkinter.CTkOptionMenu( + self, values= ["Add Up", "Add Down"], width=10, command=self.set_button, corner_radius=0 + ) + self.option_menu.set("") + self.option_menu.grid(row=0, column=1) + + def set_button(self, value): + self.option_menu.set("") + self.button.configure(text=value) + + def configure(self, *args, **kwargs): + self.button.configure(*args, **kwargs) \ No newline at end of file diff --git a/MCE/custom_widgets/icons/cancel.png b/MCE/icons/cancel.png similarity index 100% rename from MCE/custom_widgets/icons/cancel.png rename to MCE/icons/cancel.png diff --git a/MCE/custom_widgets/icons/check.png b/MCE/icons/check.png similarity index 100% rename from MCE/custom_widgets/icons/check.png rename to MCE/icons/check.png diff --git a/MCE/custom_widgets/icons/info.png b/MCE/icons/info.png similarity index 100% rename from MCE/custom_widgets/icons/info.png rename to MCE/icons/info.png diff --git a/MCE/custom_widgets/icons/question.png b/MCE/icons/question.png similarity index 100% rename from MCE/custom_widgets/icons/question.png rename to MCE/icons/question.png diff --git a/MCE/custom_widgets/icons/warning.png b/MCE/icons/warning.png similarity index 100% rename from MCE/custom_widgets/icons/warning.png rename to MCE/icons/warning.png diff --git a/aas.py b/aas.py index e95cd3e..1069bb5 100644 --- a/aas.py +++ b/aas.py @@ -62,6 +62,10 @@ class ArisuAutoSweeper(AzurLaneAutoScript): from tasks.mission.mission import Mission Mission(config=self.config, device=self.device).run() + def schedule(self): + from tasks.schedule.schedule import Schedule + Schedule(config=self.config, device=self.device).run() + def data_update(self): from tasks.item.data_update import DataUpdate DataUpdate(config=self.config, device=self.device).run() diff --git a/assets/en/base/popup/LEVEL_UP.BUTTON.png b/assets/en/base/popup/LEVEL_UP.BUTTON.png new file mode 100644 index 0000000..a8e8b85 Binary files /dev/null and b/assets/en/base/popup/LEVEL_UP.BUTTON.png differ diff --git a/assets/en/base/popup/LEVEL_UP.png b/assets/en/base/popup/LEVEL_UP.png new file mode 100644 index 0000000..19ded3d Binary files /dev/null and b/assets/en/base/popup/LEVEL_UP.png differ diff --git a/assets/en/base/popup/LOCATION_LEVEL_UP.BUTTON.png b/assets/en/base/popup/LOCATION_LEVEL_UP.BUTTON.png new file mode 100644 index 0000000..a9f6b33 Binary files /dev/null and b/assets/en/base/popup/LOCATION_LEVEL_UP.BUTTON.png differ diff --git a/assets/en/base/popup/LOCATION_LEVEL_UP.png b/assets/en/base/popup/LOCATION_LEVEL_UP.png new file mode 100644 index 0000000..cee4301 Binary files /dev/null and b/assets/en/base/popup/LOCATION_LEVEL_UP.png differ diff --git a/assets/en/base/popup/QUIT.BUTTON.png b/assets/en/base/popup/QUIT.BUTTON.png new file mode 100644 index 0000000..c1d211f Binary files /dev/null and b/assets/en/base/popup/QUIT.BUTTON.png differ diff --git a/assets/en/base/popup/QUIT.png b/assets/en/base/popup/QUIT.png new file mode 100644 index 0000000..effffef Binary files /dev/null and b/assets/en/base/popup/QUIT.png differ diff --git a/assets/en/login/OCR_YEAR.png b/assets/en/login/OCR_YEAR.png new file mode 100644 index 0000000..4db7b6f Binary files /dev/null and b/assets/en/login/OCR_YEAR.png differ diff --git a/assets/en/mission/CHECK_IR.png b/assets/en/mission/CHECK_CR.png similarity index 100% rename from assets/en/mission/CHECK_IR.png rename to assets/en/mission/CHECK_CR.png diff --git a/assets/en/mission/CHECK_BD.png b/assets/en/mission/CHECK_XP.png similarity index 100% rename from assets/en/mission/CHECK_BD.png rename to assets/en/mission/CHECK_XP.png diff --git a/assets/en/mission/EVENT_INDEX.png b/assets/en/mission/EVENT_INDEX.png new file mode 100644 index 0000000..104fbc4 Binary files /dev/null and b/assets/en/mission/EVENT_INDEX.png differ diff --git a/assets/en/mission/EVENT_ITEM.png b/assets/en/mission/EVENT_ITEM.png new file mode 100644 index 0000000..2f2a2a7 Binary files /dev/null and b/assets/en/mission/EVENT_ITEM.png differ diff --git a/assets/en/mission/EVENT_LIST.png b/assets/en/mission/EVENT_LIST.png new file mode 100644 index 0000000..a3eb22d Binary files /dev/null and b/assets/en/mission/EVENT_LIST.png differ diff --git a/assets/en/mission/EVENT_STARS.png b/assets/en/mission/EVENT_STARS.png new file mode 100644 index 0000000..bdc774b Binary files /dev/null and b/assets/en/mission/EVENT_STARS.png differ diff --git a/assets/en/mission/SELECT_IR.png b/assets/en/mission/SELECT_CR.png similarity index 100% rename from assets/en/mission/SELECT_IR.png rename to assets/en/mission/SELECT_CR.png diff --git a/assets/en/mission/SELECT_BD.png b/assets/en/mission/SELECT_XP.png similarity index 100% rename from assets/en/mission/SELECT_BD.png rename to assets/en/mission/SELECT_XP.png diff --git a/assets/en/momotalk/CHATTING.png b/assets/en/momotalk/CHATTING.png new file mode 100644 index 0000000..3908b0a Binary files /dev/null and b/assets/en/momotalk/CHATTING.png differ diff --git a/assets/en/schedule/CONFIRM.png b/assets/en/schedule/CONFIRM.png new file mode 100644 index 0000000..6fa6985 Binary files /dev/null and b/assets/en/schedule/CONFIRM.png differ diff --git a/assets/en/schedule/FIRST_ITEM.png b/assets/en/schedule/FIRST_ITEM.png new file mode 100644 index 0000000..6de565e Binary files /dev/null and b/assets/en/schedule/FIRST_ITEM.png differ diff --git a/assets/en/schedule/LOCATIONS.png b/assets/en/schedule/LOCATIONS.png new file mode 100644 index 0000000..fe96764 Binary files /dev/null and b/assets/en/schedule/LOCATIONS.png differ diff --git a/assets/en/schedule/LOCATIONS_POPUP.png b/assets/en/schedule/LOCATIONS_POPUP.png new file mode 100644 index 0000000..199c52b Binary files /dev/null and b/assets/en/schedule/LOCATIONS_POPUP.png differ diff --git a/assets/en/schedule/OCR_TICKET.png b/assets/en/schedule/OCR_TICKET.png new file mode 100644 index 0000000..2b29ef4 Binary files /dev/null and b/assets/en/schedule/OCR_TICKET.png differ diff --git a/assets/en/schedule/START_LESSON.png b/assets/en/schedule/START_LESSON.png new file mode 100644 index 0000000..ff064d4 Binary files /dev/null and b/assets/en/schedule/START_LESSON.png differ diff --git a/assets/zht/base/page/ACCOUNT_INFO_CHECK.png b/assets/zht/base/page/ACCOUNT_INFO_CHECK.png new file mode 100644 index 0000000..d6ba78c Binary files /dev/null and b/assets/zht/base/page/ACCOUNT_INFO_CHECK.png differ diff --git a/assets/zht/base/page/BOUNTY_CHECK.png b/assets/zht/base/page/BOUNTY_CHECK.png new file mode 100644 index 0000000..13bf61c Binary files /dev/null and b/assets/zht/base/page/BOUNTY_CHECK.png differ diff --git a/assets/zht/base/page/CAFE_CHECK.png b/assets/zht/base/page/CAFE_CHECK.png new file mode 100644 index 0000000..d561b42 Binary files /dev/null and b/assets/zht/base/page/CAFE_CHECK.png differ diff --git a/assets/zht/base/page/CIRCLE_CHECK.png b/assets/zht/base/page/CIRCLE_CHECK.png new file mode 100644 index 0000000..6f460a7 Binary files /dev/null and b/assets/zht/base/page/CIRCLE_CHECK.png differ diff --git a/assets/zht/base/page/COMMISSIONS_CHECK.png b/assets/zht/base/page/COMMISSIONS_CHECK.png new file mode 100644 index 0000000..f12170d Binary files /dev/null and b/assets/zht/base/page/COMMISSIONS_CHECK.png differ diff --git a/assets/zht/base/page/CRAFTING_CHECK.png b/assets/zht/base/page/CRAFTING_CHECK.png new file mode 100644 index 0000000..5b569e7 Binary files /dev/null and b/assets/zht/base/page/CRAFTING_CHECK.png differ diff --git a/assets/zht/base/page/EVENT_CHECK.png b/assets/zht/base/page/EVENT_CHECK.png new file mode 100644 index 0000000..d7c1550 Binary files /dev/null and b/assets/zht/base/page/EVENT_CHECK.png differ diff --git a/assets/zht/base/page/GACHA_CHECK.png b/assets/zht/base/page/GACHA_CHECK.png new file mode 100644 index 0000000..b3a3854 Binary files /dev/null and b/assets/zht/base/page/GACHA_CHECK.png differ diff --git a/assets/zht/base/page/MAIL_CHECK.png b/assets/zht/base/page/MAIL_CHECK.png new file mode 100644 index 0000000..bcdfb20 Binary files /dev/null and b/assets/zht/base/page/MAIL_CHECK.png differ diff --git a/assets/zht/base/page/MAIN_GO_TO_WORK.png b/assets/zht/base/page/MAIN_GO_TO_WORK.png new file mode 100644 index 0000000..6c54b11 Binary files /dev/null and b/assets/zht/base/page/MAIN_GO_TO_WORK.png differ diff --git a/assets/zht/base/page/MISSION_CHECK.png b/assets/zht/base/page/MISSION_CHECK.png new file mode 100644 index 0000000..def2658 Binary files /dev/null and b/assets/zht/base/page/MISSION_CHECK.png differ diff --git a/assets/zht/base/page/SCHEDULE_CHECK.png b/assets/zht/base/page/SCHEDULE_CHECK.png new file mode 100644 index 0000000..ee7e560 Binary files /dev/null and b/assets/zht/base/page/SCHEDULE_CHECK.png differ diff --git a/assets/zht/base/page/SCHOOL_EXCHANGE_CHECK.png b/assets/zht/base/page/SCHOOL_EXCHANGE_CHECK.png new file mode 100644 index 0000000..945a696 Binary files /dev/null and b/assets/zht/base/page/SCHOOL_EXCHANGE_CHECK.png differ diff --git a/assets/zht/base/page/SHOP_CHECK.png b/assets/zht/base/page/SHOP_CHECK.png new file mode 100644 index 0000000..c9c64a3 Binary files /dev/null and b/assets/zht/base/page/SHOP_CHECK.png differ diff --git a/assets/zht/base/page/STORY_CHECK.png b/assets/zht/base/page/STORY_CHECK.png new file mode 100644 index 0000000..e832cbf Binary files /dev/null and b/assets/zht/base/page/STORY_CHECK.png differ diff --git a/assets/zht/base/page/TACTICAL_CHALLENGE_CHECK.png b/assets/zht/base/page/TACTICAL_CHALLENGE_CHECK.png new file mode 100644 index 0000000..33bae5e Binary files /dev/null and b/assets/zht/base/page/TACTICAL_CHALLENGE_CHECK.png differ diff --git a/assets/zht/base/page/TASK_CHECK.png b/assets/zht/base/page/TASK_CHECK.png new file mode 100644 index 0000000..d76313c Binary files /dev/null and b/assets/zht/base/page/TASK_CHECK.png differ diff --git a/assets/zht/base/page/WORK_CHECK.png b/assets/zht/base/page/WORK_CHECK.png new file mode 100644 index 0000000..68281b7 Binary files /dev/null and b/assets/zht/base/page/WORK_CHECK.png differ diff --git a/assets/zht/base/page/WORK_GO_TO_BOUNTY.png b/assets/zht/base/page/WORK_GO_TO_BOUNTY.png new file mode 100644 index 0000000..68281b7 Binary files /dev/null and b/assets/zht/base/page/WORK_GO_TO_BOUNTY.png differ diff --git a/assets/zht/base/page/WORK_GO_TO_COMMISSIONS.png b/assets/zht/base/page/WORK_GO_TO_COMMISSIONS.png new file mode 100644 index 0000000..b5c9958 Binary files /dev/null and b/assets/zht/base/page/WORK_GO_TO_COMMISSIONS.png differ diff --git a/assets/zht/base/page/WORK_GO_TO_EVENT.png b/assets/zht/base/page/WORK_GO_TO_EVENT.png new file mode 100644 index 0000000..ac912f7 Binary files /dev/null and b/assets/zht/base/page/WORK_GO_TO_EVENT.png differ diff --git a/assets/zht/base/page/WORK_GO_TO_MISSION.png b/assets/zht/base/page/WORK_GO_TO_MISSION.png new file mode 100644 index 0000000..c6da7db Binary files /dev/null and b/assets/zht/base/page/WORK_GO_TO_MISSION.png differ diff --git a/assets/zht/base/page/WORK_GO_TO_SCHOOL_EXCHANGE.png b/assets/zht/base/page/WORK_GO_TO_SCHOOL_EXCHANGE.png new file mode 100644 index 0000000..d5c22ae Binary files /dev/null and b/assets/zht/base/page/WORK_GO_TO_SCHOOL_EXCHANGE.png differ diff --git a/assets/zht/base/page/WORK_GO_TO_STORY.png b/assets/zht/base/page/WORK_GO_TO_STORY.png new file mode 100644 index 0000000..5df0147 Binary files /dev/null and b/assets/zht/base/page/WORK_GO_TO_STORY.png differ diff --git a/assets/zht/base/page/WORK_GO_TO_TACTICAL_CHALLENGE.png b/assets/zht/base/page/WORK_GO_TO_TACTICAL_CHALLENGE.png new file mode 100644 index 0000000..4f50670 Binary files /dev/null and b/assets/zht/base/page/WORK_GO_TO_TACTICAL_CHALLENGE.png differ diff --git a/assets/zht/base/popup/AFFECTION_LEVEL_UP.BUTTON.png b/assets/zht/base/popup/AFFECTION_LEVEL_UP.BUTTON.png new file mode 100644 index 0000000..a331e9a Binary files /dev/null and b/assets/zht/base/popup/AFFECTION_LEVEL_UP.BUTTON.png differ diff --git a/assets/zht/base/popup/AFFECTION_LEVEL_UP.png b/assets/zht/base/popup/AFFECTION_LEVEL_UP.png new file mode 100644 index 0000000..bb3d614 Binary files /dev/null and b/assets/zht/base/popup/AFFECTION_LEVEL_UP.png differ diff --git a/assets/zht/base/popup/AP_EXCEED.BUTTON.png b/assets/zht/base/popup/AP_EXCEED.BUTTON.png new file mode 100644 index 0000000..b8c04af Binary files /dev/null and b/assets/zht/base/popup/AP_EXCEED.BUTTON.png differ diff --git a/assets/zht/base/popup/AP_EXCEED.png b/assets/zht/base/popup/AP_EXCEED.png new file mode 100644 index 0000000..5686706 Binary files /dev/null and b/assets/zht/base/popup/AP_EXCEED.png differ diff --git a/assets/zht/base/popup/GET_REWARD.BUTTON.png b/assets/zht/base/popup/GET_REWARD.BUTTON.png new file mode 100644 index 0000000..163e9c0 Binary files /dev/null and b/assets/zht/base/popup/GET_REWARD.BUTTON.png differ diff --git a/assets/zht/base/popup/GET_REWARD.png b/assets/zht/base/popup/GET_REWARD.png new file mode 100644 index 0000000..ba1ee07 Binary files /dev/null and b/assets/zht/base/popup/GET_REWARD.png differ diff --git a/assets/zht/base/popup/GET_REWARD_SKIP.png b/assets/zht/base/popup/GET_REWARD_SKIP.png new file mode 100644 index 0000000..abfdfed Binary files /dev/null and b/assets/zht/base/popup/GET_REWARD_SKIP.png differ diff --git a/assets/zht/base/popup/INSUFFICIENT_INVENTORY.BUTTON.png b/assets/zht/base/popup/INSUFFICIENT_INVENTORY.BUTTON.png new file mode 100644 index 0000000..1379d3c Binary files /dev/null and b/assets/zht/base/popup/INSUFFICIENT_INVENTORY.BUTTON.png differ diff --git a/assets/zht/base/popup/INSUFFICIENT_INVENTORY.png b/assets/zht/base/popup/INSUFFICIENT_INVENTORY.png new file mode 100644 index 0000000..c268a02 Binary files /dev/null and b/assets/zht/base/popup/INSUFFICIENT_INVENTORY.png differ diff --git a/assets/zht/base/popup/ITEM_EXPIRED.BUTTON.png b/assets/zht/base/popup/ITEM_EXPIRED.BUTTON.png new file mode 100644 index 0000000..40a515d Binary files /dev/null and b/assets/zht/base/popup/ITEM_EXPIRED.BUTTON.png differ diff --git a/assets/zht/base/popup/ITEM_EXPIRED.png b/assets/zht/base/popup/ITEM_EXPIRED.png new file mode 100644 index 0000000..53841f9 Binary files /dev/null and b/assets/zht/base/popup/ITEM_EXPIRED.png differ diff --git a/assets/zht/base/popup/LEVEL_UP.BUTTON.png b/assets/zht/base/popup/LEVEL_UP.BUTTON.png new file mode 100644 index 0000000..a8e8b85 Binary files /dev/null and b/assets/zht/base/popup/LEVEL_UP.BUTTON.png differ diff --git a/assets/zht/base/popup/LEVEL_UP.png b/assets/zht/base/popup/LEVEL_UP.png new file mode 100644 index 0000000..19ded3d Binary files /dev/null and b/assets/zht/base/popup/LEVEL_UP.png differ diff --git a/assets/zht/base/popup/LOCATION_LEVEL_UP.BUTTON.png b/assets/zht/base/popup/LOCATION_LEVEL_UP.BUTTON.png new file mode 100644 index 0000000..cd14bc8 Binary files /dev/null and b/assets/zht/base/popup/LOCATION_LEVEL_UP.BUTTON.png differ diff --git a/assets/zht/base/popup/LOCATION_LEVEL_UP.png b/assets/zht/base/popup/LOCATION_LEVEL_UP.png new file mode 100644 index 0000000..9ff58c4 Binary files /dev/null and b/assets/zht/base/popup/LOCATION_LEVEL_UP.png differ diff --git a/assets/zht/base/popup/NETWORK_RECONNECT.BUTTON.png b/assets/zht/base/popup/NETWORK_RECONNECT.BUTTON.png new file mode 100644 index 0000000..de4c8e9 Binary files /dev/null and b/assets/zht/base/popup/NETWORK_RECONNECT.BUTTON.png differ diff --git a/assets/zht/base/popup/NETWORK_RECONNECT.png b/assets/zht/base/popup/NETWORK_RECONNECT.png new file mode 100644 index 0000000..afbd04a Binary files /dev/null and b/assets/zht/base/popup/NETWORK_RECONNECT.png differ diff --git a/assets/zht/base/popup/NETWORK_RECONNECT_OK.BUTTON.png b/assets/zht/base/popup/NETWORK_RECONNECT_OK.BUTTON.png new file mode 100644 index 0000000..dcb56e4 Binary files /dev/null and b/assets/zht/base/popup/NETWORK_RECONNECT_OK.BUTTON.png differ diff --git a/assets/zht/base/popup/NETWORK_RECONNECT_OK.png b/assets/zht/base/popup/NETWORK_RECONNECT_OK.png new file mode 100644 index 0000000..df19d4d Binary files /dev/null and b/assets/zht/base/popup/NETWORK_RECONNECT_OK.png differ diff --git a/assets/zht/base/popup/QUIT.BUTTON.png b/assets/zht/base/popup/QUIT.BUTTON.png new file mode 100644 index 0000000..8cc11c4 Binary files /dev/null and b/assets/zht/base/popup/QUIT.BUTTON.png differ diff --git a/assets/zht/base/popup/QUIT.png b/assets/zht/base/popup/QUIT.png new file mode 100644 index 0000000..fd74e66 Binary files /dev/null and b/assets/zht/base/popup/QUIT.png differ diff --git a/assets/zht/bounty/CHECK_BOUNTY.png b/assets/zht/bounty/CHECK_BOUNTY.png new file mode 100644 index 0000000..9c714bb Binary files /dev/null and b/assets/zht/bounty/CHECK_BOUNTY.png differ diff --git a/assets/zht/bounty/CHECK_DESERT_RAILROAD.png b/assets/zht/bounty/CHECK_DESERT_RAILROAD.png new file mode 100644 index 0000000..e6d745d Binary files /dev/null and b/assets/zht/bounty/CHECK_DESERT_RAILROAD.png differ diff --git a/assets/zht/bounty/CHECK_HIGHWAY.png b/assets/zht/bounty/CHECK_HIGHWAY.png new file mode 100644 index 0000000..8e41f7d Binary files /dev/null and b/assets/zht/bounty/CHECK_HIGHWAY.png differ diff --git a/assets/zht/bounty/CHECK_SCHOOLHOUSE.png b/assets/zht/bounty/CHECK_SCHOOLHOUSE.png new file mode 100644 index 0000000..6c8917b Binary files /dev/null and b/assets/zht/bounty/CHECK_SCHOOLHOUSE.png differ diff --git a/assets/zht/bounty/OCR_TICKET.png b/assets/zht/bounty/OCR_TICKET.png new file mode 100644 index 0000000..4381905 Binary files /dev/null and b/assets/zht/bounty/OCR_TICKET.png differ diff --git a/assets/zht/bounty/SELECT_DESERT_RAILROAD.png b/assets/zht/bounty/SELECT_DESERT_RAILROAD.png new file mode 100644 index 0000000..13ea8c0 Binary files /dev/null and b/assets/zht/bounty/SELECT_DESERT_RAILROAD.png differ diff --git a/assets/zht/bounty/SELECT_HIGHWAY.png b/assets/zht/bounty/SELECT_HIGHWAY.png new file mode 100644 index 0000000..fc47324 Binary files /dev/null and b/assets/zht/bounty/SELECT_HIGHWAY.png differ diff --git a/assets/zht/bounty/SELECT_SCHOOLHOUSE.png b/assets/zht/bounty/SELECT_SCHOOLHOUSE.png new file mode 100644 index 0000000..9cd6bac Binary files /dev/null and b/assets/zht/bounty/SELECT_SCHOOLHOUSE.png differ diff --git a/assets/zht/cafe/CAFE_FIRST.png b/assets/zht/cafe/CAFE_FIRST.png new file mode 100644 index 0000000..a57fd71 Binary files /dev/null and b/assets/zht/cafe/CAFE_FIRST.png differ diff --git a/assets/zht/cafe/CAFE_INVITE.png b/assets/zht/cafe/CAFE_INVITE.png new file mode 100644 index 0000000..95ae99c Binary files /dev/null and b/assets/zht/cafe/CAFE_INVITE.png differ diff --git a/assets/zht/cafe/CAFE_INVITED.png b/assets/zht/cafe/CAFE_INVITED.png new file mode 100644 index 0000000..2a90265 Binary files /dev/null and b/assets/zht/cafe/CAFE_INVITED.png differ diff --git a/assets/zht/cafe/CAFE_SECOND.png b/assets/zht/cafe/CAFE_SECOND.png new file mode 100644 index 0000000..34bfc7b Binary files /dev/null and b/assets/zht/cafe/CAFE_SECOND.png differ diff --git a/assets/zht/cafe/CHANGE_CAFE_NOT_SELECTED.png b/assets/zht/cafe/CHANGE_CAFE_NOT_SELECTED.png new file mode 100644 index 0000000..4e976d7 Binary files /dev/null and b/assets/zht/cafe/CHANGE_CAFE_NOT_SELECTED.png differ diff --git a/assets/zht/cafe/CHANGE_CAFE_SELECTED.png b/assets/zht/cafe/CHANGE_CAFE_SELECTED.png new file mode 100644 index 0000000..ab5b185 Binary files /dev/null and b/assets/zht/cafe/CHANGE_CAFE_SELECTED.png differ diff --git a/assets/zht/cafe/CHECK_MOMOTALK.png b/assets/zht/cafe/CHECK_MOMOTALK.png new file mode 100644 index 0000000..9c047b8 Binary files /dev/null and b/assets/zht/cafe/CHECK_MOMOTALK.png differ diff --git a/assets/zht/cafe/CHECK_REWARD.BUTTON.png b/assets/zht/cafe/CHECK_REWARD.BUTTON.png new file mode 100644 index 0000000..15bdd00 Binary files /dev/null and b/assets/zht/cafe/CHECK_REWARD.BUTTON.png differ diff --git a/assets/zht/cafe/CHECK_REWARD.png b/assets/zht/cafe/CHECK_REWARD.png new file mode 100644 index 0000000..d602817 Binary files /dev/null and b/assets/zht/cafe/CHECK_REWARD.png differ diff --git a/assets/zht/cafe/GET_REWARD.BUTTON.png b/assets/zht/cafe/GET_REWARD.BUTTON.png new file mode 100644 index 0000000..a5ad561 Binary files /dev/null and b/assets/zht/cafe/GET_REWARD.BUTTON.png differ diff --git a/assets/zht/cafe/GET_REWARD.png b/assets/zht/cafe/GET_REWARD.png new file mode 100644 index 0000000..9b27d18 Binary files /dev/null and b/assets/zht/cafe/GET_REWARD.png differ diff --git a/assets/zht/cafe/GET_REWARD_CLOSE.png b/assets/zht/cafe/GET_REWARD_CLOSE.png new file mode 100644 index 0000000..71d457f Binary files /dev/null and b/assets/zht/cafe/GET_REWARD_CLOSE.png differ diff --git a/assets/zht/cafe/GOT_REWARD.png b/assets/zht/cafe/GOT_REWARD.png new file mode 100644 index 0000000..752e9a2 Binary files /dev/null and b/assets/zht/cafe/GOT_REWARD.png differ diff --git a/assets/zht/cafe/INVENTORY.BUTTON.png b/assets/zht/cafe/INVENTORY.BUTTON.png new file mode 100644 index 0000000..9b2c86a Binary files /dev/null and b/assets/zht/cafe/INVENTORY.BUTTON.png differ diff --git a/assets/zht/cafe/INVENTORY.png b/assets/zht/cafe/INVENTORY.png new file mode 100644 index 0000000..589ad34 Binary files /dev/null and b/assets/zht/cafe/INVENTORY.png differ diff --git a/assets/zht/cafe/INVITE_CONFIRM.BUTTON.png b/assets/zht/cafe/INVITE_CONFIRM.BUTTON.png new file mode 100644 index 0000000..6a97528 Binary files /dev/null and b/assets/zht/cafe/INVITE_CONFIRM.BUTTON.png differ diff --git a/assets/zht/cafe/INVITE_CONFIRM.png b/assets/zht/cafe/INVITE_CONFIRM.png new file mode 100644 index 0000000..b65f9c4 Binary files /dev/null and b/assets/zht/cafe/INVITE_CONFIRM.png differ diff --git a/assets/zht/cafe/INVITE_IN_SECOND.png b/assets/zht/cafe/INVITE_IN_SECOND.png new file mode 100644 index 0000000..3a786ae Binary files /dev/null and b/assets/zht/cafe/INVITE_IN_SECOND.png differ diff --git a/assets/zht/cafe/INVITE_IN_SECOND_CLOSE.png b/assets/zht/cafe/INVITE_IN_SECOND_CLOSE.png new file mode 100644 index 0000000..0bb17d2 Binary files /dev/null and b/assets/zht/cafe/INVITE_IN_SECOND_CLOSE.png differ diff --git a/assets/zht/cafe/INVITE_SUBSTITUTE.BUTTON.png b/assets/zht/cafe/INVITE_SUBSTITUTE.BUTTON.png new file mode 100644 index 0000000..1093aaa Binary files /dev/null and b/assets/zht/cafe/INVITE_SUBSTITUTE.BUTTON.png differ diff --git a/assets/zht/cafe/INVITE_SUBSTITUTE.png b/assets/zht/cafe/INVITE_SUBSTITUTE.png new file mode 100644 index 0000000..73ed16b Binary files /dev/null and b/assets/zht/cafe/INVITE_SUBSTITUTE.png differ diff --git a/assets/zht/cafe/INVITE_SUBSTITUTE_CLOSE.png b/assets/zht/cafe/INVITE_SUBSTITUTE_CLOSE.png new file mode 100644 index 0000000..61a3704 Binary files /dev/null and b/assets/zht/cafe/INVITE_SUBSTITUTE_CLOSE.png differ diff --git a/assets/zht/cafe/MOMOTALK_CLOSE.png b/assets/zht/cafe/MOMOTALK_CLOSE.png new file mode 100644 index 0000000..6a220ac Binary files /dev/null and b/assets/zht/cafe/MOMOTALK_CLOSE.png differ diff --git a/assets/zht/cafe/MOMOTALK_INVITE.png b/assets/zht/cafe/MOMOTALK_INVITE.png new file mode 100644 index 0000000..59b5576 Binary files /dev/null and b/assets/zht/cafe/MOMOTALK_INVITE.png differ diff --git a/assets/zht/cafe/MOMOTALK_ITEM.png b/assets/zht/cafe/MOMOTALK_ITEM.png new file mode 100644 index 0000000..47baae7 Binary files /dev/null and b/assets/zht/cafe/MOMOTALK_ITEM.png differ diff --git a/assets/zht/cafe/OCR_CAFE.png b/assets/zht/cafe/OCR_CAFE.png new file mode 100644 index 0000000..be8f849 Binary files /dev/null and b/assets/zht/cafe/OCR_CAFE.png differ diff --git a/assets/zht/cafe/OCR_NAME.png b/assets/zht/cafe/OCR_NAME.png new file mode 100644 index 0000000..b4e7f9f Binary files /dev/null and b/assets/zht/cafe/OCR_NAME.png differ diff --git a/assets/zht/cafe/STUDENT_LIST.BUTTON.png b/assets/zht/cafe/STUDENT_LIST.BUTTON.png new file mode 100644 index 0000000..9c65bb8 Binary files /dev/null and b/assets/zht/cafe/STUDENT_LIST.BUTTON.png differ diff --git a/assets/zht/cafe/STUDENT_LIST.png b/assets/zht/cafe/STUDENT_LIST.png new file mode 100644 index 0000000..93999fd Binary files /dev/null and b/assets/zht/cafe/STUDENT_LIST.png differ diff --git a/assets/zht/circle/GET_REWARD_AP.BUTTON.png b/assets/zht/circle/GET_REWARD_AP.BUTTON.png new file mode 100644 index 0000000..c83d9c2 Binary files /dev/null and b/assets/zht/circle/GET_REWARD_AP.BUTTON.png differ diff --git a/assets/zht/circle/GET_REWARD_AP.png b/assets/zht/circle/GET_REWARD_AP.png new file mode 100644 index 0000000..5c36bb8 Binary files /dev/null and b/assets/zht/circle/GET_REWARD_AP.png differ diff --git a/assets/zht/login/LOGIN_CONFIRM.BUTTON.png b/assets/zht/login/LOGIN_CONFIRM.BUTTON.png new file mode 100644 index 0000000..359f813 Binary files /dev/null and b/assets/zht/login/LOGIN_CONFIRM.BUTTON.png differ diff --git a/assets/zht/login/LOGIN_CONFIRM.png b/assets/zht/login/LOGIN_CONFIRM.png new file mode 100644 index 0000000..ea778c3 Binary files /dev/null and b/assets/zht/login/LOGIN_CONFIRM.png differ diff --git a/assets/zht/login/LOGIN_LOADING.png b/assets/zht/login/LOGIN_LOADING.png new file mode 100644 index 0000000..3d4424c Binary files /dev/null and b/assets/zht/login/LOGIN_LOADING.png differ diff --git a/assets/zht/login/OCR_YEAR.png b/assets/zht/login/OCR_YEAR.png new file mode 100644 index 0000000..4db7b6f Binary files /dev/null and b/assets/zht/login/OCR_YEAR.png differ diff --git a/assets/zht/login/SURVEY.BUTTON.png b/assets/zht/login/SURVEY.BUTTON.png new file mode 100644 index 0000000..000cfba Binary files /dev/null and b/assets/zht/login/SURVEY.BUTTON.png differ diff --git a/assets/zht/login/SURVEY.png b/assets/zht/login/SURVEY.png new file mode 100644 index 0000000..2f9c537 Binary files /dev/null and b/assets/zht/login/SURVEY.png differ diff --git a/assets/zht/login/UPDATE.BUTTON.png b/assets/zht/login/UPDATE.BUTTON.png new file mode 100644 index 0000000..d1c1b3d Binary files /dev/null and b/assets/zht/login/UPDATE.BUTTON.png differ diff --git a/assets/zht/login/UPDATE.png b/assets/zht/login/UPDATE.png new file mode 100644 index 0000000..1fe6fb2 Binary files /dev/null and b/assets/zht/login/UPDATE.png differ diff --git a/assets/zht/mail/MAIL_RECEIVE.png b/assets/zht/mail/MAIL_RECEIVE.png new file mode 100644 index 0000000..e7b5220 Binary files /dev/null and b/assets/zht/mail/MAIL_RECEIVE.png differ diff --git a/assets/zht/mail/MAIL_RECEIVED.png b/assets/zht/mail/MAIL_RECEIVED.png new file mode 100644 index 0000000..fd119f7 Binary files /dev/null and b/assets/zht/mail/MAIL_RECEIVED.png differ diff --git a/assets/zht/mission/CHECK_COMMISSIONS.png b/assets/zht/mission/CHECK_COMMISSIONS.png new file mode 100644 index 0000000..bb2baae Binary files /dev/null and b/assets/zht/mission/CHECK_COMMISSIONS.png differ diff --git a/assets/zht/mission/CHECK_CR.png b/assets/zht/mission/CHECK_CR.png new file mode 100644 index 0000000..048a186 Binary files /dev/null and b/assets/zht/mission/CHECK_CR.png differ diff --git a/assets/zht/mission/CHECK_MISSION_SWEEP.png b/assets/zht/mission/CHECK_MISSION_SWEEP.png new file mode 100644 index 0000000..bf6864a Binary files /dev/null and b/assets/zht/mission/CHECK_MISSION_SWEEP.png differ diff --git a/assets/zht/mission/CHECK_XP.png b/assets/zht/mission/CHECK_XP.png new file mode 100644 index 0000000..192abf6 Binary files /dev/null and b/assets/zht/mission/CHECK_XP.png differ diff --git a/assets/zht/mission/EVENT_INDEX.png b/assets/zht/mission/EVENT_INDEX.png new file mode 100644 index 0000000..104fbc4 Binary files /dev/null and b/assets/zht/mission/EVENT_INDEX.png differ diff --git a/assets/zht/mission/EVENT_ITEM.png b/assets/zht/mission/EVENT_ITEM.png new file mode 100644 index 0000000..2f2a2a7 Binary files /dev/null and b/assets/zht/mission/EVENT_ITEM.png differ diff --git a/assets/zht/mission/EVENT_LIST.png b/assets/zht/mission/EVENT_LIST.png new file mode 100644 index 0000000..a3eb22d Binary files /dev/null and b/assets/zht/mission/EVENT_LIST.png differ diff --git a/assets/zht/mission/EVENT_STARS.png b/assets/zht/mission/EVENT_STARS.png new file mode 100644 index 0000000..bdc774b Binary files /dev/null and b/assets/zht/mission/EVENT_STARS.png differ diff --git a/assets/zht/mission/HARD_OFF.png b/assets/zht/mission/HARD_OFF.png new file mode 100644 index 0000000..e41bc2a Binary files /dev/null and b/assets/zht/mission/HARD_OFF.png differ diff --git a/assets/zht/mission/HARD_ON.png b/assets/zht/mission/HARD_ON.png new file mode 100644 index 0000000..7f7dc90 Binary files /dev/null and b/assets/zht/mission/HARD_ON.png differ diff --git a/assets/zht/mission/LEFT.png b/assets/zht/mission/LEFT.png new file mode 100644 index 0000000..f1bc365 Binary files /dev/null and b/assets/zht/mission/LEFT.png differ diff --git a/assets/zht/mission/NORMAL_OFF.png b/assets/zht/mission/NORMAL_OFF.png new file mode 100644 index 0000000..2a5fab9 Binary files /dev/null and b/assets/zht/mission/NORMAL_OFF.png differ diff --git a/assets/zht/mission/NORMAL_ON.png b/assets/zht/mission/NORMAL_ON.png new file mode 100644 index 0000000..39b0af3 Binary files /dev/null and b/assets/zht/mission/NORMAL_ON.png differ diff --git a/assets/zht/mission/OCR_AREA.png b/assets/zht/mission/OCR_AREA.png new file mode 100644 index 0000000..7602382 Binary files /dev/null and b/assets/zht/mission/OCR_AREA.png differ diff --git a/assets/zht/mission/QUEST_OFF.png b/assets/zht/mission/QUEST_OFF.png new file mode 100644 index 0000000..2461875 Binary files /dev/null and b/assets/zht/mission/QUEST_OFF.png differ diff --git a/assets/zht/mission/QUEST_ON.png b/assets/zht/mission/QUEST_ON.png new file mode 100644 index 0000000..1c45adc Binary files /dev/null and b/assets/zht/mission/QUEST_ON.png differ diff --git a/assets/zht/mission/RIGHT.png b/assets/zht/mission/RIGHT.png new file mode 100644 index 0000000..e4c0e74 Binary files /dev/null and b/assets/zht/mission/RIGHT.png differ diff --git a/assets/zht/mission/SELECT_CR.png b/assets/zht/mission/SELECT_CR.png new file mode 100644 index 0000000..47dce76 Binary files /dev/null and b/assets/zht/mission/SELECT_CR.png differ diff --git a/assets/zht/mission/SELECT_XP.png b/assets/zht/mission/SELECT_XP.png new file mode 100644 index 0000000..4e972bb Binary files /dev/null and b/assets/zht/mission/SELECT_XP.png differ diff --git a/assets/zht/momotalk/BEGIN_STORY.png b/assets/zht/momotalk/BEGIN_STORY.png new file mode 100644 index 0000000..93fd84b Binary files /dev/null and b/assets/zht/momotalk/BEGIN_STORY.png differ diff --git a/assets/zht/momotalk/CHATTING.png b/assets/zht/momotalk/CHATTING.png new file mode 100644 index 0000000..3908b0a Binary files /dev/null and b/assets/zht/momotalk/CHATTING.png differ diff --git a/assets/zht/momotalk/CHAT_AREA.png b/assets/zht/momotalk/CHAT_AREA.png new file mode 100644 index 0000000..ed61a8e Binary files /dev/null and b/assets/zht/momotalk/CHAT_AREA.png differ diff --git a/assets/zht/momotalk/CONFIRM_SKIP.png b/assets/zht/momotalk/CONFIRM_SKIP.png new file mode 100644 index 0000000..596f389 Binary files /dev/null and b/assets/zht/momotalk/CONFIRM_SKIP.png differ diff --git a/assets/zht/momotalk/CONFIRM_SORT.png b/assets/zht/momotalk/CONFIRM_SORT.png new file mode 100644 index 0000000..ec30469 Binary files /dev/null and b/assets/zht/momotalk/CONFIRM_SORT.png differ diff --git a/assets/zht/momotalk/FIRST_UNREAD.png b/assets/zht/momotalk/FIRST_UNREAD.png new file mode 100644 index 0000000..deb3791 Binary files /dev/null and b/assets/zht/momotalk/FIRST_UNREAD.png differ diff --git a/assets/zht/momotalk/MENU.png b/assets/zht/momotalk/MENU.png new file mode 100644 index 0000000..0fe3caa Binary files /dev/null and b/assets/zht/momotalk/MENU.png differ diff --git a/assets/zht/momotalk/NOTIFICATION_BADGE.png b/assets/zht/momotalk/NOTIFICATION_BADGE.png new file mode 100644 index 0000000..0753e80 Binary files /dev/null and b/assets/zht/momotalk/NOTIFICATION_BADGE.png differ diff --git a/assets/zht/momotalk/REPLY.png b/assets/zht/momotalk/REPLY.png new file mode 100644 index 0000000..22ac500 Binary files /dev/null and b/assets/zht/momotalk/REPLY.png differ diff --git a/assets/zht/momotalk/SELECT_STUDENT.png b/assets/zht/momotalk/SELECT_STUDENT.png new file mode 100644 index 0000000..1ff7589 Binary files /dev/null and b/assets/zht/momotalk/SELECT_STUDENT.png differ diff --git a/assets/zht/momotalk/SKIP.png b/assets/zht/momotalk/SKIP.png new file mode 100644 index 0000000..a65e2c1 Binary files /dev/null and b/assets/zht/momotalk/SKIP.png differ diff --git a/assets/zht/momotalk/SORT_ASCENDING.png b/assets/zht/momotalk/SORT_ASCENDING.png new file mode 100644 index 0000000..617998d Binary files /dev/null and b/assets/zht/momotalk/SORT_ASCENDING.png differ diff --git a/assets/zht/momotalk/SORT_DESCENDING.png b/assets/zht/momotalk/SORT_DESCENDING.png new file mode 100644 index 0000000..f97331a Binary files /dev/null and b/assets/zht/momotalk/SORT_DESCENDING.png differ diff --git a/assets/zht/momotalk/STORY.png b/assets/zht/momotalk/STORY.png new file mode 100644 index 0000000..a821609 Binary files /dev/null and b/assets/zht/momotalk/STORY.png differ diff --git a/assets/zht/momotalk/SWITCH_MESSAGE.png b/assets/zht/momotalk/SWITCH_MESSAGE.png new file mode 100644 index 0000000..bce95dd Binary files /dev/null and b/assets/zht/momotalk/SWITCH_MESSAGE.png differ diff --git a/assets/zht/momotalk/SWITCH_MESSAGE_CHECK.png b/assets/zht/momotalk/SWITCH_MESSAGE_CHECK.png new file mode 100644 index 0000000..e3ea702 Binary files /dev/null and b/assets/zht/momotalk/SWITCH_MESSAGE_CHECK.png differ diff --git a/assets/zht/momotalk/SWITCH_STUDENT.png b/assets/zht/momotalk/SWITCH_STUDENT.png new file mode 100644 index 0000000..caf65f0 Binary files /dev/null and b/assets/zht/momotalk/SWITCH_STUDENT.png differ diff --git a/assets/zht/momotalk/SWITCH_STUDENT_CHECK.png b/assets/zht/momotalk/SWITCH_STUDENT_CHECK.png new file mode 100644 index 0000000..24191a7 Binary files /dev/null and b/assets/zht/momotalk/SWITCH_STUDENT_CHECK.png differ diff --git a/assets/zht/momotalk/UNREAD.png b/assets/zht/momotalk/UNREAD.png new file mode 100644 index 0000000..8d61179 Binary files /dev/null and b/assets/zht/momotalk/UNREAD.png differ diff --git a/assets/zht/momotalk/UNREAD_OFF.png b/assets/zht/momotalk/UNREAD_OFF.png new file mode 100644 index 0000000..0a980a6 Binary files /dev/null and b/assets/zht/momotalk/UNREAD_OFF.png differ diff --git a/assets/zht/momotalk/UNREAD_ON.png b/assets/zht/momotalk/UNREAD_ON.png new file mode 100644 index 0000000..6c16678 Binary files /dev/null and b/assets/zht/momotalk/UNREAD_ON.png differ diff --git a/assets/zht/schedule/CONFIRM.png b/assets/zht/schedule/CONFIRM.png new file mode 100644 index 0000000..d8a4d9c Binary files /dev/null and b/assets/zht/schedule/CONFIRM.png differ diff --git a/assets/zht/schedule/FIRST_ITEM.png b/assets/zht/schedule/FIRST_ITEM.png new file mode 100644 index 0000000..6de565e Binary files /dev/null and b/assets/zht/schedule/FIRST_ITEM.png differ diff --git a/assets/zht/schedule/LOCATIONS.png b/assets/zht/schedule/LOCATIONS.png new file mode 100644 index 0000000..d68babe Binary files /dev/null and b/assets/zht/schedule/LOCATIONS.png differ diff --git a/assets/zht/schedule/LOCATIONS_POPUP.png b/assets/zht/schedule/LOCATIONS_POPUP.png new file mode 100644 index 0000000..5630c4a Binary files /dev/null and b/assets/zht/schedule/LOCATIONS_POPUP.png differ diff --git a/assets/zht/schedule/OCR_TICKET.png b/assets/zht/schedule/OCR_TICKET.png new file mode 100644 index 0000000..2532168 Binary files /dev/null and b/assets/zht/schedule/OCR_TICKET.png differ diff --git a/assets/zht/schedule/SCROLL.png b/assets/zht/schedule/SCROLL.png new file mode 100644 index 0000000..c426e8d Binary files /dev/null and b/assets/zht/schedule/SCROLL.png differ diff --git a/assets/zht/schedule/START_LESSON.png b/assets/zht/schedule/START_LESSON.png new file mode 100644 index 0000000..ea75dad Binary files /dev/null and b/assets/zht/schedule/START_LESSON.png differ diff --git a/assets/zht/scrimmage/CHECK_GEHENNA.png b/assets/zht/scrimmage/CHECK_GEHENNA.png new file mode 100644 index 0000000..eda286d Binary files /dev/null and b/assets/zht/scrimmage/CHECK_GEHENNA.png differ diff --git a/assets/zht/scrimmage/CHECK_MILLENNIUM.png b/assets/zht/scrimmage/CHECK_MILLENNIUM.png new file mode 100644 index 0000000..f377868 Binary files /dev/null and b/assets/zht/scrimmage/CHECK_MILLENNIUM.png differ diff --git a/assets/zht/scrimmage/CHECK_SCRIMMAGE.png b/assets/zht/scrimmage/CHECK_SCRIMMAGE.png new file mode 100644 index 0000000..1b22ef2 Binary files /dev/null and b/assets/zht/scrimmage/CHECK_SCRIMMAGE.png differ diff --git a/assets/zht/scrimmage/CHECK_TRINITY.png b/assets/zht/scrimmage/CHECK_TRINITY.png new file mode 100644 index 0000000..8a4eb11 Binary files /dev/null and b/assets/zht/scrimmage/CHECK_TRINITY.png differ diff --git a/assets/zht/scrimmage/OCR_TICKET.png b/assets/zht/scrimmage/OCR_TICKET.png new file mode 100644 index 0000000..a78c89d Binary files /dev/null and b/assets/zht/scrimmage/OCR_TICKET.png differ diff --git a/assets/zht/scrimmage/SELECT_GEHENNA.png b/assets/zht/scrimmage/SELECT_GEHENNA.png new file mode 100644 index 0000000..398df9e Binary files /dev/null and b/assets/zht/scrimmage/SELECT_GEHENNA.png differ diff --git a/assets/zht/scrimmage/SELECT_MILLENNIUM.png b/assets/zht/scrimmage/SELECT_MILLENNIUM.png new file mode 100644 index 0000000..22adea5 Binary files /dev/null and b/assets/zht/scrimmage/SELECT_MILLENNIUM.png differ diff --git a/assets/zht/scrimmage/SELECT_TRINITY.png b/assets/zht/scrimmage/SELECT_TRINITY.png new file mode 100644 index 0000000..be4a06f Binary files /dev/null and b/assets/zht/scrimmage/SELECT_TRINITY.png differ diff --git a/assets/zht/shop/CONFIRM_PURCHASE.BUTTON.png b/assets/zht/shop/CONFIRM_PURCHASE.BUTTON.png new file mode 100644 index 0000000..47d8b24 Binary files /dev/null and b/assets/zht/shop/CONFIRM_PURCHASE.BUTTON.png differ diff --git a/assets/zht/shop/CONFIRM_PURCHASE.png b/assets/zht/shop/CONFIRM_PURCHASE.png new file mode 100644 index 0000000..e53ccd8 Binary files /dev/null and b/assets/zht/shop/CONFIRM_PURCHASE.png differ diff --git a/assets/zht/shop/CONFIRM_REFRESH.BUTTON.png b/assets/zht/shop/CONFIRM_REFRESH.BUTTON.png new file mode 100644 index 0000000..f7a8348 Binary files /dev/null and b/assets/zht/shop/CONFIRM_REFRESH.BUTTON.png differ diff --git a/assets/zht/shop/CONFIRM_REFRESH.png b/assets/zht/shop/CONFIRM_REFRESH.png new file mode 100644 index 0000000..dc9f5ca Binary files /dev/null and b/assets/zht/shop/CONFIRM_REFRESH.png differ diff --git a/assets/zht/shop/ITEM_LIST.png b/assets/zht/shop/ITEM_LIST.png new file mode 100644 index 0000000..791f09c Binary files /dev/null and b/assets/zht/shop/ITEM_LIST.png differ diff --git a/assets/zht/shop/NORMAL_OFF.png b/assets/zht/shop/NORMAL_OFF.png new file mode 100644 index 0000000..b57ccd0 Binary files /dev/null and b/assets/zht/shop/NORMAL_OFF.png differ diff --git a/assets/zht/shop/NORMAL_ON.png b/assets/zht/shop/NORMAL_ON.png new file mode 100644 index 0000000..e73ecba Binary files /dev/null and b/assets/zht/shop/NORMAL_ON.png differ diff --git a/assets/zht/shop/OCR_REFRESH.png b/assets/zht/shop/OCR_REFRESH.png new file mode 100644 index 0000000..018c8bf Binary files /dev/null and b/assets/zht/shop/OCR_REFRESH.png differ diff --git a/assets/zht/shop/PURCHASE.png b/assets/zht/shop/PURCHASE.png new file mode 100644 index 0000000..acbe756 Binary files /dev/null and b/assets/zht/shop/PURCHASE.png differ diff --git a/assets/zht/shop/REFRESH.png b/assets/zht/shop/REFRESH.png new file mode 100644 index 0000000..39005b7 Binary files /dev/null and b/assets/zht/shop/REFRESH.png differ diff --git a/assets/zht/shop/TC_OFF.png b/assets/zht/shop/TC_OFF.png new file mode 100644 index 0000000..e061a7b Binary files /dev/null and b/assets/zht/shop/TC_OFF.png differ diff --git a/assets/zht/shop/TC_ON.png b/assets/zht/shop/TC_ON.png new file mode 100644 index 0000000..57a7d27 Binary files /dev/null and b/assets/zht/shop/TC_ON.png differ diff --git a/assets/zht/stage/list/OCR_INDEX.png b/assets/zht/stage/list/OCR_INDEX.png new file mode 100644 index 0000000..7cd4625 Binary files /dev/null and b/assets/zht/stage/list/OCR_INDEX.png differ diff --git a/assets/zht/stage/list/STAGE_ENTER.png b/assets/zht/stage/list/STAGE_ENTER.png new file mode 100644 index 0000000..ba7f61f Binary files /dev/null and b/assets/zht/stage/list/STAGE_ENTER.png differ diff --git a/assets/zht/stage/list/STAGE_ITEM.png b/assets/zht/stage/list/STAGE_ITEM.png new file mode 100644 index 0000000..1df5b9f Binary files /dev/null and b/assets/zht/stage/list/STAGE_ITEM.png differ diff --git a/assets/zht/stage/list/STAGE_LIST.png b/assets/zht/stage/list/STAGE_LIST.png new file mode 100644 index 0000000..1e8eaf4 Binary files /dev/null and b/assets/zht/stage/list/STAGE_LIST.png differ diff --git a/assets/zht/stage/list/STAGE_STARS.png b/assets/zht/stage/list/STAGE_STARS.png new file mode 100644 index 0000000..07cc44a Binary files /dev/null and b/assets/zht/stage/list/STAGE_STARS.png differ diff --git a/assets/zht/stage/sweep/CHECK_SWEEP.png b/assets/zht/stage/sweep/CHECK_SWEEP.png new file mode 100644 index 0000000..813b3a3 Binary files /dev/null and b/assets/zht/stage/sweep/CHECK_SWEEP.png differ diff --git a/assets/zht/stage/sweep/ENTER.png b/assets/zht/stage/sweep/ENTER.png new file mode 100644 index 0000000..0621937 Binary files /dev/null and b/assets/zht/stage/sweep/ENTER.png differ diff --git a/assets/zht/stage/sweep/EXIT.png b/assets/zht/stage/sweep/EXIT.png new file mode 100644 index 0000000..1f0b137 Binary files /dev/null and b/assets/zht/stage/sweep/EXIT.png differ diff --git a/assets/zht/stage/sweep/MAX.png b/assets/zht/stage/sweep/MAX.png new file mode 100644 index 0000000..52f5d85 Binary files /dev/null and b/assets/zht/stage/sweep/MAX.png differ diff --git a/assets/zht/stage/sweep/MIN.png b/assets/zht/stage/sweep/MIN.png new file mode 100644 index 0000000..f583aea Binary files /dev/null and b/assets/zht/stage/sweep/MIN.png differ diff --git a/assets/zht/stage/sweep/MINUS.png b/assets/zht/stage/sweep/MINUS.png new file mode 100644 index 0000000..bd57844 Binary files /dev/null and b/assets/zht/stage/sweep/MINUS.png differ diff --git a/assets/zht/stage/sweep/OCR_NUM.png b/assets/zht/stage/sweep/OCR_NUM.png new file mode 100644 index 0000000..ffb06ec Binary files /dev/null and b/assets/zht/stage/sweep/OCR_NUM.png differ diff --git a/assets/zht/stage/sweep/PLUS.png b/assets/zht/stage/sweep/PLUS.png new file mode 100644 index 0000000..106e382 Binary files /dev/null and b/assets/zht/stage/sweep/PLUS.png differ diff --git a/assets/zht/stage/sweep/SKIP_OK_LOWER.png b/assets/zht/stage/sweep/SKIP_OK_LOWER.png new file mode 100644 index 0000000..e957d90 Binary files /dev/null and b/assets/zht/stage/sweep/SKIP_OK_LOWER.png differ diff --git a/assets/zht/stage/sweep/SKIP_OK_UPPER.png b/assets/zht/stage/sweep/SKIP_OK_UPPER.png new file mode 100644 index 0000000..e46c7ce Binary files /dev/null and b/assets/zht/stage/sweep/SKIP_OK_UPPER.png differ diff --git a/assets/zht/stage/sweep/SKIP_SKIP.png b/assets/zht/stage/sweep/SKIP_SKIP.png new file mode 100644 index 0000000..1ccacfd Binary files /dev/null and b/assets/zht/stage/sweep/SKIP_SKIP.png differ diff --git a/assets/zht/stage/sweep/SWEEP.png b/assets/zht/stage/sweep/SWEEP.png new file mode 100644 index 0000000..acbe3a2 Binary files /dev/null and b/assets/zht/stage/sweep/SWEEP.png differ diff --git a/assets/zht/stage/sweep/SWEEP_CONFIRM.BUTTON.png b/assets/zht/stage/sweep/SWEEP_CONFIRM.BUTTON.png new file mode 100644 index 0000000..b36c3a6 Binary files /dev/null and b/assets/zht/stage/sweep/SWEEP_CONFIRM.BUTTON.png differ diff --git a/assets/zht/stage/sweep/SWEEP_CONFIRM.png b/assets/zht/stage/sweep/SWEEP_CONFIRM.png new file mode 100644 index 0000000..285565d Binary files /dev/null and b/assets/zht/stage/sweep/SWEEP_CONFIRM.png differ diff --git a/assets/zht/tactical_challenge/CHALLENGE_LOSE.BUTTON.png b/assets/zht/tactical_challenge/CHALLENGE_LOSE.BUTTON.png new file mode 100644 index 0000000..7f5ba69 Binary files /dev/null and b/assets/zht/tactical_challenge/CHALLENGE_LOSE.BUTTON.png differ diff --git a/assets/zht/tactical_challenge/CHALLENGE_LOSE.png b/assets/zht/tactical_challenge/CHALLENGE_LOSE.png new file mode 100644 index 0000000..f896b77 Binary files /dev/null and b/assets/zht/tactical_challenge/CHALLENGE_LOSE.png differ diff --git a/assets/zht/tactical_challenge/CHALLENGE_WIN.BUTTON.png b/assets/zht/tactical_challenge/CHALLENGE_WIN.BUTTON.png new file mode 100644 index 0000000..10c30bc Binary files /dev/null and b/assets/zht/tactical_challenge/CHALLENGE_WIN.BUTTON.png differ diff --git a/assets/zht/tactical_challenge/CHALLENGE_WIN.png b/assets/zht/tactical_challenge/CHALLENGE_WIN.png new file mode 100644 index 0000000..d371d74 Binary files /dev/null and b/assets/zht/tactical_challenge/CHALLENGE_WIN.png differ diff --git a/assets/zht/tactical_challenge/GET_REWARD_CREDIT.png b/assets/zht/tactical_challenge/GET_REWARD_CREDIT.png new file mode 100644 index 0000000..4bbc18f Binary files /dev/null and b/assets/zht/tactical_challenge/GET_REWARD_CREDIT.png differ diff --git a/assets/zht/tactical_challenge/GET_REWARD_DAILY.png b/assets/zht/tactical_challenge/GET_REWARD_DAILY.png new file mode 100644 index 0000000..6262ed7 Binary files /dev/null and b/assets/zht/tactical_challenge/GET_REWARD_DAILY.png differ diff --git a/assets/zht/tactical_challenge/GOT_REWARD_CREDIT.png b/assets/zht/tactical_challenge/GOT_REWARD_CREDIT.png new file mode 100644 index 0000000..2bd9619 Binary files /dev/null and b/assets/zht/tactical_challenge/GOT_REWARD_CREDIT.png differ diff --git a/assets/zht/tactical_challenge/GOT_REWARD_DAILY.png b/assets/zht/tactical_challenge/GOT_REWARD_DAILY.png new file mode 100644 index 0000000..d231e39 Binary files /dev/null and b/assets/zht/tactical_challenge/GOT_REWARD_DAILY.png differ diff --git a/assets/zht/tactical_challenge/OCR_TICKET.png b/assets/zht/tactical_challenge/OCR_TICKET.png new file mode 100644 index 0000000..ecc895d Binary files /dev/null and b/assets/zht/tactical_challenge/OCR_TICKET.png differ diff --git a/assets/zht/tactical_challenge/PLAYER_SELECT_FIRST.BUTTON.png b/assets/zht/tactical_challenge/PLAYER_SELECT_FIRST.BUTTON.png new file mode 100644 index 0000000..e80cb42 Binary files /dev/null and b/assets/zht/tactical_challenge/PLAYER_SELECT_FIRST.BUTTON.png differ diff --git a/assets/zht/tactical_challenge/PLAYER_SELECT_FIRST.png b/assets/zht/tactical_challenge/PLAYER_SELECT_FIRST.png new file mode 100644 index 0000000..f330c1f Binary files /dev/null and b/assets/zht/tactical_challenge/PLAYER_SELECT_FIRST.png differ diff --git a/assets/zht/tactical_challenge/PLAYER_SELECT_SECOND.BUTTON.png b/assets/zht/tactical_challenge/PLAYER_SELECT_SECOND.BUTTON.png new file mode 100644 index 0000000..6923724 Binary files /dev/null and b/assets/zht/tactical_challenge/PLAYER_SELECT_SECOND.BUTTON.png differ diff --git a/assets/zht/tactical_challenge/PLAYER_SELECT_SECOND.png b/assets/zht/tactical_challenge/PLAYER_SELECT_SECOND.png new file mode 100644 index 0000000..6d1548a Binary files /dev/null and b/assets/zht/tactical_challenge/PLAYER_SELECT_SECOND.png differ diff --git a/assets/zht/tactical_challenge/PLAYER_SELECT_THIRD.BUTTON.png b/assets/zht/tactical_challenge/PLAYER_SELECT_THIRD.BUTTON.png new file mode 100644 index 0000000..a06c13a Binary files /dev/null and b/assets/zht/tactical_challenge/PLAYER_SELECT_THIRD.BUTTON.png differ diff --git a/assets/zht/tactical_challenge/PLAYER_SELECT_THIRD.png b/assets/zht/tactical_challenge/PLAYER_SELECT_THIRD.png new file mode 100644 index 0000000..2038593 Binary files /dev/null and b/assets/zht/tactical_challenge/PLAYER_SELECT_THIRD.png differ diff --git a/assets/zht/tactical_challenge/PREPARE_CHALLENGE.BUTTON.png b/assets/zht/tactical_challenge/PREPARE_CHALLENGE.BUTTON.png new file mode 100644 index 0000000..85b6976 Binary files /dev/null and b/assets/zht/tactical_challenge/PREPARE_CHALLENGE.BUTTON.png differ diff --git a/assets/zht/tactical_challenge/PREPARE_CHALLENGE.png b/assets/zht/tactical_challenge/PREPARE_CHALLENGE.png new file mode 100644 index 0000000..74d9fff Binary files /dev/null and b/assets/zht/tactical_challenge/PREPARE_CHALLENGE.png differ diff --git a/assets/zht/tactical_challenge/SKIP_OFF.BUTTON.png b/assets/zht/tactical_challenge/SKIP_OFF.BUTTON.png new file mode 100644 index 0000000..5f78de6 Binary files /dev/null and b/assets/zht/tactical_challenge/SKIP_OFF.BUTTON.png differ diff --git a/assets/zht/tactical_challenge/SKIP_OFF.png b/assets/zht/tactical_challenge/SKIP_OFF.png new file mode 100644 index 0000000..2dc4722 Binary files /dev/null and b/assets/zht/tactical_challenge/SKIP_OFF.png differ diff --git a/assets/zht/tactical_challenge/SKIP_ON.BUTTON.png b/assets/zht/tactical_challenge/SKIP_ON.BUTTON.png new file mode 100644 index 0000000..3404c96 Binary files /dev/null and b/assets/zht/tactical_challenge/SKIP_ON.BUTTON.png differ diff --git a/assets/zht/tactical_challenge/SKIP_ON.png b/assets/zht/tactical_challenge/SKIP_ON.png new file mode 100644 index 0000000..7785391 Binary files /dev/null and b/assets/zht/tactical_challenge/SKIP_ON.png differ diff --git a/assets/zht/tactical_challenge/START_CHALLENGE.BUTTON.png b/assets/zht/tactical_challenge/START_CHALLENGE.BUTTON.png new file mode 100644 index 0000000..0b3e8b2 Binary files /dev/null and b/assets/zht/tactical_challenge/START_CHALLENGE.BUTTON.png differ diff --git a/assets/zht/tactical_challenge/START_CHALLENGE.png b/assets/zht/tactical_challenge/START_CHALLENGE.png new file mode 100644 index 0000000..bb6c31e Binary files /dev/null and b/assets/zht/tactical_challenge/START_CHALLENGE.png differ diff --git a/assets/zht/task/CLAIM.png b/assets/zht/task/CLAIM.png new file mode 100644 index 0000000..93ac3d6 Binary files /dev/null and b/assets/zht/task/CLAIM.png differ diff --git a/assets/zht/task/CLAIMED.png b/assets/zht/task/CLAIMED.png new file mode 100644 index 0000000..858b44a Binary files /dev/null and b/assets/zht/task/CLAIMED.png differ diff --git a/assets/zht/task/CLAIMED_ALL.png b/assets/zht/task/CLAIMED_ALL.png new file mode 100644 index 0000000..844be29 Binary files /dev/null and b/assets/zht/task/CLAIMED_ALL.png differ diff --git a/assets/zht/task/CLAIM_ALL.png b/assets/zht/task/CLAIM_ALL.png new file mode 100644 index 0000000..08f2724 Binary files /dev/null and b/assets/zht/task/CLAIM_ALL.png differ diff --git a/assets/zht/task/COMPLETE.png b/assets/zht/task/COMPLETE.png new file mode 100644 index 0000000..b5d1074 Binary files /dev/null and b/assets/zht/task/COMPLETE.png differ diff --git a/config/template.json b/config/template.json index 32f08f8..294d80c 100644 --- a/config/template.json +++ b/config/template.json @@ -70,6 +70,45 @@ "Substitute": false } }, + "Schedule": { + "Scheduler": { + "Enable": false, + "NextRun": "2020-01-01 00:00:00", + "Command": "Schedule", + "ServerUpdate": "04:00" + }, + "Schedule": { + "OnError": "skip" + }, + "Choice1": { + "Location": "None", + "Classrooms": null + }, + "Choice2": { + "Location": "None", + "Classrooms": null + }, + "Choice3": { + "Location": "None", + "Classrooms": null + }, + "Choice4": { + "Location": "None", + "Classrooms": null + }, + "Choice5": { + "Location": "None", + "Classrooms": null + }, + "Choice6": { + "Location": "None", + "Classrooms": null + }, + "Choice7": { + "Location": "None", + "Classrooms": null + } + }, "Shop": { "Scheduler": { "Enable": false, diff --git a/licenses/BAAH-license b/licenses/BAAH-license new file mode 100644 index 0000000..c2885de --- /dev/null +++ b/licenses/BAAH-license @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-present Electron React Boilerplate + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/licenses/CTkMessagebox-license b/licenses/CTkMessagebox-license new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/licenses/CTkMessagebox-license @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/licenses/CTkScrollableDropdown-license b/licenses/CTkScrollableDropdown-license new file mode 100644 index 0000000..c136acb --- /dev/null +++ b/licenses/CTkScrollableDropdown-license @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Akash Bora + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/licenses/CTkToolTip-license b/licenses/CTkToolTip-license new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/licenses/CTkToolTip-license @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/module/alas.py b/module/alas.py index 56c0193..03e1586 100644 --- a/module/alas.py +++ b/module/alas.py @@ -14,6 +14,9 @@ from module.exception import * from module.logger import logger from module.notify import handle_notify +from MCE.custom_widgets.ctkmessagebox import CTkMessagebox +import subprocess +import platform class AzurLaneAutoScript: stop_event: threading.Event = None @@ -26,6 +29,7 @@ class AzurLaneAutoScript: # Failure count of tasks # Key: str, task name, value: int, failure count self.failure_record = {} + self.operating_system = platform.system() @cached_property def config(self): @@ -228,6 +232,46 @@ class AzurLaneAutoScript: if not self.wait_until(task.next_run): del_cached_property(self, 'config') continue + elif method == 'exit_aas': + if abs(task.next_run - datetime.now()) >= timedelta(minutes=2): # ensure tactical challenge is fully ran + self.config.Optimization_WhenTaskQueueEmpty = 'goto_main' + self.exit_aas() + exit(1) + release_resources() + self.device.release_during_wait() + if not self.wait_until(task.next_run): + del_cached_property(self, 'config') + continue + elif method == 'exit_emulator': + if abs(task.next_run - datetime.now()) >= timedelta(minutes=2): + self.config.Optimization_WhenTaskQueueEmpty = 'goto_main' + self.exit_emulator() + exit(1) # stops AAS from restarting emulator + release_resources() + self.device.release_during_wait() + if not self.wait_until(task.next_run): + del_cached_property(self, 'config') + continue + elif method == 'exit_aas_emulator': + if abs(task.next_run - datetime.now()) >= timedelta(minutes=2): + self.config.Optimization_WhenTaskQueueEmpty = 'goto_main' + self.exit_emulator() + self.exit_aas() + exit(1) + release_resources() + self.device.release_during_wait() + if not self.wait_until(task.next_run): + del_cached_property(self, 'config') + continue + elif method == 'shutdown': + if abs(task.next_run - datetime.now()) >= timedelta(minutes=2): + self.config.Optimization_WhenTaskQueueEmpty = 'goto_main' + self.shutdown() + release_resources() + self.device.release_during_wait() + if not self.wait_until(task.next_run): + del_cached_property(self, 'config') + continue else: logger.warning(f'Invalid Optimization_WhenTaskQueueEmpty: {method}, fallback to stay_there') release_resources() @@ -308,6 +352,55 @@ class AzurLaneAutoScript: self.checker.check_now() continue + def exit_emulator(self): + if self.operating_system != 'Windows': + logger.error("Exiting emulator is only supported on Windows") + return + try: + from module.device.platform.platform_windows import PlatformWindows + PlatformWindows(self.config).emulator_stop() + except: + logger.error("Failed to stop emulator. It may be due to a lack of administrator privileges.") + + def exit_aas(self): + if self.operating_system != 'Windows': + logger.error("Exiting AAS is only supported on Windows") + return + try: + from module.device.platform.platform_windows import PlatformWindows + from deploy.Windows.alas import AlasManager + PlatformWindows(self.config).kill_process_by_regex("aas\.exe") + AlasManager().alas_kill() + except: + logger.error("Failed to stop AAS. It may be due to a lack of administrator privileges.") + + def shutdown(self): + if self.operating_system not in ["Windows", "Linux", "Darwin"]: + logger.error("Shutdown set during wait but operating system not supported") + else: + logger.info('Shutdown during wait') + try: + self.start_shutdown() + msg = CTkMessagebox(title="AAS: Cancel Shutdown?", message="All tasks have been completed: shutting down. Do you want to cancel?", + icon="MCE\icons\question.png", option_1="Cancel") + response = msg.get() + if response=="Cancel": + self.cancel_shutdown() + except: + logger.error("Failed to shutdown. It may be due to a lack of administrator privileges.") + + def start_shutdown(self): + logger.info("Running Shutting down") + if self.operating_system == "Windows": + subprocess.run(["shutdown", "-s", "-t", "60"]) + elif self.operating_system in ["Linux", "Darwin"]: + subprocess.run(["shutdown", "-h", "+1"]) + + def cancel_shutdown(self): + if self.operating_system == "Windows": + subprocess.run(["shutdown", "-a"]) + elif self.operating_system in ["Linux", "Darwin"]: + subprocess.run(["shutdown", "-c"]) if __name__ == '__main__': alas = AzurLaneAutoScript() diff --git a/module/config/argument/args.json b/module/config/argument/args.json index e3acdf9..99a356b 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -25,7 +25,8 @@ "option": [ "auto", "jp", - "en" + "en", + "zht" ] }, "ScreenshotMethod": { @@ -128,7 +129,11 @@ "option": [ "stay_there", "goto_main", - "close_game" + "close_game", + "exit_aas", + "exit_emulator", + "exit_aas_emulator", + "shutdown" ] } } @@ -318,6 +323,204 @@ } } }, + "Schedule": { + "Scheduler": { + "Enable": { + "type": "checkbox", + "value": false, + "option": [ + true, + false + ] + }, + "NextRun": { + "type": "datetime", + "value": "2020-01-01 00:00:00", + "validate": "datetime" + }, + "Command": { + "type": "input", + "value": "Schedule", + "display": "hide" + }, + "ServerUpdate": { + "type": "input", + "value": "04:00", + "display": "hide" + } + }, + "Schedule": { + "OnError": { + "type": "select", + "value": "skip", + "option": [ + "stop", + "skip" + ] + } + }, + "Choice1": { + "Location": { + "type": "select", + "value": "None", + "option": [ + "None", + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ] + }, + "Classrooms": { + "type": "textarea", + "value": null + } + }, + "Choice2": { + "Location": { + "type": "select", + "value": "None", + "option": [ + "None", + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ] + }, + "Classrooms": { + "type": "textarea", + "value": null + } + }, + "Choice3": { + "Location": { + "type": "select", + "value": "None", + "option": [ + "None", + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ] + }, + "Classrooms": { + "type": "textarea", + "value": null + } + }, + "Choice4": { + "Location": { + "type": "select", + "value": "None", + "option": [ + "None", + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ] + }, + "Classrooms": { + "type": "textarea", + "value": null + } + }, + "Choice5": { + "Location": { + "type": "select", + "value": "None", + "option": [ + "None", + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ] + }, + "Classrooms": { + "type": "textarea", + "value": null + } + }, + "Choice6": { + "Location": { + "type": "select", + "value": "None", + "option": [ + "None", + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ] + }, + "Classrooms": { + "type": "textarea", + "value": null + } + }, + "Choice7": { + "Location": { + "type": "select", + "value": "None", + "option": [ + "None", + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ] + }, + "Classrooms": { + "type": "textarea", + "value": null + } + } + }, "Shop": { "Scheduler": { "Enable": { diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index 6ebb6c8..c83b1aa 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -23,7 +23,7 @@ Emulator: option: [ auto, ] GameLanguage: value: auto - option: [ auto, jp, en ] + option: [ auto, jp, en, zht ] ScreenshotMethod: value: auto option: [ auto, ADB, ADB_nc, uiautomator2, aScreenCap, aScreenCap_nc, DroidCast, DroidCast_raw, scrcpy ] @@ -71,7 +71,7 @@ Optimization: CombatScreenshotInterval: 1.0 WhenTaskQueueEmpty: value: goto_main - option: [ stay_there, goto_main, close_game ] + option: [ stay_there, goto_main, close_game, exit_aas, exit_emulator, exit_aas_emulator, shutdown ] # ==================== Daily ==================== @@ -93,6 +93,61 @@ Invitation: type: textarea Substitute: false +Schedule: + OnError: + value: skip + option: [ stop, skip ] + +Choice1: + Location: + value: None + option: [ None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + Classrooms: + value: null + type: textarea +Choice2: + Location: + value: None + option: [ None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + Classrooms: + value: null + type: textarea +Choice3: + Location: + value: None + option: [ None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + Classrooms: + value: null + type: textarea +Choice4: + Location: + value: None + option: [ None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + Classrooms: + value: null + type: textarea +Choice5: + Location: + value: None + option: [ None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + Classrooms: + value: null + type: textarea +Choice6: + Location: + value: None + option: [ None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + Classrooms: + value: null + type: textarea +Choice7: + Location: + value: None + option: [ None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] + Classrooms: + value: null + type: textarea + Bounty: OnError: value: skip diff --git a/module/config/argument/menu.json b/module/config/argument/menu.json index 82c45c1..9f562ec 100644 --- a/module/config/argument/menu.json +++ b/module/config/argument/menu.json @@ -13,6 +13,7 @@ "page": "setting", "tasks": [ "Cafe", + "Schedule", "Shop" ] }, diff --git a/module/config/argument/task.yaml b/module/config/argument/task.yaml index 12c9a0a..acf129b 100644 --- a/module/config/argument/task.yaml +++ b/module/config/argument/task.yaml @@ -29,6 +29,16 @@ Daily: - Scheduler - Cafe - Invitation + Schedule: + - Scheduler + - Schedule + - Choice1 + - Choice2 + - Choice3 + - Choice4 + - Choice5 + - Choice6 + - Choice7 Shop: - Scheduler - NormalShop diff --git a/module/config/config_generated.py b/module/config/config_generated.py index 9a66e6e..2d6a249 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -18,7 +18,7 @@ class GeneratedConfig: # Group `Emulator` Emulator_Serial = 'auto' Emulator_PackageName = 'auto' # auto, JP-Official, OVERSEA-TWHKMO, OVERSEA-Korea, OVERSEA-Asia, OVERSEA-America, OVERSEA-Global - Emulator_GameLanguage = 'auto' # auto, jp, en + Emulator_GameLanguage = 'auto' # auto, jp, en, zht Emulator_ScreenshotMethod = 'auto' # auto, ADB, ADB_nc, uiautomator2, aScreenCap, aScreenCap_nc, DroidCast, DroidCast_raw, scrcpy Emulator_ControlMethod = 'MaaTouch' # minitouch, MaaTouch Emulator_AdbRestart = False @@ -37,7 +37,7 @@ class GeneratedConfig: # Group `Optimization` Optimization_ScreenshotInterval = 0.3 Optimization_CombatScreenshotInterval = 1.0 - Optimization_WhenTaskQueueEmpty = 'goto_main' # stay_there, goto_main, close_game + Optimization_WhenTaskQueueEmpty = 'goto_main' # stay_there, goto_main, close_game, exit_aas, exit_emulator, exit_aas_emulator, shutdown # Group `Cafe` Cafe_Reward = True @@ -52,6 +52,37 @@ class GeneratedConfig: Invitation_Name = None Invitation_Substitute = False + # Group `Schedule` + Schedule_OnError = 'skip' # stop, skip + + # Group `Choice1` + Choice1_Location = 'None' # None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + Choice1_Classrooms = None + + # Group `Choice2` + Choice2_Location = 'None' # None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + Choice2_Classrooms = None + + # Group `Choice3` + Choice3_Location = 'None' # None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + Choice3_Classrooms = None + + # Group `Choice4` + Choice4_Location = 'None' # None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + Choice4_Classrooms = None + + # Group `Choice5` + Choice5_Location = 'None' # None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + Choice5_Classrooms = None + + # Group `Choice6` + Choice6_Location = 'None' # None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + Choice6_Classrooms = None + + # Group `Choice7` + Choice7_Location = 'None' # None, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + Choice7_Classrooms = None + # Group `Bounty` Bounty_OnError = 'skip' # stop, skip diff --git a/module/config/config_manual.py b/module/config/config_manual.py index e2b7a06..071ced1 100644 --- a/module/config/config_manual.py +++ b/module/config/config_manual.py @@ -9,7 +9,7 @@ class ManualConfig: SCHEDULER_PRIORITY = """ Restart > Cafe > TacticalChallenge > Circle > Mail - > DataUpdate > Bounty > Scrimmage > Task > Shop > Mission > Momotalk + > DataUpdate > Bounty > Scrimmage > Schedule > Task > Shop > Mission > Momotalk """ """ diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index a97c31c..899eeb1 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -34,6 +34,10 @@ "name": "Cafe", "help": "" }, + "Schedule": { + "name": "Lesson", + "help": "AAS will execute Lesson starting from Choice 1 to Choice 7.\nIt will ignore any Choice that have Location set as None or the text area for classrooms is empty.\nIf any of the active Choices have incorrect input, it will perform the action set in Error handling." + }, "Shop": { "name": "Shop", "help": "" @@ -120,7 +124,8 @@ "help": "Can't detect language automatically, please select the language manually.", "auto": "Auto-detect", "jp": "Japanese", - "en": "English" + "en": "English", + "zht": "Traditional Chinese" }, "ScreenshotMethod": { "name": "Screenshot Method", @@ -217,10 +222,14 @@ }, "WhenTaskQueueEmpty": { "name": "When Task Queue is Empty", - "help": "Close AL when there are no pending tasks, can help reduce CPU", + "help": "Close Blue Archive when there are no pending tasks, can help reduce CPU.\nExit AAS, emulator and shutdown should be set while AAS is running tasks otherwise it won't start; after their execution it will be reset to Goto Main Page.\nExit AAS and emulator are only available on Windows.\n\nExit emulator works using the values in Emulator Settings.\nFor accuracy, you should run AAS without emulator and AAS will list all detected instances in the Log. Copy and paste the name and path of the instance into the Emulator Settings.", "stay_there": "Stay There", "goto_main": "Goto Main Page", - "close_game": "Close Game" + "close_game": "Close Game", + "exit_aas": "Exit AAS", + "exit_emulator": "Exit Emulator", + "exit_aas_emulator": "Exit AAS & Emulator", + "shutdown": "Shutdown" } }, "Cafe": { @@ -270,13 +279,200 @@ }, "Name": { "name": "Inviting Student Name", - "help": "Fill in the name of the student to be invited. Use in-game text language. Use > to connect multiple students. Example:\nJP: ホシノ(水着) > 御坂美琴 > ユズ\nOVERSEA: Hoshino(Swimsuit) > Yuuka > Kayoko(New Year)" + "help": "It is recommended to use Input Helper to avoid any mistakes and paste it here using Ctrl + V.\nFill in the name of the student to be invited. Use in-game text language. Use > to connect multiple students. Example:\nJP: ホシノ(水着) > 御坂美琴 > ユズ\nOVERSEA: Hoshino(Swimsuit) > Yuuka > Kayoko(New Year)" }, "Substitute": { "name": "Replace existing student", "help": "Whether to replace the existing student with their alt.\nIf not, try to match the next student" } }, + "Schedule": { + "_info": { + "name": "Lesson Settings", + "help": "" + }, + "OnError": { + "name": "Error Handling", + "help": "Perform the selected action when an error occurs (location not unlocked or any invalid setting)", + "stop": "Stop script", + "skip": "Skip current task" + } + }, + "Choice1": { + "_info": { + "name": "Choice 1", + "help": "" + }, + "Location": { + "name": "Location", + "help": "", + "None": "None", + "0": "Schale Office", + "1": "Schale Residence", + "2": "Gehenna", + "3": "Abydos", + "4": "Millennium", + "5": "Trinity", + "6": "Red Winter", + "7": "Hyakkiyako", + "8": "D.U. Shiratori", + "9": "Shanhaijing" + }, + "Classrooms": { + "name": "Classrooms", + "help": "It is recommended to use Input Helper to avoid any mistakes and paste it here using Ctrl + V.\nType a number from 1 to 9 that represents the classroom position in the locations popup.\nUse > to connect multiple classrooms and AAS will select them following the order they appear.Example:\n8 > 7 > 6 > 5 > 4 > 3 > 2 > 1" + } + }, + "Choice2": { + "_info": { + "name": "Choice 2", + "help": "" + }, + "Location": { + "name": "Location", + "help": "", + "None": "None", + "0": "Schale Office", + "1": "Schale Residence", + "2": "Gehenna", + "3": "Abydos", + "4": "Millennium", + "5": "Trinity", + "6": "Red Winter", + "7": "Hyakkiyako", + "8": "D.U. Shiratori", + "9": "Shanhaijing" + }, + "Classrooms": { + "name": "Classrooms", + "help": "" + } + }, + "Choice3": { + "_info": { + "name": "Choice 3", + "help": "" + }, + "Location": { + "name": "Location", + "help": "", + "None": "None", + "0": "Schale Office", + "1": "Schale Residence", + "2": "Gehenna", + "3": "Abydos", + "4": "Millennium", + "5": "Trinity", + "6": "Red Winter", + "7": "Hyakkiyako", + "8": "D.U. Shiratori", + "9": "Shanhaijing" + }, + "Classrooms": { + "name": "Classrooms", + "help": "" + } + }, + "Choice4": { + "_info": { + "name": "Choice 4", + "help": "" + }, + "Location": { + "name": "Location", + "help": "", + "None": "None", + "0": "Schale Office", + "1": "Schale Residence", + "2": "Gehenna", + "3": "Abydos", + "4": "Millennium", + "5": "Trinity", + "6": "Red Winter", + "7": "Hyakkiyako", + "8": "D.U. Shiratori", + "9": "Shanhaijing" + }, + "Classrooms": { + "name": "Classrooms", + "help": "" + } + }, + "Choice5": { + "_info": { + "name": "Choice 5", + "help": "" + }, + "Location": { + "name": "Location", + "help": "", + "None": "None", + "0": "Schale Office", + "1": "Schale Residence", + "2": "Gehenna", + "3": "Abydos", + "4": "Millennium", + "5": "Trinity", + "6": "Red Winter", + "7": "Hyakkiyako", + "8": "D.U. Shiratori", + "9": "Shanhaijing" + }, + "Classrooms": { + "name": "Classrooms", + "help": "" + } + }, + "Choice6": { + "_info": { + "name": "Choice 6", + "help": "" + }, + "Location": { + "name": "Location", + "help": "", + "None": "None", + "0": "Schale Office", + "1": "Schale Residence", + "2": "Gehenna", + "3": "Abydos", + "4": "Millennium", + "5": "Trinity", + "6": "Red Winter", + "7": "Hyakkiyako", + "8": "D.U. Shiratori", + "9": "Shanhaijing" + }, + "Classrooms": { + "name": "Classrooms", + "help": "" + } + }, + "Choice7": { + "_info": { + "name": "Choice 7", + "help": "" + }, + "Location": { + "name": "Location", + "help": "", + "None": "None", + "0": "Schale Office", + "1": "Schale Residence", + "2": "Gehenna", + "3": "Abydos", + "4": "Millennium", + "5": "Trinity", + "6": "Red Winter", + "7": "Hyakkiyako", + "8": "D.U. Shiratori", + "9": "Shanhaijing" + }, + "Classrooms": { + "name": "Classrooms", + "help": "" + } + }, "Bounty": { "_info": { "name": "Bounty Settings", diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index 4ab9e1f..66affd4 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -34,6 +34,10 @@ "name": "咖啡厅", "help": "" }, + "Schedule": { + "name": "Task.Schedule.name", + "help": "Task.Schedule.help" + }, "Shop": { "name": "商店", "help": "" @@ -120,7 +124,8 @@ "help": "无法自动检测语言,请手动选择语言", "auto": "自动检测", "jp": "日语", - "en": "英语" + "en": "英语", + "zht": "zht" }, "ScreenshotMethod": { "name": "模拟器截图方案", @@ -220,7 +225,11 @@ "help": "无任务时关闭游戏,能在收菜期间降低 CPU 占用", "stay_there": "停在原处", "goto_main": "前往主界面", - "close_game": "关闭游戏" + "close_game": "关闭游戏", + "exit_aas": "exit_aas", + "exit_emulator": "exit_emulator", + "exit_aas_emulator": "exit_aas_emulator", + "shutdown": "shutdown" } }, "Cafe": { @@ -277,6 +286,193 @@ "help": "若咖啡厅已存在所邀请学生的不同服装,选择是否替换该学生\n若不替换,则尝试匹配下一位学生" } }, + "Schedule": { + "_info": { + "name": "Schedule._info.name", + "help": "Schedule._info.help" + }, + "OnError": { + "name": "Schedule.OnError.name", + "help": "Schedule.OnError.help", + "stop": "stop", + "skip": "skip" + } + }, + "Choice1": { + "_info": { + "name": "Choice1._info.name", + "help": "Choice1._info.help" + }, + "Location": { + "name": "Choice1.Location.name", + "help": "Choice1.Location.help", + "None": "None", + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9" + }, + "Classrooms": { + "name": "Choice1.Classrooms.name", + "help": "Choice1.Classrooms.help" + } + }, + "Choice2": { + "_info": { + "name": "Choice2._info.name", + "help": "Choice2._info.help" + }, + "Location": { + "name": "Choice2.Location.name", + "help": "Choice2.Location.help", + "None": "None", + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9" + }, + "Classrooms": { + "name": "Choice2.Classrooms.name", + "help": "Choice2.Classrooms.help" + } + }, + "Choice3": { + "_info": { + "name": "Choice3._info.name", + "help": "Choice3._info.help" + }, + "Location": { + "name": "Choice3.Location.name", + "help": "Choice3.Location.help", + "None": "None", + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9" + }, + "Classrooms": { + "name": "Choice3.Classrooms.name", + "help": "Choice3.Classrooms.help" + } + }, + "Choice4": { + "_info": { + "name": "Choice4._info.name", + "help": "Choice4._info.help" + }, + "Location": { + "name": "Choice4.Location.name", + "help": "Choice4.Location.help", + "None": "None", + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9" + }, + "Classrooms": { + "name": "Choice4.Classrooms.name", + "help": "Choice4.Classrooms.help" + } + }, + "Choice5": { + "_info": { + "name": "Choice5._info.name", + "help": "Choice5._info.help" + }, + "Location": { + "name": "Choice5.Location.name", + "help": "Choice5.Location.help", + "None": "None", + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9" + }, + "Classrooms": { + "name": "Choice5.Classrooms.name", + "help": "Choice5.Classrooms.help" + } + }, + "Choice6": { + "_info": { + "name": "Choice6._info.name", + "help": "Choice6._info.help" + }, + "Location": { + "name": "Choice6.Location.name", + "help": "Choice6.Location.help", + "None": "None", + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9" + }, + "Classrooms": { + "name": "Choice6.Classrooms.name", + "help": "Choice6.Classrooms.help" + } + }, + "Choice7": { + "_info": { + "name": "Choice7._info.name", + "help": "Choice7._info.help" + }, + "Location": { + "name": "Choice7.Location.name", + "help": "Choice7.Location.help", + "None": "None", + "0": "0", + "1": "1", + "2": "2", + "3": "3", + "4": "4", + "5": "5", + "6": "6", + "7": "7", + "8": "8", + "9": "9" + }, + "Classrooms": { + "name": "Choice7.Classrooms.name", + "help": "Choice7.Classrooms.help" + } + }, "Bounty": { "_info": { "name": "悬赏通缉设置", diff --git a/module/config/server.py b/module/config/server.py index 93cf319..54fc737 100644 --- a/module/config/server.py +++ b/module/config/server.py @@ -5,7 +5,7 @@ Use 'import module.config.server as server' to import, don't use 'from xxx impor lang = 'jp' # Setting default to cn, will avoid errors when using dev_tools server = 'JP-Official' -VALID_LANG = ['jp', 'en'] +VALID_LANG = ['jp', 'en', 'zht'] VALID_SERVER = { 'JP-Official': 'com.YostarJP.BlueArchive', 'OVERSEA-TWHKMO': 'com.nexon.bluearchive', diff --git a/module/device/device.py b/module/device/device.py index 7f7bf27..b080844 100644 --- a/module/device/device.py +++ b/module/device/device.py @@ -186,3 +186,6 @@ class Device(Screenshot, Control, AppControl, Platform): super().app_stop() self.stuck_record_clear() self.click_record_clear() + + def back(self): + self.adb_shell("input keyevent 4") \ No newline at end of file diff --git a/module/device/platform/platform_windows.py b/module/device/platform/platform_windows.py index 0490156..ce91808 100644 --- a/module/device/platform/platform_windows.py +++ b/module/device/platform/platform_windows.py @@ -12,6 +12,7 @@ from module.device.platform.platform_base import PlatformBase from module.device.platform.emulator_windows import Emulator, EmulatorInstance, EmulatorManager from module.logger import logger +import os class EmulatorUnknown(Exception): pass @@ -97,10 +98,15 @@ class PlatformWindows(PlatformBase, EmulatorManager): self.execute(f'"{exe}" -clone:{instance.name}') elif instance == Emulator.BlueStacks5: # HD-Player.exe -instance Pie64 - self.execute(f'"{exe}" -instance {instance.name}') + self.execute(f'"{exe}" --instance {instance.name}') elif instance == Emulator.BlueStacks4: # BlueStacks\Client\Bluestacks.exe -vmname Android_1 self.execute(f'"{exe}" -vmname {instance.name}') + elif instance == Emulator.LDPlayer9: + directory, filename = os.path.split(exe) + new_filename = 'ldconsole.exe' + exe = os.path.join(directory, new_filename) + self.execute(f'"{exe}" launch --index {instance.name.replace("leidian", "")}') else: raise EmulatorUnknown(f'Cannot start an unknown emulator instance: {instance}') @@ -153,6 +159,13 @@ class PlatformWindows(PlatformBase, EmulatorManager): elif instance == Emulator.NoxPlayerFamily: # Nox.exe -clone:Nox_1 -quit self.execute(f'"{exe}" -clone:{instance.name} -quit') + elif instance == Emulator.BlueStacks5: + self.execute(f'taskkill /fi "WINDOWTITLE eq {instance.name}" /IM "HD-Player.exe" /F') + elif instance == Emulator.LDPlayer9: + directory, filename = os.path.split(exe) + new_filename = 'ldconsole.exe' + exe = os.path.join(directory, new_filename) + self.execute(f'"{exe}" quit --index {instance.name.replace("leidian", "")}') else: raise EmulatorUnknown(f'Cannot stop an unknown emulator instance: {instance}') diff --git a/requirements-in.txt b/requirements-in.txt index 255a687..6a6893a 100644 --- a/requirements-in.txt +++ b/requirements-in.txt @@ -31,6 +31,9 @@ starlette==0.14.2 uvicorn[standard]==0.17.6 aiofiles +# GUI +customtkinter + # For dev # pip-tools pynput diff --git a/requirements.txt b/requirements.txt index d353e9e..7a60605 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,6 +19,8 @@ cigam==0.0.3 # via apkutils2 click==8.1.3 # via uvicorn colorama==0.4.6 # via click, logzero, tqdm, uvicorn coloredlogs==15.0.1 # via onnxruntime +customtkinter==5.2.1 # via -r requirements-in.txt +darkdetect==0.8.0 # via customtkinter decorator==5.1.1 # via retry deprecated==1.2.13 # via uiautomator2 deprecation==2.1.0 # via adbutils diff --git a/tasks/base/assets/assets_base_page.py b/tasks/base/assets/assets_base_page.py index a3dad32..11f1b3e 100644 --- a/tasks/base/assets/assets_base_page.py +++ b/tasks/base/assets/assets_base_page.py @@ -19,6 +19,13 @@ ACCOUNT_INFO_CHECK = ButtonWrapper( color=(192, 200, 209), button=(103, 10, 219, 39), ), + zht=Button( + file='./assets/zht/base/page/ACCOUNT_INFO_CHECK.png', + area=(92, 0, 222, 41), + search=(72, 0, 242, 61), + color=(191, 201, 210), + button=(92, 0, 222, 41), + ), ) BACK = ButtonWrapper( name='BACK', @@ -46,6 +53,13 @@ BOUNTY_CHECK = ButtonWrapper( color=(200, 208, 216), button=(101, 5, 206, 42), ), + zht=Button( + file='./assets/zht/base/page/BOUNTY_CHECK.png', + area=(92, 6, 224, 41), + search=(72, 0, 244, 61), + color=(181, 191, 201), + button=(92, 6, 224, 41), + ), ) CAFE_CHECK = ButtonWrapper( name='CAFE_CHECK', @@ -63,6 +77,13 @@ CAFE_CHECK = ButtonWrapper( color=(188, 197, 206), button=(196, 8, 259, 37), ), + zht=Button( + file='./assets/zht/base/page/CAFE_CHECK.png', + area=(94, 2, 307, 43), + search=(74, 0, 327, 63), + color=(187, 196, 201), + button=(94, 2, 307, 43), + ), ) CIRCLE_CHECK = ButtonWrapper( name='CIRCLE_CHECK', @@ -80,6 +101,13 @@ CIRCLE_CHECK = ButtonWrapper( color=(190, 199, 208), button=(102, 8, 168, 38), ), + zht=Button( + file='./assets/zht/base/page/CIRCLE_CHECK.png', + area=(93, 3, 224, 39), + search=(73, 0, 244, 59), + color=(187, 197, 206), + button=(93, 3, 224, 39), + ), ) COMMISSIONS_CHECK = ButtonWrapper( name='COMMISSIONS_CHECK', @@ -97,6 +125,13 @@ COMMISSIONS_CHECK = ButtonWrapper( color=(191, 200, 209), button=(103, 7, 286, 37), ), + zht=Button( + file='./assets/zht/base/page/COMMISSIONS_CHECK.png', + area=(93, 5, 222, 42), + search=(73, 0, 242, 62), + color=(186, 196, 205), + button=(93, 5, 222, 42), + ), ) CRAFTING_CHECK = ButtonWrapper( name='CRAFTING_CHECK', @@ -114,6 +149,13 @@ CRAFTING_CHECK = ButtonWrapper( color=(202, 210, 217), button=(103, 4, 226, 41), ), + zht=Button( + file='./assets/zht/base/page/CRAFTING_CHECK.png', + area=(97, 1, 196, 44), + search=(77, 0, 216, 64), + color=(200, 207, 206), + button=(97, 1, 196, 44), + ), ) EVENT_CHECK = ButtonWrapper( name='EVENT_CHECK', @@ -125,6 +167,13 @@ EVENT_CHECK = ButtonWrapper( color=(200, 209, 216), button=(102, 6, 187, 40), ), + zht=Button( + file='./assets/zht/base/page/EVENT_CHECK.png', + area=(96, 1, 171, 40), + search=(76, 0, 191, 60), + color=(195, 205, 213), + button=(96, 1, 171, 40), + ), ) GACHA_CHECK = ButtonWrapper( name='GACHA_CHECK', @@ -142,6 +191,13 @@ GACHA_CHECK = ButtonWrapper( color=(189, 197, 206), button=(217, 8, 385, 37), ), + zht=Button( + file='./assets/zht/base/page/GACHA_CHECK.png', + area=(94, 0, 221, 40), + search=(74, 0, 241, 60), + color=(191, 200, 209), + button=(94, 0, 221, 40), + ), ) HOME = ButtonWrapper( name='HOME', @@ -179,6 +235,13 @@ MAIL_CHECK = ButtonWrapper( color=(174, 184, 196), button=(107, 11, 216, 37), ), + zht=Button( + file='./assets/zht/base/page/MAIL_CHECK.png', + area=(89, 2, 174, 40), + search=(69, 0, 194, 60), + color=(197, 207, 215), + button=(89, 2, 174, 40), + ), ) MAIN_GO_TO_CAFE = ButtonWrapper( name='MAIN_GO_TO_CAFE', @@ -296,6 +359,13 @@ MAIN_GO_TO_WORK = ButtonWrapper( color=(90, 112, 141), button=(1127, 605, 1250, 637), ), + zht=Button( + file='./assets/zht/base/page/MAIN_GO_TO_WORK.png', + area=(1167, 595, 1277, 637), + search=(1147, 575, 1280, 657), + color=(73, 100, 133), + button=(1167, 595, 1277, 637), + ), ) MISSION_CHECK = ButtonWrapper( name='MISSION_CHECK', @@ -313,6 +383,13 @@ MISSION_CHECK = ButtonWrapper( color=(194, 202, 210), button=(105, 7, 255, 39), ), + zht=Button( + file='./assets/zht/base/page/MISSION_CHECK.png', + area=(97, 3, 222, 37), + search=(77, 0, 242, 57), + color=(174, 185, 196), + button=(97, 3, 222, 37), + ), ) MOMOTALK_CHECK = ButtonWrapper( name='MOMOTALK_CHECK', @@ -350,6 +427,13 @@ SCHEDULE_CHECK = ButtonWrapper( color=(202, 210, 217), button=(101, 5, 200, 40), ), + zht=Button( + file='./assets/zht/base/page/SCHEDULE_CHECK.png', + area=(94, 2, 196, 40), + search=(74, 0, 216, 60), + color=(186, 196, 205), + button=(94, 2, 196, 40), + ), ) SCHOOL_EXCHANGE_CHECK = ButtonWrapper( name='SCHOOL_EXCHANGE_CHECK', @@ -367,6 +451,13 @@ SCHOOL_EXCHANGE_CHECK = ButtonWrapper( color=(200, 208, 215), button=(99, 6, 263, 41), ), + zht=Button( + file='./assets/zht/base/page/SCHOOL_EXCHANGE_CHECK.png', + area=(99, 3, 244, 42), + search=(79, 0, 264, 62), + color=(187, 196, 205), + button=(99, 3, 244, 42), + ), ) SHOP_CHECK = ButtonWrapper( name='SHOP_CHECK', @@ -384,6 +475,13 @@ SHOP_CHECK = ButtonWrapper( color=(188, 197, 207), button=(103, 11, 176, 41), ), + zht=Button( + file='./assets/zht/base/page/SHOP_CHECK.png', + area=(97, 1, 166, 41), + search=(77, 0, 186, 61), + color=(194, 203, 212), + button=(97, 1, 166, 41), + ), ) STORY_CHECK = ButtonWrapper( name='STORY_CHECK', @@ -401,6 +499,13 @@ STORY_CHECK = ButtonWrapper( color=(188, 197, 207), button=(104, 11, 178, 40), ), + zht=Button( + file='./assets/zht/base/page/STORY_CHECK.png', + area=(100, 3, 163, 36), + search=(80, 0, 183, 56), + color=(173, 184, 196), + button=(100, 3, 163, 36), + ), ) TACTICAL_CHALLENGE_CHECK = ButtonWrapper( name='TACTICAL_CHALLENGE_CHECK', @@ -418,6 +523,13 @@ TACTICAL_CHALLENGE_CHECK = ButtonWrapper( color=(190, 199, 207), button=(104, 10, 214, 38), ), + zht=Button( + file='./assets/zht/base/page/TACTICAL_CHALLENGE_CHECK.png', + area=(97, 2, 222, 39), + search=(77, 0, 242, 59), + color=(185, 195, 204), + button=(97, 2, 222, 39), + ), ) TASK_CHECK = ButtonWrapper( name='TASK_CHECK', @@ -435,6 +547,13 @@ TASK_CHECK = ButtonWrapper( color=(185, 194, 204), button=(102, 11, 185, 37), ), + zht=Button( + file='./assets/zht/base/page/TASK_CHECK.png', + area=(536, 83, 607, 128), + search=(516, 63, 627, 148), + color=(77, 92, 87), + button=(536, 83, 607, 128), + ), ) WORK_CHECK = ButtonWrapper( name='WORK_CHECK', @@ -452,6 +571,13 @@ WORK_CHECK = ButtonWrapper( color=(197, 205, 213), button=(105, 5, 244, 41), ), + zht=Button( + file='./assets/zht/base/page/WORK_CHECK.png', + area=(668, 402, 774, 442), + search=(648, 382, 794, 462), + color=(182, 199, 224), + button=(668, 402, 774, 442), + ), ) WORK_GO_TO_BOUNTY = ButtonWrapper( name='WORK_GO_TO_BOUNTY', @@ -469,6 +595,13 @@ WORK_GO_TO_BOUNTY = ButtonWrapper( color=(183, 202, 227), button=(671, 409, 760, 440), ), + zht=Button( + file='./assets/zht/base/page/WORK_GO_TO_BOUNTY.png', + area=(668, 402, 774, 442), + search=(648, 382, 794, 462), + color=(182, 199, 224), + button=(668, 402, 774, 442), + ), ) WORK_GO_TO_COMMISSIONS = ButtonWrapper( name='WORK_GO_TO_COMMISSIONS', @@ -486,6 +619,13 @@ WORK_GO_TO_COMMISSIONS = ButtonWrapper( color=(192, 204, 221), button=(656, 494, 803, 517), ), + zht=Button( + file='./assets/zht/base/page/WORK_GO_TO_COMMISSIONS.png', + area=(656, 487, 759, 526), + search=(636, 467, 779, 546), + color=(194, 207, 223), + button=(656, 487, 759, 526), + ), ) WORK_GO_TO_EVENT = ButtonWrapper( name='WORK_GO_TO_EVENT', @@ -497,6 +637,13 @@ WORK_GO_TO_EVENT = ButtonWrapper( color=(134, 153, 166), button=(67, 131, 142, 201), ), + zht=Button( + file='./assets/zht/base/page/WORK_GO_TO_EVENT.png', + area=(65, 129, 142, 207), + search=(45, 109, 162, 227), + color=(136, 159, 172), + button=(65, 129, 142, 207), + ), ) WORK_GO_TO_MISSION = ButtonWrapper( name='WORK_GO_TO_MISSION', @@ -514,6 +661,13 @@ WORK_GO_TO_MISSION = ButtonWrapper( color=(192, 204, 221), button=(720, 160, 871, 206), ), + zht=Button( + file='./assets/zht/base/page/WORK_GO_TO_MISSION.png', + area=(719, 152, 805, 202), + search=(699, 132, 825, 222), + color=(182, 194, 214), + button=(719, 152, 805, 202), + ), ) WORK_GO_TO_SCHOOL_EXCHANGE = ButtonWrapper( name='WORK_GO_TO_SCHOOL_EXCHANGE', @@ -531,6 +685,13 @@ WORK_GO_TO_SCHOOL_EXCHANGE = ButtonWrapper( color=(190, 203, 221), button=(643, 572, 778, 602), ), + zht=Button( + file='./assets/zht/base/page/WORK_GO_TO_SCHOOL_EXCHANGE.png', + area=(643, 567, 768, 610), + search=(623, 547, 788, 630), + color=(186, 201, 220), + button=(643, 567, 768, 610), + ), ) WORK_GO_TO_STORY = ButtonWrapper( name='WORK_GO_TO_STORY', @@ -548,6 +709,13 @@ WORK_GO_TO_STORY = ButtonWrapper( color=(208, 215, 228), button=(994, 159, 1109, 211), ), + zht=Button( + file='./assets/zht/base/page/WORK_GO_TO_STORY.png', + area=(995, 153, 1086, 201), + search=(975, 133, 1106, 221), + color=(181, 192, 212), + button=(995, 153, 1086, 201), + ), ) WORK_GO_TO_TACTICAL_CHALLENGE = ButtonWrapper( name='WORK_GO_TO_TACTICAL_CHALLENGE', @@ -565,4 +733,11 @@ WORK_GO_TO_TACTICAL_CHALLENGE = ButtonWrapper( color=(199, 211, 227), button=(1012, 532, 1152, 591), ), + zht=Button( + file='./assets/zht/base/page/WORK_GO_TO_TACTICAL_CHALLENGE.png', + area=(1014, 530, 1120, 569), + search=(994, 510, 1140, 589), + color=(190, 201, 219), + button=(1014, 530, 1120, 569), + ), ) diff --git a/tasks/base/assets/assets_base_popup.py b/tasks/base/assets/assets_base_popup.py index 2b1d4d5..8261af0 100644 --- a/tasks/base/assets/assets_base_popup.py +++ b/tasks/base/assets/assets_base_popup.py @@ -19,6 +19,13 @@ AFFECTION_LEVEL_UP = ButtonWrapper( color=(217, 227, 243), button=(882, 244, 1176, 476), ), + zht=Button( + file='./assets/zht/base/popup/AFFECTION_LEVEL_UP.png', + area=(655, 596, 745, 647), + search=(635, 576, 765, 667), + color=(199, 220, 242), + button=(882, 244, 1176, 476), + ), ) AP_EXCEED = ButtonWrapper( name='AP_EXCEED', @@ -36,6 +43,13 @@ AP_EXCEED = ButtonWrapper( color=(197, 205, 212), button=(537, 470, 747, 530), ), + zht=Button( + file='./assets/zht/base/popup/AP_EXCEED.png', + area=(583, 138, 693, 178), + search=(563, 118, 713, 198), + color=(197, 205, 212), + button=(537, 470, 747, 530), + ), ) DAILY_NEWS = ButtonWrapper( name='DAILY_NEWS', @@ -83,6 +97,13 @@ GET_REWARD = ButtonWrapper( color=(211, 210, 90), button=(578, 617, 707, 646), ), + zht=Button( + file='./assets/zht/base/popup/GET_REWARD.png', + area=(587, 131, 630, 155), + search=(567, 111, 650, 175), + color=(225, 224, 92), + button=(574, 610, 713, 651), + ), ) GET_REWARD_SKIP = ButtonWrapper( name='GET_REWARD_SKIP', @@ -100,6 +121,13 @@ GET_REWARD_SKIP = ButtonWrapper( color=(197, 200, 205), button=(1137, 34, 1243, 65), ), + zht=Button( + file='./assets/zht/base/popup/GET_REWARD_SKIP.png', + area=(1137, 34, 1243, 65), + search=(1117, 14, 1263, 85), + color=(197, 200, 205), + button=(1137, 34, 1243, 65), + ), ) INSUFFICIENT_INVENTORY = ButtonWrapper( name='INSUFFICIENT_INVENTORY', @@ -117,6 +145,13 @@ INSUFFICIENT_INVENTORY = ButtonWrapper( color=(202, 209, 216), button=(535, 502, 747, 560), ), + zht=Button( + file='./assets/zht/base/popup/INSUFFICIENT_INVENTORY.png', + area=(578, 117, 703, 152), + search=(558, 97, 723, 172), + color=(202, 209, 216), + button=(535, 502, 747, 560), + ), ) ITEM_EXPIRED = ButtonWrapper( name='ITEM_EXPIRED', @@ -134,6 +169,49 @@ ITEM_EXPIRED = ButtonWrapper( color=(131, 145, 162), button=(537, 487, 742, 553), ), + zht=Button( + file='./assets/zht/base/popup/ITEM_EXPIRED.png', + area=(612, 147, 668, 175), + search=(592, 127, 688, 195), + color=(131, 145, 162), + button=(537, 487, 742, 553), + ), +) +LEVEL_UP = ButtonWrapper( + name='LEVEL_UP', + jp=None, + en=Button( + file='./assets/en/base/popup/LEVEL_UP.png', + area=(722, 210, 746, 238), + search=(702, 190, 766, 258), + color=(184, 202, 219), + button=(571, 559, 713, 601), + ), + zht=Button( + file='./assets/zht/base/popup/LEVEL_UP.png', + area=(722, 210, 746, 238), + search=(702, 190, 766, 258), + color=(184, 202, 219), + button=(571, 559, 713, 601), + ), +) +LOCATION_LEVEL_UP = ButtonWrapper( + name='LOCATION_LEVEL_UP', + jp=None, + en=Button( + file='./assets/en/base/popup/LOCATION_LEVEL_UP.png', + area=(430, 141, 463, 180), + search=(410, 121, 483, 200), + color=(177, 194, 207), + button=(577, 616, 707, 647), + ), + zht=Button( + file='./assets/zht/base/popup/LOCATION_LEVEL_UP.png', + area=(571, 146, 624, 172), + search=(551, 126, 644, 192), + color=(198, 219, 239), + button=(573, 614, 706, 650), + ), ) NETWORK_RECONNECT = ButtonWrapper( name='NETWORK_RECONNECT', @@ -151,6 +229,13 @@ NETWORK_RECONNECT = ButtonWrapper( color=(99, 180, 213), button=(664, 469, 871, 534), ), + zht=Button( + file='./assets/zht/base/popup/NETWORK_RECONNECT.png', + area=(688, 484, 852, 517), + search=(668, 464, 872, 537), + color=(99, 180, 213), + button=(664, 469, 871, 534), + ), ) NETWORK_RECONNECT_OK = ButtonWrapper( name='NETWORK_RECONNECT_OK', @@ -168,4 +253,29 @@ NETWORK_RECONNECT_OK = ButtonWrapper( color=(103, 189, 222), button=(540, 471, 744, 530), ), + zht=Button( + file='./assets/zht/base/popup/NETWORK_RECONNECT_OK.png', + area=(569, 483, 708, 521), + search=(549, 463, 728, 541), + color=(103, 189, 222), + button=(540, 471, 744, 530), + ), +) +QUIT = ButtonWrapper( + name='QUIT', + jp=None, + en=Button( + file='./assets/en/base/popup/QUIT.png', + area=(587, 309, 688, 357), + search=(567, 289, 708, 377), + color=(225, 225, 225), + button=(410, 473, 623, 532), + ), + zht=Button( + file='./assets/zht/base/popup/QUIT.png', + area=(556, 310, 713, 364), + search=(536, 290, 733, 384), + color=(215, 215, 215), + button=(411, 472, 620, 535), + ), ) diff --git a/tasks/base/popup.py b/tasks/base/popup.py index 2559c91..cd89495 100644 --- a/tasks/base/popup.py +++ b/tasks/base/popup.py @@ -105,3 +105,22 @@ class PopupHandler(ModuleBase): return True return False + + def handle_location_level_up(self, interval=5) -> bool: + if self.appear_then_click(LOCATION_LEVEL_UP, interval=interval): + return True + + return False + + def handle_level_up(self, interval=5) -> bool: + if self.appear_then_click(LEVEL_UP, interval=interval): + return True + + return False + + def handle_quit(self, interval=5) -> bool: + if self.appear_then_click(QUIT, interval=interval): + return True + + return False + \ No newline at end of file diff --git a/tasks/base/ui.py b/tasks/base/ui.py index b89219b..41dce08 100644 --- a/tasks/base/ui.py +++ b/tasks/base/ui.py @@ -1,11 +1,13 @@ from module.base.button import ButtonWrapper -from module.base.decorator import run_once +from module.base.decorator import run_once, Config from module.base.timer import Timer -from module.exception import GameNotRunningError, GamePageUnknownError +from module.base.utils import get_color +from module.exception import GameNotRunningError, GamePageUnknownError, RequestHumanTakeover from module.logger import logger -from module.ocr.ocr import Ocr +from module.ocr.ocr import Ocr, Digit from tasks.base.main_page import MainPage from tasks.base.page import Page, page_main +from tasks.login.assets.assets_login import LOGIN_LOADING, OCR_YEAR from tasks.base.assets.assets_base_page import BACK @@ -13,6 +15,16 @@ class UI(MainPage): ui_current: Page ui_main_confirm_timer = Timer(0.2, count=2) + @Config.when(Emulator_GameLanguage='zhs') + def appear_trademark_year(self): + ocr_year = Digit(OCR_YEAR).ocr_single_line(self.device.image) + return ocr_year == 2023 + + @Config.when(Emulator_GameLanguage=None) + def appear_trademark_year(self): + ocr_year = Digit(OCR_YEAR).ocr_single_line(self.device.image) + return ocr_year == 2021 + def ui_page_appear(self, page): """ Args: @@ -50,6 +62,7 @@ class UI(MainPage): timeout = Timer(10, count=20).start() back_timer = Timer(0.5, count=2) + u2_back = True while 1: if skip_first_screenshot: skip_first_screenshot = False @@ -78,8 +91,20 @@ class UI(MainPage): timeout.reset() continue if back_timer.reached_and_reset(): + # this might be bad but it works + if self.match_color(LOGIN_LOADING, interval=5, threshold=80) or self.appear_trademark_year(): + from tasks.login.login import Login + Login(self.config, self.device).handle_app_login() + timeout.reset() + continue logger.info("Unknown page, try to back") - self.device.click(BACK) + # allows TooManyClicks to be triggered in case something goes wrong + if u2_back: + self.device.back() + u2_back = False + else: + self.device.click(BACK) + u2_back = True app_check() minicap_check() @@ -107,7 +132,7 @@ class UI(MainPage): self.interval_clear(list(Page.iter_check_buttons())) # loading_timer = Timer(0.5) - + back_timer = Timer(15,15) logger.hr(f"UI goto {destination}") while 1: if skip_first_screenshot: @@ -126,6 +151,7 @@ class UI(MainPage): # Destination page if self.ui_page_appear(destination): logger.info(f'Page arrive: {destination}') + self.close_popup(destination.check_button) if self.ui_page_confirm(destination): logger.info(f'Page arrive confirm {destination}') break @@ -137,6 +163,7 @@ class UI(MainPage): continue if self.appear(page.check_button, interval=5): logger.info(f'Page switch: {page} -> {page.parent}') + self.close_popup(page.check_button) # self.handle_lang_check(page) if self.ui_page_confirm(page): logger.info(f'Page arrive confirm {page}') @@ -152,6 +179,19 @@ class UI(MainPage): if self.ui_additional(): continue + back_timer.start() + if back_timer.reached(): + if self.match_color(LOGIN_LOADING, interval=5, threshold=80) or self.appear_trademark_year(): + from tasks.login.login import Login + Login(self.config, self.device).handle_app_login() + # don't click back when screen is black. + # Useful for loading screen after switching between pages + elif [x for x in get_color(self.device.image, BACK.area) if x > 50]: + self.device.back() + logger.info("Unknown page, try to back") + back_timer.reset() + + # Reset connection Page.clear_connection() @@ -176,6 +216,7 @@ class UI(MainPage): if self.ui_current == destination: logger.info("Already at %s" % destination) + self.close_popup(destination.check_button) return False else: logger.info("Goto %s" % destination) @@ -337,18 +378,22 @@ class UI(MainPage): return True if self.handle_daily_news(): return True + if self.handle_quit(): + return True if self.handle_network_reconnect(): return True if self.handle_affection_level_up(): return True if self.handle_new_student(): return True - if self.handle_ap_exceed(): - return True - if self.handle_insufficient_inventory(): - return True - if self.handle_item_expired(): - return True + # disabled because will exit the game if quit appears + + #if self.handle_ap_exceed(): + # return True + #if self.handle_insufficient_inventory(): + # return True + #if self.handle_item_expired(): + # return True return False @@ -399,3 +444,18 @@ class UI(MainPage): button (Button): """ pass + + def close_popup(self, check_button): + if not self.match_color(check_button): + timer = Timer(5, 5).start() + wait = Timer(1).start() + while 1: + self.device.screenshot() + if self.match_color(check_button) or not self.appear(check_button): + break + self.device.back() + if timer.reached(): + logger.error("Failed to close popup") + raise RequestHumanTakeover + while not wait.reached(): + pass \ No newline at end of file diff --git a/tasks/bounty/assets/assets_bounty.py b/tasks/bounty/assets/assets_bounty.py index a10d2a7..2f55c21 100644 --- a/tasks/bounty/assets/assets_bounty.py +++ b/tasks/bounty/assets/assets_bounty.py @@ -19,6 +19,13 @@ CHECK_BOUNTY = ButtonWrapper( color=(92, 116, 141), button=(654, 87, 891, 126), ), + zht=Button( + file='./assets/zht/bounty/CHECK_BOUNTY.png', + area=(651, 84, 891, 130), + search=(631, 64, 911, 150), + color=(81, 107, 134), + button=(651, 84, 891, 130), + ), ) CHECK_DESERT_RAILROAD = ButtonWrapper( name='CHECK_DESERT_RAILROAD', @@ -36,6 +43,13 @@ CHECK_DESERT_RAILROAD = ButtonWrapper( color=(200, 207, 211), button=(105, 144, 490, 183), ), + zht=Button( + file='./assets/zht/bounty/CHECK_DESERT_RAILROAD.png', + area=(97, 133, 402, 184), + search=(77, 113, 422, 204), + color=(199, 206, 210), + button=(97, 133, 402, 184), + ), ) CHECK_HIGHWAY = ButtonWrapper( name='CHECK_HIGHWAY', @@ -53,6 +67,13 @@ CHECK_HIGHWAY = ButtonWrapper( color=(206, 213, 217), button=(104, 143, 391, 188), ), + zht=Button( + file='./assets/zht/bounty/CHECK_HIGHWAY.png', + area=(94, 131, 408, 186), + search=(74, 111, 428, 206), + color=(204, 211, 214), + button=(94, 131, 408, 186), + ), ) CHECK_SCHOOLHOUSE = ButtonWrapper( name='CHECK_SCHOOLHOUSE', @@ -70,6 +91,13 @@ CHECK_SCHOOLHOUSE = ButtonWrapper( color=(203, 210, 214), button=(102, 144, 408, 185), ), + zht=Button( + file='./assets/zht/bounty/CHECK_SCHOOLHOUSE.png', + area=(97, 139, 343, 183), + search=(77, 119, 363, 203), + color=(195, 201, 205), + button=(97, 139, 343, 183), + ), ) OCR_TICKET = ButtonWrapper( name='OCR_TICKET', @@ -87,6 +115,13 @@ OCR_TICKET = ButtonWrapper( color=(177, 194, 207), button=(229, 89, 285, 112), ), + zht=Button( + file='./assets/zht/bounty/OCR_TICKET.png', + area=(155, 81, 206, 119), + search=(135, 61, 226, 139), + color=(209, 217, 221), + button=(155, 81, 206, 119), + ), ) SELECT_DESERT_RAILROAD = ButtonWrapper( name='SELECT_DESERT_RAILROAD', @@ -104,6 +139,13 @@ SELECT_DESERT_RAILROAD = ButtonWrapper( color=(196, 203, 212), button=(989, 270, 1223, 308), ), + zht=Button( + file='./assets/zht/bounty/SELECT_DESERT_RAILROAD.png', + area=(1082, 266, 1229, 312), + search=(1062, 246, 1249, 332), + color=(192, 200, 210), + button=(1082, 266, 1229, 312), + ), ) SELECT_HIGHWAY = ButtonWrapper( name='SELECT_HIGHWAY', @@ -121,6 +163,13 @@ SELECT_HIGHWAY = ButtonWrapper( color=(192, 201, 211), button=(1073, 167, 1223, 202), ), + zht=Button( + file='./assets/zht/bounty/SELECT_HIGHWAY.png', + area=(1083, 157, 1231, 206), + search=(1063, 137, 1251, 226), + color=(197, 205, 215), + button=(1083, 157, 1231, 206), + ), ) SELECT_SCHOOLHOUSE = ButtonWrapper( name='SELECT_SCHOOLHOUSE', @@ -138,4 +187,11 @@ SELECT_SCHOOLHOUSE = ButtonWrapper( color=(198, 206, 215), button=(1055, 378, 1226, 415), ), + zht=Button( + file='./assets/zht/bounty/SELECT_SCHOOLHOUSE.png', + area=(1143, 374, 1233, 420), + search=(1123, 354, 1253, 440), + color=(195, 206, 216), + button=(1143, 374, 1233, 420), + ), ) diff --git a/tasks/cafe/assets/assets_cafe.py b/tasks/cafe/assets/assets_cafe.py index f058f38..6c54756 100644 --- a/tasks/cafe/assets/assets_cafe.py +++ b/tasks/cafe/assets/assets_cafe.py @@ -39,6 +39,13 @@ CAFE_FIRST = ButtonWrapper( color=(111, 127, 147), button=(82, 152, 136, 175), ), + zht=Button( + file='./assets/zht/cafe/CAFE_FIRST.png', + area=(82, 152, 136, 175), + search=(62, 132, 156, 195), + color=(111, 127, 147), + button=(82, 152, 136, 175), + ), ) CAFE_INVITE = ButtonWrapper( name='CAFE_INVITE', @@ -56,6 +63,13 @@ CAFE_INVITE = ButtonWrapper( color=(173, 182, 192), button=(816, 635, 845, 655), ), + zht=Button( + file='./assets/zht/cafe/CAFE_INVITE.png', + area=(816, 635, 845, 655), + search=(796, 615, 865, 675), + color=(173, 182, 192), + button=(816, 635, 845, 655), + ), ) CAFE_INVITED = ButtonWrapper( name='CAFE_INVITED', @@ -73,6 +87,13 @@ CAFE_INVITED = ButtonWrapper( color=(144, 144, 146), button=(815, 633, 847, 657), ), + zht=Button( + file='./assets/zht/cafe/CAFE_INVITED.png', + area=(815, 633, 847, 657), + search=(795, 613, 867, 677), + color=(144, 144, 146), + button=(815, 633, 847, 657), + ), ) CAFE_SECOND = ButtonWrapper( name='CAFE_SECOND', @@ -90,6 +111,13 @@ CAFE_SECOND = ButtonWrapper( color=(110, 126, 146), button=(219, 152, 279, 175), ), + zht=Button( + file='./assets/zht/cafe/CAFE_SECOND.png', + area=(219, 152, 279, 175), + search=(199, 132, 299, 195), + color=(110, 126, 146), + button=(219, 152, 279, 175), + ), ) CHANGE_CAFE_NOT_SELECTED = ButtonWrapper( name='CHANGE_CAFE_NOT_SELECTED', @@ -107,6 +135,13 @@ CHANGE_CAFE_NOT_SELECTED = ButtonWrapper( color=(185, 193, 203), button=(84, 89, 178, 109), ), + zht=Button( + file='./assets/zht/cafe/CHANGE_CAFE_NOT_SELECTED.png', + area=(84, 89, 178, 109), + search=(64, 69, 198, 129), + color=(185, 193, 203), + button=(84, 89, 178, 109), + ), ) CHANGE_CAFE_SELECTED = ButtonWrapper( name='CHANGE_CAFE_SELECTED', @@ -124,6 +159,13 @@ CHANGE_CAFE_SELECTED = ButtonWrapper( color=(82, 105, 130), button=(40, 87, 191, 112), ), + zht=Button( + file='./assets/zht/cafe/CHANGE_CAFE_SELECTED.png', + area=(40, 87, 191, 112), + search=(20, 67, 211, 132), + color=(82, 105, 130), + button=(40, 87, 191, 112), + ), ) CHECK_MOMOTALK = ButtonWrapper( name='CHECK_MOMOTALK', @@ -141,6 +183,13 @@ CHECK_MOMOTALK = ButtonWrapper( color=(253, 203, 212), button=(421, 83, 447, 108), ), + zht=Button( + file='./assets/zht/cafe/CHECK_MOMOTALK.png', + area=(421, 83, 447, 108), + search=(401, 63, 467, 128), + color=(253, 203, 212), + button=(421, 83, 447, 108), + ), ) CHECK_REWARD = ButtonWrapper( name='CHECK_REWARD', @@ -158,6 +207,13 @@ CHECK_REWARD = ButtonWrapper( color=(64, 88, 115), button=(1086, 611, 1229, 685), ), + zht=Button( + file='./assets/zht/cafe/CHECK_REWARD.png', + area=(1087, 609, 1222, 644), + search=(1067, 589, 1242, 664), + color=(70, 94, 120), + button=(1086, 613, 1229, 682), + ), ) CLICKABLE_TEMPLATE = ButtonWrapper( name='CLICKABLE_TEMPLATE', @@ -185,6 +241,13 @@ GET_REWARD = ButtonWrapper( color=(208, 190, 63), button=(539, 491, 741, 555), ), + zht=Button( + file='./assets/zht/cafe/GET_REWARD.png', + area=(600, 499, 681, 545), + search=(580, 479, 701, 565), + color=(204, 186, 62), + button=(543, 490, 740, 555), + ), ) GET_REWARD_CLOSE = ButtonWrapper( name='GET_REWARD_CLOSE', @@ -202,6 +265,13 @@ GET_REWARD_CLOSE = ButtonWrapper( color=(215, 220, 224), button=(883, 134, 926, 178), ), + zht=Button( + file='./assets/zht/cafe/GET_REWARD_CLOSE.png', + area=(883, 134, 926, 178), + search=(863, 114, 946, 198), + color=(215, 220, 224), + button=(883, 134, 926, 178), + ), ) GOT_REWARD = ButtonWrapper( name='GOT_REWARD', @@ -219,6 +289,13 @@ GOT_REWARD = ButtonWrapper( color=(211, 212, 212), button=(543, 489, 741, 558), ), + zht=Button( + file='./assets/zht/cafe/GOT_REWARD.png', + area=(542, 490, 737, 556), + search=(522, 470, 757, 576), + color=(211, 212, 211), + button=(542, 490, 737, 556), + ), ) INVENTORY = ButtonWrapper( name='INVENTORY', @@ -236,6 +313,13 @@ INVENTORY = ButtonWrapper( color=(197, 204, 212), button=(1123, 90, 1165, 130), ), + zht=Button( + file='./assets/zht/cafe/INVENTORY.png', + area=(603, 87, 679, 128), + search=(583, 67, 699, 148), + color=(191, 199, 207), + button=(1123, 90, 1165, 130), + ), ) INVITE_CONFIRM = ButtonWrapper( name='INVITE_CONFIRM', @@ -253,6 +337,13 @@ INVITE_CONFIRM = ButtonWrapper( color=(169, 179, 191), button=(664, 470, 872, 534), ), + zht=Button( + file='./assets/zht/cafe/INVITE_CONFIRM.png', + area=(595, 142, 677, 181), + search=(575, 122, 697, 201), + color=(186, 195, 203), + button=(663, 474, 874, 532), + ), ) INVITE_IN_SECOND = ButtonWrapper( name='INVITE_IN_SECOND', @@ -270,6 +361,13 @@ INVITE_IN_SECOND = ButtonWrapper( color=(166, 177, 188), button=(482, 147, 799, 177), ), + zht=Button( + file='./assets/zht/cafe/INVITE_IN_SECOND.png', + area=(482, 147, 799, 177), + search=(462, 127, 819, 197), + color=(166, 177, 188), + button=(482, 147, 799, 177), + ), ) INVITE_IN_SECOND_CLOSE = ButtonWrapper( name='INVITE_IN_SECOND_CLOSE', @@ -287,6 +385,13 @@ INVITE_IN_SECOND_CLOSE = ButtonWrapper( color=(180, 189, 198), button=(874, 150, 900, 176), ), + zht=Button( + file='./assets/zht/cafe/INVITE_IN_SECOND_CLOSE.png', + area=(874, 150, 900, 176), + search=(854, 130, 920, 196), + color=(180, 189, 198), + button=(874, 150, 900, 176), + ), ) INVITE_SUBSTITUTE = ButtonWrapper( name='INVITE_SUBSTITUTE', @@ -304,6 +409,13 @@ INVITE_SUBSTITUTE = ButtonWrapper( color=(176, 186, 196), button=(673, 477, 857, 542), ), + zht=Button( + file='./assets/zht/cafe/INVITE_SUBSTITUTE.png', + area=(506, 157, 775, 186), + search=(486, 137, 795, 206), + color=(176, 186, 196), + button=(673, 477, 857, 542), + ), ) INVITE_SUBSTITUTE_CLOSE = ButtonWrapper( name='INVITE_SUBSTITUTE_CLOSE', @@ -321,6 +433,13 @@ INVITE_SUBSTITUTE_CLOSE = ButtonWrapper( color=(180, 189, 199), button=(867, 158, 893, 184), ), + zht=Button( + file='./assets/zht/cafe/INVITE_SUBSTITUTE_CLOSE.png', + area=(867, 158, 893, 184), + search=(847, 138, 913, 204), + color=(180, 189, 199), + button=(867, 158, 893, 184), + ), ) MOMOTALK_CLOSE = ButtonWrapper( name='MOMOTALK_CLOSE', @@ -338,6 +457,13 @@ MOMOTALK_CLOSE = ButtonWrapper( color=(252, 182, 194), button=(824, 82, 850, 108), ), + zht=Button( + file='./assets/zht/cafe/MOMOTALK_CLOSE.png', + area=(824, 82, 850, 108), + search=(804, 62, 870, 128), + color=(252, 182, 194), + button=(824, 82, 850, 108), + ), ) MOMOTALK_INVITE = ButtonWrapper( name='MOMOTALK_INVITE', @@ -355,6 +481,13 @@ MOMOTALK_INVITE = ButtonWrapper( color=(98, 179, 211), button=(755, 210, 817, 233), ), + zht=Button( + file='./assets/zht/cafe/MOMOTALK_INVITE.png', + area=(757, 204, 818, 239), + search=(737, 184, 838, 259), + color=(103, 189, 222), + button=(757, 204, 818, 239), + ), ) MOMOTALK_ITEM = ButtonWrapper( name='MOMOTALK_ITEM', @@ -372,6 +505,13 @@ MOMOTALK_ITEM = ButtonWrapper( color=(203, 230, 240), button=(489, 193, 864, 259), ), + zht=Button( + file='./assets/zht/cafe/MOMOTALK_ITEM.png', + area=(491, 186, 872, 264), + search=(471, 166, 892, 284), + color=(209, 232, 241), + button=(491, 186, 872, 264), + ), ) OCR_CAFE = ButtonWrapper( name='OCR_CAFE', @@ -389,6 +529,13 @@ OCR_CAFE = ButtonWrapper( color=(84, 104, 127), button=(1105, 639, 1195, 674), ), + zht=Button( + file='./assets/zht/cafe/OCR_CAFE.png', + area=(1072, 639, 1232, 679), + search=(1052, 619, 1252, 699), + color=(71, 93, 118), + button=(1072, 639, 1232, 679), + ), ) OCR_NAME = ButtonWrapper( name='OCR_NAME', @@ -406,6 +553,13 @@ OCR_NAME = ButtonWrapper( color=(237, 239, 241), button=(488, 194, 704, 588), ), + zht=Button( + file='./assets/zht/cafe/OCR_NAME.png', + area=(488, 194, 704, 588), + search=(468, 174, 724, 608), + color=(237, 239, 241), + button=(488, 194, 704, 588), + ), ) STUDENT_LIST = ButtonWrapper( name='STUDENT_LIST', @@ -423,4 +577,11 @@ STUDENT_LIST = ButtonWrapper( color=(195, 202, 210), button=(548, 426, 739, 493), ), + zht=Button( + file='./assets/zht/cafe/STUDENT_LIST.png', + area=(600, 168, 677, 204), + search=(580, 148, 697, 224), + color=(178, 187, 197), + button=(540, 425, 742, 492), + ), ) diff --git a/tasks/circle/assets/assets_circle.py b/tasks/circle/assets/assets_circle.py index 2a5f4e3..bf97933 100644 --- a/tasks/circle/assets/assets_circle.py +++ b/tasks/circle/assets/assets_circle.py @@ -19,4 +19,11 @@ GET_REWARD_AP = ButtonWrapper( color=(204, 212, 219), button=(545, 460, 741, 521), ), + zht=Button( + file='./assets/zht/circle/GET_REWARD_AP.png', + area=(539, 145, 740, 175), + search=(519, 125, 760, 195), + color=(160, 172, 184), + button=(540, 456, 741, 521), + ), ) diff --git a/tasks/login/assets/assets_login.py b/tasks/login/assets/assets_login.py index 878bfb0..a3c3277 100644 --- a/tasks/login/assets/assets_login.py +++ b/tasks/login/assets/assets_login.py @@ -19,6 +19,13 @@ LOGIN_CONFIRM = ButtonWrapper( color=(216, 220, 225), button=(990, 354, 1232, 506), ), + zht=Button( + file='./assets/zht/login/LOGIN_CONFIRM.png', + area=(35, 622, 96, 654), + search=(15, 602, 116, 674), + color=(212, 216, 221), + button=(990, 354, 1232, 506), + ), ) LOGIN_LOADING = ButtonWrapper( name='LOGIN_LOADING', @@ -36,6 +43,31 @@ LOGIN_LOADING = ButtonWrapper( color=(8, 66, 96), button=(34, 682, 60, 707), ), + zht=Button( + file='./assets/zht/login/LOGIN_LOADING.png', + area=(34, 682, 60, 707), + search=(14, 662, 80, 720), + color=(8, 66, 96), + button=(34, 682, 60, 707), + ), +) +OCR_YEAR = ButtonWrapper( + name='OCR_YEAR', + jp=None, + en=Button( + file='./assets/en/login/OCR_YEAR.png', + area=(377, 689, 414, 701), + search=(357, 669, 434, 720), + color=(160, 157, 158), + button=(377, 689, 414, 701), + ), + zht=Button( + file='./assets/zht/login/OCR_YEAR.png', + area=(377, 689, 414, 701), + search=(357, 669, 434, 720), + color=(160, 157, 158), + button=(377, 689, 414, 701), + ), ) SURVEY = ButtonWrapper( name='SURVEY', @@ -47,6 +79,13 @@ SURVEY = ButtonWrapper( color=(211, 223, 166), button=(1199, 6, 1264, 75), ), + zht=Button( + file='./assets/zht/login/SURVEY.png', + area=(946, 269, 994, 307), + search=(926, 249, 1014, 327), + color=(211, 223, 166), + button=(1199, 6, 1264, 75), + ), ) UPDATE = ButtonWrapper( name='UPDATE', @@ -64,4 +103,11 @@ UPDATE = ButtonWrapper( color=(216, 216, 216), button=(665, 472, 872, 531), ), + zht=Button( + file='./assets/zht/login/UPDATE.png', + area=(446, 258, 686, 301), + search=(426, 238, 706, 321), + color=(216, 216, 216), + button=(665, 472, 872, 531), + ), ) diff --git a/tasks/login/login.py b/tasks/login/login.py index f6eaf9c..a9d602a 100644 --- a/tasks/login/login.py +++ b/tasks/login/login.py @@ -1,11 +1,9 @@ from module.base.timer import Timer -from module.base.decorator import Config from module.exception import GameNotRunningError from module.logger import logger from tasks.base.page import page_main from tasks.base.ui import UI -from tasks.login.assets.assets_login import LOGIN_CONFIRM, LOGIN_LOADING, UPDATE, SURVEY -from tasks.base.assets.assets_base_page import MAIN_GO_TO_MAIL +from tasks.login.assets.assets_login import LOGIN_CONFIRM, LOGIN_LOADING, UPDATE class Login(UI): @@ -31,20 +29,11 @@ class Login(UI): return True return False - @Config.when(Emulator_GameLanguage='en') - def _handle_survey(self): - if self.appear_then_click(SURVEY): - return True - return False - - @Config.when(Emulator_GameLanguage=None) - def _handle_survey(self): - pass - logger.hr('App login') orientation_timer = Timer(5) startup_timer = Timer(5).start() app_timer = Timer(5).start() + back_timer = Timer(2).start() login_success = False while 1: @@ -73,10 +62,11 @@ class Login(UI): break # Watch resource downloading and loading + loading = False if self.match_color(LOGIN_LOADING, interval=5, threshold=45): logger.info('Game resources downloading or loading') self.device.stuck_record_clear() - + loading = True # Login if self.appear_then_click(LOGIN_CONFIRM): login_success = True @@ -90,14 +80,10 @@ class Login(UI): # continue if self.appear_then_click(UPDATE): continue - if _handle_survey(self): - continue if self.ui_additional(): continue - # press emulator back button when random popup in main - if self.appear(MAIN_GO_TO_MAIL) and not self.match_color(MAIN_GO_TO_MAIL): - self.device.u2.press("back") - continue + if not loading and back_timer.reached_and_reset() and not self.appear_trademark_year(): + self.device.back() return True diff --git a/tasks/mail/assets/assets_mail.py b/tasks/mail/assets/assets_mail.py index 26049be..234af31 100644 --- a/tasks/mail/assets/assets_mail.py +++ b/tasks/mail/assets/assets_mail.py @@ -19,6 +19,13 @@ MAIL_RECEIVE = ButtonWrapper( color=(207, 188, 63), button=(1047, 643, 1231, 700), ), + zht=Button( + file='./assets/zht/mail/MAIL_RECEIVE.png', + area=(1045, 641, 1229, 696), + search=(1025, 621, 1249, 716), + color=(231, 214, 68), + button=(1045, 641, 1229, 696), + ), ) MAIL_RECEIVED = ButtonWrapper( name='MAIL_RECEIVED', @@ -36,4 +43,11 @@ MAIL_RECEIVED = ButtonWrapper( color=(204, 205, 206), button=(1072, 649, 1197, 686), ), + zht=Button( + file='./assets/zht/mail/MAIL_RECEIVED.png', + area=(1042, 643, 1230, 704), + search=(1022, 623, 1250, 720), + color=(209, 210, 211), + button=(1042, 643, 1230, 704), + ), ) diff --git a/tasks/mission/assets/assets_mission.py b/tasks/mission/assets/assets_mission.py index caecaed..e48a060 100644 --- a/tasks/mission/assets/assets_mission.py +++ b/tasks/mission/assets/assets_mission.py @@ -3,17 +3,6 @@ from module.base.button import Button, ButtonWrapper # This file was auto-generated, do not modify it manually. To generate: # ``` python -m dev_tools.button_extract ``` -CHECK_BD = ButtonWrapper( - name='CHECK_BD', - jp=None, - en=Button( - file='./assets/en/mission/CHECK_BD.png', - area=(94, 135, 325, 194), - search=(74, 115, 345, 214), - color=(208, 215, 220), - button=(94, 135, 325, 194), - ), -) CHECK_COMMISSIONS = ButtonWrapper( name='CHECK_COMMISSIONS', jp=None, @@ -24,17 +13,31 @@ CHECK_COMMISSIONS = ButtonWrapper( color=(70, 96, 124), button=(646, 78, 909, 135), ), + zht=Button( + file='./assets/zht/mission/CHECK_COMMISSIONS.png', + area=(650, 83, 886, 136), + search=(630, 63, 906, 156), + color=(78, 104, 131), + button=(650, 83, 886, 136), + ), ) -CHECK_IR = ButtonWrapper( - name='CHECK_IR', +CHECK_CR = ButtonWrapper( + name='CHECK_CR', jp=None, en=Button( - file='./assets/en/mission/CHECK_IR.png', + file='./assets/en/mission/CHECK_CR.png', area=(97, 137, 340, 191), search=(77, 117, 360, 211), color=(213, 220, 223), button=(97, 137, 340, 191), ), + zht=Button( + file='./assets/zht/mission/CHECK_CR.png', + area=(93, 143, 304, 183), + search=(73, 123, 324, 203), + color=(188, 194, 198), + button=(93, 143, 304, 183), + ), ) CHECK_MISSION_SWEEP = ButtonWrapper( name='CHECK_MISSION_SWEEP', @@ -46,6 +49,103 @@ CHECK_MISSION_SWEEP = ButtonWrapper( color=(208, 213, 219), button=(654, 184, 703, 209), ), + zht=Button( + file='./assets/zht/mission/CHECK_MISSION_SWEEP.png', + area=(656, 187, 698, 207), + search=(636, 167, 718, 227), + color=(201, 207, 214), + button=(656, 187, 698, 207), + ), +) +CHECK_XP = ButtonWrapper( + name='CHECK_XP', + jp=None, + en=Button( + file='./assets/en/mission/CHECK_XP.png', + area=(94, 135, 325, 194), + search=(74, 115, 345, 214), + color=(208, 215, 220), + button=(94, 135, 325, 194), + ), + zht=Button( + file='./assets/zht/mission/CHECK_XP.png', + area=(98, 141, 240, 183), + search=(78, 121, 260, 203), + color=(188, 194, 197), + button=(98, 141, 240, 183), + ), +) +EVENT_INDEX = ButtonWrapper( + name='EVENT_INDEX', + jp=None, + en=Button( + file='./assets/en/mission/EVENT_INDEX.png', + area=(704, 135, 761, 694), + search=(684, 115, 781, 714), + color=(189, 197, 195), + button=(704, 135, 761, 694), + ), + zht=Button( + file='./assets/zht/mission/EVENT_INDEX.png', + area=(704, 135, 761, 694), + search=(684, 115, 781, 714), + color=(189, 197, 195), + button=(704, 135, 761, 694), + ), +) +EVENT_ITEM = ButtonWrapper( + name='EVENT_ITEM', + jp=None, + en=Button( + file='./assets/en/mission/EVENT_ITEM.png', + area=(691, 136, 1198, 232), + search=(671, 116, 1218, 252), + color=(201, 219, 224), + button=(691, 136, 1198, 232), + ), + zht=Button( + file='./assets/zht/mission/EVENT_ITEM.png', + area=(691, 136, 1198, 232), + search=(671, 116, 1218, 252), + color=(201, 219, 224), + button=(691, 136, 1198, 232), + ), +) +EVENT_LIST = ButtonWrapper( + name='EVENT_LIST', + jp=None, + en=Button( + file='./assets/en/mission/EVENT_LIST.png', + area=(695, 137, 1196, 688), + search=(675, 117, 1216, 708), + color=(171, 185, 190), + button=(695, 137, 1196, 688), + ), + zht=Button( + file='./assets/zht/mission/EVENT_LIST.png', + area=(695, 137, 1196, 688), + search=(675, 117, 1216, 708), + color=(171, 185, 190), + button=(695, 137, 1196, 688), + ), +) +EVENT_STARS = ButtonWrapper( + name='EVENT_STARS', + jp=None, + en=Button( + file='./assets/en/mission/EVENT_STARS.png', + area=(704, 186, 761, 218), + search=(684, 166, 781, 238), + color=(228, 223, 194), + button=(704, 186, 761, 218), + ), + zht=Button( + file='./assets/zht/mission/EVENT_STARS.png', + area=(704, 186, 761, 218), + search=(684, 166, 781, 238), + color=(228, 223, 194), + button=(704, 186, 761, 218), + ), ) HARD_OFF = ButtonWrapper( name='HARD_OFF', @@ -57,6 +157,13 @@ HARD_OFF = ButtonWrapper( color=(242, 246, 248), button=(947, 132, 1193, 182), ), + zht=Button( + file='./assets/zht/mission/HARD_OFF.png', + area=(947, 132, 1193, 182), + search=(927, 112, 1213, 202), + color=(242, 246, 248), + button=(947, 132, 1193, 182), + ), ) HARD_ON = ButtonWrapper( name='HARD_ON', @@ -68,6 +175,13 @@ HARD_ON = ButtonWrapper( color=(200, 71, 63), button=(940, 133, 1189, 186), ), + zht=Button( + file='./assets/zht/mission/HARD_ON.png', + area=(940, 133, 1189, 186), + search=(920, 113, 1209, 206), + color=(200, 71, 63), + button=(940, 133, 1189, 186), + ), ) LEFT = ButtonWrapper( name='LEFT', @@ -79,6 +193,13 @@ LEFT = ButtonWrapper( color=(193, 224, 241), button=(0, 301, 89, 408), ), + zht=Button( + file='./assets/zht/mission/LEFT.png', + area=(0, 301, 89, 408), + search=(0, 281, 109, 428), + color=(193, 224, 241), + button=(0, 301, 89, 408), + ), ) NORMAL_OFF = ButtonWrapper( name='NORMAL_OFF', @@ -90,6 +211,13 @@ NORMAL_OFF = ButtonWrapper( color=(238, 243, 246), button=(682, 135, 927, 182), ), + zht=Button( + file='./assets/zht/mission/NORMAL_OFF.png', + area=(682, 135, 927, 182), + search=(662, 115, 947, 202), + color=(238, 243, 246), + button=(682, 135, 927, 182), + ), ) NORMAL_ON = ButtonWrapper( name='NORMAL_ON', @@ -101,6 +229,13 @@ NORMAL_ON = ButtonWrapper( color=(62, 81, 89), button=(682, 137, 924, 185), ), + zht=Button( + file='./assets/zht/mission/NORMAL_ON.png', + area=(682, 137, 924, 185), + search=(662, 117, 944, 205), + color=(62, 81, 89), + button=(682, 137, 924, 185), + ), ) OCR_AREA = ButtonWrapper( name='OCR_AREA', @@ -112,6 +247,13 @@ OCR_AREA = ButtonWrapper( color=(237, 238, 240), button=(108, 176, 176, 219), ), + zht=Button( + file='./assets/zht/mission/OCR_AREA.png', + area=(108, 176, 176, 219), + search=(88, 156, 196, 239), + color=(237, 238, 240), + button=(108, 176, 176, 219), + ), ) QUEST_OFF = ButtonWrapper( name='QUEST_OFF', @@ -123,6 +265,13 @@ QUEST_OFF = ButtonWrapper( color=(231, 235, 235), button=(859, 69, 1025, 125), ), + zht=Button( + file='./assets/zht/mission/QUEST_OFF.png', + area=(859, 69, 1025, 125), + search=(839, 49, 1045, 145), + color=(231, 235, 235), + button=(859, 69, 1025, 125), + ), ) QUEST_ON = ButtonWrapper( name='QUEST_ON', @@ -134,6 +283,13 @@ QUEST_ON = ButtonWrapper( color=(49, 68, 76), button=(861, 71, 1025, 124), ), + zht=Button( + file='./assets/zht/mission/QUEST_ON.png', + area=(861, 71, 1025, 124), + search=(841, 51, 1045, 144), + color=(49, 68, 76), + button=(861, 71, 1025, 124), + ), ) RIGHT = ButtonWrapper( name='RIGHT', @@ -145,26 +301,47 @@ RIGHT = ButtonWrapper( color=(193, 223, 241), button=(1202, 311, 1280, 412), ), -) -SELECT_BD = ButtonWrapper( - name='SELECT_BD', - jp=None, - en=Button( - file='./assets/en/mission/SELECT_BD.png', - area=(1016, 165, 1227, 211), - search=(996, 145, 1247, 231), - color=(205, 212, 220), - button=(1016, 165, 1227, 211), + zht=Button( + file='./assets/zht/mission/RIGHT.png', + area=(1202, 311, 1280, 412), + search=(1182, 291, 1280, 432), + color=(193, 223, 241), + button=(1202, 311, 1280, 412), ), ) -SELECT_IR = ButtonWrapper( - name='SELECT_IR', +SELECT_CR = ButtonWrapper( + name='SELECT_CR', jp=None, en=Button( - file='./assets/en/mission/SELECT_IR.png', + file='./assets/en/mission/SELECT_CR.png', area=(1004, 267, 1237, 321), search=(984, 247, 1257, 341), color=(214, 220, 227), button=(1004, 267, 1237, 321), ), + zht=Button( + file='./assets/zht/mission/SELECT_CR.png', + area=(1029, 272, 1225, 311), + search=(1009, 252, 1245, 331), + color=(178, 187, 198), + button=(1029, 272, 1225, 311), + ), +) +SELECT_XP = ButtonWrapper( + name='SELECT_XP', + jp=None, + en=Button( + file='./assets/en/mission/SELECT_XP.png', + area=(1016, 165, 1227, 211), + search=(996, 145, 1247, 231), + color=(205, 212, 220), + button=(1016, 165, 1227, 211), + ), + zht=Button( + file='./assets/zht/mission/SELECT_XP.png', + area=(1085, 163, 1230, 203), + search=(1065, 143, 1250, 223), + color=(179, 189, 201), + button=(1085, 163, 1230, 203), + ), ) diff --git a/tasks/mission/mission.py b/tasks/mission/mission.py index 5b6d103..293167a 100644 --- a/tasks/mission/mission.py +++ b/tasks/mission/mission.py @@ -3,7 +3,7 @@ from enum import Enum from module.base.timer import Timer from module.exception import RequestHumanTakeover from module.logger import logger -from tasks.mission.ui import MissionUI, CommissionsUI +from tasks.mission.ui import MissionUI, CommissionsUI, SWITCH_QUEST from tasks.stage.ap import AP from tasks.cafe.cafe import Cafe from tasks.circle.circle import Circle @@ -13,7 +13,7 @@ from tasks.item.data_update import DataUpdate import json import math from filelock import FileLock -from datetime import datetime +from datetime import datetime, timedelta class MissionStatus(Enum): AP = 0 # Calculate AP and decide to terminate Mission module or not @@ -26,11 +26,25 @@ class MissionStatus(Enum): class Mission(MissionUI, CommissionsUI): - _stage_ap = [10, 15, 15, 15] - @property def stage_ap(self): - return self._stage_ap + match self.current_mode: + case "N": + return 10 + case "H": + return 20 + case "E": + if self.current_stage >= "09": + return 20 + elif self.current_stage <= "04": + return 10 + else: + return 15 + case "XP" | "CR": + if self.current_stage >= "08": + return 40 + else: + return int(self.current_stage, base=10) * 5 @property def mission_info(self) -> list: @@ -45,8 +59,8 @@ class Mission(MissionUI, CommissionsUI): "N" : Normal Mission "H" : Hard Mission "E" : Event Quest - "IR" : Item Retrieval / Commission where you get credit - "BD" : Base Defense / Commission where you get exp + "CR" : Item Retrieval / Commission where you get credit + "XP" : Base Defense / Commission where you get exp Returns: list of list @@ -70,7 +84,7 @@ class Mission(MissionUI, CommissionsUI): logger.error("Failed to read configuration file") finally: return queue - + def check_reset_daily(self): # Check if it's time to reset the queue if self.reset_daily: @@ -80,10 +94,21 @@ class Mission(MissionUI, CommissionsUI): last_run_datetime = datetime.strptime(self.last_run, "%Y-%m-%d %H:%M:%S") reset_time = datetime.strptime(self.reset_time, "%H:%M:%S").time() - if current_date != last_run_datetime.date() and current_time >= reset_time: - self.last_run = str(datetime.now().replace(microsecond=0)) - logger.info("Reset Daily activated.") + # Check if the difference between the current date and last run date is 2 or greater days + if (current_date - last_run_datetime.date()).days >= 2: + # Set self.last_run to yesterday's date with time as reset_time + yesterday_datetime = current_datetime - timedelta(days=1) + yesterday_date = yesterday_datetime.date() + self.last_run = str(datetime.combine(yesterday_date, reset_time)) + logger.info("Reset Daily activated") return True + + # Check if the current date is different from the last run date and the current time is greater than or equal to the reset time + elif current_date != last_run_datetime.date() and current_time >= reset_time: + self.last_run = str(datetime.now().replace(microsecond=0)) + logger.info("Reset Daily activated") + return True + return False @property @@ -122,10 +147,10 @@ class Mission(MissionUI, CommissionsUI): """ if self.current_mode in ["N", "H"]: return self.select_mission(self.current_mode, self.current_stage) - elif self.current_mode in ["BD", "IR"]: + elif self.current_mode in ["CR", "XP"]: return self.select_commission(self.current_mode) elif self.current_mode == "E": - return self.select_event() + return self.select_mode(SWITCH_QUEST) else: logger.error("Uknown mode") return False @@ -134,9 +159,8 @@ class Mission(MissionUI, CommissionsUI): """ Calculate the possible number of sweeps based on the current AP """ - ap_cost = 20 if self.current_mode == "H" else 10 - required_ap = ap_cost * self.current_count - return math.floor(min(required_ap, self.current_ap) / ap_cost) + possible_count = math.floor(self.current_ap / self.stage_ap) + return min(possible_count, self.current_count) def update_task(self, failure=False): """ @@ -161,10 +185,9 @@ class Mission(MissionUI, CommissionsUI): self.task = [] def update_ap(self): - ap_cost = 20 if self.current_mode == "H" else 10 ap = self.config.stored.AP ap_old = ap.value - ap_new = ap_old - ap_cost * self.realistic_count + ap_new = ap_old - self.stage_ap * self.realistic_count ap.set(ap_new, ap.total) logger.info(f'Set AP: {ap_old} -> {ap_new}') @@ -208,7 +231,7 @@ class Mission(MissionUI, CommissionsUI): self.update_task(failure=True) return MissionStatus.AP case MissionStatus.ENTER: - if self.enter_stage(self.current_stage): + if self.enter_stage(self.current_mode, self.current_stage): return MissionStatus.SWEEP self.update_task(failure=True) return MissionStatus.AP @@ -235,24 +258,26 @@ class Mission(MissionUI, CommissionsUI): with self.lock.acquire(): self.previous_mode = None self.task = self.valid_task - action_timer = Timer(0.5, 1) - status = MissionStatus.AP + if self.task: + action_timer = Timer(0.5, 1) + status = MissionStatus.AP + + """Update the dashboard to accurately calculate AP""" + DataUpdate(config=self.config, device=self.device).run() + + while 1: + self.device.screenshot() + + if self.ui_additional(): + continue + + if action_timer.reached_and_reset(): + logger.attr('Status', status) + status = self.handle_mission(status) + + if status == MissionStatus.FINISH: + break - """Update the dashboard to accurately calculate AP""" - DataUpdate(config=self.config, device=self.device).run() - - while 1: - self.device.screenshot() - - if self.ui_additional(): - continue - - if action_timer.reached_and_reset(): - logger.attr('Status', status) - status = self.handle_mission(status) - - if status == MissionStatus.FINISH: - break - - self.config.task_delay(server_update=True) + # delay mission to 7 hours if there are still stages in the queue + self.config.task_delay(minute=420) if self.task else self.config.task_delay(server_update=True) \ No newline at end of file diff --git a/tasks/mission/ui.py b/tasks/mission/ui.py index c10e837..520feec 100644 --- a/tasks/mission/ui.py +++ b/tasks/mission/ui.py @@ -2,19 +2,19 @@ from module.base.timer import Timer from module.logger import logger from module.ui.switch import Switch from module.ocr.ocr import Digit -from tasks.base.assets.assets_base_page import BACK, MISSION_CHECK, EVENT_CHECK -from tasks.base.page import page_mission, page_commissions #,page_event +from tasks.base.assets.assets_base_page import BACK, MISSION_CHECK, EVENT_CHECK, WORK_GO_TO_EVENT +from tasks.base.page import page_mission, page_commissions, page_work #,page_event from tasks.base.ui import UI from tasks.mission.assets.assets_mission import * from tasks.stage.ap import AP from tasks.stage.mission_list import StageList from tasks.stage.sweep import StageSweep - SHARED_LIST = StageList('SharedList') -MISSION_SWEEP = StageSweep('MissionSweep', 60) -MISSION_SWEEP.set_button(button_check=CHECK_MISSION_SWEEP) # Check sweep is different for mission -SHARED_SWEEP = StageSweep('SharedSweep', 60) +EVENT_LIST = StageList('EventList', EVENT_LIST, EVENT_INDEX, EVENT_ITEM, button_stars=EVENT_STARS) +SHARED_SWEEP = StageSweep('MissionSweep', 99) +SHARED_SWEEP.set_button(button_check=CHECK_MISSION_SWEEP) # Check sweep is different for mission, event +COMMISSIONS_SWEEP = StageSweep('CommissionsSweep', 99) SWITCH_NORMAL = Switch("Normal_switch") SWITCH_NORMAL.add_state("on", NORMAL_ON) @@ -36,27 +36,19 @@ Missing for "E" because there are no event in Global and no page_event MODE_TO_PAGE = { "N": (MISSION_CHECK, page_mission), "H": (MISSION_CHECK, page_mission), - "BD": (CHECK_BD, page_commissions), - "IR": (CHECK_IR, page_commissions), - "E" : (EVENT_CHECK) #page_event + "XP": (CHECK_XP, page_commissions), + "CR": (CHECK_CR, page_commissions), + "E" : (EVENT_CHECK, None) #page_event } class MissionUI(UI, AP): def select_mission(self, mode, stage): area = int(stage.split("-")[0]) - if not self.select_area(area): - logger.warning("Area not found") - return False - - to_switch = { - "N": SWITCH_NORMAL, - "H": SWITCH_HARD - } - switch = to_switch[mode] - if not self.select_mode(switch) and not self.select_area(area): - return False - return True + switch = SWITCH_HARD if mode == "H" else SWITCH_NORMAL + if self.select_area(area) and self.select_mode(switch): + return True + return False def select_area(self, num): """" @@ -81,6 +73,7 @@ class MissionUI(UI, AP): except: tries += 1 if tries > 3: + logger.warning(f"Area {num} not found") return False def select_mode(self, switch): @@ -94,20 +87,16 @@ class MissionUI(UI, AP): return False switch.set('on', main=self) return True - - def select_event(self): - return self.select_mode(SWITCH_QUEST) - def enter_stage(self, index: int) -> bool: - if not index: - index = SHARED_LIST.insight_max_sweepable_index(self) - if SHARED_LIST.select_index_enter(self, index): + def enter_stage(self, mode, index: int) -> bool: + list = EVENT_LIST if mode == "E" else SHARED_LIST + if list.select_index_enter(self, index): return True return False def do_sweep(self, mode, num: int) -> bool: - if mode in ["N", "H", "E"]: - return MISSION_SWEEP.do_sweep(self, num=num) + if mode in ["XP", "CR"]: + return COMMISSIONS_SWEEP.do_sweep(self, num=num) else: return SHARED_SWEEP.do_sweep(self, num=num) @@ -120,10 +109,10 @@ class MissionUI(UI, AP): """ if prev==next or (prev in ["N", "H"] and next in ["N", "H"]): self.go_back(MODE_TO_PAGE[next][0]) - elif prev in ["BD", "IR"] and next in ["BD", "IR"]: + elif prev in ["XP", "CR"] and next in ["XP", "CR"]: self.go_back(CHECK_COMMISSIONS) else: - self.ui_ensure(MODE_TO_PAGE[next][1]) + self.goto_event() if next == "E" else self.ui_ensure(MODE_TO_PAGE[next][1]) def go_back(self, check): while 1: @@ -132,14 +121,28 @@ class MissionUI(UI, AP): return True self.click_with_interval(BACK, interval=2) + def goto_event(self): + """ + Should be removed after implementing ui_ensure(page_event) + """ + self.ui_ensure(page_work) + timer = Timer(1).start() + while 1: + self.device.screenshot() + if self.appear(EVENT_CHECK): + break + self.appear_then_click(WORK_GO_TO_EVENT) + self.device.swipe((40,160), (260, 40)) + while not timer.reached_and_reset(): + pass + class CommissionsUI(UI, AP): """Works the same way as select_bounty""" def select_commission(self, mode): - to_button = { - "IR": (SELECT_IR, CHECK_IR), - "BD": (SELECT_BD, CHECK_BD) - } - dest_enter, dest_check = to_button[mode] + if mode == "CR": + dest_enter, dest_check = SELECT_CR, CHECK_CR + else: + dest_enter, dest_check = SELECT_XP, CHECK_XP timer = Timer(5, 10).start() while 1: self.device.screenshot() diff --git a/tasks/momotalk/assets/assets_momotalk.py b/tasks/momotalk/assets/assets_momotalk.py index 3f0de62..7154630 100644 --- a/tasks/momotalk/assets/assets_momotalk.py +++ b/tasks/momotalk/assets/assets_momotalk.py @@ -13,6 +13,31 @@ BEGIN_STORY = ButtonWrapper( color=(107, 197, 230), button=(796, 540, 1059, 591), ), + zht=Button( + file='./assets/zht/momotalk/BEGIN_STORY.png', + area=(729, 533, 1114, 599), + search=(709, 513, 1134, 619), + color=(110, 205, 239), + button=(729, 533, 1114, 599), + ), +) +CHATTING = ButtonWrapper( + name='CHATTING', + jp=None, + en=Button( + file='./assets/en/momotalk/CHATTING.png', + area=(774, 563, 821, 585), + search=(754, 543, 841, 605), + color=(89, 102, 121), + button=(774, 563, 821, 585), + ), + zht=Button( + file='./assets/zht/momotalk/CHATTING.png', + area=(774, 563, 821, 585), + search=(754, 543, 841, 605), + color=(89, 102, 121), + button=(774, 563, 821, 585), + ), ) CHAT_AREA = ButtonWrapper( name='CHAT_AREA', @@ -24,6 +49,13 @@ CHAT_AREA = ButtonWrapper( color=(206, 212, 217), button=(760, 149, 1149, 628), ), + zht=Button( + file='./assets/zht/momotalk/CHAT_AREA.png', + area=(760, 149, 1149, 628), + search=(740, 129, 1169, 648), + color=(206, 212, 217), + button=(760, 149, 1149, 628), + ), ) CONFIRM_SKIP = ButtonWrapper( name='CONFIRM_SKIP', @@ -35,6 +67,13 @@ CONFIRM_SKIP = ButtonWrapper( color=(112, 207, 241), button=(674, 486, 871, 555), ), + zht=Button( + file='./assets/zht/momotalk/CONFIRM_SKIP.png', + area=(665, 492, 875, 555), + search=(645, 472, 895, 575), + color=(111, 209, 244), + button=(665, 492, 875, 555), + ), ) CONFIRM_SORT = ButtonWrapper( name='CONFIRM_SORT', @@ -46,6 +85,13 @@ CONFIRM_SORT = ButtonWrapper( color=(248, 249, 249), button=(239, 407, 657, 439), ), + zht=Button( + file='./assets/zht/momotalk/CONFIRM_SORT.png', + area=(240, 401, 656, 440), + search=(220, 381, 676, 460), + color=(249, 250, 250), + button=(240, 401, 656, 440), + ), ) FIRST_UNREAD = ButtonWrapper( name='FIRST_UNREAD', @@ -57,6 +103,13 @@ FIRST_UNREAD = ButtonWrapper( color=(251, 86, 45), button=(636, 239, 661, 265), ), + zht=Button( + file='./assets/zht/momotalk/FIRST_UNREAD.png', + area=(636, 239, 661, 265), + search=(616, 219, 681, 285), + color=(251, 86, 45), + button=(636, 239, 661, 265), + ), ) MENU = ButtonWrapper( name='MENU', @@ -68,6 +121,13 @@ MENU = ButtonWrapper( color=(215, 219, 222), button=(1156, 15, 1251, 63), ), + zht=Button( + file='./assets/zht/momotalk/MENU.png', + area=(1151, 20, 1256, 61), + search=(1131, 0, 1276, 81), + color=(214, 218, 223), + button=(1151, 20, 1256, 61), + ), ) NOTIFICATION_BADGE = ButtonWrapper( name='NOTIFICATION_BADGE', @@ -79,6 +139,13 @@ NOTIFICATION_BADGE = ButtonWrapper( color=(242, 101, 47), button=(171, 109, 200, 128), ), + zht=Button( + file='./assets/zht/momotalk/NOTIFICATION_BADGE.png', + area=(171, 109, 200, 128), + search=(151, 89, 220, 148), + color=(242, 101, 47), + button=(171, 109, 200, 128), + ), ) REPLY = ButtonWrapper( name='REPLY', @@ -90,6 +157,13 @@ REPLY = ButtonWrapper( color=(198, 210, 216), button=(791, 431, 855, 462), ), + zht=Button( + file='./assets/zht/momotalk/REPLY.png', + area=(783, 428, 838, 460), + search=(763, 408, 858, 480), + color=(189, 203, 211), + button=(783, 428, 838, 460), + ), ) SELECT_STUDENT = ButtonWrapper( name='SELECT_STUDENT', @@ -101,6 +175,13 @@ SELECT_STUDENT = ButtonWrapper( color=(241, 242, 242), button=(839, 369, 998, 403), ), + zht=Button( + file='./assets/zht/momotalk/SELECT_STUDENT.png', + area=(849, 365, 980, 406), + search=(829, 345, 1000, 426), + color=(236, 237, 238), + button=(849, 365, 980, 406), + ), ) SKIP = ButtonWrapper( name='SKIP', @@ -112,6 +193,13 @@ SKIP = ButtonWrapper( color=(108, 125, 145), button=(1192, 103, 1229, 141), ), + zht=Button( + file='./assets/zht/momotalk/SKIP.png', + area=(1186, 95, 1231, 144), + search=(1166, 75, 1251, 164), + color=(85, 105, 129), + button=(1186, 95, 1231, 144), + ), ) SORT_ASCENDING = ButtonWrapper( name='SORT_ASCENDING', @@ -123,6 +211,13 @@ SORT_ASCENDING = ButtonWrapper( color=(221, 228, 233), button=(631, 166, 648, 188), ), + zht=Button( + file='./assets/zht/momotalk/SORT_ASCENDING.png', + area=(631, 166, 648, 188), + search=(611, 146, 668, 208), + color=(221, 228, 233), + button=(631, 166, 648, 188), + ), ) SORT_DESCENDING = ButtonWrapper( name='SORT_DESCENDING', @@ -134,6 +229,13 @@ SORT_DESCENDING = ButtonWrapper( color=(221, 228, 234), button=(631, 166, 648, 189), ), + zht=Button( + file='./assets/zht/momotalk/SORT_DESCENDING.png', + area=(631, 166, 648, 189), + search=(611, 146, 668, 209), + color=(221, 228, 234), + button=(631, 166, 648, 189), + ), ) STORY = ButtonWrapper( name='STORY', @@ -145,6 +247,13 @@ STORY = ButtonWrapper( color=(220, 208, 214), button=(790, 529, 979, 557), ), + zht=Button( + file='./assets/zht/momotalk/STORY.png', + area=(781, 527, 878, 555), + search=(761, 507, 898, 575), + color=(208, 197, 204), + button=(781, 527, 878, 555), + ), ) SWITCH_MESSAGE = ButtonWrapper( name='SWITCH_MESSAGE', @@ -156,6 +265,13 @@ SWITCH_MESSAGE = ButtonWrapper( color=(187, 191, 201), button=(147, 271, 194, 297), ), + zht=Button( + file='./assets/zht/momotalk/SWITCH_MESSAGE.png', + area=(147, 271, 194, 297), + search=(127, 251, 214, 317), + color=(187, 191, 201), + button=(147, 271, 194, 297), + ), ) SWITCH_MESSAGE_CHECK = ButtonWrapper( name='SWITCH_MESSAGE_CHECK', @@ -167,6 +283,13 @@ SWITCH_MESSAGE_CHECK = ButtonWrapper( color=(211, 215, 217), button=(228, 165, 391, 194), ), + zht=Button( + file='./assets/zht/momotalk/SWITCH_MESSAGE_CHECK.png', + area=(226, 161, 320, 194), + search=(206, 141, 340, 214), + color=(199, 203, 205), + button=(226, 161, 320, 194), + ), ) SWITCH_STUDENT = ButtonWrapper( name='SWITCH_STUDENT', @@ -178,6 +301,13 @@ SWITCH_STUDENT = ButtonWrapper( color=(157, 166, 179), button=(148, 167, 194, 217), ), + zht=Button( + file='./assets/zht/momotalk/SWITCH_STUDENT.png', + area=(148, 167, 194, 217), + search=(128, 147, 214, 237), + color=(157, 166, 179), + button=(148, 167, 194, 217), + ), ) SWITCH_STUDENT_CHECK = ButtonWrapper( name='SWITCH_STUDENT_CHECK', @@ -189,6 +319,13 @@ SWITCH_STUDENT_CHECK = ButtonWrapper( color=(199, 203, 205), button=(229, 166, 320, 192), ), + zht=Button( + file='./assets/zht/momotalk/SWITCH_STUDENT_CHECK.png', + area=(221, 161, 281, 197), + search=(201, 141, 301, 217), + color=(210, 214, 216), + button=(221, 161, 281, 197), + ), ) UNREAD = ButtonWrapper( name='UNREAD', @@ -200,6 +337,13 @@ UNREAD = ButtonWrapper( color=(241, 242, 243), button=(454, 160, 568, 193), ), + zht=Button( + file='./assets/zht/momotalk/UNREAD.png', + area=(453, 160, 567, 195), + search=(433, 140, 587, 215), + color=(241, 242, 243), + button=(453, 160, 567, 195), + ), ) UNREAD_OFF = ButtonWrapper( name='UNREAD_OFF', @@ -211,6 +355,13 @@ UNREAD_OFF = ButtonWrapper( color=(252, 252, 251), button=(456, 273, 658, 316), ), + zht=Button( + file='./assets/zht/momotalk/UNREAD_OFF.png', + area=(459, 274, 658, 314), + search=(439, 254, 678, 334), + color=(251, 251, 251), + button=(459, 274, 658, 314), + ), ) UNREAD_ON = ButtonWrapper( name='UNREAD_ON', @@ -222,4 +373,11 @@ UNREAD_ON = ButtonWrapper( color=(245, 120, 144), button=(456, 272, 658, 314), ), + zht=Button( + file='./assets/zht/momotalk/UNREAD_ON.png', + area=(455, 272, 658, 314), + search=(435, 252, 678, 334), + color=(244, 118, 143), + button=(455, 272, 658, 314), + ), ) diff --git a/tasks/momotalk/momotalk.py b/tasks/momotalk/momotalk.py index 35f4974..5d9e3ac 100644 --- a/tasks/momotalk/momotalk.py +++ b/tasks/momotalk/momotalk.py @@ -33,7 +33,7 @@ class MomoTalk(MomoTalkUI): return MomoTalkStatus.OPEN case MomoTalkStatus.STORY: if self.skip_story(): - return MomoTalkStatus.OPEN + return MomoTalkStatus.CHAT case MomoTalkStatus.FINISHED: return status case _: diff --git a/tasks/momotalk/ui.py b/tasks/momotalk/ui.py index a41d080..647dabc 100644 --- a/tasks/momotalk/ui.py +++ b/tasks/momotalk/ui.py @@ -26,13 +26,14 @@ SWITCH_SORT.add_state("descending", SORT_DESCENDING) button can be found in different locations""" REPLY_TEMPLATE = REPLY.matched_button.image STORY_TEMPLATE = STORY.matched_button.image - +CHATTING_TEMPLATE = CHATTING.matched_button.image class MomoTalkUI(UI): def __init__(self, config, device): super().__init__(config, device) self.swipe_vector_range = (0.65, 0.85) self.list = CHAT_AREA + self.click_coords = self.device.click_methods.get(self.config.Emulator_ControlMethod, self.device.click_adb) def swipe_page(self, direction: str, main: ModuleBase, vector_range=None, reverse=False): """ @@ -58,28 +59,17 @@ class MomoTalkUI(UI): vector = (-vector[0], -vector[1]) main.device.swipe_vector(vector, self.list.button) - def select_then_check(self, dest_enter: ButtonWrapper, dest_check: ButtonWrapper, similarity=0.85): + def select_then_disappear(self, dest_enter: ButtonWrapper, dest_check: ButtonWrapper): timer = Timer(5, 10).start() while 1: self.device.screenshot() - self.appear_then_click(dest_enter, interval=1, similarity=similarity) - if self.appear(dest_check, similarity=similarity): - return True - if timer.reached(): - return False - - def select_then_disappear(self, dest_enter: ButtonWrapper, dest_check: ButtonWrapper, force_select=False): - timer = Timer(5, 10).start() - while 1: - self.device.screenshot() - if force_select or self.appear(dest_enter): - self.click_with_interval(dest_enter, interval=1) + self.click_with_interval(dest_enter, interval=1) if not self.appear(dest_check): return True if timer.reached(): return False - def set_switch(self, switch): + def set_switch(self, switch, state='on'): """ Set switch to on. However, unsure why is inaccurate in momotalk. Returns: @@ -88,17 +78,15 @@ class MomoTalkUI(UI): if not switch.appear(main=self): logger.info(f'{switch.name} not found') return False - switch.set('on', main=self) + switch.set(state, main=self) return True def click_all(self, template, x_add=0, y_add=0): """ Find the all the locations of the template adding an offset if specified and click them. - TODO: filter coords that are not inside the chat area as otherwise it will close momotalk. If after filter, no coords then swipe. """ - click_coords = self.device.click_methods.get(self.config.Emulator_ControlMethod, self.device.click_adb) image = self.device.screenshot() result = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED) threshold = 0.8 @@ -108,9 +96,10 @@ class MomoTalkUI(UI): center_pt = (int(pt[0] + template.shape[1] / 2 + x_add), int(pt[1] + template.shape[0] / 2 + y_add)) seen.add(center_pt) if seen: - seen = filter(lambda x: point_in_area(x, CHAT_AREA.area), seen) - [click_coords(coords[0], coords[1]) for coords in seen] - self.swipe_page("down", self) + if y_add != 0: + seen = filter(lambda x: point_in_area(x, CHAT_AREA.area), seen) + [self.click_coords(coords[0], coords[1]) for coords in seen] + self.swipe_page("down", self) return True return False @@ -132,18 +121,22 @@ class MomoTalkUI(UI): """ Switch from newest to unread and sort the messages in descending order """ - logger.info("Sorting messages...") - steps = [UNREAD, CONFIRM_SORT, UNREAD_OFF, UNREAD_ON] - for i in range(len(steps)-2): - self.select_then_check(steps[i], steps[i+1], similarity=0.95) - return not self.appear(CONFIRM_SORT) and self.appear(UNREAD) and self.appear(SORT_ON) + while 1: + self.device.screenshot() + if self.set_switch(SWITCH_UNREAD): + self.click_with_interval(CONFIRM_SORT, interval=2) + continue + if self.appear(UNREAD, similarity=0.95): + break + self.click_with_interval(UNREAD, interval=2) + return self.set_switch(SWITCH_SORT, "descending") def check_first_student(self): """ If the first student has a red notification return True and start chat. Otherwise it means no students are available for interaction. """ - if self.match_color(FIRST_UNREAD, threshold=80) and self.select_then_disappear(FIRST_UNREAD, SELECT_STUDENT, force_select=True): + if self.match_color(FIRST_UNREAD, threshold=80) and self.select_then_disappear(FIRST_UNREAD, SELECT_STUDENT): return True logger.warning("No students available for interaction") return False @@ -154,24 +147,23 @@ class MomoTalkUI(UI): check if a reply or story button is found and click them. If the begin story button is found skip story. """ + timer = Timer(8, 5).start() logger.info("Chatting with student...") - stability_counter = 0 while 1: - self.wait_until_stable(CHAT_AREA, timer=Timer(10, 10)) + self.device.screenshot() if self.appear(BEGIN_STORY): logger.info("Begin Story detected") return True - if self.click_all(REPLY_TEMPLATE, y_add=62): + elif self.click_all(CHATTING_TEMPLATE): + timer.reset() + elif self.click_all(REPLY_TEMPLATE, y_add=62): logger.info("Clicked on reply") - stability_counter = 0 - continue - if self.click_all(STORY_TEMPLATE, y_add=62): + timer.reset() + elif self.click_all(STORY_TEMPLATE, y_add=62): logger.info("Clicked on story") - stability_counter = 0 - continue - logger.info("No new message detected") - stability_counter += 1 - if stability_counter > 3: + timer.reset() + elif timer.reached(): + logger.info("No new message detected") return False def skip_story(self): @@ -180,11 +172,17 @@ class MomoTalkUI(UI): button is clicked and disappears """ logger.info("Attempting to skip story...") - steps = [BEGIN_STORY, MENU, SKIP] - for step in steps: - self.appear_then_click(step) - if self.appear_then_click(CONFIRM_SKIP) and not self.appear(CONFIRM_SKIP, interval=5): - logger.info("Skipped story successfully") - return True - return False + steps = [CONFIRM_SKIP, SKIP, MENU, BEGIN_STORY] + timer = Timer(1).start() + while 1: + self.device.screenshot() + if self.handle_reward(): + logger.info("Skipped story successfully") + return True + for step in steps: + if self.appear_then_click(step): + while not timer.reached_and_reset(): + pass + break + diff --git a/tasks/schedule/assets/assets_schedule.py b/tasks/schedule/assets/assets_schedule.py index 8e923b2..2e39721 100644 --- a/tasks/schedule/assets/assets_schedule.py +++ b/tasks/schedule/assets/assets_schedule.py @@ -3,6 +3,96 @@ from module.base.button import Button, ButtonWrapper # This file was auto-generated, do not modify it manually. To generate: # ``` python -m dev_tools.button_extract ``` +CONFIRM = ButtonWrapper( + name='CONFIRM', + jp=None, + en=Button( + file='./assets/en/schedule/CONFIRM.png', + area=(532, 528, 748, 589), + search=(512, 508, 768, 609), + color=(110, 207, 241), + button=(532, 528, 748, 589), + ), + zht=Button( + file='./assets/zht/schedule/CONFIRM.png', + area=(529, 526, 746, 587), + search=(509, 506, 766, 607), + color=(111, 209, 244), + button=(529, 526, 746, 587), + ), +) +FIRST_ITEM = ButtonWrapper( + name='FIRST_ITEM', + jp=None, + en=Button( + file='./assets/en/schedule/FIRST_ITEM.png', + area=(727, 137, 1103, 239), + search=(707, 117, 1123, 259), + color=(200, 209, 220), + button=(727, 137, 1103, 239), + ), + zht=Button( + file='./assets/zht/schedule/FIRST_ITEM.png', + area=(727, 137, 1103, 239), + search=(707, 117, 1123, 259), + color=(200, 209, 220), + button=(727, 137, 1103, 239), + ), +) +LOCATIONS = ButtonWrapper( + name='LOCATIONS', + jp=None, + en=Button( + file='./assets/en/schedule/LOCATIONS.png', + area=(1075, 638, 1256, 693), + search=(1055, 618, 1276, 713), + color=(107, 202, 237), + button=(1075, 638, 1256, 693), + ), + zht=Button( + file='./assets/zht/schedule/LOCATIONS.png', + area=(1078, 639, 1251, 692), + search=(1058, 619, 1271, 712), + color=(103, 193, 228), + button=(1078, 639, 1251, 692), + ), +) +LOCATIONS_POPUP = ButtonWrapper( + name='LOCATIONS_POPUP', + jp=None, + en=Button( + file='./assets/en/schedule/LOCATIONS_POPUP.png', + area=(534, 101, 750, 135), + search=(514, 81, 770, 155), + color=(194, 202, 210), + button=(534, 101, 750, 135), + ), + zht=Button( + file='./assets/zht/schedule/LOCATIONS_POPUP.png', + area=(542, 95, 732, 136), + search=(522, 75, 752, 156), + color=(184, 192, 202), + button=(542, 95, 732, 136), + ), +) +OCR_TICKET = ButtonWrapper( + name='OCR_TICKET', + jp=None, + en=Button( + file='./assets/en/schedule/OCR_TICKET.png', + area=(220, 79, 266, 121), + search=(200, 59, 286, 141), + color=(214, 225, 229), + button=(220, 79, 266, 121), + ), + zht=Button( + file='./assets/zht/schedule/OCR_TICKET.png', + area=(152, 82, 202, 120), + search=(132, 62, 222, 140), + color=(217, 228, 231), + button=(152, 82, 202, 120), + ), +) SCROLL = ButtonWrapper( name='SCROLL', jp=Button( @@ -19,4 +109,29 @@ SCROLL = ButtonWrapper( color=(198, 214, 210), button=(727, 137, 1103, 671), ), + zht=Button( + file='./assets/zht/schedule/SCROLL.png', + area=(727, 137, 1103, 671), + search=(707, 117, 1123, 691), + color=(198, 214, 210), + button=(727, 137, 1103, 671), + ), +) +START_LESSON = ButtonWrapper( + name='START_LESSON', + jp=None, + en=Button( + file='./assets/en/schedule/START_LESSON.png', + area=(506, 523, 773, 585), + search=(486, 503, 793, 605), + color=(110, 205, 239), + button=(506, 523, 773, 585), + ), + zht=Button( + file='./assets/zht/schedule/START_LESSON.png', + area=(506, 527, 774, 577), + search=(486, 507, 794, 597), + color=(104, 194, 228), + button=(506, 527, 774, 577), + ), ) diff --git a/tasks/schedule/schedule.py b/tasks/schedule/schedule.py new file mode 100644 index 0000000..f022cfa --- /dev/null +++ b/tasks/schedule/schedule.py @@ -0,0 +1,134 @@ +from enum import Flag + +from module.base.timer import Timer +from module.exception import RequestHumanTakeover +from module.logger import logger +from tasks.base.assets.assets_base_page import BACK +from tasks.base.page import page_schedule +from tasks.schedule.ui import ScheduleUI +from tasks.base.assets.assets_base_page import SCHEDULE_CHECK + +import re + +class ScheduleStatus(Flag): + OCR = 0 + ENTER = 1 + SELECT = 2 + END = 3 + FINISH = 4 + + +class Schedule(ScheduleUI): + @property + def schedule_info(self): + info = [] + input_valid = True + schedule_config = self.config.cross_get("Schedule") + choices = ["Choice1", "Choice2", "Choice3", "Choice4", "Choice5", "Choice6", "Choice7"] + + for choice in choices: + location, classrooms = schedule_config[choice]["Location"], schedule_config[choice]["Classrooms"] + if location == "None" or not classrooms or (isinstance(classrooms, str) and classrooms.replace(" ", "") == ""): + continue + elif isinstance(classrooms, int): + classrooms_list = [str(classrooms)] + else: + classrooms = classrooms.strip() + classrooms = re.sub(r'[ \t\r\n]', '', classrooms) + classrooms = (re.sub(r'[>﹥›˃ᐳ❯]', '>', classrooms)).split('>') + classrooms_list = [] + # tried to convert to set to remove duplicates but doesn't maintain order + [classrooms_list.append(x) for x in classrooms if x not in classrooms_list] + + if self.valid_classroom(classrooms_list): + info.append([location, classrooms_list]) + else: + logger.error(f"Failed to read {choice}") + input_valid = False + + return info if input_valid else [] + + def valid_classroom(self, classrooms_list): + if not classrooms_list: + return False + for classroom in classrooms_list: + if not classroom.isdigit(): + return False + if not 1 <= int(classroom) <= 9: + return False + return True + + @property + def valid_task(self) -> list: + task = self.schedule_info + if not task: + logger.warning('Lessons enabled but no task set') + self.error_handler() + return task + + def error_handler(self): + action = self.config.Schedule_OnError + if action == 'stop': + raise RequestHumanTakeover + elif action == 'skip': + with self.config.multi_set(): + self.config.task_delay(server_update=True) + self.config.task_stop() + + @property + def current_location(self): + return self.task[0][0] + + @property + def current_classrooms(self): + return self.task[0][1] + + def handle_schedule(self, status): + match status: + case ScheduleStatus.OCR: + if self.task: + self.ticket = self.get_ticket() + if self.ticket not in [0, None]: + return ScheduleStatus.ENTER + return ScheduleStatus.FINISH + case ScheduleStatus.ENTER: + if self.enter_location(self.current_location): + return ScheduleStatus.SELECT + else: + self.error_handler() + case ScheduleStatus.SELECT: + if self.select_classrooms(self.ticket, self.current_classrooms): + self.task.pop(0) + return ScheduleStatus.END + return ScheduleStatus.FINISH + case ScheduleStatus.END: + if self.appear(SCHEDULE_CHECK): + return ScheduleStatus.OCR + self.click_with_interval(BACK, interval=2) + case ScheduleStatus.FINISH: + return status + case _: + logger.warning(f'Invalid status: {status}') + return status + + def run(self): + self.ui_ensure(page_schedule) + self.task = self.valid_task + self.set_clickx() + action_timer = Timer(0.5, 1) + status = ScheduleStatus.OCR + + while 1: + self.device.screenshot() + + if self.ui_additional(): + continue + + if action_timer.reached_and_reset(): + logger.attr('Status', status) + status = self.handle_schedule(status) + + if status == ScheduleStatus.FINISH: + break + + self.config.task_delay(server_update=True) \ No newline at end of file diff --git a/tasks/schedule/scroll_select.py b/tasks/schedule/scroll_select.py new file mode 100644 index 0000000..ba43641 --- /dev/null +++ b/tasks/schedule/scroll_select.py @@ -0,0 +1,149 @@ +""" +Original Author: sanmusen214(https://github.com/sanmusen214) +Adapted from https://github.com/sanmusen214/BAAH/blob/1.2/modules/AllTask/SubTask/ScrollSelect.py +""" + +from module.logger import logger +from module.base.timer import Timer + + +class ScrollSelect: + """ + Scroll and select the corresponding level by clicking on the right-side window. + + Parameters + ---------- + targetind : int + Index of the target level + window_starty: + Y-coordinate of the upper edge of the window + first_item_endy: + Y-coordinate of the lower edge of the first item + window_endy: + Y-coordinate of the lower edge of the window + clickx: int + Base X-coordinate for sliding and clicking the button + hasexpectimage: function + Function to determine the appearance of the expected image after clicking, returns a boolean + swipeoffsetx: int + X offset of the base X-coordinate during sliding to prevent accidental button clicks + finalclick: bool + Whether to click on clickx and the last row after the sliding ends + """ + def __init__(self, window_button, first_item_button, expected_button, clickx, swipeoffsetx=-100, finalclick=True) -> None: + # TODO: Actually, only concerned about the height of one element, completely displaying the Y of the first button, completely displaying the Y of the bottom button, the number of complete elements that the window can contain, the height of the last element in the window, and the left offset and response distance. + self.window_starty = window_button.area[1] + self.window_endy = window_button.area[3] + self.first_item_endy = first_item_button.area[3] + self.windowheight = window_button.height + self.itemheight = first_item_button.height + self.clickx = clickx + self.expected_button = expected_button + self.swipeoffsetx = swipeoffsetx + self.responsey = 40 + self.finalclick = finalclick + + def compute_swipe(self, main, x1, y1, distance, responsey): + """ + Swipe vertically from bottom to top, actual swipe distance calculated based on the distance between two target points, considering inertia. + """ + distance = abs(distance) + logger.info(f"Swipe distance: {distance}") + # 0-50 + if distance < 50: + main.device.swipe((x1, y1), (x1, y1 - (distance + responsey)), duration=2) + else: + # Effective swipe distance for the Chinese server is 60 + main.device.swipe((x1, y1), (x1, int(y1 - (distance + responsey - 4 * (1 + distance / 100)))), duration=1 + distance / 100) + + def select_location(self, main, target_index) -> None: + click_coords = main.device.click_methods.get(main.config.Emulator_ControlMethod, main.device.click_adb) + logger.info("Scroll and select the {}-th level".format(target_index + 1)) + self.scroll_right_up(main, scrollx=self.clickx + self.swipeoffsetx) + # Calculate how many complete elements are on one page + itemcount = self.windowheight // self.itemheight + # Calculate how much height the last incomplete element on this page occupies + lastitemheight = self.windowheight % self.itemheight + # Height below the incomplete element + hiddenlastitemheight = self.itemheight - lastitemheight + # Center point of the height of the first element + start_center_y = self.window_starty + self.itemheight // 2 + # Center point of the last complete element on this page + end_center_y = start_center_y + (itemcount - 1) * self.itemheight + # If the target element is on the current page + if target_index < itemcount: + # Center point of the target element + target_center_y = start_center_y + self.itemheight * target_index + self.run_until(main, + lambda: click_coords(self.clickx, target_center_y), + lambda: main.appear(self.expected_button), + ) + else: + # Start scrolling from the gap in the middle of the levels + scroll_start_from_y = self.window_endy - self.itemheight // 2 + # The target element is on subsequent pages + # Calculate how much the page should be scrolled + scrolltotal_distance = (target_index - itemcount) * self.itemheight + hiddenlastitemheight + logger.info("Height hidden by the last element: %d" % hiddenlastitemheight) + # First, slide up the hidden part, add a little distance to let the system recognize it as a swipe event + self.compute_swipe(main, self.clickx + self.swipeoffsetx, scroll_start_from_y, hiddenlastitemheight, self.responsey) + logger.info(f"Swipe distance: {hiddenlastitemheight}") + # Update scrolltotal_distance + scrolltotal_distance -= hiddenlastitemheight + # Still need to scroll up (target_index - itemcount) * self.itemheight + # Important: slide the height of (itemcount - 1) elements each time + if itemcount == 1: + scroll_distance = itemcount * self.itemheight + else: + scroll_distance = (itemcount - 1) * self.itemheight + while scroll_distance <= scrolltotal_distance: + self.compute_swipe(main, self.clickx + self.swipeoffsetx, scroll_start_from_y, scroll_distance, self.responsey) + scrolltotal_distance -= scroll_distance + if scrolltotal_distance > 5: + # Last slide + self.compute_swipe(main, self.clickx + self.swipeoffsetx, scroll_start_from_y, scrolltotal_distance, self.responsey) + if self.finalclick: + # Click on the last row + self.run_until(main, + lambda: click_coords(self.clickx, self.window_endy - self.itemheight // 2), + lambda: main.appear(self.expected_button) + ) + + def run_until(self, main, func1, func2, times=6, sleeptime=1.5) -> bool: + """ + Repeat the execution of func1 up to a maximum of times or until func2 evaluates to True. + + func1 should perform a single valid operation or internally call a screenshot function. + A screenshot is triggered before evaluating func2. + + After each execution of func1, wait for sleeptime seconds. + + If func2 evaluates to True, exit and return True. Otherwise, return False. + + Note: The comment assumes that func1 produces a meaningful operation or internally calls a screenshot function, + and func2 is evaluated after each execution of func1. + """ + for i in range(times): + main.device.screenshot() + if func2(): + return True + func1() + timer = Timer(sleeptime).start() + while not timer.reached_and_reset(): + pass + main.device.screenshot() + if func2(): + return True + logger.warning("run_until exceeded max times") + return False + + def scroll_right_up(self, main, scrollx=928, times=3): + """ + scroll to top + """ + for i in range(times): + main.device.swipe((scrollx, 226), (scrollx, 561), duration=0.2) + timer = Timer(0.5).start() + while not timer.reached_and_reset(): + pass + \ No newline at end of file diff --git a/tasks/schedule/ui.py b/tasks/schedule/ui.py new file mode 100644 index 0000000..c76f9ed --- /dev/null +++ b/tasks/schedule/ui.py @@ -0,0 +1,90 @@ +from module.base.timer import Timer +from module.base.decorator import Config +from module.logger import logger +from module.ocr.ocr import DigitCounter +from tasks.base.ui import UI +from tasks.base.assets.assets_base_page import SCHEDULE_CHECK +from tasks.schedule.assets.assets_schedule import * +from tasks.schedule.scroll_select import ScrollSelect +import numpy as np + +SCROLL_SELECT = ScrollSelect(window_button=SCROLL, first_item_button=FIRST_ITEM, expected_button=LOCATIONS, clickx=1116) +xs = np.linspace(299, 995, 3, dtype=int) +ys = np.linspace(268, 573, 3, dtype=int) + +class ScheduleUI(UI): + @Config.when(Emulator_GameLanguage='jp') + def set_clickx(self): + SCROLL_SELECT.clickx = 1114 + + @Config.when(Emulator_GameLanguage=None) + def set_clickx(self): + pass + + def select_then_check(self, dest_enter: ButtonWrapper, dest_check: ButtonWrapper): + timer = Timer(8, 10).start() + while 1: + self.device.screenshot() + self.appear_then_click(dest_enter, interval=1) + if self.handle_affection_level_up() or self.handle_location_level_up(): + timer.reset() + if self.appear(dest_check): + return True + + if timer.reached(): + return False + + def click_then_check(self, coords, dest_check: ButtonWrapper): + click_coords = self.device.click_methods.get(self.config.Emulator_ControlMethod, self.device.click_adb) + timer = Timer(3, 2).start() + wait = Timer(1).start() + while 1: + click_coords(*coords) + self.device.screenshot() + if self.appear_then_click(dest_check): + return True + while not wait.reached_and_reset(): + pass + if timer.reached(): + return False + + def enter_location(self, location): + SCROLL_SELECT.select_location(self, location) + if not self.appear(LOCATIONS): + logger.error("Unable to navigate to page for location {}".format(location + 1)) + return False + return self.select_then_check(LOCATIONS, LOCATIONS_POPUP) + + def select_classrooms(self, ticket, classrooms): + for classroom in classrooms: + if ticket == 0: + return False + classroom = int(classroom) - 1 + col = int(classroom % len(xs)) + row = int((classroom - col) / len(ys)) + targetloc = (xs[col], ys[row]) + if not self.click_then_check(targetloc, START_LESSON): + logger.info(f"Classroom {classroom + 1} does not exist or has already been clicked") + continue + if self.select_then_check(START_LESSON, CONFIRM): + ticket -= 1 + if not self.select_then_check(CONFIRM, LOCATIONS_POPUP): + logger.error(f"An unexpected error occurred. Skipping location") + break + return True + + def get_ticket(self): + """ + Page: + in: page_bounty + """ + if not self.appear(SCHEDULE_CHECK): + logger.warning('OCR failed due to invalid page') + return False + ticket, _, total = DigitCounter(OCR_TICKET).ocr_single_line(self.device.image) + if total == 0: + logger.warning('Invalid ticket') + return False + logger.attr('ScheduleTicket', ticket) + #self.config.stored.BountyTicket.set(ticket) + return ticket diff --git a/tasks/scrimmage/assets/assets_scrimmage.py b/tasks/scrimmage/assets/assets_scrimmage.py index f746c23..e0824b5 100644 --- a/tasks/scrimmage/assets/assets_scrimmage.py +++ b/tasks/scrimmage/assets/assets_scrimmage.py @@ -19,6 +19,13 @@ CHECK_GEHENNA = ButtonWrapper( color=(202, 206, 208), button=(103, 145, 252, 182), ), + zht=Button( + file='./assets/zht/scrimmage/CHECK_GEHENNA.png', + area=(96, 141, 213, 182), + search=(76, 121, 233, 202), + color=(191, 194, 197), + button=(96, 141, 213, 182), + ), ) CHECK_MILLENNIUM = ButtonWrapper( name='CHECK_MILLENNIUM', @@ -36,6 +43,13 @@ CHECK_MILLENNIUM = ButtonWrapper( color=(199, 202, 204), button=(104, 145, 283, 182), ), + zht=Button( + file='./assets/zht/scrimmage/CHECK_MILLENNIUM.png', + area=(97, 136, 185, 181), + search=(77, 116, 205, 201), + color=(216, 219, 220), + button=(97, 136, 185, 181), + ), ) CHECK_SCRIMMAGE = ButtonWrapper( name='CHECK_SCRIMMAGE', @@ -53,6 +67,13 @@ CHECK_SCRIMMAGE = ButtonWrapper( color=(92, 116, 141), button=(651, 88, 891, 130), ), + zht=Button( + file='./assets/zht/scrimmage/CHECK_SCRIMMAGE.png', + area=(649, 82, 890, 129), + search=(629, 62, 910, 149), + color=(85, 110, 136), + button=(649, 82, 890, 129), + ), ) CHECK_TRINITY = ButtonWrapper( name='CHECK_TRINITY', @@ -70,6 +91,13 @@ CHECK_TRINITY = ButtonWrapper( color=(212, 216, 217), button=(100, 143, 219, 187), ), + zht=Button( + file='./assets/zht/scrimmage/CHECK_TRINITY.png', + area=(98, 138, 182, 183), + search=(78, 118, 202, 203), + color=(226, 228, 229), + button=(98, 138, 182, 183), + ), ) OCR_TICKET = ButtonWrapper( name='OCR_TICKET', @@ -87,6 +115,13 @@ OCR_TICKET = ButtonWrapper( color=(199, 206, 212), button=(229, 88, 289, 112), ), + zht=Button( + file='./assets/zht/scrimmage/OCR_TICKET.png', + area=(155, 82, 206, 118), + search=(135, 62, 226, 138), + color=(218, 222, 225), + button=(155, 82, 206, 118), + ), ) SELECT_GEHENNA = ButtonWrapper( name='SELECT_GEHENNA', @@ -104,6 +139,13 @@ SELECT_GEHENNA = ButtonWrapper( color=(199, 208, 216), button=(1076, 273, 1223, 313), ), + zht=Button( + file='./assets/zht/scrimmage/SELECT_GEHENNA.png', + area=(1115, 268, 1228, 313), + search=(1095, 248, 1248, 333), + color=(186, 196, 207), + button=(1115, 268, 1228, 313), + ), ) SELECT_MILLENNIUM = ButtonWrapper( name='SELECT_MILLENNIUM', @@ -121,6 +163,13 @@ SELECT_MILLENNIUM = ButtonWrapper( color=(193, 202, 211), button=(1045, 380, 1224, 417), ), + zht=Button( + file='./assets/zht/scrimmage/SELECT_MILLENNIUM.png', + area=(1144, 375, 1225, 420), + search=(1124, 355, 1245, 440), + color=(207, 217, 225), + button=(1144, 375, 1225, 420), + ), ) SELECT_TRINITY = ButtonWrapper( name='SELECT_TRINITY', @@ -138,4 +187,11 @@ SELECT_TRINITY = ButtonWrapper( color=(200, 209, 218), button=(1118, 164, 1224, 205), ), + zht=Button( + file='./assets/zht/scrimmage/SELECT_TRINITY.png', + area=(1148, 162, 1225, 202), + search=(1128, 142, 1245, 222), + color=(216, 226, 234), + button=(1148, 162, 1225, 202), + ), ) diff --git a/tasks/shop/assets/assets_shop.py b/tasks/shop/assets/assets_shop.py index e06b0cb..ff4534c 100644 --- a/tasks/shop/assets/assets_shop.py +++ b/tasks/shop/assets/assets_shop.py @@ -13,6 +13,13 @@ CONFIRM_PURCHASE = ButtonWrapper( color=(217, 218, 219), button=(668, 458, 865, 514), ), + zht=Button( + file='./assets/zht/shop/CONFIRM_PURCHASE.png', + area=(523, 224, 755, 320), + search=(503, 204, 775, 340), + color=(214, 215, 215), + button=(669, 456, 873, 518), + ), ) CONFIRM_REFRESH = ButtonWrapper( name='CONFIRM_REFRESH', @@ -24,6 +31,13 @@ CONFIRM_REFRESH = ButtonWrapper( color=(202, 203, 204), button=(675, 434, 863, 500), ), + zht=Button( + file='./assets/zht/shop/CONFIRM_REFRESH.png', + area=(504, 260, 782, 308), + search=(484, 240, 802, 328), + color=(205, 206, 207), + button=(671, 432, 866, 498), + ), ) ITEM_LIST = ButtonWrapper( name='ITEM_LIST', @@ -35,6 +49,13 @@ ITEM_LIST = ButtonWrapper( color=(193, 206, 213), button=(625, 127, 1244, 610), ), + zht=Button( + file='./assets/zht/shop/ITEM_LIST.png', + area=(625, 127, 1244, 610), + search=(605, 107, 1264, 630), + color=(193, 206, 213), + button=(625, 127, 1244, 610), + ), ) NORMAL_OFF = ButtonWrapper( name='NORMAL_OFF', @@ -46,6 +67,13 @@ NORMAL_OFF = ButtonWrapper( color=(248, 248, 245), button=(4, 111, 213, 167), ), + zht=Button( + file='./assets/zht/shop/NORMAL_OFF.png', + area=(4, 104, 214, 155), + search=(0, 84, 234, 175), + color=(249, 248, 245), + button=(4, 104, 214, 155), + ), ) NORMAL_ON = ButtonWrapper( name='NORMAL_ON', @@ -57,6 +85,13 @@ NORMAL_ON = ButtonWrapper( color=(57, 78, 96), button=(4, 109, 212, 170), ), + zht=Button( + file='./assets/zht/shop/NORMAL_ON.png', + area=(2, 109, 206, 167), + search=(0, 89, 226, 187), + color=(56, 77, 97), + button=(2, 109, 206, 167), + ), ) OCR_REFRESH = ButtonWrapper( name='OCR_REFRESH', @@ -68,6 +103,13 @@ OCR_REFRESH = ButtonWrapper( color=(225, 225, 226), button=(712, 302, 762, 344), ), + zht=Button( + file='./assets/zht/shop/OCR_REFRESH.png', + area=(673, 303, 731, 341), + search=(653, 283, 751, 361), + color=(226, 227, 227), + button=(673, 303, 731, 341), + ), ) PURCHASE = ButtonWrapper( name='PURCHASE', @@ -79,6 +121,13 @@ PURCHASE = ButtonWrapper( color=(226, 206, 65), button=(1102, 640, 1227, 684), ), + zht=Button( + file='./assets/zht/shop/PURCHASE.png', + area=(1105, 640, 1231, 681), + search=(1085, 620, 1251, 701), + color=(212, 191, 62), + button=(1105, 640, 1231, 681), + ), ) REFRESH = ButtonWrapper( name='REFRESH', @@ -90,6 +139,13 @@ REFRESH = ButtonWrapper( color=(231, 234, 237), button=(1098, 643, 1223, 682), ), + zht=Button( + file='./assets/zht/shop/REFRESH.png', + area=(1096, 644, 1226, 681), + search=(1076, 624, 1246, 701), + color=(221, 224, 229), + button=(1096, 644, 1226, 681), + ), ) TC_OFF = ButtonWrapper( name='TC_OFF', @@ -101,6 +157,13 @@ TC_OFF = ButtonWrapper( color=(239, 242, 244), button=(2, 503, 209, 558), ), + zht=Button( + file='./assets/zht/shop/TC_OFF.png', + area=(4, 503, 211, 553), + search=(0, 483, 231, 573), + color=(235, 239, 241), + button=(4, 503, 211, 553), + ), ) TC_ON = ButtonWrapper( name='TC_ON', @@ -112,4 +175,11 @@ TC_ON = ButtonWrapper( color=(62, 84, 99), button=(3, 493, 208, 548), ), + zht=Button( + file='./assets/zht/shop/TC_ON.png', + area=(0, 492, 211, 548), + search=(0, 472, 231, 568), + color=(65, 86, 98), + button=(0, 492, 211, 548), + ), ) diff --git a/tasks/shop/shop.py b/tasks/shop/shop.py index 8e6d132..50cd143 100644 --- a/tasks/shop/shop.py +++ b/tasks/shop/shop.py @@ -75,7 +75,7 @@ class Shop(ShopUI): self.select_items(self.current_item_list) return ShopStatus.PURCHASE case ShopStatus.PURCHASE: - if self.make_purchase(): + if self.make_purchase() and self.current_purchase_count > 1: return ShopStatus.REFRESH return ShopStatus.END case ShopStatus.REFRESH: @@ -83,7 +83,7 @@ class Shop(ShopUI): return ShopStatus.SELECT_SHOP return ShopStatus.END case ShopStatus.END: - if self.appear(page_shop.check_button): + if self.appear(page_shop.check_button) and self.match_color(page_shop.check_button): self.task.pop(0) return ShopStatus.SELECT_SHOP self.click_with_interval(BACK, interval=2) diff --git a/tasks/shop/ui.py b/tasks/shop/ui.py index 6365cf3..54a548a 100644 --- a/tasks/shop/ui.py +++ b/tasks/shop/ui.py @@ -97,10 +97,10 @@ class ShopUI(UI): one at 8 and the other at 16. Only once for each checkpoint. """ - if (8 < item < 16) and not self.swipe_flags[8]: + if (9 <= item <= 16) and not self.swipe_flags[8]: self.swipe_flags[8] = True return True - elif item > 16 and not self.swipe_flags[16]: + elif item >= 17 and not self.swipe_flags[16]: self.swipe_flags[16] = True return True return False @@ -109,7 +109,7 @@ class ShopUI(UI): self.swipe_flags[8], self.swipe_flags[16] = False, False def make_purchase(self): - if self.select_then_check(PURCHASE, CONFIRM_PURCHASE) and self.appear_then_click(CONFIRM_PURCHASE): + if self.match_color(PURCHASE) and self.select_then_check(PURCHASE, CONFIRM_PURCHASE) and self.appear_then_click(CONFIRM_PURCHASE): return True logger.warning("No items were selected. Unable to purchase.") return False diff --git a/tasks/stage/assets/assets_stage_list.py b/tasks/stage/assets/assets_stage_list.py index 9a6bf73..63b3ae6 100644 --- a/tasks/stage/assets/assets_stage_list.py +++ b/tasks/stage/assets/assets_stage_list.py @@ -19,6 +19,13 @@ OCR_INDEX = ButtonWrapper( color=(195, 196, 193), button=(701, 149, 740, 656), ), + zht=Button( + file='./assets/zht/stage/list/OCR_INDEX.png', + area=(701, 149, 740, 656), + search=(681, 129, 760, 676), + color=(195, 196, 193), + button=(701, 149, 740, 656), + ), ) STAGE_ENTER = ButtonWrapper( name='STAGE_ENTER', @@ -36,6 +43,13 @@ STAGE_ENTER = ButtonWrapper( color=(118, 195, 226), button=(1080, 168, 1156, 204), ), + zht=Button( + file='./assets/zht/stage/list/STAGE_ENTER.png', + area=(1075, 170, 1159, 202), + search=(1055, 150, 1179, 222), + color=(119, 197, 227), + button=(1075, 170, 1159, 202), + ), ) STAGE_ITEM = ButtonWrapper( name='STAGE_ITEM', @@ -53,6 +67,13 @@ STAGE_ITEM = ButtonWrapper( color=(212, 228, 233), button=(687, 148, 1181, 227), ), + zht=Button( + file='./assets/zht/stage/list/STAGE_ITEM.png', + area=(687, 148, 1181, 227), + search=(667, 128, 1201, 247), + color=(212, 228, 233), + button=(687, 148, 1181, 227), + ), ) STAGE_LIST = ButtonWrapper( name='STAGE_LIST', @@ -70,6 +91,13 @@ STAGE_LIST = ButtonWrapper( color=(194, 204, 209), button=(675, 136, 1190, 676), ), + zht=Button( + file='./assets/zht/stage/list/STAGE_LIST.png', + area=(675, 136, 1190, 676), + search=(655, 116, 1210, 696), + color=(194, 204, 209), + button=(675, 136, 1190, 676), + ), ) STAGE_STARS = ButtonWrapper( name='STAGE_STARS', @@ -87,4 +115,11 @@ STAGE_STARS = ButtonWrapper( color=(225, 214, 166), button=(693, 192, 746, 212), ), + zht=Button( + file='./assets/zht/stage/list/STAGE_STARS.png', + area=(693, 192, 746, 212), + search=(673, 172, 766, 232), + color=(225, 214, 166), + button=(693, 192, 746, 212), + ), ) diff --git a/tasks/stage/assets/assets_stage_sweep.py b/tasks/stage/assets/assets_stage_sweep.py index 6bb0861..a610588 100644 --- a/tasks/stage/assets/assets_stage_sweep.py +++ b/tasks/stage/assets/assets_stage_sweep.py @@ -19,6 +19,13 @@ CHECK_SWEEP = ButtonWrapper( color=(169, 180, 194), button=(654, 187, 706, 215), ), + zht=Button( + file='./assets/zht/stage/sweep/CHECK_SWEEP.png', + area=(651, 182, 702, 210), + search=(631, 162, 722, 230), + color=(201, 207, 215), + button=(651, 182, 702, 210), + ), ) ENTER = ButtonWrapper( name='ENTER', @@ -36,6 +43,13 @@ ENTER = ButtonWrapper( color=(226, 211, 69), button=(781, 508, 1085, 572), ), + zht=Button( + file='./assets/zht/stage/sweep/ENTER.png', + area=(764, 518, 1109, 574), + search=(744, 498, 1129, 594), + color=(226, 210, 67), + button=(764, 518, 1109, 574), + ), ) EXIT = ButtonWrapper( name='EXIT', @@ -53,6 +67,13 @@ EXIT = ButtonWrapper( color=(185, 193, 203), button=(1114, 127, 1141, 154), ), + zht=Button( + file='./assets/zht/stage/sweep/EXIT.png', + area=(1114, 127, 1141, 154), + search=(1094, 107, 1161, 174), + color=(185, 193, 203), + button=(1114, 127, 1141, 154), + ), ) MAX = ButtonWrapper( name='MAX', @@ -70,6 +91,13 @@ MAX = ButtonWrapper( color=(216, 222, 228), button=(1054, 279, 1111, 321), ), + zht=Button( + file='./assets/zht/stage/sweep/MAX.png', + area=(1054, 279, 1111, 321), + search=(1034, 259, 1131, 341), + color=(216, 222, 228), + button=(1054, 279, 1111, 321), + ), ) MIN = ButtonWrapper( name='MIN', @@ -87,6 +115,13 @@ MIN = ButtonWrapper( color=(194, 194, 194), button=(760, 278, 816, 322), ), + zht=Button( + file='./assets/zht/stage/sweep/MIN.png', + area=(760, 278, 816, 322), + search=(740, 258, 836, 342), + color=(194, 194, 194), + button=(760, 278, 816, 322), + ), ) MINUS = ButtonWrapper( name='MINUS', @@ -104,6 +139,13 @@ MINUS = ButtonWrapper( color=(221, 222, 222), button=(838, 279, 876, 320), ), + zht=Button( + file='./assets/zht/stage/sweep/MINUS.png', + area=(838, 279, 876, 320), + search=(818, 259, 896, 340), + color=(221, 222, 222), + button=(838, 279, 876, 320), + ), ) OCR_NUM = ButtonWrapper( name='OCR_NUM', @@ -121,6 +163,13 @@ OCR_NUM = ButtonWrapper( color=(81, 94, 113), button=(896, 281, 975, 323), ), + zht=Button( + file='./assets/zht/stage/sweep/OCR_NUM.png', + area=(896, 281, 975, 323), + search=(876, 261, 995, 343), + color=(81, 94, 113), + button=(896, 281, 975, 323), + ), ) PLUS = ButtonWrapper( name='PLUS', @@ -138,6 +187,13 @@ PLUS = ButtonWrapper( color=(233, 243, 246), button=(995, 278, 1034, 322), ), + zht=Button( + file='./assets/zht/stage/sweep/PLUS.png', + area=(995, 278, 1034, 322), + search=(975, 258, 1054, 342), + color=(233, 243, 246), + button=(995, 278, 1034, 322), + ), ) SKIP_OK_LOWER = ButtonWrapper( name='SKIP_OK_LOWER', @@ -155,6 +211,13 @@ SKIP_OK_LOWER = ButtonWrapper( color=(108, 204, 240), button=(540, 548, 741, 619), ), + zht=Button( + file='./assets/zht/stage/sweep/SKIP_OK_LOWER.png', + area=(542, 552, 739, 620), + search=(522, 532, 759, 640), + color=(109, 206, 241), + button=(542, 552, 739, 620), + ), ) SKIP_OK_UPPER = ButtonWrapper( name='SKIP_OK_UPPER', @@ -172,6 +235,13 @@ SKIP_OK_UPPER = ButtonWrapper( color=(107, 203, 239), button=(541, 476, 741, 542), ), + zht=Button( + file='./assets/zht/stage/sweep/SKIP_OK_UPPER.png', + area=(535, 479, 745, 542), + search=(515, 459, 765, 562), + color=(108, 206, 241), + button=(535, 479, 745, 542), + ), ) SKIP_SKIP = ButtonWrapper( name='SKIP_SKIP', @@ -189,6 +259,13 @@ SKIP_SKIP = ButtonWrapper( color=(110, 209, 244), button=(543, 477, 739, 542), ), + zht=Button( + file='./assets/zht/stage/sweep/SKIP_SKIP.png', + area=(539, 479, 743, 538), + search=(519, 459, 763, 558), + color=(109, 208, 243), + button=(539, 479, 743, 538), + ), ) SWEEP = ButtonWrapper( name='SWEEP', @@ -206,6 +283,13 @@ SWEEP = ButtonWrapper( color=(108, 202, 236), button=(795, 382, 1066, 431), ), + zht=Button( + file='./assets/zht/stage/sweep/SWEEP.png', + area=(776, 391, 1093, 434), + search=(756, 371, 1113, 454), + color=(105, 199, 233), + button=(776, 391, 1093, 434), + ), ) SWEEP_CONFIRM = ButtonWrapper( name='SWEEP_CONFIRM', @@ -223,4 +307,11 @@ SWEEP_CONFIRM = ButtonWrapper( color=(196, 203, 211), button=(665, 471, 871, 535), ), + zht=Button( + file='./assets/zht/stage/sweep/SWEEP_CONFIRM.png', + area=(596, 142, 678, 180), + search=(576, 122, 698, 200), + color=(185, 193, 202), + button=(662, 474, 869, 534), + ), ) diff --git a/tasks/stage/mission_list.py b/tasks/stage/mission_list.py index 340b73b..c622ca6 100644 --- a/tasks/stage/mission_list.py +++ b/tasks/stage/mission_list.py @@ -25,7 +25,7 @@ class StageList: ): self.name = name self.stage = button_list if button_list else STAGE_LIST - self.index_ocr = Ocr(button_index if button_index else OCR_INDEX, lang='en') + self.index_ocr = Ocr(button_index if button_index else OCR_INDEX, lang='zhs') self.stage_item = (button_item if button_item else STAGE_ITEM).button self.enter = button_enter if button_enter else STAGE_ENTER self.sweepable = button_stars if button_stars else STAGE_STARS diff --git a/tasks/tactical_challenge/assets/assets_tactical_challenge.py b/tasks/tactical_challenge/assets/assets_tactical_challenge.py index 6b03847..98f2616 100644 --- a/tasks/tactical_challenge/assets/assets_tactical_challenge.py +++ b/tasks/tactical_challenge/assets/assets_tactical_challenge.py @@ -19,6 +19,13 @@ CHALLENGE_LOSE = ButtonWrapper( color=(206, 213, 219), button=(544, 435, 741, 496), ), + zht=Button( + file='./assets/zht/tactical_challenge/CHALLENGE_LOSE.png', + area=(567, 190, 707, 226), + search=(547, 170, 727, 246), + color=(177, 186, 196), + button=(544, 434, 738, 494), + ), ) CHALLENGE_WIN = ButtonWrapper( name='CHALLENGE_WIN', @@ -36,6 +43,13 @@ CHALLENGE_WIN = ButtonWrapper( color=(193, 201, 210), button=(549, 500, 742, 555), ), + zht=Button( + file='./assets/zht/tactical_challenge/CHALLENGE_WIN.png', + area=(559, 123, 710, 163), + search=(539, 103, 730, 183), + color=(190, 200, 210), + button=(546, 499, 740, 562), + ), ) GET_REWARD_CREDIT = ButtonWrapper( name='GET_REWARD_CREDIT', @@ -53,6 +67,13 @@ GET_REWARD_CREDIT = ButtonWrapper( color=(233, 213, 66), button=(307, 361, 402, 414), ), + zht=Button( + file='./assets/zht/tactical_challenge/GET_REWARD_CREDIT.png', + area=(304, 361, 403, 413), + search=(284, 341, 423, 433), + color=(215, 193, 60), + button=(304, 361, 403, 413), + ), ) GET_REWARD_DAILY = ButtonWrapper( name='GET_REWARD_DAILY', @@ -70,6 +91,13 @@ GET_REWARD_DAILY = ButtonWrapper( color=(232, 212, 65), button=(307, 442, 399, 494), ), + zht=Button( + file='./assets/zht/tactical_challenge/GET_REWARD_DAILY.png', + area=(302, 441, 401, 492), + search=(282, 421, 421, 512), + color=(215, 193, 60), + button=(302, 441, 401, 492), + ), ) GOT_REWARD_CREDIT = ButtonWrapper( name='GOT_REWARD_CREDIT', @@ -87,6 +115,13 @@ GOT_REWARD_CREDIT = ButtonWrapper( color=(209, 211, 210), button=(307, 361, 400, 416), ), + zht=Button( + file='./assets/zht/tactical_challenge/GOT_REWARD_CREDIT.png', + area=(304, 363, 403, 413), + search=(284, 343, 423, 433), + color=(202, 204, 202), + button=(304, 363, 403, 413), + ), ) GOT_REWARD_DAILY = ButtonWrapper( name='GOT_REWARD_DAILY', @@ -104,6 +139,13 @@ GOT_REWARD_DAILY = ButtonWrapper( color=(210, 210, 210), button=(305, 439, 402, 497), ), + zht=Button( + file='./assets/zht/tactical_challenge/GOT_REWARD_DAILY.png', + area=(304, 440, 400, 498), + search=(284, 420, 420, 518), + color=(203, 203, 204), + button=(304, 440, 400, 498), + ), ) OCR_TICKET = ButtonWrapper( name='OCR_TICKET', @@ -121,6 +163,13 @@ OCR_TICKET = ButtonWrapper( color=(223, 226, 228), button=(211, 472, 251, 505), ), + zht=Button( + file='./assets/zht/tactical_challenge/OCR_TICKET.png', + area=(156, 473, 218, 504), + search=(136, 453, 238, 524), + color=(215, 216, 219), + button=(156, 473, 218, 504), + ), ) PLAYER_SELECT_FIRST = ButtonWrapper( name='PLAYER_SELECT_FIRST', @@ -138,6 +187,13 @@ PLAYER_SELECT_FIRST = ButtonWrapper( color=(206, 214, 220), button=(606, 181, 1100, 256), ), + zht=Button( + file='./assets/zht/tactical_challenge/PLAYER_SELECT_FIRST.png', + area=(469, 289, 512, 325), + search=(449, 269, 532, 345), + color=(206, 214, 221), + button=(606, 173, 1099, 260), + ), ) PLAYER_SELECT_SECOND = ButtonWrapper( name='PLAYER_SELECT_SECOND', @@ -155,6 +211,13 @@ PLAYER_SELECT_SECOND = ButtonWrapper( color=(210, 219, 225), button=(610, 338, 1098, 407), ), + zht=Button( + file='./assets/zht/tactical_challenge/PLAYER_SELECT_SECOND.png', + area=(471, 451, 504, 480), + search=(451, 431, 524, 500), + color=(201, 209, 215), + button=(606, 334, 1102, 416), + ), ) PLAYER_SELECT_THIRD = ButtonWrapper( name='PLAYER_SELECT_THIRD', @@ -172,6 +235,13 @@ PLAYER_SELECT_THIRD = ButtonWrapper( color=(208, 216, 222), button=(609, 500, 1101, 565), ), + zht=Button( + file='./assets/zht/tactical_challenge/PLAYER_SELECT_THIRD.png', + area=(470, 609, 503, 638), + search=(450, 589, 523, 658), + color=(201, 209, 215), + button=(613, 490, 1099, 572), + ), ) PREPARE_CHALLENGE = ButtonWrapper( name='PREPARE_CHALLENGE', @@ -189,6 +259,13 @@ PREPARE_CHALLENGE = ButtonWrapper( color=(191, 199, 208), button=(538, 555, 745, 602), ), + zht=Button( + file='./assets/zht/tactical_challenge/PREPARE_CHALLENGE.png', + area=(573, 74, 701, 113), + search=(553, 54, 721, 133), + color=(176, 186, 196), + button=(535, 548, 744, 602), + ), ) SKIP_OFF = ButtonWrapper( name='SKIP_OFF', @@ -206,6 +283,13 @@ SKIP_OFF = ButtonWrapper( color=(96, 137, 171), button=(1088, 585, 1249, 623), ), + zht=Button( + file='./assets/zht/tactical_challenge/SKIP_OFF.png', + area=(1121, 583, 1162, 625), + search=(1101, 563, 1182, 645), + color=(91, 131, 165), + button=(1123, 582, 1250, 625), + ), ) SKIP_ON = ButtonWrapper( name='SKIP_ON', @@ -223,6 +307,13 @@ SKIP_ON = ButtonWrapper( color=(99, 177, 212), button=(1090, 582, 1252, 625), ), + zht=Button( + file='./assets/zht/tactical_challenge/SKIP_ON.png', + area=(1123, 584, 1161, 622), + search=(1103, 564, 1181, 642), + color=(91, 147, 182), + button=(1123, 584, 1251, 622), + ), ) START_CHALLENGE = ButtonWrapper( name='START_CHALLENGE', @@ -240,4 +331,11 @@ START_CHALLENGE = ButtonWrapper( color=(190, 199, 209), button=(1089, 637, 1250, 704), ), + zht=Button( + file='./assets/zht/tactical_challenge/START_CHALLENGE.png', + area=(102, 8, 246, 38), + search=(82, 0, 266, 58), + color=(160, 172, 184), + button=(1089, 640, 1253, 701), + ), ) diff --git a/tasks/tactical_challenge/tactical_challenge.py b/tasks/tactical_challenge/tactical_challenge.py index 8202be6..66880e0 100644 --- a/tasks/tactical_challenge/tactical_challenge.py +++ b/tasks/tactical_challenge/tactical_challenge.py @@ -33,10 +33,10 @@ class TacticalChallenge(TacticalChallengeUI): return self.config.stored.TacticalChallengeTicket.value def _player_select(self, select): - if select: + if not select: return random.choice(self.select_players) else: - return self.select_players[select] + return self.select_players[select-1] def _handle_challenge(self, status): match status: diff --git a/tasks/task/assets/assets_task.py b/tasks/task/assets/assets_task.py index 4bfb5bd..e85455a 100644 --- a/tasks/task/assets/assets_task.py +++ b/tasks/task/assets/assets_task.py @@ -19,6 +19,13 @@ CLAIM = ButtonWrapper( color=(234, 214, 69), button=(935, 639, 1015, 698), ), + zht=Button( + file='./assets/zht/task/CLAIM.png', + area=(929, 647, 1016, 693), + search=(909, 627, 1036, 713), + color=(230, 210, 62), + button=(929, 647, 1016, 693), + ), ) CLAIMED = ButtonWrapper( name='CLAIMED', @@ -36,6 +43,13 @@ CLAIMED = ButtonWrapper( color=(212, 212, 211), button=(937, 641, 1010, 696), ), + zht=Button( + file='./assets/zht/task/CLAIMED.png', + area=(929, 645, 1014, 699), + search=(909, 625, 1034, 719), + color=(211, 211, 210), + button=(929, 645, 1014, 699), + ), ) CLAIMED_ALL = ButtonWrapper( name='CLAIMED_ALL', @@ -53,6 +67,13 @@ CLAIMED_ALL = ButtonWrapper( color=(193, 193, 196), button=(1058, 641, 1240, 701), ), + zht=Button( + file='./assets/zht/task/CLAIMED_ALL.png', + area=(1058, 646, 1246, 701), + search=(1038, 626, 1266, 720), + color=(190, 190, 193), + button=(1058, 646, 1246, 701), + ), ) CLAIM_ALL = ButtonWrapper( name='CLAIM_ALL', @@ -70,6 +91,13 @@ CLAIM_ALL = ButtonWrapper( color=(236, 219, 67), button=(1054, 642, 1243, 700), ), + zht=Button( + file='./assets/zht/task/CLAIM_ALL.png', + area=(1050, 645, 1248, 699), + search=(1030, 625, 1268, 719), + color=(231, 213, 65), + button=(1050, 645, 1248, 699), + ), ) COMPLETE = ButtonWrapper( name='COMPLETE', @@ -81,4 +109,11 @@ COMPLETE = ButtonWrapper( color=(127, 131, 135), button=(921, 643, 1026, 692), ), + zht=Button( + file='./assets/zht/task/COMPLETE.png', + area=(933, 644, 1016, 697), + search=(913, 624, 1036, 717), + color=(127, 131, 135), + button=(933, 644, 1016, 697), + ), ) diff --git a/tasks/task/task.py b/tasks/task/task.py index 2e0a9e6..97009ad 100644 --- a/tasks/task/task.py +++ b/tasks/task/task.py @@ -23,7 +23,7 @@ class Task(UI): self.device.click(CLAIM) logger.info("Click Claim") continue - if (self.match_color(CLAIMED) or self.match_color(COMPLETE)) and self.match_color(CLAIMED_ALL): + if self.match_color(CLAIMED_ALL) and not self.match_color(CLAIM): logger.info("All claimed") break