forked from Dniel97/artemis
idac: battle gift event, tips, QoL improvements added
This commit is contained in:
parent
c741c052e9
commit
9379172791
@ -0,0 +1,83 @@
|
||||
"""IDAC Battle Gift and Tips added
|
||||
|
||||
Revision ID: e4e8d89c9b02
|
||||
Revises: 81e44dd6047a
|
||||
Create Date: 2024-04-01 17:49:50.009718
|
||||
|
||||
"""
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = "e4e8d89c9b02"
|
||||
down_revision = "81e44dd6047a"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table(
|
||||
"idac_user_battle_gift",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("user", sa.Integer(), nullable=False),
|
||||
sa.Column("battle_gift_event_id", sa.Integer(), nullable=True),
|
||||
sa.Column("gift_id", sa.Integer(), nullable=True),
|
||||
sa.Column("gift_status", sa.Integer(), nullable=True),
|
||||
sa.Column(
|
||||
"received_date",
|
||||
sa.TIMESTAMP(),
|
||||
server_default=sa.text("now()"),
|
||||
nullable=True,
|
||||
),
|
||||
sa.ForeignKeyConstraint(
|
||||
["user"], ["aime_user.id"], onupdate="cascade", ondelete="cascade"
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint(
|
||||
"user", "battle_gift_event_id", "gift_id", name="idac_user_battle_gift_uk"
|
||||
),
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
op.create_table(
|
||||
"idac_profile_tips",
|
||||
sa.Column("id", sa.Integer(), nullable=False),
|
||||
sa.Column("user", sa.Integer(), nullable=False),
|
||||
sa.Column("version", sa.Integer(), nullable=False),
|
||||
sa.Column(
|
||||
"tips_list",
|
||||
sa.String(length=16),
|
||||
server_default="QAAAAAAAAAAAAAAA",
|
||||
nullable=True,
|
||||
),
|
||||
sa.Column(
|
||||
"timetrial_play_count", sa.Integer(), server_default="0", nullable=True
|
||||
),
|
||||
sa.Column("story_play_count", sa.Integer(), server_default="0", nullable=True),
|
||||
sa.Column(
|
||||
"store_battle_play_count", sa.Integer(), server_default="0", nullable=True
|
||||
),
|
||||
sa.Column(
|
||||
"online_battle_play_count", sa.Integer(), server_default="0", nullable=True
|
||||
),
|
||||
sa.Column(
|
||||
"special_play_count", sa.Integer(), server_default="0", nullable=True
|
||||
),
|
||||
sa.Column(
|
||||
"challenge_play_count", sa.Integer(), server_default="0", nullable=True
|
||||
),
|
||||
sa.Column("theory_play_count", sa.Integer(), server_default="0", nullable=True),
|
||||
sa.ForeignKeyConstraint(
|
||||
["user"], ["aime_user.id"], onupdate="cascade", ondelete="cascade"
|
||||
),
|
||||
sa.PrimaryKeyConstraint("id"),
|
||||
sa.UniqueConstraint("user", "version", name="idac_profile_tips_uk"),
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
op.drop_table("idac_user_battle_gift")
|
||||
op.drop_table("idac_profile_tips")
|
@ -775,7 +775,7 @@ python dbutils.py --game SDGT upgrade
|
||||
|
||||
| Display ID | Description |
|
||||
| ---------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| 1 | ADV image in the size 1280x720, shown during attract |
|
||||
| 1 | ADV image in the size 1920x1080, shown during attract |
|
||||
| 2 | Start image in the size 1280x720, shown in the Main Menu after selection the corresponding banner |
|
||||
| 3 | Banner image in the size 640×120, shown in the Main Menu |
|
||||
| 5 | Stamp Background image in the size 1780x608 |
|
||||
@ -809,6 +809,19 @@ python dbutils.py --game SDGT upgrade
|
||||
},
|
||||
```
|
||||
|
||||
### Battle Gift
|
||||
|
||||
- `gift_id`: unique gift index (starts from 0 f.e.)
|
||||
- `battle_gift_event_id`: unique event id
|
||||
- `reward_category`: item category (f.e. 21 = Chat Stamp)
|
||||
- `reward_type`: item id (f.e. 483 = Remilia Scarlet)
|
||||
- `reward_name`: name of the reward
|
||||
- `rarity`: 2 Golden, 1 Silver, 3 Bronze
|
||||
- `cash_rate`: ?
|
||||
- `customize_point_rate`: ?
|
||||
- `avatar_point_rate`: ?
|
||||
- `first_distribution_rate`: only used server side for the probability of the first distribution
|
||||
|
||||
### Credits:
|
||||
|
||||
- Bottersnike: For the HUGE Reverse Engineering help
|
||||
|
@ -10,6 +10,10 @@ server:
|
||||
port_echo2: 20002
|
||||
port_matching_p2p: 20003
|
||||
|
||||
timerelease:
|
||||
timerelease_no: 3
|
||||
timerelease_avatar_gacha_no: 3
|
||||
|
||||
stamp:
|
||||
enable: True
|
||||
enabled_stamps: # max 3 play stamps
|
||||
@ -20,3 +24,7 @@ stamp:
|
||||
timetrial:
|
||||
enable: True
|
||||
enabled_timetrial: "touhou_remilia_scarlet"
|
||||
|
||||
battle_event:
|
||||
enabled: True
|
||||
enabled_battle_event: "touhou_1st"
|
||||
|
@ -66,6 +66,22 @@ class IDACServerConfig:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "idac", "server", "port_matching_p2p", default=20003
|
||||
)
|
||||
|
||||
class IDACTimereleaseConfig:
|
||||
def __init__(self, parent: "IDACConfig") -> None:
|
||||
self.__config = parent
|
||||
|
||||
@property
|
||||
def timerelease_no(self) -> int:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "idac", "timerelease", "timerelease_no", default=1
|
||||
)
|
||||
|
||||
@property
|
||||
def timerelease_avatar_gacha_no(self) -> int:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "idac", "timerelease", "timerelease_avatar_gacha_no", default=1
|
||||
)
|
||||
|
||||
|
||||
class IDACStampConfig:
|
||||
@ -112,10 +128,32 @@ class IDACTimetrialConfig:
|
||||
"enabled_timetrial",
|
||||
default="touhou_remilia_scarlet",
|
||||
)
|
||||
|
||||
class IDACTBattleGiftConfig:
|
||||
def __init__(self, parent: "IDACConfig") -> None:
|
||||
self.__config = parent
|
||||
|
||||
@property
|
||||
def enable(self) -> bool:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config, "idac", "battle_gift", "enable", default=True
|
||||
)
|
||||
|
||||
@property
|
||||
def enabled_battle_gift(self) -> str:
|
||||
return CoreConfig.get_config_field(
|
||||
self.__config,
|
||||
"idac",
|
||||
"battle_gift",
|
||||
"enabled_battle_gift",
|
||||
default="touhou_1st",
|
||||
)
|
||||
|
||||
|
||||
class IDACConfig(dict):
|
||||
def __init__(self) -> None:
|
||||
self.server = IDACServerConfig(self)
|
||||
self.timerelease = IDACTimereleaseConfig(self)
|
||||
self.stamp = IDACStampConfig(self)
|
||||
self.timetrial = IDACTimetrialConfig(self)
|
||||
self.battle_gift = IDACTBattleGiftConfig(self)
|
||||
|
82
titles/idac/data/battle_gift/touhou_1st.json
Normal file
82
titles/idac/data/battle_gift/touhou_1st.json
Normal file
@ -0,0 +1,82 @@
|
||||
{
|
||||
"battle_gift_event_id": 2,
|
||||
"event_nm": "東方Projectコラボ",
|
||||
"start_dt": "2024-04-01",
|
||||
"end_dt": "2024-06-03",
|
||||
"mode_id": 1,
|
||||
"delivery_type": 1,
|
||||
"gift_data": [
|
||||
{
|
||||
"gift_id": 0,
|
||||
"battle_gift_event_id": 2,
|
||||
"reward_category": 21,
|
||||
"reward_type": 418,
|
||||
"reward_name": "素敵なお賽銭箱はそこよ",
|
||||
"rarity": 3,
|
||||
"cash_rate": 0,
|
||||
"customize_point_rate": 0,
|
||||
"avatar_point_rate": 0,
|
||||
"first_distribution_rate": 60
|
||||
},
|
||||
{
|
||||
"gift_id": 1,
|
||||
"battle_gift_event_id": 2,
|
||||
"reward_category": 21,
|
||||
"reward_type": 419,
|
||||
"reward_name": "面倒な種族ね",
|
||||
"rarity": 2,
|
||||
"cash_rate": 0,
|
||||
"customize_point_rate": 0,
|
||||
"avatar_point_rate": 0,
|
||||
"first_distribution_rate": 20
|
||||
},
|
||||
{
|
||||
"gift_id": 2,
|
||||
"battle_gift_event_id": 2,
|
||||
"reward_category": 21,
|
||||
"reward_type": 423,
|
||||
"reward_name": "調子がそこそこだぜ",
|
||||
"rarity": 3,
|
||||
"cash_rate": 0,
|
||||
"customize_point_rate": 0,
|
||||
"avatar_point_rate": 0,
|
||||
"first_distribution_rate": 60
|
||||
},
|
||||
{
|
||||
"gift_id": 3,
|
||||
"battle_gift_event_id": 2,
|
||||
"reward_category": 21,
|
||||
"reward_type": 422,
|
||||
"reward_name": "あー?",
|
||||
"rarity": 2,
|
||||
"cash_rate": 0,
|
||||
"customize_point_rate": 0,
|
||||
"avatar_point_rate": 0,
|
||||
"first_distribution_rate": 20
|
||||
},
|
||||
{
|
||||
"gift_id": 4,
|
||||
"battle_gift_event_id": 2,
|
||||
"reward_category": 21,
|
||||
"reward_type": 427,
|
||||
"reward_name": "さ、記事にするわよー",
|
||||
"rarity": 3,
|
||||
"cash_rate": 0,
|
||||
"customize_point_rate": 0,
|
||||
"avatar_point_rate": 0,
|
||||
"first_distribution_rate": 60
|
||||
},
|
||||
{
|
||||
"gift_id": 5,
|
||||
"battle_gift_event_id": 2,
|
||||
"reward_category": 21,
|
||||
"reward_type": 426,
|
||||
"reward_name": "号外~、号外だよ~",
|
||||
"rarity": 2,
|
||||
"cash_rate": 0,
|
||||
"customize_point_rate": 0,
|
||||
"avatar_point_rate": 0,
|
||||
"first_distribution_rate": 20
|
||||
}
|
||||
]
|
||||
}
|
@ -30,7 +30,6 @@
|
||||
180,
|
||||
180,
|
||||
180,
|
||||
200,
|
||||
200
|
||||
],
|
||||
"reward": [
|
||||
|
@ -30,7 +30,6 @@
|
||||
180,
|
||||
180,
|
||||
180,
|
||||
200,
|
||||
200
|
||||
],
|
||||
"reward": [
|
||||
|
@ -30,7 +30,6 @@
|
||||
180,
|
||||
180,
|
||||
180,
|
||||
200,
|
||||
200
|
||||
],
|
||||
"reward": [
|
||||
|
@ -321,6 +321,23 @@ timetrial_event = Table(
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
battle_gift = Table(
|
||||
"idac_user_battle_gift",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("battle_gift_event_id", Integer),
|
||||
Column("gift_id", Integer),
|
||||
Column("gift_status", Integer),
|
||||
Column("received_date", TIMESTAMP, server_default=func.now()),
|
||||
UniqueConstraint("user", "battle_gift_event_id", "gift_id", name="idac_user_battle_gift_uk"),
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
|
||||
class IDACItemData(BaseData):
|
||||
async def get_random_user_car(self, aime_id: int, version: int) -> Optional[List[Row]]:
|
||||
@ -843,6 +860,19 @@ class IDACItemData(BaseData):
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
async def get_battle_gifts(self, aime_id: int, battle_gift_event_id: int) -> Optional[Row]:
|
||||
sql = select(battle_gift).where(
|
||||
and_(
|
||||
battle_gift.c.user == aime_id,
|
||||
battle_gift.c.battle_gift_event_id == battle_gift_event_id,
|
||||
)
|
||||
)
|
||||
|
||||
result = await self.execute(sql)
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
async def put_car(self, aime_id: int, version: int, car_data: Dict) -> Optional[int]:
|
||||
car_data["user"] = aime_id
|
||||
@ -1074,3 +1104,19 @@ class IDACItemData(BaseData):
|
||||
)
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
async def put_battle_gift(
|
||||
self, aime_id: int, battle_gift_data: Dict
|
||||
) -> Optional[int]:
|
||||
battle_gift_data["user"] = aime_id
|
||||
|
||||
sql = insert(battle_gift).values(**battle_gift_data)
|
||||
conflict = sql.on_duplicate_key_update(**battle_gift_data)
|
||||
result = await self.execute(conflict)
|
||||
|
||||
if result is None:
|
||||
self.logger.warn(
|
||||
f"put_battle_gift: Failed to update! aime_id: {aime_id}"
|
||||
)
|
||||
return None
|
||||
return result.lastrowid
|
@ -244,6 +244,28 @@ theory = Table(
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
tips = Table(
|
||||
"idac_profile_tips",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("version", Integer, nullable=False),
|
||||
Column("tips_list", String(16), server_default="QAAAAAAAAAAAAAAA"),
|
||||
Column("timetrial_play_count", Integer, server_default="0"),
|
||||
Column("story_play_count", Integer, server_default="0"),
|
||||
Column("store_battle_play_count", Integer, server_default="0"),
|
||||
Column("online_battle_play_count", Integer, server_default="0"),
|
||||
Column("special_play_count", Integer, server_default="0"),
|
||||
Column("challenge_play_count", Integer, server_default="0"),
|
||||
Column("theory_play_count", Integer, server_default="0"),
|
||||
UniqueConstraint("user", "version", name="idac_profile_tips_uk"),
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
|
||||
class IDACProfileData(BaseData):
|
||||
def __init__(self, cfg: CoreConfig, conn: Connection) -> None:
|
||||
@ -348,6 +370,19 @@ class IDACProfileData(BaseData):
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
async def get_profile_tips(self, aime_id: int, version: int) -> Optional[Row]:
|
||||
sql = select(tips).where(
|
||||
and_(
|
||||
tips.c.user == aime_id,
|
||||
tips.c.version == version,
|
||||
)
|
||||
)
|
||||
|
||||
result = await self.execute(sql)
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
async def put_profile(
|
||||
self, aime_id: int, version: int, profile_data: Dict
|
||||
@ -438,3 +473,20 @@ class IDACProfileData(BaseData):
|
||||
)
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
async def put_profile_tips(
|
||||
self, aime_id: int, version: int, tips_data: Dict
|
||||
) -> Optional[int]:
|
||||
tips_data["user"] = aime_id
|
||||
tips_data["version"] = version
|
||||
|
||||
sql = insert(tips).values(**tips_data)
|
||||
conflict = sql.on_duplicate_key_update(**tips_data)
|
||||
result = await self.execute(conflict)
|
||||
|
||||
if result is None:
|
||||
self.logger.warn(
|
||||
f"put_profile_tips: Failed to update! aime_id: {aime_id}"
|
||||
)
|
||||
return None
|
||||
return result.lastrowid
|
@ -1,6 +1,6 @@
|
||||
from datetime import datetime, timedelta
|
||||
import os
|
||||
from random import choice
|
||||
from random import choice, randint
|
||||
from typing import Any, Dict, List
|
||||
import json
|
||||
import logging
|
||||
@ -17,20 +17,27 @@ class IDACSeason2(IDACBase):
|
||||
super().__init__(core_cfg, game_cfg)
|
||||
self.version = IDACConstants.VER_IDAC_SEASON_2
|
||||
|
||||
# load the play stamps and timetrial events into memory
|
||||
# load timerelease numbers from config
|
||||
self.timerelease_no = self.game_config.timerelease.timerelease_no
|
||||
self.timerelease_avatar_gacha_no = (
|
||||
self.game_config.timerelease.timerelease_avatar_gacha_no
|
||||
)
|
||||
|
||||
# load the user configured play stamps (up to 3)
|
||||
self.stamp_info = []
|
||||
if self.game_config.stamp.enable:
|
||||
for stamp in self.game_config.stamp.enabled_stamps:
|
||||
if not os.path.exists(f"./titles/idac/data/stamps/{stamp}.json"):
|
||||
if not os.path.exists(f"./titles/idac/data/stamp/{stamp}.json"):
|
||||
self.logger.warning(f"Stamp {stamp} is enabled but does not exist!")
|
||||
continue
|
||||
|
||||
with open(
|
||||
f"./titles/idac/data/stamps/{stamp}.json", encoding="UTF-8"
|
||||
f"./titles/idac/data/stamp/{stamp}.json", encoding="UTF-8"
|
||||
) as f:
|
||||
self.logger.debug(f"Loading stamp {stamp}")
|
||||
self.stamp_info.append(self._fix_dates(json.load(f)))
|
||||
|
||||
# load the user configured time trials (only one)
|
||||
self.timetrial_event = {}
|
||||
self.timetrial_event_id = None
|
||||
if self.game_config.timetrial.enable:
|
||||
@ -53,6 +60,25 @@ class IDACSeason2(IDACBase):
|
||||
"timetrial_event_id"
|
||||
)
|
||||
|
||||
# load the user configured battle gifts (only one)
|
||||
self.battle_gift_event = None
|
||||
if self.game_config.battle_gift.enable:
|
||||
battle_gift = self.game_config.battle_gift.enabled_battle_gift
|
||||
if battle_gift is not None:
|
||||
if not os.path.exists(
|
||||
f"./titles/idac/data/battle_gift/{battle_gift}.json"
|
||||
):
|
||||
self.logger.warning(
|
||||
f"Battle gift {battle_gift} is enabled but does not exist!"
|
||||
)
|
||||
else:
|
||||
self.logger.debug(f"Loading battle gift {battle_gift}")
|
||||
with open(
|
||||
f"./titles/idac/data/battle_gift/{battle_gift}.json",
|
||||
encoding="UTF-8",
|
||||
) as f:
|
||||
self.battle_gift_event = self._fix_dates(json.load(f))
|
||||
|
||||
async def handle_alive_get_request(self, data: Dict, headers: Dict):
|
||||
return {
|
||||
"status_code": "0",
|
||||
@ -122,7 +148,6 @@ class IDACSeason2(IDACBase):
|
||||
"difference_time_to_jp": 0,
|
||||
# has to match the game asset version to show theory of street
|
||||
"asset_version": "1",
|
||||
# option version? MV01?
|
||||
"optional_version": "1",
|
||||
"disconnect_offset": 0,
|
||||
"boost_balance_version": "0",
|
||||
@ -130,8 +155,8 @@ class IDACSeason2(IDACBase):
|
||||
"play_stamp_enable": 1,
|
||||
"play_stamp_bonus_coin": 1,
|
||||
"gacha_chara_needs": 1,
|
||||
"both_win_system_control": 1,
|
||||
"subcard_system_congrol": 1,
|
||||
"both_win_system_control": 0,
|
||||
"subcard_system_congrol": 0,
|
||||
"server_maintenance_start_hour": 0,
|
||||
"server_maintenance_start_minutes": 0,
|
||||
"server_maintenance_end_hour": 0,
|
||||
@ -141,7 +166,10 @@ class IDACSeason2(IDACBase):
|
||||
"domain_echo1": f"{self.core_cfg.server.hostname}:{self.game_config.server.echo1}",
|
||||
"domain_echo2": f"{self.core_cfg.server.hostname}:{self.game_config.server.echo1}",
|
||||
"domain_ping": f"{self.core_cfg.server.hostname}",
|
||||
"battle_gift_event_master": [],
|
||||
"battle_gift_event_master": (
|
||||
[self.battle_gift_event] if self.battle_gift_event else []
|
||||
),
|
||||
# online battle round event
|
||||
"round_event": [
|
||||
{
|
||||
"round_event_id": 30,
|
||||
@ -180,7 +208,7 @@ class IDACSeason2(IDACBase):
|
||||
"reward_upper_limit": 180,
|
||||
"reward_lower_limit": 180,
|
||||
"reward": [{"reward_category": 21, "reward_type": 462}],
|
||||
}
|
||||
},
|
||||
],
|
||||
"rank": [],
|
||||
"point": [],
|
||||
@ -245,26 +273,148 @@ class IDACSeason2(IDACBase):
|
||||
"round_event_exp": [],
|
||||
"stamp_info": self.stamp_info,
|
||||
# 0 = use default data, 1+ = server version of timereleasedata response
|
||||
"timerelease_no": 3,
|
||||
"timerelease_no": self.timerelease_no,
|
||||
# 0 = use default data, 1+ = server version of gachadata response
|
||||
"timerelease_avatar_gacha_no": 3,
|
||||
"takeover_reward": [],
|
||||
"timerelease_avatar_gacha_no": self.timerelease_avatar_gacha_no,
|
||||
# takover reward from other games such as 1=IDZ and 3=SWDC
|
||||
"takeover_reward": [
|
||||
{
|
||||
"takeover_reward_type": 0,
|
||||
"takeover_reward_data": [
|
||||
{"reward_no": 1, "reward_category": 1, "reward_type": 5000},
|
||||
{"reward_no": 2, "reward_category": 25, "reward_type": 1},
|
||||
],
|
||||
},
|
||||
{
|
||||
"takeover_reward_type": 1,
|
||||
"takeover_reward_data": [
|
||||
{"reward_no": 1, "reward_category": 15, "reward_type": 82},
|
||||
{"reward_no": 1, "reward_category": 15, "reward_type": 190},
|
||||
{"reward_no": 2, "reward_category": 3, "reward_type": 2},
|
||||
{"reward_no": 2, "reward_category": 5, "reward_type": 2},
|
||||
{"reward_no": 3, "reward_category": 3, "reward_type": 3},
|
||||
{"reward_no": 3, "reward_category": 5, "reward_type": 3},
|
||||
{"reward_no": 4, "reward_category": 3, "reward_type": 5},
|
||||
{"reward_no": 4, "reward_category": 5, "reward_type": 5},
|
||||
{"reward_no": 5, "reward_category": 15, "reward_type": 104},
|
||||
{"reward_no": 5, "reward_category": 15, "reward_type": 212},
|
||||
],
|
||||
},
|
||||
{
|
||||
"takeover_reward_type": 2,
|
||||
"takeover_reward_data": [
|
||||
{"reward_no": 1, "reward_category": 24, "reward_type": 4052},
|
||||
{"reward_no": 2, "reward_category": 24, "reward_type": 4053},
|
||||
{"reward_no": 3, "reward_category": 24, "reward_type": 4054},
|
||||
{"reward_no": 4, "reward_category": 24, "reward_type": 4055},
|
||||
{"reward_no": 5, "reward_category": 24, "reward_type": 4056},
|
||||
{"reward_no": 6, "reward_category": 24, "reward_type": 4057},
|
||||
{"reward_no": 7, "reward_category": 24, "reward_type": 4058},
|
||||
],
|
||||
},
|
||||
{
|
||||
"takeover_reward_type": 3,
|
||||
"takeover_reward_data": [
|
||||
{"reward_no": 1, "reward_category": 15, "reward_type": 81},
|
||||
{"reward_no": 1, "reward_category": 15, "reward_type": 189},
|
||||
{"reward_no": 2, "reward_category": 25, "reward_type": 1},
|
||||
{"reward_no": 2, "reward_category": 15, "reward_type": 103},
|
||||
{"reward_no": 2, "reward_category": 15, "reward_type": 211},
|
||||
],
|
||||
},
|
||||
],
|
||||
"subcard_judge": [
|
||||
{
|
||||
"condition_id": 1,
|
||||
"lower_rank": 0,
|
||||
"higher_rank": 10,
|
||||
"condition_start": 2,
|
||||
"condition_end": 3,
|
||||
}
|
||||
],
|
||||
"special_promote": [{"counter": 1, "online_rank_id": 1}],
|
||||
"matching_id": 1,
|
||||
"matching_group": [
|
||||
"lower_rank": 1,
|
||||
"higher_rank": 7,
|
||||
"condition_start": 17,
|
||||
"condition_end": 20,
|
||||
"calc": 3,
|
||||
},
|
||||
{
|
||||
"group_id": 1,
|
||||
"group_percent": 1,
|
||||
}
|
||||
"condition_id": 2,
|
||||
"lower_rank": 1,
|
||||
"higher_rank": 15,
|
||||
"condition_start": 10,
|
||||
"condition_end": 10,
|
||||
"calc": 20,
|
||||
},
|
||||
{
|
||||
"condition_id": 3,
|
||||
"lower_rank": 11,
|
||||
"higher_rank": 15,
|
||||
"condition_start": 80,
|
||||
"condition_end": 89,
|
||||
"calc": 7,
|
||||
},
|
||||
{
|
||||
"condition_id": 3,
|
||||
"lower_rank": 11,
|
||||
"higher_rank": 15,
|
||||
"condition_start": 90,
|
||||
"condition_end": 100,
|
||||
"calc": 10,
|
||||
},
|
||||
{
|
||||
"condition_id": 3,
|
||||
"lower_rank": 1,
|
||||
"higher_rank": 15,
|
||||
"condition_start": 0,
|
||||
"condition_end": 40,
|
||||
"calc": -100,
|
||||
},
|
||||
{
|
||||
"condition_id": 1,
|
||||
"lower_rank": 1,
|
||||
"higher_rank": 15,
|
||||
"condition_start": 21,
|
||||
"condition_end": 24,
|
||||
"calc": 7,
|
||||
},
|
||||
{
|
||||
"condition_id": 1,
|
||||
"lower_rank": 1,
|
||||
"higher_rank": 15,
|
||||
"condition_start": 25,
|
||||
"condition_end": 25,
|
||||
"calc": 10,
|
||||
},
|
||||
{
|
||||
"condition_id": 3,
|
||||
"lower_rank": 16,
|
||||
"higher_rank": 20,
|
||||
"condition_start": 70,
|
||||
"condition_end": 89,
|
||||
"calc": 6,
|
||||
},
|
||||
{
|
||||
"condition_id": 3,
|
||||
"lower_rank": 16,
|
||||
"higher_rank": 20,
|
||||
"condition_start": 90,
|
||||
"condition_end": 100,
|
||||
"calc": 12,
|
||||
},
|
||||
{
|
||||
"condition_id": 3,
|
||||
"lower_rank": 16,
|
||||
"higher_rank": 20,
|
||||
"condition_start": 0,
|
||||
"condition_end": 50,
|
||||
"calc": -100,
|
||||
},
|
||||
],
|
||||
"special_promote": [
|
||||
{"counter": 50, "online_rank_id": 8},
|
||||
{"counter": 200, "online_rank_id": 16},
|
||||
{"counter": 255, "online_rank_id": 21},
|
||||
],
|
||||
"matching_id": 0,
|
||||
"matching_group": [
|
||||
{"group_id": 1, "group_percent": 30},
|
||||
{"group_id": 2, "group_percent": 50},
|
||||
{"group_id": 3, "group_percent": 100},
|
||||
],
|
||||
"timetrial_disp_date": int(
|
||||
datetime.strptime("2023-10-01", "%Y-%m-%d").timestamp()
|
||||
@ -272,21 +422,22 @@ class IDACSeason2(IDACBase):
|
||||
# price for every car
|
||||
"buy_car_need_cash": 5000,
|
||||
# number of buyable shop/customization time limits
|
||||
"time_extension_limit": 1,
|
||||
"time_extension_limit": 5,
|
||||
"collabo_id": 0,
|
||||
"driver_debut_end_date": int(
|
||||
datetime.strptime("2029-01-01", "%Y-%m-%d").timestamp()
|
||||
),
|
||||
"online_battle_param1": 1,
|
||||
"online_battle_param2": 1,
|
||||
"online_battle_param3": 1,
|
||||
"online_battle_param4": 1,
|
||||
"online_battle_param5": 1,
|
||||
"online_battle_param6": 1,
|
||||
"online_battle_param7": 1,
|
||||
"online_battle_param8": 1,
|
||||
"theory_open_version": "1.30",
|
||||
"theory_close_version": "1.50",
|
||||
"online_battle_param1": 0,
|
||||
"online_battle_param2": 0,
|
||||
"online_battle_param3": 0,
|
||||
"online_battle_param4": 0,
|
||||
"online_battle_param5": 0,
|
||||
"online_battle_param6": 2,
|
||||
"online_battle_param7": 0,
|
||||
"online_battle_param8": 3900,
|
||||
"theory_open_version": "1.30.00",
|
||||
"theory_close_version": "9.99.99",
|
||||
# unlocks teh version specific special mode
|
||||
"special_mode_data": {
|
||||
"start_dt": int(
|
||||
datetime.strptime("2023-01-01", "%Y-%m-%d").timestamp()
|
||||
@ -692,6 +843,20 @@ class IDACSeason2(IDACBase):
|
||||
vs_info["course_select_priority"] = data.get("course_select_priority")
|
||||
return vs_info
|
||||
|
||||
def _choose_gift_id(self) -> Dict:
|
||||
gift_data = self.battle_gift_event["gift_data"]
|
||||
# calculate the total_rate based on the first_distribution_rate
|
||||
total_rate = sum(gift["first_distribution_rate"] for gift in gift_data)
|
||||
|
||||
# randomly choose a number between 1 and the total rate
|
||||
rand_num = randint(1, total_rate)
|
||||
cumulative_rate = 0
|
||||
for gift in gift_data:
|
||||
# if the random number is less than the cumulative rate, return the gift
|
||||
cumulative_rate += gift["first_distribution_rate"]
|
||||
if rand_num <= cumulative_rate:
|
||||
return gift
|
||||
|
||||
async def handle_user_getdata_request(self, data: Dict, headers: Dict):
|
||||
user_id = int(headers["session"])
|
||||
|
||||
@ -926,6 +1091,74 @@ class IDACSeason2(IDACBase):
|
||||
"point": timetrial["point"],
|
||||
}
|
||||
|
||||
# check if the battle gift event is active
|
||||
if self.battle_gift_event:
|
||||
# get the users battle gifts, for the current active battle gift event
|
||||
battle_gifts = await self.data.item.get_battle_gifts(
|
||||
user_id, self.battle_gift_event.get("battle_gift_event_id")
|
||||
)
|
||||
|
||||
if battle_gifts:
|
||||
# just return all aquired gifts
|
||||
battle_gift_data = [
|
||||
{
|
||||
"first_distribution_flag": 0,
|
||||
"gift_data": [
|
||||
{
|
||||
"gift_id": gift["gift_id"],
|
||||
# 1 = acquired
|
||||
"gift_get_status": gift["gift_status"],
|
||||
}
|
||||
for gift in battle_gifts
|
||||
],
|
||||
}
|
||||
]
|
||||
else:
|
||||
# get a random gift from the active battle gift event
|
||||
gift_id = self._choose_gift_id()["gift_id"]
|
||||
|
||||
# save the battle_gift inside the database
|
||||
await self.data.item.put_battle_gift(
|
||||
user_id,
|
||||
{
|
||||
"battle_gift_event_id": self.battle_gift_event.get(
|
||||
"battle_gift_event_id"
|
||||
),
|
||||
"gift_id": gift_id,
|
||||
"gift_status": 1, # aquired
|
||||
},
|
||||
)
|
||||
|
||||
battle_gift_data = [
|
||||
{
|
||||
# trigger the first gift animation
|
||||
"first_distribution_flag": 1,
|
||||
"gift_data": [
|
||||
{
|
||||
# return a random selected gift_id
|
||||
"gift_id": gift_id,
|
||||
# set the status to 2 = new gift
|
||||
"gift_get_status": 2,
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
# get the tips from the database
|
||||
tips = await self.data.profile.get_profile_tips(user_id, self.version)
|
||||
|
||||
# if there are no tips, create a new one
|
||||
if tips is None:
|
||||
await self.data.profile.put_profile_tips(user_id, self.version, {})
|
||||
|
||||
# get the tips from the database
|
||||
tips = await self.data.profile.get_profile_tips(user_id, self.version)
|
||||
|
||||
tips_info = tips._asdict()
|
||||
del tips_info["id"]
|
||||
del tips_info["user"]
|
||||
del tips_info["version"]
|
||||
|
||||
return {
|
||||
"status_code": "0",
|
||||
"user_base_data": user_data,
|
||||
@ -969,7 +1202,9 @@ class IDACSeason2(IDACBase):
|
||||
"frozen_data": {"frozen_status": 2},
|
||||
"penalty_data": {"penalty_flag": 0, "penalty_2_level": 0},
|
||||
"config_data": config_data,
|
||||
"battle_gift_data": [],
|
||||
# gift_get_status 2 = new gift, 1 = acquired
|
||||
# first_distribution related are useless since this is all handled by server
|
||||
"battle_gift_data": battle_gift_data,
|
||||
"ticket_data": ticket_data,
|
||||
"round_event": [],
|
||||
"last_round_event": [],
|
||||
@ -984,17 +1219,16 @@ class IDACSeason2(IDACBase):
|
||||
"car_use_count": [],
|
||||
"maker_use_count": [],
|
||||
"story_course": [{"course_id": 0, "count": 1}],
|
||||
# TODO!
|
||||
# "driver_debut": {
|
||||
# "play_count": 137,
|
||||
# "daily_play": 5,
|
||||
# "last_play_dt": 0,
|
||||
# "use_start_date": 0,
|
||||
# "use_end_date": 0,
|
||||
# "use_dt": 0,
|
||||
# "ticket_cnt": 0,
|
||||
# "ticket_get_bit": 0,
|
||||
# },
|
||||
"driver_debut": {
|
||||
# "play_count": 5,
|
||||
# "daily_play": 5,
|
||||
# "last_play_dt": datetime.now().timestamp() - 86400,
|
||||
# "use_start_date": datetime.now().timestamp() - 86400,
|
||||
# "use_end_date": datetime.now().timestamp() + 86400,
|
||||
# "use_dt": datetime.now().timestamp(),
|
||||
# "ticket_cnt": 1,
|
||||
# "ticket_get_bit": (2 ** 5) - 1,
|
||||
},
|
||||
"theory_data": theory_data,
|
||||
"theory_course_data": theory_course_data,
|
||||
"theory_partner_data": theory_partner_data,
|
||||
@ -1004,6 +1238,7 @@ class IDACSeason2(IDACBase):
|
||||
"season_rewards_data": [],
|
||||
"timetrial_event_data": timetrial_event_data,
|
||||
"special_mode_hint_data": {"story_type": 0, "hint_display_flag": 0},
|
||||
"tips_info": tips_info,
|
||||
}
|
||||
|
||||
async def handle_timetrial_getbestrecordpreta_request(
|
||||
@ -1596,6 +1831,12 @@ class IDACSeason2(IDACBase):
|
||||
user_id, self.timetrial_event_id, event_point
|
||||
)
|
||||
|
||||
# update the tips play count
|
||||
tips = await self.data.profile.get_profile_tips(user_id, self.version)
|
||||
await self.data.profile.put_profile_tips(
|
||||
user_id, self.version, {"timetrial_play_count": tips["timetrial_play_count"] + 1}
|
||||
)
|
||||
|
||||
return {
|
||||
"status_code": "0",
|
||||
"course_rank": course_rank,
|
||||
@ -1733,6 +1974,12 @@ class IDACSeason2(IDACBase):
|
||||
},
|
||||
)
|
||||
|
||||
# update the tips play count
|
||||
tips = await self.data.profile.get_profile_tips(user_id, self.version)
|
||||
await self.data.profile.put_profile_tips(
|
||||
user_id, self.version, {"story_play_count": tips["story_play_count"] + 1}
|
||||
)
|
||||
|
||||
return {
|
||||
"status_code": "0",
|
||||
"story_data": await self._generate_story_data(user_id),
|
||||
@ -1806,6 +2053,12 @@ class IDACSeason2(IDACBase):
|
||||
# finally save the special mode with story_type=4 in database
|
||||
await self.data.item.put_challenge(user_id, data)
|
||||
|
||||
# update the tips play count
|
||||
tips = await self.data.profile.get_profile_tips(user_id, self.version)
|
||||
await self.data.profile.put_profile_tips(
|
||||
user_id, self.version, {"special_play_count": tips["special_play_count"] + 1}
|
||||
)
|
||||
|
||||
return {
|
||||
"status_code": "0",
|
||||
"special_mode_data": await self._generate_special_data(user_id),
|
||||
@ -1886,6 +2139,12 @@ class IDACSeason2(IDACBase):
|
||||
# finally save the challenge mode with story_type=3 in database
|
||||
await self.data.item.put_challenge(user_id, data)
|
||||
|
||||
# update the tips play count
|
||||
tips = await self.data.profile.get_profile_tips(user_id, self.version)
|
||||
await self.data.profile.put_profile_tips(
|
||||
user_id, self.version, {"challenge_play_count": tips["challenge_play_count"] + 1}
|
||||
)
|
||||
|
||||
return {
|
||||
"status_code": "0",
|
||||
"challenge_mode_data": await self._generate_challenge_data(user_id),
|
||||
@ -2118,7 +2377,12 @@ class IDACSeason2(IDACBase):
|
||||
# not required?
|
||||
mode_id = data.pop("mode_id")
|
||||
standby_play_flag = data.pop("standby_play_flag")
|
||||
|
||||
# save the tips list in database
|
||||
tips_list = data.pop("tips_list")
|
||||
await self.data.profile.put_profile_tips(
|
||||
user_id, self.version, {"tips_list": tips_list}
|
||||
)
|
||||
|
||||
# save stock data in database
|
||||
await self._save_stock_data(user_id, stock_data)
|
||||
@ -2522,6 +2786,12 @@ class IDACSeason2(IDACBase):
|
||||
},
|
||||
)
|
||||
|
||||
# update the tips play count
|
||||
tips = await self.data.profile.get_profile_tips(user_id, self.version)
|
||||
await self.data.profile.put_profile_tips(
|
||||
user_id, self.version, {"theory_play_count": tips["theory_play_count"] + 1}
|
||||
)
|
||||
|
||||
return {
|
||||
"status_code": "0",
|
||||
"played_powerhouse_lv": data.get("powerhouse_lv"),
|
||||
@ -2584,7 +2854,9 @@ class IDACSeason2(IDACBase):
|
||||
"bothwin_penalty": 1,
|
||||
}
|
||||
|
||||
async def handle_user_updateonlinebattleresult_request(self, data: Dict, headers: Dict):
|
||||
async def handle_user_updateonlinebattleresult_request(
|
||||
self, data: Dict, headers: Dict
|
||||
):
|
||||
user_id = headers["session"]
|
||||
|
||||
stock_data: Dict = data.pop("stock_obj")
|
||||
@ -2640,7 +2912,15 @@ class IDACSeason2(IDACBase):
|
||||
},
|
||||
)
|
||||
|
||||
vs_info = self._update_vs_info(user_id, IDACConstants.BATTLE_MODE_ONLINE, data)
|
||||
vs_info = await self._update_vs_info(
|
||||
user_id, IDACConstants.BATTLE_MODE_ONLINE, data
|
||||
)
|
||||
|
||||
# update the tips play count
|
||||
tips = await self.data.profile.get_profile_tips(user_id, self.version)
|
||||
await self.data.profile.put_profile_tips(
|
||||
user_id, self.version, {"online_battle_play_count": tips["online_battle_play_count"] + 1}
|
||||
)
|
||||
|
||||
return {
|
||||
"status_code": "0",
|
||||
@ -2671,9 +2951,20 @@ class IDACSeason2(IDACBase):
|
||||
|
||||
# no idea?
|
||||
result = data.pop("result")
|
||||
|
||||
# save the received battle gift in database, hopefully that works
|
||||
battle_gift_event_id = data.pop("battle_gift_event_id")
|
||||
gift_id = data.pop("gift_id")
|
||||
|
||||
await self.data.item.put_battle_gift(
|
||||
user_id,
|
||||
{
|
||||
"battle_gift_event_id": battle_gift_event_id,
|
||||
"gift_id": gift_id,
|
||||
"gift_status": 1, # aquired
|
||||
},
|
||||
)
|
||||
|
||||
# save stock data in database
|
||||
await self._save_stock_data(user_id, stock_data)
|
||||
|
||||
@ -2726,6 +3017,12 @@ class IDACSeason2(IDACBase):
|
||||
user_id, IDACConstants.BATTLE_MODE_OFFLINE, data
|
||||
)
|
||||
|
||||
# update the tips play count
|
||||
tips = await self.data.profile.get_profile_tips(user_id, self.version)
|
||||
await self.data.profile.put_profile_tips(
|
||||
user_id, self.version, {"store_battle_play_count": tips["store_battle_play_count"] + 1}
|
||||
)
|
||||
|
||||
return {
|
||||
"status_code": "0",
|
||||
"vsinfo_data": vs_info,
|
||||
|
Loading…
Reference in New Issue
Block a user