Exemplo n.º 1
0
 def __init__(self,
              target_default=ParticipantType.Object,
              locked_args={},
              carry_target_default=ParticipantType.Object,
              **kwargs):
     super().__init__(
         TunableTuple(
             affordance=TunableReference(
                 services.affordance_manager(),
                 description=
                 'The affordance to push as a continuation on the actor for this SI.'
             ),
             si_affordance_override=TunableReference(
                 services.affordance_manager(),
                 description=
                 "When the tuned affordance is a mixer for a different SI, use this to specify the mixer's appropriate SI. This is useful for pushing socials."
             ),
             actor=TunableEnumEntry(
                 ParticipantType,
                 ParticipantType.Actor,
                 description='The Sim on which the affordance is pushed.'),
             target=TunableEnumEntry(
                 ParticipantType,
                 target_default,
                 description='The participant the affordance will target.'),
             carry_target=OptionalTunable(
                 TunableEnumEntry(
                     ParticipantType,
                     carry_target_default,
                     description=
                     'The participant the affordance will set as a carry target.'
                 )),
             locked_args=locked_args), **kwargs)
Exemplo n.º 2
0
class TravelTuning:
    ENTER_LOT_AFFORDANCE = TunableReference(services.affordance_manager(), description='SI to push when sim enters the lot.')
    EXIT_LOT_AFFORDANCE = TunableReference(services.affordance_manager(), description='SI to push when sim is exiting the lot.')
    NPC_WAIT_TIME = TunableSimMinute(15, description='Delay in sim minutes before pushing the ENTER_LOT_AFFORDANCE on a NPC at the spawn point if they have not moved.')
    TRAVEL_AVAILABILITY_SIM_FILTER = TunableSimFilter.TunableReference(description='Sim Filter to show what Sims the player can travel with to send to Game Entry.')
    TRAVEL_SUCCESS_AUDIO_STING = TunablePlayAudio(description='\n        The sound to play when we finish loading in after the player has traveled.\n        ')
    NEW_GAME_AUDIO_STING = TunablePlayAudio(description='\n        The sound to play when we finish loading in from a new game, resume, or\n        household move in.\n        ')
    GO_HOME_INTERACTION = TunableReference(description='\n        The interaction to push a Sim to go home.\n        ', manager=services.get_instance_manager(sims4.resources.Types.INTERACTION))
Exemplo n.º 3
0
class TeleportLiability(Liability, HasTunableFactory, AutoFactoryInit):
    __qualname__ = 'TeleportLiability'
    LIABILITY_TOKEN = 'TeleportLiability'
    FACTORY_TUNABLES = {
        'on_success_affordance':
        TunableReference(
            description=
            '\n            If specified, the affordance to push if the teleportation was\n            successful.\n            ',
            manager=services.affordance_manager()),
        'on_failure_affordance':
        TunableReference(
            description=
            '\n            If specified, the affordance to push if the teleportation failed or\n            if on_success_affordance is specified and failed to execute.\n            ',
            manager=services.affordance_manager())
    }

    def __init__(self, interaction, **kwargs):
        super().__init__(**kwargs)
        self._interaction = interaction
        self._interaction.route_fail_on_transition_fail = False
        self._constraint = self._interaction.constraint_intersection()

    @classmethod
    def on_affordance_loaded_callback(cls, affordance, liability_tuning):
        affordance.disable_distance_estimation_and_posture_checks = True

    def release(self):
        if self._teleport() and self.on_success_affordance is not None:
            if self._interaction.sim.push_super_affordance(
                    self.on_success_affordance, self._interaction.target,
                    self._interaction.context):
                return
        if self._interaction.transition_failed and self.on_failure_affordance is not None:
            self._interaction.sim.push_super_affordance(
                self.on_failure_affordance, self._interaction.target,
                self._interaction.context)

    def _teleport(self):
        polygon = None if self._constraint.geometry is None else self._constraint.geometry.polygon
        if isinstance(polygon, CompoundPolygon):
            scoring_functions = [ScoringFunctionPolygon(cp) for cp in polygon]
        else:
            scoring_functions = (ScoringFunctionPolygon(polygon), )
        search_flags = FGLSearchFlagsDefault | FGLSearchFlag.USE_SIM_FOOTPRINT
        routing_surface = self._constraint.routing_surface
        fgl_context = FindGoodLocationContext(
            starting_position=self._constraint.average_position,
            scoring_functions=scoring_functions,
            starting_routing_surface=routing_surface,
            search_flags=search_flags)
        (translation, orientation) = find_good_location(fgl_context)
        if polygon and translation is not None and orientation is not None:
            self._interaction.sim.move_to(translation=translation,
                                          orientation=orientation,
                                          routing_surface=routing_surface)
            return True
        return False
Exemplo n.º 4
0
class PickUpObjectSuperInteraction(SuperInteraction):
    INSTANCE_TUNABLES = {
        'basic_content':
        TunableBasicContentSet(one_shot=True,
                               no_content=True,
                               default='no_content'),
        'si_to_push':
        TunableReference(services.affordance_manager(),
                         allow_none=True,
                         description='SI to push after picking up the object.')
    }

    @classmethod
    def _constraint_gen(cls, *args, **kwargs):
        yield Constraint(debug_name='PickUpObjectSuperInteraction({})'.format(
            cls.si_to_push),
                         posture_state_spec=CARRY_TARGET_POSTURE_STATE_SPEC)

    @classmethod
    def _test(cls, target, context, **kwargs):
        from sims.sim import Sim
        if isinstance(target.parent, Sim):
            return TestResult(False,
                              'Cannot pick up an object parented to a Sim.')
        if context.source == context.SOURCE_AUTONOMY and context.sim.posture_state.get_carry_track(
                target.definition.id) is not None:
            return TestResult(
                False,
                'Sims should not autonomously pick up more than one object.')
        return TestResult.TRUE
class InteractionOfInterest(AutoFactoryInit):
    __qualname__ = 'InteractionOfInterest'
    FACTORY_TUNABLES = {
        'affordances':
        TunableList(
            TunableReference(services.affordance_manager()),
            description=
            "The Sim must have started either any affordance in this list or an interaction matching one of the tags in this tunable's Tags field."
        ),
        'tags':
        TunableSet(
            TunableEnumEntry(Tag, Tag.INVALID),
            description=
            'The Sim must have run either an interaction matching one of these Tags or an affordance from the list of Affordances in this tunable.'
        )
    }

    def get_expected_args(self):
        return {'interaction': event_testing.test_events.FROM_EVENT_DATA}

    def __call__(self, interaction=None):
        if interaction is not None and self.tags & interaction.get_category_tags(
        ):
            tag_match = True
        else:
            tag_match = False
        if not tag_match and interaction.affordance not in self.affordances:
            return TestResult(False, 'Failed affordance check: {} not in {}',
                              interaction.affordance, self.affordances)
        return TestResult.TRUE
Exemplo n.º 6
0
class VoodooSummonSituation(situations.situation_complex.SituationComplexCommon
                            ):
    __qualname__ = 'VoodooSummonSituation'
    INSTANCE_TUNABLES = {
        'summoned_job':
        sims4.tuning.tunable.TunableTuple(
            situation_job=SituationJob.TunableReference(
                description=
                '\n                          A reference to the SituationJob used for the Sim summoned.\n                          '
            ),
            come_to_me_state=RoleState.TunableReference(
                description=
                '\n                          The state for telling the summoned sim to come here.\n                          '
            )),
        'come_here_affordance':
        sims4.tuning.tunable.TunableReference(
            services.affordance_manager(),
            description='SI to bring summoned sim to the summoner.')
    }
    REMOVE_INSTANCE_TUNABLES = (
        '_buff', '_cost', '_NPC_host_filter', '_NPC_hosted_player_tests',
        'NPC_hosted_situation_start_message',
        'NPC_hosted_situation_use_player_sim_as_filter_requester',
        'NPC_hosted_situation_player_job', 'venue_types',
        'venue_invitation_message', 'venue_situation_player_job', 'category',
        'main_goal', 'minor_goal_chains', 'max_participants',
        '_initiating_sim_tests', '_icon', 'targeted_situation',
        '_resident_job', 'situation_description', 'job_display_ordering',
        'entitlement', '_jobs_to_put_in_party',
        '_relationship_between_job_members', 'main_goal_audio_sting',
        'audio_sting_on_start', '_level_data', '_display_name')

    @staticmethod
    def _states():
        return [(1, _ComeHereState)]

    @classmethod
    def _get_tuned_job_and_default_role_state_tuples(cls):
        return [(cls.summoned_job.situation_job,
                 cls.summoned_job.come_to_me_state)]

    @classmethod
    def default_job(cls):
        return cls.summoned_job.situation_job

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

    def start_situation(self):
        super().start_situation()
        self._change_state(_ComeHereState())

    def _on_set_sim_job(self, sim, job_type):
        super()._on_set_sim_job(sim, job_type)
        self._summoned_sim = sim

    def _on_sim_removed_from_situation_prematurely(self, sim):
        super()._on_sim_removed_from_situation_prematurely(sim)
        self._summoned_sim = None
Exemplo n.º 7
0
class InteractionOfInterest(AutoFactoryInit):
    __qualname__ = 'InteractionOfInterest'
    FACTORY_TUNABLES = {
        'affordance':
        TunableReference(
            description=
            '\n                The affordance that we are are timing for length of runtime.\n                ',
            manager=services.affordance_manager(),
            class_restrictions='SuperInteraction'),
        'tags':
        TunableSet(
            description=
            '\n                A set of tags that will match an affordance instead of looking\n                for a specific one.\n                ',
            tunable=TunableEnumEntry(Tag, Tag.INVALID)),
        'duration':
        TunableRange(
            description=
            '\n                The amount of time in sim hours that this interaction has to\n                run for this test to be considered passed.\n                ',
            tunable_type=int,
            default=10,
            minimum=1)
    }

    def get_expected_args(self):
        return {'interaction': event_testing.test_events.FROM_EVENT_DATA}

    def __call__(self, interaction=None):
        if interaction.affordance is self.affordance:
            return TestResult.TRUE
        if self.tags & interaction.get_category_tags():
            return TestResult.TRUE
        return TestResult(
            False,
            'Failed affordance check: {} is not {} and does not have any matching tags in {}.',
            interaction.affordance, self.affordance, self.tags)
