示例#1
0
    def Enable(self) -> None:
        def SpawnPopulationControlledActor(caller: unrealsdk.UObject,
                                           function: unrealsdk.UFunction,
                                           params: unrealsdk.FStruct) -> bool:
            if caller != self.CurrentPopMaster:
                self.CurrentPopMaster = caller
                self.OriginalLimit = caller.MaxActorCost

                if self.SpawnLimitSpinner.CurrentValue == "Linear":
                    caller.MaxActorCost *= self.MultiplierSlider.CurrentValue
                elif self.SpawnLimitSpinner.CurrentValue == "Unlimited":
                    caller.MaxActorCost = 0x7FFFFFFF

            return True

        def PostBeginPlay(caller: unrealsdk.UObject,
                          function: unrealsdk.UFunction,
                          params: unrealsdk.FStruct) -> bool:
            unrealsdk.DoInjectedCallNext()
            caller.PostBeginPlay()

            self.MultiplyDenIfAble(caller, self.MultiplierSlider.CurrentValue)

            return False

        for den in unrealsdk.FindAll("PopulationOpportunityDen"):
            self.MultiplyDenIfAble(den, self.MultiplierSlider.CurrentValue)

        self.OldMultiplier = self.MultiplierSlider.CurrentValue
        unrealsdk.RunHook(
            "GearboxFramework.PopulationMaster.SpawnPopulationControlledActor",
            self.Name, SpawnPopulationControlledActor)
        unrealsdk.RunHook("WillowGame.PopulationOpportunityDen.PostBeginPlay",
                          self.Name, PostBeginPlay)
示例#2
0
    def Enable(self) -> None:
        def GiveTo(caller: unrealsdk.UObject, function: unrealsdk.UFunction,
                   params: unrealsdk.FStruct) -> bool:
            if params.Other != unrealsdk.GetEngine().GamePlayers[0].Actor.Pawn:
                return True

            if not self.CanItemBeEquipped(caller):
                if params.Other.InvManager is None:
                    return True

                params.Other.InvManager.ClientConditionalIncrementPickupStats(
                    caller)
                # Force bReady False so that you don't force equip
                params.Other.InvManager.AddInventory(caller, False, False,
                                                     params.bPlayPickupSound)
                return False

            return True

        def CanBeUsedBy(caller: unrealsdk.UObject,
                        function: unrealsdk.UFunction,
                        params: unrealsdk.FStruct) -> bool:
            if params.Other != unrealsdk.GetEngine().GamePlayers[0].Actor.Pawn:
                return True
            return self.CanItemBeEquipped(caller)

        def SetItemCardEx(caller: unrealsdk.UObject,
                          function: unrealsdk.UFunction,
                          params: unrealsdk.FStruct) -> bool:
            if params.InventoryItem.ObjectPointer is None:
                return True
            if self.CanItemBeEquipped(params.InventoryItem.ObjectPointer):
                return True

            caller.SetItemCardEx(params.WPC,
                                 params.InventoryItem.ObjectPointer,
                                 params.CompareAgainstInventoryItem,
                                 params.CurrencyType, params.OverrideValue)
            caller.SetLevelRequirement(True, False, False,
                                       self.UnableToEquipMessage)

            return False

        def InventoryShouldBeReadiedWhenEquipped(
                caller: unrealsdk.UObject, function: unrealsdk.UFunction,
                params: unrealsdk.FStruct) -> bool:
            if caller.Owner != unrealsdk.GetEngine().GamePlayers[0].Actor.Pawn:
                return True
            return self.CanItemBeEquipped(params.WillowInv)

        unrealsdk.RunHook("Engine.Inventory.GiveTo", self.Name, GiveTo)
        unrealsdk.RunHook("Engine.WillowInventory.CanBeUsedBy", self.Name,
                          CanBeUsedBy)
        unrealsdk.RunHook("WillowGame.ItemCardGFxObject.SetItemCardEx",
                          self.Name, SetItemCardEx)
        unrealsdk.RunHook(
            "WillowGame.WillowInventoryManager.InventoryShouldBeReadiedWhenEquipped",
            self.Name, InventoryShouldBeReadiedWhenEquipped)
示例#3
0
    def Enable(self) -> None:
        def UpdateOpportunityEnabledStates(caller: unrealsdk.UObject,
                                           function: unrealsdk.UFunction,
                                           params: unrealsdk.FStruct) -> bool:
            # Seems to be -1 on map load - though I've never seen it get called at another time
            if params.nWave != -1:
                return True

            self.MultiplePopEncounterIfAble(caller,
                                            self.MultiplierSlider.CurrentValue)

            return True

        def SpawnPopulationControlledActor(caller: unrealsdk.UObject,
                                           function: unrealsdk.UFunction,
                                           params: unrealsdk.FStruct) -> bool:
            if caller != self.CurrentPopMaster:
                self.CurrentPopMaster = caller
                self.OriginalLimit = caller.MaxActorCost

                if self.SpawnLimitSpinner.CurrentValue == SpawnLimitType.Linear:
                    caller.MaxActorCost *= self.MultiplierSlider.CurrentValue
                elif self.SpawnLimitSpinner.CurrentValue == SpawnLimitType.Unlimited:
                    caller.MaxActorCost = 0x7FFFFFFF

            return True

        def PostBeginPlay(caller: unrealsdk.UObject,
                          function: unrealsdk.UFunction,
                          params: unrealsdk.FStruct) -> bool:
            unrealsdk.DoInjectedCallNext()
            caller.PostBeginPlay()

            self.MultiplyDenIfAble(caller, self.MultiplierSlider.CurrentValue)

            return False

        for den in unrealsdk.FindAll("PopulationOpportunityDen"):
            self.MultiplyDenIfAble(den, self.MultiplierSlider.CurrentValue)
        for encounter in unrealsdk.FindAll("PopulationEncounter"):
            self.MultiplePopEncounterIfAble(encounter,
                                            self.MultiplierSlider.CurrentValue)

        self.OldMultiplier = self.MultiplierSlider.CurrentValue

        unrealsdk.RunHook(
            "GearboxFramework.PopulationEncounter.UpdateOpportunityEnabledStates",
            self.Name, UpdateOpportunityEnabledStates)
        unrealsdk.RunHook(
            "GearboxFramework.PopulationMaster.SpawnPopulationControlledActor",
            self.Name, SpawnPopulationControlledActor)
        unrealsdk.RunHook("WillowGame.PopulationOpportunityDen.PostBeginPlay",
                          self.Name, PostBeginPlay)
