def UnloadWithHost (host: Mods.Mod) -> None: """ Unload all registered and loaded saving objects with the specified host """ if not isinstance(host, Mods.Mod): raise Exceptions.IncorrectTypeException(host, "host", (Mods.Mod,)) Debug.Log("Unloading all saving objects from the host '%s'" % host.Namespace, This.Mod.Namespace, Debug.LogLevels.Info, group = This.Mod.Namespace, owner = __name__) failedSavingIdentifiers = list() # type: typing.List[str] for savingObject in _registeredSavingObjects: # type: Saving.SaveBase try: if not savingObject.Host == host: continue if not savingObject.Loaded: continue savingObject.Unload() # type: bool except Exception: Debug.Log("Encountered an unhandled exception upon unloading a saving object with the identifier '" + savingObject.Identifier + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__) failedSavingIdentifiers.append(savingObject.Identifier) if len(failedSavingIdentifiers) != 0: _ShowModUnloadFailureDialog(failedSavingIdentifiers) Debug.Log("Finished unloading all saving object from the host '%s' and encountered %s error(s)." % (host.Namespace, str(len(failedSavingIdentifiers))), This.Mod.Namespace, Debug.LogLevels.Info, group = This.Mod.Namespace, owner = __name__)
def _OnStop(cause) -> None: if len(_fullUpdateTimes) != 0: averageFullUpdateTime = round( sum(_fullUpdateTimes) / len(_fullUpdateTimes), 5) # type: float Debug.Log( "Average full reproductive system update time for session: %s seconds." % str(averageFullUpdateTime), This.Mod.Namespace, Debug.LogLevels.Info, group=This.Mod.Namespace, owner=__name__) if len(_individualUpdateTimes) != 0: averageIndividualUpdateTime = round( sum(_individualUpdateTimes) / len(_individualUpdateTimes), 5) # type: float Debug.Log( "Average individual reproductive system update time for session: %s seconds." % str(averageIndividualUpdateTime), This.Mod.Namespace, Debug.LogLevels.Info, group=This.Mod.Namespace, owner=__name__)
def ShowStatusNotification (targetSimInfo: sim_info.SimInfo) -> None: # TODO create quick glance notification, only show the times? if not isinstance(targetSimInfo, sim_info.SimInfo): raise Exceptions.IncorrectTypeException(targetSimInfo, "targetSimInfo", (sim_info.SimInfo,)) targetDotInformation = Dot.GetDotInformation(targetSimInfo) # type: typing.Optional[Dot.DotInformation] if targetDotInformation is None: Debug.Log("Attempted to show a dot app status notification on a sim missing a dot information object.\nSim ID: %s" % targetSimInfo.id, This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__) return if not targetDotInformation.Enabled: Debug.Log("Attempted to show a dot app status notification on a sim its not enabled for.\nSim ID: %s" % targetSimInfo.id, This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__) return dotCycle = targetDotInformation.GetCurrentCycle() # type: typing.Optional[Dot.DotCycle] if dotCycle is None: ShowErrorNotification(targetSimInfo) return text = Language.MakeLocalizationStringCallable(_BuildStatusText(targetSimInfo, dotCycle)) notificationArguments = { "owner": targetSimInfo, "title": StatusNotificationTitle.GetCallableLocalizationString(), "text": text, "icon": lambda *args, **kwargs: shared_messages.IconInfoData(icon_resource = resources.ResourceKeyWrapper(CycleUIResources.DotAppIconKey)), "secondary_icon": lambda *args, **kwargs: shared_messages.IconInfoData(obj_instance = targetSimInfo), } Notifications.ShowNotification(queue = False, **notificationArguments)
def _ShowDialog(key: str, _connection: int = None) -> None: try: if not isinstance(key, str): raise Exceptions.IncorrectTypeException(key, "key", (str, )) except Exception: Debug.Log("Incorrect types for command.", This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__) return try: allSettings = Settings.GetAllSettings() for setting in allSettings: # type: SettingsBase.Setting if setting.Key.lower() == key: setting.ShowDialog() return except Exception: commands.cheat_output( "Failed to show dialog for setting '" + key + "'.", _connection) Debug.Log("Failed to show dialog for setting '" + key + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__) return commands.cheat_output("Cannot find setting '" + key + "'.\n", _connection)
def _WickedWhimsTakeBirthControlPillPatch(originalCallable: typing.Callable, turbo_sim: typing.Any, no_inventory: bool = False, *args, **kwargs) -> bool: try: Debug.Log("Here Pill", This.Mod.Namespace, Debug.LogLevels.Warning) # TODO REMOVE targetSimInfo = turbo_sim.get_sim_info( ) # type: typing.Optional[sim_info.SimInfo] if targetSimInfo is None: return False if no_inventory: SafetyBirthControlPills.TakePill(targetSimInfo, None, requiresPill=False, removePill=False) except: Debug.Log( "Failed to handle WickedWhim's take birth control pill function.", This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__, lockIdentifier=__name__ + ":" + str(Python.GetLineNumber())) return originalCallable(turbo_sim, no_inventory=no_inventory, *args, **kwargs)
def GetLastSimID(targetSimInfo: sim_info.SimInfo) -> typing.Optional[int]: if not isinstance(targetSimInfo, sim_info.SimInfo): Exceptions.IncorrectTypeException(targetSimInfo, "targetSimInfo", (sim_info.SimInfo, )) lastSimIDStatisticType = services.get_instance_manager( resources.Types.STATISTIC).get( LastSimIDStatisticID, None) # type: typing.Optional[typing.Type[statistic.Statistic]] if lastSimIDStatisticType is None: Debug.Log( "Could not find the last sim id statistic type.\nTarget Sim ID: %s" % str(targetSimInfo.id), This.Mod.Namespace, Debug.LogLevels.Error, group=This.Mod.Namespace, owner=__name__, lockIdentifier=__name__ + ":MissingLastSimIDStatisticType") return None lastSimIDStatisticTracker = targetSimInfo.get_tracker( lastSimIDStatisticType ) # type: typing.Optional[statistic_tracker.StatisticTracker] if lastSimIDStatisticTracker is None: Debug.Log( "Could not find the last sim id statistic's tracker in the target sim.\nTarget Sim ID: %s" % str(targetSimInfo.id), This.Mod.Namespace, Debug.LogLevels.Error, group=This.Mod.Namespace, owner=__name__, lockIdentifier=__name__ + ":MissingLastSimIDStatisticTracker") return None lastSimIDStatistic = lastSimIDStatisticTracker.get_statistic( lastSimIDStatisticType, add=True) # type: typing.Optional[statistic.Statistic] if lastSimIDStatistic is None: Debug.Log( "Could not retrieve a sim's last sim id statistic\nTarget Sim ID: %s" % str(targetSimInfo.id), This.Mod.Namespace, Debug.LogLevels.Error, group=This.Mod.Namespace, owner=__name__, lockIdentifier=__name__ + ":MissingLastSimIDStatistic") return None lastSimID = lastSimIDStatistic.get_value() # type: int if lastSimID == 0: return None else: return lastSimID
def _LoadFromDictionaryInternal (self, data: dict, lastVersion: typing.Optional[Version.Version]) -> bool: superOperationSuccessful = super()._LoadFromDictionaryInternal(data, lastVersion) # type: bool self._AddMissingEffects() operationSuccessful = True # type: bool operationInformation = self.SavableOperationInformation # type: str effectsSavingKey = self._effectsSavingKey # type: str effectsDataSavingKey = "Data" # type: str effectsTypeSavingKey = "Type" # type: str try: effectsListData = data[effectsSavingKey] # type: typing.Optional[list] except KeyError: return True if not isinstance(effectsListData, list): raise Exceptions.IncorrectTypeException(effectsListData, "data[%s]" % self._effectsSavingKey, (list,)) for activeEffect in self._activeEffects: # type: EffectsBase.EffectBase if not isinstance(activeEffect, EffectsBase.EffectBase): Debug.Log("Found an object in the effects list that was not an effect.\n%s" % operationInformation, self.HostNamespace, Debug.LogLevels.Warning, group = self.HostNamespace, owner = __name__, lockIdentifier = __name__ + ":EffectSavingOperationNotEffectType") continue try: for effectDataIndex in range(len(effectsListData)): # type: int effectContainerData = effectsListData[effectDataIndex] # type: dict effectTypeIdentifier = effectContainerData.get(effectsTypeSavingKey, None) # type: typing.Optional[str] if effectTypeIdentifier is None or effectTypeIdentifier != activeEffect.TypeIdentifier: continue if not isinstance(effectContainerData, dict): raise Exceptions.IncorrectTypeException(effectContainerData, "data[%s][%s]" % (effectsSavingKey, effectDataIndex), (dict,)) effectData = effectContainerData[effectsDataSavingKey] # type: typing.Optional[dict] if not isinstance(effectData, dict): raise Exceptions.IncorrectTypeException(effectData, "data[%s][%s][%s]" % (effectsSavingKey, effectDataIndex, effectsDataSavingKey), (dict,)) if not activeEffect.LoadFromDictionary(effectData, lastVersion = lastVersion): operationSuccessful = False break except: Debug.Log("Load operation in a savable object failed to load the effect data of an effect with the identifier '%s'.\n%s" % (activeEffect.TypeIdentifier, operationInformation), self.HostNamespace, Debug.LogLevels.Warning, group = self.HostNamespace, owner = __name__) operationSuccessful = False if not operationSuccessful: return False return superOperationSuccessful
def _TargetException (exception: BaseException) -> None: originalCallableFullName = Types.GetFullName(information.OriginalCallable) # type: str if originalCallableFullName == Types.GetFullName(log.exception): Debug.Log("Failed to call target function '" + Types.GetFullName(information.TargetFunction) + "'. Original callable: '" + originalCallableFullName + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, exception = exception, logToGame = False) information.OriginalCallable(This.Mod.Namespace, "Failed to call target function '" + Types.GetFullName(information.TargetFunction) + "'. Original callable: '" + originalCallableFullName + "'.", exc = exception) else: if originalCallableFullName == Types.GetFullName(log.Logger.exception): Debug.Log("Failed to call target function '" + Types.GetFullName(information.TargetFunction) + "'. Original callable: '" + originalCallableFullName + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, exception = exception, logToGame = False) information.OriginalCallable(log.Logger(This.Mod.Namespace), "Failed to call target function '" + Types.GetFullName(information.TargetFunction) + "'. Original callable: '" + originalCallableFullName + "'.", exc = exception) else: Debug.Log("Failed to call target function '" + Types.GetFullName(information.TargetFunction) + "'. Original callable: '" + originalCallableFullName + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, exception = exception)
def _CycleSimulationPhase (self, simulation: ReproductionShared.Simulation, ticks: int) -> None: reproductiveTimeMultiplier = self.ReproductiveTimeMultiplier # type: typing.Union[float, int] simulatingMinutes = ReproductionShared.TicksToReproductiveMinutes(ticks, reproductiveTimeMultiplier) # type: typing.Union[float, int] simulationMemoryKey = self.SimulationMemoryKey simulationMemoryExists = simulationMemoryKey in simulation.Memory # type: bool simulationMemory = simulation.Memory.get(simulationMemoryKey, CycleTrackerSimulationMemory()) # type: CycleTrackerSimulationMemory if self.TimeSinceLastCycle is not None: self.TimeSinceLastCycle += simulatingMinutes if self.CurrentCycle is not None: cycleTicksRemaining = ReproductionShared.ReproductiveMinutesToTicks(self.CurrentCycle.TimeRemaining, reproductiveTimeMultiplier) # type: typing.Union[float, int] if cycleTicksRemaining < ticks: Debug.Log("Simulation stepped over the end of a cycle by %s ticks, this may cause lost time for the tracking sim.\n%s" % (str(ticks - cycleTicksRemaining), self.DebugInformation), This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockReference = self.TrackingSystem) self.CurrentCycle.Simulate(simulation, ticks, reproductiveTimeMultiplier) else: if simulationMemory.CycleStartTesting is None: Debug.Log("Expected the 'CycleStartTesting' to be in the simulation memory, but all we found was None.\n" + self.DebugInformation, This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockReference = self.TrackingSystem) simulationMemory.CycleStartTesting = self.DoCycleStartTesting() elif not simulationMemoryExists: simulationMemory.CycleStartTesting = self.DoCycleStartTesting() if simulationMemory.CycleStartTesting.GetCanStart(): timeUntilCycleStart = simulationMemory.CycleStartTesting.GetTimeUntilStart() # type: typing.Optional[float] cycleStartPlanned = timeUntilCycleStart is not None # type: bool if cycleStartPlanned: ticksUntilCycleStart = ReproductionShared.ReproductiveMinutesToTicks(timeUntilCycleStart, reproductiveTimeMultiplier) # type: int else: ticksUntilCycleStart = 1 # type: int if ticksUntilCycleStart <= ticks: if cycleStartPlanned and ticksUntilCycleStart < ticks: Debug.Log("Simulation stepped over the start of a cycle by %s ticks, this may cause lost time for the tracking sim.\n%s" % (str(ticks - ticksUntilCycleStart), self.DebugInformation), This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockReference = self.TrackingSystem) cycleTypeIdentifier = simulationMemory.CycleStartTesting.GetCycleTypeIdentifier() # type: str cycle = self.GenerateCycle(cycleTypeIdentifier) self.CycleStartTestingSeed = None simulationMemory.CycleStartTesting = None self.CurrentCycle = cycle else: simulationMemory.CycleStartTesting.IncreaseTimeSinceTest(simulatingMinutes) if not simulationMemoryExists: simulation.Memory[simulationMemoryKey] = simulationMemory
def _ShowUpdatesList (updatedModsHex: str, _connection: int = None) -> None: try: updatedMods = ToolsDistribution.UpdateInformation.UpdateInformationListFromHex(updatedModsHex) # type: typing.List[ToolsDistribution.UpdateInformation] except Exception as e: Debug.Log("Failed to decode the inputted update mods data.\nInputted Hex: " + updatedModsHex, This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, exception = e) return try: UIDistribution.ShowUpdatesList(updatedMods) except Exception as e: Debug.Log("Failed to the show updates list dialog.\nInputted Hex: " + updatedModsHex, This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, exception = e) return
def _BuildStatusText (targetSimInfo: sim_info.SimInfo, dotCycle: Dot.DotCycle) -> localization.LocalizedString: if typing.TYPE_CHECKING: majorPhaseText: localization.LocalizedString majorPhaseTimePeriodText: localization.LocalizedString minorPhaseText: localization.LocalizedString minorPhaseTimePeriodText: localization.LocalizedString if dotCycle.GetPhaseIsActive(CycleShared.MenstrualCyclePhases.Follicular): majorPhaseText = StatusNotificationTextFollicular.GetLocalizationString() majorPhaseTimePeriodText = _GetStatusTimePeriodEndingText(dotCycle.GetTimeUntilPhaseEnds(CycleShared.MenstrualCyclePhases.Follicular)) elif dotCycle.GetPhaseIsActive(CycleShared.MenstrualCyclePhases.Luteal): majorPhaseText = StatusNotificationTextLuteal.GetLocalizationString() majorPhaseTimePeriodText = _GetStatusTimePeriodEndingText(dotCycle.GetTimeUntilPhaseEnds(CycleShared.MenstrualCyclePhases.Luteal)) else: majorPhaseText = StatusNotificationTextLuteal.GetLocalizationString() majorPhaseTimePeriodText = _GetStatusTimePeriodEndingText(dotCycle.GetTimeUntilPhaseEnds(CycleShared.MenstrualCyclePhases.Luteal)) Debug.Log("The follicular and luteal phases were both inactive, according to dot.\nTarget Sim ID: %s" % targetSimInfo.id, This.Mod.Namespace, Debug.LogLevels.Error, group = This.Mod.Namespace, owner = __name__) if dotCycle.GetPhaseIsActive(CycleShared.MenstrualCyclePhases.Ovulation): minorPhaseText = StatusNotificationTextOvulationEnding.GetLocalizationString() minorPhaseTimePeriodText = _GetStatusTimePeriodEndingText(dotCycle.GetTimeUntilPhaseEnds(CycleShared.MenstrualCyclePhases.Ovulation)) elif dotCycle.GetPhaseIsActive(CycleShared.MenstrualCyclePhases.Menstruation): minorPhaseText = StatusNotificationTextMenstruationEnding.GetLocalizationString() minorPhaseTimePeriodText = _GetStatusTimePeriodEndingText(dotCycle.GetTimeUntilPhaseEnds(CycleShared.MenstrualCyclePhases.Menstruation)) else: timeUntilOvulation = dotCycle.GetTimeUntilPhaseStarts(CycleShared.MenstrualCyclePhases.Ovulation) # type: float timeUntilMenstruation = dotCycle.GetTimeUntilPhaseStarts(CycleShared.MenstrualCyclePhases.Menstruation) # type: float if timeUntilOvulation > 0: minorPhaseText = StatusNotificationTextOvulationStarting.GetLocalizationString() minorPhaseTimePeriodText = _GetStatusTimePeriodStartingText(dotCycle.GetTimeUntilPhaseStarts(CycleShared.MenstrualCyclePhases.Ovulation)) elif timeUntilMenstruation > 0: minorPhaseText = StatusNotificationTextMenstruationStarting.GetLocalizationString() minorPhaseTimePeriodText = _GetStatusTimePeriodStartingText(dotCycle.GetTimeUntilPhaseStarts(CycleShared.MenstrualCyclePhases.Menstruation)) else: minorPhaseText = StatusNotificationTextMenstruationStarting.GetLocalizationString() minorPhaseTimePeriodText = _GetStatusTimePeriodStartingText(dotCycle.GetTimeUntilPhaseStarts(CycleShared.MenstrualCyclePhases.Menstruation)) Debug.Log("The ovulation and menstruation phases have both finished, according to dot. The cycle was supposed to end at the same time menstruation did.\nTarget Sim ID: %s" % targetSimInfo.id, This.Mod.Namespace, Debug.LogLevels.Error, group = This.Mod.Namespace, owner = __name__) statusText = TextBuilder.BuildText( [ majorPhaseText, "\n", majorPhaseTimePeriodText, "\n\n", minorPhaseText, "\n", minorPhaseTimePeriodText ] ) return statusText
def _ScanForAllSnippets() -> None: if services.snippet_manager is None: raise Exception("Cannot look for snippets, the manager is None.") if len(_scanningSnippets) == 0: return operationStartTime = time.time() # type: float snippetsByType = dict( ) # type: typing.Dict[str, typing.List[snippets.SnippetInstanceMetaclass]] for snippetID, snippet in services.snippet_manager().types.items( ): # type: typing.Any, snippets.SnippetInstanceMetaclass if isinstance(snippet, snippets.SnippetInstanceMetaclass): snippetList = snippetsByType.get( snippet.snippet_type, None) # type: typing.List[snippets.SnippetInstanceMetaclass] if snippetList is None: snippetList = list() snippetsByType[snippet.snippet_type] = snippetList snippetList.append(snippet) for snippetType, snippetCallbacks in _scanningSnippets.items( ): # type: str, typing.List[typing.Callable] snippetList = snippetsByType.get(snippetType, None) if snippetList is None: snippetList = list() for snippetCallback in snippetCallbacks: # type: typing.Callable try: snippetCallback(snippetList) except: Debug.Log("Failed to trigger snippet scan callback at '%s'." % Types.GetFullName(snippetCallback), This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__) operationTime = time.time() - operationStartTime Debug.Log( "Finished scanning for %s types of snippet in %s seconds with %s snippets existing." % (len(_scanningSnippets), operationTime, len(services.snippet_manager().types)), This.Mod.Namespace, Debug.LogLevels.Info, group=This.Mod.Namespace, owner=__name__)
def _TriggerAnnouncement (self, announcementMethodName: str, preemptive: bool, *announcementArgs, **announcementKwargs) -> None: for announcer in Director.GetAllAnnouncers(): # type: typing.Type[Director.Announcer] readReportLockIdentifier = None # type: typing.Optional[str] readReportLockReference = None # type: typing.Any if self.LimitErrors: readReportLockIdentifier = __name__ + ":" + str(Python.GetLineNumber()) # type: str readReportLockReference = announcer try: if not announcer.Enabled: continue if not announcer.Host.IsLoaded() and not announcer.Reliable: continue if preemptive != announcer.Preemptive: continue announcementMethod = getattr(announcer, announcementMethodName) # type: typing.Callable except Exception: from NeonOcean.S4.Main import Debug Debug.Log("Failed to read the announcer at '" + Types.GetFullName(announcer) + "' when triggering the announcement '" + announcementMethodName + "'.", announcer.Host.Namespace, Debug.LogLevels.Exception, group = announcer.Host.Namespace, owner = __name__, lockIdentifier = readReportLockIdentifier, lockReference = readReportLockReference) return else: if readReportLockIdentifier is not None: from NeonOcean.S4.Main import Debug Debug.Unlock(readReportLockIdentifier, readReportLockReference) callReportLockIdentifier = None # type: typing.Optional[str] callReportLockReference = None # type: typing.Any if self.LimitErrors: callReportLockIdentifier = __name__ + ":" + str(Python.GetLineNumber()) # type: str callReportLockReference = announcer try: if self.AnnouncementCallWrapper is None: announcementMethod(*announcementArgs, **announcementKwargs) else: self.AnnouncementCallWrapper(announcementMethod, *announcementArgs, **announcementKwargs) except Exception: from NeonOcean.S4.Main import Debug Debug.Log("Failed to trigger the announcement '" + announcementMethodName + "' for '" + Types.GetFullName(announcer) + "'.", announcer.Host.Namespace, Debug.LogLevels.Exception, group = announcer.Host.Namespace, owner = __name__, lockIdentifier = callReportLockIdentifier, lockReference = callReportLockReference) return else: if callReportLockIdentifier is not None: from NeonOcean.S4.Main import Debug Debug.Unlock(callReportLockIdentifier, callReportLockReference)
def _ShowURL (urlHex: str, _connection: int = None) -> None: try: if not isinstance(urlHex, str): raise Exceptions.IncorrectTypeException(urlHex, "urlHex", (str,)) except Exception as e: Debug.Log("Incorrect types for command.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, exception = e) return try: url = codecs.decode(urlHex, "hex").decode("utf-8") Generic.ShowOpenBrowserDialog(url) except Exception as e: Debug.Log("Failed to show distribution url.\nURL hex '" + str(urlHex) + "'.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__, exception = e) return
def DetermineAllObjectTypes(cls) -> None: operationStartTime = time.time() # type: float cls._objectsByType = dict( ) # type: typing.Dict[str, typing.Set[typing.Type[script_object.ScriptObject]]] # noinspection PyProtectedMember objectManager = services.get_instance_manager( resources.Types.OBJECT ) # type: definition_manager.DefinitionManager objectDefinitions = objectManager.loaded_definitions for typeIdentifier, typeDeterminer in cls._typeDeterminers.items( ): # type: str, typing.Callable matchingObjects = set( ) # type: typing.Set[typing.Type[script_object.ScriptObject]] for objectDefinition in objectDefinitions: # type: typing.Any, definition.Definition matchingType = False # type: bool try: matchingType = typeDeterminer(objectDefinition) except: Debug.Log( "Type determiner failed to determine if an object definition matches the type identifier '" + typeIdentifier + "'.\nObject Definition ID:" + str(objectDefinition.id), cls.Host.Namespace, Debug.LogLevels.Exception, group=cls.Host.Namespace, owner=__name__, lockIdentifier=__name__ + ":" + str(Python.GetLineNumber()), lockReference=typeDeterminer) if matchingType: matchingObjects.add(objectDefinition.cls) cls._objectsByType[typeIdentifier] = matchingObjects operationTime = time.time() - operationStartTime cls._objectTypesDetermined = True Debug.Log( "Finished organizing all objects by type in %s seconds with %s type determiners and %s object definitions existing." % (operationTime, len(cls._typeDeterminers), len(objectDefinitions)), cls.Host.Namespace, Debug.LogLevels.Info, group=cls.Host.Namespace, owner=__name__)
def _SimulateInternal(self, simulation: ReproductionShared.Simulation, ticks: int, reproductiveTimeMultiplier: float) -> None: simulatingMinutes = ReproductionShared.TicksToReproductiveMinutes( ticks, reproductiveTimeMultiplier) # type: float quickMode = Settings.QuickMode.Get() # type: bool if not self.Fertilized: decaying = False # type: bool if self.Age < self.TimeRemaining <= (self.Age + simulatingMinutes): decaying = True if decaying: #TODO set age first? if self.DecayedCallback is None: Debug.Log( "Missing callback to be triggered on ovum decay.", This.Mod.Namespace, Debug.LogLevels.Warning, group=This.Mod.Namespace, owner=__name__, lockIdentifier=__name__ + ":" + str(Python.GetLineNumber())) else: self.DecayedCallback(self) else: if quickMode: implanting = True # type: bool self.Age = self.ImplantationTime else: implanting = False # type: bool if self.Age < self.TimeUntilImplantation <= ( self.Age + simulatingMinutes): implanting = True if implanting: if self.AttemptImplantationCallback is None: Debug.Log( "Missing callback to be triggered on ovum implantation attempt.", This.Mod.Namespace, Debug.LogLevels.Warning, group=This.Mod.Namespace, owner=__name__, lockIdentifier=__name__ + ":" + str(Python.GetLineNumber())) else: self.AttemptImplantationCallback(self) self.Age += simulatingMinutes
def _PregnancyCommodityWatcher( statisticTracker: base_statistic_tracker.BaseStatisticTracker, statisticType: typing.Type[base_statistic.BaseStatistic], oldValue: float, newValue: float) -> None: try: if oldValue != newValue: # We only care about statistic modifier changes here, when those change the old value will always equal the new value. return if not isinstance(statisticTracker.owner, sim_info.SimInfo): return if not statisticTracker.owner.is_pregnant: return if statisticType is not GamePregnancyTracker.PregnancyTracker.PREGNANCY_COMMODITY_MAP.get( sim_info_types.Species.HUMAN, None): return statistic = statisticTracker.get_statistic( statisticType, add=True) # type: base_statistic.BaseStatistic _ApplySettingsPregnancyStatistic(statistic) except: Debug.Log("Failed to handle statistic change.", This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__, lockIdentifier=__name__ + ":" + str(Python.GetLineNumber()))
def _CycleRemovePillFromObjectPatch( originalCallable: typing.Callable, pillsObject: script_object.ScriptObject) -> bool: try: # noinspection PyUnresolvedReferences from wickedwhims.sex.pregnancy.birth_control import pills if pillsObject.definition is not None: if pillsObject.definition.id == pills.BIRTH_CONTROL_PILL_OBJECT_ID: pillsObjectContainingInventory = pillsObject.get_inventory( ) # type: typing.Optional[ComponentsInventory.InventoryComponent] if pillsObjectContainingInventory is not None: return pillsObjectContainingInventory.try_destroy_object( pillsObject) else: pillsObject.destroy() return True except: Debug.Log("Failed to handle Cycle's remove pill from object method.", This.Mod.Namespace, Debug.LogLevels.Warning, group=This.Mod.Namespace, owner=__name__) return originalCallable(pillsObject)
def _OnSimAddCallback (simInfo: sim_info.SimInfo) -> None: if not This.Mod.IsLoaded(): return try: if Reproduction.SimHasSystem(simInfo): Debug.Log("Went to create a reproductive system for a sim being added, but one already exists.", This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__) return simSystem = Reproduction.InitiateReproductiveSystem(simInfo) simsSection = Saving.GetSimsSection() # type: SectionBranched.SectionBranched if Saving.GetSimsSection().SavingObject.Loaded: simSystem.Load(simsSection) except: Debug.Log("Reproduction on sim add callback failed.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__)
def OnClientConnect(cls, clientReference: client.Client) -> None: if not cls._onClientConnectTriggered: searchStartTime = time.time() # type: float try: # noinspection PyProtectedMember _AddLocalizationStringsToDictionaries( GenderedLanguage._allLocalizationStrings, GenderedLanguage._genderedLocalizationStrings) except: _ShowGameSTBLPackageReadErrorNotification() raise searchTime = time.time() - searchStartTime # type: float # noinspection PyProtectedMember Debug.Log( "Found %s localization strings. Of those strings, we found %s with gendered terms we can handle. This operation took %s seconds to complete." % (len(GenderedLanguage._allLocalizationStrings), len(GenderedLanguage._genderedLocalizationStrings), searchTime), This.Mod.Namespace, Debug.LogLevels.Info, group=This.Mod.Namespace, owner=__name__) cls._onClientConnectTriggered = True
def _AddSperm(targetSimHandler: argument_helpers.RequiredTargetParam, sourceSimHandler: argument_helpers.RequiredTargetParam, tryingForBaby: bool = True, _connection=None) -> None: try: if game_services.service_manager is None: return targetSimInfo = targetSimHandler.get_target( services.sim_info_manager()) sourceSimInfo = sourceSimHandler.get_target( services.sim_info_manager()) if not isinstance(targetSimInfo, sim_info.SimInfo): raise ValueError( "Failed to get the target sim, %s is not a valid sim id." % targetSimHandler.target_id) if not isinstance(sourceSimInfo, sim_info.SimInfo): raise ValueError( "Failed to get the source sim, %s is not a valid sim id." % sourceSimHandler.target_id) Insemination.AutoInseminate(targetSimInfo, sourceSimInfo, tryingForBaby=tryingForBaby, generateGenericSperm=True) except Exception as e: Debug.Log("Failed to add sperm to a sim.", This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__, exception=e) raise e
def _Help(_connection: int = None) -> None: try: helpText = "" for consoleCommand in _consoleCommands: # type: ConsoleCommand if not consoleCommand.ShowHelp: continue if len(helpText) != 0: helpText += "\n" if consoleCommand.HelpInput is not None: helpText += consoleCommand.Alias[ consoleCommand. HelpAliasPosition] + " " + consoleCommand.HelpInput else: helpText += consoleCommand.Alias[ consoleCommand.HelpAliasPosition] commands.cheat_output(helpText + "\n", _connection) except Exception: output = commands.CheatOutput(_connection) output("Failed to show help information.") Debug.Log("Failed to show help information.", This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__)
def _AddMissingHandlers(self) -> None: activeTypeIdentifiers = set( handler.TypeIdentifier for handler in self.ActiveHandlers) # type: typing.Set[str] allTypeIdentifiers = HandlersTypes.GetAllHandlerTypeIdentifiers( ) # type: typing.Set[str] for typeIdentifier in allTypeIdentifiers: # type: str if not typeIdentifier in activeTypeIdentifiers: addingHandlerType = HandlersTypes.GetHandlerType( typeIdentifier) try: addingHandler = addingHandlerType( self.TrackingSystem) # type: HandlersBase.HandlerBase except: Debug.Log( "Failed to create instance of the handler type '" + Types.GetFullName(addingHandlerType) + "'.\n" + self.TrackingSystem.DebugInformation, This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__, lockIdentifier=__name__ + " | Creating_Handler", lockReference=addingHandlerType) continue self._AddHandler(addingHandler)
def _WickedWhimsUpdateSexSettingsToGeneralSaveDataPatch( originalCallable: typing.Callable, *args, **kwargs) -> bool: try: # noinspection PyUnresolvedReferences from wickedwhims.sex import sex_settings as WickedWhimsSexSettings if WickedWhimsSexSettings.get_sex_setting( WickedWhimsSexSettings.SexSetting.PREGNANCY_MODE ) != WickedWhimsSexSettings.PregnancyModeSetting.SIMPLE: # noinspection PyProtectedMember WickedWhimsSexSettings._sex_settings_data[ WickedWhimsSexSettings.SexSetting. PREGNANCY_MODE] = WickedWhimsSexSettings.PregnancyModeSetting.SIMPLE if WickedWhimsSexSettings.get_sex_setting( WickedWhimsSexSettings.SexSetting.BIRTH_CONTROL_PILLS_AUTO_USE ) != 0: # noinspection PyProtectedMember WickedWhimsSexSettings._sex_settings_data[ WickedWhimsSexSettings.SexSetting. BIRTH_CONTROL_PILLS_AUTO_USE] = 0 return originalCallable(*args, **kwargs) except: Debug.Log( "Failed to handle WickedWhim's update sex settings to general save data function.", This.Mod.Namespace, Debug.LogLevels.Exception, group=This.Mod.Namespace, owner=__name__, lockIdentifier=__name__ + ":" + str(Python.GetLineNumber())) return originalCallable(*args, **kwargs)
def _SimulateInternal (self, simulation: ReproductionShared.Simulation, ticks: int, reproductiveTimeMultiplier: typing.Union[float, int]) -> None: ageTicks = ReproductionShared.ReproductiveMinutesToTicks(self.Age, reproductiveTimeMultiplier) # type: typing.Union[float, int] decayTick = ReproductionShared.ReproductiveMinutesToTicks(self.Lifetime, reproductiveTimeMultiplier) # type: typing.Union[float, int] decaying = False # type: bool decayed = False # type: bool if ageTicks < decayTick <= (ageTicks + ticks): decaying = True if decayTick <= (ageTicks + ticks): decayed = True if not decayed: decayingAmount = self.DecayingTicks(ticks, reproductiveTimeMultiplier) # type: int else: decayingAmount = self.SpermCount # type: int self.Age = ReproductionShared.TicksToReproductiveMinutes(ageTicks + ticks, reproductiveTimeMultiplier) self.SpermCount -= decayingAmount if decaying: if self.DecayedCallback is None: Debug.Log("Missing callback to be triggered on sperm decay.", This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber())) else: self.DecayedCallback(self)
def Decaying (self, reproductiveMinutes: typing.Union[float, int]) -> int: """ Get the amount of sperm cells that will decay within this many reproductive minutes. This may return a slightly incorrect value if the age or the input are between two game tick. """ if not isinstance(reproductiveMinutes, (float, int)): raise Exceptions.IncorrectTypeException(reproductiveMinutes, "reproductiveMinutes", (float, int)) if reproductiveMinutes < 0: raise ValueError("The parameter 'reproductiveMinutes' cannot be less than 0.") if self.SpermCount == 0: return 0 if reproductiveMinutes == 0: return 0 currentAge = self.Age # type: float nextAge = self.Age + reproductiveMinutes # type: float if nextAge >= self.Lifetime: return self.SpermCount currentPercentageRemaining = 1.0 - self.LifetimeDistribution.CumulativeDistribution(currentAge) # type: typing.Union[float, int] nextPercentageRemaining = 1.0 - self.LifetimeDistribution.CumulativeDistribution(nextAge) # type: typing.Union[float, int] percentageRemainingChange = nextPercentageRemaining - currentPercentageRemaining # type: typing.Union[float, int] originalSpermCount = int(self.SpermCount / currentPercentageRemaining) # type: int decayingSpermCount = int(originalSpermCount * percentageRemainingChange) # type: int if decayingSpermCount < 0: Debug.Log("Calculated a decaying sperm count of less than zero (%s)." % decayingSpermCount, This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber())) return int(originalSpermCount * percentageRemainingChange)
def ZoneSave (cls, zoneReference: zone.Zone, saveSlotData: typing.Optional[typing.Any] = None) -> None: if saveSlotData is None: return commitSave = saveSlotData.slot_id != 0 # type: bool doOverrideBackupCommit = False # type: bool try: if commitSave: gameSaveFilePath = SaveShared.GetGameSaveFilePath(saveSlotData.slot_id) # type: str loadedSlotID = Save.GetLoadedSlotID() # type: typing.Optional[int] if loadedSlotID is not None: overridingSave = loadedSlotID != saveSlotData.slot_id and os.path.exists(gameSaveFilePath) # type: bool if overridingSave: gameSaveModifiedTime = datetime.datetime.fromtimestamp(os.path.getmtime(gameSaveFilePath)) # type: datetime.datetime overrideBackupMargin = datetime.timedelta(seconds = 3) if datetime.datetime.now() - overrideBackupMargin <= gameSaveModifiedTime: doOverrideBackupCommit = True except: Debug.Log("Failed to check if an override backup commit occurred.", This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__) if doOverrideBackupCommit: Save.DoOverrideBackupCommit(saveSlotData.slot_id) Save.Save(saveSlotID = saveSlotData.slot_id, commitSave = commitSave)
def SelectPerformanceType (self, seed: typing.Optional[int] = None) -> typing.Tuple[str, PerformanceTypeInfo]: """ Randomly select one of the performance type in this woohoo safety method. """ if seed is None: seed = random.randint(-1000000000, 1000000000) # type: int if not isinstance(seed, int): raise Exceptions.IncorrectTypeException(seed, "seed", (int, None)) if len(self.PerformanceTypes) == 0: raise Exception("Could not find any safety method performance type to select.\nGUID: %s" % self.GUID) if len(self.PerformanceTypeChances.Options) == 0: raise Exception("Could not select a performance type 'PerformanceTypeChances' has no options.\nGUID: %s" % self.GUID) performanceType = self.PerformanceTypeChances.ChooseOption(seed = seed + -443757754).Identifier # type: str performanceTypeInfo = self.PerformanceTypes.get(performanceType, None) # type: WoohooSafetyMethod.PerformanceTypeInfo if performanceTypeInfo is None: Debug.Log("Randomly selected performance type that doesn't exist.\nGUID: %s, Performance Type: %s" % (str(self.GUID), performanceType), This.Mod.Namespace, Debug.LogLevels.Error, group = This.Mod.Namespace, owner = __name__) return random.choice(self.PerformanceTypes) return performanceType, performanceTypeInfo
def __init__ (self, woohooSafetyMethod: WoohooSafetyMethod, autoSelectPerformance: bool = True, autoSelectSeed: typing.Optional[int] = None): """ An object to choose a woohoo safety method performance type and keep track of the selection. :param woohooSafetyMethod: The woohoo safety method from which we are selecting a performance type. :type woohooSafetyMethod: WoohooSafetyMethod :param autoSelectPerformance: Whether or not we should automatically select a performance type from this safety method. :type autoSelectPerformance: bool :param autoSelectSeed: The seed that will be used to randomly select a performance type. :type autoSelectSeed: typing.Optional[int] """ if not isinstance(woohooSafetyMethod, WoohooSafetyMethod): raise Exceptions.IncorrectTypeException(woohooSafetyMethod, "woohooSafetyMethod", (WoohooSafetyMethod,)) if not isinstance(autoSelectPerformance, bool): raise Exceptions.IncorrectTypeException(autoSelectPerformance, "autoSelectPerformance", (bool,)) if not isinstance(autoSelectSeed, int) and autoSelectSeed is not None: raise Exceptions.IncorrectTypeException(autoSelectSeed, "autoSelectSeed", (int,)) self.WoohooSafetyMethod = woohooSafetyMethod # type: WoohooSafetyMethod self.SelectedPerformanceType = None # type: typing.Optional[str] self.SelectedPerformanceTypeInfo = None # type: typing.Optional[WoohooSafetyMethod.PerformanceTypeInfo] if autoSelectPerformance: if autoSelectSeed is None: autoSelectSeed = woohooSafetyMethod.GetUniqueSeed() + -443757754 try: self.SelectPerformanceType(seed = autoSelectSeed) except: Debug.Log("Failed to select performance type.", This.Mod.Namespace, Debug.LogLevels.Exception, group = This.Mod.Namespace, owner = __name__)
def ResolveSTBLText (text: str, tokens: typing.Sequence) -> typing.Optional[str]: """ Get the true text this STBL string combined with these tokens. This will return none if the text could not be resolved, or if the current language is not supported. Not all texts can be resolved because this system doesn't handle every tag that the game can handle. """ if not isinstance(text, str): raise Exceptions.IncorrectTypeException(text, "text", (str,)) if not isinstance(tokens, typing.Sequence): raise Exceptions.IncorrectTypeException(tokens, "tokens", (typing.Sequence,)) currentLanguageHandler = LanguageHandlers.GetCurrentLanguageHandler() # type: typing.Optional[typing.Type[LanguageHandlers.LanguageHandlerBase]] if currentLanguageHandler is None: return None try: resolvedText = _ResolveRegularTags(text, tokens, currentLanguageHandler) if re.match(SingleTagPattern, resolvedText) is not None: raise _UnsupportedLocalizationStringException("Found a tag that was never resolved.") except _UnsupportedLocalizationStringException: Debug.Log("Could not resolve an unsupported localization string.\nText: %s" % text, This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockThreshold = 2) return None return resolvedText