Exemplo n.º 8
0
class PushInteractionOnAllGreetedSimsInteraction(
        interactions.base.super_interaction.SuperInteraction):
    __qualname__ = 'PushInteractionOnAllGreetedSimsInteraction'
    INSTANCE_TUNABLES = {
        '_pushed_interaction_tunables':
        TunableTuple(
            affordance_to_push=sims4.tuning.tunable.TunableReference(
                description=
                '\n                Affordance to push on all sims in the household and all greeted\n                sims.\n                ',
                manager=services.affordance_manager()),
            push_on_actor=sims4.tuning.tunable.Tunable(
                description=
                '\n               Whether Afforance To Push should be pushed on the actor.\n               ',
                tunable_type=bool,
                default=False),
            target_override_for_pushed_affordance=OptionalTunable(
                TunableEnumEntry(
                    description=
                    '\n                ParticipantType for the target to be set on the pushed\n                affordance.\n                ',
                    tunable_type=ParticipantType,
                    default=ParticipantType.Actor))),
        '_required_appropriateness_tags':
        TunableSet(
            description=
            '\n            A list of tags that a Sim must have to be eligible for this\n            interaction.\n            ',
            tunable=TunableEnumEntry(tunable_type=tag.Tag,
                                     default=tag.Tag.INVALID))
    }

    @classmethod
    def _test(cls, target, context, **interaction_parameters):
        sim = next(cls._target_sim_gen(context.sim), None)
        if sim is None:
            return event_testing.results.TestResult(False,
                                                    'No valid sims to call.')
        return super()._test(target, context, **interaction_parameters)

    def _run_interaction_gen(self, timeline):
        if self._pushed_interaction_tunables.target_override_for_pushed_affordance is not None:
            new_target = self.get_participant(
                self._pushed_interaction_tunables.
                target_override_for_pushed_affordance)
        else:
            new_target = self.target
        for target_sim in self._target_sim_gen(self.sim):
            target_context = self.context.clone_for_sim(target_sim)
            target_sim.push_super_affordance(
                self._pushed_interaction_tunables.affordance_to_push,
                new_target, target_context)
        return event_testing.results.ExecuteResult.NONE

    @classmethod
    def _target_sim_gen(cls, sim):
        for target_sim in services.sim_info_manager(
        ).instanced_sims_on_active_lot_gen():
            while target_sim.Buffs.is_appropriate(
                    cls._required_appropriateness_tags):
                if not cls._pushed_interaction_tunables.push_on_actor and target_sim is sim:
                    pass
                yield target_sim
Exemplo n.º 9
0
def MP_Chat_add_super_affordances(original, self):
    original(self)
    sa_list = []
    affordance_manager = services.affordance_manager()
    for sa_id in MP_Chat_sa_instance_ids:
        tuning_class = affordance_manager.get(sa_id)
        if not tuning_class is None:
            sa_list.append(tuning_class)
    self._super_affordances = self._super_affordances + tuple(sa_list)
class EnvironmentScoreTuning:
    __qualname__ = 'EnvironmentScoreTuning'
    ENVIRONMENT_SCORE_BROADCASTER = BroadcasterEnvironmentScore.TunableReference(
        description=
        '\n        The singleton broadcaster that groups all scoring objects. The\n        constraints on this broadcaster determine the constraint within which a\n        Sim is affected by environment score.\n        '
    )
    ENVIRONMENT_SCORE_MOODS = TunableMapping(
        description=
        "\n        Tags on Objects correspond to a particular Mood.\n                \n        When an object is going to contribute to the environment score, put a\n        tag in it's catalog object, and make sure that tag points to a Mood\n        here.\n        ",
        key_type=TunableEnumEntry(
            description=
            '\n            The Tag that corresponds to mood and environmental scoring data.\n            ',
            tunable_type=tag.Tag,
            default=tag.Tag.INVALID),
        value_type=Mood.TunableReference(
            description=
            '\n            The mood that the Sim must be in for an object that emits this mood\n            to score. Corresponds to the mood_tag.\n            '
        ),
        key_name='object_tag',
        value_name='mood')
    NEGATIVE_ENVIRONMENT_SCORING = Commodity.TunableReference(
        description=
        '\n        Defines the ranges and corresponding buffs to apply for negative\n        environmental contribution.\n        \n        Be sure to tune min, max, and the different states. The convergence\n        value is what will remove the buff. Suggested to be 0.\n        '
    )
    POSITIVE_ENVIRONMENT_SCORING = Commodity.TunableReference(
        description=
        '\n        Defines the ranges and corresponding buffs to apply for positive\n        environmental contribution.\n        \n        Be sure to tune min, max, and the different states. The convergence\n        value is what will remove the buff. Suggested to be 0.\n        '
    )
    ENABLE_AFFORDANCE = TunableReference(
        description=
        '\n        The interaction that will turn on Environment Score for a particular\n        object. This interaction should set a state on the object that will\n        have multipliers of 1 and adders of 0 for all moods.\n        ',
        manager=services.affordance_manager())
    DISABLE_AFFORDANCE = TunableReference(
        description=
        '\n        The interaction that will turn off Environment Score for a particular\n        object. This interaction should set a state on the object that will\n        have multipliers of 0 and adders of 0 for all moods.\n        ',
        manager=services.affordance_manager())
    ENABLED_STATE_VALUE = ObjectStateValue.TunableReference(
        description=
        '\n        A state value that indicates the object should be contributing\n        Environment Score.\n        '
    )
    DISABLED_STATE_VALUE = ObjectStateValue.TunableReference(
        description=
        '\n        A state value that indicates the object should not be contributing\n        Environment Score.\n        '
    )
Exemplo n.º 11
0
 def get_affordance(pack_safe=False):
     return {
         'affordance':
         TunableReference(
             description=
             '\n                The affordance to push on the subject.\n                ',
             manager=services.affordance_manager(),
             class_restrictions=('SuperInteraction', ),
             pack_safe=pack_safe)
     }
Exemplo n.º 12
0
class SpawnActionAffordance(HasTunableSingletonFactory, AutoFactoryInit):
    __qualname__ = 'SpawnActionAffordance'
    FACTORY_TUNABLES = {
        'spawn_affordance':
        TunableReference(
            description=
            '\n            The affordance that is pushed on the Sim as soon as they are spawned\n            on the lot.\n            ',
            manager=services.affordance_manager(),
            class_restrictions=('SuperInteraction', ))
    }

    def __call__(self, sim):
        context = InteractionContext(sim, InteractionSource.SCRIPT,
                                     Priority.Critical)
        return sim.push_super_affordance(self.spawn_affordance, None, context)
Exemplo n.º 13
0
class TimeoutLiability(Liability, HasTunableFactory):
    LIABILITY_TOKEN = 'TimeoutLiability'
    FACTORY_TUNABLES = {
        'description':
        'Establish a timeout for this affordance. If it has not run when the timeout hits, cancel and push timeout_affordance, if set.',
        'timeout':
        TunableSimMinute(
            4,
            minimum=0,
            description=
            'The time, in Sim minutes, after which the interaction is canceled and time_toute affordance is pushed, if set.'
        ),
        'timeout_affordance':
        TunableReference(
            services.affordance_manager(),
            allow_none=True,
            description=
            'The affordance to push when the timeout expires. Can be unset, in which case the interaction will just be canceled.'
        )
    }

    def __init__(self, interaction, *, timeout, timeout_affordance, **kwargs):
        super().__init__(**kwargs)

        def on_alarm(*_, **__):
            if interaction.running:
                return
            if interaction.transition is not None and interaction.transition.running:
                return
            if timeout_affordance is not None:
                context = interaction.context.clone_for_continuation(
                    interaction)
                interaction.sim.push_super_affordance(timeout_affordance,
                                                      interaction.target,
                                                      context)
            interaction.cancel(
                FinishingType.LIABILITY,
                cancel_reason_msg='Timeout after {} sim minutes.'.format(
                    timeout))

        time_span = clock.interval_in_sim_minutes(timeout)
        self._handle = alarms.add_alarm(self, time_span, on_alarm)

    def release(self):
        alarms.cancel_alarm(self._handle)

    def should_transfer(self, continuation):
        return False
class VoodooSummonSituation(situations.situation_complex.SituationComplexCommon
                            ):
    INSTANCE_TUNABLES = {
        'summoned_job':
        sims4.tuning.tunable.TunableTuple(
            situation_job=SituationJob.TunableReference(
                description=
                '\n                          A reference to the SituationJob used for the Sim summoned.\n                          '
            ),
            come_to_me_state=RoleState.TunableReference(
                description=
                '\n                          The state for telling the summoned sim to come here.\n                          '
            )),
        'come_here_affordance':
        sims4.tuning.tunable.TunableReference(
            services.affordance_manager(),
            description='SI to bring summoned sim to the summoner.')
    }
    REMOVE_INSTANCE_TUNABLES = Situation.NON_USER_FACING_REMOVE_INSTANCE_TUNABLES

    @classmethod
    def _states(cls):
        return (SituationStateData(1, _ComeHereState), )

    @classmethod
    def _get_tuned_job_and_default_role_state_tuples(cls):
        return [(cls.summoned_job.situation_job,
                 cls.summoned_job.come_to_me_state)]

    @classmethod
    def default_job(cls):
        return cls.summoned_job.situation_job

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

    def start_situation(self):
        super().start_situation()
        self._change_state(_ComeHereState())

    def _on_set_sim_job(self, sim, job_type):
        super()._on_set_sim_job(sim, job_type)
        self._summoned_sim = sim

    def _on_sim_removed_from_situation_prematurely(self, sim, sim_job):
        self._summoned_sim = None
Exemplo n.º 15
0
    def inject_into_relationship_panel(cls, sim):
        affordance_manager = services.affordance_manager()
        injected_interactions = []

        for interaction_id in cls.sim_interactions:
            interaction_class = affordance_manager.get(interaction_id)

            if interaction_class is None:
                Logger.log(
                    'interaction {} not found in affordance_manager'.format(
                        interaction_id))
                continue

            injected_interactions.append(interaction_class)

        sim._relation_panel_affordances = (sim._relation_panel_affordances +
                                           tuple(injected_interactions))
Exemplo n.º 16
0
class PushAffordanceFromRole(HasTunableSingletonFactory, AutoFactoryInit):
    __qualname__ = 'PushAffordanceFromRole'
    FACTORY_TUNABLES = {
        'description':
        '\n                        Push the specific affordance onto the sim.\n                        ',
        'affordance':
        TunableReference(services.affordance_manager()),
        'source':
        TunableEnumEntry(tunable_type=InteractionSource,
                         default=InteractionSource.SCRIPT),
        'priority':
        TunableEnumEntry(tunable_type=Priority,
                         default=Priority.High,
                         description='Priority to push the interaction'),
        'run_priority':
        TunableEnumEntry(
            tunable_type=Priority,
            default=None,
            description=
            'Priority to run the interaction. None means use the (push) priority'
        ),
        'target':
        TunableEnumEntry(
            description=
            '\n                            The target of the affordance. We will try to get\n                            the target from the situation the role sim is\n                            running.\n                            ',
            tunable_type=SituationAffordanceTarget,
            default=SituationAffordanceTarget.NO_TARGET)
    }

    def __call__(self, role_state, role_affordance_target):
        sim = role_state.sim
        affordance = self.affordance
        source = self.source
        priority = self.priority
        run_priority = self.run_priority
        if run_priority is None:
            run_priority = priority
        interaction_context = InteractionContext(sim,
                                                 source,
                                                 priority,
                                                 run_priority=run_priority)
        target = role_state._get_target_for_push_affordance(
            self.target, role_affordance_target=role_affordance_target)
        sim.push_super_affordance(affordance, target, interaction_context)
