Пример #1
0
class HovertipTuning:
    HOVERTIP_RESTRICTIONS = TunableList(
        description=
        '\n        List of skill dependencies for tooltip fields.  This will show the \n        tagged fields only if the selected sim matches the skill requirement\n        tuned. \n        e.g.  Only sims with gardening level 2 can see all the sub_icon data\n        of a plant.\n        PS: This tunable is on expert mode since on field_name refers to \n        field names on a protobuff, this should only be tuned by a GPE or with \n        a GPE help.  \n        ',
        tunable=TunableHovertipTuple(),
        tuning_filter=FilterTag.EXPERT_MODE,
        export_modes=tunable_base.ExportModes.All)
Пример #2
0
def _get_tunable_household_member_list(template_type, is_optional=False):
    if template_type == SimTemplateType.PREMADE_HOUSEHOLD:
        template_reference_type = PremadeSimTemplate
    else:
        template_reference_type = TunableSimTemplate
    tuple_elements = {
        'sim_template':
        template_reference_type.TunableReference(
            description=
            '            \n            A template to use for creating a household member. If this\n            references a resource that is not installed, the household member is\n            ignored and the family is going to be created without this\n            individual.\n            ',
            pack_safe=is_optional),
        'household_member_tag':
        TunableEnumWithFilter(
            description=
            '            \n            Tag to be used to create relationship between sim members. This does\n            NOT have to be unique for all household templates. If you want to\n            add more tags in the tag tuning just add with prefix of\n            household_member.r.\n            ',
            tunable_type=tag.Tag,
            default=tag.Tag.INVALID,
            filter_prefixes=HOUSEHOLD_FILTER_PREFIX)
    }
    if is_optional:
        tuple_elements['chance'] = TunablePercent(
            description=
            '\n            The chance that this household member is created when the household\n            is created. This is useful for "optional" Sims. For example, you\n            might want to tune a third of typical nuclear families to own a dog,\n            should the resource be available.\n            ',
            default=100)
    else:
        tuple_elements['locked_args'] = {'chance': 1}
    return TunableList(
        description=
        '\n        A list of sim templates that will make up the sims in this household.\n        ',
        tunable=TunableTuple(**tuple_elements))
class _TargetActionRules(HasTunableFactory, AutoFactoryInit):
    FACTORY_TUNABLES = {
        'chance':
        TunablePercent(
            description=
            '\n            A random chance of this action getting applied (default 100%).\n            ',
            default=100),
        'test':
        TunableTestSet(
            description=
            '\n            A test to decide whether or not to apply this particular set of actions to the target object.\n            ',
            tuning_group=GroupNames.TESTS),
        'actions':
        TunableList(
            description=
            '\n            A list of one or more ObjectRoutingBehaviorActions to run on the\n            target object after routing to it. These are applied in sequence.\n            ',
            tunable=TunableVariant(
                play_animation=ObjectRoutingBehaviorActionAnimation.
                TunableFactory(),
                destroy_objects=ObjectRoutingBehaviorActionDestroyObjects.
                TunableFactory(),
                apply_loot=ObjectRoutingBehaviorActionApplyLoot.TunableFactory(
                ),
                default='play_animation')),
        'abort_if_applied':
        Tunable(
            description=
            "\n            Don't run any further actions from this list of action rules if \n            conditions are met and this action is executed.\n            ",
            tunable_type=bool,
            default=False)
    }
class OwnableComponent(Component,
                       HasTunableFactory,
                       component_name=types.OWNABLE_COMPONENT,
                       persistence_key=protocols.PersistenceMaster.
                       PersistableData.OwnableComponent):
    __qualname__ = 'OwnableComponent'
    DEFAULT_OWNABLE_COMPONENT_AFFORDANCES = TunableList(
        TunableReference(manager=services.get_instance_manager(
            sims4.resources.Types.INTERACTION)),
        description='Affordances that all ownable component owners have.')

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._sim_owner_id = None

    def update_sim_ownership(self, new_sim_id):
        self._sim_owner_id = new_sim_id

    @componentmethod_with_fallback(lambda: None)
    def get_sim_owner_id(self):
        return self._sim_owner_id

    def save(self, persistence_master_message):
        if self._sim_owner_id is None:
            return
        persistable_data = protocols.PersistenceMaster.PersistableData()
        persistable_data.type = protocols.PersistenceMaster.PersistableData.OwnableComponent
        ownable_component_data = persistable_data.Extensions[
            protocols.PersistableOwnableComponent.persistable_data]
        if self._sim_owner_id is not None:
            ownable_component_data.sim_owner_id = self._sim_owner_id
        persistence_master_message.data.extend([persistable_data])

    def _owning_sim_in_owning_household(self, sim_id):
        owner_household_id = self.owner.get_household_owner_id()
        if sim_id is None or owner_household_id is None:
            return False
        household = services.household_manager().get(owner_household_id)
        if household is None:
            return False
        return household.sim_in_household(sim_id)

    def _on_households_loaded_verify(self):
        if not self._owning_sim_in_owning_household(self._sim_owner_id):
            self._sim_owner_id = None
        else:
            self.owner.update_object_tooltip()

    def load(self, persistable_data):
        ownable_component_data = persistable_data.Extensions[
            protocols.PersistableOwnableComponent.persistable_data]
        if ownable_component_data.HasField('sim_owner_id'):
            self._sim_owner_id = ownable_component_data.sim_owner_id
            services.current_zone().register_callback(
                zone_types.ZoneState.HOUSEHOLDS_AND_SIM_INFOS_LOADED,
                self._on_households_loaded_verify)

    def component_super_affordances_gen(self, **kwargs):
        for affordance in self.DEFAULT_OWNABLE_COMPONENT_AFFORDANCES:
            yield affordance
