Skip to content

Commit b61c8fc

Browse files
committed
Adding Cartype and Upgrades Level
1 parent 59a5302 commit b61c8fc

File tree

1 file changed

+98
-9
lines changed

1 file changed

+98
-9
lines changed

opengsq/protocols/flatout2.py

Lines changed: 98 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,59 @@ class Flatout2(ProtocolBase):
2626
PACKET_END = b"\x2e\x55\x19\xb4\xe1\x4f\x81\x4a"
2727

2828
# Car Type Identifiers (byte at position -8 from end)
29+
# Based on comprehensive analysis: Car Type + Upgrade Setting combinations
2930
CAR_TYPE_IDENTIFIERS = {
30-
0x08: "Jeder", # Alle Wagentypen erlaubt
31-
0x18: "Derby", # Derby-Wagen
32-
0x28: "Rennen", # Rennwagen
33-
0x38: "Strasse", # Straßenwagen
34-
0xE8: "Wie Host", # Wagentyp wie Host-Einstellung
31+
# Jeder (Alle Wagentypen erlaubt)
32+
0x00: "Jeder (0% Upgrades)",
33+
0x04: "Jeder (50% Upgrades)",
34+
0x08: "Jeder (100% Upgrades)",
35+
0x0C: "Jeder (Wählbare Upgrades)",
36+
37+
# Derby-Wagen
38+
0x10: "Derby (0% Upgrades)",
39+
0x14: "Derby (50% Upgrades)",
40+
0x18: "Derby (100% Upgrades)",
41+
0x1C: "Derby (Wählbare Upgrades)",
42+
43+
# Rennwagen
44+
0x20: "Rennen (0% Upgrades)",
45+
0x24: "Rennen (50% Upgrades)",
46+
0x28: "Rennen (100% Upgrades)",
47+
0x2C: "Rennen (Wählbare Upgrades)",
48+
49+
# Straßenwagen
50+
0x30: "Strasse (0% Upgrades)",
51+
0x34: "Strasse (50% Upgrades)",
52+
0x38: "Strasse (100% Upgrades)",
53+
0x3C: "Strasse (Wählbare Upgrades)",
54+
55+
# Wie Host
56+
0xD0: "Wie Host (0% Upgrades)",
57+
0xD4: "Wie Host (50% Upgrades)",
58+
0xD8: "Wie Host (100% Upgrades)",
59+
0xDC: "Wie Host (Wählbare Upgrades)",
60+
61+
# Legacy support for old single-byte car type detection
62+
0xE8: "Wie Host", # Old identifier, kept for backward compatibility
63+
}
64+
65+
# Separate mappings for detailed analysis
66+
CAR_TYPE_BASE = {
67+
0x00: "Jeder", 0x04: "Jeder", 0x08: "Jeder", 0x0C: "Jeder",
68+
0x10: "Derby", 0x14: "Derby", 0x18: "Derby", 0x1C: "Derby",
69+
0x20: "Rennen", 0x24: "Rennen", 0x28: "Rennen", 0x2C: "Rennen",
70+
0x30: "Strasse", 0x34: "Strasse", 0x38: "Strasse", 0x3C: "Strasse",
71+
0xD0: "Wie Host", 0xD4: "Wie Host", 0xD8: "Wie Host", 0xDC: "Wie Host",
72+
0xE8: "Wie Host", # Legacy
73+
}
74+
75+
UPGRADE_SETTINGS = {
76+
0x00: "0%", 0x04: "50%", 0x08: "100%", 0x0C: "Wählbar",
77+
0x10: "0%", 0x14: "50%", 0x18: "100%", 0x1C: "Wählbar",
78+
0x20: "0%", 0x24: "50%", 0x28: "100%", 0x2C: "Wählbar",
79+
0x30: "0%", 0x34: "50%", 0x38: "100%", 0x3C: "Wählbar",
80+
0xD0: "0%", 0xD4: "50%", 0xD8: "100%", 0xDC: "Wählbar",
81+
0xE8: "Unknown", # Legacy
3582
}
3683

3784
# Game Mode Identifiers (byte at position -7 from end)
@@ -245,6 +292,41 @@ def _extract_car_type(self, data: bytes) -> str:
245292
print(f"Error extracting car type: {e}")
246293
return "Unknown"
247294

295+
def _extract_car_type_base(self, data: bytes) -> str:
296+
"""
297+
Extracts the base car type (without upgrade info) from the payload data.
298+
299+
:param data: The complete response data
300+
:return: The base car type name or "Unknown" if not found
301+
"""
302+
try:
303+
if len(data) >= 8:
304+
car_type_id = data[-8] # 8 bytes from end
305+
return self.CAR_TYPE_BASE.get(car_type_id, f"Unknown (0x{car_type_id:02X})")
306+
else:
307+
return "Unknown"
308+
except Exception as e:
309+
print(f"Error extracting base car type: {e}")
310+
return "Unknown"
311+
312+
def _extract_upgrade_setting(self, data: bytes) -> str:
313+
"""
314+
Extracts the upgrade setting from the payload data.
315+
Upgrade setting is encoded in the car type byte at offset -8.
316+
317+
:param data: The complete response data
318+
:return: The upgrade setting or "Unknown" if not found
319+
"""
320+
try:
321+
if len(data) >= 8:
322+
car_type_id = data[-8] # 8 bytes from end
323+
return self.UPGRADE_SETTINGS.get(car_type_id, f"Unknown (0x{car_type_id:02X})")
324+
else:
325+
return "Unknown"
326+
except Exception as e:
327+
print(f"Error extracting upgrade setting: {e}")
328+
return "Unknown"
329+
248330
def _extract_game_mode(self, data: bytes) -> str:
249331
"""
250332
Extracts the game mode from the payload data.
@@ -371,10 +453,15 @@ def _parse_response(self, br: BinaryReader, original_data: bytes) -> Status:
371453
server_name = self._read_utf16_string(br)
372454
info["hostname"] = server_name
373455

374-
# Extract car type from the payload
375-
# Car type identifier at offset -8
376-
car_type = self._extract_car_type(original_data)
377-
info["car_type"] = car_type
456+
# Extract car type and upgrade information from the payload
457+
# Car type identifier at offset -8 (includes upgrade settings)
458+
car_type_full = self._extract_car_type(original_data)
459+
car_type_base = self._extract_car_type_base(original_data)
460+
upgrade_setting = self._extract_upgrade_setting(original_data)
461+
462+
info["car_type"] = car_type_full # Full description with upgrades
463+
info["car_type_base"] = car_type_base # Base car type only
464+
info["upgrade_setting"] = upgrade_setting # Upgrade setting only
378465

379466
# Extract game mode from the payload
380467
# Game mode identifier at offset -7
@@ -449,6 +536,8 @@ def _parse_response(self, br: BinaryReader, original_data: bytes) -> Status:
449536
# Set defaults on error
450537
info.setdefault("hostname", "Unknown Server")
451538
info.setdefault("car_type", "Unknown")
539+
info.setdefault("car_type_base", "Unknown")
540+
info.setdefault("upgrade_setting", "Unknown")
452541
info.setdefault("game_mode", "Unknown")
453542
info.setdefault("map", "Unknown Map")
454543
info.setdefault("lap_count", None)

0 commit comments

Comments
 (0)