Skip to content

Commit 7ee1f4f

Browse files
authored
Merge pull request #269 from cc004/dev
2 parents ef71f4c + 661d5ca commit 7ee1f4f

21 files changed

Lines changed: 740 additions & 1699 deletions

autopcr/core/datamgr.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,14 @@ class datamgr(BaseModel, Component[apiclient]):
6060
cleared_byway_quest_id_set: Set[int] = set({})
6161
return_fes_info_list: List[ReturnFesInfo] = None
6262
data_time: int = 0
63-
version: int = 3
63+
version: int = 4
6464
caravan_dishes: typing.Counter[int] = Counter()
6565
user_clan_battle_ex_equip_restriction: Dict[int, RestrictionExtraEquip] = {}
6666
talent_quest_area_info: Dict[int, TalentQuestAreaInfo] = {}
6767
cleared_talent_quest_ids: Dict[int, int] = {}
6868
princess_knight_info: PrincessKnightInfo = None
69+
cleared_abyss_quests: Set[int] = set()
70+
abyss_quest_info: Dict[int, AbyssDailyClearCountList] = {}
6971

7072
@staticmethod
7173
async def try_update_database(ver: int):
@@ -587,7 +589,7 @@ def get_not_enough_item(self, demand: typing.Counter[ItemType]) -> typing.Counte
587589
return bad
588590

589591
def get_unit_power(self, unit_id: int) -> int:
590-
power = db.calc_unit_power(self.unit[unit_id], set(self.read_story_ids))
592+
power = db.calc_unit_power(self.unit[unit_id], set(self.read_story_ids), self.ex_equips)
591593
return int(power + 0.5)
592594

593595
def is_quest_cleared(self, quest: int) -> bool:

autopcr/core/pcrclient.py

Lines changed: 81 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,18 @@ async def read_story(self, story_id: int):
732732
await self.story_check(story_id)
733733
return await self.story_view(story_id)
734734

735+
async def tpr_register_success(self, panel_id: int, correct_type: int, parts_id_list: List[int]):
736+
req = SubStoryTprRegisterSuccessRequest()
737+
req.panel_id = panel_id
738+
req.correct_type = correct_type
739+
req.parts_id_list = parts_id_list
740+
return await self.request(req)
741+
742+
async def read_tpr_story(self, sub_story_id: int):
743+
req = SubStoryTprReadStoryRequest()
744+
req.sub_story_id = sub_story_id
745+
return await self.request(req)
746+
735747
async def apg_story_top(self):
736748
req = SubStoryApgTopRequest()
737749
return await self.request(req)
@@ -1135,6 +1147,30 @@ async def training_quest_skip(self, quest: int, times: int):
11351147
req.random_count = times
11361148
return await self.request(req)
11371149

1150+
async def abyss_top(self, abyss_id: int):
1151+
req = AbyssTopRequest()
1152+
req.abyss_id = abyss_id
1153+
req.is_first = 1
1154+
return await self.request(req)
1155+
1156+
async def abyss_boss_skip(self, abyss_id: int, boss_id: int, enemy_index: int, exec_skip_num: int, current_boss_ticket_num: int):
1157+
req = AbyssBossSkipRequest()
1158+
req.abyss_id = abyss_id
1159+
req.boss_id = boss_id
1160+
req.enemy_index = enemy_index
1161+
req.exec_skip_num = exec_skip_num
1162+
req.current_skip_ticket_num = self.data.get_inventory((eInventoryType.Item, 23001))
1163+
req.current_boss_ticket_num = current_boss_ticket_num
1164+
return await self.request(req)
1165+
1166+
async def abyss_quest_skip(self, quest_id: int, times: int):
1167+
req = AbyssQuestSkipMultipleRequest()
1168+
req.abyss_id = db.quest_info[quest_id].abyss_id
1169+
req.skip_list = [QuestSkipInfo(quest_id=quest_id, skip_count=times)]
1170+
req.current_ticket_num = self.data.get_inventory((eInventoryType.Item, 23001))
1171+
req.exec_type = 1 # for single 2 for multiple
1172+
return await self.request(req)
1173+
11381174
async def talent_quest_skip(self, quest_id: int, use_ticket_num: int):
11391175
req = TalentQuestSkipRequest()
11401176
req.quest_id = quest_id
@@ -1383,7 +1419,7 @@ async def unlock_quest_id(self, quest: int):
13831419
(quest in db.tower_quest and self.data.tower_status and self.data.tower_status.cleared_floor_num >= db.tower_quest[quest].floor_num)
13841420
)
13851421

