Merge pull request #579 from LmeSzinc/dev

Dev
This commit is contained in:
LmeSzinc 2024-07-19 10:06:21 +08:00 committed by GitHub
commit 7e44dbed36
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 646 additions and 17 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -111,6 +111,11 @@
"DungeonDouble": {}, "DungeonDouble": {},
"EchoOfWar": {}, "EchoOfWar": {},
"SimulatedUniverse": {} "SimulatedUniverse": {}
},
"TrailblazePower": {
"ExtractReservedTrailblazePower": false,
"UseFuel": false,
"FuelReserve": 5
} }
}, },
"DailyQuest": { "DailyQuest": {
@ -140,6 +145,7 @@
"BattlePassQuestEchoOfWar": {}, "BattlePassQuestEchoOfWar": {},
"BattlePassQuestCredits": {}, "BattlePassQuestCredits": {},
"BattlePassQuestSynthesizeConsumables": {}, "BattlePassQuestSynthesizeConsumables": {},
"BattlePassQuestStagnantShadow": {},
"BattlePassQuestCavernOfCorrosion": {}, "BattlePassQuestCavernOfCorrosion": {},
"BattlePassQuestTrailblazePower": {} "BattlePassQuestTrailblazePower": {}
} }
@ -252,6 +258,11 @@
"DungeonSupport": { "DungeonSupport": {
"Use": "when_daily", "Use": "when_daily",
"Character": "FirstCharacter" "Character": "FirstCharacter"
},
"TrailblazePower": {
"ExtractReservedTrailblazePower": false,
"UseFuel": false,
"FuelReserve": 5
} }
}, },
"Daemon": { "Daemon": {

View File

@ -738,6 +738,20 @@
"order": 6, "order": 6,
"color": "#8fb5fe" "color": "#8fb5fe"
} }
},
"TrailblazePower": {
"ExtractReservedTrailblazePower": {
"type": "checkbox",
"value": false
},
"UseFuel": {
"type": "checkbox",
"value": false
},
"FuelReserve": {
"type": "input",
"value": 5
}
} }
}, },
"DailyQuest": { "DailyQuest": {
@ -858,6 +872,12 @@
"display": "display", "display": "display",
"stored": "StoredBattlePassQuestSynthesizeConsumables" "stored": "StoredBattlePassQuestSynthesizeConsumables"
}, },
"BattlePassQuestStagnantShadow": {
"type": "stored",
"value": {},
"display": "display",
"stored": "StoredBattlePassQuestStagnantShadow"
},
"BattlePassQuestCavernOfCorrosion": { "BattlePassQuestCavernOfCorrosion": {
"type": "stored", "type": "stored",
"value": {}, "value": {},
@ -1532,6 +1552,20 @@
"Yukong" "Yukong"
] ]
} }
},
"TrailblazePower": {
"ExtractReservedTrailblazePower": {
"type": "checkbox",
"value": false
},
"UseFuel": {
"type": "checkbox",
"value": false
},
"FuelReserve": {
"type": "input",
"value": 5
}
} }
}, },
"Daemon": { "Daemon": {

View File

@ -103,6 +103,10 @@ Dungeon:
Team: Team:
value: 1 value: 1
option: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] option: [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
TrailblazePower:
ExtractReservedTrailblazePower: false
UseFuel: false
FuelReserve: 5
DungeonSupport: DungeonSupport:
Use: Use:
value: when_daily value: when_daily
@ -179,6 +183,9 @@ BattlePassStorage:
BattlePassQuestSynthesizeConsumables: BattlePassQuestSynthesizeConsumables:
stored: StoredBattlePassQuestSynthesizeConsumables stored: StoredBattlePassQuestSynthesizeConsumables
display: display display: display
BattlePassQuestStagnantShadow:
stored: StoredBattlePassQuestStagnantShadow
display: display
BattlePassQuestCavernOfCorrosion: BattlePassQuestCavernOfCorrosion:
stored: StoredBattlePassQuestCavernOfCorrosion stored: StoredBattlePassQuestCavernOfCorrosion
display: display display: display

View File

@ -715,7 +715,9 @@
"quest4": "", "quest4": "",
"quest5": "", "quest5": "",
"quest6": "", "quest6": "",
"total": 6, "quest7": "",
"quest8": "",
"total": 8,
"value": 0 "value": 0
}, },
"order": 0, "order": 0,
@ -806,6 +808,19 @@
"order": 0, "order": 0,
"color": "#777777" "color": "#777777"
}, },
"BattlePassQuestStagnantShadow": {
"name": "BattlePassQuestStagnantShadow",
"path": "BattlePass.BattlePassStorage.BattlePassQuestStagnantShadow",
"i18n": "BattlePassStorage.BattlePassQuestStagnantShadow.name",
"stored": "StoredBattlePassQuestStagnantShadow",
"attrs": {
"time": "2020-01-01 00:00:00",
"total": 3,
"value": 0
},
"order": 0,
"color": "#777777"
},
"BattlePassQuestCavernOfCorrosion": { "BattlePassQuestCavernOfCorrosion": {
"name": "BattlePassQuestCavernOfCorrosion", "name": "BattlePassQuestCavernOfCorrosion",
"path": "BattlePass.BattlePassStorage.BattlePassQuestCavernOfCorrosion", "path": "BattlePass.BattlePassStorage.BattlePassQuestCavernOfCorrosion",

View File

@ -28,6 +28,7 @@ Daily:
- Dungeon - Dungeon
- DungeonSupport - DungeonSupport
- DungeonStorage - DungeonStorage
- TrailblazePower
DailyQuest: DailyQuest:
- Scheduler - Scheduler
- DailyStorage - DailyStorage
@ -64,6 +65,7 @@ Weekly:
- Scheduler - Scheduler
- Ornament - Ornament
- DungeonSupport - DungeonSupport
- TrailblazePower
# ==================== Tool ==================== # ==================== Tool ====================

View File

@ -516,7 +516,17 @@ class AzurLaneConfig(ConfigUpdater, ManualConfig, GeneratedConfig, ConfigWatcher
self.stored.DailyActivity.clear() self.stored.DailyActivity.clear()
if self.stored.DailyQuest.is_expired(): if self.stored.DailyQuest.is_expired():
logger.info('DailyQuest expired') logger.info('DailyQuest expired')
self.stored.DailyQuest.clear() q = self.stored.DailyQuest
q.clear()
# Assume fixed quests
q.write_quests([
'Complete_1_Daily_Mission',
'Log_in_to_the_game',
'Dispatch_1_assignments',
'Complete_Divergent_Universe_or_Simulated_Universe_1_times',
'Obtain_victory_in_combat_with_Support_Characters_1_times',
'Consume_120_Trailblaze_Power',
])
def update_battle_pass_quests(self): def update_battle_pass_quests(self):
""" """

View File

@ -46,6 +46,11 @@ class GeneratedConfig:
Dungeon_NameAtDoubleRelic = 'Cavern_of_Corrosion_Path_of_Providence' # 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, Cavern_of_Corrosion_Path_of_Darkness, Cavern_of_Corrosion_Path_of_Dreamdive, Cavern_of_Corrosion_Path_of_Cavalier Dungeon_NameAtDoubleRelic = 'Cavern_of_Corrosion_Path_of_Providence' # 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, Cavern_of_Corrosion_Path_of_Darkness, Cavern_of_Corrosion_Path_of_Dreamdive, Cavern_of_Corrosion_Path_of_Cavalier
Dungeon_Team = 1 # 1, 2, 3, 4, 5, 6, 7, 8, 9 Dungeon_Team = 1 # 1, 2, 3, 4, 5, 6, 7, 8, 9
# Group `TrailblazePower`
TrailblazePower_ExtractReservedTrailblazePower = False
TrailblazePower_UseFuel = False
TrailblazePower_FuelReserve = 5
# Group `DungeonSupport` # Group `DungeonSupport`
DungeonSupport_Use = 'when_daily' # always_use, when_daily, do_not_use DungeonSupport_Use = 'when_daily' # always_use, when_daily, do_not_use
DungeonSupport_Character = 'FirstCharacter' # FirstCharacter, Acheron, Argenti, Arlan, Asta, Aventurine, Bailu, BlackSwan, Blade, Boothill, Bronya, Clara, DanHeng, DanHengImbibitorLunae, DrRatio, Firefly, FuXuan, Gallagher, Gepard, Guinaifen, Hanya, Herta, Himeko, Hook, Huohuo, JingYuan, Jingliu, Kafka, Luka, Luocha, Lynx, March7th, Misha, Natasha, Pela, Qingque, Robin, RuanMei, Sampo, Seele, Serval, SilverWolf, Sparkle, Sushang, Tingyun, TopazNumby, TrailblazerDestruction, TrailblazerHarmony, TrailblazerPreservation, Welt, Xueyi, Yanqing, Yukong DungeonSupport_Character = 'FirstCharacter' # FirstCharacter, Acheron, Argenti, Arlan, Asta, Aventurine, Bailu, BlackSwan, Blade, Boothill, Bronya, Clara, DanHeng, DanHengImbibitorLunae, DrRatio, Firefly, FuXuan, Gallagher, Gepard, Guinaifen, Hanya, Herta, Himeko, Hook, Huohuo, JingYuan, Jingliu, Kafka, Luka, Luocha, Lynx, March7th, Misha, Natasha, Pela, Qingque, Robin, RuanMei, Sampo, Seele, Serval, SilverWolf, Sparkle, Sushang, Tingyun, TopazNumby, TrailblazerDestruction, TrailblazerHarmony, TrailblazerPreservation, Welt, Xueyi, Yanqing, Yukong
@ -130,6 +135,7 @@ class GeneratedConfig:
BattlePassStorage_BattlePassQuestEchoOfWar = {} BattlePassStorage_BattlePassQuestEchoOfWar = {}
BattlePassStorage_BattlePassQuestCredits = {} BattlePassStorage_BattlePassQuestCredits = {}
BattlePassStorage_BattlePassQuestSynthesizeConsumables = {} BattlePassStorage_BattlePassQuestSynthesizeConsumables = {}
BattlePassStorage_BattlePassQuestStagnantShadow = {}
BattlePassStorage_BattlePassQuestCavernOfCorrosion = {} BattlePassStorage_BattlePassQuestCavernOfCorrosion = {}
BattlePassStorage_BattlePassQuestTrailblazePower = {} BattlePassStorage_BattlePassQuestTrailblazePower = {}

View File

@ -828,6 +828,8 @@ class ConfigUpdater:
Yields: Yields:
str: Arg path that should be hidden str: Arg path that should be hidden
""" """
if deep_get(data, 'Dungeon.TrailblazePower.UseFuel') == False:
yield 'Dungeon.TrailblazePower.UseFuelUntilRemainCount'
if deep_get(data, 'Rogue.RogueBlessing.PresetBlessingFilter') != 'custom': if deep_get(data, 'Rogue.RogueBlessing.PresetBlessingFilter') != 'custom':
yield 'Rogue.RogueBlessing.CustomBlessingFilter' yield 'Rogue.RogueBlessing.CustomBlessingFilter'
if deep_get(data, 'Rogue.RogueBlessing.PresetResonanceFilter') != 'custom': if deep_get(data, 'Rogue.RogueBlessing.PresetResonanceFilter') != 'custom':

View File

@ -345,6 +345,24 @@
"9": "9" "9": "9"
} }
}, },
"TrailblazePower": {
"_info": {
"name": "TrailblazePower Settings",
"help": ""
},
"ExtractReservedTrailblazePower": {
"name": "Extract reserve exploration power",
"help": ""
},
"UseFuel": {
"name": "Use Fuel",
"help": ""
},
"FuelReserve": {
"name": "Reserve X Fuel",
"help": ""
}
},
"DungeonSupport": { "DungeonSupport": {
"_info": { "_info": {
"name": "Support Settings", "name": "Support Settings",
@ -740,6 +758,10 @@
"name": "Synthesize Consumables 10 time(s)", "name": "Synthesize Consumables 10 time(s)",
"help": "" "help": ""
}, },
"BattlePassQuestStagnantShadow": {
"name": "Clear Stagnant Shadow 3 time(s)",
"help": ""
},
"BattlePassQuestCavernOfCorrosion": { "BattlePassQuestCavernOfCorrosion": {
"name": "Clear Cavern of Corrosion 8 time(s)", "name": "Clear Cavern of Corrosion 8 time(s)",
"help": "" "help": ""

View File

@ -345,6 +345,24 @@
"9": "9" "9": "9"
} }
}, },
"TrailblazePower": {
"_info": {
"name": "Ajustes de Poder Trazacaminos",
"help": ""
},
"ExtractReservedTrailblazePower": {
"name": "Extraer reserva de poder de trazacaminos",
"help": ""
},
"UseFuel": {
"name": "Usar combustible",
"help": ""
},
"FuelReserve": {
"name": "Reserva X Combustible",
"help": ""
}
},
"DungeonSupport": { "DungeonSupport": {
"_info": { "_info": {
"name": "Ajustes de Apoyo", "name": "Ajustes de Apoyo",
@ -740,6 +758,10 @@
"name": "Sintetiza consumibles 10 veces", "name": "Sintetiza consumibles 10 veces",
"help": "" "help": ""
}, },
"BattlePassQuestStagnantShadow": {
"name": "Completa Sombra paralizada 3 veces",
"help": ""
},
"BattlePassQuestCavernOfCorrosion": { "BattlePassQuestCavernOfCorrosion": {
"name": "Completa Caverna de la corrosión 8 veces", "name": "Completa Caverna de la corrosión 8 veces",
"help": "" "help": ""

View File

@ -345,6 +345,24 @@
"9": "9" "9": "9"
} }
}, },
"TrailblazePower": {
"_info": {
"name": "TrailblazePower._info.name",
"help": "TrailblazePower._info.help"
},
"ExtractReservedTrailblazePower": {
"name": "TrailblazePower.ExtractReservedTrailblazePower.name",
"help": "TrailblazePower.ExtractReservedTrailblazePower.help"
},
"UseFuel": {
"name": "TrailblazePower.UseFuel.name",
"help": "TrailblazePower.UseFuel.help"
},
"FuelReserve": {
"name": "TrailblazePower.FuelReserve.name",
"help": "TrailblazePower.FuelReserve.help"
}
},
"DungeonSupport": { "DungeonSupport": {
"_info": { "_info": {
"name": "DungeonSupport._info.name", "name": "DungeonSupport._info.name",
@ -740,6 +758,10 @@
"name": "BattlePassStorage.BattlePassQuestSynthesizeConsumables.name", "name": "BattlePassStorage.BattlePassQuestSynthesizeConsumables.name",
"help": "BattlePassStorage.BattlePassQuestSynthesizeConsumables.help" "help": "BattlePassStorage.BattlePassQuestSynthesizeConsumables.help"
}, },
"BattlePassQuestStagnantShadow": {
"name": "BattlePassStorage.BattlePassQuestStagnantShadow.name",
"help": "BattlePassStorage.BattlePassQuestStagnantShadow.help"
},
"BattlePassQuestCavernOfCorrosion": { "BattlePassQuestCavernOfCorrosion": {
"name": "BattlePassStorage.BattlePassQuestCavernOfCorrosion.name", "name": "BattlePassStorage.BattlePassQuestCavernOfCorrosion.name",
"help": "BattlePassStorage.BattlePassQuestCavernOfCorrosion.help" "help": "BattlePassStorage.BattlePassQuestCavernOfCorrosion.help"

View File

@ -345,6 +345,24 @@
"9": "9" "9": "9"
} }
}, },
"TrailblazePower": {
"_info": {
"name": "开拓力设置",
"help": ""
},
"ExtractReservedTrailblazePower": {
"name": "取出后备开拓力",
"help": ""
},
"UseFuel": {
"name": "使用燃料",
"help": ""
},
"FuelReserve": {
"name": "保留 X 燃料",
"help": ""
}
},
"DungeonSupport": { "DungeonSupport": {
"_info": { "_info": {
"name": "支援设置", "name": "支援设置",
@ -740,6 +758,10 @@
"name": "累计合成消耗品10次", "name": "累计合成消耗品10次",
"help": "" "help": ""
}, },
"BattlePassQuestStagnantShadow": {
"name": "完成3次「凝滞虚影」",
"help": ""
},
"BattlePassQuestCavernOfCorrosion": { "BattlePassQuestCavernOfCorrosion": {
"name": "完成8次「侵蚀隧洞」", "name": "完成8次「侵蚀隧洞」",
"help": "" "help": ""

View File

@ -345,6 +345,24 @@
"9": "9" "9": "9"
} }
}, },
"TrailblazePower": {
"_info": {
"name": "開拓力設定",
"help": ""
},
"ExtractReservedTrailblazePower": {
"name": "取出後備開拓力",
"help": ""
},
"UseFuel": {
"name": "使用燃料",
"help": ""
},
"FuelReserve": {
"name": "保留 X 燃料",
"help": ""
}
},
"DungeonSupport": { "DungeonSupport": {
"_info": { "_info": {
"name": "支援設定", "name": "支援設定",
@ -740,6 +758,10 @@
"name": "累计合成消耗品10次", "name": "累计合成消耗品10次",
"help": "" "help": ""
}, },
"BattlePassQuestStagnantShadow": {
"name": "完成3次「凝滯虛影」",
"help": ""
},
"BattlePassQuestCavernOfCorrosion": { "BattlePassQuestCavernOfCorrosion": {
"name": "完成8次「侵蚀隧洞」", "name": "完成8次「侵蚀隧洞」",
"help": "" "help": ""

View File

@ -234,8 +234,10 @@ class StoredDaily(StoredCounter, StoredExpiredAt0400):
quest4 = '' quest4 = ''
quest5 = '' quest5 = ''
quest6 = '' quest6 = ''
quest7 = ''
quest8 = ''
FIXED_TOTAL = 6 FIXED_TOTAL = 8
def load_quests(self): def load_quests(self):
""" """
@ -245,7 +247,8 @@ class StoredDaily(StoredCounter, StoredExpiredAt0400):
# DailyQuest should be lazy loaded # DailyQuest should be lazy loaded
from tasks.daily.keywords import DailyQuest from tasks.daily.keywords import DailyQuest
quests = [] quests = []
for name in [self.quest1, self.quest2, self.quest3, self.quest4, self.quest5, self.quest6]: for name in [self.quest1, self.quest2, self.quest3, self.quest4,
self.quest5, self.quest6, self.quest7, self.quest8]:
if not name: if not name:
continue continue
try: try:
@ -288,6 +291,14 @@ class StoredDaily(StoredCounter, StoredExpiredAt0400):
self.quest6 = quests[5] self.quest6 = quests[5]
except IndexError: except IndexError:
self.quest6 = '' self.quest6 = ''
try:
self.quest7 = quests[6]
except IndexError:
self.quest7 = ''
try:
self.quest8 = quests[7]
except IndexError:
self.quest8 = ''
def clear(self): def clear(self):
with self._config.multi_set(): with self._config.multi_set():
@ -297,6 +308,8 @@ class StoredDaily(StoredCounter, StoredExpiredAt0400):
self.quest4 = '' self.quest4 = ''
self.quest5 = '' self.quest5 = ''
self.quest6 = '' self.quest6 = ''
self.quest7 = ''
self.quest8 = ''
class StoredDungeonDouble(StoredExpiredAt0400): class StoredDungeonDouble(StoredExpiredAt0400):
@ -411,9 +424,8 @@ class StoredBattlePassQuestSynthesizeConsumables(StoredCounter):
FIXED_TOTAL = 10 FIXED_TOTAL = 10
# Not exists on client side class StoredBattlePassQuestStagnantShadow(StoredCounter):
# class StoredBattlePassQuestStagnantShadow(StoredCounter): FIXED_TOTAL = 3
# FIXED_TOTAL = 8
class StoredBattlePassQuestCavernOfCorrosion(StoredCounter): class StoredBattlePassQuestCavernOfCorrosion(StoredCounter):

View File

@ -6,6 +6,7 @@ from module.config.stored.classes import (
StoredBattlePassQuestCavernOfCorrosion, StoredBattlePassQuestCavernOfCorrosion,
StoredBattlePassQuestCredits, StoredBattlePassQuestCredits,
StoredBattlePassQuestEchoOfWar, StoredBattlePassQuestEchoOfWar,
StoredBattlePassQuestStagnantShadow,
StoredBattlePassQuestSynthesizeConsumables, StoredBattlePassQuestSynthesizeConsumables,
StoredBattlePassQuestTrailblazePower, StoredBattlePassQuestTrailblazePower,
StoredBattlePassSimulatedUniverse, StoredBattlePassSimulatedUniverse,
@ -97,6 +98,7 @@ class StoredGenerated:
BattlePassQuestEchoOfWar = StoredBattlePassQuestEchoOfWar("BattlePass.BattlePassStorage.BattlePassQuestEchoOfWar") BattlePassQuestEchoOfWar = StoredBattlePassQuestEchoOfWar("BattlePass.BattlePassStorage.BattlePassQuestEchoOfWar")
BattlePassQuestCredits = StoredBattlePassQuestCredits("BattlePass.BattlePassStorage.BattlePassQuestCredits") BattlePassQuestCredits = StoredBattlePassQuestCredits("BattlePass.BattlePassStorage.BattlePassQuestCredits")
BattlePassQuestSynthesizeConsumables = StoredBattlePassQuestSynthesizeConsumables("BattlePass.BattlePassStorage.BattlePassQuestSynthesizeConsumables") BattlePassQuestSynthesizeConsumables = StoredBattlePassQuestSynthesizeConsumables("BattlePass.BattlePassStorage.BattlePassQuestSynthesizeConsumables")
BattlePassQuestStagnantShadow = StoredBattlePassQuestStagnantShadow("BattlePass.BattlePassStorage.BattlePassQuestStagnantShadow")
BattlePassQuestCavernOfCorrosion = StoredBattlePassQuestCavernOfCorrosion("BattlePass.BattlePassStorage.BattlePassQuestCavernOfCorrosion") BattlePassQuestCavernOfCorrosion = StoredBattlePassQuestCavernOfCorrosion("BattlePass.BattlePassStorage.BattlePassQuestCavernOfCorrosion")
BattlePassQuestTrailblazePower = StoredBattlePassQuestTrailblazePower("BattlePass.BattlePassStorage.BattlePassQuestTrailblazePower") BattlePassQuestTrailblazePower = StoredBattlePassQuestTrailblazePower("BattlePass.BattlePassStorage.BattlePassQuestTrailblazePower")
Assignment = StoredAssignment("Assignment.Assignment.Assignment") Assignment = StoredAssignment("Assignment.Assignment.Assignment")

View File

@ -354,6 +354,8 @@ class BattlePassUI(UI):
self.config.stored.BattlePassQuestCredits, self.config.stored.BattlePassQuestCredits,
KEYWORDS_BATTLE_PASS_QUEST.Synthesize_Consumables_1_times: KEYWORDS_BATTLE_PASS_QUEST.Synthesize_Consumables_1_times:
self.config.stored.BattlePassQuestSynthesizeConsumables, self.config.stored.BattlePassQuestSynthesizeConsumables,
KEYWORDS_BATTLE_PASS_QUEST.Clear_Stagnant_Shadow_1_times:
self.config.stored.BattlePassQuestStagnantShadow,
KEYWORDS_BATTLE_PASS_QUEST.Clear_Cavern_of_Corrosion_1_times: KEYWORDS_BATTLE_PASS_QUEST.Clear_Cavern_of_Corrosion_1_times:
self.config.stored.BattlePassQuestCavernOfCorrosion, self.config.stored.BattlePassQuestCavernOfCorrosion,
KEYWORDS_BATTLE_PASS_QUEST.Consume_a_total_of_1_Trailblaze_Power_1400_Trailblazer_Power_max: KEYWORDS_BATTLE_PASS_QUEST.Consume_a_total_of_1_Trailblaze_Power_1400_Trailblazer_Power_max:

View File

@ -0,0 +1,165 @@
from module.base.button import Button, ButtonWrapper
# This file was auto-generated, do not modify it manually. To generate:
# ``` python -m dev_tools.button_extract ```
EXTRACT_RESERVED_TRAILBLAZE_POWER = ButtonWrapper(
name='EXTRACT_RESERVED_TRAILBLAZE_POWER',
share=Button(
file='./assets/share/combat/fuel/EXTRACT_RESERVED_TRAILBLAZE_POWER.png',
area=(909, 506, 929, 526),
search=(889, 486, 949, 546),
color=(91, 91, 91),
button=(909, 506, 929, 526),
),
)
FUEL = ButtonWrapper(
name='FUEL',
share=Button(
file='./assets/share/combat/fuel/FUEL.png',
area=(592, 276, 688, 366),
search=(474, 271, 811, 396),
color=(123, 96, 134),
button=(592, 276, 688, 366),
),
)
FUEL_ENTRANCE = ButtonWrapper(
name='FUEL_ENTRANCE',
share=Button(
file='./assets/share/combat/fuel/FUEL_ENTRANCE.png',
area=(1035, 26, 1056, 48),
search=(1015, 6, 1076, 68),
color=(188, 180, 226),
button=(1035, 26, 1056, 48),
),
)
FUEL_MINUS = ButtonWrapper(
name='FUEL_MINUS',
share=Button(
file='./assets/share/combat/fuel/FUEL_MINUS.png',
area=(472, 425, 510, 450),
search=(452, 405, 530, 470),
color=(236, 236, 236),
button=(472, 425, 510, 450),
),
)
FUEL_PLUS = ButtonWrapper(
name='FUEL_PLUS',
share=Button(
file='./assets/share/combat/fuel/FUEL_PLUS.png',
area=(967, 426, 1005, 449),
search=(947, 406, 1025, 469),
color=(232, 232, 232),
button=(967, 426, 1005, 449),
),
)
FUEL_SELECTED = ButtonWrapper(
name='FUEL_SELECTED',
share=Button(
file='./assets/share/combat/fuel/FUEL_SELECTED.png',
area=(587, 271, 692, 368),
search=(474, 271, 811, 396),
color=(136, 112, 144),
button=(587, 271, 692, 368),
),
)
FUEL_SLIDER = ButtonWrapper(
name='FUEL_SLIDER',
share=Button(
file='./assets/share/combat/fuel/FUEL_SLIDER.png',
area=(561, 434, 916, 441),
search=(541, 414, 936, 461),
color=(215, 185, 154),
button=(561, 434, 916, 441),
),
)
OCR_EXTRACT_RESERVED_TRAILBLAZE_POWER_COUNT = ButtonWrapper(
name='OCR_EXTRACT_RESERVED_TRAILBLAZE_POWER_COUNT',
share=Button(
file='./assets/share/combat/fuel/OCR_EXTRACT_RESERVED_TRAILBLAZE_POWER_COUNT.png',
area=(425, 415, 688, 436),
search=(405, 395, 708, 456),
color=(192, 192, 192),
button=(425, 415, 688, 436),
),
)
OCR_FUEL = ButtonWrapper(
name='OCR_FUEL',
share=Button(
file='./assets/share/combat/fuel/OCR_FUEL.png',
area=(605, 369, 678, 386),
search=(585, 349, 698, 406),
color=(66, 66, 66),
button=(605, 369, 678, 386),
),
)
OCR_FUEL_COUNT = ButtonWrapper(
name='OCR_FUEL_COUNT',
share=Button(
file='./assets/share/combat/fuel/OCR_FUEL_COUNT.png',
area=(686, 409, 881, 425),
search=(666, 389, 901, 445),
color=(205, 205, 205),
button=(686, 409, 881, 425),
),
)
OCR_RESERVED_TRAILBLAZE_POWER = ButtonWrapper(
name='OCR_RESERVED_TRAILBLAZE_POWER',
share=Button(
file='./assets/share/combat/fuel/OCR_RESERVED_TRAILBLAZE_POWER.png',
area=(883, 29, 992, 44),
search=(863, 9, 1012, 64),
color=(51, 65, 65),
button=(883, 29, 992, 44),
),
)
RESERVED_MINUS = ButtonWrapper(
name='RESERVED_MINUS',
share=Button(
file='./assets/share/combat/fuel/RESERVED_MINUS.png',
area=(248, 474, 281, 498),
search=(228, 454, 301, 518),
color=(238, 238, 238),
button=(248, 474, 281, 498),
),
)
RESERVED_PLUS = ButtonWrapper(
name='RESERVED_PLUS',
share=Button(
file='./assets/share/combat/fuel/RESERVED_PLUS.png',
area=(938, 475, 974, 498),
search=(918, 455, 994, 518),
color=(232, 232, 232),
button=(938, 475, 974, 498),
),
)
RESERVED_SLIDER = ButtonWrapper(
name='RESERVED_SLIDER',
share=Button(
file='./assets/share/combat/fuel/RESERVED_SLIDER.png',
area=(334, 483, 873, 489),
search=(314, 463, 893, 509),
color=(212, 173, 130),
button=(334, 483, 873, 489),
),
)
RESERVED_TRAILBLAZE_POWER_ENTRANCE = ButtonWrapper(
name='RESERVED_TRAILBLAZE_POWER_ENTRANCE',
share=Button(
file='./assets/share/combat/fuel/RESERVED_TRAILBLAZE_POWER_ENTRANCE.png',
area=(895, 26, 916, 48),
search=(875, 6, 936, 68),
color=(154, 213, 214),
button=(895, 26, 916, 48),
),
)
USING_FUEL = ButtonWrapper(
name='USING_FUEL',
share=Button(
file='./assets/share/combat/fuel/USING_FUEL.png',
area=(263, 265, 363, 365),
search=(243, 245, 383, 385),
color=(161, 116, 129),
button=(263, 265, 363, 365),
),
)

View File

@ -5,6 +5,7 @@ from tasks.combat.assets.assets_combat_finish import COMBAT_AGAIN, COMBAT_EXIT
from tasks.combat.assets.assets_combat_interact import DUNGEON_COMBAT_INTERACT from tasks.combat.assets.assets_combat_interact import DUNGEON_COMBAT_INTERACT
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 from tasks.combat.assets.assets_combat_team import COMBAT_TEAM_PREPARE, COMBAT_TEAM_SUPPORT
from tasks.combat.fuel import Fuel
from tasks.combat.interact import CombatInteract from tasks.combat.interact import CombatInteract
from tasks.combat.obtain import CombatObtain from tasks.combat.obtain import CombatObtain
from tasks.combat.prepare import CombatPrepare from tasks.combat.prepare import CombatPrepare
@ -17,7 +18,7 @@ from tasks.map.control.joystick import MapControlJoystick
class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSupport, CombatSkill, CombatObtain, class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSupport, CombatSkill, CombatObtain,
MapControlJoystick): MapControlJoystick, Fuel):
dungeon: DungeonList | None = None dungeon: DungeonList | None = None
is_doing_planner: bool = False is_doing_planner: bool = False
@ -53,8 +54,7 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
# Check limits # Check limits
if self.config.stored.TrailblazePower.value < self.combat_wave_cost: if self.config.stored.TrailblazePower.value < self.combat_wave_cost:
logger.info('Trailblaze power exhausted, cannot continue combat') return self._try_get_more_trablaize_power(self.config.stored.TrailblazePower.value, self.combat_wave_cost)
return False
if self.combat_waves <= 0: if self.combat_waves <= 0:
logger.info('Combat wave limited, cannot continue combat') logger.info('Combat wave limited, cannot continue combat')
return False return False
@ -221,8 +221,7 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
logger.info(f'Current has {current}, combat costs {self.combat_wave_cost}, can run again') logger.info(f'Current has {current}, combat costs {self.combat_wave_cost}, can run again')
return True return True
else: else:
logger.info(f'Current has {current}, combat costs {self.combat_wave_cost}, can not run again') return self._try_get_more_trablaize_power(current, self.combat_wave_cost * self.combat_waves)
return False
elif self.combat_wave_cost <= 0: elif self.combat_wave_cost <= 0:
logger.info(f'Free combat, combat costs {self.combat_wave_cost}, can not run again') logger.info(f'Free combat, combat costs {self.combat_wave_cost}, can not run again')
return False return False
@ -231,8 +230,25 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
logger.info(f'Current has {current}, combat costs {self.combat_wave_cost}, can run again') logger.info(f'Current has {current}, combat costs {self.combat_wave_cost}, can run again')
return True return True
else: else:
logger.info(f'Current has {current}, combat costs {self.combat_wave_cost}, can not run again') return self._try_get_more_trablaize_power(current, self.combat_wave_cost * self.combat_waves)
return False
def _try_get_more_trablaize_power(self, current, cost):
if self.config.TrailblazePower_ExtractReservedTrailblazePower:
logger.info('Extract reserved trailblaze power to get more trailblaze power')
if self.extract_reserved_trailblaze_power(current):
self.combat_get_trailblaze_power()
self.get_interval_timer(COMBAT_EXIT).wait()
if self.config.TrailblazePower_UseFuel:
logger.info('Use fuel to get more trailblaze power')
if self.use_fuel(current):
self.combat_get_trailblaze_power()
self.get_interval_timer(COMBAT_AGAIN).wait()
if current >= cost:
return True
else:
logger.info(f'Current has {current}, combat costs {self.combat_wave_cost}, can not run again')
return False
def _combat_should_reenter(self): def _combat_should_reenter(self):
""" """

209
tasks/combat/fuel.py Normal file
View File

@ -0,0 +1,209 @@
import module.config.server as server
from module.base.timer import Timer
from module.base.utils import area_offset, crop
from module.logger import logger
from module.ocr.ocr import Digit
from tasks.base.assets.assets_base_popup import GET_REWARD, POPUP_CANCEL, POPUP_CONFIRM
from tasks.base.ui import UI
from tasks.combat.assets.assets_combat_finish import COMBAT_AGAIN, COMBAT_EXIT
from tasks.combat.assets.assets_combat_fuel import *
from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE
from tasks.item.slider import Slider
class Fuel(UI):
fuel_trailblaze_power = 60
def _use_fuel_finish(self):
"""
Two possible finish states after using fuel/extract trailblaze power:
1. COMBAT_PREPARE
2. COMBAT_AGAIN
"""
if self.appear(COMBAT_AGAIN):
if self.image_color_count(COMBAT_AGAIN, color=(227, 227, 228), threshold=221, count=50):
logger.info(f'Use fuel finished at COMBAT_AGAIN')
return True
if self.appear(COMBAT_PREPARE):
if self.image_color_count(COMBAT_PREPARE.button, color=(230, 230, 230), threshold=240, count=400):
logger.info(f'Use fuel finished at COMBAT_AGAIN')
return True
return False
def _fuel_confirm(self, skip_first_screenshot=True):
"""
Pages:
in: fuel popup
out: _use_fuel_finish
"""
logger.info('Fuel confirm')
self.interval_clear([POPUP_CONFIRM, POPUP_CANCEL, GET_REWARD])
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self._use_fuel_finish():
break
if self.handle_popup_confirm():
continue
if self.handle_reward():
continue
self._fuel_wait_leave()
def _fuel_cancel(self, skip_first_screenshot=True):
"""
Pages:
in: fuel popup
out: _use_fuel_finish
"""
logger.info('Fuel cancel')
self.interval_clear([POPUP_CONFIRM, POPUP_CANCEL, GET_REWARD])
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self._use_fuel_finish():
break
if self.handle_popup_cancel():
continue
if self.handle_reward():
continue
self._fuel_wait_leave()
def _fuel_wait_leave(self):
# Blur disappears before popup
# so there's a short period of time that COMBAT_AGAIN is unclickable
# This is equivalent to poor sleep
timer = self.get_interval_timer(COMBAT_AGAIN, interval=5, renew=True)
timer.set_current(4.4)
timer = self.get_interval_timer(COMBAT_EXIT, interval=5, renew=True)
timer.set_current(4.4)
def extract_reserved_trailblaze_power(self, current, skip_first_screenshot=True):
"""
Extract reserved trailblaze power from previous combat.
Returns:
bool: If extracted
"""
logger.info('Extract reserved trailblaze power')
reserved = Digit(OCR_RESERVED_TRAILBLAZE_POWER).ocr_single_line(self.device.image)
if reserved <= 0:
logger.info('No reserved trailblaze power')
return False
self.interval_clear([POPUP_CONFIRM, POPUP_CANCEL, GET_REWARD])
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self.appear(POPUP_CONFIRM):
break
if self.appear_then_click(EXTRACT_RESERVED_TRAILBLAZE_POWER):
continue
if self.appear_then_click(RESERVED_TRAILBLAZE_POWER_ENTRANCE):
continue
count = min(reserved, self.config.stored.TrailblazePower.FIXED_TOTAL - current)
logger.info(f'Having {reserved} reserved, going to use {count}')
self.set_reserved_trailblaze_power(count, total=reserved)
self._fuel_confirm()
return True
def set_reserved_trailblaze_power(self, count, total):
slider = Slider(main=self, slider=RESERVED_SLIDER)
slider.set(count, total)
self.ui_ensure_index(
count, letter=Digit(OCR_EXTRACT_RESERVED_TRAILBLAZE_POWER_COUNT, lang=server.lang),
next_button=RESERVED_PLUS, prev_button=RESERVED_MINUS,
skip_first_screenshot=True
)
def set_fuel_count(self, count):
slider = Slider(main=self, slider=FUEL_SLIDER)
# Can only use 5 fuel at one time
slider.set(count, 5)
self.ui_ensure_index(
count, letter=Digit(OCR_FUEL_COUNT, lang=server.lang),
next_button=FUEL_PLUS, prev_button=FUEL_MINUS,
skip_first_screenshot=True
)
def use_fuel(self, current, skip_first_screenshot=True):
"""
Args:
current:
skip_first_screenshot:
Returns:
bool: If used
"""
limit = self.config.stored.TrailblazePower.FIXED_TOTAL
use = (limit - current) // self.fuel_trailblaze_power
if use == 0:
logger.info(f"Current trailblaze power is near {limit}, no need to use fuel")
return False
logger.info("Use Fuel")
timeout = Timer(1, count=3)
has_fuel = False
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self.appear(FUEL_SELECTED):
logger.info('Fuel selected')
break
if self.appear(POPUP_CONFIRM):
timeout.start()
if self.appear(FUEL_SELECTED) or self.appear(FUEL):
has_fuel = True
if not has_fuel and timeout.reached():
logger.info("No fuel found")
return False
if self.appear_then_click(FUEL):
has_fuel = True
continue
if not self.appear(POPUP_CONFIRM) and self.appear_then_click(FUEL_ENTRANCE):
continue
offset = FUEL_SELECTED.button_offset
image = crop(self.device.image, area_offset(OCR_FUEL.area, offset), copy=False)
count = Digit(OCR_FUEL).ocr_single_line(image, direct_ocr=True)
reserve = self.config.TrailblazePower_FuelReserve
available_count = max(count - reserve, 0)
use = min(use, available_count)
logger.info(f'Having {count} fuel, reserve {reserve} fuel, going to use {use} fuel')
if use <= 0:
logger.info("Fuel remain is under the reserve threshold, stop using fuel")
self._fuel_cancel()
skip_first_screenshot = True
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self.appear(USING_FUEL):
break
if self.appear(FUEL) and self.handle_popup_confirm():
continue
if self.appear(FUEL_SELECTED) and self.handle_popup_confirm():
continue
self.set_fuel_count(use)
self._fuel_confirm()
return True

View File

@ -24,6 +24,8 @@ class TrailblazePowerOcr(DigitCounter):
result = re.sub(r'[买米装:()]', '', result) result = re.sub(r'[买米装:()]', '', result)
# 61240 -> 6/240 # 61240 -> 6/240
result = re.sub(r'1240$', '/240', result) result = re.sub(r'1240$', '/240', result)
# 0*0/24 -> 0/240
result = re.sub(r'24$', '240', result)
return result return result

View File

@ -350,8 +350,8 @@ class DailyQuestUI(DungeonUI, RouteLoader):
else: else:
logger.info('Daily support cannot achieved, dungeon task is scheduled tomorrow') logger.info('Daily support cannot achieved, dungeon task is scheduled tomorrow')
if KEYWORDS_DAILY_QUEST.Consume_120_Trailblaze_Power in quests: if KEYWORDS_DAILY_QUEST.Consume_120_Trailblaze_Power in quests:
# 12h10min in advance, waiting for stamina # 6h in advance, waiting for stamina
if dungeon < reset - timedelta(hours=12, minutes=10): if dungeon < reset - timedelta(hours=6, minutes=0):
logger.info('Stamina consume can be achieved in the future') logger.info('Stamina consume can be achieved in the future')
future += 200 future += 200
else: else:

View File

@ -1,5 +1,8 @@
from datetime import timedelta
from module.base.decorator import set_cached_property from module.base.decorator import set_cached_property
from module.base.utils import area_offset from module.base.utils import area_offset
from module.config.stored.classes import now
from module.logger import logger from module.logger import logger
from tasks.battle_pass.keywords import KEYWORDS_BATTLE_PASS_QUEST from tasks.battle_pass.keywords import KEYWORDS_BATTLE_PASS_QUEST
from tasks.combat.combat import Combat from tasks.combat.combat import Combat
@ -121,6 +124,12 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat):
if KEYWORDS_DAILY_QUEST.Clear_Stagnant_Shadow_1_times in self.daily_quests: if KEYWORDS_DAILY_QUEST.Clear_Stagnant_Shadow_1_times in self.daily_quests:
logger.info('Achieve daily quest Clear_Stagnant_Shadow_1_times') logger.info('Achieve daily quest Clear_Stagnant_Shadow_1_times')
self.achieved_daily_quest = True self.achieved_daily_quest = True
if KEYWORDS_BATTLE_PASS_QUEST.Clear_Stagnant_Shadow_1_times in self.weekly_quests:
logger.info('Done weekly quest Clear_Stagnant_Shadow_1_times once')
self.config.stored.BattlePassQuestStagnantShadow.add()
if self.config.stored.BattlePassQuestStagnantShadow.is_full():
logger.info('Achieved weekly quest Clear_Stagnant_Shadow_1_times')
self.achieved_weekly_quest = True
# Cavern_of_Corrosion # Cavern_of_Corrosion
if dungeon.is_Cavern_of_Corrosion: if dungeon.is_Cavern_of_Corrosion:
if KEYWORDS_DAILY_QUEST.Clear_Cavern_of_Corrosion_1_times in self.daily_quests: if KEYWORDS_DAILY_QUEST.Clear_Cavern_of_Corrosion_1_times in self.daily_quests:
@ -222,6 +231,10 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat):
or self.config.stored.DungeonDouble.calyx > 0 or self.config.stored.DungeonDouble.calyx > 0
or self.config.stored.DungeonDouble.relic > 0 or self.config.stored.DungeonDouble.relic > 0
or self.config.stored.DungeonDouble.rogue > 0): or self.config.stored.DungeonDouble.rogue > 0):
update = self.config.stored.DungeonDouble.time
if update <= now() <= update + timedelta(seconds=5):
logger.info('Dungeon double just updated, skip')
return
logger.info('Get dungeon double remains') logger.info('Get dungeon double remains')
# UI switches # UI switches
switched = self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) switched = self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index)