Пример #5
0
class _ObjectDefinitionTested(CreationDataBase, HasTunableSingletonFactory,
                              AutoFactoryInit):
    FACTORY_TUNABLES = {
        'fallback_definition':
        TunableReference(
            description=
            '\n            Should no test pass, use this definition.\n            ',
            manager=services.definition_manager(),
            allow_none=True),
        'definitions':
        TunableList(
            description=
            '\n            A list of potential object definitions to use.\n            ',
            tunable=TunableTuple(
                weight=TunableMultiplier.TunableFactory(
                    description=
                    '\n                    The weight of this definition relative to other\n                    definitions in this list.\n                    '
                ),
                definition=TunableReference(
                    description=
                    '\n                    The definition of the object to be created.\n                    ',
                    manager=services.definition_manager(),
                    pack_safe=True)))
    }

    def get_definition(self, resolver):
        definition = weighted_random_item([
            (pair.weight.get_multiplier(resolver), pair.definition)
            for pair in self.definitions
        ])
        if definition is not None:
            return definition
        return self.fallback_definition
Пример #6
0
class _RandomWeightedRecipe(_RandomRecipeBase, CreationDataBase,
                            HasTunableSingletonFactory, AutoFactoryInit):
    FACTORY_TUNABLES = {
        'weighted_recipes':
        TunableList(
            description=
            '\n            A list of weighted list of recipes that can be available for recipe creation.\n            ',
            tunable=TunableTuple(
                description=
                '\n                The weighted recipe.\n                ',
                recipe=_RecipeDefinition.TunableFactory(
                    recipe_factory_tuning={'pack_safe': True}),
                weight=TunableMultiplier.TunableFactory()),
            minlength=1)
    }

    def get_creation_params(self, resolver):
        weighted_recipe_creation_data = list(
            (weighted_recipe.weight.get_multiplier(resolver),
             weighted_recipe.recipe)
            for weighted_recipe in self.weighted_recipes)
        recipe_factory = weighted_random_item(weighted_recipe_creation_data)
        return ObjectCreationParams(
            recipe_factory.get_definition(resolver),
            {'chosen_creation_data': (recipe_factory, recipe_factory.recipe)})
Пример #7
0
class MaxisLotData(metaclass=HashedTunedInstanceMetaclass,
                   manager=services.get_instance_manager(
                       sims4.resources.Types.MAXIS_LOT)):
    __qualname__ = 'MaxisLotData'
    INSTANCE_TUNABLES = {
        'household_description':
        TunableHouseDescription(
            description=
            '\n                The household description for this static lot.\n                '
        ),
        'venue_types':
        TunableList(tunable=TunableReference(
            description=
            '\n                    Venue types for which this venue lot is valid.\n                    ',
            manager=services.get_instance_manager(sims4.resources.Types.VENUE),
            class_restrictions=Venue))
    }

    @classmethod
    def supports_any_venue_type(cls, venue_types):
        for venue_type in cls.venue_types:
            while venue_type in venue_types:
                return True
        return False

    @classmethod
    def get_intersecting_venue_types(cls, venue_types):
        intersecting_venues = []
        for venue_type in cls.venue_types:
            while venue_type in venue_types:
                intersecting_venues.append(venue_type)
        if intersecting_venues:
            return intersecting_venues
Пример #8
0
 def __init__(
         self,
         locked_animation_args=DEFAULT,
         animation_callback=DEFAULT,
         interaction_asm_type=DEFAULT,
         override_animation_context=False,
         participant_enum_override=DEFAULT,
         description='There is an arbitrary number of possible animation selectors, based on participation in group.',
         **kwargs):
     if participant_enum_override is DEFAULT:
         participant_enum_type = ParticipantTypeAnimation
         participant_enum_default = ParticipantTypeAnimation.Invalid
     else:
         participant_enum_type = participant_enum_override[0]
         participant_enum_default = participant_enum_override[1]
     super().__init__(groups=TunableList(
         TunableTuple(
             group=TunableEnumFlags(
                 participant_enum_type,
                 participant_enum_default,
                 description='The group the Sim must be a participant of'),
             animation_ref=TunableAnimationReference(
                 allow_reactionlets=False,
                 override_animation_context=override_animation_context,
                 callback=animation_callback)),
         description='A list of difficulty to animation mappings.'),
                      description=description,
                      **kwargs)
Пример #9
0
class EmergencyFrequency(HasTunableSingletonFactory, AutoFactoryInit):
    FACTORY_TUNABLES = {
        'max_emergency_situations_per_shift':
        TunableRange(
            description=
            '\n            The maximum number of times during a shift that an emergency\n            situation can be created/started.\n            ',
            tunable_type=int,
            default=1,
            minimum=0),
        'inital_lockout_in_sim_minutes':
        TunableSimMinute(
            description=
            '\n            The time, in Sim minutes, that pass at the beginning of a shift\n            before the first check for creating/starting an emergency happens.\n            ',
            default=60),
        'cool_down_in_sim_minutes':
        TunableSimMinute(
            description=
            '\n            How often a check for whether or not to create/start an emergency\n            happens.\n            ',
            default=60),
        'percent_chance_of_emergency':
        TunablePercent(
            description=
            '\n            The percentage chance that on any given check an emergency is to\n            to be created/started.\n            ',
            default=30),
        'weighted_situations':
        TunableList(
            description=
            '\n            A weighted list of situations to be used as emergencies. When a\n            check passes to create/start an emergency, this is the list\n            of emergency situations that will be chosen from.\n            ',
            tunable=TunableTuple(situation=Situation.TunableReference(),
                                 weight=Tunable(tunable_type=int, default=1)))
    }
