def ModOptionChanged(self, option: OptionsWrapper.Base, newValue: Any) -> None: if option not in self.Options: return # Only need to redo these numbers when changing multiplier, always have to redo spawn limit if option == self.MultiplierSlider: # This function gets called after the value is changed grr adjustment = self.MultiplierSlider.CurrentValue / self.OldMultiplier self.OldMultiplier = self.MultiplierSlider.CurrentValue for den in unrealsdk.FindAll("PopulationOpportunityDen"): self.MultiplyDenIfAble(den, adjustment) # Again careful incase our reference has been GCed popMaster = unrealsdk.FindAll("WillowPopulationMaster")[-1] if popMaster is None: return if popMaster != self.CurrentPopMaster: self.CurrentPopMaster = popMaster self.OriginalLimit = popMaster.MaxActorCost if self.SpawnLimitSpinner.CurrentValue == "Standard": popMaster.MaxActorCost = self.OriginalLimit elif self.SpawnLimitSpinner.CurrentValue == "Linear": popMaster.MaxActorCost = self.OriginalLimit * self.MultiplierSlider.CurrentValue elif self.SpawnLimitSpinner.CurrentValue == "Unlimited": popMaster.MaxActorCost = 0x7FFFFFFF
def merge_files(self): SparkServiceConfiguration = None set_cmd = "set {} {} ({})\n" with open(os.path.join(self.PATH, "merge.txt"), "w", encoding="cp1252") as merge_fp: for file in self.definition_files: with open(file, "r", encoding="cp1252") as fp: for line in fp: if line.lstrip().lower().startswith("set"): if "SparkService" not in line: merge_fp.write(line) else: _split = line.split(maxsplit=3) attr = _split[2] # set0 Object1 attribute2 value3: to_merge = _split[3].rstrip() if attr.lower() == "keys": self.keys.append(to_merge[1:-1]) elif attr.lower() == "values": self.values.append(to_merge[1:-1]) for x in unrealsdk.FindAll("SparkServiceConfiguration"): if x.ServiceName == "Micropatch": SparkServiceConfiguration = x.PathName(x) break if not SparkServiceConfiguration: SparkServiceConfiguration = "Transient.SparkServiceConfiguration_0" merge_fp.write("set Transient.SparkServiceConfiguration_0 ServiceName Micropatch\n") merge_fp.write("set Transient.SparkServiceConfiguration_0 ConfigurationGroup Default\n") gb_acc = unrealsdk.FindAll("GearboxAccountData")[-1] merge_fp.write( "set {} Services (Transient.SparkServiceConfiguration_0)\n".format(gb_acc.PathName(gb_acc))) merge_fp.write(set_cmd.format(SparkServiceConfiguration, "Keys", ",".join(self.keys))) merge_fp.write(set_cmd.format(SparkServiceConfiguration, "Values", ",".join(self.values)))
def OnUpdate(self) -> None: # Can't look for pawns directly due to the streaming ones, which will crash the game all_pawns = [ PC.Pawn for PC in unrealsdk.FindAll("WillowPlayerController") if PC.Pawn is not None ] for vendor in unrealsdk.FindAll("WillowVendingMachine"): closet_pawn = None min_dist = -1 for pawn in all_pawns: dist = ((vendor.Location.X - pawn.Location.X)**2 + (vendor.Location.Y - pawn.Location.Y)**2 # noqa + (vendor.Location.Z - pawn.Location.Z)**2 # noqa )**0.5 if dist < min_dist or min_dist == -1: dist = min_dist closet_pawn = pawn cost: int if vendor.ShopType == 2: cost = self.GetHealthCost(closet_pawn, vendor) elif vendor.ShopType == 1: cost = self.GetAmmoCost(closet_pawn, vendor) else: continue vendor.SetUsability(cost != 0, 1) vendor.Behavior_ChangeUsabilityCost(1, 0, cost, 1)
def BuyAmmo(self, Pawn: unrealsdk.UObject, Vendor: unrealsdk.UObject) -> None: manager = Pawn.Controller.ResourcePoolManager # Don't want to refill nades/rockets in maps that don't sell them valid_pools = [] for item in unrealsdk.FindAll("WillowUsableItem"): if item.Owner != Vendor: continue if item.DefinitionData is None or item.DefinitionData.ItemDefinition is None: continue name = item.DefinitionData.ItemDefinition.Name if name not in self.AMMO_MAP: continue valid_pools.append(self.AMMO_MAP[name].ResourceName) for pool in unrealsdk.FindAll("AmmoResourcePool"): if pool.Outer != manager: continue if pool.Definition.Resource.Name in valid_pools: pool.SetCurrentValue(pool.GetMaxValue()) if "Ammo_Grenade_Protean" in valid_pools: for pool in unrealsdk.FindAll("ResourcePool"): if pool.Outer != manager: continue if pool.Definition.Resource.Name == "Ammo_Grenade_Protean": pool.SetCurrentValue(pool.GetMaxValue()) break
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 OnPress(self) -> None: playerPools = [] # Unintuitively, `unrealsdk.GetEngine().GamePlayers` does not hold remote players for pawn in unrealsdk.FindAll("WillowPlayerPawn"): if pawn.HealthPool.Data is not None: playerPools.append(pawn.HealthPool.Data) for pool in unrealsdk.FindAll("HealthResourcePool"): if pool in playerPools: continue pool.CurrentValue = 0
def OnRun(self, msg: JSON) -> None: self.ShowRedemption(msg) player_pools = [] # Unintuitively, `unrealsdk.GetEngine().GamePlayers` does not hold remote players for pawn in unrealsdk.FindAll("WillowPlayerPawn"): if pawn.HealthPool.Data is not None: player_pools.append(pawn.HealthPool.Data) for pool in unrealsdk.FindAll("HealthResourcePool"): if pool in player_pools: continue pool.CurrentValue = 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)
def Disable(self) -> None: unrealsdk.RemoveHook( "GearboxFramework.PopulationMaster.SpawnPopulationControlledActor", self.Name) unrealsdk.RemoveHook( "WillowGame.PopulationOpportunityDen.PostBeginPlay", self.Name) for den in unrealsdk.FindAll("PopulationOpportunityDen"): self.MultiplyDenIfAble(den, 1 / self.MultiplierSlider.CurrentValue) # Being careful incase our reference has been GCed if unrealsdk.FindAll( "WillowPopulationMaster")[-1] == self.CurrentPopMaster: self.CurrentPopMaster.MaxActorCost = self.OriginalLimit
def get_current_region_stage() -> int: pc = bl2tools.get_player_controller() if pc.GetCurrentPlaythrough() != 2: will_pop = unrealsdk.FindAll("WillowPopulationOpportunityPoint")[1:] pop = unrealsdk.FindAll("PopulationOpportunityPoint")[1:] regions = pop if len(pop) > len(will_pop) else will_pop region_game_stage = max( pc.GetGameStageFromRegion(x.GameStageRegion) for x in regions if x.GameStageRegion) else: # op_choice = pc.OverpowerChoiceValue region_game_stage = pc.Pawn.GetGameStage( ) # (op_choice if op_choice is not None else 0) return region_game_stage
def TakeDamage(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool: PC = unrealsdk.GetEngine().GamePlayers[0].Actor if params.InstigatedBy != PC: return True if not self.IsOn: return True game = unrealsdk.FindAll("WillowCoopGameInfo")[-1] if game.IsFriendlyFire(caller, params.InstigatedBy.Pawn): return True caller.SetShieldStrength(0) # Try set the health to 1 so that your shot kills them, giving xp # Only do it if they have more than 1 health though, so that you don't get stuck in a # loop if you somehow deal less than 1 damage if caller.GetHealth() > 1: caller.SetHealth(1) else: caller.SetHealth(0) return True
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)
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)
def Enable(self) -> None: def CreateWeaponScopeMovie(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.WillowHUD.CreateWeaponScopeMovie", "ItemLevelUncapper", CreateWeaponScopeMovie) # 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 in objects: unrealsdk.KeepAlive(unrealsdk.FindObject(obj[0], obj[1])) # 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)
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
def ModOptionChanged(self, option, new_value): if option in self.Options: if not get_pc() or not get_pc().Pawn or not get_pc().Pawn.Weapon: return WeaponType = get_pc( ).Pawn.Weapon.DefinitionData.WeaponTypeDefinition if option.Caption == "FirstPersonMeshFOV": self.change_MeshFOV(new_value, WeaponType) elif option.Caption == "PlayerViewOffset.X": self.change_ViewOffset(option.Caption, new_value, WeaponType) elif option.Caption == "PlayerViewOffset.Y": self.change_ViewOffset(option.Caption, new_value, WeaponType) elif option.Caption == "PlayerViewOffset.Z": self.change_ViewOffset(option.Caption, new_value, WeaponType) elif option.Caption == "Save current type to file": self.save_to_json(WeaponType) elif option.Caption == "Save same type to file": for wt in unrealsdk.FindAll("WeaponTypeDefinition"): if wt.BodyWeaponHoldName == WeaponType.BodyWeaponHoldName: self.save_to_json(wt) elif option.Caption == "Load from files": self.load_from_files()
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
def HandleVerificationReceived(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool: base = unrealsdk.FindAll("SparkServiceConfiguration")[-1] for i in range(self.DUMMY_AMOUNT): obj = unrealsdk.ConstructObject(Class=base.Class, Outer=base.Outer) obj.ServiceName = "Dummy" unrealsdk.RemoveHook("GearboxFramework.SparkInitializationProcess.HandleVerificationReceived", "FixHotfixes") return True
def CreateWeaponScopeMovie(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
def map_loaded(caller: unrealsdk.UObject, function: unrealsdk.UFunction, params: unrealsdk.FStruct) -> bool: pc = unrealsdk.GetEngine().GamePlayers[0].Actor if pc and pc.Pawn: self.ak_events = [ ak for ak in unrealsdk.FindAll("AkEvent")[1:] if ak.bVoice ] return True
def SettingsInputPressed(self, name: str) -> None: if name == "Load": self.SettingsInputs = { "R": "Reload From File", "N": "New Seed", "Delete": "Delete All", "O": "Open Seed File" } # self.Status = "<font color='#00FF00'>Loaded</font>" self.Status = "Enabled" self.Name = super().Name + " - <font color='#00FF00'>Loaded</font>" # Save the default mission dependencies, so that we're able to restore them # We can't do this in __init__() cause they're not all loaded at that point self.DefaultDependencies: Dict[unrealsdk.UObject, List[unrealsdk.UObject]] = {} self.DefaultObjectiveDependencies: Dict[unrealsdk.UObject, Tuple[unrealsdk.UObject, int]] = {} for mission in unrealsdk.FindAll("MissionDefinition"): # Filter out the default MissionDefinition and all main missions if mission.bPlotCritical or not mission.MissionName: continue # Need to convert this to a list because the default FArray returned is a reference self.DefaultDependencies[mission] = list(mission.Dependencies) self.DefaultObjectiveDependencies[mission] = ( mission.ObjectiveDependency.Objective, mission.ObjectiveDependency.Status) self.LoadFromFile() elif name == "Reload From File": self.LoadFromFile() elif name == "New Seed": seed = random.randrange(0xFFFFFFFF) SMRSeed = SideMissionRandomizerSeed(seed, str(seed)) self.SeedInfo.append(SMRSeed) self.SaveSeedInfo() newMod = SideMissionRandomizerChild(SMRSeed) index = unrealsdk.Mods.index(self) + 1 unrealsdk.Mods.insert(index, newMod) self.EnableChild(newMod) elif name == "Delete All": if path.exists(self.SEED_PATH): remove(self.SEED_PATH) self.LoadFromFile() elif name == "Open Seed File": if not path.exists(self.SEED_PATH): self.SaveSeedInfo() startfile(self.SEED_PATH)
def OnPress(self) -> None: playerPawn = unrealsdk.GetEngine().GamePlayers[0].Actor.Pawn game = unrealsdk.FindAll("WillowCoopGameInfo")[-1] playerPools = [] # Unintuitively, `unrealsdk.GetEngine().GamePlayers` does not hold remote players for pawn in unrealsdk.FindAll("WillowPlayerPawn"): if pawn.HealthPool.Data is not None: playerPools.append(pawn.HealthPool.Data) for pool in unrealsdk.FindAll("HealthResourcePool"): if pool in playerPools: continue if pool.AssociatedProvider is None or pool.AssociatedProvider.Pawn is None: continue if game.IsFriendlyFire(pool.AssociatedProvider.Pawn, playerPawn): continue pool.CurrentValue = 0
def OnPress(self) -> None: count = 0 for obj in unrealsdk.FindAll("WillowVendingMachine"): if obj.Name == "Default__WillowVendingMachine": continue count += 1 obj.ResetInventory() ShowHUDMessage(self.Name, f"Reset {count} shops")
def LoadPlayerPools(self, pawn: unrealsdk.UObject) -> None: if pawn in self.PlayerAmmoPools: return self.PlayerAmmoPools[pawn] = set() # Unfortuantly manager.ResourcePools is another fixed array, we need another findall manager = pawn.Controller.ResourcePoolManager for pool in unrealsdk.FindAll("AmmoResourcePool"): if pool.Outer != manager: continue self.PlayerAmmoPools[pawn].add(pool) # Of course there had to be one odd one out, leading to yet another findall :| for pool in unrealsdk.FindAll("ResourcePool"): if pool.Outer != manager: continue if pool.Definition.Resource.Name == "Ammo_Grenade_Protean": self.PlayerAmmoPools[pawn].add(pool) return
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 ShowChatMessage(User: str, Message: str, Timestap: datetime = datetime.now(), ShowTimestamp: bool = True) -> None: is12h = unrealsdk.FindAll("WillowSaveGameManager")[0].TimeFormat == "12" time_str = Timestap.strftime(("[%H:%M:%S]", "[%I:%M:%S%p]")[is12h]).lower() if ShowTimestamp: User = f"{User} {time_str}" ChatMovie = unrealsdk.GetEngine().GamePlayers[0].Actor.GetTextChatMovie() ChatMovie.AddChatMessageInternal(User, Message)
def GetAmmoCost(self, Pawn: unrealsdk.UObject, Vendor: unrealsdk.UObject) -> int: manager = Pawn.Controller.ResourcePoolManager ammo_needed = {} for pool in unrealsdk.FindAll("AmmoResourcePool"): if pool.Outer != manager: continue name = pool.Definition.Resource.Name ammo_needed[name] = int(pool.GetMaxValue()) - int( pool.GetCurrentValue()) # Of course there had to be one odd one out :| for pool in unrealsdk.FindAll("ResourcePool"): if pool.Outer != manager: continue if pool.Definition.Resource.Name == "Ammo_Grenade_Protean": name = pool.Definition.Resource.Name ammo_needed[name] = int(pool.GetMaxValue()) - int( pool.GetCurrentValue()) break total_price = 0 for item in unrealsdk.FindAll("WillowUsableItem"): if item.Owner != Vendor: continue if item.DefinitionData is None or item.DefinitionData.ItemDefinition is None: continue name = item.DefinitionData.ItemDefinition.Name if name not in self.AMMO_MAP: continue amount = self.AMMO_MAP[name].AmountPerPurchase price = Vendor.GetSellingPriceForInventory(item, Pawn.Controller, 1) / amount needed = ammo_needed[self.AMMO_MAP[name].ResourceName] if needed != 0: total_price += max(1, int(needed * price)) return total_price
def instantiate(static_mesh: unrealsdk.UObject) -> unrealsdk.UObject: if not static_mesh: return None new_smc = bl2tools.get_world_info( ).MyEmitterPool.GetFreeStaticMeshComponent(True) collection_actor = unrealsdk.FindAll("StaticMeshCollectionActor")[-1] new_smc.SetStaticMesh(static_mesh, True) new_smc.SetBlockRigidBody(True) new_smc.SetActorCollision(True, True, True) new_smc.SetTraceBlocking(True, True) collection_actor.AttachComponent(new_smc) return new_smc
def ModOptionChanged(self, option: Options.Base, new_value: Any) -> None: if option not in self.Options: return # Only need to redo these numbers when changing multiplier, always have to redo spawn limit if option == self.MultiplierSlider: new_value = cast(int, new_value) # This function gets called after the value is changed grr adjustment = new_value / self.OldMultiplier self.OldMultiplier = new_value for den in unrealsdk.FindAll("PopulationOpportunityDen"): self.MultiplyDenIfAble(den, adjustment) for encounter in unrealsdk.FindAll("PopulationEncounter"): self.MultiplePopEncounterIfAble(encounter, adjustment) # Again careful incase our reference has been GCed pop_master = unrealsdk.FindAll("WillowPopulationMaster")[-1] if pop_master is None: return if pop_master != self.CurrentPopMaster: self.CurrentPopMaster = pop_master self.OriginalLimit = pop_master.MaxActorCost # Make sure we have the new value spawn_limit = self.SpawnLimitSpinner.CurrentValue if option == self.SpawnLimitSpinner: spawn_limit = cast(str, new_value) if spawn_limit == SpawnLimitType.Standard: pop_master.MaxActorCost = self.OriginalLimit elif spawn_limit == SpawnLimitType.Linear: multiplier = self.MultiplierSlider.CurrentValue if option == self.MultiplierSlider: multiplier = cast(int, new_value) pop_master.MaxActorCost = round(self.OriginalLimit * multiplier) elif spawn_limit == SpawnLimitType.Unlimited: pop_master.MaxActorCost = 0x7FFFFFFF
def ModOptionChanged(self, option: unrealsdk.Options.Boolean, new_value: bool) -> None: if option != self.UpdatingOption: return # If you turn on updating and there are people close to vendors, start updating if new_value: if len(self.TouchingActors) > 0: AsyncUtil.RunEvery(self.UPDATE_DELAY, self.OnUpdate, self.Name) # If you turn off updating, stop updating and make sure all vendors are usable at no cost else: AsyncUtil.CancelFutureCallbacks(self.Name) for vendor in unrealsdk.FindAll("WillowVendingMachine"): if vendor.ShopType == 1 or vendor.ShopType == 2: vendor.SetUsability(True, 1) vendor.Behavior_ChangeUsabilityCost(1, 0, 0, 1)