View File

@ -93,6 +93,16 @@ class Slider:
logger.warning('Detected slider too short') logger.warning('Detected slider too short')
# self.main.device.image_save() # self.main.device.image_save()
def is_slider_arrive(self, detect):
"""
Args:
detect: Area to detect
Returns:
bool: If slider arrive detect area
"""
return self.main.image_color_count(detect, color=(255, 255, 255), threshold=235, count=50)
def set(self, value: int, total: int, skip_first_screenshot=True): def set(self, value: int, total: int, skip_first_screenshot=True):
""" """
Args: Args:
@ -158,7 +168,7 @@ class Slider:
if trial > 3: if trial > 3:
logger.warning('Slider.set failed after 3 trial') logger.warning('Slider.set failed after 3 trial')
return False return False
if self.main.image_color_count(detect, color=(255, 255, 255), threshold=221, count=50): if self.is_slider_arrive(detect):
logger.info('Slider set done') logger.info('Slider set done')
return True return True

View File

@ -78,6 +78,7 @@ class Ornament(OrnamentCombat):
if self.config.stored.DungeonDouble.calyx or self.config.stored.DungeonDouble.relic: if self.config.stored.DungeonDouble.calyx or self.config.stored.DungeonDouble.relic:
logger.info('During double calyx or relic event, delay Ornament') logger.info('During double calyx or relic event, delay Ornament')
future = self.config.cross_get('Dungeon.Scheduler.NextRun', default=DEFAULT_TIME) future = self.config.cross_get('Dungeon.Scheduler.NextRun', default=DEFAULT_TIME)
future = max(now(), future)
future = future + timedelta(minutes=1) future = future + timedelta(minutes=1)
with self.config.multi_set(): with self.config.multi_set():
self.config.task_delay(target=future) self.config.task_delay(target=future)