Пример #10
0
 def schedule_entry_data(pack_safe=False):
     return {
         'schedule_entries':
         TunableList(
             description=
             '\n                A list of event schedules. Each event is a mapping of days of the\n                week to a start_time and duration.\n                ',
             tunable=ScheduleEntry.TunableFactory(
                 schedule_entry_data={
                     'tuning_name':
                     'situation',
                     'tuning_type':
                     TunableTuple(
                         situation=TunableReference(
                             description=
                             '\n                                The situation to start according to the tuned schedule.\n                                ',
                             manager=services.get_instance_manager(
                                 sims4.resources.Types.
                                 SITUATION),
                             pack_safe=pack_safe),
                         tests=TunableTestSet(
                             description=
                             '\n                                A set of tests to run before attempting to start the\n                                scheduled situation. If any test fails, the situation\n                                will not start.\n                                '
                         ))
                 }))
     }
Пример #11
0
class OpenStreetDirectorCallToActionMixin:
    INSTANCE_TUNABLES = {'_call_to_actions': TunableList(description='\n            List of call to actions that should be started at the beginning\n            of this Open Street Director, and last until it ends (or until\n            a basic extra ends it "early").\n            ', tunable=TunableReference(manager=services.get_instance_manager(sims4.resources.Types.CALL_TO_ACTION)))}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._ended_cta_ids = []

    def on_startup(self):
        super().on_startup()
        call_to_action_service = services.call_to_action_service()
        for call_to_action_fact in self._call_to_actions:
            if call_to_action_fact.guid64 not in self._ended_cta_ids:
                call_to_action_service.begin(call_to_action_fact, self)

    def _clean_up(self):
        call_to_action_service = services.call_to_action_service()
        for call_to_action_fact in self._call_to_actions:
            call_to_action_service.end(call_to_action_fact)
        super()._clean_up()

    def on_cta_ended(self, value):
        self._ended_cta_ids.append(value)

    def _load_custom_open_street_director(self, street_director_proto, reader):
        super()._load_custom_open_street_director(street_director_proto, reader)
        if reader is not None:
            self._ended_cta_ids = list(reader.read_uint64s(OPENSTREETDIRECTOR_ENDED_CTA_TOKEN, ()))

    def _save_custom_open_street_director(self, street_director_proto, writer):
        super()._save_custom_open_street_director(street_director_proto, writer)
        if self._ended_cta_ids is not None:
            writer.write_uint64s(OPENSTREETDIRECTOR_ENDED_CTA_TOKEN, self._ended_cta_ids)
class _PickerDisplaySnippet(HasTunableSingletonFactory, AutoFactoryInit):
    FACTORY_TUNABLES = {
        'display_snippet':
        TunableReference(
            description=
            '\n            A display snippet that holds the display data that will\n            populate the row in the picker.\n            ',
            manager=services.get_instance_manager(
                sims4.resources.Types.SNIPPET),
            class_restrictions='DisplaySnippet',
            allow_none=False),
        'loot_on_selected':
        TunableList(
            description=
            '\n            A list of loot actions that will be applied to the subject Sim.\n            ',
            tunable=LootActions.TunableReference(
                description=
                '\n                A loot action applied to the subject Sim.\n                '
            )),
        'tests':
        TunableTestSetWithTooltip(
            description=
            '\n            Test set that must pass for this snippet to be available.\n            NOTE: A tooltip test result will take priority over any\n            instance display tooltip tuned in the display snippet.\n            \n            ID of the snippet will be the PickedItemID participant\n            '
        ),
        'display_snippet_text_tokens':
        LocalizationTokens.TunableFactory(
            description=
            '\n            Localization tokens passed into the display snippet text fields.\n            These will be appended to the list of tokens when evaluating \n            strings for this snippet. \n            ',
            tuning_group=GroupNames.PICKERTUNING)
    }

    def test(self, resolver):
        return self.tests.run_tests(resolver, search_for_tooltip=True)
Пример #13
0
class TutorialTipGroup(
        metaclass=sims4.tuning.instances.HashedTunedInstanceMetaclass,
        manager=services.get_instance_manager(
            sims4.resources.Types.TUTORIAL_TIP)):
    __qualname__ = 'TutorialTipGroup'
    INSTANCE_TUNABLES = {
        'tips':
        TunableList(
            description=
            '\n            The tips that are associated with this tip group.\n            ',
            tunable=TunableReference(manager=services.get_instance_manager(
                sims4.resources.Types.TUTORIAL_TIP),
                                     class_restrictions='TutorialTip',
                                     export_modes=ExportModes.ClientBinary)),
        'group_requirement':
        TunableEnumEntry(
            description=
            '\n            The requirement for completing this tip group. ANY means any of the\n            tips in this group need to be completed for the group to be\n            considered complete. ALL means all of the tips in this group need\n            to be completed for the group to be considered complete.\n            ',
            tunable_type=TutorialTipGroupRequirementType,
            default=TutorialTipGroupRequirementType.ALL,
            export_modes=ExportModes.ClientBinary)
    }

    def __init__(self):
        raise NotImplementedError
Пример #14
0
class PlayMultipleEffects(HasTunableFactory):
    __qualname__ = 'PlayMultipleEffects'
    FACTORY_TUNABLES = {
        'description':
        '\n            Play multiple visual effects.\n            ',
        'vfx_list':
        TunableList(
            description='\n            A list of effects to play\n            ',
            tunable=PlayEffect.TunableFactory(
                description=
                '\n                A single effect to play.\n                ')
        )
    }

    def __init__(self, owner, *args, vfx_list=None, **kwargs):
        self.vfx_list = []
        for vfx_factory in vfx_list:
            self.vfx_list.append(vfx_factory(owner))

    def start(self, *args, **kwargs):
        for play_effect in self.vfx_list:
            play_effect.start(*args, **kwargs)

    def stop(self, *args, **kwargs):
        for play_effect in self.vfx_list:
            play_effect.stop(*args, **kwargs)
