Skip to content

Commit fe0f776

Browse files
committed
Functional v1.5 patch without datapack support.
1 parent a3c8c42 commit fe0f776

File tree

7 files changed

+595
-1121
lines changed

7 files changed

+595
-1121
lines changed

sc2reader/constants.py

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@
5555
#
5656

5757
RACE_CODES = {
58-
'rreT': 'Terran',
59-
'greZ': 'Zerg',
60-
'torP': 'Protoss',
61-
'DNAR': 'Random',
58+
'Terr': 'Terran',
59+
'Zerg': 'Zerg',
60+
'Prot': 'Protoss',
61+
'RAND': 'Random',
6262
}
6363
MESSAGE_CODES = {
6464
'0': 'All',
@@ -67,35 +67,35 @@
6767
'125': 'Ping',
6868
}
6969
TEAM_COLOR_CODES = {
70-
'10ct': "Red",
71-
'20ct': "Blue",
72-
'30ct': "Teal",
73-
'40ct': "Purple",
74-
'50ct': "Yellow",
75-
'60ct': "Orange",
76-
'70ct': "Green",
77-
'80ct': "Light Pink",
78-
'90ct': "Violet",
79-
'01ct': "Light Grey",
80-
'11ct': "Dark Green",
81-
'21ct': "Brown",
82-
'31ct': "Light Green",
83-
'41ct': "Dark Grey",
84-
'51ct': "Pink",
85-
'61ct': "??",
70+
'tc01': "Red",
71+
'tc02': "Blue",
72+
'tc03': "Teal",
73+
'tc04': "Purple",
74+
'tc05': "Yellow",
75+
'tc06': "Orange",
76+
'tc07': "Green",
77+
'tc08': "Light Pink",
78+
'tc09': "Violet",
79+
'tc10': "Light Grey",
80+
'tc11': "Dark Green",
81+
'tc12': "Brown",
82+
'tc13': "Light Green",
83+
'tc14': "Dark Grey",
84+
'tc15': "Pink",
85+
'tc16': "??",
8686
}
8787
DIFFICULTY_CODES = {
88-
'yEyV': 'Very easy',
89-
'ysaE': 'Easy',
90-
'ideM': 'Medium',
91-
'draH': 'Hard',
92-
'dHyV': 'Very hard',
93-
'asnI': 'Insane',
88+
'VyEy': 'Very easy',
89+
'Easy': 'Easy',
90+
'Medi': 'Medium',
91+
'Hard': 'Hard',
92+
'VyHd': 'Very hard',
93+
'Insa': 'Insane',
9494
}
9595
GAME_TYPE_CODES = {
96-
'virP': 'Private',
97-
'buP': 'Public',
98-
'mmA': 'Ladder',
96+
'Priv': 'Private',
97+
'Pub': 'Public',
98+
'Amm': 'Ladder',
9999
'': 'Single',
100100
}
101101
# (name, key for team ids)
@@ -106,14 +106,14 @@
106106
'4v4': '4v4',
107107
'5v5': '5v5',
108108
'6v6': '6v6',
109-
'AFF': 'FFA',
109+
'FFA': 'FFA',
110110
}
111111
GAME_SPEED_CODES = {
112-
'rolS': 'Slower',
113-
'wolS': 'Slow',
114-
'mroN': 'Normal',
115-
'tsaF': 'Fast',
116-
'rsaF': 'Faster',
112+
'Slor': 'Slower',
113+
'Slow': 'Slow',
114+
'Norm': 'Normal',
115+
'Fast': 'Fast',
116+
'Fasr': 'Faster',
117117
}
118118

119119
GAME_SPEED_FACTOR = {
@@ -125,10 +125,10 @@
125125
}
126126