def generate_animation_element_data(*args, zone_id: int = None, **kwargs):
    affordance_manager = services.affordance_manager()
    animation_element_data = []
    for (animation_element, usage) in get_animation_reference_usage().items():
        animation_element_data.append({
            'animation_element_name':
            animation_element.__name__,
            'count_interaction':
            usage[InteractionAsmType.Interaction],
            'count_outcome':
            usage[InteractionAsmType.Outcome],
            'count_response':
            usage[InteractionAsmType.Response],
            'count_reactionlet':
            usage[InteractionAsmType.Reactionlet],
            'count_total':
            sum(count for count in usage.values())
        })
    return animation_element_data
def writeauto_add_superaffordances(original, self):
    original(self)

    if self.TYPE == Types.OBJECT:
        # First, get a tuple containing the tunings for all the super affordances...
        affordance_manager = services.affordance_manager()
        sa_list = []
        for sa_id in jay_writeautonomously_sa_instance_ids:
            key = sims4.resources.get_resource_key(sa_id, Types.INTERACTION)
            sa_tuning = affordance_manager.get(key)
            if not sa_tuning is None:
                sa_list.append(sa_tuning)
        sa_tuple = tuple(sa_list)

        # Now update the tunings for all the objects in our object list
        for obj_id in JAY_COMPUTER_IDS:
            key = sims4.resources.get_resource_key(obj_id, Types.OBJECT)
            obj_tuning = self._tuned_classes.get(key)
            if not obj_tuning is None:
                obj_tuning._super_affordances = obj_tuning._super_affordances + sa_tuple
Exemplo n.º 19
0
class ChooseDeliverySuperInteraction(CraftingPhaseSuperInteractionMixin, SuperInteraction):
    __qualname__ = 'ChooseDeliverySuperInteraction'
    INSTANCE_TUNABLES = {'delivery_to_bar_affordance': TunableReference(services.affordance_manager(), class_restrictions=ServeDrinkToCounterSuperInteraction, description="Affordance used to deliver a drink to a slot, if the order sim doesn't sit at the barstool slot to the bar."), 'delivery_to_sit_drink_slot_affordance': TunableReference(services.affordance_manager(), class_restrictions=ServeDrinkToSitDrinkSlotSuperInteraction, description='The affordance to delivery a drink to the sit_drink slot, if the order sim sits at the barstool slot to the bar.')}

    @property
    def auto_goto_next_phase(self):
        return False

    @classmethod
    def is_guaranteed(cls, *args, **kwargs):
        return True

    def _pick_affordance(self, order_sim, object_info, context):
        deliver_part = None
        carry_track = object_info.carry_track
        deliver_to_bar = self.delivery_to_bar_affordance
        deliver_to_sit_drink_slot = self.delivery_to_sit_drink_slot_affordance
        if self.sim == order_sim or order_sim is None:
            return (deliver_to_bar, self.target, deliver_part, carry_track)
        order_surface_target = order_sim.posture_state.surface_target
        if order_surface_target is not None and order_surface_target.is_part:
            bar = None
            if self.target.is_part:
                bar = self.target.part_owner
            if order_surface_target.part_owner is bar:
                if order_surface_target.is_valid_for_placement(definition=object_info.definition):
                    deliver_part = order_surface_target
                    return (deliver_to_sit_drink_slot, self.target, deliver_part, carry_track)
        return (deliver_to_bar, self.target, deliver_part, carry_track)

    def _run_interaction_gen(self, timeline):
        (order_sim, recipe) = self.process.pop_order()
        object_info = recipe.final_product
        context = self.context.clone_for_continuation(self)
        (deliver_affordance, target, deliver_part, carry_track) = self._pick_affordance(order_sim, object_info, context)
        obj_info_copy = FrozenAttributeDict(object_info, carry_track=carry_track)
        new_process = self.process.copy_for_serve_drink(recipe)
        aop = AffordanceObjectPair(deliver_affordance, target, deliver_affordance, None, order_sim=order_sim, object_info=obj_info_copy, deliver_part=deliver_part, phase=self.process.phase, crafting_process=new_process)
        self._went_to_next_phase_or_finished_crafting = True
        return aop.test_and_execute(context)
Exemplo n.º 20
0
class FinishWalkState(CommonInteractionCompletedSituationState):
    FACTORY_TUNABLES = {
        'go_home_affordance':
        TunableReference(
            description=
            '\n            The affordance that the dog walker runs to go home.\n            ',
            manager=services.affordance_manager())
    }

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

    def on_activate(self, reader=None):
        super().on_activate(reader=reader)
        walker = self.owner.get_walker()
        if walker is None or not walker.sim_info.lives_here:
            self.owner.walk_onward()
        context = InteractionContext(walker,
                                     InteractionContext.SOURCE_SCRIPT,
                                     Priority.High,
                                     insert_strategy=QueueInsertStrategy.NEXT)
        aop = interactions.aop.AffordanceObjectPair(self.go_home_affordance,
                                                    walker,
                                                    self.go_home_affordance,
                                                    None)
        aop.test_and_execute(context)

    def _additional_tests(self, sim_info, event, resolver):
        walker = self.owner.get_walker()
        if walker is None or not sim_info.id == walker.id:
            return False
        return True

    def _on_interaction_of_interest_complete(self, **kwargs):
        self.owner.walk_onward()

    def timer_expired(self):
        self.owner.walk_onward()
Exemplo n.º 21
0
class SpawnActionAffordance(HasTunableSingletonFactory, AutoFactoryInit):
    FACTORY_TUNABLES = {
        'spawn_affordance':
        TunableReference(
            description=
            '\n            The affordance that is pushed on the Sim as soon as they are spawned\n            on the lot.\n            ',
            manager=services.affordance_manager(),
            class_restrictions=('SuperInteraction', ))
    }

    def __call__(self, sim):
        context = InteractionContext(sim, InteractionSource.SCRIPT,
                                     Priority.Critical)
        result = sim.push_super_affordance(self.spawn_affordance, None,
                                           context)
        if not result:
            logger.error('{} failed to run, with result {}. Fading {} in.',
                         self.spawn_affordance, result, sim)
            sim.fade_in()
        result.interaction.add_liability(
            SpawnActionLiability.LIABILITY_TOKEN,
            SpawnActionLiability(sim, self.spawn_affordance))
        return True
class MultipleSimInteractionOfInterest(AutoFactoryInit):
    __qualname__ = 'MultipleSimInteractionOfInterest'
    FACTORY_TUNABLES = {
        'affordance':
        TunableReference(
            description=
            '\n                The affordance in question that is being run by all the sims.\n                ',
            manager=services.affordance_manager(),
            class_restrictions='SuperInteraction'),
        'tags':
        TunableSet(
            description=
            '\n                A set of tags that match the affordance being run by all the sims. \n                ',
            tunable=TunableEnumWithFilter(
                tunable_type=tag.Tag,
                default=tag.Tag.INVALID,
                filter_prefixes=tag.INTERACTION_PREFIX)),
        'sim_count':
        Tunable(
            description=
            '\n                The number of sims simultaneously running the appropriate interactions.\n                ',
            tunable_type=int,
            default=2)
    }

    def get_expected_args(self):
        return {'interaction': event_testing.test_events.FROM_EVENT_DATA}

    def __call__(self, interaction=None):
        if interaction.affordance is self.affordance:
            return TestResult.TRUE
        if self.tags & interaction.get_category_tags():
            return TestResult.TRUE
        return TestResult(
            False,
            'Failed affordance check: {} is not {} and does not have any matching tags in {}.',
            interaction.affordance, self.affordance, self.tags)
Exemplo n.º 23
0
class InteractionOfInterest(AutoFactoryInit):
    FACTORY_TUNABLES = {
        'affordances':
        TunableList(
            description=
            "\n            The Sim must have started either any affordance in this list or an\n            interaction matching one of the tags in this tunable's Tags\n            field.\n            ",
            tunable=TunableReference(services.affordance_manager(),
                                     pack_safe=True)),
        'tags':
        TunableSet(
            description=
            '\n            The Sim must have run either an interaction matching one of these\n            Tags or an affordance from the list of Affordances in this\n            tunable.',
            tunable=TunableEnumEntry(Tag, Tag.INVALID))
    }
    expected_kwargs = (('interaction',
                        event_testing.test_constants.FROM_EVENT_DATA), )

    def get_expected_args(self):
        return dict(self.expected_kwargs)

    def __call__(self, interaction=None):
        if interaction is None:
            return TestResult(False, 'No affordance to check against {}',
                              self.affordances)
        if self.tags & interaction.get_category_tags():
            return TestResult.TRUE
        if interaction.affordance in self.affordances:
            return TestResult.TRUE
        return TestResult(False, 'Failed affordance check: {} not in {}',
                          interaction.affordance, self.affordances)

    def custom_keys_gen(self):
        for affordance in self.affordances:
            yield affordance
        for tag in self.tags:
            yield tag
Exemplo n.º 24
0
class PushAffordanceFromRole(HasTunableSingletonFactory, AutoFactoryInit):
    FACTORY_TUNABLES = {
        'description':
        '\n            Push the specific affordance onto the sim.\n            ',
        'affordance':
        TunableReference(manager=services.affordance_manager()),
        'super_affordance_for_mixer':
        OptionalTunable(
            description=
            '\n            If we want to push mixer directly in the affordance tuning for this\n            role state, we would need to provide a super affordance here to\n            handle the mixer.\n            ',
            tunable=TunableReference(manager=services.affordance_manager()),
            disabled_name='do_not_need_si',
            enabled_name='provide_si'),
        'source':
        TunableEnumEntry(tunable_type=InteractionSource,
                         default=InteractionSource.SCRIPT),
        'priority':
        TunableEnumEntry(
            description=
            '\n            Priority to push the interaction\n            ',
            tunable_type=Priority,
            default=Priority.High),
        'run_priority':
        TunableEnumEntry(
            description=
            '\n            Priority to run the interaction. None means use the (push) priority\n            ',
            tunable_type=Priority,
            default=None),
        'target':
        TunableEnumEntry(
            description=
            '\n            The target of the affordance. We will try to get\n            the target from the situation the role sim is\n            running.\n            ',
            tunable_type=SituationAffordanceTarget,
            default=SituationAffordanceTarget.NO_TARGET),
        'leave_situation_on_failure':
        Tunable(
            description=
            '\n            If set to True, when push affordance on the sim fails, sim will\n            leave the situation.\n            ',
            tunable_type=bool,
            default=False),
        'add_situation_liability':
        Tunable(
            description=
            '\n            If set to True, we will add a liability to the pushed interaction\n            such that we will cancel the situation owning this role state\n            if the interaction (and its continuations) are completed or \n            canceled.\n            ',
            tunable_type=bool,
            default=False)
    }

    def __call__(self,
                 role_state,
                 role_affordance_target,
                 situation=None,
                 **kwargs):
        sim = role_state.sim
        affordance = self.affordance
        source = self.source
        priority = self.priority
        run_priority = self.run_priority
        if run_priority is None:
            run_priority = priority
        interaction_context = InteractionContext(sim,
                                                 source,
                                                 priority,
                                                 run_priority=run_priority,
                                                 **kwargs)
        target = role_state._get_target_for_push_affordance(
            self.target,
            situation=situation,
            role_affordance_target=role_affordance_target)
        try:
            push_result = False
            if affordance.is_super:
                push_result = sim.push_super_affordance(
                    affordance, target, interaction_context)
            else:
                super_affordance = self.super_affordance_for_mixer
                if super_affordance is not None:
                    potential_parent_si = sim.si_state.get_si_by_affordance(
                        super_affordance)
                    if potential_parent_si is not None:
                        aop = AffordanceObjectPair(affordance, target,
                                                   super_affordance,
                                                   potential_parent_si)
                        push_result = aop.test_and_execute(interaction_context)
            if push_result:
                if self.add_situation_liability:
                    liability = SituationLiability(situation)
                    push_result.interaction.add_liability(
                        SITUATION_LIABILITY, liability)
            elif self.leave_situation_on_failure:
                situation_manager = services.get_zone_situation_manager()
                situation_manager.remove_sim_from_situation(sim, situation.id)
        except AttributeError:
            logger.error(
                'Attribute Error occurred pushing interaction {} on sim: {} for role_state:{}',
                affordance,
                sim,
                role_state,
                owner='msantander')
            raise