1386-
async def quest_skip_aware(self, quest: int, times: int, recover: bool = False, is_total: bool = False):
1422+
async def quest_skip_aware(self, quest: int, times: int, recover: bool = False, is_total: bool = False) -> Tuple[List[InventoryInfo], int, bool]:
13871423
name = db.get_quest_name(quest)
13881424
if db.is_hatsune_quest(quest):
13891425
if not quest in db.quest_to_event:
@@ -1407,6 +1443,14 @@ async def quest_skip_aware(self, quest: int, times: int, recover: bool = False,
14071443
daily_clear_count = 0,
14081444
daily_recovery_count = 0,
14091445
))
1446+
elif db.is_abyss_quest(quest):
1447+
if quest not in self.data.cleared_abyss_quests:
1448+
raise AbortError(f"任务{name}未通关或不存在")
1449+
qinfo = self.data.abyss_quest_info.get(quest, AbyssDailyClearCountList(
1450+
quest_id = quest,
1451+
daily_clear_count = 0,
1452+
))
1453+
qinfo.__dict__['daily_recovery_count'] = 0
14101454
else:
14111455
if not quest in self.data.quest_dict:
14121456
raise AbortError(f"任务{name}未通关或不存在")
@@ -1418,26 +1462,47 @@ async def quest_skip_aware(self, quest: int, times: int, recover: bool = False,
14181462
info = db.quest_info[quest]
14191463
if db.is_talent_quest(quest): # fix
14201464
setattr(info, 'daily_limit', self.data.settings.talent_quest.daily_clear_limit_count)
1465+
elif db.is_abyss_quest(quest):
1466+
setattr(info, 'daily_limit', self.data.settings.abyss.daily_clear_limit_count)
14211467

14221468
stamina_coefficient = self.data.get_quest_stamina_half_campaign_times(quest)
14231469
if not stamina_coefficient: stamina_coefficient = 100
14241470
result: List[InventoryInfo] = []
1425-
async def skip(times):
1471+
clear_count = 0
1472+
async def skip(times) -> Tuple[bool, List[InventoryInfo]]:
14261473
while self.data.stamina < int(math.floor((info.stamina * (stamina_coefficient / 100)))) * times:
14271474
if self.stamina_recover_cnt > self.data.recover_stamina_exec_count:
14281475
await self.recover_stamina()
14291476
else:
1430-
raise AbortError(f"任务{name}体力不足")
1477+
return True, []
14311478
if db.is_shiori_quest(quest):
14321479
event = db.quest_to_event[quest].event_id
1433-
return await self.shiori_quest_skip(event, quest, times)
1480+
resp = await self.shiori_quest_skip(event, quest, times)
14341481
elif db.is_hatsune_quest(quest):
14351482
event = db.quest_to_event[quest].event_id
1436-
return await self.hatsune_quest_skip(event, quest, times)
1483+
resp = await self.hatsune_quest_skip(event, quest, times)
14371484
elif db.is_talent_quest(quest):
1438-
return await self.talent_quest_skip(quest, times)
1485+
resp = await self.talent_quest_skip(quest, times)
1486+
elif db.is_abyss_quest(quest):
1487+
resp = await self.abyss_quest_skip(quest, times)
14391488
else:
1440-
return await self.quest_skip(quest, times)
1489+
resp = await self.quest_skip(quest, times)
1490+
1491+
nonlocal clear_count
1492+
clear_count += times
1493+
result = []
1494+
if resp.quest_result_list:
1495+
for result_list in resp.quest_result_list:
1496+
if hasattr(result_list, 'quest_result'):
1497+
for quest_result in result_list.quest_result:
1498+
result = result + quest_result.reward_list
1499+
else:
1500+
result = result + result_list.reward_list
1501+
if resp.bonus_reward_list:
1502+
result = result + resp.bonus_reward_list
1503+
return False, result
1504+
1505+
no_stamina = False
14411506
if info.daily_limit:
14421507
if is_total:
14431508
times -= qinfo.daily_clear_count
@@ -1454,24 +1519,19 @@ async def skip(times):
14541519
await self.recover_challenge(quest)
14551520
remain = info.daily_limit
14561521
t = min(times, remain)
1457-
resp = await skip(t)
1458-
if resp.quest_result_list:
1459-
for result_list in resp.quest_result_list:
1460-
result = result + result_list.reward_list
1461-
if resp.bonus_reward_list:
1462-
result = result + resp.bonus_reward_list
1463-
1522+
no_stamina, resp = await skip(t)
1523+
if no_stamina:
1524+
break
1525+
1526+
result = result + resp
1527+
14641528
times -= t
14651529
remain -= t
14661530
else:
1467-
resp = await skip(times)
1468-
if resp.quest_result_list:
1469-
for result_list in resp.quest_result_list:
1470-
result = result + result_list.reward_list
1471-
if resp.bonus_reward_list:
1472-
result = result + resp.bonus_reward_list
1531+
no_stamina, resp = await skip(times)
1532+
result = result + resp
14731533

1474-
return result
1534+
return result, clear_count, no_stamina
14751535

14761536
async def refresh(self):
14771537
req = HomeIndexRequest()

autopcr/db/database.py

Lines changed: 89 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from typing import List, Dict, Set, Tuple, Union
22
import typing
33
from ..model.enums import eCampaignCategory
4-
from ..model.common import UnitData, eInventoryType, RoomUserItem, InventoryInfo
5-
from ..model.custom import ItemType
4+
from ..model.common import ExtraEquipInfo, UnitData, eInventoryType, RoomUserItem, InventoryInfo
5+
from ..model.custom import ItemType, eDifficulty
66
import datetime
77
from collections import Counter, defaultdict
88
from .dbmgr import dbmgr
@@ -14,6 +14,7 @@
1414
from ..core.apiclient import apiclient
1515
from typing import TypeVar, Generic
1616
from ..util.pcr_data import CHARA_NICKNAME
17+
from ..util.logger import instance as logger
1718

1819
T = TypeVar("T")
1920

@@ -664,9 +665,27 @@ def quest_info(self) -> Dict[int, QuestDatum]:
664665
.concat(HatsuneQuest.query(db))
665666
.concat(ShioriQuest.query(db))
666667
.concat(TalentQuestDatum.query(db))
668+
.concat(AbyssQuestDatum.query(db))
667669
.to_dict(lambda x: x.quest_id, lambda x: x)
668670
)
669671

