Refactor: Link task dungeon with daily quests

This commit is contained in:
LmeSzinc 2023-08-27 17:13:05 +08:00
parent 4719d3da60
commit a5e2eb0004
20 changed files with 2401 additions and 163 deletions

View File

@ -43,9 +43,20 @@
"Name": "Calyx_Golden_Treasures", "Name": "Calyx_Golden_Treasures",
"NameAtDoubleCalyx": "Calyx_Golden_Treasures", "NameAtDoubleCalyx": "Calyx_Golden_Treasures",
"NameAtDoubleRelic": "Cavern_of_Corrosion_Path_of_Providence", "NameAtDoubleRelic": "Cavern_of_Corrosion_Path_of_Providence",
"Team": 1, "Team": 1
"Support": "when_daily", },
"SupportCharacter": "FirstCharacter" "DungeonDaily": {
"CalyxGolden": "Calyx_Golden_Treasures",
"CalyxCrimson": "Calyx_Crimson_Erudition",
"StagnantShadow": "do_not_archive",
"CavernOfCorrosion": "Cavern_of_Corrosion_Path_of_Providence"
},
"DungeonSupport": {
"Use": "when_daily",
"Character": "FirstCharacter"
},
"DungeonStorage": {
"DungeonDouble": {}
} }
}, },
"DailyQuest": { "DailyQuest": {
@ -54,6 +65,37 @@
"NextRun": "2020-01-01 00:00:00", "NextRun": "2020-01-01 00:00:00",
"Command": "DailyQuest", "Command": "DailyQuest",
"ServerUpdate": "04:00" "ServerUpdate": "04:00"
},
"AchievableQuest": {
"Complete_1_Daily_Mission": "not_supported",
"Clear_Calyx_Golden_1_times": "not_set",
"Complete_Calyx_Crimson_1_time": "not_set",
"Clear_Stagnant_Shadow_1_times": "not_set",
"Clear_Cavern_of_Corrosion_1_times": "not_set",
"In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": "not_supported",
"Inflict_Weakness_Break_5_times": "not_supported",
"Defeat_a_total_of_20_enemies": "not_supported",
"Enter_combat_by_attacking_enemy_Weakness_and_win_3_times": "not_supported",
"Use_Technique_2_times": "achievable",
"Go_on_assignment_1_time": "not_set",
"Take_1_photo": "achievable",
"Destroy_3_destructible_objects": "not_supported",
"Complete_Forgotten_Hall_1_time": "not_supported",
"Complete_Echo_of_War_1_times": "not_supported",
"Complete_1_stage_in_Simulated_Universe_Any_world": "not_supported",
"Obtain_victory_in_combat_with_support_characters_1_time": "not_set",
"Use_an_Ultimate_to_deal_the_final_blow_1_time": "not_supported",
"Level_up_any_character_1_time": "not_supported",
"Level_up_any_Light_Cone_1_time": "not_supported",
"Level_up_any_Relic_1_time": "not_supported",
"Salvage_any_Relic": "achievable",
"Synthesize_Consumable_1_time": "achievable",
"Synthesize_material_1_time": "achievable",
"Use_Consumables_1_time": "achievable"
},
"DailyStorage": {
"DailyActivity": {},
"DailyQuest": {}
} }
}, },
"BattlePass": { "BattlePass": {

View File

@ -243,17 +243,76 @@
5, 5,
6 6
] ]
}
},
"DungeonDaily": {
"CalyxGolden": {
"type": "select",
"value": "Calyx_Golden_Treasures",
"option": [
"do_not_achieve",
"Calyx_Golden_Memories",
"Calyx_Golden_Aether",
"Calyx_Golden_Treasures"
]
}, },
"Support": { "CalyxCrimson": {
"type": "select",
"value": "Calyx_Crimson_Erudition",
"option": [
"do_not_achieve",
"Calyx_Crimson_Destruction",
"Calyx_Crimson_Preservation",
"Calyx_Crimson_Hunt",
"Calyx_Crimson_Abundance",
"Calyx_Crimson_Erudition",
"Calyx_Crimson_Harmony",
"Calyx_Crimson_Nihility"
]
},
"StagnantShadow": {
"type": "select",
"value": "do_not_archive",
"option": [
"do_not_achieve",
"Stagnant_Shadow_Quanta",
"Stagnant_Shadow_Gust",
"Stagnant_Shadow_Fulmination",
"Stagnant_Shadow_Blaze",
"Stagnant_Shadow_Spike",
"Stagnant_Shadow_Rime",
"Stagnant_Shadow_Mirage",
"Stagnant_Shadow_Icicle",
"Stagnant_Shadow_Doom",
"Stagnant_Shadow_Celestial"
]
},
"CavernOfCorrosion": {
"type": "select",
"value": "Cavern_of_Corrosion_Path_of_Providence",
"option": [
"do_not_achieve",
"Cavern_of_Corrosion_Path_of_Gelid_Wind",
"Cavern_of_Corrosion_Path_of_Jabbing_Punch",
"Cavern_of_Corrosion_Path_of_Drifting",
"Cavern_of_Corrosion_Path_of_Providence",
"Cavern_of_Corrosion_Path_of_Holy_Hymn",
"Cavern_of_Corrosion_Path_of_Conflagration",
"Cavern_of_Corrosion_Path_of_Elixir_Seekers"
]
}
},
"DungeonSupport": {
"Use": {
"type": "select", "type": "select",
"value": "when_daily", "value": "when_daily",
"option": [ "option": [
"do_not_use",
"always_use", "always_use",
"when_daily" "when_daily",
"do_not_use"
] ]
}, },
"SupportCharacter": { "Character": {
"type": "select", "type": "select",
"value": "FirstCharacter", "value": "FirstCharacter",
"option": [ "option": [
@ -290,6 +349,14 @@
"Yukong" "Yukong"
] ]
} }
},
"DungeonStorage": {
"DungeonDouble": {
"type": "stored",
"value": {},
"display": "hide",
"stored": "StoredDungeonDouble"
}
} }
}, },
"DailyQuest": { "DailyQuest": {
@ -313,6 +380,397 @@
"value": "04:00", "value": "04:00",
"display": "hide" "display": "hide"
} }
},
"AchievableQuest": {
"Complete_1_Daily_Mission": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Clear_Calyx_Golden_1_times": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Complete_Calyx_Crimson_1_time": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Clear_Stagnant_Shadow_1_times": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Clear_Cavern_of_Corrosion_1_times": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Inflict_Weakness_Break_5_times": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Defeat_a_total_of_20_enemies": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Enter_combat_by_attacking_enemy_Weakness_and_win_3_times": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Use_Technique_2_times": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Go_on_assignment_1_time": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Take_1_photo": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Destroy_3_destructible_objects": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Complete_Forgotten_Hall_1_time": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Complete_Echo_of_War_1_times": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Complete_1_stage_in_Simulated_Universe_Any_world": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Obtain_victory_in_combat_with_support_characters_1_time": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Use_an_Ultimate_to_deal_the_final_blow_1_time": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Level_up_any_character_1_time": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Level_up_any_Light_Cone_1_time": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Level_up_any_Relic_1_time": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Salvage_any_Relic": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Synthesize_Consumable_1_time": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Synthesize_material_1_time": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
},
"Use_Consumables_1_time": {
"type": "state",
"value": "achievable",
"option": [
"achievable",
"not_set",
"not_supported"
],
"option_bold": [
"achievable"
],
"option_light": [
"not_supported"
]
}
},
"DailyStorage": {
"DailyActivity": {
"type": "stored",
"value": {},
"display": "hide",
"stored": "StoredDailyActivity"
},
"DailyQuest": {
"type": "stored",
"value": {},
"display": "hide",
"stored": "StoredDaily"
}
} }
}, },
"BattlePass": { "BattlePass": {

View File

@ -71,27 +71,56 @@ Optimization:
Dungeon: Dungeon:
Name: Name:
# Options will be injected in config updater # Dungeon names will be injected in config updater
value: Calyx_Golden_Treasures value: Calyx_Golden_Treasures
option: [Calyx_Golden_Treasures, ] option: [ ]
NameAtDoubleCalyx: NameAtDoubleCalyx:
# Options will be injected in config updater
value: Calyx_Golden_Treasures value: Calyx_Golden_Treasures
option: [ do_not_participate, ] option: [ do_not_participate, ]
NameAtDoubleRelic: NameAtDoubleRelic:
# Options will be injected in config updater
value: Cavern_of_Corrosion_Path_of_Providence value: Cavern_of_Corrosion_Path_of_Providence
option: [ do_not_participate, ] option: [ do_not_participate, ]
Team: Team:
value: 1 value: 1
option: [ 1, 2, 3, 4, 5, 6 ] option: [ 1, 2, 3, 4, 5, 6 ]
Support: DungeonDaily:
# Dungeon names will be injected in config updater
CalyxGolden:
value: Calyx_Golden_Treasures
option: [ do_not_achieve, ]
CalyxCrimson:
value: Calyx_Crimson_Erudition
option: [ do_not_achieve, ]
StagnantShadow:
value: do_not_archive
option: [ do_not_achieve, ]
CavernOfCorrosion:
value: Cavern_of_Corrosion_Path_of_Providence
option: [ do_not_achieve, ]
DungeonSupport:
Use:
value: when_daily value: when_daily
option: [do_not_use, always_use, when_daily] option: [ always_use, when_daily, do_not_use ]
SupportCharacter: Character:
# Options will be injected in config updater # Options will be injected in config updater
value: FirstCharacter value: FirstCharacter
option: [FirstCharacter, ] option: [ FirstCharacter, ]
DungeonStorage:
DungeonDouble:
stored: StoredDungeonDouble
AchievableQuest:
# Quests will be injected in config updater
# Complete_1_Daily_Mission:
# type: state
# value: achievable
# option: [ achievable, not_set, not_supported ]
# option_bold: [ achievable, ]
DailyStorage:
DailyActivity:
stored: StoredDailyActivity
DailyQuest:
stored: StoredDaily
Assignment: Assignment:
Duration: Duration:

View File

@ -25,8 +25,13 @@ Daily:
Dungeon: Dungeon:
- Scheduler - Scheduler
- Dungeon - Dungeon
- DungeonDaily
- DungeonSupport
- DungeonStorage
DailyQuest: DailyQuest:
- Scheduler - Scheduler
- AchievableQuest
- DailyStorage
BattlePass: BattlePass:
- Scheduler - Scheduler
Assignment: Assignment:

View File

@ -3,11 +3,14 @@ import datetime
import operator import operator
import threading import threading
from module.base.decorator import cached_property, del_cached_property
from module.base.filter import Filter from module.base.filter import Filter
from module.base.utils import SelectedGrids from module.base.utils import SelectedGrids
from module.config.config_generated import GeneratedConfig from module.config.config_generated import GeneratedConfig
from module.config.config_manual import ManualConfig from module.config.config_manual import ManualConfig
from module.config.config_updater import ConfigUpdater from module.config.config_updater import ConfigUpdater
from module.config.stored.stored_generated import StoredGenerated
from module.config.stored.classes import iter_attribute
from module.config.utils import * from module.config.utils import *
from module.config.watcher import ConfigWatcher from module.config.watcher import ConfigWatcher
from module.exception import RequestHumanTakeover, ScriptError from module.exception import RequestHumanTakeover, ScriptError
@ -168,6 +171,15 @@ class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig, ConfigWatcher
self.data, keys="Alas.Optimization.CloseGameDuringWait", default=False self.data, keys="Alas.Optimization.CloseGameDuringWait", default=False
) )
@cached_property
def stored(self) -> StoredGenerated:
stored = StoredGenerated()
# Bind config
for _, value in iter_attribute(stored):
value._bind(self)
del_cached_property(value, '_stored')
return stored
def get_next_task(self): def get_next_task(self):
""" """
Calculate tasks, set pending_task and waiting_task Calculate tasks, set pending_task and waiting_task
@ -241,6 +253,7 @@ class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig, ConfigWatcher
) )
# Don't use self.modified = {}, that will create a new object. # Don't use self.modified = {}, that will create a new object.
self.modified.clear() self.modified.clear()
del_cached_property(self, 'stored')
self.write_file(self.config_name, data=self.data) self.write_file(self.config_name, data=self.data)
def update(self): def update(self):

View File