Exemplo n.º 25
0
class RoleState(HasDependentTunableReference,
                role.role_state_base.RoleStateBase,
                metaclass=HashedTunedInstanceMetaclass,
                manager=services.get_instance_manager(
                    sims4.resources.Types.ROLE_STATE)):
    INSTANCE_TUNABLES = {
        '_role_priority':
        TunableEnumEntry(
            RolePriority,
            RolePriority.NORMAL,
            description=
            '\n                The priority of this role state.  All the role states with the\n                same priority will all be applied together.  The highest group\n                of priorities is considered the active ones.\n                '
        ),
        '_buffs':
        TunableList(
            buffs.tunable.TunableBuffReference(pack_safe=True),
            description=
            '\n                Buffs that will be added to sim when role is active.\n                '
        ),
        '_off_lot_autonomy_buff':
        buffs.tunable.TunableBuffReference(
            description=
            'A buff that\n            prevents autonomy from considering some objects based on the\n            location of the object (e.g. on lot, off lot, within a radius of the\n            sim).\n             \n            In the buff set: Game Effect Modifiers->Autonomy Modifier->Off Lot\n            Autonomy Rule.\n            ',
            allow_none=True),
        'tags':
        TunableSet(
            TunableEnumEntry(Tag, Tag.INVALID),
            description=
            '\n                Tags for the role state for checking role states against a set\n                of tags rather than against a list of role states.\n                '
        ),
        'role_affordances':
        TunableList(
            description=
            "\n            A list of affordances that are available on the Sim in this Role\n            State.\n            \n            e.g: when a Maid is in the working Role State, he or she will have\n            the 'Dismiss' and 'Fire' affordances available in the Pie Menu.\n            ",
            tunable=TunableReference(manager=services.affordance_manager(),
                                     class_restrictions=('SuperInteraction', ),
                                     pack_safe=True)),
        'role_target_affordances':
        TunableList(
            description=
            '\n            A list of affordances that are available on other Sims when the\n            actor Sim is in this Role State.\n            \n            e.g. a Sim in a specific Role State could have an "Invite to\n            Situation" interaction available when bringing up other Sims\' Pie\n            Menus.\n            ',
            tunable=TunableReference(manager=services.affordance_manager(),
                                     class_restrictions=('SuperInteraction', ),
                                     pack_safe=True)),
        'preroll_affordances':
        TunableList(
            description=
            '\n            A list of affordances that are available for sims to consider when\n            running pre-roll. Objects related to role can specify preroll\n            autonomy, but there are some roles that may not have an object\n            associated with it\n            \n            e.g. Romance guru in romance festival preroll to an attractor point.\n            ',
            tunable=TunableReference(manager=services.affordance_manager(),
                                     class_restrictions=('SuperInteraction', ),
                                     pack_safe=True)),
        '_on_activate':
        TunableVariant(
            description=
            '\n                Select the autonomy behavior when this role state becomes active on the sim.\n                disabled: Take no action.\n                autonomy_ping: We explicitly force an autonomy ping on the sim.\n                push_affordance: Push the specific affordance on the sim.\n                ',
            locked_args={'disabled': None},
            autonomy_ping=DoAutonomyPingFromRole.TunableFactory(),
            parameterized_autonomy_ping=DoParameterizedAutonomyPingFromRole.
            TunableFactory(),
            push_affordance=PushAffordanceFromRole.TunableFactory(),
            default='disabled'),
        '_portal_disallowance_tags':
        TunableSet(
            description=
            '\n                A set of tags that define what the portal disallowance tags of\n                this role state are.  Portals that include any of these\n                disallowance tags are considered locked for sims that have this\n                role state.\n                ',
            tunable=TunableEnumWithFilter(
                description=
                '\n                    A single portal disallowance tag.\n                    ',
                tunable_type=tag.Tag,
                default=tag.Tag.INVALID,
                filter_prefixes=tag.PORTAL_DISALLOWANCE_PREFIX)),
        '_allow_npc_routing_on_active_lot':
        Tunable(
            description=
            '\n                If True, then npc in this role will be allowed to route on the\n                active lot.\n                If False, then npc in this role will not be allowed to route on the\n                active lot, unless they are already on the lot when the role\n                state is activated.\n                \n                This flag is ignored for player sims and npcs who live on the\n                active lot.\n                \n                e.g. ambient walkby sims should not be routing on the active lot\n                because that is rude.\n                ',
            tunable_type=bool,
            default=True),
        '_autonomy_state_override':
        OptionalTunable(
            description=
            '\n            If tuned, will force role sims into a specific autonomy state.\n            Please consult your GPE partner before using this.\n            ',
            tunable=TunableEnumEntry(tunable_type=AutonomyState,
                                     default=AutonomyState.LIMITED_ONLY,
                                     invalid_enums=(AutonomyState.MEDIUM, )),
            tuning_filter=FilterTag.EXPERT_MODE),
        '_crafting_process_override':
        TunableEnumEntry(
            description=
            '\n                The override option of who to assign ownership of objects made\n                by Sims in this role state.\n                ',
            tunable_type=RoleStateCraftingOwnershipOverride,
            default=RoleStateCraftingOwnershipOverride.NO_OVERRIDE),
        'always_active':
        Tunable(
            description=
            "\n                If set to True, this role will always be allowed to be active\n                when set on a Sim, regardless of whether or not it is \n                lower priority than the Sim's other currently active roles. \n                Use for roles that are important but retuning priority for it \n                and/or other roles isn't feasible.\n                \n                Consult a GPE before you set this to True.\n                This is not to be used lightly and there may be other options\n                like situation exclusivity that can be explored before you\n                go down this route.\n                \n                e.g. Sim is possessed which runs at HIGH priority.\n                Sim wants to go visit an NPC residential lot, which places\n                Sim in NORMAL priority Role_UngreetedPlayerVisitingNPC, which\n                sets portal disallowance and adds specific buffs.\n                \n                We actually want Role_UngreetedPlayerVisitingNPC to run\n                even though the role priority is now HIGH, because \n                otherwise a possessed Sim visiting an NPC would magically\n                be able to route through homes because portal disallowance\n                is removed.\n                ",
            tunable_type=bool,
            default=False)
    }

    @classmethod
    def _verify_tuning_callback(cls):
        for buff_ref in cls.buffs:
            if buff_ref is None:
                logger.error(
                    '{} has empty buff in buff list. Please fix tuning.', cls)
            elif buff_ref.buff_type._temporary_commodity_info is not None:
                logger.error(
                    '{} has a buff {} that has a temporary commodity.', cls,
                    buff_ref.buff_type)

    @classproperty
    def role_priority(cls):
        return cls._role_priority

    @classproperty
    def buffs(cls):
        return cls._buffs

    @classproperty
    def off_lot_autonomy_buff(cls):
        return cls._off_lot_autonomy_buff

    @classproperty
    def role_specific_affordances(cls):
        return cls.role_affordances

    @classproperty
    def allow_npc_routing_on_active_lot(cls):
        return cls._allow_npc_routing_on_active_lot

    @classproperty
    def autonomy_state_override(cls):
        return cls._autonomy_state_override

    @classproperty
    def on_activate(cls):
        return cls._on_activate

    @classproperty
    def portal_disallowance_tags(cls):
        return cls._portal_disallowance_tags

    @classproperty
    def has_full_permissions(cls):
        current_venue = services.get_current_venue()
        if current_venue and current_venue.allow_rolestate_routing_on_navmesh:
            return True
        return not cls._portal_disallowance_tags and cls._allow_npc_routing_on_active_lot

    def _get_target_for_push_affordance(self,
                                        situation_target,
                                        situation=None,
                                        role_affordance_target=None):
        if situation_target == SituationAffordanceTarget.NO_TARGET:
            return
        if situation_target == SituationAffordanceTarget.CRAFTED_OBJECT:
            return role_affordance_target
        if situation_target == SituationAffordanceTarget.TARGET_OBJECT and situation is not None:
            return situation.get_target_object()
        if situation_target == SituationAffordanceTarget.CREATED_OBJECT and situation is not None:
            return situation.get_created_object()
        logger.error(
            'Unable to resolve target when trying to push affordance on role state {} activate. requested target type was {}',
            self, self._on_activate.target)

    @classproperty
    def active_household_crafting_override(cls):
        return cls._crafting_process_override == RoleStateCraftingOwnershipOverride.ACTIVE_HOUSEHOLD

    @classproperty
    def lot_owner_crafting_override(cls):
        return cls._crafting_process_override == RoleStateCraftingOwnershipOverride.LOT_OWNER
