Пример #1
0
def end_scene_callback() -> None:
    global last_color, color_scheme
    if last_color != color_scheme:
        last_color = color_scheme
        if last_color == "Dark":
            pyd_imgui.style_colors_dark()
        elif last_color == "Light":
            pyd_imgui.style_colors_light()
        elif last_color == "Classic":
            pyd_imgui.style_colors_classic()

    # noinspection PyBroadException
    try:
        for func in _on_end_scene.copy(
        ):  # a copy should fix 'RuntimeError: Set changed size during iteration'
            func()
    except Exception:
        # call new_frame to override the current draw stack
        pyd_imgui.new_frame()
        # instead, show the error message
        pyd_imgui.begin("An Exception occured!",
                        flags=pyd_imgui.WINDOW_FLAGS_ALWAYS_AUTO_RESIZE)
        pyd_imgui.text("[PyImgui] An exception was raised in drawthread!")
        pyd_imgui.text(
            "Please fix the error before continuing using this mod!")
        pyd_imgui.text("Full traceback:")
        pyd_imgui.separator()
        pyd_imgui.text_unformatted(traceback.format_exc())
        pyd_imgui.end()
        pyd_imgui.end_frame()

        unrealsdk.Log(
            f"[PyImgui] An exception was raised in drawthread! Game might crash now."
        )
        unrealsdk.Log(traceback.format_exc())
Пример #2
0
def handle_load_package(args: argparse.Namespace) -> None:
    upks = fnmatch.filter(all_upks, args.package)
    if len(upks) <= 0:
        unrealsdk.Log(f"Could not find package '{args.package}'!")
    elif len(upks) > 10:
        unrealsdk.Log(f"'{args.package}' matches more than 10 packages!")
    else:
        for package in upks:
            unrealsdk.LoadPackage(package)
Пример #3
0
def SaveAllModSettings() -> None:
    """ Saves the options, keybinds, and enabled state of all loaded mods, where applicable. """
    for mod in ModObjects.Mods:
        try:
            SaveModSettings(mod)
        except Exception:
            unrealsdk.Log(f"Unable to save settings for '{mod.Name}'")
            tb = traceback.format_exc().split('\n')
            unrealsdk.Log(f"    {tb[-4].strip()}")
            unrealsdk.Log(f"    {tb[-3].strip()}")
            unrealsdk.Log(f"    {tb[-2].strip()}")
Пример #4
0
    def HandleStdout(self, msg: str) -> None:
        msg_dict: Dict[str, Any]
        title: str
        try:
            msg_dict = json.loads(msg)
            title = msg_dict["data"]["redemption"]["reward"]["title"].lower().strip()
        except (json.JSONDecodeError, KeyError) as ex:
            unrealsdk.Log("Error parsing message:")
            unrealsdk.Log(ex)
            return

        for trig in self.Triggers:
            if title == trig.Trigger.lower() and trig.IsEnabled:
                trig.Effect.OnRedeem(msg_dict)
Пример #5
0
def end_scene_callback() -> None:
    pyd_imgui.new_frame()
    # noinspection PyBroadException
    try:
        for func in _on_end_scene:
            func()
    except Exception:
        unrealsdk.Log(
            f"[PyImgui] An exception was raised in drawthread! Game might crash now."
        )
        unrealsdk.Log(traceback.format_exc())

    pyd_imgui.end_frame()
    pyd_imgui.render()
Пример #6
0
def handle_keep_alive(args: argparse.Namespace) -> None:
    match = re_obj_name.match(args.object)
    if match is None:
        unrealsdk.Log(f"Unable to parse object name {args.object}")
        return

    klass = match.group("class") or "Object"
    name = match.group("fullname")
    obj = unrealsdk.FindObject(klass, name)
    if obj is None:
        unrealsdk.Log(f"Unable to find object {args.object}")
        return

    unrealsdk.KeepAlive(obj)
Пример #7
0
    def Enable(self) -> None:
        def WillowClientDisableLoadingMovie(caller: unrealsdk.UObject,
                                            function: unrealsdk.UFunction,
                                            params: unrealsdk.FStruct) -> bool:
            for clas, handler in self.CLASS_HANDLER_MAP.items():
                for obj in unrealsdk.FindAll(clas):
                    if obj not in self.MenuObjects:
                        handler(obj)
            return True

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

        # If you're re-enabling then we can exit right here, the rest of this is non-reversible
        if len(self.MenuObjects) > 0:
            return

        # Objects we load here will still be alive for all the FindAll commands, we don't need to
        #  parse them yet
        for package, objects in self.FORCE_LOAD.items():
            unrealsdk.LoadPackage(package)
            for obj_name in objects:
                obj = unrealsdk.FindObject(obj_name[0], obj_name[1])
                if obj is None:
                    unrealsdk.Log(
                        f"[{self.Name}] Unable to find object '{obj_name[1]}'")

                unrealsdk.KeepAlive(obj)

        # Do our inital parse over everything, saving what we can access
        for clas, handler in self.CLASS_HANDLER_MAP.items():
            for obj in unrealsdk.FindAll(clas):
                self.MenuObjects.add(obj)
                handler(obj)
