diff --git a/sc2reader/data/attributes.json b/sc2reader/data/attributes.json index b0bffe78..aa651dc2 100644 --- a/sc2reader/data/attributes.json +++ b/sc2reader/data/attributes.json @@ -298,7 +298,10 @@ "T5": "Team 5", "T6": "Team 6", "T7": "Team 7", - "T8": "Team 8" + "T8": "Team 8", + "T9": "Team 9", + "T10": "Team 10", + "T11": "Team 11" } ], "3000": [ @@ -697,10 +700,17 @@ "Commander", { "": "Pick Commander", + "Abat": "Abathur", + "Alar": "Alarak", "Arta": "Artanis", + "Deha": "Dehaka", + "Feni": "Fenix", + "Horn": "Horner", "Kara": "Karax", "Kerr": "Kerrigan", + "Nova": "Nova", "Rayn": "Raynor", + "Stuk": "Stukov", "Swan": "Swann", "Vora": "Vorazun", "Zaga": "Zagara" diff --git a/sc2reader/objects.py b/sc2reader/objects.py index 203a7340..eaa2e28b 100644 --- a/sc2reader/objects.py +++ b/sc2reader/objects.py @@ -124,7 +124,7 @@ def __init__(self, sid, slot_data): #: self.hero_mount = slot_data['mount'] - + #: The unique Battle.net account identifier in the form of #: -S2-- self.toon_handle = slot_data['toon_handle'] @@ -164,10 +164,13 @@ class Player(object): :param dict detail_data: The detail data associated with this player :param dict attribute_data: The attribute data associated with this player """ - def __init__(self, pid, detail_data, attribute_data): + def __init__(self, pid, slot_data, detail_data, attribute_data): #: The player's unique in-game player id self.pid = int(pid) + #: The player's replay.initData slot data + self.slot_data = slot_data + #: The replay.details data on this player self.detail_data = detail_data @@ -197,6 +200,24 @@ def __init__(self, pid, detail_data, attribute_data): #: One of Protoss, Terran, Zerg self.play_race = LOCALIZED_RACES.get(detail_data['race'], detail_data['race']) + #: The co-op commander the player picked + #: Kerrigan, Raynor, etc. + self.commander = slot_data['commander'] + if self.commander is not None: + self.commander = self.commander.decode('utf8') + + #: The level of the co-op commander + #: 1-15 or None + self.commander_level = slot_data['commander_level'] + + #: The mastery level of the co-op commander + #: >0 or None + self.commander_mastery_level = slot_data['commander_mastery_talents'] + + #: The mastery talents picked for the co-op commander + #: list of longs of length 6, each between 0 and 30 + self.commander_mastery_talents = slot_data['commander_mastery_talents'] + #: A reference to a :class:`~sc2reader.utils.Color` object representing the player's color self.color = utils.Color(**detail_data['color']) @@ -290,7 +311,7 @@ class Computer(Entity, Player): """ def __init__(self, sid, slot_data, pid, detail_data, attribute_data): Entity.__init__(self, sid, slot_data) - Player.__init__(self, pid, detail_data, attribute_data) + Player.__init__(self, pid, slot_data, detail_data, attribute_data) #: The auto-generated in-game name for this computer player self.name = detail_data['name'] @@ -316,7 +337,7 @@ class Participant(Entity, User, Player): def __init__(self, sid, slot_data, uid, init_data, pid, detail_data, attribute_data): Entity.__init__(self, sid, slot_data) User.__init__(self, uid, init_data) - Player.__init__(self, pid, detail_data, attribute_data) + Player.__init__(self, pid, slot_data, detail_data, attribute_data) def __str__(self): return "Player {0} - {1} ({2})".format(self.pid, self.name, self.play_race) @@ -563,7 +584,7 @@ def __init__(self, contents): # Leave early so we dont barf. Turns out ggtracker doesnt need # any of the map data thats loaded below. return - + #: Load screen type: 0 = default, 1 = custom self.load_screen_type = data.read_uint32() diff --git a/sc2reader/resources.py b/sc2reader/resources.py index a24f07b5..0c797015 100644 --- a/sc2reader/resources.py +++ b/sc2reader/resources.py @@ -416,7 +416,8 @@ def load_players(self): self.entities.append(Observer(slot_id, slot_data, user_id, initData['user_initial_data'][user_id], player_id)) player_id += 1 - elif slot_data['control'] == 3: + elif slot_data['control'] == 3 and detail_id < len(details['players']): + # detail_id check needed for coop self.entities.append(Computer(slot_id, slot_data, player_id, details['players'][detail_id], self.attributes.get(player_id, dict()))) detail_id += 1 player_id += 1 diff --git a/test_replays/coop/CoA.SC2Replay b/test_replays/coop/CoA.SC2Replay new file mode 100644 index 00000000..db64d833 Binary files /dev/null and b/test_replays/coop/CoA.SC2Replay differ diff --git a/test_replays/test_all.py b/test_replays/test_all.py index d04e2089..d66cc528 100644 --- a/test_replays/test_all.py +++ b/test_replays/test_all.py @@ -568,6 +568,13 @@ def test_64469(self): factory = sc2reader.factories.SC2Factory() replay = factory.load_replay(replayfilename) + def test_coop(self): + for replayfilename in [ + "test_replays/coop/CoA.SC2Replay", + ]: + factory = sc2reader.factories.SC2Factory() + replay = factory.load_replay(replayfilename) + class TestGameEngine(unittest.TestCase): class TestEvent(object):