@ -43,8 +43,50 @@ class GeneratedConfig:
Dungeon_NameAtDoubleCalyx = 'Calyx_Golden_Treasures' # do_not_participate, Calyx_Golden_Memories, Calyx_Golden_Aether, Calyx_Golden_Treasures, Calyx_Crimson_Destruction, Calyx_Crimson_Preservation, Calyx_Crimson_Hunt, Calyx_Crimson_Abundance, Calyx_Crimson_Erudition, Calyx_Crimson_Harmony, Calyx_Crimson_Nihility Dungeon_NameAtDoubleCalyx = 'Calyx_Golden_Treasures' # do_not_participate, Calyx_Golden_Memories, Calyx_Golden_Aether, Calyx_Golden_Treasures, Calyx_Crimson_Destruction, Calyx_Crimson_Preservation, Calyx_Crimson_Hunt, Calyx_Crimson_Abundance, Calyx_Crimson_Erudition, Calyx_Crimson_Harmony, Calyx_Crimson_Nihility
Dungeon_NameAtDoubleRelic = 'Cavern_of_Corrosion_Path_of_Providence' # do_not_participate, Cavern_of_Corrosion_Path_of_Gelid_Wind, Cavern_of_Corrosion_Path_of_Jabbing_Punch, Cavern_of_Corrosion_Path_of_Drifting, Cavern_of_Corrosion_Path_of_Providence, Cavern_of_Corrosion_Path_of_Holy_Hymn, Cavern_of_Corrosion_Path_of_Conflagration, Cavern_of_Corrosion_Path_of_Elixir_Seekers Dungeon_NameAtDoubleRelic = 'Cavern_of_Corrosion_Path_of_Providence' # do_not_participate, Cavern_of_Corrosion_Path_of_Gelid_Wind, Cavern_of_Corrosion_Path_of_Jabbing_Punch, Cavern_of_Corrosion_Path_of_Drifting, Cavern_of_Corrosion_Path_of_Providence, Cavern_of_Corrosion_Path_of_Holy_Hymn, Cavern_of_Corrosion_Path_of_Conflagration, Cavern_of_Corrosion_Path_of_Elixir_Seekers
Dungeon_Team = 1 # 1, 2, 3, 4, 5, 6 Dungeon_Team = 1 # 1, 2, 3, 4, 5, 6
Dungeon_Support = 'when_daily' # do_not_use, always_use, when_daily
Dungeon_SupportCharacter = 'FirstCharacter' # FirstCharacter, Arlan, Asta, Bailu, Blade, Bronya, Clara, DanHeng, Gepard, Herta, Himeko, Hook, JingYuan, Kafka, Luka, Luocha, March7th, Natasha, Pela, Qingque, Sampo, Seele, Serval, SilverWolf, Sushang, Tingyun, TrailblazerDestruction, TrailblazerPreservation, Welt, Yanqing, Yukong # Group `DungeonDaily`
DungeonDaily_CalyxGolden = 'Calyx_Golden_Treasures' # do_not_achieve, Calyx_Golden_Memories, Calyx_Golden_Aether, Calyx_Golden_Treasures
DungeonDaily_CalyxCrimson = 'Calyx_Crimson_Erudition' # do_not_achieve, Calyx_Crimson_Destruction, Calyx_Crimson_Preservation, Calyx_Crimson_Hunt, Calyx_Crimson_Abundance, Calyx_Crimson_Erudition, Calyx_Crimson_Harmony, Calyx_Crimson_Nihility
DungeonDaily_StagnantShadow = 'do_not_archive' # do_not_achieve, Stagnant_Shadow_Quanta, Stagnant_Shadow_Gust, Stagnant_Shadow_Fulmination, Stagnant_Shadow_Blaze, Stagnant_Shadow_Spike, Stagnant_Shadow_Rime, Stagnant_Shadow_Mirage, Stagnant_Shadow_Icicle, Stagnant_Shadow_Doom, Stagnant_Shadow_Celestial
DungeonDaily_CavernOfCorrosion = 'Cavern_of_Corrosion_Path_of_Providence' # do_not_achieve, Cavern_of_Corrosion_Path_of_Gelid_Wind, Cavern_of_Corrosion_Path_of_Jabbing_Punch, Cavern_of_Corrosion_Path_of_Drifting, Cavern_of_Corrosion_Path_of_Providence, Cavern_of_Corrosion_Path_of_Holy_Hymn, Cavern_of_Corrosion_Path_of_Conflagration, Cavern_of_Corrosion_Path_of_Elixir_Seekers
# Group `DungeonSupport`
DungeonSupport_Use = 'when_daily' # always_use, when_daily, do_not_use
DungeonSupport_Character = 'FirstCharacter' # FirstCharacter, Arlan, Asta, Bailu, Blade, Bronya, Clara, DanHeng, Gepard, Herta, Himeko, Hook, JingYuan, Kafka, Luka, Luocha, March7th, Natasha, Pela, Qingque, Sampo, Seele, Serval, SilverWolf, Sushang, Tingyun, TrailblazerDestruction, TrailblazerPreservation, Welt, Yanqing, Yukong
# Group `DungeonStorage`
DungeonStorage_DungeonDouble = {}
# Group `AchievableQuest`
AchievableQuest_Complete_1_Daily_Mission = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Clear_Calyx_Golden_1_times = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Complete_Calyx_Crimson_1_time = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Clear_Stagnant_Shadow_1_times = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Clear_Cavern_of_Corrosion_1_times = 'achievable' # achievable, not_set, not_supported
AchievableQuest_In_a_single_battle_inflict_3_Weakness_Break_of_different_Types = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Inflict_Weakness_Break_5_times = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Defeat_a_total_of_20_enemies = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Enter_combat_by_attacking_enemy_Weakness_and_win_3_times = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Use_Technique_2_times = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Go_on_assignment_1_time = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Take_1_photo = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Destroy_3_destructible_objects = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Complete_Forgotten_Hall_1_time = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Complete_Echo_of_War_1_times = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Complete_1_stage_in_Simulated_Universe_Any_world = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Obtain_victory_in_combat_with_support_characters_1_time = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Use_an_Ultimate_to_deal_the_final_blow_1_time = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Level_up_any_character_1_time = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Level_up_any_Light_Cone_1_time = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Level_up_any_Relic_1_time = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Salvage_any_Relic = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Synthesize_Consumable_1_time = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Synthesize_material_1_time = 'achievable' # achievable, not_set, not_supported
AchievableQuest_Use_Consumables_1_time = 'achievable' # achievable, not_set, not_supported
# Group `DailyStorage`
DailyStorage_DailyActivity = {}
DailyStorage_DailyQuest = {}
# Group `Assignment` # Group `Assignment`
Assignment_Duration = 20 # 4, 8, 12, 20 Assignment_Duration = 20 # 4, 8, 12, 20

View File

@ -8,7 +8,7 @@ class ManualConfig:
SCHEDULER_PRIORITY = """ SCHEDULER_PRIORITY = """
Restart Restart
> Dungeon > Assignment > DailyQuest > BattlePass > DailyQuest > Dungeon > Assignment > BattlePass
""" """
""" """

View File