示例#4
0
def _FrontEndPopulate(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool:
    """
    This function is called to create the front end menu. We use it to replace the DLC caption and
     event id.
    """
    def AddListItem(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool:
        """
        This function is called every time an item is added to *any* menu list - we obviously can't
         use a generic hook.
        Using it cause it simplifies the code to replace the caption.
        """
        if params.Caption == "$WillowMenu.WillowScrollingListDataProviderFrontEnd.DLC":
            unrealsdk.DoInjectedCallNext()
            caller.AddListItem(_MODS_EVENT_ID, _MODS_MENU_NAME, False, False)
            return False

        return True

    unrealsdk.RunHook("WillowGame.WillowScrollingList.AddListItem", "ModMenu.MenuManager", AddListItem)

    unrealsdk.DoInjectedCallNext()
    caller.Populate(params.TheList)

    unrealsdk.RemoveHook("WillowGame.WillowScrollingList.AddListItem", "ModMenu.MenuManager")
    return False
示例#5
0
def _TopLevelOptionsPopulate(caller: unrealsdk.UObject,
                             function: unrealsdk.UFunction,
                             params: unrealsdk.FStruct) -> bool:
    """ This function is called to create the options menu. We use it to inject our `MODS` menu. """
    # If not mods have accessable options, we want to disable the mods entry
    disabled = True
    for mod in ModObjects.Mods:
        if not mod.IsEnabled:
            continue
        if _is_anything_shown(mod.Options):
            disabled = False
            break

    def AddListItem(caller: unrealsdk.UObject, function: unrealsdk.UFunction,
                    params: unrealsdk.FStruct) -> bool:
        """
        This function is called every time an item is added to *any* menu list - we obviously can't
         use a generic hook.
        Using it cause it simplifies the code to add our own entry.
        """
        if params.Caption == "$WillowGame.WillowScrollingList.BackCaption":
            caller.AddListItem(_MOD_OPTIONS_EVENT_ID, _MOD_OPTIONS_MENU_NAME,
                               disabled, False)

        return True

    unrealsdk.RunHook("WillowGame.WillowScrollingList.AddListItem",
                      "ModMenu.OptionManager", AddListItem)

    unrealsdk.DoInjectedCallNext()
    caller.Populate(params.TheList)

    unrealsdk.RemoveHook("WillowGame.WillowScrollingList.AddListItem",
                         "ModMenu.OptionManager")
    return False
示例#6
0
def ApplyWeaponSaveGameData(caller: unrealsdk.UObject,
                            function: unrealsdk.UFunction,
                            params: unrealsdk.FStruct) -> bool:
    """
    We need to call `FixupSavedWeapons` at the start here, but it uses an out argument.
    If we block `ValidateWeaponDefinition` and `IsLocalPlayerController`, so they return false, this
    function will do nothing except make that call for us
    """
    unrealsdk.RunHook(
        "WillowGame.WillowPlayerController.IsLocalPlayerController", __name__,
        Block)
    unrealsdk.RunHook(
        "WillowGame.WillowPlayerController.ValidateWeaponDefinition", __name__,
        Block)

    caller.ApplyWeaponSaveGameData(params.SaveGame)

    unrealsdk.RemoveHook(
        "WillowGame.WillowPlayerController.IsLocalPlayerController", __name__)
    unrealsdk.RemoveHook(
        "WillowGame.WillowPlayerController.ValidateWeaponDefinition", __name__)

    # Now we can recreate the call like normal
    inv_manager = caller.GetPawnInventoryManager()
    is_local = caller.IsLocalPlayerController()

    for idx, saved_weap in enumerate(params.SaveGame.WeaponData):
        if saved_weap.QuickSlot != 0:
            if caller.Role == 3:  # ROLE_Authority
                ServerSetWeaponSaveGameData(caller, idx,
                                            saved_weap.WeaponDefinitionData,
                                            saved_weap.QuickSlot,
                                            saved_weap.Mark)
            continue
        if is_local:
            inv_manager.ClientAddWeaponToBackpack(
                expand_weapon_definition_data(saved_weap.WeaponDefinitionData),
                saved_weap.Mark, False, 14)

    if is_local:
        caller.UnloadableDlcWeaponData = list(
            params.SaveGame.UnloadableDlcWeaponData)
    caller.ServerItemSaveGameDataCompleted()

    return False
示例#7
0
    def OnStart(self, msg: JSON) -> None:
        self.ShowRedemption(msg)

        def BlockCall(caller: unrealsdk.UObject, function: unrealsdk.UFunction,
                      params: unrealsdk.FStruct) -> bool:
            return False

        unrealsdk.RunHook("WillowGame.WillowPlayerPawn.TakeDamage",
                          "CCGodMode", BlockCall)
示例#8
0
def _enqueue_message(message: _Message) -> None:
    """ Add a message to the message queue, sending it if message queue is empty. """
    _message_queue.append(message)

    # If this was the first message to be added to the queue, send it now, and register our tick
    # hook to observe for its timeout.
    if len(_message_queue) == 1:
        message.send()
        unrealsdk.RunHook("Engine.PlayerController.PlayerTick",
                          "ModMenu.NetworkManager", _PlayerTick)
示例#9
0
    def OnStart(self, msg: JSON) -> None:
        self.ShowRedemption(msg)

        def BlockCall(caller: unrealsdk.UObject, function: unrealsdk.UFunction,
                      params: unrealsdk.FStruct) -> bool:
            return False

        unrealsdk.RunHook(
            "WillowGame.WillowWeapon.ShouldAutoReloadWhileFiring",
            "CCManualReloads", BlockCall)
示例#10
0
    def Enable(self) -> None:
        def AddChatMessage(caller: unrealsdk.UObject,
                           function: unrealsdk.UFunction,
                           params: unrealsdk.FStruct) -> bool:
            if unrealsdk.GetEngine(
            ).SparkInterface.ObjectPointer.IsSparkEnabled():
                return True

            time = caller.GetTimestampString(
                unrealsdk.FindAll("WillowSaveGameManager")[-1].TimeFormat)
            caller.AddChatMessageInternal(params.PRI.PlayerName + time,
                                          params.msg)
            return False

        def DisplayOkBoxTextFromSpark(caller: unrealsdk.UObject,
                                      function: unrealsdk.UFunction,
                                      params: unrealsdk.FStruct) -> bool:
            if not self.WarningOption.CurrentValue:
                return True
            if params.Section == "dlgCouldNotConnectSHiFT":
                caller.Close()
                return False
            return True

        def DoSparkAuthentication(caller: unrealsdk.UObject,
                                  function: unrealsdk.UFunction,
                                  params: unrealsdk.FStruct) -> bool:
            if self.ForceOption.CurrentValue:
                caller.ShouldStartSparkInitialization = False
            return True

        unrealsdk.RunHook("WillowGame.TextChatGFxMovie.AddChatMessage",
                          self.Name, AddChatMessage)
        unrealsdk.RunHook(
            "WillowGame.WillowGFxDialogBox.DisplayOkBoxTextFromSpark",
            self.Name, DisplayOkBoxTextFromSpark)
        unrealsdk.RunHook(
            "WillowGame.WillowGFxMoviePressStart.DoSparkAuthentication",
            self.Name, DoSparkAuthentication)
示例#11
0
def _KeyboardMouseOptionsPopulate(caller: unrealsdk.UObject,
                                  function: unrealsdk.UFunction,
                                  params: unrealsdk.FStruct) -> bool:
    """
    This function is called to create the kb/m settings menu. We use it to inject our own
     "MODDED KEYBINDS" menu.
    """
    # If we have no modded binds, disable the menu
    disabled = True
    for mod in ModObjects.Mods:
        if not mod.IsEnabled:
            continue
        for input in mod.Keybinds:
            if isinstance(input, Keybind) and input.IsHidden:
                continue
            disabled = False
            break
        if not disabled:
            break

    def AddListItem(caller: unrealsdk.UObject, function: unrealsdk.UFunction,
                    params: unrealsdk.FStruct) -> bool:
        """
        This function is called every time an item is added to *any* menu list - we obviously can't
         use a generic hook.
        Using it cause it simplifies the code to add our own entry.
        """
        if params.Caption != "$WillowMenu.MenuOptionDisplayNames.KeyBinds":
            return True

        # Want ours to display after the normal keybinds option
        unrealsdk.DoInjectedCallNext()
        caller.AddListItem(params.EventID, params.Caption, params.bDisabled,
                           params.bNew)

        caller.AddListItem(_MODDED_EVENT_ID, _MODDED_KEYBINDS_CAPTION,
                           disabled, False)
        return False

    unrealsdk.RunHook("WillowGame.WillowScrollingList.AddListItem",
                      "ModMenu.KeybindManager", AddListItem)

    unrealsdk.DoInjectedCallNext()
    caller.Populate(params.TheList)
    caller.AddDescription(_MODDED_EVENT_ID,
                          "$WillowMenu.MenuOptionDisplayNames.KeyBindsDesc")

    unrealsdk.RemoveHook("WillowGame.WillowScrollingList.AddListItem",
                         "ModMenu.KeybindManager")

    return False
示例#12
0
    def apply_hook(function: AnyHook) -> AnyHook:
        # If the function has four parameters, it should be a method.
        params = signature(function).parameters
        is_method = (len(params) == 4)

        # Retrieve the function's dictionary of targets. If it does not yet have one, we preform
        # initial setup on it now.
        hook_targets = getattr(function, "HookTargets", None)
        if hook_targets is None:
            param_exception = ValueError(
                "Hook functions must have the signature"
                " ([self,] caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct)"
            )

            # If the function is an instance method, create a mutable list of the parameters and
            # remove the `self` one, so we may check the remaining ones same as a non-method.
            param_list = list(params.values())
            if is_method:
                del param_list[0]
            # If the function has neither 4 nor 3 parameters, it is invalid.
            elif len(param_list) != 3:
                raise param_exception
            # If the functions parameters do not accept positional arguments, it is invalid.
            for param in param_list:
                if Parameter.POSITIONAL_ONLY != param.kind != Parameter.POSITIONAL_OR_KEYWORD:
                    raise param_exception

            # If the function is a method, store the name format string on it for formatting with
            # future instances. If it's a simple function, format its name for use now.
            function.HookName = name if is_method else name.format(  # type: ignore
                f"{function.__module__}.{function.__qualname__}", id(function)
            )

            # With the function now known as valid, create its set of targets.
            hook_targets = function.HookTargets = set()  # type: ignore

        hook_targets.add(target)

        if not is_method:
            unrealsdk.RunHook(target, function.HookName, function)  # type: ignore

        return function
示例#13
0
    def OnStart(self, msg: JSON) -> None:
        user = "******"
        try:
            user = msg["data"]["redemption"]["user"]["login"]
        except KeyError:
            pass
        # Can't exactly show this on the hud, we'll let other messages stay hidden though :)
        ShowChatMessage("Crowd Control:",
                        f"{user} redeemed '{self.Name}'",
                        ShowTimestamp=False)

        unrealsdk.GetEngine().GamePlayers[0].Actor.HideHUD()

        def BlockCall(caller: unrealsdk.UObject, function: unrealsdk.UFunction,
                      params: unrealsdk.FStruct) -> bool:
            return False

        # Pausing/unpausing will make it show again so got to block that
        unrealsdk.RunHook("WillowGame.WillowHUDGFxMovie.Start", "CCHideHUD",
                          BlockCall)
示例#14
0
def RegisterHooks(obj: object) -> None:
    """
    Registers all `@Hook` decorated methods for the object. Said methods will subsequently be called
    in response to the hooked Unreal Engine methods.

    Args:
        obj: The object for which to register method hooks.
    """

    # Create a weak reference to the object which we may use in attributes on it without creating
    # cyclical references. Before destruction, `RemoveHooks` should be called on the object to
    # ensure there are no remaining hooks that reference it.
    obj_ref = weakref.ref(obj, RemoveHooks)

    # Iterate over each attribute on the object's class that contains a function.
    for attribute_name, function in type(obj).__dict__.items():
        if not callable(function):
            continue

        # Attempt to get the set of hook targets from the function. If it doesn't have one, or if
        # its signature doesn't have 4 parameters, it is not a hook method.
        hook_targets = getattr(function, "HookTargets", None)
        if hook_targets is None or len(signature(function).parameters) != 4:
            continue

        # Create a wrapper to replace the descriptor of the attribute, "binding" the function to the
        # mod's weak reference, in a function that can be passed to `unrealsdk.RunHook`.
        method_wrapper = _create_method_wrapper(obj_ref, function)
        setattr(obj, attribute_name, method_wrapper)

        # Format the provided hook name.
        method_wrapper.HookName = function.HookName.format(  # type: ignore
            f"{function.__module__}.{function.__qualname__}", id(obj)
        )

        for target in hook_targets:
            unrealsdk.RunHook(target, method_wrapper.HookName, method_wrapper)  # type: ignore
示例#15
0
            dh.PrintWarning(KeybindManager.Keybind._list_deprecation_warning)
            if input[0] in saved_keybinds:
                input[1] = saved_keybinds[input[0]]

    if settings.get(_ENABLED_CATEGORY_NAME, False):
        if mod.SaveEnabledState == ModObjects.EnabledSaveType.LoadWithSettings:
            if not mod.IsEnabled:
                mod.SettingsInputPressed("Enable")
        elif mod.SaveEnabledState == ModObjects.EnabledSaveType.LoadOnMainMenu:
            _mods_to_enable_on_main_menu.add(mod)


def _FrontendGFxMovieStart(caller: unrealsdk.UObject,
                           function: unrealsdk.UFunction,
                           params: unrealsdk.FStruct) -> bool:
    """
    This function is called upon reaching the main menu, after hotfix objects already exist and all
     the main packages are loaded. We use it to enable all `LoadOnMainMenu` mods.
    """
    for mod in _mods_to_enable_on_main_menu:
        if not mod.IsEnabled:
            mod.SettingsInputPressed("Enable")

    _mods_to_enable_on_main_menu.clear()

    return True


unrealsdk.RunHook("WillowGame.FrontendGFxMovie.Start",
                  "ModMenu.SettingsManager", _FrontendGFxMovieStart)
示例#16
0
 def Enable(self) -> None:
     for hook, func_list in ALL_HOOKS.items():
         for i, func in enumerate(func_list):
             unrealsdk.RunHook(hook, f"{self.Name}{i}", func)
示例#17
0
                if in_option_list(option.Children):
                    return True
        return False

    for mod in unrealsdk.Mods:
        if in_option_list(mod.Options):
            # Calling this before updating the value
            mod.ModOptionChanged(changed_option, new_value)
            changed_option.CurrentValue = new_value
            break

    return True


unrealsdk.RunHook(
    "WillowGame.WillowScrollingListDataProviderTopLevelOptions.Populate",
    "ModMenu.OptionManager", _TopLevelOptionsPopulate)
unrealsdk.RunHook("WillowGame.WillowScrollingList.OnClikEvent",
                  "ModMenu.OptionManager", _WillowScrollingListOnClikEvent)
unrealsdk.RunHook(
    "WillowGame.WillowScrollingListDataProviderOptionsBase.Populate",
    "ModMenu.OptionManager", _DataProviderOptionsBasePopulate)
unrealsdk.RunHook(
    "WillowGame.WillowScrollingListDataProviderOptionsBase.OnPop",
    "ModMenu.OptionManager", _DataProviderOptionsBaseOnPop)
unrealsdk.RunHook(
    "WillowGame.WillowScrollingListDataProviderOptionsBase.HandleSpinnerChange",
    "ModMenu.OptionManager", _HandleSpinnerSliderChange)
unrealsdk.RunHook(
    "WillowGame.WillowScrollingListDataProviderOptionsBase.HandleSliderChange",
    "ModMenu.OptionManager", _HandleSpinnerSliderChange)
示例#18
0
    if caller.CanShowSpectatorControls():
        tooltip += caller.TooltipSpacing + caller.SpectatorTooltip

    if caller.CanShowCharacterSelect(-1):
        tooltip += caller.TooltipSpacing + caller.CharacterSelectTooltip

    if caller.WPCOwner.WorldInfo.NetMode != 3:
        tooltip += caller.TooltipSpacing + caller.NetworkOptionsTooltip

        # Only show on the main menu, not also the pause menu
        if caller.Class.Name == "FrontendGFxMovie":
            tooltip += caller.TooltipSpacing + "[M] Mods"

    if caller.MyFrontendDefinition is not None:
        caller.SetVariableString(
            caller.MyFrontendDefinition.TooltipPath,
            caller.ResolveDataStoreMarkup(tooltip)
        )

    return False


unrealsdk.RunHook("WillowGame.WillowScrollingListDataProviderFrontEnd.Populate", "ModMenu.MenuManager", _FrontEndPopulate)
unrealsdk.RunHook("WillowGame.MarketplaceGFxMovie.RefreshDLC", "ModMenu.MenuManager", _RefreshDLC)
unrealsdk.RunHook("WillowGame.MarketplaceGFxMovie.OnDownloadableContentListRead", "ModMenu.MenuManager", _OnDownloadableContentListRead)
unrealsdk.RunHook("WillowGame.MarketplaceGFxMovie.ShopInputKey", "ModMenu.MenuManager", _ShopInputKey)
unrealsdk.RunHook("WillowGame.MarketplaceGFxMovie.extOnOfferingChanged", "ModMenu.MenuManager", _extOnOfferingChanged)
unrealsdk.RunHook("WillowGame.WillowScrollingListDataProviderFrontEnd.HandleClick", "ModMenu.MenuManager", _FrontEndHandleClick)
unrealsdk.RunHook("WillowGame.FrontendGFxMovie.SharedHandleInputKey", "ModMenu.MenuManager", _SharedHandleInputKey)
unrealsdk.RunHook("WillowGame.FrontendGFxMovie.UpdateTooltips", "ModMenu.MenuManager", _FrontEndUpdateTooltips)
示例#19
0
            unrealsdk.Log(
                f"Unable to deserialize arguments for '{message_type}'")
            tb = traceback.format_exc().split('\n')
            unrealsdk.Log(f"    {tb[-4].strip()}")
            unrealsdk.Log(f"    {tb[-3].strip()}")
            unrealsdk.Log(f"    {tb[-2].strip()}")

        if arguments is not None:
            for method in methods:
                try:
                    method(*arguments["args"], **arguments["kwargs"])
                except Exception:
                    unrealsdk.Log(
                        f"Unable to call remotely requested {method}.")
                    tb = traceback.format_exc().split('\n')
                    unrealsdk.Log(f"    {tb[-4].strip()}")
                    unrealsdk.Log(f"    {tb[-3].strip()}")
                    unrealsdk.Log(f"    {tb[-2].strip()}")

    caller.ServerSpeech(message_id, 0, "unrealsdk.__clientack__")
    return False


unrealsdk.RunHook("Engine.PlayerController.ServerSpeech",
                  "ModMenu.NetworkManager", _server_speech)
unrealsdk.RunHook("WillowGame.WillowPlayerController.ClientMessage",
                  "ModMenu.NetworkManager", _client_message)
unrealsdk.RunHook("Engine.GameInfo.Logout", "ModMenu.NetworkManager", _Logout)
unrealsdk.RunHook("Engine.GameViewportClient.GameSessionEnded",
                  "ModMenu.NetworkManager", _GameSessionEnded)
示例#20
0
        if time < now:
            for callbk in callbk_list:
                try:
                    callbk()
                except Exception:
                    unrealsdk.Log("[AsyncUtil] Exception thrown:")
                    for line in traceback.format_exc().split("\n"):
                        unrealsdk.Log(line)
            if time != datetime.min:
                del _Callbacks[time]
        else:
            break
    return True


unrealsdk.RunHook("WillowGame.WillowGameViewportClient.Tick", "AsyncUtil", _OnTick)


def RunIn(time: float, callbk: Callback, key: str = "") -> None:
    """
    Runs a callback in the provided amount of seconds.

    Args:
        time: The amount of time (in seconds) to wait before running the callback.
        callbk: The callback.
        key: An optional key to help identify the callback if you want to cancel it later.
    """
    if time <= 0:
        raise ValueError("RunIn() requires a non-zero, positive, time!")

    if len(key) == 0:
示例#21
0
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
示例#22
0
tries to exec your file without running Command Extensions.
"""[1:-1],
    formatter_class=argparse.RawDescriptionHelpFormatter)
suppress_next_chat_parser.add_argument(
    "pattern",
    nargs="?",
    default="*",
    help="The glob pattern matching the message to suppress.")


def ServerSay(caller: unrealsdk.UObject, function: unrealsdk.UFunction,
              params: unrealsdk.FStruct) -> bool:
    global suppress_global_count

    for pattern, count in suppressed_patterns.items():
        if fnmatch.fnmatch(params.msg, pattern):
            if count == 1:
                del suppressed_patterns[pattern]
            else:
                suppressed_patterns[pattern] -= 1
            return False

    if suppress_global_count > 0:
        suppress_global_count -= 1
        return False

    return True


unrealsdk.RunHook("Engine.PlayerController.ServerSay", __name__, ServerSay)
示例#23
0
            # Prefer the callback
            function = (returned_input.OnPress or functools.partial(
                mod.GameInputPressed, returned_input))

            if len(inspect.signature(function).parameters) == 0:
                if params.Event == InputEvent.Pressed:
                    function()
                    return False
            else:
                function(InputEvent(params.Event))
                return False
    return True


unrealsdk.RunHook(
    "WillowGame.WillowScrollingListDataProviderKeyboardMouseOptions.Populate",
    "ModMenu.KeybindManager", _KeyboardMouseOptionsPopulate)
unrealsdk.RunHook(
    "WillowGame.WillowScrollingListDataProviderKeyboardMouseOptions.extOnPopulateKeys",
    "ModMenu.KeybindManager", _extOnPopulateKeys)
unrealsdk.RunHook(
    "WillowGame.WillowScrollingListDataProviderKeyboardMouseOptions.HandleSelectionChange",
    "ModMenu.KeybindManager", _HandleSelectionChangeRollover)
unrealsdk.RunHook(
    "WillowGame.WillowScrollingListDataProviderKeyboardMouseOptions.HandleSelectionRollover",
    "ModMenu.KeybindManager", _HandleSelectionChangeRollover)
unrealsdk.RunHook(
    "WillowGame.WillowScrollingListDataProviderKeyboardMouseOptions.DoBind",
    "ModMenu.KeybindManager", _DoBind)
unrealsdk.RunHook(
    "WillowGame.WillowScrollingListDataProviderKeyboardMouseOptions.BindCurrentSelection",
示例#24
0
    def Enable(self) -> None:
        self.CreateIcons()

        def ConditionalReactToUse(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool:
            if caller.Class.Name != "WillowVendingMachine":
                return True
            if params.UsedType != 1:
                return True
            if params.User is None:
                return True

            PC = params.User.Controller
            PRI = PC.PlayerReplicationInfo

            wallet = PRI.GetCurrencyOnHand(0)
            cost = 0
            if caller.ShopType == 2:
                cost = self.GetHealthCost(params.User, caller)
            elif caller.ShopType == 1:
                cost = self.GetAmmoCost(params.User, caller)
            else:
                return True

            if cost == 0 or wallet < cost:
                PC.NotifyUnableToAffordUsableObject(1)
                return True

            # If you have updating costs on, block payment so we can do it manually
            # This ensures that it always costs the right amount, even if it's displaying wrong
            #  (e.g. if in coop a different player is closer to the vendor)
            if self.UpdatingOption.CurrentValue:
                vendor = caller

                def PayForUsedObject(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool:
                    if params.UsedObject.ObjectPointer == vendor and params.UsabilityType == 1:
                        unrealsdk.RemoveHook("WillowGame.WillowPlayerController.PayForUsedObject", self.Name)
                        return False
                    else:
                        return True

                unrealsdk.RegisterHook("WillowGame.WillowPlayerController.PayForUsedObject", self.Name, PayForUsedObject)

            PRI.AddCurrencyOnHand(0, -cost)
            PC.SetPendingTransactionStatus(1)

            if caller.ShopType == 2:
                self.BuyHealth(params.User, caller)
            elif caller.ShopType == 1:
                self.BuyAmmo(params.User, caller)

            return True

        def InitializeFromDefinition(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool:
            if caller.Class.Name != "WillowVendingMachine":
                return True

            if caller.ShopType == 2:
                params.Definition.HUDIconDefSecondary = self.HealthIcon
                caller.SetUsability(True, 1)
            elif caller.ShopType == 1:
                params.Definition.HUDIconDefSecondary = self.AmmoIcon
                caller.SetUsability(True, 1)

            return True

        # Touch and UnTouch are called whenever a player gets close to an interactive object
        # We use them to disable the update loop when we don't need it, to reduce lag
        # Process it even if updating costs are off so that it switches seamlessly on option change
        def Touch(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool:
            if caller.Class.Name != "WillowVendingMachine":
                return True
            if params.Other.Class.Name != "WillowPlayerPawn":
                return True

            # If no one's currently near a vendor, but is about to be, and if updating costs are on,
            #  start the update loop
            if self.UpdatingOption.CurrentValue and len(self.TouchingActors) == 0:
                AsyncUtil.RunEvery(self.UPDATE_DELAY, self.OnUpdate, self.Name)

            if caller not in self.TouchingActors:
                self.TouchingActors[caller] = set()
            self.TouchingActors[caller].add(params.Other)

            return True

        def UnTouch(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool:
            if caller.Class.Name != "WillowVendingMachine":
                return True
            if params.Other.Class.Name != "WillowPlayerPawn":
                return True

            try:
                self.TouchingActors[caller].remove(params.Other)
                if len(self.TouchingActors[caller]) == 0:
                    del self.TouchingActors[caller]
            except (KeyError, ValueError):  # If the player or vendor aren't in the dict
                pass

            if self.UpdatingOption.CurrentValue and len(self.TouchingActors) == 0:
                AsyncUtil.CancelFutureCallbacks(self.Name)

            return True

        def WillowClientDisableLoadingMovie(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool:
            # On level change reset all our caching
            self.TouchingActors = {}
            self.VialCosts = {}
            self.AmmoCosts = {}
            self.PlayerAmmoPools = {}
            AsyncUtil.CancelFutureCallbacks(self.Name)
            return True

        def GenerateInventory(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool:
            # Whenever a vendor inventory is generated, update our cached costs
            # Unfortuantly ShopInventory is a fixed array, which we can't iterate though, so we have
            #  to do a findall to find the items
            unrealsdk.DoInjectedCallNext()
            caller.GenerateInventory()

            PC = unrealsdk.GetEngine().GamePlayers[0].Actor

            if caller.ShopType == 1:
                self.AmmoCosts[caller] = {}

            for item in unrealsdk.FindAll("WillowUsableItem"):
                if item.Owner != caller:
                    continue
                if item.DefinitionData is None or item.DefinitionData.ItemDefinition is None:
                    continue

                if caller.ShopType == 2:
                    if item.DefinitionData.ItemDefinition.Name == "BuffDrink_HealingInstant":
                        self.VialCosts[caller] = caller.GetSellingPriceForInventory(item, PC, 1)
                        break

                elif caller.ShopType == 1:
                    name = item.DefinitionData.ItemDefinition.Name
                    if name not in self.AMMO_COUNTS:
                        continue

                    info = self.AMMO_COUNTS[name]
                    price = caller.GetSellingPriceForInventory(item, PC, 1) / info.BulletsPerItem
                    self.AmmoCosts[caller][info.ResourcePoolName] = price

            return False

        unrealsdk.RunHook("WillowGame.WillowInteractiveObject.ConditionalReactToUse", self.Name, ConditionalReactToUse)
        unrealsdk.RunHook("WillowGame.WillowInteractiveObject.InitializeFromDefinition", self.Name, InitializeFromDefinition)
        unrealsdk.RunHook("WillowGame.WillowInteractiveObject.Touch", self.Name, Touch)
        unrealsdk.RunHook("WillowGame.WillowInteractiveObject.UnTouch", self.Name, UnTouch)
        unrealsdk.RunHook("WillowGame.WillowPlayerController.WillowClientDisableLoadingMovie", self.Name, WillowClientDisableLoadingMovie)
        unrealsdk.RunHook("WillowGame.WillowVendingMachine.GenerateInventory", self.Name, GenerateInventory)
示例#25
0
def _BindCurrentSelection(caller: unrealsdk.UObject,
                          function: unrealsdk.UFunction,
                          params: unrealsdk.FStruct) -> bool:
    """
    This function is called when a key is rebound. We basically entirely rewrite it, making sure to
     update modded binds, as well as adding the ability to unbind modded keys.

    Unbinding default binds won't save, so doing so has been disabled.
    If you want to look into it more, it's probably caused by how it gets saved to your profile,
     follow the trail from `OnPop()`.
    """
    selected_idx = caller.CurrentKeyBindSelection
    selected_bind = caller.KeyBinds[selected_idx]

    translation_context = unrealsdk.GetEngine(
    ).GamePlayers[0].GetTranslationContext()

    if selected_bind.Tag.startswith(_TAG_SEPERATOR):
        return False

    key = params.Key
    if selected_bind.CurrentKey == key:
        # Don't allow unbinding defaults
        if selected_idx not in _modded_keybind_map:
            return False
        key = "None"

    if selected_idx in _modded_keybind_map:
        input = _modded_keybind_map[selected_idx]
        if isinstance(input, Keybind):
            input.Key = key
        else:
            dh.PrintWarning(Keybind._list_deprecation_warning)
            input[1] = key

    # Find if we have to swap the bind with anything
    for idx, bind in enumerate(caller.KeyBinds):
        if bind.CurrentKey != params.Key:
            continue
        if bind == selected_bind:
            continue

        # Allow multiple "None" binds
        # Using continue rather than a break so that it falls into the else
        if key == "None":
            continue

        # If you would swap a default bind to None
        if selected_bind.CurrentKey == "None" and idx not in _modded_keybind_map:
            # Show a small explanatory dialog.
            dialog = caller.WPCOwner.GFxUIManager.ShowDialog()

            title = dialog.Localize("dlgKeyBindSwap", "Caption", "WillowMenu")
            msg = (
                f"Unable to bind \"{selected_bind.Caption}\" to \"{key}\".\n"
                f"\n"
                f"Doing so would cause the default bind \"{bind.Caption}\" to become unbound."
            )
            dialog.SetText(title, msg)
            dialog.SetVariableString(
                "tooltips.text", "$<Strings:WillowMenu.TitleMenu.BackBar>")
            dialog.ApplyLayout()

            def HandleInputKey(caller: unrealsdk.UObject,
                               function: unrealsdk.UFunction,
                               params: unrealsdk.FStruct) -> bool:
                """
                This function is called on any key event on any `WillowGFxDialogBox`. Only using it
                 to replicate adding `HandleKeySwapDialog` as a delegate, sdk can't quite do so yet.
                """
                if caller != dialog:
                    return True

                if (params.uevent == InputEvent.Released and params.ukey
                        in ("Escape", "XboxTypeS_B", "XboxTypeS_Back")):
                    dialog.Close()
                    unrealsdk.RemoveHook(
                        "WillowGame.WillowGFxDialogBox.HandleInputKey",
                        "ModMenu.KeybindManager")
                return True

            unrealsdk.RunHook("WillowGame.WillowGFxDialogBox.HandleInputKey",
                              "ModMenu.KeybindManager", HandleInputKey)

            return False

        if idx in _modded_keybind_map:
            input = _modded_keybind_map[idx]
            if isinstance(input, Keybind):
                input.Key = selected_bind.CurrentKey
            else:
                dh.PrintWarning(Keybind._list_deprecation_warning)
                input[1] = selected_bind.CurrentKey

        unrealsdk.DoInjectedCallNext()
        caller.BindCurrentSelection(key)

        bind.Object.SetString(
            "value", _get_fixed_localized_key_name(caller, bind.CurrentKey),
            translation_context)
    else:
        caller.bNeedsToSaveKeyBinds = True
        selected_bind.CurrentKey = key

    selected_bind.Object.SetString(
        "value", _get_fixed_localized_key_name(caller,
                                               selected_bind.CurrentKey),
        translation_context)

    caller.ControllerMappingClip.InvalidateKeyData()

    return False
示例#26
0
    def Enable(self) -> None:
        self.CreateIcons()

        def ConditionalReactToUse(caller: unrealsdk.UObject,
                                  function: unrealsdk.UFunction,
                                  params: unrealsdk.FStruct) -> bool:
            if params.UsedType != 1:
                return True
            if str(caller).split(" ")[0] != "WillowVendingMachine":
                return True

            # If you have updating costs off we have to take the off money ourselves
            if not self.UpdatingOption.CurrentValue:
                PC = params.User.Controller
                PRI = PC.PlayerReplicationInfo

                wallet = PRI.GetCurrencyOnHand(0)
                cost = 0
                if caller.ShopType == 2:
                    cost = self.GetHealthCost(params.User, caller)
                elif caller.ShopType == 1:
                    cost = self.GetAmmoCost(params.User, caller)
                else:
                    return True

                if cost == 0 or wallet < cost:
                    PC.NotifyUnableToAffordUsableObject(1)
                    return True

                PRI.AddCurrencyOnHand(0, -cost)
                PC.SetPendingTransactionStatus(1)

            if caller.ShopType == 2:
                self.BuyHealth(params.user, caller)
            elif caller.ShopType == 1:
                self.BuyAmmo(params.user, caller)

            return True

        def InitializeFromDefinition(caller: unrealsdk.UObject,
                                     function: unrealsdk.UFunction,
                                     params: unrealsdk.FStruct) -> bool:
            if str(caller).split(" ")[0] != "WillowVendingMachine":
                return True

            if caller.ShopType == 2:
                params.Definition.HUDIconDefSecondary = self.HealthIcon
                caller.SetUsability(True, 1)
            elif caller.ShopType == 1:
                params.Definition.HUDIconDefSecondary = self.AmmoIcon
                caller.SetUsability(True, 1)

            return True

        def Touch(caller: unrealsdk.UObject, function: unrealsdk.UFunction,
                  params: unrealsdk.FStruct) -> bool:
            if not self.UpdatingOption.CurrentValue:
                return True
            if str(caller).split(" ")[0] != "WillowVendingMachine":
                return True

            self.TouchingActors.add(params.Other)
            if self.UpdatingOption.CurrentValue and len(
                    self.TouchingActors) == 1:
                AsyncUtil.RunEvery(self.UPDATE_DELAY, self.OnUpdate, self.Name)

            return True

        def UnTouch(caller: unrealsdk.UObject, function: unrealsdk.UFunction,
                    params: unrealsdk.FStruct) -> bool:
            if str(caller).split(" ")[0] != "WillowVendingMachine":
                return True

            try:
                self.TouchingActors.remove(params.Other)
            except KeyError:  # If the player is not already in the set
                pass

            if self.UpdatingOption.CurrentValue and len(
                    self.TouchingActors) == 0:
                AsyncUtil.CancelFutureCallbacks(self.Name)

            return True

        def WillowClientDisableLoadingMovie(caller: unrealsdk.UObject,
                                            function: unrealsdk.UFunction,
                                            params: unrealsdk.FStruct) -> bool:
            self.TouchingActors.clear()
            return True

        unrealsdk.RunHook(
            "WillowGame.WillowInteractiveObject.ConditionalReactToUse",
            self.Name, ConditionalReactToUse)
        unrealsdk.RunHook(
            "WillowGame.WillowInteractiveObject.InitializeFromDefinition",
            self.Name, InitializeFromDefinition)
        unrealsdk.RunHook("WillowGame.WillowInteractiveObject.Touch",
                          self.Name, Touch)
        unrealsdk.RunHook("WillowGame.WillowInteractiveObject.UnTouch",
                          self.Name, UnTouch)
        unrealsdk.RunHook(
            "WillowGame.WillowPlayerController.WillowClientDisableLoadingMovie",
            self.Name, WillowClientDisableLoadingMovie)
示例#27
0
 def Enable(self) -> None:
     update_compression(self.CompressOption.CurrentValue)
     for func, hook in AllHooks.items():
         unrealsdk.RunHook(func, self.Name, hook)