Exemplo n.º 26
0
class CarryableComponent(
        Component,
        HasTunableFactory,
        AutoFactoryInit,
        component_name=objects.components.types.CARRYABLE_COMPONENT):
    class _CarryableAllowedHands(HasTunableSingletonFactory, AutoFactoryInit):
        FACTORY_TUNABLES = {
            'biped_allowed_hands':
            TunableVariant(locked_args={
                'both': (Hand.LEFT, Hand.RIGHT),
                'left_only': (Hand.LEFT, ),
                'right_only': (Hand.RIGHT, )
            },
                           default='both'),
            'quadruped_allowed_hands':
            TunableVariant(locked_args={
                'both': (Hand.LEFT, Hand.RIGHT),
                'mouth_only': (Hand.RIGHT, ),
                'back_only': (Hand.LEFT, )
            },
                           default='mouth_only')
        }

        def get_allowed_hands(self, sim):
            if sim is None:
                return self.biped_allowed_hands
            return sim.get_allowed_hands_type(self)

    class _CarryableTransitionConstraint(HasTunableSingletonFactory,
                                         AutoFactoryInit):
        FACTORY_TUNABLES = {
            'constraint_mobile':
            TunableList(
                description=
                '\n                The constraint to use when the Sim is in a mobile posture.\n                ',
                tunable=TunableGeometricConstraintVariant(
                    disabled_constraints={
                        'spawn_points', 'relative_circle', 'current_position'
                    })),
            'constraint_non_mobile':
            TunableList(
                description=
                '\n                The constraint to use when the Sim is not in a mobile posture.\n                ',
                tunable=TunableGeometricConstraintVariant(
                    disabled_constraints={
                        'spawn_points', 'relative_circle', 'current_position'
                    }))
        }

    DEFAULT_GEOMETRIC_TRANSITION_CONSTRAINT = _CarryableTransitionConstraint.TunableFactory(
        description=
        '\n        Unless specifically overridden, the constraint to use when transitioning\n        into and out of a carry for any carryable object.\n        '
    )
    DEFAULT_GEOMETRIC_TRANSITION_LARGE = TunableRange(
        description=
        '\n        This is a large transition distance. This is used by:\n            * TYAE humans picking up any pet\n        ',
        tunable_type=float,
        default=0.7,
        minimum=0)
    DEFAULT_GEOMETRIC_TRANSITION_MEDIUM = TunableRange(
        description=
        '\n        This is a medium transition distance. This is used by:\n            * TYAE humans picking up P humans\n        ',
        tunable_type=float,
        default=0.6,
        minimum=0)
    DEFAULT_GEOMETRIC_TRANSITION_SMALL = TunableRange(
        description=
        '\n        This is a small transition distance. This is used by:\n            * C humans picking up AE cats and AE small dogs\n        ',
        tunable_type=float,
        default=0.503,
        minimum=0)
    DEFAULT_GEOMETRIC_TRANSITION_TINY = TunableRange(
        description=
        '\n        This is a tiny transition distance. This is used by:\n            * C humans picking up C cats and C dogs and small dogs\n        ',
        tunable_type=float,
        default=0.419,
        minimum=0)
    DEFAULT_CARRY_AFFORDANCES = TunableList(
        description=
        '\n        The list of default carry affordances.\n        ',
        tunable=TunableReference(manager=services.get_instance_manager(
            sims4.resources.Types.INTERACTION)))
    PUT_IN_INVENTORY_AFFORDANCE = TunableReference(
        description=
        '\n        The affordance used by carryable component to put objects in inventory.\n        ',
        manager=services.get_instance_manager(
            sims4.resources.Types.INTERACTION))
    PUT_DOWN_HERE_AFFORDANCE = TunableReference(
        description=
        '\n        The affordance used by carryable component to put down here via the\n        PutDownLiability liability.\n        ',
        manager=services.get_instance_manager(
            sims4.resources.Types.INTERACTION))
    PUT_DOWN_ANYWHERE_AFFORDANCE = TunableReference(
        description=
        '\n        The affordance used by carryable component to put down objects anywhere\n        via the PutDownLiability liability.\n        ',
        manager=services.get_instance_manager(
            sims4.resources.Types.INTERACTION))
    FACTORY_TUNABLES = {
        'put_down_tuning':
        TunableVariant(
            description=
            '\n            Define how Sims prefer to put this object down.\n            ',
            reference=TunablePutDownStrategySpeciesMapping(
                description=
                '\n                Define specific costs for all the possible locations this object\n                could be put down. Also, define, if necessary, custom\n                interactions to put the object down.\n                \n                If this is not specified, and the default is used, the most\n                appropriate put down strategy is used. This allows the object to\n                be put down in most places (floor, inventory, slots). Also,\n                species might specify their own custom behavior.\n                '
            ),
            locked_args={'use_default': None},
            default='use_default'),
        'state_based_put_down_tuning':
        TunableMapping(
            description=
            '\n            A mapping from a state value to a putdownstrategy. If the owning\n            object is in any of the states tuned here, it will use that state\'s\n            associated putdownstrategy in place of the one putdownstrategy tuned\n            in the "put_down_tuning" field. If the object is in multiple states\n            listed in this mapping, the behavior is undefined.\n            ',
            key_type=TunableReference(
                description=
                '\n                The state value this object must be in in order to use the\n                associated putdownstrategy.\n                ',
                manager=services.get_instance_manager(
                    sims4.resources.Types.OBJECT_STATE)),
            value_type=
            TunableVariant(reference=TunablePutDownStrategySpeciesMapping(
                description=
                '\n                    Tuning for how to score where a Sim might want to set an\n                    object down.\n                    '
            )),
            key_name='State',
            value_name='PutDownStrategy'),
        'carry_affordances':
        OptionalTunable(tunable=TunableList(tunable=TunableReference(
            description=
            '\n                    The versions of the HoldObject affordance that this object\n                    supports.\n                    ',
            manager=services.affordance_manager())),
                        disabled_name='use_default_affordances',
                        enabled_name='use_custom_affordances'),
        'provided_affordances':
        TunableProvidedAffordances(
            description=
            '\n            Affordances that are generated when a Sim holding this object\n            selects another object to interact with. The generated interactions\n            target the selected object, and have their carry target set to the\n            component\'s owner.\n            \n            By default, this is applied to Sims. e.g.: The "Drink" interaction\n            provides "Make Toast" on other Sims.\n            \n            Optionally, you can specify a tag to have the interaction appear on\n            other objects. e.g.: The "Hold Puppy" interaction might unlock "Put\n            Down Here" on sofas.\n                \n            Target defaults to the object selected (Invalid). Carry Target is\n            locked to this object being carried. If is_linked is\n            checked, the affordance will be linked to the interaction\n            carrying this object.\n            ',
            class_restrictions=('SuperInteraction', ),
            locked_args={
                'allow_self': False,
                'target': ParticipantType.Object,
                'carry_target': ParticipantType.CarriedObject
            }),
        'constraint_pick_up':
        OptionalTunable(
            description=
            '\n            A list of constraints that must be fulfilled in order to\n            interact with this object.\n            ',
            tunable=TunableList(tunable=TunableConstraintVariant(
                description=
                '\n                    A constraint that must be fulfilled in order to\n                    interact with this object.\n                    '
            ))),
        'allowed_hands_data':
        _CarryableAllowedHands.TunableFactory(),
        'holster_while_routing':
        Tunable(
            description=
            '\n            If True, the Sim will holster the object before routing and\n            unholster when the route is complete.\n            ',
            tunable_type=bool,
            default=False),
        'holster_compatibility':
        TunableAffordanceFilterSnippet(
            description=
            '\n            Define interactions for which holstering this object is\n            explicitly disallowed.\n            \n            e.g. The Scythe is tuned to be holster-incompatible with\n            sitting, meaning that Sims will holster the Sctyhe when sitting.\n            '
        ),
        'unholster_when_routing':
        TunableUnholsterWhileRoutingBehaviorVariant(),
        'prefer_owning_sim_inventory_when_not_on_home_lot':
        Tunable(
            description=
            "\n            If checked, this object will highly prefer to be put into the\n            owning Sim's inventory when being put down by the owning Sim on\n            a lot other than their home lot.\n            \n            Certain objects, like consumables, should be exempt from this.\n            ",
            tunable_type=bool,
            default=True),
        'is_valid_posture_graph_object':
        Tunable(
            description=
            '\n            If this is checked, this object is allowed to provide postures and\n            expand in the posture graph, despite its ability to be carried.\n            \n            Normally, for the performance reasons, carryable objects are not\n            posture providing objects. The preferred way of interacting with a\n            carryable object is marking it as a carry requirement in the ASM.\n            \n            However, there are objects for which this is not possible. For\n            example, Nesting Blocks are carryable, but toddlers interact with\n            them while in the "Sit On Ground" posture, which must be provided by\n            the object\'s parts.\n            \n            This field should be used with caution, since posture graph\n            generation is one of our slowest systems. Do not enable it on\n            objects such as food or drinks, since the world is bound to have\n            many of them.\n            ',
            tunable_type=bool,
            default=False),
        'portal_key_mask_flags':
        TunableEnumFlags(
            description=
            "\n            Any flag tuned here will be kept on the Sim routing context who's\n            picking up this object.  This will allow a Sim to pickup some\n            type of objects and still be allowed to transition through\n            some portals while carrying an object.\n            ",
            enum_type=PortalFlags,
            allow_no_flags=True),
        'reslot_plumbbob':
        OptionalTunable(
            description=
            '\n            If tuned, the plumbbob will be repositioned when this item is carried.\n            Reslot will always go away when sim stops carrying the object.\n            ',
            tunable=TunableReslotPlumbbob()),
        'defer_putdown':
        Tunable(
            description=
            '\n            If true, the put down will be deferred to the end of the route. \n            If false, put down will be done at the start of the route. This\n            should be the default behavior. \n            ',
            tunable_type=bool,
            default=False),
        'put_down_height_tolerance':
        TunableRange(
            description=
            '\n            Maximum height tolerance on the terrain we will use for the \n            placement of this object when asking FGL to find a spot on the\n            floor.\n            Having a high value here will make it so an object can be placed\n            in a terrain spot with a high slope that might result with\n            clipping depending on the width of the object.  The way this will\n            work will be using the object footprint, if the edges are at a\n            height higher than the height tolerance, then the location will\n            not be valid.\n            ',
            tunable_type=float,
            default=1.1,
            minimum=0)
    }

    def __init__(self, owner, **kwargs):
        super().__init__(owner, **kwargs)
        self._attempted_putdown = False
        self._attempted_alternative_putdown = False
        self._cached_put_down_strategy = None

    @property
    def attempted_putdown(self):
        return self._attempted_putdown

    @property
    def attempted_alternative_putdown(self):
        return self._attempted_alternative_putdown

    @property
    def ideal_slot_type_set(self):
        put_down_strategy = self.get_put_down_strategy()
        return put_down_strategy.ideal_slot_type_set

    @componentmethod
    def get_carry_object_posture(self):
        if self.carry_affordances is None:
            return CarryPostureStaticTuning.POSTURE_CARRY_OBJECT
        return self.carry_affordances[0].provided_posture_type

    @componentmethod_with_fallback(lambda *_, **__: ())
    def get_allowed_hands(self, sim):
        return self.allowed_hands_data.get_allowed_hands(sim)

    @componentmethod_with_fallback(lambda *_, **__: 0)
    def get_portal_key_make_for_carry(self):
        return self.portal_key_mask_flags

    @componentmethod
    def should_unholster(self, *args, **kwargs):
        return self.unholster_when_routing.should_unholster(*args, **kwargs)

    @componentmethod
    def get_put_down_strategy(self, parent=DEFAULT):
        if self._cached_put_down_strategy is None:
            parent = self.owner.parent if parent is DEFAULT else parent
            species = parent.species if parent is not None else Species.HUMAN
            for (state_value, put_down_strategy
                 ) in self.state_based_put_down_tuning.items():
                if self.owner.state_value_active(state_value):
                    self._cached_put_down_strategy = put_down_strategy.get(
                        species)
                    break
            else:
                if self.put_down_tuning is not None:
                    self._cached_put_down_strategy = self.put_down_tuning.get(
                        species)
            if self._cached_put_down_strategy is None:
                put_down_strategy = parent.get_default_put_down_strategy()
                self._cached_put_down_strategy = put_down_strategy
        return self._cached_put_down_strategy

    def _get_carry_transition_distance_for_sim(self, sim):
        carry_sim = self.owner.sim_info
        carrying_sim = sim.sim_info
        if carry_sim.is_toddler:
            return self.DEFAULT_GEOMETRIC_TRANSITION_MEDIUM
        if carrying_sim.is_teen_or_older:
            return self.DEFAULT_GEOMETRIC_TRANSITION_LARGE
        if carry_sim.is_teen_or_older:
            return self.DEFAULT_GEOMETRIC_TRANSITION_SMALL
        return self.DEFAULT_GEOMETRIC_TRANSITION_TINY

    def _get_adjusted_circle_constraint(self, sim, constraint):
        if not self.owner.is_sim:
            return constraint
        if not isinstance(constraint, TunedCircle):
            return constraint
        ideal_radius_override = self._get_carry_transition_distance_for_sim(
            sim)
        constraint = copy.copy(constraint)
        constraint.ideal_radius_width = constraint.ideal_radius_width / constraint.ideal_radius * ideal_radius_override
        constraint.radius = constraint.radius / constraint.ideal_radius * ideal_radius_override
        constraint.ideal_radius = ideal_radius_override
        return constraint

    @componentmethod
    def get_carry_transition_constraint(self,
                                        sim,
                                        position,
                                        routing_surface,
                                        cost=0,
                                        mobile=True):
        constraints = self.DEFAULT_GEOMETRIC_TRANSITION_CONSTRAINT
        constraints = constraints.constraint_mobile if mobile else constraints.constraint_non_mobile
        final_constraint = Anywhere()
        for constraint in constraints:
            if mobile:
                constraint = self._get_adjusted_circle_constraint(
                    sim, constraint)
            final_constraint = final_constraint.intersect(
                constraint.create_constraint(None,
                                             None,
                                             target_position=position,
                                             routing_surface=routing_surface))
        final_constraint = final_constraint.generate_constraint_with_cost(cost)
        final_constraint = final_constraint._copy(_multi_surface=True)
        return final_constraint

    @componentmethod
    def get_pick_up_constraint(self, sim):
        if self.constraint_pick_up is None:
            return
        final_constraint = Anywhere()
        for constraint in self.constraint_pick_up:
            constraint = self._get_adjusted_circle_constraint(sim, constraint)
            constraint = constraint.create_constraint(sim, target=self.owner)
            final_constraint = final_constraint.intersect(constraint)
        final_constraint = final_constraint._copy(_multi_surface=True)
        return final_constraint

    @componentmethod
    def get_provided_aops_gen(self, target, context, **kwargs):
        for provided_affordance_data in self.provided_affordances:
            if not provided_affordance_data.affordance.is_affordance_available(
                    context=context):
                continue
            if not provided_affordance_data.object_filter.is_object_valid(
                    target):
                continue
            if provided_affordance_data.affordance.is_social and not target.is_sim:
                affordance = provided_affordance_data.affordance
                interaction_target = self.owner
                preferred_objects = (target, )
            else:
                affordance = CarryTargetInteraction.generate(
                    provided_affordance_data.affordance, self.owner)
                interaction_target = target
                preferred_objects = ()
            depended_on_si = None
            parent = self.owner.parent
            if parent is not None:
                if parent.is_sim:
                    carry_posture = parent.posture_state.get_carry_posture(
                        self.owner)
                    if carry_posture is not None:
                        if provided_affordance_data.is_linked:
                            depended_on_si = carry_posture.source_interaction
            yield from affordance.potential_interactions(
                interaction_target,
                context,
                depended_on_si=depended_on_si,
                preferred_objects=preferred_objects,
                **kwargs)

    def component_super_affordances_gen(self, **kwargs):
        if self.carry_affordances is None:
            affordances = self.DEFAULT_CARRY_AFFORDANCES
        else:
            affordances = self.carry_affordances
        for affordance in affordances:
            yield affordance

    def component_interactable_gen(self):
        yield self

    def on_state_changed(self, state, old_value, new_value, from_init):
        if new_value in self.state_based_put_down_tuning or old_value in self.state_based_put_down_tuning:
            self._cached_put_down_strategy = None

    def component_reset(self, reset_reason):
        self.reset_put_down_count()

    @componentmethod
    def get_initial_put_down_position(self, carrying_sim=None):
        carrying_sim = carrying_sim or self.owner.parent
        if carrying_sim is None:
            return (self.owner.position, self.owner.routing_surface)
        additional_put_down_distance = carrying_sim.posture.additional_put_down_distance
        position = carrying_sim.position + carrying_sim.forward * (
            carrying_sim.object_radius + additional_put_down_distance)
        sim_los_constraint = carrying_sim.lineofsight_component.constraint
        if not sims4.geometry.test_point_in_compound_polygon(
                position, sim_los_constraint.geometry.polygon):
            position = carrying_sim.position
        return (position, carrying_sim.routing_surface)

    @componentmethod
    def get_put_down_aop(self,
                         interaction,
                         context,
                         alternative_multiplier=1,
                         own_inventory_multiplier=1,
                         object_inventory_multiplier=DEFAULT,
                         in_slot_multiplier=DEFAULT,
                         on_floor_multiplier=1,
                         visibility_override=None,
                         display_name_override=None,
                         additional_post_run_autonomy_commodities=None,
                         add_putdown_liability=False,
                         **kwargs):
        sim = interaction.sim
        owner = self.owner
        if owner.transient:
            return self._get_destroy_aop(sim, **kwargs)
        put_down_strategy = self.get_put_down_strategy(parent=sim)
        if object_inventory_multiplier is DEFAULT:
            object_inventory_multiplier = sim.get_put_down_object_inventory_cost_override(
            )
        if in_slot_multiplier is DEFAULT:
            in_slot_multiplier = sim.get_put_down_slot_cost_override()
        slot_types_and_costs = self.get_slot_types_and_costs(
            multiplier=in_slot_multiplier)
        (terrain_transform,
         terrain_routing_surface) = self._get_terrain_transform(interaction)
        objects = self._get_objects_with_inventory(interaction)
        objects = [obj for obj in objects if obj.can_access_for_putdown(sim)]
        if put_down_strategy.floor_cost is not None and on_floor_multiplier is not None:
            world_cost = put_down_strategy.floor_cost * on_floor_multiplier
        else:
            world_cost = None
        if put_down_strategy.inventory_cost is not None and own_inventory_multiplier is not None:
            sim_inventory_cost = put_down_strategy.inventory_cost * own_inventory_multiplier
        else:
            sim_inventory_cost = None
        if put_down_strategy.object_inventory_cost is not None and object_inventory_multiplier is not None:
            object_inventory_cost = put_down_strategy.object_inventory_cost * object_inventory_multiplier
        else:
            object_inventory_cost = None
        if not put_down_strategy.affordances:
            self._attempted_alternative_putdown = True
        if not self._attempted_alternative_putdown or self.owner.is_sim:
            self._attempted_alternative_putdown = True
            scored_aops = []
            for scored_aop in self._gen_affordance_score_and_aops(
                    interaction,
                    slot_types_and_costs=slot_types_and_costs,
                    world_cost=world_cost,
                    sim_inventory_cost=sim_inventory_cost,
                    object_inventory_cost=object_inventory_cost,
                    terrain_transform=terrain_transform,
                    terrain_routing_surface=terrain_routing_surface,
                    objects_with_inventory=objects,
                    visibility_override=visibility_override,
                    display_name_override=display_name_override,
                    additional_post_run_autonomy_commodities=
                    additional_post_run_autonomy_commodities,
                    multiplier=alternative_multiplier,
                    add_putdown_liability=add_putdown_liability):
                if scored_aop.aop.test(context):
                    scored_aops.append(scored_aop)
            if scored_aops:
                scored_aops.sort(key=operator.itemgetter(0))
                return scored_aops[-1].aop
        affordance = CarryableComponent.PUT_DOWN_ANYWHERE_AFFORDANCE
        if add_putdown_liability:
            liabilities = ((PutDownLiability.LIABILITY_TOKEN,
                            PutDownLiability(self.owner)), )
        else:
            liabilities = ()
        aop = AffordanceObjectPair(
            affordance,
            self.owner,
            affordance,
            None,
            slot_types_and_costs=slot_types_and_costs,
            world_cost=world_cost,
            sim_inventory_cost=sim_inventory_cost,
            object_inventory_cost=object_inventory_cost,
            terrain_transform=terrain_transform,
            terrain_routing_surface=terrain_routing_surface,
            objects_with_inventory=objects,
            visibility_override=visibility_override,
            display_name_override=display_name_override,
            additional_post_run_autonomy_commodities=
            additional_post_run_autonomy_commodities,
            liabilities=liabilities,
            **kwargs)
        self._attempted_putdown = True
        return aop

    def _gen_affordance_score_and_aops(
            self,
            interaction,
            slot_types_and_costs,
            world_cost,
            sim_inventory_cost,
            object_inventory_cost,
            terrain_transform,
            terrain_routing_surface,
            objects_with_inventory,
            visibility_override,
            display_name_override,
            additional_post_run_autonomy_commodities,
            multiplier=1,
            add_putdown_liability=False):
        put_down_strategy = self.get_put_down_strategy()
        for affordance in put_down_strategy.affordances:
            if add_putdown_liability:
                liabilities = ((PutDownLiability.LIABILITY_TOKEN,
                                PutDownLiability(self.owner)), )
            else:
                liabilities = ()
            aop = AffordanceObjectPair(
                affordance,
                self.owner,
                affordance,
                None,
                slot_types_and_costs=slot_types_and_costs,
                world_cost=world_cost,
                sim_inventory_cost=sim_inventory_cost,
                object_inventory_cost=object_inventory_cost,
                terrain_transform=terrain_transform,
                terrain_routing_surface=terrain_routing_surface,
                objects_with_inventory=objects,
                visibility_override=visibility_override,
                display_name_override=display_name_override,
                additional_post_run_autonomy_commodities=
                additional_post_run_autonomy_commodities,
                liabilities=liabilities)
            yield ScoredAOP(multiplier, aop)

    def _get_cost_for_slot_type(self, slot_type):
        put_down_strategy = self.get_put_down_strategy()
        if slot_type in self.owner.ideal_slot_types:
            return put_down_strategy.preferred_slot_cost
        return put_down_strategy.normal_slot_cost

    def get_slot_types_and_costs(self, multiplier=1):
        slot_types_and_costs = []
        for slot_type in self.owner.all_valid_slot_types:
            cost = self._get_cost_for_slot_type(slot_type)
            if cost is not None and multiplier is not None:
                cost *= multiplier
            else:
                cost = None
            slot_types_and_costs.append((slot_type, cost))
        return slot_types_and_costs

    def _get_terrain_transform(self, interaction):
        if not self.owner.is_sim and self.owner.footprint_component is None:
            return (None, None)
        else:
            sim = interaction.sim
            put_down_position = interaction.interaction_parameters.get(
                'put_down_position')
            put_down_routing_surface = interaction.interaction_parameters.get(
                'put_down_routing_surface')
            if put_down_position is None:
                (starting_position, starting_routing_surface
                 ) = self.get_initial_put_down_position(carrying_sim=sim)
            else:
                starting_position = put_down_position
                starting_routing_surface = put_down_routing_surface
            starting_location = placement.create_starting_location(
                position=starting_position,
                orientation=sim.orientation,
                routing_surface=starting_routing_surface)
            if self.owner.is_sim:
                search_flags = FGLSearchFlagsDefaultForSim | FGLSearchFlag.STAY_IN_CURRENT_BLOCK
                fgl_context_fn = functools.partial(
                    placement.create_fgl_context_for_sim,
                    search_flags=search_flags)
            else:
                search_flags = FGLSearchFlag.STAY_IN_CURRENT_BLOCK | FGLSearchFlag.SHOULD_TEST_ROUTING | FGLSearchFlag.CALCULATE_RESULT_TERRAIN_HEIGHTS | FGLSearchFlag.DONE_ON_MAX_RESULTS | FGLSearchFlag.SHOULD_TEST_BUILDBUY
                fgl_context_fn = functools.partial(
                    placement.create_fgl_context_for_object,
                    search_flags=search_flags)
            MAX_PUTDOWN_STEPS = 8
            MAX_PUTDOWN_DISTANCE = 10
            fgl_context = fgl_context_fn(
                starting_location,
                self.owner,
                max_steps=MAX_PUTDOWN_STEPS,
                max_distance=MAX_PUTDOWN_DISTANCE,
                height_tolerance=self.put_down_height_tolerance)
            (position, orientation) = placement.find_good_location(fgl_context)
            if position is not None:
                put_down_transform = sims4.math.Transform(
                    position, orientation)
                return (put_down_transform, starting_routing_surface)
        return (None, None)

    def _get_objects_with_inventory(self, interaction):
        objects = []
        inventory_item = self.owner.inventoryitem_component
        if inventory_item is not None:
            if CarryableComponent.PUT_IN_INVENTORY_AFFORDANCE is not None:
                for obj in inventory_item.valid_object_inventory_gen():
                    objects.append(obj)
        return objects

    def _get_destroy_aop(self, sim, **kwargs):
        affordance = CarryableComponent.PUT_DOWN_HERE_AFFORDANCE
        return AffordanceObjectPair(affordance,
                                    self.owner,
                                    affordance,
                                    None,
                                    put_down_transform=None,
                                    **kwargs)

    def reset_put_down_count(self):
        self._attempted_alternative_putdown = False
        self._attempted_putdown = False
        self._cached_put_down_strategy = None

    def on_object_carry(self, actor, *_, **__):
        if self.reslot_plumbbob is not None:
            reslot_plumbbob(actor, self.reslot_plumbbob)

    def on_object_uncarry(self, actor, *_, **__):
        if self.reslot_plumbbob is not None:
            unslot_plumbbob(actor)
