mirror of
https://gitea.tendokyu.moe/Hay1tsme/artemis.git
synced 2026-02-04 14:47:29 +08:00
chuni: fix map area/unlock challenge conditions (#237)
- Document all map area/unlock challenge condition IDs - Add conditions for missing secret maps in LUMINOUS PLUS/VERSE Reviewed-on: https://gitea.tendokyu.moe/Hay1tsme/artemis/pulls/237 Reviewed-by: Dniel97 <dniel97@noreply.gitea.tendokyu.moe> Co-authored-by: beerpsi <beerpsi@duck.com> Co-committed-by: beerpsi <beerpsi@duck.com>
This commit is contained in:
@@ -112,30 +112,138 @@ class ChuniConstants:
|
||||
return cls.VERSION_LUT.get(str(floor_to_nearest_005(ver)), None)
|
||||
|
||||
class MapAreaConditionType(IntEnum):
|
||||
"""Condition types for the GetGameMapAreaConditionApi endpoint. Incomplete.
|
||||
"""
|
||||
Condition IDs for the `GetGameMapAreaConditionApi` and `GetGameUCConditionApi` requests.
|
||||
|
||||
For the MAP_CLEARED/MAP_AREA_CLEARED/TROPHY_OBTAINED conditions, the conditionId
|
||||
is the map/map area/trophy.
|
||||
|
||||
For the RANK_*/ALL_JUSTICE conditions, the conditionId is songId * 100 + difficultyId.
|
||||
For example, Halcyon [ULTIMA] would be 173 * 100 + 4 = 17304.
|
||||
- "Item" or "locked item" refers to the map area, unlock challenge or
|
||||
Linked VERSE locked using this system.
|
||||
- "Chart ID" refers to musicID \\* 100 + difficulty, where difficulty is 0 for BASIC
|
||||
up to 6 for WORLD'S END. For example, Halcyon ULTIMA is 17305.
|
||||
"""
|
||||
|
||||
INVALID = 0
|
||||
"""
|
||||
Invalid condition type. Should cause the hidden item to be automatically unlocked,
|
||||
but seemingly only works with map areas.
|
||||
"""
|
||||
|
||||
ALWAYS_UNLOCKED = 0
|
||||
|
||||
MAP_CLEARED = 1
|
||||
"""Finish the map with ID `conditionId`."""
|
||||
|
||||
MAP_AREA_CLEARED = 2
|
||||
|
||||
"""Finish the map area with ID `conditionId`."""
|
||||
|
||||
TROPHY_OBTAINED = 3
|
||||
"""Unlock the trophy with ID `conditionId`."""
|
||||
|
||||
TROPHY_EQUIPPED = 4
|
||||
"""
|
||||
Equip the trophy with ID `conditionId`. The item is locked again when the trophy is
|
||||
unequipped.
|
||||
"""
|
||||
|
||||
NAMEPLATE_OBTAINED = 5
|
||||
"""Unlock the nameplate with ID `conditionId`."""
|
||||
|
||||
NAMEPLATE_EQUIPPED = 6
|
||||
"""
|
||||
Equip the nameplate with ID `conditionId`. The item is locked again when the nameplate
|
||||
is unequipped.
|
||||
"""
|
||||
|
||||
CHARACTER_OBTAINED = 7
|
||||
"""Unlock the character with ID `conditionId`."""
|
||||
|
||||
CHARACTER_EQUIPPED = 8
|
||||
"""
|
||||
Equip the character with ID `conditionId`. The item is locked again when the character
|
||||
is unequipped.
|
||||
"""
|
||||
|
||||
CHARACTER_TRANSFORM_EQUIPPED = 9
|
||||
"""
|
||||
Equip the character, with the character transform ID `conditionId`. The item is locked again
|
||||
if the incorrect character is equipped, or the correct character is equipped with the wrong
|
||||
transform.
|
||||
"""
|
||||
|
||||
MUSIC_OBTAINED = 10
|
||||
"""Unlock the music with ID `conditionId`."""
|
||||
|
||||
AVATAR_ACCESSORY_OBTAINED = 11
|
||||
"""Unlock the avatar accessory with ID `conditionId`."""
|
||||
|
||||
AVATAR_ACCESSORY_EQUIPPED = 12
|
||||
"""
|
||||
Equip the avatar accessory with ID `conditionId`. The item is locked again when the avatar
|
||||
accessory is unequipped.
|
||||
"""
|
||||
|
||||
MAP_ICON_OBTAINED = 13
|
||||
"""Unlock the map icon with ID `conditionId`."""
|
||||
|
||||
MAP_ICON_EQUIPPED = 14
|
||||
"""
|
||||
Equip the map icon with ID `conditionId`. The item is locked again when the map icon is
|
||||
unequipped.
|
||||
"""
|
||||
|
||||
SYSTEM_VOICE_OBTAINED = 15
|
||||
"""Unlock the system voice with ID `conditionId`."""
|
||||
|
||||
SYSTEM_VOICE_EQUIPPED = 16
|
||||
"""
|
||||
Equip the system voice with ID `conditionId`. The item is locked again when the system voice
|
||||
is unequipped.
|
||||
"""
|
||||
|
||||
ALL_JUSTICE_CRITICAL = 17
|
||||
"""Obtain ALL JUSTICE CRITICAL on the chart given by `conditionId`."""
|
||||
|
||||
RANK_SSSP = 18
|
||||
"""Obtain rank SSS+ on the chart given by `conditionId`."""
|
||||
|
||||
RANK_SSS = 19
|
||||
"""Obtain rank SSS on the chart given by `conditionId`."""
|
||||
|
||||
RANK_SSP = 20
|
||||
"""Obtain rank SS+ on the chart given by `conditionId`."""
|
||||
|
||||
RANK_SS = 21
|
||||
"""Obtain rank SS on the chart given by `conditionId`."""
|
||||
|
||||
RANK_SP = 22
|
||||
"""Obtain rank S+ on the chart given by `conditionId`."""
|
||||
|
||||
RANK_S = 23
|
||||
"""Obtain rank S on the chart given by `conditionId`."""
|
||||
|
||||
RANK_AAA = 24
|
||||
"""Obtain rank AAA on the chart given by `conditionId`."""
|
||||
|
||||
RANK_AA = 25
|
||||
"""Obtain rank AA on the chart given by `conditionId`."""
|
||||
|
||||
RANK_A = 26
|
||||
"""Obtain rank A on the chart given by `conditionId`."""
|
||||
|
||||
MINIMUM_BEST_30_AVERAGE = 27
|
||||
"""Obtain a best 30 average of at least `conditionId / 100`."""
|
||||
|
||||
ALL_JUSTICE = 28
|
||||
"""Obtain ALL JUSTICE on the chart given by `conditionId`."""
|
||||
|
||||
FULL_COMBO = 29
|
||||
"""Obtain FULL COMBO on the chart given by `conditionId`."""
|
||||
|
||||
UNLOCK_CHALLENGE_DISCOVERED = 30
|
||||
"""Discover/unlock the unlock challenge with ID `conditionId`."""
|
||||
|
||||
UNLOCK_CHALLENGE_CLEARED = 31
|
||||
"""Clear the unlock challenge with ID `conditionId`."""
|
||||
|
||||
MINIMUM_RATING = 32
|
||||
"""Obtain a rating of at least `conditionId / 100`."""
|
||||
|
||||
|
||||
class MapAreaConditionLogicalOperator(Enum):
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
from datetime import timedelta
|
||||
from typing import Dict
|
||||
|
||||
from sqlalchemy.engine import Row
|
||||
|
||||
from core.config import CoreConfig
|
||||
from titles.chuni.config import ChuniConfig
|
||||
from titles.chuni.const import (
|
||||
@@ -11,6 +13,73 @@ from titles.chuni.const import (
|
||||
from titles.chuni.sunplus import ChuniSunPlus
|
||||
|
||||
|
||||
class MysticAreaConditions:
|
||||
"""The "Mystic Rainbow of <VERSION>" map is a special reward map for obtaining
|
||||
rainbow statues. There's one gold statue area that's unlocked when at least one
|
||||
original map is finished, and additional rainbow statue areas are added as new
|
||||
original maps are added.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, events_by_id: dict[int, Row], map_area_1_id: int, date_time_format: str
|
||||
):
|
||||
self.events_by_id = events_by_id
|
||||
self.date_time_format = date_time_format
|
||||
|
||||
self._map_area_1_conditions = {
|
||||
"mapAreaId": map_area_1_id,
|
||||
"length": 0,
|
||||
"mapAreaConditionList": [],
|
||||
}
|
||||
self._map_area_1_added = False
|
||||
self._conditions = []
|
||||
|
||||
@property
|
||||
def conditions(self):
|
||||
return self._conditions
|
||||
|
||||
def add_condition(
|
||||
self, map_flag_event_id: int, condition_map_id: int, mystic_map_area_id: int
|
||||
):
|
||||
if (event := self.events_by_id.get(map_flag_event_id)) is None:
|
||||
return
|
||||
|
||||
start_date = event["startDate"].strftime(self.date_time_format)
|
||||
|
||||
self._map_area_1_conditions["mapAreaConditionList"].append(
|
||||
{
|
||||
"type": MapAreaConditionType.MAP_CLEARED.value,
|
||||
"conditionId": condition_map_id,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.OR.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00",
|
||||
}
|
||||
)
|
||||
self._map_area_1_conditions["length"] = len(
|
||||
self._map_area_1_conditions["mapAreaConditionList"]
|
||||
)
|
||||
|
||||
if not self._map_area_1_added:
|
||||
self._conditions.append(self._map_area_1_conditions)
|
||||
self._map_area_1_added = True
|
||||
|
||||
self._conditions.append(
|
||||
{
|
||||
"mapAreaId": mystic_map_area_id,
|
||||
"length": 1,
|
||||
"mapAreaConditionList": [
|
||||
{
|
||||
"type": MapAreaConditionType.MAP_CLEARED.value,
|
||||
"conditionId": condition_map_id,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.AND.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00",
|
||||
}
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class ChuniLuminous(ChuniSunPlus):
|
||||
def __init__(self, core_cfg: CoreConfig, game_cfg: ChuniConfig) -> None:
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
@@ -77,18 +146,18 @@ class ChuniLuminous(ChuniSunPlus):
|
||||
async def handle_get_game_map_area_condition_api_request(self, data: Dict) -> Dict:
|
||||
# There is no game data for this, everything is server side.
|
||||
# However, we can selectively show/hide events as data is imported into the server.
|
||||
events = await self.data.static.get_enabled_events(self.version)
|
||||
events = await self.data.static.get_enabled_events(self.version) or []
|
||||
event_by_id = {evt["eventId"]: evt for evt in events}
|
||||
conditions = []
|
||||
|
||||
# The Mystic Rainbow of LUMINOUS map unlocks when any mainline LUMINOUS area
|
||||
# (ep. I, ep. II, ep. III) are completed.
|
||||
mystic_area_1_conditions = {
|
||||
"mapAreaId": 3229301, # Mystic Rainbow of LUMINOUS Area 1
|
||||
"length": 0,
|
||||
"mapAreaConditionList": [],
|
||||
}
|
||||
mystic_area_1_added = False
|
||||
mystic_conditions = MysticAreaConditions(
|
||||
event_by_id, 3229301, self.date_time_format
|
||||
)
|
||||
mystic_conditions.add_condition(14005, 3020701, 3229302)
|
||||
mystic_conditions.add_condition(14251, 3020702, 3229303)
|
||||
mystic_conditions.add_condition(14481, 3020703, 3229304)
|
||||
|
||||
conditions += mystic_conditions.conditions
|
||||
|
||||
# Secret AREA: MUSIC GAME
|
||||
if 14029 in event_by_id:
|
||||
@@ -229,114 +298,6 @@ class ChuniLuminous(ChuniSunPlus):
|
||||
]
|
||||
)
|
||||
|
||||
# LUMINOUS ep. I
|
||||
if 14005 in event_by_id:
|
||||
start_date = event_by_id[14005]["startDate"].strftime(self.date_time_format)
|
||||
|
||||
if not mystic_area_1_added:
|
||||
conditions.append(mystic_area_1_conditions)
|
||||
mystic_area_1_added = True
|
||||
|
||||
mystic_area_1_conditions["length"] += 1
|
||||
mystic_area_1_conditions["mapAreaConditionList"].append(
|
||||
{
|
||||
"type": MapAreaConditionType.MAP_CLEARED.value,
|
||||
"conditionId": 3020701,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.OR.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00.0",
|
||||
}
|
||||
)
|
||||
|
||||
conditions.append(
|
||||
{
|
||||
"mapAreaId": 3229302, # Mystic Rainbow of LUMINOUS Area 2,
|
||||
"length": 1,
|
||||
# Unlocks when LUMINOUS ep. I is completed.
|
||||
"mapAreaConditionList": [
|
||||
{
|
||||
"type": MapAreaConditionType.MAP_CLEARED.value,
|
||||
"conditionId": 3020701,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.AND.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00.0",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
# LUMINOUS ep. II
|
||||
if 14251 in event_by_id:
|
||||
start_date = event_by_id[14251]["startDate"].strftime(self.date_time_format)
|
||||
|
||||
if not mystic_area_1_added:
|
||||
conditions.append(mystic_area_1_conditions)
|
||||
mystic_area_1_added = True
|
||||
|
||||
mystic_area_1_conditions["length"] += 1
|
||||
mystic_area_1_conditions["mapAreaConditionList"].append(
|
||||
{
|
||||
"type": MapAreaConditionType.MAP_CLEARED.value,
|
||||
"conditionId": 3020702,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.OR.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00.0",
|
||||
}
|
||||
)
|
||||
|
||||
conditions.append(
|
||||
{
|
||||
"mapAreaId": 3229303, # Mystic Rainbow of LUMINOUS Area 3,
|
||||
"length": 1,
|
||||
# Unlocks when LUMINOUS ep. II is completed.
|
||||
"mapAreaConditionList": [
|
||||
{
|
||||
"type": MapAreaConditionType.MAP_CLEARED.value,
|
||||
"conditionId": 3020702,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.AND.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00.0",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
# LUMINOUS ep. III
|
||||
if 14481 in event_by_id:
|
||||
start_date = event_by_id[14481]["startDate"].strftime(self.date_time_format)
|
||||
|
||||
if not mystic_area_1_added:
|
||||
conditions.append(mystic_area_1_conditions)
|
||||
mystic_area_1_added = True
|
||||
|
||||
mystic_area_1_conditions["length"] += 1
|
||||
mystic_area_1_conditions["mapAreaConditionList"].append(
|
||||
{
|
||||
"type": MapAreaConditionType.MAP_CLEARED.value,
|
||||
"conditionId": 3020703,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.OR.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00.0",
|
||||
}
|
||||
)
|
||||
|
||||
conditions.append(
|
||||
{
|
||||
"mapAreaId": 3229304, # Mystic Rainbow of LUMINOUS Area 4,
|
||||
"length": 1,
|
||||
# Unlocks when LUMINOUS ep. III is completed.
|
||||
"mapAreaConditionList": [
|
||||
{
|
||||
"type": MapAreaConditionType.MAP_CLEARED.value,
|
||||
"conditionId": 3020703,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.AND.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00.0",
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
# 1UM1N0U5 ep. 111
|
||||
if 14483 in event_by_id:
|
||||
start_date = event_by_id[14483]["startDate"].replace(
|
||||
@@ -381,14 +342,14 @@ class ChuniLuminous(ChuniSunPlus):
|
||||
MapAreaConditionType.RANK_SSP.value,
|
||||
MapAreaConditionType.RANK_SP.value,
|
||||
MapAreaConditionType.RANK_S.value,
|
||||
MapAreaConditionType.ALWAYS_UNLOCKED.value,
|
||||
MapAreaConditionType.INVALID.value,
|
||||
]
|
||||
):
|
||||
start = (start_date + timedelta(days=14 * (i + 1))).strftime(
|
||||
self.date_time_format
|
||||
)
|
||||
|
||||
if typ != MapAreaConditionType.ALWAYS_UNLOCKED.value:
|
||||
if typ != MapAreaConditionType.INVALID.value:
|
||||
end = (
|
||||
start_date + timedelta(days=14 * (i + 2)) - timedelta(seconds=1)
|
||||
).strftime(self.date_time_format)
|
||||
@@ -407,7 +368,7 @@ class ChuniLuminous(ChuniSunPlus):
|
||||
)
|
||||
else:
|
||||
end = "2099-12-31 00:00:00"
|
||||
|
||||
|
||||
title_conditions.append(
|
||||
{
|
||||
"type": typ,
|
||||
@@ -431,7 +392,7 @@ class ChuniLuminous(ChuniSunPlus):
|
||||
# Ultimate Force
|
||||
# For the first 14 days, the condition is to obtain all 9 "Key of ..." titles
|
||||
# Afterwards, the condition is the 6 "Key of ..." titles that you can obtain
|
||||
# by playing the 6 areas, as well as obtaining specific ranks on
|
||||
# by playing the 6 areas, as well as obtaining specific ranks on
|
||||
# [CRYSTAL_ACCESS] / Strange Love / βlαnoir
|
||||
ultimate_force_conditions = []
|
||||
|
||||
@@ -473,7 +434,7 @@ class ChuniLuminous(ChuniSunPlus):
|
||||
start = (start_date + timedelta(days=14 * (i + 1))).strftime(
|
||||
self.date_time_format
|
||||
)
|
||||
|
||||
|
||||
end = (
|
||||
start_date + timedelta(days=14 * (i + 2)) - timedelta(seconds=1)
|
||||
).strftime(self.date_time_format)
|
||||
@@ -487,7 +448,7 @@ class ChuniLuminous(ChuniSunPlus):
|
||||
"startDate": start,
|
||||
"endDate": end,
|
||||
}
|
||||
for condition_id in {109403, 212103, 244203}
|
||||
for condition_id in {109403, 212103, 244203}
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from typing import Dict
|
||||
from core.config import CoreConfig
|
||||
from titles.chuni.config import ChuniConfig
|
||||
from titles.chuni.const import ChuniConstants, MapAreaConditionLogicalOperator, MapAreaConditionType
|
||||
from titles.chuni.luminous import ChuniLuminous
|
||||
from titles.chuni.luminous import ChuniLuminous, MysticAreaConditions
|
||||
|
||||
|
||||
class ChuniLuminousPlus(ChuniLuminous):
|
||||
@@ -66,6 +66,158 @@ class ChuniLuminousPlus(ChuniLuminous):
|
||||
events = await self.data.static.get_enabled_events(self.version)
|
||||
event_by_id = {evt["eventId"]: evt for evt in events}
|
||||
conditions = []
|
||||
|
||||
mystic_conditions = MysticAreaConditions(
|
||||
event_by_id,
|
||||
3229601,
|
||||
self.date_time_format,
|
||||
)
|
||||
|
||||
# Mystic Rainbow of LUMINOUS PLUS - LUMINOUS ep. IV
|
||||
mystic_conditions.add_condition(15005, 3020704, 3229602)
|
||||
|
||||
# Mystic Rainbow of LUMINOUS PLUS - LUMINOUS ep. V
|
||||
mystic_conditions.add_condition(15306, 3020705, 3229603)
|
||||
|
||||
# Mystic Rainbow of LUMINOUS PLUS - LUMINOUS ep. VI
|
||||
mystic_conditions.add_condition(15451, 3020706, 3229604)
|
||||
|
||||
# Mystic Rainbow of LUMINOUS PLUS - LUMINOUS ep. VII
|
||||
mystic_conditions.add_condition(15506, 3020707, 3229605)
|
||||
|
||||
conditions += mystic_conditions.conditions
|
||||
|
||||
# 1UM1N0U5 ep. 111 continues. The map is automatically unlocked after finishing
|
||||
# LUMINOUS ep. III in LUMINOUS PLUS.
|
||||
if ep_111 := event_by_id.get(15009):
|
||||
start_date = ep_111["startDate"].strftime(self.date_time_format)
|
||||
|
||||
conditions.append({
|
||||
"mapAreaId": 3229207,
|
||||
"length": 1,
|
||||
"mapAreaConditionList": [
|
||||
{
|
||||
"type": MapAreaConditionType.MAP_CLEARED.value,
|
||||
"conditionId": 3020703,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.AND.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00",
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
# ■・■■■■■■・■
|
||||
# Finish LUMINOUS ep. IV and obtain the title 「ここは…何処なんだ…?」.
|
||||
if re_fiction_o := event_by_id.get(15032):
|
||||
start_date = re_fiction_o["startDate"].strftime(self.date_time_format)
|
||||
|
||||
conditions.append({
|
||||
"mapAreaId": 3229501,
|
||||
"length": 2,
|
||||
"mapAreaConditionList": [
|
||||
{
|
||||
"type": MapAreaConditionType.MAP_CLEARED.value,
|
||||
"conditionId": 3020704,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.AND.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00",
|
||||
},
|
||||
{
|
||||
"type": MapAreaConditionType.TROPHY_OBTAINED.value,
|
||||
"conditionId": 7105,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.AND.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00",
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
# The Conductor's Path
|
||||
# ALL JUSTICE CRITICAL 其のエメラルドを見よ MASTER.
|
||||
if the_conductors_path := event_by_id.get(15033):
|
||||
start_date = the_conductors_path["startDate"].strftime(self.date_time_format)
|
||||
|
||||
conditions.append({
|
||||
"mapAreaId": 3229701,
|
||||
"length": 1,
|
||||
"mapAreaConditionList": [
|
||||
{
|
||||
"type": MapAreaConditionType.ALL_JUSTICE_CRITICAL.value,
|
||||
"conditionId": 260003,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.AND.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00",
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
# Cave of RVESE
|
||||
if episode__x__ := event_by_id.get(15254):
|
||||
start_date = episode__x__["startDate"].strftime(self.date_time_format)
|
||||
|
||||
conditions.extend([
|
||||
# Episode. _ _ X _ _ map area 1
|
||||
# Finish the HARDCORE TANO*C collaboration map.
|
||||
{
|
||||
"mapAreaId": 2208801,
|
||||
"length": 1,
|
||||
"mapAreaConditionList": [
|
||||
{
|
||||
"type": MapAreaConditionType.MAP_CLEARED.value,
|
||||
"conditionId": 2006533,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.AND.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00",
|
||||
},
|
||||
],
|
||||
},
|
||||
# Episode. _ _ X _ _ map area 2
|
||||
# Equip the title 「第壱の石版【V】」 to access the map area.
|
||||
{
|
||||
"mapAreaId": 2208802,
|
||||
"length": 1,
|
||||
"mapAreaConditionList": [
|
||||
{
|
||||
"type": MapAreaConditionType.TROPHY_EQUIPPED.value,
|
||||
"conditionId": 7107,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.AND.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00",
|
||||
},
|
||||
],
|
||||
},
|
||||
# Episode. _ _ X _ _ map area 3
|
||||
# Equip the title 「第弐の石版【Λ】」 to access the map area.
|
||||
{
|
||||
"mapAreaId": 2208803,
|
||||
"length": 1,
|
||||
"mapAreaConditionList": [
|
||||
{
|
||||
"type": MapAreaConditionType.TROPHY_EQUIPPED.value,
|
||||
"conditionId": 7104,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.AND.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00",
|
||||
},
|
||||
],
|
||||
},
|
||||
# Episode. _ _ X _ _ map area 4
|
||||
# Complete the 3 other map areas.
|
||||
{
|
||||
"mapAreaId": 2208804,
|
||||
"length": 3,
|
||||
"mapAreaConditionList": [
|
||||
{
|
||||
"type": MapAreaConditionType.MAP_AREA_CLEARED.value,
|
||||
"conditionId": area_id,
|
||||
"logicalOpe": MapAreaConditionLogicalOperator.AND.value,
|
||||
"startDate": start_date,
|
||||
"endDate": "2099-12-31 00:00:00",
|
||||
}
|
||||
for area_id in range(2208801, 2208804)
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
# LUMINOUS ep. Ascension
|
||||
if ep_ascension := event_by_id.get(15512):
|
||||
|
||||
@@ -8,6 +8,7 @@ from titles.chuni.const import (
|
||||
MapAreaConditionLogicalOperator,
|
||||
MapAreaConditionType,
|
||||
)
|
||||
from titles.chuni.luminous import MysticAreaConditions
|
||||
from titles.chuni.luminousplus import ChuniLuminousPlus
|
||||
|
||||
|
||||
@@ -22,6 +23,38 @@ class ChuniVerse(ChuniLuminousPlus):
|
||||
# Does CARD MAKER 1.35 work this far up?
|
||||
user_data["lastDataVersion"] = "2.30.00"
|
||||
return user_data
|
||||
|
||||
async def handle_get_game_map_area_condition_api_request(self, data: Dict) -> Dict:
|
||||
# There is no game data for this, everything is server side.
|
||||
# However, we can selectively show/hide events as data is imported into the server.
|
||||
events = await self.data.static.get_enabled_events(self.version)
|
||||
event_by_id = {evt["eventId"]: evt for evt in events}
|
||||
conditions = []
|
||||
|
||||
mystic_conditions = MysticAreaConditions(
|
||||
event_by_id,
|
||||
3230401,
|
||||
self.date_time_format,
|
||||
)
|
||||
|
||||
# Mystic Rainbow of VERSE - VERSE ep. I
|
||||
mystic_conditions.add_condition(16006, 3020798, 3230402)
|
||||
|
||||
# Mystic Rainbow of VERSE - VERSE ep. II
|
||||
mystic_conditions.add_condition(16204, 3020799, 3230403)
|
||||
|
||||
# Mystic Rainbow of VERSE - VERSE ep. III
|
||||
mystic_conditions.add_condition(16455, 3020800, 3230404)
|
||||
|
||||
# Mystic Rainbow of VERSE - VERSE ep. IV
|
||||
mystic_conditions.add_condition(16607, 3020802, 3230405)
|
||||
|
||||
conditions += mystic_conditions.conditions
|
||||
|
||||
return {
|
||||
"length": len(conditions),
|
||||
"gameMapAreaConditionList": conditions,
|
||||
}
|
||||
|
||||
async def handle_get_game_course_level_api_request(self, data: Dict) -> Dict:
|
||||
unlock_challenges = await self.data.static.get_unlock_challenges(self.version)
|
||||
@@ -81,9 +114,10 @@ class ChuniVerse(ChuniLuminousPlus):
|
||||
|
||||
unlock_condition = conditions.get(
|
||||
unlock_challenge_id,
|
||||
# default is to unlock for players above 5.00 rating
|
||||
{
|
||||
"type": MapAreaConditionType.TROPHY_OBTAINED.value, # always unlocked
|
||||
"conditionId": 0,
|
||||
"type": MapAreaConditionType.MINIMUM_RATING.value,
|
||||
"conditionId": 500,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -173,7 +207,7 @@ class ChuniVerse(ChuniLuminousPlus):
|
||||
|
||||
user_rec_music_list = [
|
||||
{
|
||||
"musicId": 1, # no idea
|
||||
"musicId": 1, # a song the player recently played
|
||||
# recMusicList is a semi colon-separated list of music IDs and their order comma separated
|
||||
# for some reason, not all music ids are shown in game?!
|
||||
"recMusicList": ";".join(
|
||||
@@ -193,7 +227,8 @@ class ChuniVerse(ChuniLuminousPlus):
|
||||
class UserRecRating:
|
||||
ratingMin: int
|
||||
ratingMax: int
|
||||
# same as recMusicList in get_user_rec_music_api_request
|
||||
# semicolon-delimited list of (musicId, level, sortingKey, score), in the
|
||||
# same format as GetUserRecMusicApi
|
||||
recMusicList: str
|
||||
|
||||
length: int
|
||||
|
||||
Reference in New Issue
Block a user