672+
@lazy_property
673+
def abyss_quest_info(self) -> Dict[int, List[AbyssQuestDatum]]:
674+
with self.dbmgr.session() as db:
675+
return (
676+
AbyssQuestDatum.query(db)
677+
.group_by(lambda x: x.abyss_id)
678+
.to_dict(lambda x: x.key, lambda x: x.to_list())
679+
)
680+
681+
@lazy_property
682+
def abyss_boss_data(self) -> Dict[int, AbyssBossDatum]:
683+
with self.dbmgr.session() as db:
684+
return (
685+
AbyssBossDatum.query(db)
686+
.to_dict(lambda x: x.boss_id, lambda x: x)
687+
)
688+
670689
@lazy_property
671690
def chara_story_status(self) -> Dict[int, CharaStoryStatus]:
672691
with self.dbmgr.session() as db:
@@ -1070,6 +1089,22 @@ def colosseum_schedule_data(self) -> Dict[int, ColosseumScheduleDatum]:
10701089
.to_dict(lambda x: x.schedule_id, lambda x: x)
10711090
)
10721091

1092+
@lazy_property
1093+
def dome_schedule_data(self) -> Dict[int, DomeScheduleDatum]:
1094+
with self.dbmgr.session() as db:
1095+
return (
1096+
DomeScheduleDatum.query(db)
1097+
.to_dict(lambda x: x.schedule_id, lambda x: x)
1098+
)
1099+
1100+
@lazy_property
1101+
def abyss_schedule(self) -> Dict[int, AbyssSchedule]:
1102+
with self.dbmgr.session() as db:
1103+
return (
1104+
AbyssSchedule.query(db)
1105+
.to_dict(lambda x: x.abyss_id, lambda x: x)
1106+
)
1107+
10731108
@lazy_property
10741109
def tower_schedule(self) -> Dict[int, TowerSchedule]:
10751110
with self.dbmgr.session() as db:
@@ -1228,6 +1263,22 @@ def hatsune_item(self) -> Dict[int, HatsuneItem]:
12281263
.to_dict(lambda x: x.event_id, lambda x: x)
12291264
)
12301265