Пример #8
0
def _OnTick(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool:
    now = datetime.now()
    for time, callbk_list in _Callbacks.items():
        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
Пример #9
0
    def HandlePartListCollection(self, obj: unrealsdk.UObject) -> None:
        if "WillowGame.Default__" in str(obj):
            return
        item_type = str(obj).split(" ")[0]
        all_parts: Set[str] = set()
        if item_type == "ItemPartListCollectionDefinition":
            all_parts = {
                "AlphaPartData", "BetaPartData", "GammaPartData",
                "DeltaPartData", "EpsilonPartData", "ZetaPartData",
                "EtaPartData", "ThetaPartData", "MaterialPartData"
            }
        elif item_type == "WeaponPartListCollectionDefinition":
            all_parts = {
                "BodyPartData", "GripPartData", "BarrelPartData",
                "SightPartData", "StockPartData", "ElementalPartData",
                "Accessory1PartData", "Accessory2PartData", "MaterialPartData"
            }
        else:
            unrealsdk.Log(
                f"[{self.Name}] Unexpected class '{item_type}' on '{obj.PathName(obj)}'"
            )
            return

        level_indexes = set()
        for part in all_parts:
            weighted = getattr(obj, part).WeightedParts
            if weighted is not None:
                for weighted_part in weighted:
                    if weighted_part.MaxGameStageIndex:
                        level_indexes.add(weighted_part.MaxGameStageIndex)
        self.FixCAID(obj, level_indexes)
Пример #10
0
def Close(caller: unrealsdk.UObject, function: unrealsdk.UFunction,
          params: unrealsdk.FStruct) -> bool:
    PC = caller.Outer.GetOwningPlayerController()
    inv_manager = PC.GetPawnInventoryManager()

    save_name: str
    is_bank: bool
    if caller == inv_manager.TheBank:
        save_name = PC.SaveGameName
        is_bank = True
    elif caller == inv_manager.TheStash:
        save_name = STASH_NAME
        is_bank = False
    else:
        unrealsdk.Log("[SanitySaver] Could not identify opened container!")
        return True

    new_save = SaveManager(save_name, is_bank)
    existing_save = SaveManager(save_name, is_bank)
    existing_save.load()

    for chest_data in caller.TheChest:
        item = chest_data.Inventory
        if item is None or item.DefinitionData is None:
            continue

        new_save.add_item(item.DefinitionData,
                          chest_data.InventoryClass.Name == "WillowWeapon",
                          existing_save)

    new_save.write()

    return True
Пример #11
0
        def DisplayRecentDamageForPlayer(caller: unrealsdk.UObject,
                                         function: unrealsdk.UFunction,
                                         params: unrealsdk.FStruct) -> bool:
            PC = unrealsdk.GetEngine().GamePlayers[0].Actor
            if params.PC != PC:
                return True

            damage = params.DamageEventData.TotalDamageForDamageType
            if damage < 10**self.MinDamageSlider.CurrentValue:
                return True

            actor = params.DamageEventData.DamagedActor

            name = actor.PathName(actor)
            if actor.AIClass is not None and actor.AIClass.DefaultDisplayName is not None:
                name = actor.AIClass.DefaultDisplayName

            if actor.BalanceDefinitionState.BalanceDefinition is not None:
                ptNum = PC.GetCurrentPlaythrough() + 1
                for pt in actor.BalanceDefinitionState.BalanceDefinition.PlayThroughs:
                    if pt.PlayThrough > ptNum:
                        continue
                    if pt.DisplayName is None or len(pt.DisplayName) == 0:
                        continue
                    name = pt.DisplayName

            unrealsdk.Log(
                f"Dealt {damage} damage to level {actor.GetExpLevel()} {name}")

            return True
Пример #12
0
 def _print_message(self,
                    message: str,
                    file: Optional[IO[str]] = None) -> None:
     if message and file is None:
         unrealsdk.Log(message)
     else:
         super()._print_message(message, file)
Пример #13
0
    def command(self, caller: unrealsdk.UObject, function: unrealsdk.UFunction,
                params: unrealsdk.FStruct) -> bool:
        args: List[str] = params.Command.split()
        cmd: str = args[0].strip().lower()

        if cmd == "exec":
            binaries = self.FILE_PATH
            while os.path.basename(binaries).lower() != "binaries":
                binaries = os.path.abspath(os.path.join(binaries, ".."))
            exec_file = os.path.join(
                binaries,
                args[1].lstrip("/").lstrip("\\"))  # this is case-sensitive
            if not os.path.isfile(exec_file):  # we could not find the file
                return True
            with open(exec_file) as fp:
                for line in fp:  # type: str
                    if line.lower().startswith("set") \
                            and unrealsdk.FindObject("MaterialInstanceConstant", line.split()[1]) is not None:
                        try:
                            _exec_skins(line)
                        except Exception as e:
                            unrealsdk.Log(e)
        elif cmd == "set":
            if len(args) >= 4:
                if unrealsdk.FindObject("MaterialInstanceConstant",
                                        args[1]) is not None:
                    _exec_skins(params.Command)
        return True
Пример #14
0
 def on_start_load(self, movie_name: str) -> None:
     if movie_name != "Loading.bik":  # loading main menu, all pawns already got cleaned up
         # for some weird reason some WillowAiPawns don't get destroyed, resulting in endless loading screens
         for pawn in self.spawned_pawns:
             if pawn:
                 unrealsdk.Log(bl2tools.get_obj_path_name(pawn))
                 pawn.Destroyed()
     self.spawned_pawns.clear()  # all pawns are dead
Пример #15
0
def projectile_body_composition_helper(template_obj: unrealsdk.UObject, new_obj: unrealsdk.UObject) -> None:
    for i, data_union in enumerate(template_obj.BodyComposition.Attachments):
        if data_union.Data.ComponentData.Component:
            template = data_union.Data.ComponentData.Component
            new_comp = unrealsdk.ConstructObject(Class=template.Class, Outer=new_obj,
                                                 Name=f"{template.Name}_{i}", Template=template)
            unrealsdk.Log(bl2tools.get_obj_path_name(new_comp))
            unrealsdk.KeepAlive(new_comp)
            if new_comp:
                new_comp.ObjectFlags.B |= 4
                try:
                    unrealsdk.Log(new_obj.BodyComposition.Attachments)
                    new_obj.BodyComposition.Attachments[i].Data.ComponentData.Component = new_comp
                    unrealsdk.Log("works")
                except Exception as e:
                    unrealsdk.Log(f"Exception: {repr(e)}")
                    unrealsdk.Log(e)
Пример #16
0
def PrintWarning(msg: str) -> None:
    """
    Prints a warning containing the provided message. Will only happen once per message.

    Args:
        msg: The message to print.
    """
    if msg not in _printed_deprecation_warnings:
        _printed_deprecation_warnings.add(msg)
        unrealsdk.Log(f"[Warning] {msg}")
Пример #17
0
 def InjectSkills(self, caller: UObject, function: UFunction, params: FStruct) -> bool:
     if not self.Seed:
         self.Seed = random.randrange(sys.maxsize)
         unrealsdk.Log("Randomizing with seed '{}'".format(self.Seed))
         self.RNG = random.Random(self.Seed)
         self.RecordSeed()
     else:
         self.RNG = random.Random(self.Seed)
     self.RandomizeTree(params.SkillTreeDef)
     return True
Пример #18
0
    def Execute(self) -> None:
        for mod in unrealsdk.Mods:
            if mod.Name == self.ModName:
                if mod.Status == "Enabled":
                    unrealsdk.Log(f"[{self.Name}] Mod '{self.ModName}' is already enabled!")
                    break
                if "Enable" not in mod.SettingsInputs.values():
                    unrealsdk.Log(f"[{self.Name}] Mod '{self.ModName}' does not currently support an enable input!")
                    break

                try:
                    mod.SettingsInputPressed("Enable")
                except Exception:
                    unrealsdk.Log(f"[{self.Name}] Mod '{self.ModName}' caused an exception while trying to enable:")
                    for line in traceback.format_exc():
                        unrealsdk.Log(line)
                break
        else:
            unrealsdk.Log(f"[{self.Name}] Unable to find mod '{self.ModName}'!")
        self.OnFinishExecution()
Пример #19
0
def handle_clone(args: argparse.Namespace) -> None:
    src_match = re_obj_name.match(args.base)
    if src_match is None:
        unrealsdk.Log(f"Unable to parse object name {args.base}")
        return

    src_class = src_match.group("class") or "Object"
    src_fullname = src_match.group("fullname")
    src_object = unrealsdk.FindObject(src_class, src_fullname)
    if src_object is None:
        unrealsdk.Log(f"Unable to find object {args.base}")
        return

    dst_match = re_obj_name.match(args.clone)
    if dst_match is None:
        unrealsdk.Log(f"Unable to parse object name {args.clone}")
        return

    dst_class = dst_match.group("class") or "Object"
    if dst_class != "Object" and dst_class != src_class:
        unrealsdk.Log(
            f"Cannot clone object of class {src_class} as class {dst_class}")
        return

    dst_outer = dst_match.group("outer")
    dst_outer_object = None
    if dst_outer:
        dst_outer_object = unrealsdk.FindObject("Object", dst_outer)
        if dst_outer_object is None:
            unrealsdk.Log(f"Unable to find outer object {dst_outer}")
            return

    dst_name = dst_match.group("name")

    cloned = unrealsdk.ConstructObject(Class=src_object.Class,
                                       Outer=dst_outer_object,
                                       Name=dst_name,
                                       Template=src_object)
    if cloned is not None:
        unrealsdk.KeepAlive(cloned)
Пример #20
0
def cached_obj_find(klass: str, name: str) -> unrealsdk.UObject:
    if name is None or name == "None":
        return None
    if name in obj_cache:
        return obj_cache[name]
    obj = unrealsdk.FindObject(klass, name)

    # Warn about missing objects but still cache them
    if obj is None:
        unrealsdk.Log(f"[SanitySaver] Couldn't find {klass}'{name}'")

    obj_cache[name] = obj
    return obj
Пример #21
0
 def check_willow_engine_ini() -> bool:
     ini_path = os.path.join(os.path.expanduser("~"), "Documents",
                             "my games", "Borderlands 2", "WillowGame",
                             "Config")
     try:
         with open(os.path.join(ini_path, "WillowEngine.ini"), "r") as f:
             for line in f:
                 if "bforcenomovies=true" in line.lower():
                     return False
         return True
     except Exception as e:
         unrealsdk.Log(e)
         return True
Пример #22
0
 def Execute(self) -> None:
     for mod in unrealsdk.Mods:
         if mod.Name == self.ModName:
             if self.Input in mod.SettingsInputs:
                 try:
                     mod.SettingsInputPressed(
                         mod.SettingsInputs[self.Input])
                 except Exception:
                     unrealsdk.Log(
                         f"[{self.Name}] Mod '{self.ModName}' caused an exception while inputing '{self.Input}':"
                     )
                     for line in traceback.format_exc():
                         unrealsdk.Log(line)
             else:
                 unrealsdk.Log(
                     f"[{self.Name}] Mod '{self.ModName}' does not currently support the input '{self.Input}'!"
                 )
             break
     else:
         unrealsdk.Log(
             f"[{self.Name}] Unable to find mod '{self.ModName}'!")
     self.OnFinishExecution()
Пример #23
0
def _try_handle_command(cmd: str) -> bool:
    """
    Takes in a command string `cmd` and tries to handle it.

    Returns:
        True if the command string corosponded to one of our custom commands, or False otherwise.
    """
    name, _, args = cmd.partition(" ")
    name = name.lower()

    if name == "exec":
        try:
            parsed_args = _exec_parser.parse_args(shlex.split(args))
            file_path = path.abspath(
                path.join(path.dirname(sys.executable), "..",
                          parsed_args.file))
            if not path.isfile(file_path):
                return False

            with open(file_path) as file:
                firstline = file.readline().strip()
                file.seek(0)

                # Handle it as a blcm file if we can
                if firstline.startswith("<BLCMM"):
                    _handle_blcmm_file(file)
                    return False

                # Otherwise treat each line as it's own command
                for line in file:
                    _try_handle_command(line)

        except (_ParsingFailedError, SystemExit):
            pass
        return False

    if name not in _parser_callback_map:
        return False

    parser, callback, splitter = _parser_callback_map[name]
    try:
        callback(parser.parse_args(splitter(args)))
    except _ParsingFailedError as ex:
        ex.log()
    except SystemExit:
        pass
    except Exception:
        unrealsdk.Log(traceback.format_exc())

    return True
Пример #24
0
def _client_message(caller: unrealsdk.UObject, function: unrealsdk.UFunction,
                    params: unrealsdk.FStruct) -> bool:
    message = params.S
    message_type = params.Type
    if message_type is None or not message_type.startswith("unrealsdk."):
        return True

    if message_type == "unrealsdk.__serverack__":
        if len(_message_queue) > 0 and _message_queue[0].ID == message:
            _dequeue_message()
        return False

    message_components = message.split(":", 1)
    if len(message_components) != 2:
        return False
    message_id = message_components[0]

    methods = _client_message_types.get(message_type)
    if methods is not None and len(methods) > 0:
        sample_method = next(iter(methods))
        cls = type(sample_method.__self__)  # type: ignore

        arguments = None
        try:
            arguments = cls.NetworkDeserialize(message_components[1])
        except Exception:
            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
Пример #25
0
    def Hide(self) -> None:
        """
        Hides the text input box, without running any callbacks.

        Displays a warning but does nothing if the text input box is not currently being displayed.
        """
        if self._TrainingBox is None:
            unrealsdk.Log(
                "[UserFeedback] Warning: tried to hide a text input box that was already closed"
            )
            return

        unrealsdk.RemoveHook("WillowGame.WillowGFxTrainingDialogBox.HandleInputKey", "CustomTextInputBox")

        self._TrainingBox.Close()
        self._TrainingBox = None
Пример #26
0
 def open_map(self, levelname):
     """
     Loads the specified map name
     """
     pc = unrealsdk.GetEngine().GamePlayers[0].Actor
     maplist = dumperdata.level_pkgs[self.game][levelname]
     maplist_len = len(maplist)
     for idx, pkgname in enumerate(maplist):
         unrealsdk.Log('Preparing map change for {}: {}, {}'.format(
             pkgname,
             idx == 0,
             idx == (maplist_len - 1),
         ))
         pc.ClientPrepareMapChange(pkgname, idx == 0,
                                   idx == (maplist_len - 1))
     #pc.ClientPrepareMapChange(levelname, True, True)
     pc.ClientCommitMapChange()
     self.setNextDelay(self.map_change_delay)
Пример #27
0
    def ShowButton(self, button: OptionBoxButton) -> None:
        """
        This has been deprecated since version 1.3. Use the optional argument on `Show()` instead.

        Displays the option box with the provided button selected.

        Args:
            button: The button you want to be selected
        Raises:
            ValueError:
                If the provided button is not currently in one of the stored pages. This may happen
                 if you forgot to call Update().
        """
        if not self._DeprecationWarning_ShowButton:
            unrealsdk.Log(
                "[UserFeedback] Use of `OptionBox.ShowButton()` is deprecated!"
            )
            self._DeprecationWarning_ShowButton = True
        self.Show(button)
Пример #28
0
    def Hide(self) -> None:
        """
        Hides the chat box, without running any callbacks.

        Displays a warning but does nothing if the chat box is not currently being displayed.
        """
        if not self.IsShowing():
            unrealsdk.Log(
                "[UserFeedback] Warning: tried to hide a chat box that was already closed"
            )
            return

        unrealsdk.RemoveHook(
            "WillowGame.TextChatGFxMovie.AddChatMessageInternal",
            "ChatBoxInput")
        unrealsdk.RemoveHook("WillowGame.TextChatGFxMovie.HandleTextChatInput",
                             "ChatBoxInput")

        self._Chat.StopTextChatInternal()
        self._Chat.Close()
Пример #29
0
    def load_map(self, name: str, curr_map: str) -> None:
        """
        Load a custom map from a given .json file.

        :param name: The name of the .json map file.
        :return:
        """
        if os.path.isfile(os.path.join(self.path, "Maps", f"{name}.json")):
            with open(os.path.join(self.path, "Maps", f"{name}.json")) as fp:
                map_dict = json.load(fp)
        else:
            unrealsdk.Log(
                f"Map {os.path.join(self.path, 'Maps', f'{name}.json')} does not exist!"
            )
            return

        load_this = map_dict.get(curr_map, None)
        if not load_this:  # No Map data for currently loaded map found!
            return
        placeablehelper.load_map(
            load_this)  # Finally, load the actual map from data dict
Пример #30
0
    def Hide(self) -> None:
        unrealsdk.RemoveHook("WillowGame.WillowGFxDialogBox.Accepted",
                             "CustomOptionBox")
        unrealsdk.RemoveHook("WillowGame.WillowGFxDialogBox.Cancelled",
                             "CustomOptionBox")
        unrealsdk.RemoveHook("WillowGame.WillowGFxDialogBox.HandleInputKey",
                             "CustomOptionBox")

        # If it's already closed just give a warning
        if self._OptionBox is None:
            unrealsdk.Log(
                "[UserFeedback] Warning: tried to hide a option box page that was already closed"
            )
            return

        # This convinces it to instantly GC itself somehow. It'd get collected next cycle if we
        #  ignored it anyway, but might as well get rid of it now.
        self._OptionBox.Cancelled(0)

        self._OptionBox.Close()
        self._OptionBox = None