forked from Hay1tsme/artemis
Equipments saving for SAO now completed
This commit is contained in:
parent
e466ddce55
commit
bf6d126f8a
@ -30,6 +30,9 @@ Games listed below have been tested and confirmed working. Only game versions ol
|
||||
+ POKKÉN TOURNAMENT
|
||||
+ Final Online
|
||||
|
||||
+ Sword Art Online Arcade (partial support)
|
||||
+ Final
|
||||
|
||||
## Requirements
|
||||
- python 3 (tested working with 3.9 and 3.10, other versions YMMV)
|
||||
- pip
|
||||
|
@ -81,6 +81,9 @@ class SaoBase:
|
||||
self.game_data.item.put_hero_log(user_id, 102000010, 1, 0, 103000006, 0, 30086, 1001, 1002, 1003, 1005)
|
||||
self.game_data.item.put_hero_log(user_id, 103000010, 1, 0, 112000009, 0, 30086, 1001, 1002, 1003, 1005)
|
||||
self.game_data.item.put_hero_party(user_id, 0, 101000010, 102000010, 103000010)
|
||||
self.game_data.item.put_equipment_data(user_id, 101000016, 1, 200, 0, 0, 0)
|
||||
self.game_data.item.put_equipment_data(user_id, 103000006, 1, 200, 0, 0, 0)
|
||||
self.game_data.item.put_equipment_data(user_id, 112000009, 1, 200, 0, 0, 0)
|
||||
|
||||
self.logger.info(f"User Authenticated: { access_code } | { user_id }")
|
||||
|
||||
@ -145,9 +148,19 @@ class SaoBase:
|
||||
|
||||
def handle_c602(self, request: Any) -> bytes:
|
||||
#have_object/get_equipment_user_data_list
|
||||
equipmentIdsData = self.game_data.static.get_equipment_ids(0, True)
|
||||
|
||||
resp = SaoGetEquipmentUserDataListResponse(int.from_bytes(bytes.fromhex(request[:4]), "big")+1, equipmentIdsData)
|
||||
req = bytes.fromhex(request)[24:]
|
||||
req_struct = Struct(
|
||||
Padding(16),
|
||||
"user_id_size" / Rebuild(Int32ub, len_(this.user_id) * 2), # calculates the length of the user_id
|
||||
"user_id" / PaddedString(this.user_id_size, "utf_16_le"), # user_id is a (zero) padded string
|
||||
|
||||
)
|
||||
req_data = req_struct.parse(req)
|
||||
user_id = req_data.user_id
|
||||
|
||||
equipment_data = self.game_data.item.get_user_equipments(user_id)
|
||||
|
||||
resp = SaoGetEquipmentUserDataListResponse(int.from_bytes(bytes.fromhex(request[:4]), "big")+1, equipment_data)
|
||||
return resp.make()
|
||||
|
||||
def handle_c604(self, request: Any) -> bytes:
|
||||
@ -510,10 +523,11 @@ class SaoBase:
|
||||
randomized_unanalyzed_id = choice(data_unanalyzed)
|
||||
|
||||
heroList = self.game_data.static.get_hero_id(randomized_unanalyzed_id['CommonRewardId'])
|
||||
equipmentList = self.game_data.static.get_equipment_id(randomized_unanalyzed_id['CommonRewardId'])
|
||||
if heroList:
|
||||
self.game_data.item.put_hero_log(req_data.user_id, randomized_unanalyzed_id['CommonRewardId'], 1, 0, 101000016, 0, 30086, 1001, 1002, 0, 0)
|
||||
|
||||
# Item and Equipments saving will be done later here
|
||||
if equipmentList:
|
||||
self.game_data.item.put_equipment_data(req_data.user_id, randomized_unanalyzed_id['CommonRewardId'], 1, 200, 0, 0, 0)
|
||||
|
||||
# Send response
|
||||
|
||||
@ -532,4 +546,4 @@ class SaoBase:
|
||||
def handle_c90a(self, request: Any) -> bytes: #should be tweaked for proper item unlock
|
||||
#quest/episode_play_end_unanalyzed_log_fixed
|
||||
resp = SaoEpisodePlayEndUnanalyzedLogFixedResponse(int.from_bytes(bytes.fromhex(request[:4]), "big")+1)
|
||||
return resp.make()
|
||||
return resp.make()
|
||||
|
121
titles/sao/data/EquipmentLevel.csv
Normal file
121
titles/sao/data/EquipmentLevel.csv
Normal file
@ -0,0 +1,121 @@
|
||||
EquipmentLevelId,RequireExp
|
||||
1,200,
|
||||
2,400,
|
||||
3,600,
|
||||
4,800,
|
||||
5,1000,
|
||||
6,1200,
|
||||
7,1400,
|
||||
8,1600,
|
||||
9,1800,
|
||||
10,2000,
|
||||
11,2200,
|
||||
12,2400,
|
||||
13,2600,
|
||||
14,2800,
|
||||
15,3000,
|
||||
16,3200,
|
||||
17,3400,
|
||||
18,3600,
|
||||
19,3800,
|
||||
20,4000,
|
||||
21,4200,
|
||||
22,4400,
|
||||
23,4600,
|
||||
24,4800,
|
||||
25,5000,
|
||||
26,5200,
|
||||
27,5400,
|
||||
28,5600,
|
||||
29,5800,
|
||||
30,6000,
|
||||
31,6200,
|
||||
32,6400,
|
||||
33,6600,
|
||||
34,6800,
|
||||
35,7000,
|
||||
36,7200,
|
||||
37,7400,
|
||||
38,7600,
|
||||
39,7800,
|
||||
40,8000,
|
||||
41,8200,
|
||||
42,8400,
|
||||
43,8600,
|
||||
44,8800,
|
||||
45,9000,
|
||||
46,9200,
|
||||
47,9400,
|
||||
48,9600,
|
||||
49,9800,
|
||||
50,10000,
|
||||
51,10200,
|
||||
52,10400,
|
||||
53,10600,
|
||||
54,10800,
|
||||
55,11000,
|
||||
56,11200,
|
||||
57,11400,
|
||||
58,11600,
|
||||
59,11800,
|
||||
60,12000,
|
||||
61,12200,
|
||||
62,12400,
|
||||
63,12600,
|
||||
64,12800,
|
||||
65,13000,
|
||||
66,13200,
|
||||
67,13400,
|
||||
68,13600,
|
||||
69,13800,
|
||||
70,14000,
|
||||
71,14200,
|
||||
72,14400,
|
||||
73,14600,
|
||||
74,14800,
|
||||
75,15000,
|
||||
76,15200,
|
||||
77,15400,
|
||||
78,15600,
|
||||
79,15800,
|
||||
80,16000,
|
||||
81,16200,
|
||||
82,16400,
|
||||
83,16600,
|
||||
84,16800,
|
||||
85,17000,
|
||||
86,17200,
|
||||
87,17400,
|
||||
88,17600,
|
||||
89,17800,
|
||||
90,18000,
|
||||
91,18200,
|
||||
92,18400,
|
||||
93,18600,
|
||||
94,18800,
|
||||
95,19000,
|
||||
96,19200,
|
||||
97,19400,
|
||||
98,19600,
|
||||
99,19800,
|
||||
100,100000,
|
||||
101,150000,
|
||||
102,200000,
|
||||
103,250000,
|
||||
104,300000,
|
||||
105,350000,
|
||||
106,400000,
|
||||
107,450000,
|
||||
108,500000,
|
||||
109,550000,
|
||||
110,600000,
|
||||
111,650000,
|
||||
112,700000,
|
||||
113,750000,
|
||||
114,800000,
|
||||
115,850000,
|
||||
116,900000,
|
||||
117,950000,
|
||||
118,1000000,
|
||||
119,1000000,
|
||||
120,1000000,
|
|
@ -660,19 +660,57 @@ class SaoGetEquipmentUserDataListRequest(SaoBaseRequest):
|
||||
super().__init__(data)
|
||||
|
||||
class SaoGetEquipmentUserDataListResponse(SaoBaseResponse):
|
||||
def __init__(self, cmd, equipmentIdsData) -> None:
|
||||
def __init__(self, cmd, equipment_data) -> None:
|
||||
super().__init__(cmd)
|
||||
self.result = 1
|
||||
|
||||
self.user_equipment_id = []
|
||||
self.enhancement_value = []
|
||||
self.max_enhancement_value_extended_num = []
|
||||
self.enhancement_exp = []
|
||||
self.awakening_stage = []
|
||||
self.awakening_exp = []
|
||||
self.possible_awakening_flag = []
|
||||
equipment_level = 0
|
||||
|
||||
for i in range(len(equipment_data)):
|
||||
|
||||
# Calculate level based off experience and the CSV list
|
||||
with open(r'titles/sao/data/EquipmentLevel.csv') as csv_file:
|
||||
csv_reader = csv.reader(csv_file, delimiter=',')
|
||||
line_count = 0
|
||||
data = []
|
||||
rowf = False
|
||||
for row in csv_reader:
|
||||
if rowf==False:
|
||||
rowf=True
|
||||
else:
|
||||
data.append(row)
|
||||
|
||||
exp = equipment_data[i][4]
|
||||
|
||||
for e in range(0,len(data)):
|
||||
if exp>=int(data[e][1]) and exp<int(data[e+1][1]):
|
||||
equipment_level = int(data[e][0])
|
||||
break
|
||||
|
||||
self.user_equipment_id.append(equipment_data[i][2])
|
||||
self.enhancement_value.append(equipment_level)
|
||||
self.max_enhancement_value_extended_num.append(equipment_level)
|
||||
self.enhancement_exp.append(equipment_data[i][4])
|
||||
self.awakening_stage.append(equipment_data[i][5])
|
||||
self.awakening_exp.append(equipment_data[i][6])
|
||||
self.possible_awakening_flag.append(equipment_data[i][7])
|
||||
|
||||
# equipment_user_data_list
|
||||
self.user_equipment_id = list(map(str,equipmentIdsData)) #str
|
||||
self.equipment_id = equipmentIdsData #int
|
||||
self.enhancement_value = 10 #short
|
||||
self.max_enhancement_value_extended_num = 10 #short
|
||||
self.enhancement_exp = 1000 #int
|
||||
self.possible_awakening_flag = 0 #byte
|
||||
self.awakening_stage = 0 #short
|
||||
self.awakening_exp = 0 #int
|
||||
self.user_equipment_id = list(map(str,self.user_equipment_id)) #str
|
||||
self.equipment_id = list(map(int,self.user_equipment_id)) #int
|
||||
self.enhancement_value = list(map(int,self.enhancement_value)) #short
|
||||
self.max_enhancement_value_extended_num = list(map(int,self.max_enhancement_value_extended_num)) #short
|
||||
self.enhancement_exp = list(map(int,self.enhancement_exp)) #int
|
||||
self.possible_awakening_flag = list(map(int,self.possible_awakening_flag)) #byte
|
||||
self.awakening_stage = list(map(int,self.awakening_stage)) #short
|
||||
self.awakening_exp = list(map(int,self.awakening_exp)) #int
|
||||
self.property1_property_id = 0 #int
|
||||
self.property1_value1 = 0 #int
|
||||
self.property1_value2 = 0 #int
|
||||
@ -739,12 +777,12 @@ class SaoGetEquipmentUserDataListResponse(SaoBaseResponse):
|
||||
user_equipment_id_size=len(self.user_equipment_id[i]) * 2,
|
||||
user_equipment_id=[ord(x) for x in self.user_equipment_id[i]],
|
||||
equipment_id=self.equipment_id[i],
|
||||
enhancement_value=self.enhancement_value,
|
||||
max_enhancement_value_extended_num=self.max_enhancement_value_extended_num,
|
||||
enhancement_exp=self.enhancement_exp,
|
||||
possible_awakening_flag=self.possible_awakening_flag,
|
||||
awakening_stage=self.awakening_stage,
|
||||
awakening_exp=self.awakening_exp,
|
||||
enhancement_value=self.enhancement_value[i],
|
||||
max_enhancement_value_extended_num=self.max_enhancement_value_extended_num[i],
|
||||
enhancement_exp=self.enhancement_exp[i],
|
||||
possible_awakening_flag=self.possible_awakening_flag[i],
|
||||
awakening_stage=self.awakening_stage[i],
|
||||
awakening_exp=self.awakening_exp[i],
|
||||
property1_property_id=self.property1_property_id,
|
||||
property1_value1=self.property1_value1,
|
||||
property1_value2=self.property1_value2,
|
||||
|
@ -8,6 +8,26 @@ from sqlalchemy.dialects.mysql import insert
|
||||
|
||||
from core.data.schema import BaseData, metadata
|
||||
|
||||
equipment_data = Table(
|
||||
"sao_equipment_data",
|
||||
metadata,
|
||||
Column("id", Integer, primary_key=True, nullable=False),
|
||||
Column(
|
||||
"user",
|
||||
ForeignKey("aime_user.id", ondelete="cascade", onupdate="cascade"),
|
||||
nullable=False,
|
||||
),
|
||||
Column("equipment_id", Integer, nullable=False),
|
||||
Column("enhancement_value", Integer, nullable=False),
|
||||
Column("enhancement_exp", Integer, nullable=False),
|
||||
Column("awakening_exp", Integer, nullable=False),
|
||||
Column("awakening_stage", Integer, nullable=False),
|
||||
Column("possible_awakening_flag", Integer, nullable=False),
|
||||
Column("get_date", TIMESTAMP, nullable=False, server_default=func.now()),
|
||||
UniqueConstraint("user", "equipment_id", name="sao_equipment_data_uk"),
|
||||
mysql_charset="utf8mb4",
|
||||
)
|
||||
|
||||
hero_log_data = Table(
|
||||
"sao_hero_log_data",
|
||||
metadata,
|
||||
@ -84,6 +104,34 @@ class SaoItemData(BaseData):
|
||||
self.logger.error(f"Failed to create SAO session for user {user_id}!")
|
||||
return None
|
||||
return result.lastrowid
|
||||
|
||||
def put_equipment_data(self, user_id: int, equipment_id: int, enhancement_value: int, enhancement_exp: int, awakening_exp: int, awakening_stage: int, possible_awakening_flag: int) -> Optional[int]:
|
||||
sql = insert(equipment_data).values(
|
||||
user=user_id,
|
||||
equipment_id=equipment_id,
|
||||
enhancement_value=enhancement_value,
|
||||
enhancement_exp=enhancement_exp,
|
||||
awakening_exp=awakening_exp,
|
||||
awakening_stage=awakening_stage,
|
||||
possible_awakening_flag=possible_awakening_flag,
|
||||
)
|
||||
|
||||
conflict = sql.on_duplicate_key_update(
|
||||
enhancement_value=enhancement_value,
|
||||
enhancement_exp=enhancement_exp,
|
||||
awakening_exp=awakening_exp,
|
||||
awakening_stage=awakening_stage,
|
||||
possible_awakening_flag=possible_awakening_flag,
|
||||
)
|
||||
|
||||
result = self.execute(conflict)
|
||||
if result is None:
|
||||
self.logger.error(
|
||||
f"{__name__} failed to insert equipment! user: {user_id}, equipment_id: {equipment_id}"
|
||||
)
|
||||
return None
|
||||
|
||||
return result.lastrowid
|
||||
|
||||
def put_hero_log(self, user_id: int, user_hero_log_id: int, log_level: int, log_exp: int, main_weapon: int, sub_equipment: int, skill_slot1_skill_id: int, skill_slot2_skill_id: int, skill_slot3_skill_id: int, skill_slot4_skill_id: int, skill_slot5_skill_id: int) -> Optional[int]:
|
||||
sql = insert(hero_log_data).values(
|
||||
@ -144,6 +192,23 @@ class SaoItemData(BaseData):
|
||||
return None
|
||||
|
||||
return result.lastrowid
|
||||
|
||||
def get_user_equipments(
|
||||
self, user_id: int
|
||||
) -> Optional[List[Row]]:
|
||||
"""
|
||||
A catch-all equipments lookup given a profile
|
||||
"""
|
||||
sql = equipment_data.select(
|
||||
and_(
|
||||
equipment_data.c.user == user_id,
|
||||
)
|
||||
)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchall()
|
||||
|
||||
def get_hero_log(
|
||||
self, user_id: int, user_hero_log_id: int = None
|
||||
@ -167,7 +232,7 @@ class SaoItemData(BaseData):
|
||||
self, user_id: int
|
||||
) -> Optional[List[Row]]:
|
||||
"""
|
||||
A catch-all hero lookup given a profile and user_party_team_id and ID specifiers
|
||||
A catch-all hero lookup given a profile
|
||||
"""
|
||||
sql = hero_log_data.select(
|
||||
and_(
|
||||
|
@ -264,6 +264,14 @@ class SaoStaticData(BaseData):
|
||||
return None
|
||||
return [list[2] for list in result.fetchall()]
|
||||
|
||||
def get_equipment_id(self, equipmentId: int) -> Optional[Dict]:
|
||||
sql = equipment.select(equipment.c.equipmentId == equipmentId)
|
||||
|
||||
result = self.execute(sql)
|
||||
if result is None:
|
||||
return None
|
||||
return result.fetchone()
|
||||
|
||||
def get_equipment_ids(self, version: int, enabled: bool) -> Optional[List[Dict]]:
|
||||
sql = equipment.select(equipment.c.version == version and equipment.c.enabled == enabled).order_by(
|
||||
equipment.c.equipmentId.asc()
|
||||
|
Loading…
Reference in New Issue
Block a user