127127
PLAYER_TYPE_CODES = {
128-
'nmuH': 'Human',
129-
'pmoC': 'Computer',
130-
'nepO': 'Open',
131-
'dslC': 'Closed',
128+
'Humn': 'Human',
129+
'Comp': 'Computer',
130+
'Open': 'Open',
131+
'Clsd': 'Closed',
132132
}
133133
GATEWAY_CODES = {
134134
'US': 'Americas',
@@ -191,7 +191,7 @@
191191

192192
BUILD_ORDER_UPGRADES = {
193193
# Protoss
194-
194+
195195
## Forge
196196
0x2902 : 'Protoss Ground Weapons Level 1',
197197
0x2a02 : 'Protoss Ground Weapons Level 2',
@@ -221,14 +221,14 @@
221221
## Fleet Beacon
222222
0x0302 : 'Graviton Catapult',
223223
0x7102 : 'Anion Pulse-Crystals',
224-
225-
#Zerg
226-
224+
225+
#Zerg
226+
227227
## Roach Warren
228228
0x0402 : 'Gial Reconstitution',
229229
0x0502 : 'Tunneling Claws',
230230
## Ultralisk Cavern
231-
0x0602 : 'Chitinous Plating',
231+
0x0602 : 'Chitinous Plating',
232232
## Evo. chamber
233233
0x3702 : 'Zerg Melee Attacks Level 1',
234234
0x3802 : 'Zerg Melee Attacks Level 2',
@@ -249,10 +249,10 @@
249249
## Hydra den
250250
0x4502 : 'Grooved Spines',
251251
## Spire
252-
0x4602 : 'Zerg Flyer Attacks Level 1',
252+
0x4602 : 'Zerg Flyer Attacks Level 1',
253253
0x4702 : 'Zerg Flyer Attacks Level 2',
254254
0x4802 : 'Zerg Flyer Attacks Level 3',
255-
0x4902 : 'Zerg Flyer Carapace Level 1',
255+
0x4902 : 'Zerg Flyer Carapace Level 1',
256256
0x4a02 : 'Zerg Flyer Carapace Level 2',
257257
0x4b02 : 'Zerg Flyer Carapace Level 3',
258258
## Infestation pit

sc2reader/events.py

Lines changed: 77 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ def load_context(self, replay):
2121
@loggable
2222
class GameEvent(Event):
2323
"""Abstract Event Type, should not be directly instanciated"""
24-
def __init__(self, frame, pid, event_type, event_code):
24+
def __init__(self, frame, pid, event_type):
2525
super(GameEvent, self).__init__(frame, pid)
2626

2727
self.type = event_type
28-
self.code = event_code
2928
self.is_local = (pid != 16)
3029

3130
self.is_init = (event_type == 0x00)
@@ -52,35 +51,25 @@ def __init__(self, frame, pid, flags):
5251

5352
@loggable
5453
class ChatEvent(MessageEvent):
55-
def __init__(self, frame, pid, flags, buffer):
54+
def __init__(self, frame, pid, flags, target, text):
5655
super(ChatEvent, self).__init__(frame, pid, flags)
57-
58-
# A flag set without the 0x80 bit set is a player message. Messages
59-
# store a target (allies or all) as well as the message text.
60-
extension = (flags & 0x18) << 3
61-
self.target = flags & 0x03
62-
self.text = buffer.read_chars(buffer.read_byte() + extension)
56+
self.target = target
57+
self.text = text
6358
self.to_all = (self.target == 0)
6459
self.to_allies = (self.target == 2)
60+
self.to_observers = (self.target == 4)
6561

6662
@loggable
6763
class PacketEvent(MessageEvent):
68-
def __init__(self, frame, pid, flags, buffer):
64+
def __init__(self, frame, pid, flags, info):
6965
super(PacketEvent, self).__init__(frame, pid, flags)
70-
71-
# The 0x80 flag marks a network packet. I believe these mark packets
72-
# send over the network to establish latency or connectivity.
73-
self.data = buffer.read_chars(4)
66+
self.info = info
7467

7568
@loggable
7669
class PingEvent(MessageEvent):
77-
def __init__(self, frame, pid, flags, buffer):
70+
def __init__(self, frame, pid, flags, x, y):
7871
super(PingEvent, self).__init__(frame, pid, flags)
79-
80-
# The 0x83 flag indicates a minimap ping and contains the x and
81-
# y coordinates of that ping as the payload.
82-
self.x=buffer.read_int(LITTLE_ENDIAN)
83-
self.y=buffer.read_int(LITTLE_ENDIAN)
72+
self.x, self.y = x, y
8473

8574

8675
#############################################3
@@ -91,46 +80,73 @@ class UnknownEvent(GameEvent):
9180
pass
9281

9382
class PlayerJoinEvent(GameEvent):
94-
pass
83+
def __init__(self, frames, pid, event_type, flags):
84+
super(PlayerJoinEvent, self).__init__(frames, pid, event_type)
85+
self.flags = flags
9586

9687
class GameStartEvent(GameEvent):
9788
pass
9889

9990
class PlayerLeaveEvent(GameEvent):
10091
pass
10192

102-
class CameraMovementEvent(GameEvent):
103-
pass
93+
class CameraEvent(GameEvent):
94+
def __init__(self, frames, pid, event_type, x, y, distance, pitch, yaw, height_offset):
95+
super(CameraEvent, self).__init__(frames, pid, event_type)
96+
self.x, self.y = x, y
97+
self.distance = distance
98+
self.pitch = pitch
99+
self.yaw = yaw
100+
self.height_offset = height_offset
101+
102+
def __str__(self):
103+
return self._str_prefix() + " camera at ({}, {})".format(x,y)
104104

105105
class PlayerActionEvent(GameEvent):
106106
pass
107107

108108
@loggable
109-
class ResourceTransferEvent(PlayerActionEvent):
110-
def __init__(self, frames, pid, type, code, target, minerals, vespene):
111-
super(ResourceTransferEvent, self).__init__(frames, pid, type, code)
109+
class SendResourceEvent(PlayerActionEvent):
110+
def __init__(self, frames, pid, event_type, target, minerals, vespene, terrazine, custom):
111+
super(SendResourceEvent, self).__init__(frames, pid, event_type)
112112
self.sender = pid
113113
self.reciever = target
114114
self.minerals = minerals
115115
self.vespene = vespene
116+
self.terrazine = terrazine
117+
self.custom = custom
116118

117119
def __str__(self):
118-
return self._str_prefix() + "%s transfer %d minerals and %d gas to %s" % (self.sender, self.minerals, self.vespene, self.reciever)
120+
return self._str_prefix() + " transfer {} minerals, {} gas, {} terrazine, and {} custom to {}" % (self.minerals, self.vespene, self.terrazine, self.custom, self.reciever)
119121

120122
def load_context(self, replay):
121-
super(ResourceTransferEvent, self).load_context(replay)
123+
super(SendResourceEvent, self).load_context(replay)
122124
self.sender = replay.player[self.sender]
123125
self.reciever = replay.player[self.reciever]
124126

127+
@loggable
128+
class RequestResourceEvent(PlayerActionEvent):
129+
def __init__(self, frames, pid, event_type, minerals, vespene, terrazine, custom):
130+
super(RequestResourceEvent, self).__init__(frames, pid, event_type)
131+
self.minerals = minerals
132+
self.vespene = vespene
133+
self.terrazine = terrazine
134+
self.custom = custom
135+
136+
def __str__(self):
137+
return self._str_prefix() + " requests {} minerals, {} gas, {} terrazine, and {} custom" % (self.minerals, self.vespene, self.terrazine, self.custom)
138+
125139
@loggable
126140
class AbilityEvent(PlayerActionEvent):
127-
def __init__(self, framestamp, player, type, code, ability):
128-
super(AbilityEvent, self).__init__(framestamp, player, type, code)
141+
def __init__(self, frame, pid, event_type, ability):
142+
super(AbilityEvent, self).__init__(frame, pid, event_type)
129143
self.ability_code = ability
130144
self.ability_name = 'Uknown'
131145

132146
def load_context(self, replay):
133147
super(AbilityEvent, self).load_context(replay)
148+
if not replay.datapack:
149+
return
134150

135151
if self.ability_code not in replay.datapack.abilities:
136152
if not getattr(replay, 'marked_error', None):
@@ -153,18 +169,34 @@ def __str__(self):
153169

154170
@loggable
155171
class TargetAbilityEvent(AbilityEvent):
156-
def __init__(self, framestamp, player, type, code, ability, target):
157-
super(TargetAbilityEvent, self).__init__(framestamp, player, type, code, ability)
172+
def __init__(self, frame, pid, event_type, ability, target, player, team, location):
173+
super(TargetAbilityEvent, self).__init__(frame, pid, event_type, ability)
158174
self.target = None
159175
self.target_id, self.target_type = target
160-
#Forgot why we have to munge this
161-
self.target_type = self.target_type << 8 | 0x01
176+
self.target_owner = None
177+
self.target_owner_id = player
178+
self.target_team = None
179+
self.target_team_id = team
180+
self.location = location
181+
#Forgot why we have to munge this so lets not for now
182+
#self.target_type = self.target_type << 8 | 0x01
162183

163184

164185
def load_context(self, replay):
165186
super(TargetAbilityEvent, self).load_context(replay)
166-
uid = (self.target_id, self.target_type)
167187

188+
if self.target_owner_id:
189+
self.target_owner = replay.player[self.target_owner_id]
190+
191+
""" Disabled since team seems to always be the same player
192+
if self.target_team_id:
193+
self.target_team = replay.team[self.target_team_id]
194+
"""
195+
196+
if not replay.datapack:
197+
return
198+
199+
uid = (self.target_id, self.target_type)
168200
if uid in replay.objects:
169201
self.target = replay.objects[uid]
170202

@@ -189,20 +221,23 @@ def __str__(self):
189221

190222
@loggable
191223
class LocationAbilityEvent(AbilityEvent):
192-
def __init__(self, framestamp, player, type, code, ability, location):
193-
super(LocationAbilityEvent, self).__init__(framestamp, player, type, code, ability)
224+
def __init__(self, frame, pid, event_type, ability, location):
225+
super(LocationAbilityEvent, self).__init__(frame, pid, event_type, ability)
194226
self.location = location
195227

196228
def __str__(self):
197229
return AbilityEvent.__str__(self) + "; Location: %s" % str(self.location)
198230

231+
@loggable
199232
class SelfAbilityEvent(AbilityEvent):
200-
pass
233+
def __init__(self, frame, pid, event_type, ability, info):
234+
super(SelfAbilityEvent, self).__init__(frame, pid, event_type, ability)
235+
self.info = info
201236

202237
@loggable
203238
class HotkeyEvent(PlayerActionEvent):
204-
def __init__(self, framestamp, player, type, code, hotkey, deselect):
205-
super(HotkeyEvent, self).__init__(framestamp, player, type, code)
239+
def __init__(self, frame, pid, event_type, hotkey, deselect):
240+
super(HotkeyEvent, self).__init__(frame, pid, event_type)
206241
self.hotkey = hotkey
207242
self.deselect = deselect
208243

@@ -217,8 +252,8 @@ class GetFromHotkeyEvent(HotkeyEvent):
217252

218253
@loggable
219254
class SelectionEvent(PlayerActionEvent):
220-
def __init__(self, framestamp, player, type, code, bank, objects, deselect):
221-
super(SelectionEvent, self).__init__(framestamp, player, type, code)
255+
def __init__(self, frame, pid, event_type, bank, objects, deselect):
256+
super(SelectionEvent, self).__init__(frame, pid, event_type)
222257
self.bank = bank
223258
self.objects = objects
224259
self.deselect = deselect

0 commit comments

Comments
 (0)