Exemplo n.º 27
0
class _BehaviorActionRunInteraction(_BehaviorAction):
    FACTORY_TUNABLES = {'affordance': TunableReference(description='\n            The interaction to push.\n            ', manager=services.affordance_manager()), 'cancel_trigger_interaction': Tunable(description="\n            If this is checked, once this interaction has completed, we'll\n            attempt to cancel the triggering interaction. If multiple\n            interactions are triggered (e.g. by multiple behaviors or multiple\n            slaves), the last interaction to complete cancels the interaction.\n            ", tunable_type=bool, default=False)}

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

    def execute_behavior_action(self, resolver=None, **event_data):
        for si in self._slave.si_state:
            if si.get_liability(_BehaviorActionRunInteractionLiability.LIABILITY_TOKEN) is not None:
                return
        context = InteractionContext(self._slave, InteractionContext.SOURCE_SCRIPT, Priority.Low)
        result = self._slave.push_super_affordance(self.affordance, None, context)
        if not result:
            return
        self._interaction = result.interaction
        cancel_trigger_liability = None
        if self.cancel_trigger_interaction:
            trigger_interaction = resolver.interaction if resolver is not None else None
            if trigger_interaction is not None:
                cancel_trigger_liability = trigger_interaction.get_liability(_BehaviorActionCancelInteractionLiability.LIABILITY_TOKEN)
                if cancel_trigger_liability is None:
                    cancel_trigger_liability = _BehaviorActionCancelInteractionLiability(trigger_interaction)
                    trigger_interaction.add_liability(_BehaviorActionCancelInteractionLiability.LIABILITY_TOKEN, cancel_trigger_liability)
                cancel_trigger_liability.add_triggered_interaction()
        liability = _BehaviorActionRunInteractionLiability(self, cancel_trigger_liability)
        self._interaction.add_liability(_BehaviorActionRunInteractionLiability.LIABILITY_TOKEN, liability)

    def stop_behavior_action(self, *, from_release):
        if from_release:
            return
        if self._interaction is not None and not self._interaction.is_finishing:
            self._interaction.cancel(FinishingType.NATURAL, cancel_reason_msg='Slaved Sim required to route.')