1266+
@lazy_property
1267+
def tpr_story_data(self) -> Dict[int, TprStoryDatum]:
1268+
with self.dbmgr.session() as db:
1269+
return (
1270+
TprStoryDatum.query(db)
1271+
.to_dict(lambda x: x.sub_story_id, lambda x: x)
1272+
)
1273+
1274+
@lazy_property
1275+
def tpr_panel_data(self) -> Dict[int, TprPanelDatum]:
1276+
with self.dbmgr.session() as db:
1277+
return (
1278+
TprPanelDatum.query(db)
1279+
.to_dict(lambda x: x.panel_id, lambda x: x)
1280+
)
1281+
12311282
@lazy_property
12321283
def apg_story_data(self) -> Dict[int, ApgStoryDatum]:
12331284
with self.dbmgr.session() as db:
@@ -1516,6 +1567,9 @@ def quest_name(self) -> Dict[int, str]:
15161567
ret.update(
15171568
{x.travel_quest_id :x.travel_quest_name for x in self.travel_quest_data.values()}
15181569
)
1570+
ret.update(
1571+
{x.quest_id: f"{x.quest_name}-{eDifficulty(x.difficulty).name}" for xs in self.abyss_quest_info.values() for x in xs}
1572+
)
15191573
return ret
15201574

15211575
@lazy_property
@@ -1675,9 +1729,9 @@ def get_inventory_name_san(self, item: ItemType) -> str:
16751729
except:
16761730
return f"未知物品({item[0]}, {item[1]})"
16771731

1678-
def get_ex_equip_name(self, item: int, rank: int = 0) -> str:
1732+
def get_ex_equip_name(self, item: int, rank: int = -1) -> str:
16791733
try:
1680-
return f"{self.ex_rarity_name[self.ex_equipment_data[item].rarity]}{rank}-" + self.inventory_name[(eInventoryType.ExtraEquip, item)]
1734+
return f"{self.ex_rarity_name[self.ex_equipment_data[item].rarity]}{rank if rank != -1 else ''}-" + self.inventory_name[(eInventoryType.ExtraEquip, item)]
16811735
except:
16821736
return f"未知ex装备({item})"
16831737

@@ -1791,6 +1845,9 @@ def is_talent_quest(self, quest_id: int) -> bool:
17911845
top = quest_id // 1000000
17921846
return top >= 81 and top <= 85
17931847

