def bank_on_close(self, caller: unrealsdk.UObject) -> bool: if caller.MaxSlots == 4: read_f = open(self.STASH_PATH, "r") save_json = json.load(read_f) elif caller.MaxSlots == 3: # the grinder in TPS return True else: read_f = open(self.LOAD_PATH, "r") save_json = json.load(read_f) read_f.close() wweapon_class = unrealsdk.FindClass("WillowWeapon") bank = {"Weapons": list(), "Items": list()} for chest_data in caller.TheChest: if not chest_data.Inventory: break mark: int = chest_data.Inventory.Mark if chest_data.Inventory.Class == wweapon_class: bank["Weapons"].append(get_weapon_from_data(chest_data.Inventory.DefinitionData, mark=mark)) else: bank["Items"].append(get_item_from_data(chest_data.Inventory.DefinitionData, mark=mark)) chest_data.Inventory.Destroy() chest_data.Inventory = None bl2tools.get_player_controller().OnChestClosing(caller) caller.ChestIsOpen = False with open(self.LOAD_PATH if caller.MaxSlots != 4 else self.STASH_PATH, "w") as f: if caller.MaxSlots == 4: json.dump(bank, f, indent=4) else: save_json["Bank"] = bank json.dump(save_json, f, indent=4) return False
def bank_on_open(self, caller: unrealsdk.UObject) -> bool: if caller.MaxSlots == 4: caller.ChestSlots = self.stash_size # we opened the stash read_f = open(self.STASH_PATH, "r") bank = json.load(read_f) elif caller.MaxSlots == 3: # the grinder in TPS return True else: read_f = open(self.LOAD_PATH, "r") bank = json.load(read_f).get("Bank", dict()) read_f.close() owner = bl2tools.get_player_controller().Pawn static_wweapon: unrealsdk.UObject = unrealsdk.FindAll("WillowWeapon")[0] static_witem: unrealsdk.UObject = unrealsdk.FindAll("WillowItem")[0] bank_things: list = [] for weapon in bank.get("Weapons", list()): wpn_data, mark = load_weapon_data(weapon) new_weapon: unrealsdk.UObject = static_wweapon.CreateWeaponFromDef(wpn_data, owner, True) new_weapon.Mark = mark bank_things.append((new_weapon.Class, tuple(), new_weapon)) for item in bank.get("Items", list()): item_data, mark = load_item_data(item) new_item: unrealsdk.UObject = static_witem.CreateItemFromDef(item_data, owner, 1, True) new_item.Mark = mark bank_things.append((new_item.Class, tuple(), new_item)) caller.TheChest = bank_things caller.ChestIsOpen = True return False
def Open(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool: if caller.ChestIsOpen: return False # We'll set this later cause we re-call this function and don't want it to early exit PC = caller.Outer.GetOwningPlayerController() if PC is None: return False inv_manager = PC.GetPawnInventoryManager() save_manager: SaveManager if caller == inv_manager.TheBank: save_manager = SaveManager(PC.SaveGameName, True) elif caller == inv_manager.TheStash: save_manager = SaveManager(STASH_NAME) else: unrealsdk.Log("[SanitySaver] Could not identify opened container!") return False save_manager.load() PC.OnChestOpened(caller) """ This is a bit of a mess. All items are stored as serial number structs, which contain a static array. This means we can't ever pass one of these structs, or even whole the list, from Python back into UnrealScript. So how do we convert these to a useable format? `WillowInventory.CreateInventoryFromSerialNumber` We still can't call this ourself though, we have to get something else to. And unfortuantly it happens to only be called by the very function we have to overwrite to remove the sanity check in the first place. The only way we can actually extract item references is by hooking the sanity check functions. Hooking them means we have to force all items to get sanity checked and be destroyed, but luckily there's handy functions to recreate them from the definition with our changes. """ inv_list = [] def ValidateItemWeaponDefinition(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool: is_weapon = function.Name == "ValidateWeaponDefinition" inv_list.append( (save_manager.apply_replacements(params.DefinitionData, is_weapon), is_weapon)) return False unrealsdk.RunHook("WillowGame.WillowPlayerController.OnChestOpened", __name__, Block) unrealsdk.RunHook( "WillowGame.WillowPlayerController.ValidateItemDefinition", __name__, ValidateItemWeaponDefinition) unrealsdk.RunHook( "WillowGame.WillowPlayerController.ValidateWeaponDefinition", __name__, ValidateItemWeaponDefinition) caller.Open() unrealsdk.RemoveHook("WillowGame.WillowPlayerController.OnChestOpened", __name__) unrealsdk.RemoveHook( "WillowGame.WillowPlayerController.ValidateItemDefinition", __name__) unrealsdk.RemoveHook( "WillowGame.WillowPlayerController.ValidateWeaponDefinition", __name__) save_manager.write() caller.ChestIsOpen = True for def_data, is_weapon in inv_list: if is_weapon: caller.AddWeaponFromDef(def_data, False, False) else: caller.AddItemFromDef(def_data, False, False) """ Technically we should get this function to return True, which should be doable by blocking more function calls and caching some stuff, but nothing that calls this function relies on that value anyway. """ return False