Exemplo n.º 28
0
class _BehaviorTriggerInteractionStart(_BehaviorTrigger):
    FACTORY_TUNABLES = {'affordance': TunableReference(description='\n            The trigger is fired if the master runs this specific interaction.\n            ', manager=services.affordance_manager())}

    def get_events(self):
        return (TestEvent.InteractionStart,)

    def _callback(self, resolver):
        if resolver.interaction is None:
            return
        if resolver.interaction.get_interaction_type() is not self.affordance:
            return
        return super()._callback(resolver=resolver)
Exemplo n.º 29
0
class CurfewComponent(Component,
                      HasTunableFactory,
                      AutoFactoryInit,
                      component_name=CURFEW_COMPONENT):
    FACTORY_TUNABLES = {
        'curfew_state_reference':
        TunableStateTypeReference(
            description=
            '\n            This is a reference to the State type we will be manipulating when\n            we change states on this object.\n            '
        ),
        'times_state_reference':
        TunableStateTypeReference(
            description=
            '\n            This is a reference to the State type we will be manipulating when\n            we change states on this object.\n            '
        ),
        'curfew_not_set':
        TunableStateValueReference(
            description=
            '\n            This is the reference to the state to apply on the owning object\n            when there is no active curfew setting. Or the setting is UNSET.\n            '
        ),
        'curfew_warning_state':
        TunableStateValueReference(
            description=
            '\n            This is the reference to the state to apply to the owning object\n            when the curfew is about to start.\n            '
        ),
        'curfew_past_state':
        TunableStateValueReference(
            description=
            '\n            This is the reference to the state to apply to the owning object\n            when curfew is active.\n            '
        ),
        'curfew_on_state':
        TunableStateValueReference(
            description=
            '\n            This is the reference to the state to apply to the owning object\n            when the curfew is set but not currently active.\n            '
        ),
        'not_set_state':
        TunableStateValueReference(
            description=
            "\n            This is the reference to the state to apply to the owning object\n            when there isn't a curfew set at all.\n            "
        ),
        'times_set':
        TunableMapping(
            description=
            '\n            This is a Mapping of time (in military time) to state to apply to\n            the owning object in order to display the correct time that the\n            curfew is set for.\n            ',
            key_type=int,
            value_type=TunableStateValueReference()),
        'set_curfew_affordances':
        TunableList(
            description=
            '\n            A List of the interactions that will be used to set the curfew\n            via this object.\n            ',
            tunable=TunableReference(
                description=
                '\n              This is the interaction that will be used to "set" the curfew.\n                ',
                manager=services.affordance_manager(),
                class_restrictions=('SuperInteraction', )))
    }

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

    def on_add(self):
        curfew_service = services.get_curfew_service()
        current_curfew = curfew_service.get_zone_curfew(
            services.current_zone_id())
        if current_curfew not in self.times_set:
            pass
        self.apply_state_for_setting(current_curfew)
        self.apply_warning_state(current_curfew)
        self._register_for_alarms(curfew_service)

    def on_remove(self):
        curfew_service = services.get_curfew_service()
        self._unregister_for_alarms(curfew_service)

    def component_super_affordances_gen(self, **kwargs):
        yield from self.set_curfew_affordances

    def update_states(self, curfew_setting):
        if curfew_setting == self._current_curfew_setting:
            return
        self.apply_state_for_setting(curfew_setting)
        self.apply_warning_state(curfew_setting)

    def apply_state_for_setting(self, setting):
        if setting is CurfewService.UNSET:
            self.owner.set_state(self.times_state_reference,
                                 self.not_set_state)
        state_to_apply = self.times_set.get(setting)
        if state_to_apply is not None:
            self.owner.set_state(self.times_state_reference, state_to_apply)

    def apply_warning_state(self, curfew_setting):
        if curfew_setting is CurfewService.UNSET:
            self.owner.set_state(self.curfew_state_reference,
                                 self.curfew_not_set)
            return
        now = services.time_service().sim_now.hour()
        if now >= CurfewService.CURFEW_END_TIME and now < curfew_setting:
            self._on_curfew_over_alarm()
        elif now == curfew_setting - 1:
            self._on_warning_time_alarm()
        else:
            self._on_curfew_started_alarm()

    def _register_for_alarms(self, curfew_service):
        curfew_service.register_for_alarm_callbacks(
            self._on_warning_time_alarm, self._on_curfew_started_alarm,
            self._on_curfew_over_alarm, self.update_states)

    def _unregister_for_alarms(self, curfew_service):
        curfew_service.unregister_for_alarm_callbacks(
            self._on_warning_time_alarm, self._on_curfew_started_alarm,
            self._on_curfew_over_alarm, self.update_states)

    def _on_warning_time_alarm(self):
        self.owner.set_state(self.curfew_state_reference,
                             self.curfew_warning_state,
                             force_update=True)

    def _on_curfew_started_alarm(self):
        self.owner.set_state(self.curfew_state_reference,
                             self.curfew_past_state,
                             force_update=True)

    def _on_curfew_over_alarm(self):
        self.owner.set_state(self.curfew_state_reference,
                             self.curfew_on_state,
                             force_update=True)
Exemplo n.º 30
0
 def __init__(self, target_default=ParticipantType.Object, locked_args={}, carry_target_default=ParticipantType.Object, **kwargs):
     super().__init__(TunableTuple(affordance=TunableReference(services.affordance_manager(), description='The affordance to push as a continuation on the actor for this SI.'), si_affordance_override=TunableReference(services.affordance_manager(), description="When the tuned affordance is a mixer for a different SI, use this to specify the mixer's appropriate SI. This is useful for pushing socials."), actor=TunableEnumEntry(ParticipantType, ParticipantType.Actor, description='The Sim on which the affordance is pushed.'), target=TunableEnumEntry(ParticipantType, target_default, description='The participant the affordance will target.'), carry_target=OptionalTunable(TunableEnumEntry(ParticipantType, carry_target_default, description='The participant the affordance will set as a carry target.')), locked_args=locked_args), **kwargs)