1848+
def is_abyss_quest(self, quest_id: int) -> bool:
1849+
return quest_id // 1000000 == 92
1850+
17941851
def is_hatsune_normal_quest(self, quest_id: int) -> bool:
17951852
return self.is_hatsune_quest(quest_id) and (quest_id // 100) % 10 == 1
17961853

@@ -1878,6 +1935,17 @@ def get_open_hatsune(self) -> List[HatsuneSchedule]:
18781935
.where(lambda x: now >= self.parse_time(x.start_time) and now <= self.parse_time(x.close_time)) \
18791936
.to_list()
18801937

1938+
def get_active_abyss(self) -> List[AbyssSchedule]:
1939+
now = apiclient.datetime
1940+
return flow(self.abyss_schedule.values()) \
1941+
.where(lambda x: now >= self.parse_time(x.start_time) and now <= self.parse_time(x.end_time)) \
1942+
.to_list()
1943+
1944+
def get_abyss_bosses(self, abyss_id: int) -> List[AbyssBossDatum]:
1945+
return flow(self.abyss_boss_data.values()) \
1946+
.where(lambda x: x.abyss_id == abyss_id) \
1947+
.to_list()
1948+
18811949
def get_active_seasonpass(self) -> List[SeasonpassFoundation]:
18821950
now = apiclient.datetime
18831951
return flow(self.seasonpass_foundation.values()) \
@@ -2301,7 +2369,7 @@ def get_gacha_prize_name(self, gacha_id: int, prize_rarity: int) -> str:
23012369
def is_unit_rank_bonus(self, unit_id: int, promotion_level: int) -> bool:
23022370
return unit_id in self.promote_bonus and promotion_level in self.promote_bonus[unit_id]
23032371

2304-
def calc_unit_attribute(self, unit_data: UnitData, read_story: Set[int]) -> UnitAttribute:
2372+
def calc_unit_attribute(self, unit_data: UnitData, read_story: Set[int], ex_equips: Dict[int, ExtraEquipInfo]) -> UnitAttribute:
23052373
unit_id = unit_data.id
23062374
promotion_level = unit_data.promotion_level.value
23072375
rarity = unit_data.battle_rarity if unit_data.battle_rarity else unit_data.unit_rarity
@@ -2342,10 +2410,22 @@ def calc_unit_attribute(self, unit_data: UnitData, read_story: Set[int]) -> Unit
23422410
kizuna_attribute += story.get_unit_attribute()
23432411

23442412
unit_attribute = base_attribute.round() + rb_attribute.round() + equip_attribute.round() + unique_equip_attribute.ceil() + kizuna_attribute.round()
2413+
2414+
# EX装备
2415+
ex_attribute = UnitAttribute()
2416+
for ex_equip in unit_data.ex_equip_slot:
2417+
if ex_equip.serial_id:
2418+
ex_equip_data = ex_equips[ex_equip.serial_id]
2419+
star = self.get_ex_equip_star_from_pt(ex_equip_data.ex_equipment_id, ex_equip_data.enhancement_pt)
2420+
attr = self.ex_equipment_data[ex_equip_data.ex_equipment_id].get_unit_attribute(star)
2421+
bonus = unit_attribute.ex_equipment_mul(attr).ceil()
2422+
ex_attribute += bonus
2423+
unit_attribute += ex_attribute
2424+
23452425
return unit_attribute
23462426

2347-
def calc_unit_attribute_power(self, unit_data: UnitData, read_story: Set[int], coefficient: UnitStatusCoefficient) -> float:
2348-
unit_attribute = self.calc_unit_attribute(unit_data, read_story)
2427+
def calc_unit_attribute_power(self, unit_data: UnitData, read_story: Set[int], ex_equips: Dict[int, ExtraEquipInfo], coefficient: UnitStatusCoefficient) -> float:
2428+
unit_attribute = self.calc_unit_attribute(unit_data, read_story, ex_equips)
23492429
return unit_attribute.get_power(coefficient)
23502430

23512431
def calc_skill_power(self, unit_data: UnitData, coefficient: UnitStatusCoefficient) -> float:
@@ -2374,9 +2454,9 @@ def calc_skill_power(self, unit_data: UnitData, coefficient: UnitStatusCoefficie
23742454

23752455
return skill_power * coefficient.skill_lv_coefficient
23762456

2377-
def calc_unit_power(self, unit_data: UnitData, read_story: Set[int]) -> float:
2457+
def calc_unit_power(self, unit_data: UnitData, read_story: Set[int], ex_equips: Dict[int, ExtraEquipInfo]) -> float:
23782458
coefficient = self.unit_status_coefficient[1]
2379-
attribute_power = self.calc_unit_attribute_power(unit_data, read_story, coefficient)
2459+
attribute_power = self.calc_unit_attribute_power(unit_data, read_story, ex_equips, coefficient)
23802460
skill_power = self.calc_skill_power(unit_data, coefficient)
23812461
return attribute_power + skill_power
23822462

0 commit comments

Comments
 (0)