Skip to content

Commit fbec6a7

Browse files
committed
Add basic context loading.
A unit type name -> unit type id map is needed to use the Born and Init events fully. A unit tag index -> unit map is needed to use the Positions event.
1 parent 9780cbc commit fbec6a7

File tree

2 files changed

+106
-5
lines changed

2 files changed

+106
-5
lines changed

sc2reader/events/tracker.py

Lines changed: 97 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ def __init__(self, frames):
88
def __str__(self):
99
return json.dumps(self.__dict__)
1010

11+
def load_context(self, replay):
12+
pass
13+
14+
1115
class PlayerStatsEvent(TrackerEvent):
1216
name = 'PlayerStatsEvent'
1317

@@ -119,6 +123,10 @@ def __init__(self, frames, data):
119123
#: The total vespene value of all active forces
120124
self.vespene_used_active_forces = self.stats[32]
121125

126+
def load_context(self, replay):
127+
self.player = replay.player[self.pid]
128+
129+
122130
class UnitBornEvent(TrackerEvent):
123131
name = 'UnitBornEvent'
124132

@@ -152,6 +160,19 @@ def __init__(self, frames, data):
152160
#: The map location of the unit birth
153161
self.location = (self.x, self.y)
154162

163+
def load_context(self, replay):
164+
if self.control_pid: # 0 means neutral unit
165+
self.unit_controller = replay.player[self.control_pid]
166+
167+
if self.upkeep_pid: # 0 means neutral unit
168+
self.unit_upkeeper = replay.player[self.upkeep_pid]
169+
170+
if self.unit_id in replay.objects:
171+
self.unit = replay.objects[self.unit_id]
172+
else:
173+
# Create a new unit, but we don't have a type name map yet!
174+
self.unit = None
175+
155176

156177
class UnitDiedEvent(TrackerEvent):
157178
name = 'UnitDiedEvent'
@@ -180,6 +201,16 @@ def __init__(self, frames, data):
180201
#: The map location the unit was killed at.
181202
self.location = (self.x, self.y)
182203

204+
def load_context(self, replay):
205+
if self.unit_id in replay.objects:
206+
self.unit = replay.objects[self.unit_id]
207+
else:
208+
# Create a new unit, but we don't have a type name map yet!
209+
self.unit = None
210+
211+
if self.killer_pid: # This field isn't always available
212+
self.killer = replay.player[self.killer_pid]
213+
183214

184215
class UnitOwnerChangeEvent(TrackerEvent):
185216
name = 'UnitOwnerChangeEvent'
@@ -202,7 +233,20 @@ def __init__(self, frames, data):
202233
#: The new id of the player that pays upkeep for this unit.
203234
self.upkeep_pid = data[3]
204235

205-
fields = ['unit_tag_index','unit_tag_recycle','control_player_id','upkeep_player_id']
236+
237+
def load_context(self, replay):
238+
if self.control_pid: # 0 means neutral unit
239+
self.unit_controller = replay.player[self.control_pid]
240+
241+
if self.upkeep_pid: # 0 means neutral unit
242+
self.unit_upkeeper = replay.player[self.upkeep_pid]
243+
244+
if self.unit_id in replay.objects:
245+
self.unit = replay.objects[self.unit_id]
246+
else:
247+
# Create a new unit, but we don't have a type name map yet!
248+
self.unit = None
249+
206250

207251
class UnitTypeChangeEvent(TrackerEvent):
208252
name = 'UnitTypeChangeEvent'
@@ -222,6 +266,14 @@ def __init__(self, frames, data):
222266
#: The the new unit type name
223267
self.unit_type_name = data[2]
224268

269+
def load_context(self, replay):
270+
if self.unit_id in replay.objects:
271+
self.unit = replay.objects[self.unit_id]
272+
else:
273+
# Create a new unit, but we don't have a type name map yet!
274+
self.unit = None
275+
276+
225277
class UpgradeCompleteEvent(TrackerEvent):
226278
name = 'UpgradeCompleteEvent'
227279

@@ -237,6 +289,12 @@ def __init__(self, frames, data):
237289
#: The number of times this upgrade as been researched
238290
self.count = data[2]
239291

292+
293+
def load_context(self, replay):
294+
self.player = replay.player[self.pid]
295+
# TODO: We don't have upgrade -> ability maps
296+
297+
240298
class UnitInitEvent(TrackerEvent):
241299
name = 'UnitInitEvent'
242300

@@ -252,21 +310,38 @@ def __init__(self, frames, data):
252310
#: The unique id of the stated unit
253311
self.unit_id = self.unit_id_index << 16 | self.unit_id_recycle
254312

313+
#: The the new unit type name
314+
self.unit_type_name = data[2]
315+
255316
#: The id of the player that controls this unit.
256-
self.control_pid = data[2]
317+
self.control_pid = data[3]
257318

258319
#: The id of the player that pays upkeep for this unit.
259-
self.upkeep_pid = data[3]
320+
self.upkeep_pid = data[4]
260321

261322
#: The x coordinate of the location
262-
self.x = data[4]
323+
self.x = data[5]
263324

264325
#: The y coordinate of the location
265-
self.y = data[5]
326+
self.y = data[6]
266327

267328
#: The map location the unit was started at
268329
self.location = (self.x, self.y)
269330

331+
def load_context(self, replay):
332+
if self.control_pid: # 0 means neutral unit
333+
self.unit_controller = replay.player[self.control_pid]
334+
335+
if self.upkeep_pid: # 0 means neutral unit
336+
self.unit_upkeeper = replay.player[self.upkeep_pid]
337+
338+
if self.unit_id in replay.objects:
339+
self.unit = replay.objects[self.unit_id]
340+
else:
341+
# Create a new unit, but we don't have a type name map yet!
342+
self.unit = None
343+
344+
270345
class UnitDoneEvent(TrackerEvent):
271346
name = 'UnitDoneEvent'
272347

@@ -282,6 +357,14 @@ def __init__(self, frames, data):
282357
#: The unique id of the finished unit
283358
self.unit_id = self.unit_id_index << 16 | self.unit_id_recycle
284359

360+
def load_context(self, replay):
361+
if self.unit_id in replay.objects:
362+
self.unit = replay.objects[self.unit_id]
363+
else:
364+
# Create a new unit, but we don't have a type name map yet!
365+
self.unit = None
366+
367+
285368
class UnitPositionsEvent(TrackerEvent):
286369
name = 'UnitPositionsEvent'
287370

@@ -293,3 +376,12 @@ def __init__(self, frames, data):
293376

294377
#: ???
295378
self.items = data[1]
379+
380+
""" We need to be able to find units without the recycle id, can't do this yet!
381+
unitTagIndex = event['m_firstUnitIndex']
382+
for i in xrange(len(event['m_items']) / 3):
383+
unitTagIndex += event['m_items'][i * 3 + 0]
384+
x = event['m_items'][i * 3 + 1] * 4
385+
y = event['m_items'][i * 3 + 2] * 4
386+
# the unit with unitTagIndex is now at coordinate (x, y)
387+
"""

sc2reader/resources.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,15 @@ def load_events(self):
502502
elif is_ability:
503503
event.player.ability_events.append(event)
504504

505+
def load_tracker_events(self):
506+
if 'replay.tracker.events' not in self.raw_data:
507+
return
508+
509+
self.tracker_events = self.raw_data['replay.tracker.events']
510+
511+
for event in self.tracker_events:
512+
event.load_context(self)
513+
505514
def register_reader(self, data_file, reader, filterfunc=lambda r: True):
506515
"""
507516
Allows you to specify your own reader for use when reading the data

0 commit comments

Comments
 (0)