Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add co-op support #44

Merged
merged 6 commits into from
May 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion sc2reader/data/attributes.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down Expand Up @@ -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"
Expand Down
31 changes: 26 additions & 5 deletions sc2reader/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
#: <region_id>-S2-<subregion>-<toon_id>
self.toon_handle = slot_data['toon_handle']
Expand Down Expand Up @@ -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):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have to pass slot_data through to Player because that's where the commander name is

#: 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

Expand Down Expand Up @@ -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'])

Expand Down Expand Up @@ -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']
Expand All @@ -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)
Expand Down Expand Up @@ -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()

Expand Down
3 changes: 2 additions & 1 deletion sc2reader/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']):
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be honest, I'm not really sure why this was necessary

# 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
Expand Down
Binary file added test_replays/coop/CoA.SC2Replay
Binary file not shown.
7 changes: 7 additions & 0 deletions test_replays/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down