From 7b8c113962a62c63563b9d0cc5e81811ebd0557b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 10:12:49 +0100 Subject: [PATCH 01/17] suits: Record a newly bought suit in monitor.state['Suits'] We can't fill in the 'id' field, but this is likely the FDevID of the suit type ? --- monitor.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/monitor.py b/monitor.py index baf79bfb..98dc4593 100644 --- a/monitor.py +++ b/monitor.py @@ -973,10 +973,22 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # • Loadoutname pass - # `BuySuit` has no useful info as of 4.0.0.13 elif event_type == 'BuySuit': - # alpha4 - should have 'SuitID' + # alpha4 : + # { "timestamp":"2021-04-29T09:03:37Z", "event":"BuySuit", "Name":"UtilitySuit_Class1", + # "Name_Localised":"Maverick Suit", "Price":150000, "SuitID":1698364934364699 } + self.state['Suits'].update( + {entry['SuitID']: { + 'name': entry['Name'], + 'locName': entry.get('Name_Localised', entry['Name']), + # 'id': ???, # Is this an FDev ID for suit type ? + 'suitId': entry['SuitID'], + 'slots': [], + }} + ) + # update credits + self.state['Credits'] -= entry.get('Price', 0) pass elif event_type == 'SellSuit': From c8d98bba2e2fa780ff5130d95410d1caca3304d7 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 10:23:39 +0100 Subject: [PATCH 02/17] suits: Guard against "no CAPI pull yet" on BuySuit --- monitor.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/monitor.py b/monitor.py index 98dc4593..f42b68b1 100644 --- a/monitor.py +++ b/monitor.py @@ -977,19 +977,23 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # alpha4 : # { "timestamp":"2021-04-29T09:03:37Z", "event":"BuySuit", "Name":"UtilitySuit_Class1", # "Name_Localised":"Maverick Suit", "Price":150000, "SuitID":1698364934364699 } - self.state['Suits'].update( - {entry['SuitID']: { - 'name': entry['Name'], - 'locName': entry.get('Name_Localised', entry['Name']), - # 'id': ???, # Is this an FDev ID for suit type ? - 'suitId': entry['SuitID'], - 'slots': [], - }} - ) + new_suit = { + 'name': entry['Name'], + 'locName': entry.get('Name_Localised', entry['Name']), + # 'id': ???, # Is this an FDev ID for suit type ? + 'suitId': entry['SuitID'], + 'slots': [], + } + if self.state['Suits'] is None: + self.state['Suits'] = {entry['SuitID']: new_suit} + + else: + self.state['Suits'].update( + {entry['SuitID']: new_suit} + ) # update credits self.state['Credits'] -= entry.get('Price', 0) - pass elif event_type == 'SellSuit': # Remove from known suits @@ -1002,6 +1006,9 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # • Name # • Price # • SuitID + # alpha4: + # { "timestamp":"2021-04-29T09:15:51Z", "event":"SellSuit", "SuitID":1698364937435505, + # "Name":"explorationsuit_class1", "Name_Localised":"Artemis Suit", "Price":90000 } # update credits total pass From aeca211a88287e9361f6a2e85ced13a460f4472c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 10:26:55 +0100 Subject: [PATCH 03/17] Suits: Handle 'SellSuit' --- monitor.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/monitor.py b/monitor.py index f42b68b1..b61eb965 100644 --- a/monitor.py +++ b/monitor.py @@ -1009,8 +1009,14 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # alpha4: # { "timestamp":"2021-04-29T09:15:51Z", "event":"SellSuit", "SuitID":1698364937435505, # "Name":"explorationsuit_class1", "Name_Localised":"Artemis Suit", "Price":90000 } + try: + self.state['Suits'].pop(entry['SuitID']) + + except KeyError: + logger.exception(f"SellSuit for a suit we didn't know about? {entry['SuitID']}") + # update credits total - pass + self.state['Credits'] += entry.get('Price', 0) elif event_type == 'UpgradeSuit': # alpha4 From 29a517ce115f07f0fc2849979bd9c174848c268a Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 10:34:03 +0100 Subject: [PATCH 04/17] Suits: Note that we need an 'UpgradeSuit' example still The journal document has to be mistaken about cost being in credits. --- monitor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/monitor.py b/monitor.py index b61eb965..c6c2836e 100644 --- a/monitor.py +++ b/monitor.py @@ -1027,7 +1027,8 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # • SuitID # • Class # • Cost - # Update credits total ? + # Update credits total ? It shouldn't even involve credits! + # Actual alpha4 - need to grind mats pass # `LoadoutEquipModule` has no instance-specific ID as of 4.0.0.13 From addb178d3dadea7b0bca427a4c610d6d129c0264 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 11:23:14 +0100 Subject: [PATCH 05/17] Suits: Handle 'CreateSuitLoadout' This entails converting the Journal supplied data into CAPI form. --- monitor.py | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/monitor.py b/monitor.py index c6c2836e..47249e2c 100644 --- a/monitor.py +++ b/monitor.py @@ -949,7 +949,32 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # • SuitName # • LoadoutID # • LoadoutName - pass + # alpha4: + # { "timestamp":"2021-04-29T09:37:08Z", "event":"CreateSuitLoadout", "SuitID":1698364940285172, + # "SuitName":"tacticalsuit_class1", "SuitName_Localised":"Dominator Suit", "LoadoutID":4293000001, + # "LoadoutName":"Dom L/K/K", "Modules":[ + # { + # "SlotName":"PrimaryWeapon1", + # "SuitModuleID":1698364962722310, + # "ModuleName":"wpn_m_assaultrifle_laser_fauto", + # "ModuleName_Localised":"TK Aphelion" + # }, + # { "SlotName":"PrimaryWeapon2", + # "SuitModuleID":1698364956302993, "ModuleName":"wpn_m_assaultrifle_kinetic_fauto", + # "ModuleName_Localised":"Karma AR-50" }, { "SlotName":"SecondaryWeapon", + # "SuitModuleID":1698292655291850, "ModuleName":"wpn_s_pistol_kinetic_sauto", + # "ModuleName_Localised":"Karma P-15" } ] } + new_loadout = { + 'loadoutSlotId': self.suit_loadout_id_from_loadoutid(entry['LoadoutID']), + 'suit': { + 'name': entry['SuitName'], + 'locName': entry.get('SuitName_Localised', entry['SuitName']), + 'suitId': entry['SuitID'], + }, + 'mame': entry['LoadoutName'], + 'slots': self.suit_loadout_slots_array_to_dict(entry['Modules']), + } + self.state['SuitLoadouts'][new_loadout['loadoutSlotId']] = new_loadout elif event_type == 'DeleteSuitLoadout': # We should remove this from the monitor.state record of loadouts. The slotid @@ -1618,6 +1643,29 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below return out + def suit_loadout_slots_array_to_dict(self, loadout: dict) -> dict: + """ + Return a CAPI-style Suit loadout from a Journal style dict. + + :param loadout: e.g. Journal 'CreateSuitLoadout'->'Modules'. + :return: CAPI-style dict for a suit loadout. + """ + loadout_slots = {x['SlotName']: x for x in loadout} + slots = {} + for s in ('PrimaryWeapon1', 'PrimaryWeapon2', 'SecondaryWeapon'): + if loadout_slots.get(s) is None: + continue + + slots[s] = { + 'name': loadout_slots[s]['ModuleName'], + # 'id': None, # FDevID ? + 'weaponrackId': loadout_slots[s]['SuitModuleID'], + 'locName': loadout_slots[s].get('ModuleName_Localised', loadout_slots[s]['ModuleName']), + 'locDescription': '', + } + + return slots + # singleton monitor = EDLogs() From bd1b86d3a3dd1356df733a1cc008b4dba729c91f Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 11:30:55 +0100 Subject: [PATCH 06/17] Suits/Loadouts: Always convert to dict form for simpler downstream code. --- PLUGINS.md | 15 +++++++-------- companion.py | 15 +++++++++++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/PLUGINS.md b/PLUGINS.md index e09e8359..d596a337 100644 --- a/PLUGINS.md +++ b/PLUGINS.md @@ -537,16 +537,15 @@ Content of `state` (updated to the current journal entry): | `Data` | `dict` | 'Data' MicroResources in Odyssey, `int` count each. | | `BackPack` | `dict` | `dict` of Odyssey MicroResources in backpack. | | `SuitCurrent` | `dict` | CAPI-returned data of currently worn suit. NB: May be `None` if no data. | -| `Suits` | `dict` or `list`[1] | CAPI-returned data of owned suits. NB: Type depends on if array is sparse or not. May be `None` if no data. | +| `Suits` | `dict`[1] | CAPI-returned data of owned suits. NB: May be `None` if no data. | | `SuitLoadoutCurrent` | `dict` | CAPI-returned data of current Suit Loadout. NB: May be `None` if no data. | -| `SuitLoadouts` | `dict` | CAPI-returned data of all Suit Loadouts. NB: May be `None` if no data. | +| `SuitLoadouts` | `dict`[1] | CAPI-returned data of all Suit Loadouts. NB: May be `None` if no data. | -[1] - With `Suits` there's a caveat depending on all the slots from 0 are -contiguously used or not. If they are then the type is `list` and -indexing is purely numeric. If not then it's a `dict` and you need to index it -with a string. There is `companion.index_possibly_sparse_list()` to aid -with this, or if you wish to iterate over it use `companion.listify()` to -fill in any gaps and have a `list` to operate on. +[1] - Some data from the CAPI is sometimes returned as a `list` (when all +members are present) and other times as an integer-keyed `dict` (when at +least one member is missing, so the indices are not contiguous). We choose to +always convert to the integer-keyed `dict` form so that code utilising the data +is simpler. New in version 4.1.6: diff --git a/companion.py b/companion.py index f1f38bd6..4243f817 100644 --- a/companion.py +++ b/companion.py @@ -680,13 +680,24 @@ class Session(object): return monitor.state['SuitCurrent'] = current_suit - monitor.state['Suits'] = data.get('suits') + # It's easier to always have this in the 'sparse array' dict form + suits = data.get('suits') + if isinstance(suits, list): + monitor.state['Suits'] = dict(enumerate(suits)) + + else: + monitor.state['Suits'] = suits if (suit_loadouts := data.get('loadouts')) is None: logger.warning('CAPI data had "suit" but no (suit) "loadouts"') monitor.state['SuitLoadoutCurrent'] = data.get('loadout') - monitor.state['SuitLoadouts'] = suit_loadouts + # It's easier to always have this in the 'sparse array' dict form + if isinstance(suit_loadouts, list): + monitor.state['SuitLoadouts'] = dict(enumerate(suit_loadouts)) + + else: + monitor.state['SuitLoadouts'] = suit_loadouts def close(self) -> None: """Close CAPI authorization session.""" From e24e0b354728101059ac7e655b85bdc009e16cb5 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 11:34:29 +0100 Subject: [PATCH 07/17] Suits: Update `DeleteSuitLoadout` code with alpha4 example Also slightly simplified this. Leaving the try/except for now, although it should no longer be necessary. --- monitor.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/monitor.py b/monitor.py index 47249e2c..f265604a 100644 --- a/monitor.py +++ b/monitor.py @@ -977,16 +977,17 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.state['SuitLoadouts'][new_loadout['loadoutSlotId']] = new_loadout elif event_type == 'DeleteSuitLoadout': - # We should remove this from the monitor.state record of loadouts. The slotid - # could end up valid due to CreateSuitLoadout events, but we won't have the - # correct new loadout data until next CAPI pull. - loadoutid = entry['LoadoutID'] - slotid = self.suit_loadout_id_from_loadoutid(loadoutid) - # This might be a Loadout that was created after our last CAPI pull. + # alpha4: + # { "timestamp":"2021-04-29T10:32:27Z", "event":"DeleteSuitLoadout", "SuitID":1698365752966423, + # "SuitName":"explorationsuit_class1", "SuitName_Localised":"Artemis Suit", "LoadoutID":4293000003, + # "LoadoutName":"Loadout 1" } + + slotid = self.suit_loadout_id_from_loadoutid(entry['LoadoutID']) try: self.state['SuitLoadouts'].pop(f'{slotid}') except KeyError: + # This should no longer happen, as we're now handling CreateSuitLoadout properly logger.exception(f"slot id {slotid} doesn't exist, not in last CAPI pull ?") elif event_type == 'RenameSuitLoadout': From e796684fc6c1d6f663453dc310e0516acd909ba8 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 11:40:59 +0100 Subject: [PATCH 08/17] Suits: Handle `RenameSuitLoadout` --- monitor.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/monitor.py b/monitor.py index f265604a..80adee29 100644 --- a/monitor.py +++ b/monitor.py @@ -997,7 +997,12 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # • SuitName # • LoadoutID # • Loadoutname - pass + # alpha4: + # { "timestamp":"2021-04-29T10:35:55Z", "event":"RenameSuitLoadout", "SuitID":1698365752966423, + # "SuitName":"explorationsuit_class1", "SuitName_Localised":"Artemis Suit", "LoadoutID":4293000003, + # "LoadoutName":"Art L/K" } + loadout_id = self.suit_loadout_id_from_loadoutid(entry['LoadoutID']) + self.state['SuitLoadouts'][loadout_id]['name'] = entry['LoadoutName'] elif event_type == 'BuySuit': # alpha4 : From 2253e45c18e98f3243aa9384dabf754f6b9706c5 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 11:45:06 +0100 Subject: [PATCH 09/17] Suits: Add some paranoia around Loadouts * Initialise to empty dict. * try/except in case CAPI pull hasn't happened yet when parsing Journal events. --- monitor.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/monitor.py b/monitor.py index 80adee29..b969f2d2 100644 --- a/monitor.py +++ b/monitor.py @@ -153,7 +153,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'SuitCurrent': None, 'Suits': None, 'SuitLoadoutCurrent': None, - 'SuitLoadouts': None, + 'SuitLoadouts': {}, } def start(self, root: 'tkinter.Tk') -> bool: # noqa: CCR001 @@ -982,13 +982,13 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # "SuitName":"explorationsuit_class1", "SuitName_Localised":"Artemis Suit", "LoadoutID":4293000003, # "LoadoutName":"Loadout 1" } - slotid = self.suit_loadout_id_from_loadoutid(entry['LoadoutID']) + loadout_id = self.suit_loadout_id_from_loadoutid(entry['LoadoutID']) try: - self.state['SuitLoadouts'].pop(f'{slotid}') + self.state['SuitLoadouts'].pop(f'{loadout_id}') except KeyError: # This should no longer happen, as we're now handling CreateSuitLoadout properly - logger.exception(f"slot id {slotid} doesn't exist, not in last CAPI pull ?") + logger.exception(f"loadout slot id {loadout_id} doesn't exist, not in last CAPI pull ?") elif event_type == 'RenameSuitLoadout': # alpha4 @@ -1002,7 +1002,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # "SuitName":"explorationsuit_class1", "SuitName_Localised":"Artemis Suit", "LoadoutID":4293000003, # "LoadoutName":"Art L/K" } loadout_id = self.suit_loadout_id_from_loadoutid(entry['LoadoutID']) - self.state['SuitLoadouts'][loadout_id]['name'] = entry['LoadoutName'] + try: + self.state['SuitLoadouts'][loadout_id]['name'] = entry['LoadoutName'] + + except KeyError: + logger.exception(f"loadout slot id {loadout_id} doesn't exist, not in last CAPI pull ?") elif event_type == 'BuySuit': # alpha4 : From 218073ed73dc262098128f4fed268c06e981e1cd Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 12:07:48 +0100 Subject: [PATCH 10/17] Suits: Remove weapon from all loadouts if sold. Also update credits total for the sale. --- monitor.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/monitor.py b/monitor.py index b969f2d2..90aa94a5 100644 --- a/monitor.py +++ b/monitor.py @@ -1103,8 +1103,22 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # • Name # • Price # • SuitModuleID + # alpha4: + # { "timestamp":"2021-04-29T10:50:34Z", "event":"SellWeapon", "Name":"wpn_m_assaultrifle_laser_fauto", + # "Name_Localised":"TK Aphelion", "Price":75000, "SuitModuleID":1698364962722310 } + + # We need to look over all Suit Loadouts for ones that used this specific weapon + # and update them to entirely empty that slot. + for sl in self.state['SuitLoadouts']: + for w in self.state['SuitLoadouts'][sl]['slots']: + if self.state['SuitLoadouts'][sl]['slots'][w]['weaponrackId'] == entry['SuitModuleID']: + self.state['SuitLoadouts'][sl]['slots'].pop(w) + # We've changed the dict, so iteration breaks, but also the weapon + # could only possibly have been here once. + break + # Update credits total - pass + self.state['Credits'] += entry.get('Price', 0) # `UpgradeWeapon` has no instance-specific ID as of 4.0.0.13 elif event_type == 'UpgradeWeapon': From d35f64ebd5d40c93c3071eccf7541f4ef75710f3 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 12:21:08 +0100 Subject: [PATCH 11/17] Suits: Handle `LoadoutRemoveModule` Currently this seems to only trigger if you 'overwrite' an equipped weapon with another one. The one being removed will be cited in this event. --- monitor.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/monitor.py b/monitor.py index 90aa94a5..76de2d98 100644 --- a/monitor.py +++ b/monitor.py @@ -1066,9 +1066,12 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # Actual alpha4 - need to grind mats pass - # `LoadoutEquipModule` has no instance-specific ID as of 4.0.0.13 elif event_type == 'LoadoutEquipModule': - # alpha4 - should have necessary IDs + # alpha4: + # { "timestamp":"2021-04-29T11:11:13Z", "event":"LoadoutEquipModule", "LoadoutName":"Dom L/K/K", + # "SuitID":1698364940285172, "SuitName":"tacticalsuit_class1", "SuitName_Localised":"Dominator Suit", + # "LoadoutID":4293000001, "SlotName":"PrimaryWeapon2", "ModuleName":"wpn_m_assaultrifle_laser_fauto", + # "ModuleName_Localised":"TK Aphelion", "SuitModuleID":1698372938719590 } pass elif event_type == 'LoadoutRemoveModule': @@ -1082,7 +1085,13 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # • LoadoutName # • ModuleName: weapon or other item removed from loadout # • SuitModuleID - pass + # alpha4 - triggers if selecting an already-equipped weapon into a different slot + # { "timestamp":"2021-04-29T11:11:13Z", "event":"LoadoutRemoveModule", "LoadoutName":"Dom L/K/K", + # "SuitID":1698364940285172, "SuitName":"tacticalsuit_class1", "SuitName_Localised":"Dominator Suit", + # "LoadoutID":4293000001, "SlotName":"PrimaryWeapon1", "ModuleName":"wpn_m_assaultrifle_laser_fauto", + # "ModuleName_Localised":"TK Aphelion", "SuitModuleID":1698372938719590 } + loadout_id = self.suit_loadout_id_from_loadoutid(entry['LoadoutID']) + self.state['SuitLoadouts'][loadout_id]['slots'].pop(entry['SlotName']) # `BuyWeapon` has no instance-specific ID as of 4.0.0.13 elif event_type == 'BuyWeapon': From d27075cb38342823099e041ca3adbe2bde9fc7ee Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 12:28:45 +0100 Subject: [PATCH 12/17] Suits: Handle `LoadoutEquipModule` event We're assuming weapons only at this point. Might need adjustment when we get access to engineering. --- monitor.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/monitor.py b/monitor.py index 76de2d98..cac535bc 100644 --- a/monitor.py +++ b/monitor.py @@ -1072,7 +1072,14 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # "SuitID":1698364940285172, "SuitName":"tacticalsuit_class1", "SuitName_Localised":"Dominator Suit", # "LoadoutID":4293000001, "SlotName":"PrimaryWeapon2", "ModuleName":"wpn_m_assaultrifle_laser_fauto", # "ModuleName_Localised":"TK Aphelion", "SuitModuleID":1698372938719590 } - pass + loadout_id = self.suit_loadout_id_from_loadoutid(entry['LoadoutID']) + self.state['SuitLoadouts'][loadout_id]['slots'][entry['SlotName']] = { + 'name': entry['ModuleName'], + 'locName': entry.get('ModuleName_Localised', entry['ModuleName']), + 'id': None, + 'weaponrackId': entry['SuitModuleID'], + 'locDescription': '', + } elif event_type == 'LoadoutRemoveModule': # alpha4 From 7b76e327ce76d28dda828b09dc6c0c6e2f441f3e Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 12:32:31 +0100 Subject: [PATCH 13/17] Suits: Always set 'id' to None Better to get a `None` value than a KeyError. --- monitor.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/monitor.py b/monitor.py index cac535bc..c5cf08e8 100644 --- a/monitor.py +++ b/monitor.py @@ -1013,11 +1013,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # { "timestamp":"2021-04-29T09:03:37Z", "event":"BuySuit", "Name":"UtilitySuit_Class1", # "Name_Localised":"Maverick Suit", "Price":150000, "SuitID":1698364934364699 } new_suit = { - 'name': entry['Name'], - 'locName': entry.get('Name_Localised', entry['Name']), - # 'id': ???, # Is this an FDev ID for suit type ? - 'suitId': entry['SuitID'], - 'slots': [], + 'name': entry['Name'], + 'locName': entry.get('Name_Localised', entry['Name']), + 'id': None, # Is this an FDev ID for suit type ? + 'suitId': entry['SuitID'], + 'slots': [], } if self.state['Suits'] is None: self.state['Suits'] = {entry['SuitID']: new_suit} @@ -1698,7 +1698,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below slots[s] = { 'name': loadout_slots[s]['ModuleName'], - # 'id': None, # FDevID ? + 'id': None, # FDevID ? 'weaponrackId': loadout_slots[s]['SuitModuleID'], 'locName': loadout_slots[s].get('ModuleName_Localised', loadout_slots[s]['ModuleName']), 'locDescription': '', From ac4f05269539387181fb0ab6ceb441b99c3683b4 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Thu, 29 Apr 2021 12:38:01 +0100 Subject: [PATCH 14/17] Suits: Update credits on `BuyWeapon` Also cleaning out some verbose comments. --- monitor.py | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/monitor.py b/monitor.py index c5cf08e8..bea4ab00 100644 --- a/monitor.py +++ b/monitor.py @@ -1082,16 +1082,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below } elif event_type == 'LoadoutRemoveModule': - # alpha4 - # This event is logged when a player removes a weapon from a suit loadout - # - # Parameters: - # • SuitID - # • SuitName - # • LoadoutID - # • LoadoutName - # • ModuleName: weapon or other item removed from loadout - # • SuitModuleID # alpha4 - triggers if selecting an already-equipped weapon into a different slot # { "timestamp":"2021-04-29T11:11:13Z", "event":"LoadoutRemoveModule", "LoadoutName":"Dom L/K/K", # "SuitID":1698364940285172, "SuitName":"tacticalsuit_class1", "SuitName_Localised":"Dominator Suit", @@ -1100,25 +1090,16 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below loadout_id = self.suit_loadout_id_from_loadoutid(entry['LoadoutID']) self.state['SuitLoadouts'][loadout_id]['slots'].pop(entry['SlotName']) - # `BuyWeapon` has no instance-specific ID as of 4.0.0.13 elif event_type == 'BuyWeapon': # alpha4 - # Parameters: - # • Name - # • Price - # • SuitModuleID + # { "timestamp":"2021-04-29T11:10:51Z", "event":"BuyWeapon", "Name":"Wpn_M_AssaultRifle_Laser_FAuto", + # "Name_Localised":"TK Aphelion", "Price":125000, "SuitModuleID":1698372938719590 } # update credits - pass + self.state['Credits'] -= entry.get('Price', 0) - # `SellWeapon` has no instance-specific ID as of 4.0.0.13 elif event_type == 'SellWeapon': - # alpha4 - # This event is logged when a player sells a hand weapon - # - # Parameters: - # • Name - # • Price - # • SuitModuleID + # We're not actually keeping track of all owned weapons, only those in + # Suit Loadouts. # alpha4: # { "timestamp":"2021-04-29T10:50:34Z", "event":"SellWeapon", "Name":"wpn_m_assaultrifle_laser_fauto", # "Name_Localised":"TK Aphelion", "Price":75000, "SuitModuleID":1698364962722310 } @@ -1136,8 +1117,9 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # Update credits total self.state['Credits'] += entry.get('Price', 0) - # `UpgradeWeapon` has no instance-specific ID as of 4.0.0.13 elif event_type == 'UpgradeWeapon': + # We're not actually keeping track of all owned weapons, only those in + # Suit Loadouts. # alpha4 pass From 203fb051b09c9762707f140f2cc768b1a5f2c4f4 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 30 Apr 2021 10:47:09 +0100 Subject: [PATCH 15/17] Suits: Simplify `BuySuit` code. --- monitor.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/monitor.py b/monitor.py index bea4ab00..92522bfe 100644 --- a/monitor.py +++ b/monitor.py @@ -1012,20 +1012,13 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # alpha4 : # { "timestamp":"2021-04-29T09:03:37Z", "event":"BuySuit", "Name":"UtilitySuit_Class1", # "Name_Localised":"Maverick Suit", "Price":150000, "SuitID":1698364934364699 } - new_suit = { + self.state['Suits'][entry['SuitID']] = { 'name': entry['Name'], 'locName': entry.get('Name_Localised', entry['Name']), 'id': None, # Is this an FDev ID for suit type ? 'suitId': entry['SuitID'], 'slots': [], } - if self.state['Suits'] is None: - self.state['Suits'] = {entry['SuitID']: new_suit} - - else: - self.state['Suits'].update( - {entry['SuitID']: new_suit} - ) # update credits self.state['Credits'] -= entry.get('Price', 0) From 30b8a5eeadffc53a0c8f0e237d23b3a2e06032e9 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 30 Apr 2021 10:49:39 +0100 Subject: [PATCH 16/17] Suits: Log if a buy/sell event doesn't contain Price --- monitor.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/monitor.py b/monitor.py index 92522bfe..e25a3236 100644 --- a/monitor.py +++ b/monitor.py @@ -1021,7 +1021,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below } # update credits - self.state['Credits'] -= entry.get('Price', 0) + if price := entry.get('Price') is None: + logger.error(f"BuySuit didn't contain Price: {entry}") + + else: + self.state['Credits'] -= price elif event_type == 'SellSuit': # Remove from known suits @@ -1044,7 +1048,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below logger.exception(f"SellSuit for a suit we didn't know about? {entry['SuitID']}") # update credits total - self.state['Credits'] += entry.get('Price', 0) + if price := entry.get('Price') is None: + logger.error(f"SellSuit didn't contain Price: {entry}") + + else: + self.state['Credits'] += price elif event_type == 'UpgradeSuit': # alpha4 @@ -1088,7 +1096,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # { "timestamp":"2021-04-29T11:10:51Z", "event":"BuyWeapon", "Name":"Wpn_M_AssaultRifle_Laser_FAuto", # "Name_Localised":"TK Aphelion", "Price":125000, "SuitModuleID":1698372938719590 } # update credits - self.state['Credits'] -= entry.get('Price', 0) + if price := entry.get('Price') is None: + logger.error(f"BuyWeapon didn't contain Price: {entry}") + + else: + self.state['Credits'] -= price elif event_type == 'SellWeapon': # We're not actually keeping track of all owned weapons, only those in @@ -1108,7 +1120,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below break # Update credits total - self.state['Credits'] += entry.get('Price', 0) + if price := entry.get('Price') is None: + logger.error(f"SellWeapon didn't contain Price: {entry}") + + else: + self.state['Credits'] += price elif event_type == 'UpgradeWeapon': # We're not actually keeping track of all owned weapons, only those in From eed4402340570749dac6ab19003cd52f84f37c14 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 30 Apr 2021 10:53:38 +0100 Subject: [PATCH 17/17] Suits: Init monitor.state['Suits'] to empty dict --- monitor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/monitor.py b/monitor.py index e25a3236..dbaaa05b 100644 --- a/monitor.py +++ b/monitor.py @@ -151,7 +151,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'Data': defaultdict(int), # Backpack Data }, 'SuitCurrent': None, - 'Suits': None, + 'Suits': {}, 'SuitLoadoutCurrent': None, 'SuitLoadouts': {}, }