class TimeOfDayComponent(Component,
                         HasTunableFactory,
                         component_name=types.TIME_OF_DAY_COMPONENT):
    __qualname__ = 'TimeOfDayComponent'
    DAILY_REPEAT = date_and_time.create_time_span(hours=24)
    FACTORY_TUNABLES = {
        'state_changes':
        TunableMapping(
            description=
            '\n            A mapping from state to times of the day when the state should be \n            set to a tuned value.\n            ',
            key_type=TunableStateTypeReference(
                description='The state to be set.'),
            value_type=TunableList(
                description='List of times to modify the state at.',
                tunable=TunableTuple(start_time=TunableRange(
                    float,
                    0,
                    description=
                    'The start time (24 hour clock time) for the Day_Time state.',
                    minimum=0,
                    maximum=24),
                                     value=TunableStateValueReference(
                                         description='New state value.'))))
    }

    def __init__(self, owner, *, state_changes):
        super().__init__(owner)
        self.state_changes = state_changes
        self.alarm_handles = []

    def _add_alarm(self, cur_state, game_clock, state, change):
        time_to_day = game_clock.time_until_hour_of_day(change.start_time)

        def change_state(_):
            self.owner.set_state(state, change.value)

        self.alarm_handles.append(
            alarms.add_alarm(self.owner,
                             time_to_day,
                             change_state,
                             repeating=True,
                             repeating_time_span=self.DAILY_REPEAT))
        if cur_state is None or time_to_day > cur_state[0]:
            return (time_to_day, change.value)
        return cur_state

    def on_add(self):
        game_clock_service = services.game_clock_service()
        for (state, changes) in self.state_changes.items():
            current_state = None
            for change in changes:
                current_state = self._add_alarm(current_state,
                                                game_clock_service, state,
                                                change)
            while current_state is not None:
                self.owner.set_state(state, current_state[1])

    def on_remove(self):
        for handle in self.alarm_handles:
            alarms.cancel_alarm(handle)
Пример #16
0
class ItemCost(ItemCostBase, AutoFactoryInit, HasTunableSingletonFactory):
    UNAVAILABLE_TOOLTIP_HEADER = TunableLocalizedStringFactory(
        description=
        '\n        A string to be used as a header for a bulleted list of items that the\n        Sim is missing in order to run this interaction.\n        '
    )
    AVAILABLE_TOOLTIP_HEADER = TunableLocalizedStringFactory(
        description=
        '\n        A string to be used as a header for a bulleted list of items that the\n        Sim will consume in order to run this interaction.\n        '
    )
    FACTORY_TUNABLES = {
        'ingredients':
        TunableList(
            description=
            '\n            List of tuples of Objects and Quantity, which will indicate\n            the cost of items for this interaction to run\n            ',
            tunable=TunableTuple(
                description=
                '\n                Pair of Object and Quantity needed for this interaction\n                ',
                ingredient=TunableReference(
                    description=
                    '\n                    Object reference of the type of game object needed.\n                    ',
                    manager=services.definition_manager()),
                quantity=TunableRange(
                    description=
                    '\n                    Quantity of objects needed\n                    ',
                    tunable_type=int,
                    default=1,
                    minimum=1),
                missing_ingredient_additional_text=OptionalTunable(
                    description=
                    '\n                    If set, this text is inserted on a new line following a missing ingredient.\n                    ',
                    tunable=TunableLocalizedString(
                        default=None,
                        description='The string key of the text description'
                    ))))
    }
Пример #17
0
class DecorativeSlotTuning:
    __qualname__ = 'DecorativeSlotTuning'
    DECORATIVE_SLOT_TYPES = TunableList(TunableReference(services.get_instance_manager(sims4.resources.Types.SLOT_TYPE)), description='The list of gameplay-only slot types. There must be an entry for each possible decorative slot size.')
    _NO_SLOTS = EMPTY_SET

    @classmethod
    def get_slot_types_for_object(cls, deco_size):
        if deco_size == 0:
            return cls._NO_SLOTS
        deco_size -= 1
        return frozenset(cls.DECORATIVE_SLOT_TYPES[deco_size:])

    @classmethod
    def get_slot_types_for_slot(cls, deco_size):
        if deco_size == 0:
            return cls._NO_SLOTS
        deco_size -= 1
        return frozenset(cls.DECORATIVE_SLOT_TYPES[:deco_size + 1])

    @classmethod
    def slot_types_are_all_decorative(cls, slot_types):
        if not slot_types:
            return False
        if not slot_types.issubset(cls.DECORATIVE_SLOT_TYPES):
            return False
        return True