@ -4,7 +4,7 @@ from cached_property import cached_property
from deploy.Windows.utils import DEPLOY_TEMPLATE, poor_yaml_read, poor_yaml_write from deploy.Windows.utils import DEPLOY_TEMPLATE, poor_yaml_read, poor_yaml_write
from module.base.timer import timer from module.base.timer import timer
from module.config.server import to_package, VALID_PACKAGE, VALID_CHANNEL_PACKAGE from module.config.server import VALID_CHANNEL_PACKAGE, VALID_PACKAGE, to_package
from module.config.utils import * from module.config.utils import *
CONFIG_IMPORT = ''' CONFIG_IMPORT = '''
@ -32,6 +32,11 @@ def gui_lang_to_ingame_lang(lang: str) -> str:
return DICT_GUI_TO_INGAME.get(lang, 'en') return DICT_GUI_TO_INGAME.get(lang, 'en')
def get_generator():
from module.base.code_generator import CodeGenerator
return CodeGenerator()
class ConfigGenerator: class ConfigGenerator:
@cached_property @cached_property
def argument(self): def argument(self):
@ -47,6 +52,55 @@ class ConfigGenerator:
""" """
data = {} data = {}
raw = read_file(filepath_argument('argument')) raw = read_file(filepath_argument('argument'))
def option_add(keys, options):
options = deep_get(raw, keys=keys, default=[]) + options
deep_set(raw, keys=keys, value=options)
# Insert dungeons
from tasks.dungeon.keywords import DungeonList
option_add(
keys='Dungeon.Name.option',
options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_daily_dungeon])
# Double events
option_add(
keys='Dungeon.NameAtDoubleCalyx.option',
options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Calyx])
option_add(
keys='Dungeon.NameAtDoubleRelic.option',
options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Cavern_of_Corrosion])
# Dungeon daily
option_add(
keys='DungeonDaily.CalyxGolden.option',
options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Calyx_Golden])
option_add(
keys='DungeonDaily.CalyxCrimson.option',
options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Calyx_Crimson])
option_add(
keys='DungeonDaily.StagnantShadow.option',
options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Stagnant_Shadow])
option_add(
keys='DungeonDaily.CavernOfCorrosion.option',
options=[dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Cavern_of_Corrosion])
# Insert characters
from tasks.character.keywords import CharacterList
unsupported_characters = ["DanHengImbibitorLunae"]
characters = [character.name for character in CharacterList.instances.values()
if character.name not in unsupported_characters]
option_add(keys='DungeonSupport.Character.option', options=characters)
# Insert daily quests
from tasks.daily.keywords import DailyQuest
for quest in DailyQuest.instances.values():
quest: DailyQuest
deep_set(raw, keys=['AchievableQuest', quest.name], value={
'type': 'state',
'value': 'achievable',
'option': ['achievable', 'not_set', 'not_supported'],
'option_bold': ['achievable'],
'option_light': ['not_supported'],
})
# Load
for path, value in deep_iter(raw, depth=2): for path, value in deep_iter(raw, depth=2):
arg = { arg = {
'type': 'input', 'type': 'input',
@ -56,6 +110,9 @@ class ConfigGenerator:
if not isinstance(value, dict): if not isinstance(value, dict):
value = {'value': value} value = {'value': value}
arg['type'] = data_to_type(value, arg=path[1]) arg['type'] = data_to_type(value, arg=path[1])
if arg['type'] == 'stored':
value['value'] = {}
arg['display'] = 'hide' # Hide `stored` by default
if isinstance(value['value'], datetime): if isinstance(value['value'], datetime):
arg['type'] = 'datetime' arg['type'] = 'datetime'
arg['validate'] = 'datetime' arg['validate'] = 'datetime'
@ -63,14 +120,6 @@ class ConfigGenerator:
arg.update(value) arg.update(value)
deep_set(data, keys=path, value=arg) deep_set(data, keys=path, value=arg)
# Define storage group
# arg = {
# 'type': 'storage',
# 'value': {},
# 'valuetype': 'ignore',
# 'display': 'disabled',
# }
# deep_set(data, keys=['Storage', 'Storage'], value=arg)
return data return data
@cached_property @cached_property
@ -216,6 +265,28 @@ class ConfigGenerator:
for text in lines: for text in lines:
f.write(text + '\n') f.write(text + '\n')
@timer
def generate_stored(self):
import module.config.stored.classes as classes
gen = get_generator()
gen.add('from module.config.stored.classes import (')
with gen.tab():
for cls in sorted([name for name in dir(classes) if name.startswith('Stored')]):
gen.add(cls + ',')
gen.add(')')
gen.Empty()
gen.Empty()
gen.Empty()
gen.CommentAutoGenerage('module/config/config_updater.py')
with gen.Class('StoredGenerated'):
for path, data in deep_iter(self.args, depth=3):
cls = data.get('stored')
if cls:
gen.add(f'{path[-1]} = {cls}("{".".join(path)}")')
gen.write('module/config/stored/stored_generated.py')
@timer @timer
def generate_i18n(self, lang): def generate_i18n(self, lang):
""" """
@ -282,27 +353,44 @@ class ConfigGenerator:
if dungeon.name in dailies: if dungeon.name in dailies:
value = dungeon.__getattribute__(ingame_lang) value = dungeon.__getattribute__(ingame_lang)
deep_set(new, keys=['Dungeon', 'Name', dungeon.name], value=value) deep_set(new, keys=['Dungeon', 'Name', dungeon.name], value=value)
# Copy dungeon i18n to double events
for dungeon in deep_get(new, keys='Dungeon.NameAtDoubleCalyx').values():
if '_' in dungeon:
value = deep_get(new, keys=['Dungeon', 'Name', dungeon])
if value:
deep_set(new, keys=['Dungeon', 'NameAtDoubleCalyx', dungeon], value=value)
for dungeon in deep_get(new, keys='Dungeon.NameAtDoubleRelic').values():
if '_' in dungeon:
value = deep_get(new, keys=['Dungeon', 'Name', dungeon])
if value:
deep_set(new, keys=['Dungeon', 'NameAtDoubleRelic', dungeon], value=value)
# Copy dungeon i18n to double events
def update_dungeon_names(keys):
for dungeon in deep_get(new, keys=keys).values():
if '_' in dungeon:
value = deep_get(new, keys=['Dungeon', 'Name', dungeon])
if value:
deep_set(new, keys=f'{keys}.{dungeon}', value=value)
update_dungeon_names('Dungeon.NameAtDoubleCalyx')
update_dungeon_names('Dungeon.NameAtDoubleRelic')
update_dungeon_names('DungeonDaily.CalyxGolden')
update_dungeon_names('DungeonDaily.CalyxCrimson')
update_dungeon_names('DungeonDaily.StagnantShadow')
update_dungeon_names('DungeonDaily.CavernOfCorrosion')
# Character names
from tasks.character.keywords import CharacterList from tasks.character.keywords import CharacterList
ingame_lang = gui_lang_to_ingame_lang(lang) ingame_lang = gui_lang_to_ingame_lang(lang)
characters = deep_get(self.argument, keys='Dungeon.SupportCharacter.option') characters = deep_get(self.argument, keys='DungeonSupport.Character.option')
for character in CharacterList.instances.values(): for character in CharacterList.instances.values():
if character.name in characters: if character.name in characters:
value = character.__getattribute__(ingame_lang) value = character.__getattribute__(ingame_lang)
if "Trailblazer" in value: if "Trailblazer" in value:
continue continue
deep_set(new, keys=['Dungeon', 'SupportCharacter', character.name], value=value) deep_set(new, keys=['DungeonSupport', 'Character', character.name], value=value)
# Daily quests
from tasks.daily.keywords import DailyQuest
for quest in DailyQuest.instances.values():
value = quest.__getattribute__(ingame_lang)
deep_set(new, keys=['AchievableQuest', quest.name, 'name'], value=value)
# deep_set(new, keys=['DailyQuest', quest.name, 'help'], value='')
copy_from = 'Complete_1_Daily_Mission'
if quest.name != copy_from:
for option in deep_get(self.args, keys=['DailyQuest', 'AchievableQuest', copy_from, 'option']):
value = deep_get(new, keys=['AchievableQuest', copy_from, option])
deep_set(new, keys=['AchievableQuest', quest.name, option], value=value)
# GUI i18n # GUI i18n
for path, _ in deep_iter(self.gui, depth=2): for path, _ in deep_iter(self.gui, depth=2):
@ -371,30 +459,6 @@ class ConfigGenerator:
# update('template-docker', docker) # update('template-docker', docker)
# update('template-docker-cn', docker, cn) # update('template-docker-cn', docker, cn)
def insert_dungeon(self):
from tasks.dungeon.keywords import DungeonList
dungeons = [dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_daily_dungeon]
deep_set(self.argument, keys='Dungeon.Name.option', value=dungeons)
deep_set(self.args, keys='Dungeon.Dungeon.Name.option', value=dungeons)
from tasks.character.keywords import CharacterList
unsupported_characters = ["DanHengImbibitorLunae"]
characters = ['FirstCharacter'] + [character.name for character in CharacterList.instances.values() if
character.name not in unsupported_characters]
deep_set(self.argument, keys='Dungeon.SupportCharacter.option', value=characters)
deep_set(self.args, keys='Dungeon.Dungeon.SupportCharacter.option', value=characters)
# Double events
dungeons = deep_get(self.argument, keys='Dungeon.NameAtDoubleCalyx.option')
dungeons += [dungeon.name for dungeon in DungeonList.instances.values()
if dungeon.is_Calyx_Golden or dungeon.is_Calyx_Crimson]
deep_set(self.argument, keys='Dungeon.NameAtDoubleCalyx.option', value=dungeons)
deep_set(self.args, keys='Dungeon.Dungeon.NameAtDoubleCalyx.option', value=dungeons)
dungeons = deep_get(self.argument, keys='Dungeon.NameAtDoubleRelic.option')
dungeons += [dungeon.name for dungeon in DungeonList.instances.values() if dungeon.is_Cavern_of_Corrosion]
deep_set(self.argument, keys='Dungeon.NameAtDoubleRelic.option', value=dungeons)
deep_set(self.args, keys='Dungeon.Dungeon.NameAtDoubleRelic.option', value=dungeons)
def insert_assignment(self): def insert_assignment(self):
from tasks.assignment.keywords import AssignmentEntry from tasks.assignment.keywords import AssignmentEntry
assignments = [entry.name for entry in AssignmentEntry.instances.values()] assignments = [entry.name for entry in AssignmentEntry.instances.values()]
@ -414,13 +478,13 @@ class ConfigGenerator:
_ = self.args _ = self.args
_ = self.menu _ = self.menu
# _ = self.event # _ = self.event
self.insert_dungeon()
self.insert_assignment() self.insert_assignment()
self.insert_package() self.insert_package()
# self.insert_server() # self.insert_server()
write_file(filepath_args(), self.args) write_file(filepath_args(), self.args)
write_file(filepath_args('menu'), self.menu) write_file(filepath_args('menu'), self.menu)
self.generate_code() self.generate_code()
self.generate_stored()
for lang in LANGUAGES: for lang in LANGUAGES:
self.generate_i18n(lang) self.generate_i18n(lang)
self.generate_deploy_template() self.generate_deploy_template()
@ -429,6 +493,8 @@ class ConfigGenerator:
class ConfigUpdater: class ConfigUpdater:
# source, target, (optional)convert_func # source, target, (optional)convert_func
redirection = [ redirection = [
('Dungeon.Dungeon.Support', 'Dungeon.DungeonSupport.Use'),
('Dungeon.Dungeon.SupportCharacter', 'Dungeon.DungeonSupport.Character'),
] ]
@cached_property @cached_property
@ -449,7 +515,9 @@ class ConfigUpdater:
def deep_load(keys): def deep_load(keys):
data = deep_get(self.args, keys=keys, default={}) data = deep_get(self.args, keys=keys, default={})
value = deep_get(old, keys=keys, default=data['value']) value = deep_get(old, keys=keys, default=data['value'])
if is_template or value is None or value == '' or data['type'] == 'lock' or data.get('display') == 'hide': typ = data['type']
display = data.get('display')
if is_template or value is None or value == '' or typ == 'lock' or (display == 'hide' and typ != 'stored'):
value = data['value'] value = data['value']
value = parse_value(value, data=data) value = parse_value(value, data=data)
deep_set(new, keys=keys, value=value) deep_set(new, keys=keys, value=value)
@ -459,6 +527,7 @@ class ConfigUpdater:
if not is_template: if not is_template:
new = self.config_redirect(old, new) new = self.config_redirect(old, new)
new = self.update_state(new)
return new return new
@ -511,6 +580,53 @@ class ConfigUpdater:
return new return new
@staticmethod
def update_state(data):
def set_daily(quest, value):
if value is True:
value = 'achievable'
if value is False:
value = 'not_set'
deep_set(data, keys=['DailyQuest', 'AchievableQuest', quest], value=value)
set_daily('Complete_1_Daily_Mission', 'not_supported')
# Dungeon
dungeon = deep_get(data, keys='Dungeon.Scheduler.Enable')
set_daily('Clear_Calyx_Golden_1_times',
dungeon and deep_get(data, 'Dungeon.DungeonDaily.CalyxGolden') != 'do_not_achieve')
set_daily('Complete_Calyx_Crimson_1_time',
dungeon and deep_get(data, 'Dungeon.DungeonDaily.CalyxCrimson') != 'do_not_achieve')
set_daily('Clear_Stagnant_Shadow_1_times',
dungeon and deep_get(data, 'Dungeon.DungeonDaily.StagnantShadow') != 'do_not_achieve')
set_daily('Clear_Cavern_of_Corrosion_1_times',
dungeon and deep_get(data, 'Dungeon.DungeonDaily.CavernOfCorrosion') != 'do_not_achieve')
# Combat requirements
set_daily('In_a_single_battle_inflict_3_Weakness_Break_of_different_Types', 'not_supported')
set_daily('Inflict_Weakness_Break_5_times', 'not_supported')
set_daily('Defeat_a_total_of_20_enemies', 'not_supported')
set_daily('Enter_combat_by_attacking_enemy_Weakness_and_win_3_times', 'not_supported')
set_daily('Use_Technique_2_times', 'achievable')
# Other game systems
set_daily('Go_on_assignment_1_time', deep_get(data, 'Assignment.Scheduler.Enable'))
set_daily('Take_1_photo', 'achievable')
set_daily('Destroy_3_destructible_objects', 'not_supported')
set_daily('Complete_Forgotten_Hall_1_time', 'not_supported')
set_daily('Complete_Echo_of_War_1_times', 'not_supported')
set_daily('Complete_1_stage_in_Simulated_Universe_Any_world', 'not_supported')
set_daily('Obtain_victory_in_combat_with_support_characters_1_time',
dungeon and deep_get(data, 'Dungeon.DungeonSupport.Use') in ['when_daily', 'always_use'])
set_daily('Use_an_Ultimate_to_deal_the_final_blow_1_time', 'not_supported')
# Build
set_daily('Level_up_any_character_1_time', 'not_supported')
set_daily('Level_up_any_Light_Cone_1_time', 'not_supported')
set_daily('Level_up_any_Relic_1_time', 'not_supported')
# Items
set_daily('Salvage_any_Relic', 'achievable')
set_daily('Synthesize_Consumable_1_time', 'achievable')
set_daily('Synthesize_material_1_time', 'achievable')
set_daily('Use_Consumables_1_time', 'achievable')
return data
def read_file(self, config_name, is_template=False): def read_file(self, config_name, is_template=False):
""" """
Read and update config file. Read and update config file.

View File

@ -247,18 +247,77 @@
"4": "4", "4": "4",
"5": "5", "5": "5",
"6": "6" "6": "6"
}
},
"DungeonDaily": {
"_info": {
"name": "Daily Quest Settings",
"help": "Clear required dungeon once to achieve daily quests"
}, },
"Support": { "CalyxGolden": {
"name": "Enable buddy support", "name": "Clear Calyx Golden 1 times",
"help": "Whether to enable buddy support", "help": "",
"do_not_use": "do_not_use", "do_not_achieve": "Don't Do This Quest",
"always_use": "always_use", "Calyx_Golden_Memories": "Material: Character EXP (Bud of Memories)",
"when_daily": "when_daily" "Calyx_Golden_Aether": "Material: Light Cone EXP (Bud of Aether)",
"Calyx_Golden_Treasures": "Material: Credit (Bud of Treasures)"
}, },
"SupportCharacter": { "CalyxCrimson": {
"name": "Dungeon.SupportCharacter.name", "name": "Clear Calyx Crimson 1 times",
"help": "Dungeon.SupportCharacter.help", "help": "",
"FirstCharacter": "FirstCharacter", "do_not_achieve": "Don't Do This Quest",
"Calyx_Crimson_Destruction": "Trace: Destruction (Bud of Destruction)",
"Calyx_Crimson_Preservation": "Trace: Preservation (Bud of Preservation)",
"Calyx_Crimson_Hunt": "Trace: Hunt (Bud of Hunt)",
"Calyx_Crimson_Abundance": "Trace: Abundance (Bud of Abundance)",
"Calyx_Crimson_Erudition": "Trace: Erudition (Bud of Erudition)",
"Calyx_Crimson_Harmony": "Trace: Harmony (Bud of Harmony)",
"Calyx_Crimson_Nihility": "Trace: Nihility (Bud of Nihility)"
},
"StagnantShadow": {
"name": "Clear Stagnant Shadow 1 times",
"help": "",
"do_not_achieve": "Don't Do This Quest",
"Stagnant_Shadow_Quanta": "Ascension: Quantum (Shape of Quanta)",
"Stagnant_Shadow_Gust": "Ascension: Wind (Shape of Gust)",
"Stagnant_Shadow_Fulmination": "Ascension: Lighting (Shape of Fulmination)",
"Stagnant_Shadow_Blaze": "Ascension: Fire (Shape of Blaze)",
"Stagnant_Shadow_Spike": "Ascension: Physical (Shape of Spike)",
"Stagnant_Shadow_Rime": "Ascension: Ice (Shape of Rime)",
"Stagnant_Shadow_Mirage": "Ascension: Imaginary (Shape of Mirage)",
"Stagnant_Shadow_Icicle": "Ascension: Ice (Shape of Icicle)",
"Stagnant_Shadow_Doom": "Ascension: Lighting (Shape of Doom)",
"Stagnant_Shadow_Celestial": "Ascension: Wind (Shape of Celestial)"
},
"CavernOfCorrosion": {
"name": "Clear Cavern of Corrosion 1 times",
"help": "",
"do_not_achieve": "Don't Do This Quest",
"Cavern_of_Corrosion_Path_of_Gelid_Wind": "Relics: Ice Set & Wind Set (Path of Gelid Wind)",
"Cavern_of_Corrosion_Path_of_Jabbing_Punch": "Relics: Physical Set & Break Effect Set (Path of Jabbing Punch)",
"Cavern_of_Corrosion_Path_of_Drifting": "Relics: Healing Set & Musketeer Set (Path of Drifting)",
"Cavern_of_Corrosion_Path_of_Providence": "Relics: Guard Set & Quantum Set (Path of Providence)",
"Cavern_of_Corrosion_Path_of_Holy_Hymn": "Relics: DEF Set & Lighting Set (Path of Holy Hymn)",
"Cavern_of_Corrosion_Path_of_Conflagration": "Relics: Fire Set & Imaginary Set (Path of Conflagration)",
"Cavern_of_Corrosion_Path_of_Elixir_Seekers": "Relics: HP Set & SPD Set (Path of Elixir Seekers)"
}
},
"DungeonSupport": {
"_info": {
"name": "Support Settings",
"help": ""
},
"Use": {
"name": "Use Friend Support",
"help": "",
"always_use": "Always Use",
"when_daily": "Use Only When Required by Dailies",
"do_not_use": "Don't Use"
},
"Character": {
"name": "Support Character",
"help": "Select a friend support character, if not found, select the default (first) role",
"FirstCharacter": "First Character",
"Arlan": "Arlan", "Arlan": "Arlan",
"Asta": "Asta", "Asta": "Asta",
"Bailu": "Bailu", "Bailu": "Bailu",
@ -284,13 +343,218 @@
"SilverWolf": "Silver Wolf", "SilverWolf": "Silver Wolf",
"Sushang": "Sushang", "Sushang": "Sushang",
"Tingyun": "Tingyun", "Tingyun": "Tingyun",
"TrailblazerDestruction": "TrailblazerDestruction", "TrailblazerDestruction": "Trailblazer Destruction",
"TrailblazerPreservation": "TrailblazerPreservation", "TrailblazerPreservation": "Trailblazer Preservation",
"Welt": "Welt", "Welt": "Welt",
"Yanqing": "Yanqing", "Yanqing": "Yanqing",
"Yukong": "Yukong" "Yukong": "Yukong"
} }
}, },
"DungeonStorage": {
"_info": {
"name": "DungeonStorage._info.name",
"help": "DungeonStorage._info.help"
},
"DungeonDouble": {
"name": "DungeonStorage.DungeonDouble.name",
"help": "DungeonStorage.DungeonDouble.help"
}
},
"AchievableQuest": {
"_info": {
"name": "Achievable Quests",
"help": "When the task status is \"Not Set\", you need to configure the SRC as required to achieve the quest\nNote: Please keep more tasks in \"Achievable\" status, otherwise SRC may not be able to grind 500 activity"
},
"Complete_1_Daily_Mission": {
"name": "Complete 1 Daily Mission",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Clear_Calyx_Golden_1_times": {
"name": "Clear Calyx (Golden) 1 time(s)",
"help": "Need to configure and enable the \"Dungeon\" task",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Complete_Calyx_Crimson_1_time": {
"name": "Complete Calyx (Crimson) 1 time",
"help": "Need to configure and enable the \"Dungeon\" task",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Clear_Stagnant_Shadow_1_times": {
"name": "Clear Stagnant Shadow 1 time(s)",
"help": "Need to configure and enable the \"Dungeon\" task",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Clear_Cavern_of_Corrosion_1_times": {
"name": "Clear Cavern of Corrosion 1 time(s)",
"help": "Need to configure and enable the \"Dungeon\" task",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": {
"name": "In a single battle, inflict 3 Weakness Break of different Types",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Inflict_Weakness_Break_5_times": {
"name": "Inflict Weakness Break 5 times",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Defeat_a_total_of_20_enemies": {
"name": "Defeat a total of 20 enemies",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Enter_combat_by_attacking_enemy_Weakness_and_win_3_times": {
"name": "Enter combat by attacking enemy's Weakness and win 3 times",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Use_Technique_2_times": {
"name": "Use Technique 2 times",
"help": "Achievable by default, will go to the abyssal 1 and use technique twice",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Go_on_assignment_1_time": {
"name": "Go on assignment 1 time",
"help": "Need to configure and enable the \"Assignment\" task",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Take_1_photo": {
"name": "Take 1 photo",
"help": "Achievable by default",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Destroy_3_destructible_objects": {
"name": "Destroy 3 destructible objects",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Complete_Forgotten_Hall_1_time": {
"name": "Complete Forgotten Hall 1 time",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Complete_Echo_of_War_1_times": {
"name": "Complete Echo of War 1 time(s)",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Complete_1_stage_in_Simulated_Universe_Any_world": {
"name": "Complete 1 stage in Simulated Universe (Any world)",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Obtain_victory_in_combat_with_support_characters_1_time": {
"name": "Obtain victory in combat with support characters 1 time",
"help": "Need to configure and enable the \"Dungeon\" task, configure support settings also",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Use_an_Ultimate_to_deal_the_final_blow_1_time": {
"name": "Use an Ultimate to deal the final blow 1 time",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Level_up_any_character_1_time": {
"name": "Level up any character 1 time",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Level_up_any_Light_Cone_1_time": {
"name": "Level up any Light Cone 1 time",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Level_up_any_Relic_1_time": {
"name": "Level up any Relic 1 time",
"help": "",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Salvage_any_Relic": {
"name": "Salvage any Relic",
"help": "Achievable by default, will salvage the first one in reverse order of rarity",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Synthesize_Consumable_1_time": {
"name": "Synthesize Consumable 1 time",
"help": "Achievable by default, will synthesize low-rarity snacks",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Synthesize_material_1_time": {
"name": "Synthesize material 1 time",
"help": "Achievable by default, will synthesize low-rarity material",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
},
"Use_Consumables_1_time": {
"name": "Use Consumables 1 time",
"help": "Achievable by default, will use gear. If there is no material, synthesized before use",
"achievable": "Achievable",
"not_set": "Not Set",
"not_supported": "Not Supported Yet"
}
},
"DailyStorage": {
"_info": {
"name": "DailyStorage._info.name",
"help": "DailyStorage._info.help"
},
"DailyActivity": {
"name": "DailyStorage.DailyActivity.name",
"help": "DailyStorage.DailyActivity.help"
},
"DailyQuest": {
"name": "DailyStorage.DailyQuest.name",
"help": "DailyStorage.DailyQuest.help"
}
},
"Assignment": { "Assignment": {
"_info": { "_info": {
"name": "Assignment Settings", "name": "Assignment Settings",

View File

@ -247,17 +247,76 @@
"4": "4", "4": "4",
"5": "5", "5": "5",
"6": "6" "6": "6"
}
},
"DungeonDaily": {
"_info": {
"name": "DungeonDaily._info.name",
"help": "DungeonDaily._info.help"
}, },
"Support": { "CalyxGolden": {
"name": "Dungeon.Support.name", "name": "DungeonDaily.CalyxGolden.name",
"help": "Dungeon.Support.help", "help": "DungeonDaily.CalyxGolden.help",
"do_not_use": "do_not_use", "do_not_achieve": "do_not_achieve",
"Calyx_Golden_Memories": "疑似花萼(金)・回憶の蕾",
"Calyx_Golden_Aether": "疑似花萼(金)・エーテルの蕾",
"Calyx_Golden_Treasures": "疑似花萼(金)・秘蔵の蕾"
},
"CalyxCrimson": {
"name": "DungeonDaily.CalyxCrimson.name",
"help": "DungeonDaily.CalyxCrimson.help",
"do_not_achieve": "do_not_achieve",
"Calyx_Crimson_Destruction": "疑似花萼(赤)・壊滅の蕾",
"Calyx_Crimson_Preservation": "疑似花萼(赤)・存護の蕾",
"Calyx_Crimson_Hunt": "疑似花萼(赤)・巡狩の蕾",
"Calyx_Crimson_Abundance": "疑似花萼(赤)・豊穣の蕾",
"Calyx_Crimson_Erudition": "疑似花萼(赤)・知恵の蕾",
"Calyx_Crimson_Harmony": "疑似花萼(赤)・調和の蕾",
"Calyx_Crimson_Nihility": "疑似花萼(赤)・虚無の蕾"
},
"StagnantShadow": {
"name": "DungeonDaily.StagnantShadow.name",
"help": "DungeonDaily.StagnantShadow.help",
"do_not_achieve": "do_not_achieve",
"Stagnant_Shadow_Quanta": "凝結虚影・虚海の形",
"Stagnant_Shadow_Gust": "凝結虚影・薫風の形",
"Stagnant_Shadow_Fulmination": "凝結虚影・鳴雷の形",
"Stagnant_Shadow_Blaze": "凝結虚影・炎華の形",
"Stagnant_Shadow_Spike": "凝結虚影・切先の形",
"Stagnant_Shadow_Rime": "凝結虚影・霜晶の形",
"Stagnant_Shadow_Mirage": "凝結虚影・幻光の形",
"Stagnant_Shadow_Icicle": "凝結虚影・氷柱の形",
"Stagnant_Shadow_Doom": "凝結虚影・震厄の形",
"Stagnant_Shadow_Celestial": "凝結虚影・天人の形"
},
"CavernOfCorrosion": {
"name": "DungeonDaily.CavernOfCorrosion.name",
"help": "DungeonDaily.CavernOfCorrosion.help",
"do_not_achieve": "do_not_achieve",
"Cavern_of_Corrosion_Path_of_Gelid_Wind": "侵蝕トンネル・霜風の路",
"Cavern_of_Corrosion_Path_of_Jabbing_Punch": "侵蝕トンネル・迅拳の路",
"Cavern_of_Corrosion_Path_of_Drifting": "侵蝕トンネル・漂泊の路",
"Cavern_of_Corrosion_Path_of_Providence": "侵蝕トンネル・睿治の路",
"Cavern_of_Corrosion_Path_of_Holy_Hymn": "侵蝕トンネル・聖頌の路",
"Cavern_of_Corrosion_Path_of_Conflagration": "侵蝕トンネル・野焔の路",
"Cavern_of_Corrosion_Path_of_Elixir_Seekers": "侵蝕トンネル・薬使の路"
}
},
"DungeonSupport": {
"_info": {
"name": "DungeonSupport._info.name",
"help": "DungeonSupport._info.help"
},
"Use": {
"name": "DungeonSupport.Use.name",
"help": "DungeonSupport.Use.help",
"always_use": "always_use", "always_use": "always_use",
"when_daily": "when_daily" "when_daily": "when_daily",
"do_not_use": "do_not_use"
}, },
"SupportCharacter": { "Character": {
"name": "Dungeon.SupportCharacter.name", "name": "DungeonSupport.Character.name",
"help": "Dungeon.SupportCharacter.help", "help": "DungeonSupport.Character.help",
"FirstCharacter": "FirstCharacter", "FirstCharacter": "FirstCharacter",
"Arlan": "アーラン", "Arlan": "アーラン",
"Asta": "アスター", "Asta": "アスター",
@ -291,6 +350,211 @@
"Yukong": "御空" "Yukong": "御空"
} }
}, },
"DungeonStorage": {
"_info": {
"name": "DungeonStorage._info.name",
"help": "DungeonStorage._info.help"
},
"DungeonDouble": {
"name": "DungeonStorage.DungeonDouble.name",
"help": "DungeonStorage.DungeonDouble.help"
}
},
"AchievableQuest": {
"_info": {
"name": "AchievableQuest._info.name",
"help": "AchievableQuest._info.help"
},
"Complete_1_Daily_Mission": {
"name": "デイリークエストを1回クリアする",
"help": "AchievableQuest.Complete_1_Daily_Mission.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Clear_Calyx_Golden_1_times": {
"name": "「疑似花萼」を1回クリアする",
"help": "AchievableQuest.Clear_Calyx_Golden_1_times.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Complete_Calyx_Crimson_1_time": {
"name": "「疑似花萼」を1回クリアする",
"help": "AchievableQuest.Complete_Calyx_Crimson_1_time.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Clear_Stagnant_Shadow_1_times": {
"name": "「凝結虚影」を1回クリアする",
"help": "AchievableQuest.Clear_Stagnant_Shadow_1_times.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Clear_Cavern_of_Corrosion_1_times": {
"name": "「侵蝕トンネル」を1回クリアする",
"help": "AchievableQuest.Clear_Cavern_of_Corrosion_1_times.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": {
"name": "一度の戦闘で、異なる3種の属性の弱点撃破を発動する",
"help": "AchievableQuest.In_a_single_battle_inflict_3_Weakness_Break_of_different_Types.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Inflict_Weakness_Break_5_times": {
"name": "累計で弱点撃破効果を5回発動する",
"help": "AchievableQuest.Inflict_Weakness_Break_5_times.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Defeat_a_total_of_20_enemies": {
"name": "敵を累計で20体倒す",
"help": "AchievableQuest.Defeat_a_total_of_20_enemies.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Enter_combat_by_attacking_enemy_Weakness_and_win_3_times": {
"name": "弱点を攻撃して戦闘に入り、3回勝利する",
"help": "AchievableQuest.Enter_combat_by_attacking_enemy_Weakness_and_win_3_times.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Use_Technique_2_times": {
"name": "秘技を累計2回発動する",
"help": "AchievableQuest.Use_Technique_2_times.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Go_on_assignment_1_time": {
"name": "依頼に1回派遣する",
"help": "AchievableQuest.Go_on_assignment_1_time.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Take_1_photo": {
"name": "1回撮影する",
"help": "AchievableQuest.Take_1_photo.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Destroy_3_destructible_objects": {
"name": "破壊できるオブジェクトを累計で3つ破壊する",
"help": "AchievableQuest.Destroy_3_destructible_objects.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Complete_Forgotten_Hall_1_time": {
"name": "「忘却の庭」を1回クリアする",
"help": "AchievableQuest.Complete_Forgotten_Hall_1_time.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Complete_Echo_of_War_1_times": {
"name": "「歴戦余韻」を1回クリアする",
"help": "AchievableQuest.Complete_Echo_of_War_1_times.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Complete_1_stage_in_Simulated_Universe_Any_world": {
"name": "「模擬宇宙」のエリアを1つクリアする任意の世界",
"help": "AchievableQuest.Complete_1_stage_in_Simulated_Universe_Any_world.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Obtain_victory_in_combat_with_support_characters_1_time": {
"name": "サポートキャラを使い、戦闘に1回勝利する",
"help": "AchievableQuest.Obtain_victory_in_combat_with_support_characters_1_time.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Use_an_Ultimate_to_deal_the_final_blow_1_time": {
"name": "必殺技で最後の一撃を1回与える",
"help": "AchievableQuest.Use_an_Ultimate_to_deal_the_final_blow_1_time.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Level_up_any_character_1_time": {
"name": "任意のキャラを1回レベルアップする",
"help": "AchievableQuest.Level_up_any_character_1_time.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Level_up_any_Light_Cone_1_time": {
"name": "任意の光円錐を1回レベルアップする",
"help": "AchievableQuest.Level_up_any_Light_Cone_1_time.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Level_up_any_Relic_1_time": {
"name": "任意の遺物を1回レベルアップする",
"help": "AchievableQuest.Level_up_any_Relic_1_time.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Salvage_any_Relic": {
"name": "任意の遺物1つを分解する",
"help": "AchievableQuest.Salvage_any_Relic.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Synthesize_Consumable_1_time": {
"name": "消耗品を1回合成する",
"help": "AchievableQuest.Synthesize_Consumable_1_time.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Synthesize_material_1_time": {
"name": "素材を1回合成する",
"help": "AchievableQuest.Synthesize_material_1_time.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
},
"Use_Consumables_1_time": {
"name": "消耗品を1個使う",
"help": "AchievableQuest.Use_Consumables_1_time.help",
"achievable": "achievable",
"not_set": "not_set",
"not_supported": "not_supported"
}
},
"DailyStorage": {
"_info": {
"name": "DailyStorage._info.name",
"help": "DailyStorage._info.help"
},
"DailyActivity": {
"name": "DailyStorage.DailyActivity.name",
"help": "DailyStorage.DailyActivity.help"
},
"DailyQuest": {
"name": "DailyStorage.DailyQuest.name",
"help": "DailyStorage.DailyQuest.help"
}
},
"Assignment": { "Assignment": {
"_info": { "_info": {
"name": "依頼設定", "name": "依頼設定",

View File

@ -31,7 +31,7 @@
"help": "" "help": ""
}, },
"Assignment": { "Assignment": {
"name": "委托设置", "name": "委托",
"help": "" "help": ""
} }
}, },
@ -247,15 +247,74 @@
"4": "4", "4": "4",
"5": "5", "5": "5",
"6": "6" "6": "6"
}
},
"DungeonDaily": {
"_info": {
"name": "每日任务设置",
"help": "打一次特定的本,以满足每日任务的要求"
}, },
"Support": { "CalyxGolden": {
"name": "启用好友支援", "name": "完成1次拟造花萼",
"help": "是否启用好友支援", "help": "",
"do_not_use": "否", "do_not_achieve": "不完成这个任务",
"always_use": "是", "Calyx_Golden_Memories": "材料:角色经验(回忆之蕾•拟造花萼金)",
"when_daily": "仅当每日任务需要时" "Calyx_Golden_Aether": "材料:武器经验(以太之蕾•拟造花萼金)",
"Calyx_Golden_Treasures": "材料:信用点(藏珍之蕾•拟造花萼金)"
}, },
"SupportCharacter": { "CalyxCrimson": {
"name": "完成1次拟造花萼",
"help": "",
"do_not_achieve": "不完成这个任务",
"Calyx_Crimson_Destruction": "行迹材料:毁灭(毁灭之蕾•拟造花萼赤)",
"Calyx_Crimson_Preservation": "行迹材料:存护(存护之蕾•拟造花萼赤)",
"Calyx_Crimson_Hunt": "行迹材料:巡猎(存护之蕾•拟造花萼赤)",
"Calyx_Crimson_Abundance": "行迹材料:丰饶(丰饶之蕾•拟造花萼赤)",
"Calyx_Crimson_Erudition": "行迹材料:智识(智识之蕾•拟造花萼赤)",
"Calyx_Crimson_Harmony": "行迹材料:同谐(同谐之蕾•拟造花萼赤)",
"Calyx_Crimson_Nihility": "行迹材料:虚无(虚无之蕾•拟造花萼赤)"
},
"StagnantShadow": {
"name": "完成1次凝滞虚影",
"help": "",
"do_not_achieve": "不完成这个任务",
"Stagnant_Shadow_Quanta": "角色晋阶材料:量子(空海之形•凝滞虚影)",
"Stagnant_Shadow_Gust": "角色晋阶材料:风(巽风之形•凝滞虚影)",
"Stagnant_Shadow_Fulmination": "角色晋阶材料:雷(鸣雷之形•凝滞虚影)",
"Stagnant_Shadow_Blaze": "角色晋阶材料:火(炎华之形•凝滞虚影)",
"Stagnant_Shadow_Spike": "角色晋阶材料:物理(锋芒之形•凝滞虚影)",
"Stagnant_Shadow_Rime": "角色晋阶材料:冰(霜晶之形•凝滞虚影)",
"Stagnant_Shadow_Mirage": "角色晋阶材料:虚数(幻光之形•凝滞虚影)",
"Stagnant_Shadow_Icicle": "角色晋阶材料:冰(冰棱之形•凝滞虚影)",
"Stagnant_Shadow_Doom": "角色晋阶材料:雷(震厄之形•凝滞虚影)",
"Stagnant_Shadow_Celestial": "角色晋阶材料:风(天人之形•凝滞虚影)"
},
"CavernOfCorrosion": {
"name": "完成1次侵蚀隧洞",
"help": "",
"do_not_achieve": "不完成这个任务",
"Cavern_of_Corrosion_Path_of_Gelid_Wind": "遗器:冰套+风套(霜风之径•侵蚀隧洞)",
"Cavern_of_Corrosion_Path_of_Jabbing_Punch": "遗器:物理套+击破套(迅拳之径•侵蚀隧洞)",
"Cavern_of_Corrosion_Path_of_Drifting": "遗器:治疗套+快枪手(漂泊之径•侵蚀隧洞)",
"Cavern_of_Corrosion_Path_of_Providence": "遗器:铁卫套+量子套(睿治之径•侵蚀隧洞)",
"Cavern_of_Corrosion_Path_of_Holy_Hymn": "遗器:防御套+雷套(圣颂之径•侵蚀隧洞)",
"Cavern_of_Corrosion_Path_of_Conflagration": "遗器:火套+虚数套(野焰之径•侵蚀隧洞)",
"Cavern_of_Corrosion_Path_of_Elixir_Seekers": "遗器:生命套+速度套(药使之径•侵蚀隧洞)"
}
},
"DungeonSupport": {
"_info": {
"name": "支援设置",
"help": ""
},
"Use": {
"name": "使用好友支援",
"help": "",
"always_use": "总是使用",
"when_daily": "仅当每日任务需要时使用",
"do_not_use": "不使用"
},
"Character": {
"name": "好友支援角色", "name": "好友支援角色",
"help": "选择好友支援角色,未找到则选择默认(第一个)角色", "help": "选择好友支援角色,未找到则选择默认(第一个)角色",
"FirstCharacter": "支援列表第一个角色", "FirstCharacter": "支援列表第一个角色",
@ -291,6 +350,211 @@
"Yukong": "驭空" "Yukong": "驭空"
} }
}, },
"DungeonStorage": {
"_info": {
"name": "DungeonStorage._info.name",
"help": "DungeonStorage._info.help"
},
"DungeonDouble": {
"name": "DungeonStorage.DungeonDouble.name",
"help": "DungeonStorage.DungeonDouble.help"
}
},
"AchievableQuest": {
"_info": {
"name": "可完成的任务",
"help": "任务状态为 \"未设置\" 时需要按照要求设置SRC才能启用任务\n注意请让更多的任务处于 \"可完成\" 状态否则SRC可能无法完成500点的活跃度要求"
},
"Complete_1_Daily_Mission": {
"name": "完成1个日常任务",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Clear_Calyx_Golden_1_times": {
"name": "完成1次「拟造花萼」",
"help": "需要设置并启用\"每日副本\"任务",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Complete_Calyx_Crimson_1_time": {
"name": "完成1次「拟造花萼」",
"help": "需要设置并启用\"每日副本\"任务",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Clear_Stagnant_Shadow_1_times": {
"name": "完成1次「凝滞虚影」",
"help": "需要设置并启用\"每日副本\"任务",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Clear_Cavern_of_Corrosion_1_times": {
"name": "完成1次「侵蚀隧洞」",
"help": "需要设置并启用\"每日副本\"任务",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": {
"name": "单场战斗中触发3种不同属性的弱点击破",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Inflict_Weakness_Break_5_times": {
"name": "累计触发弱点击破效果5次",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Defeat_a_total_of_20_enemies": {
"name": "累计消灭20个敌人",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Enter_combat_by_attacking_enemy_Weakness_and_win_3_times": {
"name": "利用弱点进入战斗并获胜3次",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Use_Technique_2_times": {
"name": "累计施放2次秘技",
"help": "默认可完成将前往深渊一施放2次秘技",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Go_on_assignment_1_time": {
"name": "派遣1次委托",
"help": "需要设置并启用\"委托\"任务",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Take_1_photo": {
"name": "拍照1次",
"help": "默认可完成",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Destroy_3_destructible_objects": {
"name": "累计击碎3个可破坏物",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Complete_Forgotten_Hall_1_time": {
"name": "完成1次「忘却之庭」",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Complete_Echo_of_War_1_times": {
"name": "完成1次「历战余响」",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Complete_1_stage_in_Simulated_Universe_Any_world": {
"name": "通关「模拟宇宙」任意世界的1个区域",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Obtain_victory_in_combat_with_support_characters_1_time": {
"name": "使用支援角色并获得战斗胜利1次",
"help": "需要设置并启用\"每日副本\",且设置好友支援",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Use_an_Ultimate_to_deal_the_final_blow_1_time": {
"name": "施放终结技造成制胜一击1次",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Level_up_any_character_1_time": {
"name": "将任意角色等级提升1次",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Level_up_any_Light_Cone_1_time": {
"name": "将任意光锥等级提升1次",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Level_up_any_Relic_1_time": {
"name": "将任意遗器等级提升1次",
"help": "",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Salvage_any_Relic": {
"name": "分解任意1件遗器",
"help": "默认可完成,将分解遗器稀有度倒序的第一个",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Synthesize_Consumable_1_time": {
"name": "合成1次消耗品",
"help": "默认可完成,将合成最低级零食",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Synthesize_material_1_time": {
"name": "合成1次材料",
"help": "默认可完成,将合成最低级材料",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
},
"Use_Consumables_1_time": {
"name": "使用1件消耗品",
"help": "默认可完成,将使用护具,无材料时先合成再使用",
"achievable": "可完成",
"not_set": "未设置",
"not_supported": "暂未支持"
}
},
"DailyStorage": {
"_info": {
"name": "DailyStorage._info.name",
"help": "DailyStorage._info.help"
},
"DailyActivity": {
"name": "DailyStorage.DailyActivity.name",
"help": "DailyStorage.DailyActivity.help"
},
"DailyQuest": {
"name": "DailyStorage.DailyQuest.name",
"help": "DailyStorage.DailyQuest.help"
}
},
"Assignment": { "Assignment": {
"_info": { "_info": {
"name": "委托设置", "name": "委托设置",

View File

@ -31,7 +31,7 @@
"help": "" "help": ""
}, },
"Assignment": { "Assignment": {
"name": "委託設置", "name": "委託",
"help": "" "help": ""
} }
}, },
@ -247,18 +247,77 @@
"4": "4", "4": "4",
"5": "5", "5": "5",
"6": "6" "6": "6"
}
},
"DungeonDaily": {
"_info": {
"name": "每日任務設定",
"help": "打一次特定的本,以滿足每日任務的要求"
}, },
"Support": { "CalyxGolden": {
"name": "Dungeon.Support.name", "name": "完成1次擬造花萼",
"help": "Dungeon.Support.help", "help": "",
"do_not_use": "do_not_use", "do_not_achieve": "不完成這個任務",
"always_use": "always_use", "Calyx_Golden_Memories": "材料:角色經驗(回憶之蕾•擬造花萼金)",
"when_daily": "when_daily" "Calyx_Golden_Aether": "材料:武器經驗(乙太之蕾•擬造花萼金)",
"Calyx_Golden_Treasures": "材料:信用點(藏珍之蕾•擬造花萼金)"
}, },
"SupportCharacter": { "CalyxCrimson": {
"name": "Dungeon.SupportCharacter.name", "name": "完成1次擬造花萼",
"help": "Dungeon.SupportCharacter.help", "help": "",
"FirstCharacter": "FirstCharacter", "do_not_achieve": "不完成這個任務",
"Calyx_Crimson_Destruction": "行跡材料:毀滅(毀滅之蕾•擬造花萼赤)",
"Calyx_Crimson_Preservation": "行跡材料:存護(存護之蕾•擬造花萼赤)",
"Calyx_Crimson_Hunt": "行跡材料:巡獵(存護之蕾•擬造花萼赤)",
"Calyx_Crimson_Abundance": "行跡材料:豐饒(豐饒之蕾•擬造花萼赤)",
"Calyx_Crimson_Erudition": "行跡材料:智識(智識之蕾•擬造花萼赤)",
"Calyx_Crimson_Harmony": "行跡材料:同諧(同諧之蕾•擬造花萼赤)",
"Calyx_Crimson_Nihility": "行跡材料:虛無(虛無之蕾•擬造花萼赤)"
},
"StagnantShadow": {
"name": "完成1次凝滯虛影",
"help": "",
"do_not_achieve": "不完成這個任務",
"Stagnant_Shadow_Quanta": "角色晉階材料:量子(空海之形•凝滯虛影)",
"Stagnant_Shadow_Gust": "角色晉階材料:風(巽風之形•凝滯虛影)",
"Stagnant_Shadow_Fulmination": "角色晉階材料:雷(鳴雷之形•凝滯虛影)",
"Stagnant_Shadow_Blaze": "角色晉階材料:火(炎華之形•凝滯虛影)",
"Stagnant_Shadow_Spike": "角色晉階材料:物理(鋒芒之形•凝滯虛影)",
"Stagnant_Shadow_Rime": "角色晉階材料:冰(霜晶之形•凝滯虛影)",
"Stagnant_Shadow_Mirage": "角色晉階材料:虛數(幻光之形•凝滯虛影)",
"Stagnant_Shadow_Icicle": "角色晉階材料:冰(冰稜之形•凝滯虛影)",
"Stagnant_Shadow_Doom": "角色晉階材料:雷(震厄之形•凝滯虛影)",
"Stagnant_Shadow_Celestial": "角色晉階材料:風(天人之形•凝滯虛影)"
},
"CavernOfCorrosion": {
"name": "完成1次侵蝕隧洞",
"help": "",
"do_not_achieve": "不完成這個任務",
"Cavern_of_Corrosion_Path_of_Gelid_Wind": "遺器:冰套+風套(霜風之徑•侵蝕隧洞)",
"Cavern_of_Corrosion_Path_of_Jabbing_Punch": "遺器:物理套+擊破套(迅拳之徑•侵蝕隧洞)",
"Cavern_of_Corrosion_Path_of_Drifting": "遺器:治療套+快槍手(漂泊之徑•侵蝕隧洞)",
"Cavern_of_Corrosion_Path_of_Providence": "遺器:鐵衛套+量子套(睿治之徑•侵蝕隧洞)",
"Cavern_of_Corrosion_Path_of_Holy_Hymn": "遺器:防禦套+雷套(聖頌之徑•侵蝕隧洞)",
"Cavern_of_Corrosion_Path_of_Conflagration": "遺器:火套+虛數套(野焰之徑•侵蝕隧洞)",
"Cavern_of_Corrosion_Path_of_Elixir_Seekers": "遺器:生命套+速度套(藥使之徑•侵蝕隧洞)"
}
},
"DungeonSupport": {
"_info": {
"name": "支援設定",
"help": ""
},
"Use": {
"name": "使用好友支援",
"help": "",
"always_use": "總是使用",
"when_daily": "僅當每日任務需要時使用",
"do_not_use": "不使用"
},
"Character": {
"name": "好友支援角色",
"help": "選擇好友支援角色,未找到則選擇默認(第一個)角色",
"FirstCharacter": "支援列表第一個角色",
"Arlan": "阿蘭", "Arlan": "阿蘭",
"Asta": "艾絲妲", "Asta": "艾絲妲",
"Bailu": "白露", "Bailu": "白露",
@ -284,16 +343,221 @@
"SilverWolf": "銀狼", "SilverWolf": "銀狼",
"Sushang": "素裳", "Sushang": "素裳",
"Tingyun": "停雲", "Tingyun": "停雲",
"TrailblazerDestruction": "TrailblazerDestruction", "TrailblazerDestruction": "開拓者•毀滅",
"TrailblazerPreservation": "TrailblazerPreservation", "TrailblazerPreservation": "開拓者•存護",
"Welt": "瓦爾特", "Welt": "瓦爾特",
"Yanqing": "彥卿", "Yanqing": "彥卿",
"Yukong": "馭空" "Yukong": "馭空"
} }
}, },
"DungeonStorage": {
"_info": {
"name": "DungeonStorage._info.name",
"help": "DungeonStorage._info.help"
},
"DungeonDouble": {
"name": "DungeonStorage.DungeonDouble.name",
"help": "DungeonStorage.DungeonDouble.help"
}
},
"AchievableQuest": {
"_info": {
"name": "可完成的任務",
"help": "任務狀態為 \"未設定\" 時需要按照要求設定SRC才能啟用任務\n注意請讓更多的任務處於 \"可完成\" 狀態否則SRC可能無法完成500點的活躍度要求"
},
"Complete_1_Daily_Mission": {
"name": "完成1個每日任務",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Clear_Calyx_Golden_1_times": {
"name": "完成1次「擬造花萼」",
"help": "需要設定並啟用\"每日副本\"任務",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Complete_Calyx_Crimson_1_time": {
"name": "完成1次「擬造花萼」",
"help": "需要設定並啟用\"每日副本\"任務",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Clear_Stagnant_Shadow_1_times": {
"name": "完成1次「凝滯虛影」",
"help": "需要設定並啟用\"每日副本\"任務",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Clear_Cavern_of_Corrosion_1_times": {
"name": "完成1次「侵蝕隧洞」",
"help": "需要設定並啟用\"每日副本\"任務",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"In_a_single_battle_inflict_3_Weakness_Break_of_different_Types": {
"name": "單場戰鬥中觸發3種不同屬性的弱點擊破",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Inflict_Weakness_Break_5_times": {
"name": "累積觸發弱點擊破效果5次",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Defeat_a_total_of_20_enemies": {
"name": "累積消滅20個敵人",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Enter_combat_by_attacking_enemy_Weakness_and_win_3_times": {
"name": "利用弱點進入戰鬥並獲勝3次",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Use_Technique_2_times": {
"name": "累積施放2次秘技",
"help": "默認可完成將前往深淵一施放2次秘技",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Go_on_assignment_1_time": {
"name": "派遣1次委託",
"help": "需要設定並啟用\"委託\"任務",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Take_1_photo": {
"name": "拍照1次",
"help": "默认可完成",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Destroy_3_destructible_objects": {
"name": "累積擊碎3個可破壞物",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Complete_Forgotten_Hall_1_time": {
"name": "完成1次「忘卻之庭」",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Complete_Echo_of_War_1_times": {
"name": "完成1次「歷戰餘響」",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Complete_1_stage_in_Simulated_Universe_Any_world": {
"name": "完成「模擬宇宙」任意世界的1個區域",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Obtain_victory_in_combat_with_support_characters_1_time": {
"name": "使用支援角色並獲得戰鬥勝利1次",
"help": "需要設定並啟用\"每日副本\",且設並好友支援",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Use_an_Ultimate_to_deal_the_final_blow_1_time": {
"name": "施放終結技造成制勝一擊1次",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Level_up_any_character_1_time": {
"name": "將任意角色等級提升1次",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Level_up_any_Light_Cone_1_time": {
"name": "將任意光錐等級提升1次",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Level_up_any_Relic_1_time": {
"name": "將任意遺器等級提升1次",
"help": "",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Salvage_any_Relic": {
"name": "分解任意1件遺器",
"help": "默認可完成,將分解遺器稀有度倒序的第一個",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Synthesize_Consumable_1_time": {
"name": "合成1次消耗品",
"help": "默認可完成,將合成最低級零食",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Synthesize_material_1_time": {
"name": "合成1次素材",
"help": "默認可完成,將合成最低級素材",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
},
"Use_Consumables_1_time": {
"name": "使用1件消耗品",
"help": "默認可完成,將使用護具,無材料時先合成再使用",
"achievable": "可完成",
"not_set": "未設定",
"not_supported": "暫未支援"
}
},
"DailyStorage": {
"_info": {
"name": "DailyStorage._info.name",
"help": "DailyStorage._info.help"
},
"DailyActivity": {
"name": "DailyStorage.DailyActivity.name",
"help": "DailyStorage.DailyActivity.help"
},
"DailyQuest": {
"name": "DailyStorage.DailyQuest.name",
"help": "DailyStorage.DailyQuest.help"
}
},
"Assignment": { "Assignment": {
"_info": { "_info": {
"name": "委託設置", "name": "委託設",
"help": "領取獎勵並派遣,優先處理指定委託\n若處理指定委託之後未達到上限則按經驗材料 → 角色專屬素材 → 合成材料的順序來派遣委託" "help": "領取獎勵並派遣,優先處理指定委託\n若處理指定委託之後未達到上限則按經驗材料 → 角色專屬素材 → 合成材料的順序來派遣委託"
}, },
"Duration": { "Duration": {

View File

@ -0,0 +1,242 @@
import time
from datetime import datetime
from functools import cached_property as functools_cached_property
from module.base.decorator import cached_property
from module.config.utils import DEFAULT_TIME, deep_get, get_server_last_update
from module.exception import ScriptError
def now():
return datetime.now().replace(microsecond=0)
def iter_attribute(cls):
"""
Args:
cls: Class or object
Yields:
str, obj: Attribute name, attribute value
"""
for attr in dir(cls):
if attr.startswith('_'):
continue
value = getattr(cls, attr)
if type(value).__name__ in ['function', 'property']:
continue
yield attr, value
class StoredBase:
time = DEFAULT_TIME
def __init__(self, key):
self._key = key
self._config = None
@cached_property
def _name(self):
return self._key.split('.')[-1]
def _bind(self, config):
"""
Args:
config (AzurLaneConfig):
"""
self._config = config
@functools_cached_property
def _stored(self):
assert self._config is not None, 'StoredBase._bind() must be called before getting stored data'
from module.logger import logger
out = {}
stored = deep_get(self._config.data, keys=self._key, default={})
for attr, default in self._attrs.items():
value = stored.get(attr, default)
if attr == 'time':
if not isinstance(value, datetime):
try:
value = datetime.fromisoformat(value)
except ValueError:
logger.warning(f'{self._name} has invalid attr: {attr}={value}, use default={default}')
value = default
else:
if not isinstance(value, type(default)):
logger.warning(f'{self._name} has invalid attr: {attr}={value}, use default={default}')
value = default
out[attr] = value
return out
@cached_property
def _attrs(self) -> dict:
"""
All attributes defined
"""
attrs = {
# time is the first one
'time': DEFAULT_TIME
}
for attr, value in iter_attribute(self.__class__):
attrs[attr] = value
return attrs
def __setattr__(self, key, value):
if key in self._attrs:
stored = self._stored
stored['time'] = now()
stored[key] = value
self._config.modified[self._key] = stored
if self._config.auto_update:
self._config.update()
else:
super().__setattr__(key, value)
def __getattribute__(self, item):
if not item.startswith('_') and item in self._attrs:
return self._stored[item]
else:
return super().__getattribute__(item)
def is_expired(self) -> bool:
return False
def show(self):
"""
Log self
"""
from module.logger import logger
logger.attr(self._name, self._stored)
def dashboard(self) -> str:
"""
Return a string to show on GUI
"""
return 'None'
def readable_time(self):
diff = self.time.timestamp() - time.time()
if diff < -1:
return '', 'TimeError'
elif diff < 60:
# < 1 min
return '', 'JustNow'
elif diff < 3600:
return str(int(diff // 60)), 'MinutesAgo'
elif diff < 86400:
return str(int(diff // 86400)), 'HoursAgo'
elif diff < 129600:
return str(int(diff // 129600)), 'DaysAgo'
else:
# > 15 days
return '', 'LongTimeAgo'
class StoredExpiredAt0400(StoredBase):
def is_expired(self):
from module.logger import logger
self.show()
expired = self.time < get_server_last_update('04:00')
logger.attr(f'{self._name} expired', expired)
return expired
class StoredInt(StoredBase):
value = 0
class StoredCounter(StoredBase):
current = 0
total = 0
def set(self, current, total):
with self._config.multi_set():
self.current = current
self.total = total
def to_counter(self) -> str:
return f'{self.current}/{self.total}'
def is_full(self) -> bool:
return self.current >= self.total
def get_remain(self) -> int:
return self.total - self.current
class StoredDailyActivity(StoredCounter, StoredExpiredAt0400):
def set(self, current):
return super().set(current=current, total=500)
@property
def _stored(self):
stored = super()._stored
stored['total'] = 500
return stored
class StoredDaily(StoredExpiredAt0400):
quest1 = ''
quest2 = ''
quest3 = ''
quest4 = ''
quest5 = ''
quest6 = ''
def load_quests(self):
"""
Returns:
list[DailyQuest]: Note that must check if quests are expired
"""
# DailyQuest should be lazy loaded
from tasks.daily.keywords import DailyQuest
quests = []
for name in [self.quest1, self.quest2, self.quest3, self.quest4, self.quest5, self.quest6]:
if not name:
continue
try:
quest = DailyQuest.find(name)
quests.append(quest)
except ScriptError:
pass
return quests
def write_quests(self, quests):
"""
Args:
quests (list[DailyQuest, str]):
"""
from tasks.daily.keywords import DailyQuest
quests = [q.name if isinstance(q, DailyQuest) else q for q in quests]
with self._config.multi_set():
try:
self.quest1 = quests[0]
except IndexError:
self.quest1 = ''
try:
self.quest2 = quests[1]
except IndexError:
self.quest2 = ''
try:
self.quest3 = quests[2]
except IndexError:
self.quest3 = ''
try:
self.quest4 = quests[3]
except IndexError:
self.quest4 = ''
try:
self.quest5 = quests[4]
except IndexError:
self.quest5 = ''
try:
self.quest6 = quests[5]
except IndexError:
self.quest6 = ''
class StoredDungeonDouble(StoredExpiredAt0400):
calyx = 0
relic = 0

View File

@ -0,0 +1,18 @@
from module.config.stored.classes import (
StoredBase,
StoredCounter,
StoredDaily,
StoredDailyActivity,
StoredDungeonDouble,
StoredExpiredAt0400,
StoredInt,
)
# This file was auto-generated, do not modify it manually. To generate:
# ``` python -m module/config/config_updater.py ```
class StoredGenerated:
DungeonDouble = StoredDungeonDouble("Dungeon.DungeonStorage.DungeonDouble")
DailyActivity = StoredDailyActivity("DailyQuest.DailyStorage.DailyActivity")
DailyQuest = StoredDaily("DailyQuest.DailyStorage.DailyQuest")

View File

@ -332,8 +332,9 @@ def data_to_type(data, **kwargs):
""" """
| Condition | Type | | Condition | Type |
| ------------------------------------ | -------- | | ------------------------------------ | -------- |
| Value is bool | checkbox | | `value` is bool | checkbox |
| Arg has options | select | | Arg has `options` | select |
| Arg has `stored` | select |
| `Filter` is in name (in data['arg']) | textarea | | `Filter` is in name (in data['arg']) | textarea |
| Rest of the args | input | | Rest of the args | input |
@ -345,10 +346,12 @@ def data_to_type(data, **kwargs):
str: str:
""" """
kwargs.update(data) kwargs.update(data)
if isinstance(kwargs['value'], bool): if isinstance(kwargs.get('value'), bool):
return 'checkbox' return 'checkbox'
elif 'option' in kwargs and kwargs['option']: elif 'option' in kwargs and kwargs['option']:
return 'select' return 'select'
elif 'stored' in kwargs and kwargs['stored']:
return 'stored'
elif 'Filter' in kwargs['arg']: elif 'Filter' in kwargs['arg']:
return 'textarea' return 'textarea'
else: else:

View File

@ -3,13 +3,12 @@ from module.logger import logger
from tasks.base.assets.assets_base_page import CLOSE from tasks.base.assets.assets_base_page import CLOSE
from tasks.combat.assets.assets_combat_finish import COMBAT_AGAIN, COMBAT_EXIT from tasks.combat.assets.assets_combat_finish import COMBAT_AGAIN, COMBAT_EXIT
from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE
from tasks.combat.assets.assets_combat_team import COMBAT_TEAM_PREPARE, COMBAT_TEAM_SUPPORT, COMBAT_TEAM_DISMISSSUPPORT from tasks.combat.assets.assets_combat_team import COMBAT_TEAM_PREPARE, COMBAT_TEAM_SUPPORT
from tasks.combat.assets.assets_combat_support import COMBAT_SUPPORT_ADD, COMBAT_SUPPORT_LIST
from tasks.combat.interact import CombatInteract from tasks.combat.interact import CombatInteract
from tasks.combat.prepare import CombatPrepare from tasks.combat.prepare import CombatPrepare
from tasks.combat.state import CombatState from tasks.combat.state import CombatState
from tasks.combat.team import CombatTeam
from tasks.combat.support import CombatSupport from tasks.combat.support import CombatSupport
from tasks.combat.team import CombatTeam
from tasks.map.control.joystick import MapControlJoystick from tasks.map.control.joystick import MapControlJoystick
@ -69,9 +68,8 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
""" """
Args: Args:
team: 1 to 6. team: 1 to 6.
skip_first_screenshot:
support_character: Support character name support_character: Support character name
Returns: Returns:
bool: True if success to enter combat bool: True if success to enter combat
False if trialblaze power is not enough False if trialblaze power is not enough
@ -272,21 +270,23 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
self.device.click(COMBAT_EXIT) self.device.click(COMBAT_EXIT)
continue continue
def combat(self, team: int = 1, wave_limit: int = 0, skip_first_screenshot=True, support_character: str = None): def is_stamina_exhausted(self) -> bool:
flag = self.state.TrailblazePower < self.combat_wave_cost
logger.attr('StaminaExhausted', flag)
return flag
def combat(self, team: int = 1, wave_limit: int = 0, support_character: str = None, skip_first_screenshot=True):
""" """
Combat until trailblaze power runs out. Combat until trailblaze power runs out.
Args: Args:
team: 1 to 6. team: 1 to 6.
wave_limit: Limit combat runs, 0 means no limit. wave_limit: Limit combat runs, 0 means no limit.
skip_first_screenshot:
use_support: "do_not_use", "always_use", "when_daily"
is_daily: True if is a daily task
support_character: Support character name support_character: Support character name
skip_first_screenshot:
Returns: Returns:
bool: True if trailblaze power exhausted int: Run count
False if reached wave_limit but still have trailblaze power
Pages: Pages:
in: COMBAT_PREPARE in: COMBAT_PREPARE
@ -298,6 +298,7 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
self.combat_wave_limit = wave_limit self.combat_wave_limit = wave_limit
self.combat_wave_done = 0 self.combat_wave_done = 0
run_count = 0
while 1: while 1:
logger.hr('Combat', level=2) logger.hr('Combat', level=2)
logger.info(f'Combat, team={team}, wave={self.combat_wave_done}/{self.combat_wave_limit}') logger.info(f'Combat, team={team}, wave={self.combat_wave_done}/{self.combat_wave_limit}')
@ -312,7 +313,9 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
finish = self.combat_finish() finish = self.combat_finish()
if self._combat_should_reenter(): if self._combat_should_reenter():
continue continue
run_count += 1
if finish: if finish:
break break
return self.state.TrailblazePower < self.combat_wave_cost logger.attr('CombatRunCount', run_count)
return run_count

View File

@ -94,6 +94,7 @@ class CombatState(UI):
self._combat_auto_checked = True self._combat_auto_checked = True
else: else:
if self._combat_click_interval.reached(): if self._combat_click_interval.reached():
self.device.image_save()
self.device.click(COMBAT_AUTO) self.device.click(COMBAT_AUTO)
self._combat_click_interval.reset() self._combat_click_interval.reset()
return True return True

View File

@ -99,6 +99,7 @@ class DailyQuestUI(DungeonUI):
results = [result.matched_keyword for result in results] results = [result.matched_keyword for result in results]
logger.info("Daily quests recognition complete") logger.info("Daily quests recognition complete")
logger.info(f"Daily quests: {results}") logger.info(f"Daily quests: {results}")
self.config.stored.DailyQuest.write_quests(results)
return results return results
def _get_quest_reward(self, skip_first_screenshot=True): def _get_quest_reward(self, skip_first_screenshot=True):
@ -128,7 +129,7 @@ class DailyQuestUI(DungeonUI):
def _get_active_point_reward(self, skip_first_screenshot=True): def _get_active_point_reward(self, skip_first_screenshot=True):
def get_active(): def get_active():
for button in [ for b in [
ACTIVE_POINTS_1_UNLOCK, ACTIVE_POINTS_1_UNLOCK,
ACTIVE_POINTS_2_UNLOCK, ACTIVE_POINTS_2_UNLOCK,
ACTIVE_POINTS_3_UNLOCK, ACTIVE_POINTS_3_UNLOCK,
@ -136,8 +137,8 @@ class DailyQuestUI(DungeonUI):
ACTIVE_POINTS_5_UNLOCK ACTIVE_POINTS_5_UNLOCK
]: ]:
# Black gift icon # Black gift icon
if self.image_color_count(button, color=(61, 53, 53), threshold=221, count=100): if self.image_color_count(b, color=(61, 53, 53), threshold=221, count=100):
return button return b
return None return None
interval = Timer(2) interval = Timer(2)
@ -156,6 +157,26 @@ class DailyQuestUI(DungeonUI):
self.device.click(active) self.device.click(active)
interval.reset() interval.reset()
# Write stored
point = 0
for progress, button in zip(
[100, 200, 300, 400, 500],
[
ACTIVE_POINTS_1_CHECKED,
ACTIVE_POINTS_2_CHECKED,
ACTIVE_POINTS_3_CHECKED,
ACTIVE_POINTS_4_CHECKED,
ACTIVE_POINTS_5_CHECKED
]
):
if self.appear(button):
point = progress
logger.attr('Daily activity', point)
with self.config.multi_set():
self.config.stored.DailyActivity.set(point)
if point == 500:
self.config.stored.DailyQuest.write_quests([])
def get_daily_rewards(self): def get_daily_rewards(self):
""" """
Returns: Returns:

View File

@ -1,58 +1,219 @@
from module.base.utils import area_offset from module.base.utils import area_offset
from module.logger import logger from module.logger import logger
from tasks.combat.combat import Combat from tasks.combat.combat import Combat
from tasks.daily.keywords import KEYWORDS_DAILY_QUEST
from tasks.dungeon.event import DungeonEvent from tasks.dungeon.event import DungeonEvent
from tasks.dungeon.keywords import DungeonList, KEYWORDS_DUNGEON_LIST, KEYWORDS_DUNGEON_TAB from tasks.dungeon.keywords import DungeonList, KEYWORDS_DUNGEON_LIST, KEYWORDS_DUNGEON_TAB
from tasks.dungeon.ui import DungeonUI from tasks.dungeon.ui import DungeonUI
class Dungeon(DungeonUI, DungeonEvent, Combat): class Dungeon(DungeonUI, DungeonEvent, Combat):
def run(self, dungeon: DungeonList = None, team: int = None, use_support: str = None, is_daily: bool = False, called_daily_support = False
support_character: str = None): achieved_daily_quest = False
if dungeon is None: daily_quests = []
dungeon = DungeonList.find(self.config.Dungeon_Name)
def _dungeon_run(self, dungeon: DungeonList, team: int = None, wave_limit: int = 0, support_character: str = None,
skip_ui_switch: bool = False):
"""
Args:
dungeon:
team: 1 to 6.
wave_limit: Limit combat runs, 0 means no limit.
support_character: Support character name
skip_ui_switch: True if already at dungeon aside
Returns:
int: Run count
Pages:
in: Any
out: page_main
"""
if team is None: if team is None:
team = self.config.Dungeon_Team team = self.config.Dungeon_Team
if use_support is None: if support_character is None and self.config.DungeonSupport_Use == 'always_use':
use_support = self.config.Dungeon_Support support_character = self.config.DungeonSupport_Character
if support_character is None:
support_character = self.config.Dungeon_SupportCharacter if use_support == "always_use" or use_support == "when_daily" and is_daily else None
# UI switches logger.hr('Dungeon run', level=1)
switched = self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) logger.info(f'Dungeon: {dungeon}, team={team}, wave_limit={wave_limit}, support_character={support_character}')
if not switched:
# Nav must at top, reset nav states if not skip_ui_switch:
self.ui_goto_main()
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
self.dungeon_goto(dungeon)
# Check double events if dungeon == KEYWORDS_DUNGEON_LIST.Stagnant_Shadow_Blaze:
if self.config.Dungeon_NameAtDoubleCalyx != 'do_not_participate' and self.has_double_calyx_event(): if self.handle_destructible_around_blaze():
calyx = DungeonList.find(self.config.Dungeon_NameAtDoubleCalyx) self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
self._dungeon_nav_goto(calyx) self.dungeon_goto(dungeon)
if remain := self.get_double_event_remain():
self.dungeon_goto(calyx)
if self.combat(team, wave_limit=remain, support_character=support_character):
self.delay_dungeon_task(calyx)
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
if self.config.Dungeon_NameAtDoubleRelic != 'do_not_participate' and self.has_double_relic_event():
calyx = DungeonList.find(self.config.Dungeon_NameAtDoubleRelic)
self._dungeon_nav_goto(calyx)
if remain := self.get_double_event_remain():
self.dungeon_goto(calyx)
if self.combat(team, wave_limit=remain, support_character=support_character):
self.delay_dungeon_task(calyx)
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
# Combat # Combat
self.dungeon_goto(dungeon) count = self.combat(team=team, wave_limit=wave_limit, support_character=support_character)
if dungeon == KEYWORDS_DUNGEON_LIST.Stagnant_Shadow_Blaze: # Update quest states
if self.handle_destructible_around_blaze(): if dungeon.is_Calyx_Golden \
and KEYWORDS_DAILY_QUEST.Clear_Calyx_Golden_1_times in self.daily_quests:
logger.info('Achieved daily quest Clear_Calyx_Golden_1_times')
self.achieved_daily_quest = True
if dungeon.is_Calyx_Crimson \
and KEYWORDS_DAILY_QUEST.Complete_Calyx_Crimson_1_time in self.daily_quests:
logger.info('Achieve daily quest Complete_Calyx_Crimson_1_time')
self.achieved_daily_quest = True
if dungeon.is_Stagnant_Shadow \
and KEYWORDS_DAILY_QUEST.Clear_Stagnant_Shadow_1_times in self.daily_quests:
logger.info('Achieve daily quest Clear_Stagnant_Shadow_1_times')
self.achieved_daily_quest = True
if dungeon.is_Cavern_of_Corrosion \
and KEYWORDS_DAILY_QUEST.Clear_Cavern_of_Corrosion_1_times in self.daily_quests:
logger.info('Achieve daily quest Clear_Cavern_of_Corrosion_1_times')
self.achieved_daily_quest = True
if support_character is not None:
self.called_daily_support = True
if KEYWORDS_DAILY_QUEST.Obtain_victory_in_combat_with_support_characters_1_time:
logger.info('Achieve daily quest Obtain_victory_in_combat_with_support_characters_1_time')
self.achieved_daily_quest = True
# Check stamina, this may stop current task
if self.is_stamina_exhausted():
self.delay_dungeon_task(dungeon)
return count
def dungeon_run(
self, dungeon: DungeonList, team: int = None, wave_limit: int = 0, support_character: str = None):
"""
Run dungeon, and handle daily support
Args:
dungeon:
team: 1 to 6.
wave_limit: Limit combat runs, 0 means no limit.
support_character: Support character name
Returns:
int: Run count
Pages:
in: Any
out: page_main
"""
require = self.require_compulsory_support()
if require:
logger.info('Run once with support')
count = self._dungeon_run(dungeon=dungeon, team=team, wave_limit=1,
support_character=self.config.DungeonSupport_Character)
logger.info('Run the rest waves without compulsory support')
if wave_limit >= 2 or wave_limit == 0:
# Already at page_name with DUNGEON_COMBAT_INTERACT
if wave_limit >= 2:
wave_limit -= 1
count += self._dungeon_run(dungeon=dungeon, team=team, wave_limit=wave_limit,
support_character=support_character, skip_ui_switch=True)
return count
else:
# Normal run
return self._dungeon_run(dungeon=dungeon, team=team, wave_limit=wave_limit,
support_character=support_character)
def run(self):
# Update daily quests
if self.config.stored.DailyActivity.is_expired():
logger.info('Daily activity expired, call task to update')
self.config.task_call('DailyQuest')
self.config.task_stop()
if self.config.stored.DailyQuest.is_expired():
logger.info('Daily quests expired, call task to update')
self.config.task_call('DailyQuest')
self.config.task_stop()
self.called_daily_support = False
self.achieved_daily_quest = False
self.daily_quests = self.config.stored.DailyQuest.load_quests()
# Update double event records
if self.config.stored.DungeonDouble.is_expired():
logger.info('Get dungeon double remains')
# UI switches
switched = self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
if not switched:
# Nav must at top, reset nav states
self.ui_goto_main()
self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)
self.dungeon_goto(dungeon) # Check remains
calyx = 0
relic = 0
if self.has_double_calyx_event():
self._dungeon_nav_goto(KEYWORDS_DUNGEON_LIST.Calyx_Golden_Treasures)
calyx = self.get_double_event_remain()
if self.has_double_relic_event():
self._dungeon_nav_goto(KEYWORDS_DUNGEON_LIST.Cavern_of_Corrosion_Path_of_Gelid_Wind)
relic = self.get_double_event_remain()
with self.config.multi_set():
self.config.stored.DungeonDouble.calyx = calyx
self.config.stored.DungeonDouble.relic = relic
self.combat(team=team, support_character=support_character) # Run double events
self.delay_dungeon_task(dungeon) ran_calyx_golden = False
ran_calyx_crimson = False
ran_cavern_of_corrosion = False
# Double calyx
if self.config.Dungeon_NameAtDoubleCalyx != 'do_not_participate' \
and self.config.stored.DungeonDouble.calyx > 0:
logger.info('Run double calyx')
dungeon = DungeonList.find(self.config.Dungeon_NameAtDoubleCalyx)
if self.dungeon_run(dungeon=dungeon, wave_limit=self.config.stored.DungeonDouble.calyx):
if dungeon.is_Calyx_Golden:
ran_calyx_golden = True
if dungeon.is_Calyx_Crimson:
ran_calyx_crimson = True
# Double relic
if self.config.Dungeon_NameAtDoubleRelic != 'do_not_participate' \
and self.config.stored.DungeonDouble.relic > 0:
logger.info('Run double relic')
dungeon = DungeonList.find(self.config.Dungeon_NameAtDoubleRelic)
if self.dungeon_run(dungeon=dungeon, wave_limit=self.config.stored.DungeonDouble.relic):
ran_cavern_of_corrosion = True
# Dungeon to clear all trailblaze power
final = DungeonList.find(self.config.Dungeon_Name)
# Run dungeon that required by daily quests
# Calyx_Golden
if KEYWORDS_DAILY_QUEST.Clear_Calyx_Golden_1_times in self.daily_quests \
and self.config.DungeonDaily_CalyxGolden != 'do_not_achieve' \
and not final.is_Calyx_Golden \
and not ran_calyx_golden:
logger.info('Run Calyx_Golden once')
dungeon = DungeonList.find(self.config.DungeonDaily_CalyxGolden)
self.dungeon_run(dungeon=dungeon, wave_limit=1)
# Calyx_Crimson
if KEYWORDS_DAILY_QUEST.Complete_Calyx_Crimson_1_time in self.daily_quests \
and self.config.DungeonDaily_CalyxCrimson != 'do_not_achieve' \
and not final.is_Calyx_Crimson \
and not ran_calyx_crimson:
logger.info('Run Calyx_Crimson once')
dungeon = DungeonList.find(self.config.DungeonDaily_CalyxCrimson)
self.dungeon_run(dungeon=dungeon, wave_limit=1)
# Stagnant_Shadow
if KEYWORDS_DAILY_QUEST.Clear_Stagnant_Shadow_1_times in self.daily_quests \
and self.config.DungeonDaily_StagnantShadow != 'do_not_achieve' \
and not final.is_Stagnant_Shadow:
logger.info('Run Stagnant_Shadow once')
dungeon = DungeonList.find(self.config.DungeonDaily_StagnantShadow)
self.dungeon_run(dungeon=dungeon, wave_limit=1)
# Cavern_of_Corrosion
if KEYWORDS_DAILY_QUEST.Clear_Cavern_of_Corrosion_1_times in self.daily_quests \
and self.config.DungeonDaily_CavernOfCorrosion != 'do_not_achieve' \
and not final.is_Cavern_of_Corrosion \
and not ran_cavern_of_corrosion:
logger.info('Run Cavern_of_Corrosion once')
dungeon = DungeonList.find(self.config.DungeonDaily_CavernOfCorrosion)
self.dungeon_run(dungeon=dungeon, wave_limit=1)
# Combat
self.dungeon_run(final)
self.delay_dungeon_task(final)
def delay_dungeon_task(self, dungeon): def delay_dungeon_task(self, dungeon):
if dungeon.is_Cavern_of_Corrosion: if dungeon.is_Cavern_of_Corrosion:
@ -62,7 +223,11 @@ class Dungeon(DungeonUI, DungeonEvent, Combat):
# Recover 1 trailbaze power each 6 minutes # Recover 1 trailbaze power each 6 minutes
cover = max(limit - self.state.TrailblazePower, 0) * 6 cover = max(limit - self.state.TrailblazePower, 0) * 6
logger.info(f'Currently has {self.state.TrailblazePower} need {cover} minutes to reach {limit}') logger.info(f'Currently has {self.state.TrailblazePower} need {cover} minutes to reach {limit}')
self.config.task_delay(minute=cover) logger.attr('achieved_daily_quest', self.achieved_daily_quest)
with self.config.multi_set():
if self.achieved_daily_quest:
self.config.task_call('DailyQuest')
self.config.task_delay(minute=cover)
self.config.task_stop() self.config.task_stop()
def handle_destructible_around_blaze(self): def handle_destructible_around_blaze(self):
@ -104,3 +269,23 @@ class Dungeon(DungeonUI, DungeonEvent, Combat):
break break
return handled return handled
def require_compulsory_support(self) -> bool:
require = False
if not self.config.stored.DailyActivity.is_full():
if KEYWORDS_DAILY_QUEST.Obtain_victory_in_combat_with_support_characters_1_time \
in self.daily_quests:
require = True
logger.attr('called_daily_support', self.called_daily_support)
if self.called_daily_support:
require = False
# Not required, cause any dungeon run will achieve the quest
logger.attr('DungeonSupport_Use', self.config.DungeonSupport_Use)
if self.config.DungeonSupport_Use == 'always_use':
require = False
logger.attr('Require compulsory support', require)
return require

View File

@ -28,6 +28,10 @@ class DungeonList(Keyword):
def is_Calyx_Crimson(self): def is_Calyx_Crimson(self):
return 'Calyx_Crimson' in self.name return 'Calyx_Crimson' in self.name
@cached_property
def is_Calyx(self):
return self.is_Calyx_Golden or self.is_Calyx_Crimson
@cached_property @cached_property
def is_Stagnant_Shadow(self): def is_Stagnant_Shadow(self):
return 'Stagnant_Shadow' in self.name return 'Stagnant_Shadow' in self.name