class ObjectRelationshipInteraction(ImmediateSuperInteraction):
    INSTANCE_TUNABLES = {
        'object_variant_mapping':
        TunableMapping(
            description=
            '\n            Map of the possible object relationship tracks, each representing\n            an object, and the associated interaction that will be pushed when \n            selected.\n            ',
            key_type=TunableReference(
                manager=services.statistic_manager(),
                class_restrictions='ObjectRelationshipTrack',
                pack_safe=True),
            value_type=TunableReference(manager=services.affordance_manager(),
                                        class_restrictions='SuperInteraction',
                                        pack_safe=True)),
        'custom_name_string_wrapper':
        OptionalTunable(
            description=
            '\n            If tuned, if the object relationship name has been set\n            with the name component, then the display name of the interaction\n            will be wrapped into this string.\n            \n            It should be written like this, with the object name\n            token indexed at 0:\n            "Summon 0.String" \n            ',
            tunable=TunableLocalizedStringFactory())
    }

    def __init__(self, aop, context, track=None, **kwargs):
        super().__init__(aop, context, **kwargs)
        self.rel_track = track

    @flexmethod
    def _get_name(cls,
                  inst,
                  target=DEFAULT,
                  context=DEFAULT,
                  track=None,
                  **interaction_parameters):
        if track is None:
            return inst.create_localized_string(inst.display_name)
        tag_set = None
        if track in ObjectRelationshipTrack.OBJECT_BASED_FRIENDSHIP_TRACKS:
            tag_set = ObjectRelationshipTrack.OBJECT_BASED_FRIENDSHIP_TRACKS[
                track]
        if tag_set is not None:
            relationship_service = services.relationship_service()
            relationship = relationship_service.get_object_relationship(
                context.sim.id, tag_set)
            if relationship is not None:
                object_name = relationship.get_object_rel_name()
                if object_name:
                    if cls.custom_name_string_wrapper is not None:
                        return cls.custom_name_string_wrapper(
                            LocalizationHelperTuning.get_raw_text(object_name))
                    return LocalizationHelperTuning.get_raw_text(object_name)
        if track in cls.object_variant_mapping:
            return cls.create_localized_string(
                cls.object_variant_mapping[track].display_name,
                context=context,
                target=target)
        return inst.create_localized_string(inst.display_name)

    @classmethod
    def potential_interactions(cls,
                               target,
                               context,
                               from_inventory_to_owner=False,
                               **kwargs):
        if not cls.allow_autonomous and context.source == InteractionSource.AUTONOMY:
            return ()
            yield
        for (rel_track, affordance) in cls.object_variant_mapping.items():
            tag_set = None
            tag_set = ObjectRelationshipTrack.OBJECT_BASED_FRIENDSHIP_TRACKS[
                rel_track]
            if not rel_track in ObjectRelationshipTrack.OBJECT_BASED_FRIENDSHIP_TRACKS or tag_set is not None:
                result = affordance.test(target=target, context=context)
                if result or result.tooltip is not None:
                    yield AffordanceObjectPair(
                        cls,
                        target,
                        cls,
                        None,
                        track=rel_track,
                        from_inventory_to_owner=from_inventory_to_owner)

    @flexmethod
    def test(cls,
             inst,
             target=DEFAULT,
             context=DEFAULT,
             super_interaction=None,
             skip_safe_tests=False,
             **interaction_parameters):
        rel_track = interaction_parameters.get('track')
        if rel_track is not None and rel_track in cls.object_variant_mapping:
            affordance = cls.object_variant_mapping[rel_track].affordance
            if affordance is not None:
                return affordance.test(target=target, context=context)

    def _run_interaction_gen(self, timeline):
        if self.rel_track is None:
            return False
            yield
        context = InteractionContext(self.sim,
                                     InteractionContext.SOURCE_PIE_MENU,
                                     Priority.High)
        result = self.sim.push_super_affordance(
            self.object_variant_mapping[self.rel_track], self.target, context)
        return True
        yield
Exemplo n.º 32
0
def generate_animation_element_data(*args, zone_id:int=None, **kwargs):
    affordance_manager = services.affordance_manager()
    animation_element_data = []
    for (animation_element, usage) in get_animation_reference_usage().items():
        animation_element_data.append({'animation_element_name': animation_element.__name__, 'count_interaction': usage[InteractionAsmType.Interaction], 'count_outcome': usage[InteractionAsmType.Outcome], 'count_response': usage[InteractionAsmType.Response], 'count_reactionlet': usage[InteractionAsmType.Reactionlet], 'count_total': sum(count for count in usage.values())})
    return animation_element_data
Exemplo n.º 33
0
AFFORDANCE_FILTER = 'affordance_filter'
AFFORDANCE_LIST = 'affordance_list'
ANIMATION = 'animation'
ANIMATION_LIST = 'animation_list'
ANIMATION_TRIPLET = 'animation_triplet'
ANIMATION_TRIPLET_LIST = 'animation_triplet_list'
COLOR = 'color'
POSTURE_TYPE_LIST = 'posture_type_list'
OBJECT_LIST = 'objects_list'
VENUE_LIST = 'venue_list'
SCREEN_SLAM = 'screen_slam'
(TunableAffordanceListReference,
 TunableAffordanceListSnippet) = define_snippet(
     AFFORDANCE_LIST,
     TunableList(TunableReference(services.affordance_manager(),
                                  needs_tuning=True)))
(TunableVenueListReference, TunableVenueListSnippet) = define_snippet(
    VENUE_LIST,
    TunableList(TunableReference(manager=services.get_instance_manager(
        sims4.resources.Types.VENUE),
                                 tuning_group=GroupNames.VENUES)))


class _TunableAffordanceFilter(TunableFactory, is_fragment=True):
    __qualname__ = '_TunableAffordanceFilter'

    @staticmethod
    def _filter(affordance, default_inclusion, affordance_types=None):
        affordance = affordance.affordance
        include_all_by_default = default_inclusion.include_all_by_default
Exemplo n.º 34
0
AFFORDANCE_FILTER = 'affordance_filter'
AFFORDANCE_LIST = 'affordance_list'
ANIMATION = 'animation'
ANIMATION_LIST = 'animation_list'
ANIMATION_TRIPLET = 'animation_triplet'
ANIMATION_TRIPLET_LIST = 'animation_triplet_list'
COLOR = 'color'
POSTURE_TYPE_LIST = 'posture_type_list'
OBJECT_LIST = 'objects_list'
VENUE_LIST = 'venue_list'
SCREEN_SLAM = 'screen_slam'
ANIMATION_ACTOR_MAP = 'animation_actor_map'
MUSIC_TRACK_DATA = 'music_track_data'
CUSTOM_STATES_SITUATION_STATE = 'custom_states_situation_state'
(TunableAffordanceListReference, TunableAffordanceListSnippet) = define_snippet(AFFORDANCE_LIST, TunableList(TunableReference(services.affordance_manager(), pack_safe=True)))
(TunableVenueListReference, TunableVenueListSnippet) = define_snippet(VENUE_LIST, TunableList(TunableReference(manager=services.get_instance_manager(sims4.resources.Types.VENUE), pack_safe=True, tuning_group=GroupNames.VENUES)))

class _TunableAffordanceFilter(TunableFactory, is_fragment=True):

    @staticmethod
    def _filter(affordance, default_inclusion, affordance_types=None, allow_ignore_exclude_all=False):
        affordance = affordance.affordance
        if affordance_types is None:
            if hasattr(affordance, '__mro__'):
                affordance_types = set(affordance.__mro__)
            else:
                affordance_types = {affordance}
        excluded_affordances = set(default_inclusion.exclude_affordances)
        for affordance_list in default_inclusion.exclude_lists:
            excluded_affordances.update(affordance_list)
 def __init__(self, description='Holds information about carrying and putting down an object.', **kwargs):
     super().__init__(put_down_tuning=TunableVariant(reference=TunableReference(description='\n                    Tuning for how to score where a Sim might want to set an\n                    object down.\n                    ', manager=services.get_instance_manager(sims4.resources.Types.STRATEGY)), literal=TunablePutDownStrategy().TunableFactory(), default='literal'), state_based_put_down_tuning=TunableMapping(description='\n                A mapping from a state value to a putdownstrategy. If the\n                owning object is in any of the states tuned here, it will use\n                that state\'s associated putdownstrategy in place of the one\n                putdownstrategy tuned in the "put_down_tuning" field. If the\n                object is in multiple states listed in this mapping, the\n                behavior is undefined.\n                ', key_type=TunableReference(description='\n                    The state value this object must be in in order to use the\n                    associated putdownstrategy.\n                    ', manager=services.get_instance_manager(sims4.resources.Types.OBJECT_STATE)), value_type=TunableVariant(reference=TunableReference(description='\n                        Tuning for how to score where a Sim might want to set\n                        an object down.\n                        ', manager=services.get_instance_manager(sims4.resources.Types.STRATEGY)), literal=TunablePutDownStrategy().TunableFactory()), key_name='State', value_name='PutDownStrategy'), carry_affordances=OptionalTunable(TunableList(TunableReference(description='\n                    The versions of the HoldObject affordance that this object\n                    supports.\n                    ', manager=services.affordance_manager())), disabled_name='use_default_affordances', enabled_name='use_custom_affordances'), provided_affordances=TunableList(description='\n                A list of affordances that are generated when a Sim holding\n                this object selects another Sim to interact with. The generated\n                interactions will target the selected Sim but will have this\n                object set as their carry target.\n                ', tunable=TunableReference(manager=services.affordance_manager())), constraint_pick_up=OptionalTunable(description='\n                A list of constraints that must be fulfilled in order to\n                interact with this object.\n                ', tunable=TunableList(tunable=interactions.constraints.TunableConstraintVariant(description='\n                        A constraint that must be fulfilled in order to\n                        interact with this object.\n                        '))), allowed_hands=TunableVariant(locked_args={'both': (Hand.LEFT, Hand.RIGHT), 'left_only': (Hand.LEFT,), 'right_only': (Hand.RIGHT,)}, default='both'), holster_while_routing=Tunable(description='\n                If True, the Sim will holster the object before routing and\n                unholster when the route is complete.\n                ', tunable_type=bool, default=False), holster_compatibility=TunableAffordanceFilterSnippet(description='\n                Define interactions for which holstering this object is\n                explicitly disallowed.\n                \n                e.g. The Scythe is tuned to be holster-incompatible with\n                sitting, meaning that Sims will holster the Sctyhe when sitting.\n                '), unholster_on_long_route_only=Tunable(description='\n                If True, then the Sim will not unholster this object (assuming\n                it was previously holstered) unless a transition involving a\n                long route is about to happen.\n                \n                If False, then the standard holstering rules apply.\n                ', tunable_type=bool, default=False), prefer_owning_sim_inventory_when_not_on_home_lot=Tunable(description="\n                If checked, this object will highly prefer to be put into the\n                owning Sim's inventory when being put down by the owning Sim on\n                a lot other than their home lot.\n                \n                Certain objects, like consumables, should be exempt from this.\n                ", tunable_type=bool, default=True), description=description, **kwargs)