Пример #18
0
class TunablePutDownStrategy(
        HasTunableFactory,
        metaclass=TunedInstanceMetaclass,
        manager=services.get_instance_manager(sims4.resources.Types.STRATEGY)):
    __qualname__ = 'TunablePutDownStrategy'
    INSTANCE_TUNABLES = {
        'preferred_slot_cost': OptionalTunable(
            enabled_by_default=True,
            tunable=
            Tunable(description=
                    '\n                    Base cost for a slot that this object prefers.\n                    ',
                    tunable_type=float,
                    default=0)),
        'normal_slot_cost': OptionalTunable(
            enabled_by_default=True,
            tunable=Tunable(
                description=
                '\n                    Base score for a slot that this object does not prefer.\n                    ',
                tunable_type=float,
                default=1)),
        'object_inventory_cost': OptionalTunable(
            enabled_by_default=True,
            tunable=Tunable(
                description=
                '\n                    Base cost for a sim putting the object in a valid object\n                    inventory.\n                    ',
                tunable_type=float,
                default=5)),
        'floor_cost': OptionalTunable(
            enabled_by_default=True,
            tunable=Tunable(
                description=
                '\n                    The base cost used to compare putting an object on the ground\n                    with other options.\n                    ',
                tunable_type=float,
                default=15)),
        'inventory_cost': OptionalTunable(
            enabled_by_default=True,
            tunable=Tunable(
                description=
                '\n                    Cost for how likely a sim puts the object in their inventory\n                    instead of putting it down.\n                    ',
                tunable_type=float,
                default=20)),
        'affordances': TunableList(
            description=
            '\n                A list of interactions that should be considered to be an\n                alternative to putting the object down.\n                ',
            tunable=TunableReference(services.get_instance_manager(
                sims4.resources.Types.INTERACTION))),
        'put_down_on_terrain_facing_sim': Tunable(
            description=
            "\n                If true, the object will face the Sim when placing it on\n                terrain.  Guitars and violins will enable this so they don't\n                pop 180 degrees after the Sim puts it down. \n                ",
            tunable_type=bool,
            default=False),
        'ideal_slot_type_set': OptionalTunable(TunableReference(
            description=
            "\n                 If specified, this set of slots will have the cost specified\n                 in the 'preferred_slot_cost' field in put_down_tuning.\n                 \n                 This allows us to tell Sims to weight specific slot types\n                 higher than others when considering where to put down this\n                 object.\n                 ",
            manager=services.get_instance_manager(
                sims4.resources.Types.SLOT_TYPE_SET)))
    }
    FACTORY_TUNABLES = {}
    FACTORY_TUNABLES.update(INSTANCE_TUNABLES)
class ObjectRoutingBehaviorActionDestroyObjects(ObjectRoutingBehaviorAction):
    FACTORY_TUNABLES = {
        'animation_success':
        OptionalTunable(
            description=
            '\n            If enabled, the animation to play if there are objects to destroy.\n            ',
            tunable=_ObjectRoutingActionAnimation.TunableFactory()),
        'animation_failure':
        OptionalTunable(
            description=
            '\n            If enabled, the animation to play if there are no objects to destroy.\n            ',
            tunable=_ObjectRoutingActionAnimation.TunableFactory()),
        'loot_success':
        TunableList(
            description=
            '\n            For each destroyed object, apply this loot between the routing\n            object (Actor) and the destroyed object (Object).\n            ',
            tunable=LootActions.TunableReference()),
        'object_selection_method':
        TunableVariant(tags=_DestroyObjectSelectionRuleTags.TunableFactory(),
                       target_object=_DestroyObjectSelectionRuleTargetObject.
                       TunableFactory(),
                       default='tags')
    }

    def run_action_gen(self, timeline, obj, target):
        objects = self.object_selection_method.get_objects(obj, target)
        if not objects:
            if self.animation_failure is not None:
                result = yield from self.animation_failure(
                    timeline, obj, target)
                return result
                yield
            return True
            yield

        def _callback(_):
            for o in objects:
                resolver = DoubleObjectResolver(obj, o)
                for loot_action in self.loot_success:
                    loot_action.apply_to_resolver(resolver)
                o.remove_from_client(fade_duration=obj.FADE_DURATION)
                o.destroy(
                    source=self,
                    cause=
                    'Object being destroyed by ObjectRoutingBehaviorActionDestroyObjects'
                )

        if self.animation_success is not None:
            result = yield from self.animation_success(timeline,
                                                       obj,
                                                       target,
                                                       callback=_callback)
            if not result:
                return result
                yield
        else:
            _callback(timeline)
        return True
        yield
Пример #20
0
class BroadcasterEffectSelfLoot(_BroadcasterEffectTested):
    FACTORY_TUNABLES = {
        'broadcastee_count_interval':
        TunableInterval(
            description=
            '\n            If the number of objects within this broadcaster is in this\n            interval, loot will be awarded. Includes lower and upper.\n            ',
            tunable_type=int,
            default_lower=1,
            default_upper=2,
            minimum=0),
        'loot_list':
        TunableList(description=
                    '\n            A list of loot operations.\n            ',
                    tunable=TunableReference(
                        manager=services.get_instance_manager(
                            sims4.resources.Types.ACTION),
                        class_restrictions=('LootActions', ),
                        pack_safe=True)),
        'apply_loot_on_remove':
        Tunable(
            description=
            "\n            If enabled, determine whether or not we want to apply this broadcaster's\n            loot when the broadcaster is removed.\n            True means we will apply the loot on removal of the broadcaster\n            False means we will apply the loot as soon as enough sims enter the constraint\n            ",
            tunable_type=bool,
            default=True)
    }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._observing_objs = set()

    @classproperty
    def apply_when_linked(cls):
        return True

    @classproperty
    def apply_when_removed(cls):
        return True

    def _count_is_within_interval(self, broadcaster):
        object_count = len(self._observing_objs)
        return object_count in self.broadcastee_count_interval

    def apply_broadcaster_loot(self, broadcaster):
        if self.apply_loot_on_remove:
            self._try_apply_loot(broadcaster)
        self._observing_objs = set()

    def _apply_broadcaster_effect(self, broadcaster, affected_object):
        if self._should_apply_broadcaster_effect(broadcaster, affected_object):
            self._observing_objs.add(affected_object.id)
        if not self.apply_loot_on_remove:
            self._try_apply_loot(broadcaster)

    def _try_apply_loot(self, broadcaster):
        if self._count_is_within_interval(broadcaster):
            resolver = broadcaster.get_resolver(
                broadcaster.broadcasting_object)
            for loot_action in self.loot_list:
                loot_action.apply_to_resolver(resolver)
