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
|
+ POKKÉN TOURNAMENT
|
||||||
+ Final Online
|
+ Final Online
|
||||||
|
|
||||||
|
+ Sword Art Online Arcade (partial support)
|
||||||
|
+ Final
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
- python 3 (tested working with 3.9 and 3.10, other versions YMMV)
|
- python 3 (tested working with 3.9 and 3.10, other versions YMMV)
|
||||||
- pip
|
- 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, 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_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_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 }")
|
self.logger.info(f"User Authenticated: { access_code } | { user_id }")
|
||||||
|
|
||||||
@ -145,9 +148,19 @@ class SaoBase:
|
|||||||
|
|
||||||
def handle_c602(self, request: Any) -> bytes:
|
def handle_c602(self, request: Any) -> bytes:
|
||||||
#have_object/get_equipment_user_data_list
|
#have_object/get_equipment_user_data_list
|
||||||
equipmentIdsData = self.game_data.static.get_equipment_ids(0, True)
|
req = bytes.fromhex(request)[24:]
|
||||||
|
req_struct = Struct(
|
||||||
resp = SaoGetEquipmentUserDataListResponse(int.from_bytes(bytes.fromhex(request[:4]), "big")+1, equipmentIdsData)
|
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()
|
return resp.make()
|
||||||
|
|
||||||
def handle_c604(self, request: Any) -> bytes:
|
def handle_c604(self, request: Any) -> bytes:
|
||||||
@ -510,10 +523,11 @@ class SaoBase:
|
|||||||
randomized_unanalyzed_id = choice(data_unanalyzed)
|
randomized_unanalyzed_id = choice(data_unanalyzed)
|
||||||
|
|
||||||
heroList = self.game_data.static.get_hero_id(randomized_unanalyzed_id['CommonRewardId'])
|
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:
|
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)
|
self.game_data.item.put_hero_log(req_data.user_id, randomized_unanalyzed_id['CommonRewardId'], 1, 0, 101000016, 0, 30086, 1001, 1002, 0, 0)
|
||||||
|
if equipmentList:
|
||||||
# Item and Equipments saving will be done later here
|
self.game_data.item.put_equipment_data(req_data.user_id, randomized_unanalyzed_id['CommonRewardId'], 1, 200, 0, 0, 0)
|
||||||
|
|
||||||
# Send response
|
# Send response
|
||||||
|
|
||||||
@ -532,4 +546,4 @@ class SaoBase:
|
|||||||
def handle_c90a(self, request: Any) -> bytes: #should be tweaked for proper item unlock
|
def handle_c90a(self, request: Any) -> bytes: #should be tweaked for proper item unlock
|
||||||
#quest/episode_play_end_unanalyzed_log_fixed
|
#quest/episode_play_end_unanalyzed_log_fixed
|
||||||
resp = SaoEpisodePlayEndUnanalyzedLogFixedResponse(int.from_bytes(bytes.fromhex(request[:4]), "big")+1)
|
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)
|
super().__init__(data)
|
||||||
|
|
||||||
class SaoGetEquipmentUserDataListResponse(SaoBaseResponse):
|
class SaoGetEquipmentUserDataListResponse(SaoBaseResponse):
|
||||||
def __init__(self, cmd, equipmentIdsData) -> None:
|
def __init__(self, cmd, equipment_data) -> None:
|
||||||
super().__init__(cmd)
|
super().__init__(cmd)
|
||||||
self.result = 1
|
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
|
# equipment_user_data_list
|
||||||
self.user_equipment_id = list(map(str,equipmentIdsData)) #str
|
self.user_equipment_id = list(map(str,self.user_equipment_id)) #str
|
||||||
self.equipment_id = equipmentIdsData #int
|
self.equipment_id = list(map(int,self.user_equipment_id)) #int
|
||||||
self.enhancement_value = 10 #short
|
self.enhancement_value = list(map(int,self.enhancement_value)) #short
|
||||||
self.max_enhancement_value_extended_num = 10 #short
|
self.max_enhancement_value_extended_num = list(map(int,self.max_enhancement_value_extended_num)) #short
|
||||||
self.enhancement_exp = 1000 #int
|
self.enhancement_exp = list(map(int,self.enhancement_exp)) #int
|
||||||
self.possible_awakening_flag = 0 #byte
|
self.possible_awakening_flag = list(map(int,self.possible_awakening_flag)) #byte
|
||||||
self.awakening_stage = 0 #short
|
self.awakening_stage = list(map(int,self.awakening_stage)) #short
|
||||||
self.awakening_exp = 0 #int
|
self.awakening_exp = list(map(int,self.awakening_exp)) #int
|
||||||
self.property1_property_id = 0 #int
|
self.property1_property_id = 0 #int
|
||||||
self.property1_value1 = 0 #int
|
self.property1_value1 = 0 #int
|
||||||
self.property1_value2 = 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_size=len(self.user_equipment_id[i]) * 2,
|
||||||
user_equipment_id=[ord(x) for x in self.user_equipment_id[i]],
|
user_equipment_id=[ord(x) for x in self.user_equipment_id[i]],
|
||||||
equipment_id=self.equipment_id[i],
|
equipment_id=self.equipment_id[i],
|
||||||
enhancement_value=self.enhancement_value,
|
enhancement_value=self.enhancement_value[i],
|
||||||
max_enhancement_value_extended_num=self.max_enhancement_value_extended_num,
|
max_enhancement_value_extended_num=self.max_enhancement_value_extended_num[i],
|
||||||
enhancement_exp=self.enhancement_exp,
|
enhancement_exp=self.enhancement_exp[i],
|
||||||
possible_awakening_flag=self.possible_awakening_flag,
|
possible_awakening_flag=self.possible_awakening_flag[i],
|
||||||
awakening_stage=self.awakening_stage,
|
awakening_stage=self.awakening_stage[i],
|
||||||
awakening_exp=self.awakening_exp,
|
awakening_exp=self.awakening_exp[i],
|
||||||
property1_property_id=self.property1_property_id,
|
property1_property_id=self.property1_property_id,
|
||||||
property1_value1=self.property1_value1,
|
property1_value1=self.property1_value1,
|
||||||
property1_value2=self.property1_value2,
|
property1_value2=self.property1_value2,
|
||||||
|
@ -8,6 +8,26 @@ from sqlalchemy.dialects.mysql import insert
|
|||||||
|
|
||||||
from core.data.schema import BaseData, metadata
|
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(
|
hero_log_data = Table(
|
||||||
"sao_hero_log_data",
|
"sao_hero_log_data",
|
||||||
metadata,
|
metadata,
|
||||||
@ -84,6 +104,34 @@ class SaoItemData(BaseData):
|
|||||||
self.logger.error(f"Failed to create SAO session for user {user_id}!")
|
self.logger.error(f"Failed to create SAO session for user {user_id}!")
|
||||||
return None
|
return None
|
||||||
return result.lastrowid
|
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]:
|
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(
|
sql = insert(hero_log_data).values(
|
||||||
@ -144,6 +192,23 @@ class SaoItemData(BaseData):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
return result.lastrowid
|
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(
|
def get_hero_log(
|
||||||
self, user_id: int, user_hero_log_id: int = None
|
self, user_id: int, user_hero_log_id: int = None
|
||||||
@ -167,7 +232,7 @@ class SaoItemData(BaseData):
|
|||||||
self, user_id: int
|
self, user_id: int
|
||||||
) -> Optional[List[Row]]:
|
) -> 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(
|
sql = hero_log_data.select(
|
||||||
and_(
|
and_(
|
||||||
|
@ -264,6 +264,14 @@ class SaoStaticData(BaseData):
|
|||||||
return None
|
return None
|
||||||
return [list[2] for list in result.fetchall()]
|
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]]:
|
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(
|
sql = equipment.select(equipment.c.version == version and equipment.c.enabled == enabled).order_by(
|
||||||
equipment.c.equipmentId.asc()
|
equipment.c.equipmentId.asc()
|
||||||
|
Loading…
Reference in New Issue
Block a user