Пример #21
0
class PlayEffectState(HasTunableFactory, AutoFactoryInit, NeedsStateValue):
    FACTORY_TUNABLES = {
        'state_index':
        TunableRange(
            description=
            '\n            The index of the state to apply to the VFX activated by the state\n            that is also activating this state change. This is defined in the\n            Swarm file.\n            ',
            tunable_type=int,
            minimum=0,
            default=0),
        'state_owning_vfx':
        OptionalTunable(
            description=
            '\n            Specify which client states the VFX that we care about are owned by.\n            ',
            tunable=TunableList(
                description=
                '\n                Specify specific state(s) that own VFX.\n                ',
                tunable=TunableReference(
                    description=
                    '\n                    The client state(s) owning the VFX we want to modify.\n                    ',
                    manager=services.get_instance_manager(
                        sims4.resources.Types.OBJECT_STATE),
                    class_restrictions='ObjectState',
                    pack_safe=True)),
            enabled_name='Use_Specific_State',
            disabled_name='Use_Current_State')
    }

    def __init__(self, target, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._target = target
        self._pending_primitives = None

    def start(self):
        states_owning_vfx = (
            self.state_value.state,
        ) if self.state_owning_vfx is None else self.state_owning_vfx
        client_connected = bool(services.client_manager())
        for state_owning_vfx in states_owning_vfx:
            vfx_distributable = self.distributable_manager.get_distributable(
                'vfx_state', state_owning_vfx)
            if vfx_distributable is not None:
                target = vfx_distributable.target
                vfx_state_op = SetEffectState(
                    target.id,
                    vfx_distributable.actor_id,
                    self.state_index,
                    write_callback=self.write_callback)
                vfx_state_op.attach(target)
                if not client_connected:
                    if self._pending_primitives is None:
                        self._pending_primitives = []
                    self._pending_primitives.append(vfx_state_op)

    def stop(self, **kwargs):
        pass

    def write_callback(self, primitive):
        if self._pending_primitives:
            self._pending_primitives.remove(primitive)
class LoadLayerFestivalState(BaseFestivalState):
    FACTORY_TUNABLES = {
        '_conditional_layers':
        TunableList(
            description=
            '\n            A list of layers to be loaded.  Each one will load one after\n            another.\n            ',
            tunable=TunableReference(
                description=
                '\n                The Conditional Layer that will be loaded.\n                ',
                manager=services.get_instance_manager(
                    sims4.resources.Types.CONDITIONAL_LAYER)),
            unique_entries=True)
    }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._layers_to_load = []

    def _get_next_state(self):
        raise NotImplementedError

    def _load_layers(self):
        self._layers_to_load = list(self._conditional_layers)
        for conditional_layer in tuple(self._layers_to_load):
            if services.current_zone().is_zone_running:
                self._owner.load_layer_gradually(conditional_layer)
            else:
                self._owner.load_layer_immediately(conditional_layer)

    def on_layer_loaded(self, conditional_layer):
        if self._owner._prerolling:
            return
        self._layers_to_load.remove(conditional_layer)
        if self._layers_to_load:
            return
        self._preroll_end_of_state()

    def on_state_activated(self, reader=None, preroll_time_override=None):
        super().on_state_activated(reader=reader,
                                   preroll_time_override=preroll_time_override)
        if len(self._conditional_layers) == 0:
            self._preroll_end_of_state()
            return
        self._load_layers()

    def _run_preroll(self):
        for conditional_layer in self._conditional_layers:
            self._owner.load_layer_immediately(conditional_layer)
        super()._run_preroll()

    def _get_fake_preroll_time(self):
        return TimeSpan.ZERO

    def _preroll_end_of_state(self):
        next_state = self._get_next_state()
        if next_state is not None:
            self._owner.change_state(next_state)
        else:
            self._owner.self_destruct()
Пример #23
0
class TelemetryTuning:
    BUFF_ALARM_TIME = TunableRange(
        description=
        "\n        Integer value in sim minutes in which the buff alarm will trigger to \n        send a telemetry report of current active buff's on the household sims.\n        ",
        tunable_type=int,
        minimum=1,
        default=60)
    EMOTION_REL_ALARM_TIME = TunableRange(
        description=
        '\n        Integer value in sim minutes in which the emotion and relationship \n        alarm will trigger to send a telemetry report of the emotion and \n        relationship status of the household sims.\n        ',
        tunable_type=int,
        minimum=1,
        default=60)
    HOOK_ACTIONS = TunableList(
        description=
        '\n        List of hook actions that we want to drop or collect to create rules \n        to disable them from triggering.\n        ',
        tunable=TunableTuple(
            description='\n            Hook actions.\n            ',
            module_tag=Tunable(
                description=
                "\n                Module identifier of the hook where the action should be \n                applied.\n                Can be empty if we want to apply an action by only group or \n                hook tag. \n                e.g. 'GAME'.  \n                ",
                tunable_type=str,
                default=''),
            group_tag=Tunable(
                description=
                "\n                Group identifier of the hook where the action should be \n                applied.\n                Can be empty if we want to apply an action by only module or \n                hook tag.\n                e.g. 'WHIM'\n                ",
                tunable_type=str,
                default=''),
            hook_tag=Tunable(
                description=
                "\n                Tag identifier of the hook where the action should be \n                applied.\n                Can be empty if we want to apply an action by only module or \n                group tag.\n                e.g. 'WADD'\n                ",
                tunable_type=str,
                default=''),
            priority=Tunable(
                description=
                "\n                Priority for this rule to apply.  The rules are sorted in \n                priority order (lowest priority first).  The the first rule \n                that matches a hook causes the hook to be blocked or collected, \n                depending on the value of action. \n                e.g. We can have an action to COLLECT hook {GAME, WHIM, WADD} \n                with priority 0, and an action to DROP hooks with module 'GAME'\n                {GAME, '', ''} with priority 1, this means the collected hook\n                action will have more importance than the rule to drop all \n                GAME hooks.                \n                ",
                tunable_type=int,
                default=0),
            action=TunableEnumEntry(
                description=
                '\n                Action to take for the specified tags. \n                COLLECT to enable the hook.\n                DROP to disable the hook.\n                ',
                tunable_type=RuleAction,
                default=RuleAction.DROP)))

    @classmethod
    def filter_tunable_hooks(cls):
        for hook in TelemetryTuning.HOOK_ACTIONS:
            module_tag = hook.module_tag
            group_tag = hook.group_tag
            hook_tag = hook.hook_tag
            if module_tag == '':
                module_tag = None
            if group_tag == '':
                group_tag = None
            if hook_tag == '':
                hook_tag = None
            sims4.telemetry.add_filter_rule(hook.priority, module_tag,
                                            group_tag, hook_tag, None,
                                            hook.action)
class NeighborhoodPopulationService(Service):
    __qualname__ = 'NeighborhoodPopulationService'
    REGION_TO_HOUSEHOLD_POPULATION_DATA = TunableMapping(description='\n        Mapping of Region Description ID to household population data.  This is\n        used to fill households for the different type of regions.\n        ', key_name='Region Description', key_type=TunableRegionDescription(), value_name='Household Population Data', value_type=HouseholdPopulationData.TunableFactory())
    HOMELESS_HOUSEHOLD_TEMPLATES = TunableList(description='\n        A List of household templates that will be considered for homelesss\n        households.\n        ', tunable=TunableHouseholdTemplateWeightTuple())
    NUM_BEDS_TO_IDEAL_HOUSEHOLD_CURVE = TunableMapping(description='\n        Based on the number of beds and the number of sims in the household, a\n        multiplier will be applied to the household to determine if household\n        will be selected and added to zone.\n        ', key_name='Num Beds', key_type=Tunable(tunable_type=int, default=1), value_name='Ideal Household Curve', value_type=TunableCurve(x_axis_name='num_sim_in_household', y_axis_name='bonus_multiplier'))
    KID_TO_KID_BED_MULTIPLIER = TunableRange(description='\n        When trying to populate a lot if lot has a kids bed and household has a\n        kid in it.  This multiplier will be applied to the weight of household\n        when selecting household to move in.\n        ', tunable_type=float, default=1, minimum=1)
    SIGNIFICANT_OTHER_MULTIPLIER = TunableRange(description='\n        When trying to populate a lot and if lot has a double bed and household\n        contains a pair of sims that are considered significant other.  This\n        multiplier will be applied to the weight of household when selecting\n        household to move in.\n        ', tunable_type=float, default=1, minimum=1)

    def __init__(self):
        self._requests = []
        self._processing_element_handle = None

    def _process_population_request_gen(self, timeline):
        while self._requests:
            request = self._requests.pop(0)
            try:
                yield request.process_request_gen(timeline)
                request.process_completed(True)
            except GeneratorExit:
                raise
            except BaseException:
                request.process_completed(False)
                logger.exception('Exception raised while processing creating npc households')
            while self._requests:
                yield element_utils.run_child(timeline, element_utils.sleep_until_next_tick_element())
                continue
        self._processing_element_handle = None

    def add_population_request(self, num_to_fill, neighborhood_id, completion_callback, available_zone_ids, try_existing_households):
        account = self._get_account()
        if account is None:
            return False
        request = _FillZonePopulationRequest(account, num_to_fill, neighborhood_id, completion_callback, available_zone_ids=available_zone_ids, try_existing_households=try_existing_households)
        self._add_request(request)
        return True

    def add_homeless_household_request(self, num_to_fill, completion_callback):
        account = self._get_account()
        if account is None:
            return False
        request = _CreateHomelessHouseholdRequest(account, num_to_fill, None, completion_callback)
        self._add_request(request)
        return True

    def _get_account(self):
        client = services.client_manager().get_first_client()
        if client.account is not None or client.household is not None:
            return client.account

    @property
    def is_processing_requests(self):
        return self._processing_element_handle or len(self._requests) > 0

    def _add_request(self, request):
        self._requests.append(request)
        if self._processing_element_handle is None:
            timeline = services.time_service().sim_timeline
            element = elements.GeneratorElement(self._process_population_request_gen)
            self._processing_element_handle = timeline.schedule(element)
Пример #25
0
class _PortalTypeDataBase(HasTunableSingletonFactory, AutoFactoryInit):
    FACTORY_TUNABLES = {'portal_events': TunableList(description='\n            A list of portal events to add when a Sim uses the portal.\n            ', tunable=TunablePortalEventVariant(description='\n                The tuning for a specific portal event.\n                '))}

    @property
    def portal_type(self):
        raise NotImplementedError

    @property
    def outfit_change(self):
        pass

    @property
    def requires_los_between_points(self):
        return True

    @property
    def lock_portal_on_use(self):
        return True

    def get_additional_required_portal_flags(self, entry_location, exit_location):
        return 0

    def notify_in_use(self, user, portal_instance, portal_object):
        pass

    def add_portal_data(self, actor, portal_instance, is_mirrored, walkstyle):
        pass

    def add_portal_events(self, portal, actor, obj, time, route_pb):
        for portal_event in self.portal_events:
            op = portal_event.get_portal_op(actor, obj)
            event = route_pb.events.add()
            event.time = max(0, time + portal_event.time)
            event.type = portal_event.get_portal_event_type()
            event.data = op.SerializeToString()

    def get_portal_asm_params(self, portal_instance, portal_id, sim):
        return {}

    def get_destination_objects(self):
        return ()

    def get_portal_duration(self, portal_instance, is_mirrored, walkstyle, age, gender, species):
        raise NotImplementedError

    def get_portal_locations(self, obj):
        raise NotImplementedError

    def get_posture_change(self, portal_instance, is_mirrored, initial_posture):
        return (initial_posture, initial_posture)

    def is_ungreeted_sim_disallowed(self):
        return False

    def split_path_on_portal(self):
        return PathSplitType.PathSplitType_DontSplit

    def provide_route_events(self, *args, **kwargs):
        pass
Пример #26
0
class CSFCustomSliderInfoCollection(metaclass=HashedTunedInstanceMetaclass,
                                    manager=services.get_instance_manager(
                                        Types.SNIPPET)):
    """ Holds information related to a collection of custom sliders. """
    INSTANCE_TUNABLES = {
        'custom_slider_info_list':
        TunableList(tunable=CSFCustomSliderInfo.TunableFactory())
    }
class BroadcasterEffectLoot(_BroadcasterEffectTested):
    __qualname__ = 'BroadcasterEffectLoot'
    FACTORY_TUNABLES = {'loot_list': TunableList(description='\n            A list of loot operations.\n            ', tunable=TunableReference(manager=services.get_instance_manager(sims4.resources.Types.ACTION), class_restrictions=('LootActions',)))}

    def _apply_broadcaster_effect(self, broadcaster, affected_object):
        resolver = broadcaster.get_resolver(affected_object)
        for loot_action in self.loot_list:
            loot_action.apply_to_resolver(resolver)
Пример #28
0
class Party:
    RALLY_FALSE_ADS = TunableList(
        description=
        ' \n        A list of false advertisement for rallyable interactions. Use this\n        tunable to entice Sims to autonomously choose rallyable over non-\n        rallyable interactions.\n        ',
        tunable=TunableStatisticChange(locked_args={
            'subject': ParticipantType.Actor,
            'advertise': True
        }))
Пример #29
0
class MobilePosture(Posture):
    INSTANCE_TUNABLES = {
        'compatible_walkstyles':
        TunableList(
            description=
            '\n            The exhaustive list of walkstyles allowed while Sims are in this\n            mobile posture. If a Sim has a request for a walkstyle that is not\n            supported, the first element is used as a replacement.\n            ',
            tunable=TunableWalkstyle(pack_safe=True),
            unique_entries=False),
        'posture_objects':
        OptionalTunable(
            description=
            '\n            If enabled, we will use this tuning to find objects related to this\n            posture if it is unconstrained. This allows unconstrained mobile\n            postures to reset back into the object they were contained in.\n            ',
            tunable=ObjectDefinitonsOrTagsVariant(
                description=
                '\n                The filter we use to check objects that this posture cares about.\n                '
            )),
        '_skip_route':
        Tunable(
            description=
            '\n            If checked, this mobile posture does not use a route to transition \n            to and from another posture. WARNING: Please consult a GPE before\n            checking this.\n            ',
            tunable_type=bool,
            default=False)
    }
    _posture_at_none_posture_state_spec = None
    _posture_at_none_constraint = None

    @constproperty
    def mobile():
        return True

    @classproperty
    def is_vehicle(cls):
        return not cls.unconstrained

    @classproperty
    def skip_route(cls):
        return cls._skip_route

    @classmethod
    def is_object_related(cls, test_object):
        if cls.posture_objects is not None:
            return cls.posture_objects.matches(test_object)
        return False

    @classmethod
    def get_mobile_at_none_constraint(cls):
        if cls._posture_at_none_constraint is None:
            cls._cache_mobile_posture_constraint()
        return cls._posture_at_none_constraint

    @classmethod
    def _cache_mobile_posture_constraint(cls):
        if cls._posture_at_none_constraint is None:
            cls._posture_at_none_posture_state_spec = create_body_posture_state_spec(
                cls.get_provided_postures(), body_target=None)
            cls._posture_at_none_constraint = Constraint(
                debug_name='{}@None'.format(cls.name),
                posture_state_spec=cls._posture_at_none_posture_state_spec)
class RandomDisplayName(HasTunableSingletonFactory, AutoFactoryInit):
    __qualname__ = 'RandomDisplayName'
    FACTORY_TUNABLES = {
        'overrides':
        TunableList(
            description=
            '\n            A list of random strings and icons to select randomly.\n            ',
            tunable=TunableTuple(
                new_display_name=TunableLocalizedStringFactory(),
                new_pie_menu_icon=TunableResourceKey(
                    default=None,
                    resource_types=sims4.resources.CompoundTypes.IMAGE),
                new_display_tooltip=OptionalTunable(
                    description=
                    '\n                    Tooltip to show on this pie menu option.\n                    ',
                    tunable=sims4.localization.TunableLocalizedStringFactory(
                    )),
                locked_args={'new_pie_menu_category': None})),
        'timeout':
        TunableSimMinute(
            description=
            '\n            The time it will take for a new string to be generated given the\n            same set of data.\n            ',
            minimum=0,
            default=10)
    }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._key_map = {}

    def get_display_names_gen(self):
        for override in self.overrides:
            yield override.new_display_name

    def get_display_name_and_result(self,
                                    interaction,
                                    target=DEFAULT,
                                    context=DEFAULT):
        context = interaction.context if context is DEFAULT else context
        target = interaction.target if target is DEFAULT else target
        key = (context.sim.id, 0 if target is None else target.id,
               interaction.affordance)
        random_names = getattr(context, 'random_names', dict())
        result = random_names.get(key)
        if result is not None:
            return (result, TestResult.NONE)
        now = services.time_service().sim_now
        result_and_timestamp = self._key_map.get(key)
        if result_and_timestamp is not None:
            time_delta = now - result_and_timestamp[1]
            if self.timeout > time_delta.in_minutes():
                self._key_map[key] = (result_and_timestamp[0], now)
                return (result_and_timestamp[0], TestResult.NONE)
        result = random.choice(self.overrides)
        random_names[key] = result
        setattr(context, 'random_names', random_names)
        self._key_map[key] = (result, now)
        return (result, TestResult.NONE)