def on_activate(self, reader=None):
     super().on_activate(reader)
     leader_sim = self.owner.initiating_sim_info.get_sim_instance()
     if leader_sim is None:
         self.owner._self_destruct()
     members = list(self.owner.all_sims_in_situation_gen())
     constraint_affordance = self.owner.constraint_affordance
     follower_sim_ids = set()
     for sim in members:
         if sim is leader_sim:
             if not sim.si_state.is_running_affordance(
                     self.owner.constraint_leader_affordance):
                 self.owner.remove_sim_from_situation(sim)
                 if not sim.si_state.is_running_affordance(
                         constraint_affordance):
                     self.owner.remove_sim_from_situation(sim)
                 else:
                     follower_sim_ids.add(sim.id)
         elif not sim.si_state.is_running_affordance(constraint_affordance):
             self.owner.remove_sim_from_situation(sim)
         else:
             follower_sim_ids.add(sim.id)
     interaction_context = InteractionContext(
         leader_sim, InteractionSource.SCRIPT_WITH_USER_INTENT,
         Priority.High)
     aop = AffordanceObjectPair(self.owner.affordance,
                                self.owner._target_object,
                                self.owner.affordance,
                                None,
                                picked_item_ids=follower_sim_ids)
     aop.test_and_execute(interaction_context)
示例#2
0
 def _changed_state_callback(self, target, state, old_value, new_value):
     if new_value != Television.TV_OFF_STATE:
         context = self.context.clone_for_continuation(self)
         affordance = self.generate_continuation_affordance(new_value.affordance)
         aop = AffordanceObjectPair(affordance, self.target, affordance, None)
         aop.test_and_execute(context)
     self.cancel(FinishingType.OBJECT_CHANGED, cancel_reason_msg='state: interaction canceled on state change ({} != {})'.format(new_value.value, self.required_channel.value))
 def _count_callback(self, _):
     for sim in self.owner.all_sims_in_situation_gen():
         parent_si = sim.si_state.get_si_by_affordance(
             self.countdown_affordance)
         if parent_si is not None:
             interaction_context = InteractionContext(
                 sim, InteractionSource.PIE_MENU, Priority.Critical)
             aop = AffordanceObjectPair(self.count_mixer, None,
                                        self.countdown_affordance,
                                        parent_si)
             aop.test_and_execute(interaction_context)
 def _route_sim(self, sim):
     interaction_context = InteractionContext(
         sim, InteractionSource.SCRIPT_WITH_USER_INTENT, Priority.High)
     leader_sim = self.initiating_sim_info.get_sim_instance()
     if leader_sim is sim:
         affordance = self.constraint_leader_affordance
     else:
         affordance = self.constraint_affordance
     aop = AffordanceObjectPair(affordance, self._target_object, affordance,
                                None)
     aop.test_and_execute(interaction_context)
     self._routing_sims.append(sim.id)
示例#5
0
            def run_age_up(kid):
                def age_up_exit_behavior():
                    new_bassinet = create_object(
                        Baby.get_corresponding_definition(
                            middle_bassinet.definition))
                    new_bassinet.location = middle_bassinet.location
                    middle_bassinet.make_transient()

                kid.fade_opacity(1, 0)
                kid.visibility = VisibilityState(False)
                affordance = Baby.BABY_AGE_UP.age_up_affordance
                aop = AffordanceObjectPair(
                    affordance,
                    middle_bassinet,
                    affordance,
                    None,
                    exit_functions=(age_up_exit_behavior, ))
                context = InteractionContext(
                    kid,
                    InteractionSource.SCRIPT,
                    interactions.priority.Priority.Critical,
                    insert_strategy=QueueInsertStrategy.NEXT)
                result = aop.test_and_execute(context)
                if result:
                    result.interaction.add_liability(
                        AGING_LIABILITY, AgingLiability(sim_info, Age.BABY))
                else:
                    logger.error('Failed to run baby age up interaction.',
                                 owner='jjacobson')
                return True
 def _run_obstacle_course_autonomy_request(self, timeline):
     try:
         selected_interaction = yield from services.autonomy_service(
         ).find_best_action_gen(
             timeline,
             self._autonomy_request,
             randomization_override=AutonomyRandomization.DISABLED)
     finally:
         self._autonomy_request_handle = None
     if self.owner is None:
         return False
         yield
     if selected_interaction is not None:
         selected_interaction.invalidate()
         affordance = selected_interaction.affordance
         aop = AffordanceObjectPair(affordance, selected_interaction.target,
                                    affordance, None)
         result = aop.test_and_execute(self._interaction_context)
         if not result:
             return result
             yield
         self.owner.continue_course()
         return True
         yield
     self.owner.finish_course()
     return True
     yield
示例#7
0
 def _on_spawn(sim):
     affordance = bassinet.get_age_up_addordance()
     aop = AffordanceObjectPair(affordance, middle_bassinet, affordance, None, is_baby_age_up=True)
     context = InteractionContext(sim, InteractionSource.SCRIPT, Priority.Critical, insert_strategy=QueueInsertStrategy.NEXT)
     result = aop.test_and_execute(context)
     if not result:
         logger.error('Failed to run baby age up interaction: {}', result, owner='jjacobson')
def push_travel_interaction(sim, from_zone_id, to_zone_id, callback, context):
    travel_affordance = TravelService.TRAVEL_AFFORDANCE
    travel_aop = AffordanceObjectPair(travel_affordance, None, travel_affordance, None, from_zone_id=from_zone_id, to_zone_id=to_zone_id, on_complete_callback=callback, on_complete_context=context)
    interaction_context = InteractionContext(sim, InteractionContext.SOURCE_PIE_MENU, Priority.High)
    if not travel_aop.test_and_execute(interaction_context):
        logger.error('Critical Failure: Failed to push travel affordance: {0} on sim: {1}', travel_affordance, sim, owner='mduke')
        callback(from_zone_id, sim.sim_info.sim_id, 0, context)
    else:
        services.travel_service().add_pending_travel(sim)
示例#9
0
 def on_activate(self, reader=None):
     super().on_activate(reader)
     dancers = list(self.owner.all_sims_in_situation_gen())
     constraint_affordance = self.owner.constraint_affordance
     for sim in dancers:
         if not sim.si_state.is_running_affordance(constraint_affordance):
             self.owner.remove_sim_from_situation(sim)
     leader_sim = self.owner.initiating_sim_info.get_sim_instance()
     interaction_context = InteractionContext(
         leader_sim, InteractionSource.SCRIPT_WITH_USER_INTENT,
         Priority.High)
     aop = AffordanceObjectPair(self.owner.dance_affordance,
                                None,
                                self.owner.dance_affordance,
                                None,
                                jig_object=self.owner._jig_object,
                                jig_part_index=0)
     aop.test_and_execute(interaction_context)
示例#10
0
 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)
示例#11
0
def solve_motive(stat_type, opt_sim:OptionalTargetParam=None, _connection=None):
    sim = get_optional_target(opt_sim, _connection)
    if sim is None or stat_type is None:
        sims4.commands.output('Unable to identify Sim or Motive - invalid arguments.', _connection)
        return
    stat = sim.commodity_tracker.get_statistic(stat_type)
    if stat is None:
        sims4.commands.output('Unable to motive {} on the Sim .'.format(stat_type), _connection)
        return
    if not sim.queue.can_queue_visible_interaction():
        sims4.commands.output('Interaction queue is full, cannot add anymore interactions.', _connection)
        return
    context = InteractionContext(sim, InteractionContext.SOURCE_AUTONOMY, priority.Priority.High, bucket=InteractionBucketType.DEFAULT)
    autonomy_request = autonomy.autonomy_request.AutonomyRequest(sim, autonomy_mode=autonomy.autonomy_modes.FullAutonomy, commodity_list=[stat], context=context, consider_scores_of_zero=True, posture_behavior=AutonomyPostureBehavior.IGNORE_SI_STATE, is_script_request=True, allow_opportunity_cost=False, autonomy_mode_label_override='AutoSolveMotive')
    selected_interaction = services.autonomy_service().find_best_action(autonomy_request)
    if selected_interaction is None:
        stat_str = '{}'.format(stat_type)
        commodity_interaction = CommodityTuning.BLADDER_SOLVING_FAILURE_INTERACTION
        if stat_str == "<class 'sims4.tuning.instances.motive_Energy'>":
            commodity_interaction = CommodityTuning.ENERGY_SOLVING_FAILURE_INTERACTION
        elif stat_str == "<class 'sims4.tuning.instances.motive_Fun'>":
            commodity_interaction = CommodityTuning.FUN_SOLVING_FAILURE_INTERACTION
        elif stat_str == "<class 'sims4.tuning.instances.motive_Hunger'>":
            commodity_interaction = CommodityTuning.HUNGER_SOLVING_FAILURE_INTERACTION
        elif stat_str == "<class 'sims4.tuning.instances.motive_Hygiene'>":
            commodity_interaction = CommodityTuning.HYGIENE_SOLVING_FAILURE_INTERACTION
        elif stat_str == "<class 'sims4.tuning.instances.motive_Social'>":
            commodity_interaction = CommodityTuning.SOCIAL_SOLVING_FAILURE_INTERACTION
        if not sim.queue.has_duplicate_super_affordance(commodity_interaction, sim, None):
            failure_aop = AffordanceObjectPair(commodity_interaction, None, commodity_interaction, None)
            failure_aop.test_and_execute(context)
        sims4.commands.output('Could not find a good interaction to solve {}.'.format(stat_type), _connection)
        return
    if sim.queue.has_duplicate_super_affordance(selected_interaction.affordance, sim, selected_interaction.target):
        sims4.commands.output('Duplicate Interaction in the queue.', _connection)
        return
    if not AffordanceObjectPair.execute_interaction(selected_interaction):
        sims4.commands.output('Failed to execute SI {}.'.format(selected_interaction), _connection)
        return
    sims4.commands.output('Successfully executed SI {}.'.format(selected_interaction), _connection)
示例#12
0
 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
示例#13
0
 def _apply_daycare_effects_to_sim(self, sim_info):
     self._excluded_sims.discard(sim_info)
     sim = services.object_manager().get(sim_info.id)
     if sim_info.is_baby:
         sim.empty_baby_state()
     elif sim_info.is_toddler:
         daycare_interaction = self._daycare_interactions.get(sim_info)
         if daycare_interaction is None:
             aop = AffordanceObjectPair(DaycareTuning.GO_TO_DAYCARE_INTERACTION, None, DaycareTuning.GO_TO_DAYCARE_INTERACTION, None)
             context = InteractionContext(sim, InteractionContext.SOURCE_SCRIPT, Priority.High, insert_strategy=QueueInsertStrategy.FIRST, must_run_next=True)
             execute_result = aop.test_and_execute(context)
             if execute_result:
                 self._daycare_interactions[sim_info] = execute_result.interaction
     return True
示例#14
0
            def run_age_up(kid):

                def age_up_exit_behavior():
                    new_bassinet = create_object(Baby.get_corresponding_definition(middle_bassinet.definition))
                    new_bassinet.location = middle_bassinet.location
                    middle_bassinet.make_transient()

                kid.fade_opacity(1, 0)
                kid.visibility = VisibilityState(False)
                affordance = Baby.BABY_AGE_UP.age_up_affordance
                aop = AffordanceObjectPair(affordance, middle_bassinet, affordance, None, exit_functions=(age_up_exit_behavior,))
                context = InteractionContext(kid, InteractionSource.SCRIPT, interactions.priority.Priority.Critical, insert_strategy=QueueInsertStrategy.NEXT)
                result = aop.test_and_execute(context)
                if result:
                    result.interaction.add_liability(AGING_LIABILITY, AgingLiability(sim_info, Age.BABY))
                else:
                    logger.error('Failed to run baby age up interaction.', owner='jjacobson')
                return True
 def _push_loss_on_player(self):
     motherplant = self._get_motherplant()
     for (sim, situation_sim) in self._situation_sims.items():
         if situation_sim.current_job_type is self.player_job:
             parent_si = sim.si_state.get_si_by_affordance(
                 self.fight_affordance)
             if parent_si is not None:
                 interaction_context = InteractionContext(
                     sim, InteractionSource.PIE_MENU, Priority.Critical)
                 aop = AffordanceObjectPair(self.loss_interaction_mixer,
                                            motherplant,
                                            self.fight_affordance,
                                            parent_si)
                 if not aop.test_and_execute(interaction_context):
                     logger.error(
                         'Attempting to push Motherplant Battle Ending Interaction, but failed.'
                     )
     self._push_interaction_on_all_helpers(self.helper_lose_affordance)
示例#16
0
def push_travel_interaction(sim, from_zone_id, to_zone_id, callback, context):
    travel_affordance = TravelService.TRAVEL_AFFORDANCE
    travel_aop = AffordanceObjectPair(travel_affordance,
                                      None,
                                      travel_affordance,
                                      None,
                                      from_zone_id=from_zone_id,
                                      to_zone_id=to_zone_id,
                                      on_complete_callback=callback,
                                      on_complete_context=context)
    interaction_context = InteractionContext(
        sim, InteractionContext.SOURCE_PIE_MENU, Priority.High)
    if not travel_aop.test_and_execute(interaction_context):
        logger.error(
            'Critical Failure: Failed to push travel affordance: {0} on sim: {1}',
            travel_affordance,
            sim,
            owner='mduke')
        callback(from_zone_id, sim.sim_info.sim_id, 0, context)
    else:
        services.travel_service().add_pending_travel(sim)
示例#17
0
 def _push_affordance(self,
                      sim,
                      affordance,
                      target,
                      depend_on_si,
                      priority=Priority.High,
                      must_run_next=True,
                      **kwargs):
     aop = AffordanceObjectPair(affordance,
                                target,
                                affordance,
                                None,
                                route_fail_on_transition_fail=False,
                                allow_posture_changes=True,
                                depend_on_si=depend_on_si,
                                **kwargs)
     context = InteractionContext(sim,
                                  InteractionContext.SOURCE_SCRIPT,
                                  priority,
                                  insert_strategy=QueueInsertStrategy.FIRST,
                                  must_run_next=must_run_next,
                                  group_id=depend_on_si.group_id
                                  if depend_on_si is not None else None)
     return aop.test_and_execute(context)
示例#18
0
 def _push_serve_affordance(self, order_sim, recipe):
     object_info = recipe.final_product
     context = self.context.clone_for_continuation(self)
     (deliver_affordance, target, deliver_part,
      carry_track) = self._pick_serve_affordance(order_sim, object_info,
                                                 context)
     if deliver_affordance is None:
         logger.error(
             '{} failed to find serve affordance to deliver final product.',
             self,
             owner='rmccord')
         return TestResult(
             False,
             'failed to find serve affordance to deliver final product')
     if object_info.carry_track != carry_track:
         aop_obj_info = object_info.clone_with_overrides(
             carry_track=carry_track)
     else:
         aop_obj_info = object_info
     self.process.ready_to_serve = True
     new_process = self.process.copy_for_serve_interaction(recipe)
     anim_overrides = self.process.phase.anim_overrides if self.process.phase is not None else None
     aop = AffordanceObjectPair(
         deliver_affordance,
         target,
         deliver_affordance,
         None,
         order_sim=order_sim,
         object_info=aop_obj_info,
         deliver_part=deliver_part,
         consume_affordance_override=self.consume_affordance_override,
         phase=self.process.phase,
         crafting_process=new_process,
         anim_overrides=anim_overrides)
     self._went_to_next_phase_or_finished_crafting = True
     return aop.test_and_execute(context)
    def _get_close_to_deploy(self, timeline, vehicle):
        sim = self._interaction.sim
        constraint = self._get_deployment_constraint()
        if not constraint.valid:
            return InteractionQueuePreparationStatus.FAILURE
            yield
        handles = constraint.get_connectivity_handles(sim)
        goals = []
        for handle in handles:
            goals.extend(handle.get_goals(single_goal_only=True))
        if not goals:
            return InteractionQueuePreparationStatus.FAILURE
            yield
        if sim.posture.unconstrained:
            source_constraint = Position(sim.position, routing_surface=sim.routing_surface)
        else:
            source_constraint = Circle(sim.position, self.SOURCE_CONNECTIVITY_HANDLE_RADIUS, sim.routing_surface)
        source_handles = source_constraint.get_connectivity_handles(sim)
        if not source_handles:
            return InteractionQueuePreparationStatus.FAILURE
            yield
        source_goals = source_handles[0].get_goals(single_goal_only=True)
        if not source_goals:
            return InteractionQueuePreparationStatus.FAILURE
            yield
        source_goal = source_goals[0]
        if source_goal.position == goals[0].position and source_goal.routing_surface_id == goals[0].routing_surface_id:
            return InteractionQueuePreparationStatus.SUCCESS
            yield
        route = routing.Route(source_goal.location, goals, routing_context=sim.routing_context)
        plan_primitive = PlanRoute(route, sim, interaction=self._interaction)
        result = yield from element_utils.run_child(timeline, plan_primitive)
        if not result and not (not plan_primitive.path.nodes and not plan_primitive.path.nodes.plan_success):
            return InteractionQueuePreparationStatus.FAILURE
            yield
        cur_path = plan_primitive.path
        if not cur_path.nodes:
            return InteractionQueuePreparationStatus.FAILURE
            yield

        def get_start_node_index_for_path(vehicle, path):
            nodes = list(path.nodes)
            object_manager = services.object_manager()
            prev_node = None
            for node in nodes[::-1]:
                portal_obj_id = node.portal_object_id
                portal_obj = object_manager.get(portal_obj_id) if portal_obj_id else None
                if node.portal_id:
                    if portal_obj:
                        if not vehicle.vehicle_component.can_transition_through_portal(portal_obj, node.portal_id):
                            break
                prev_node = node
            else:
                return 0
            return prev_node.index

        split_paths = False
        while cur_path.next_path is not None:
            split_paths = True
            cur_path = cur_path.next_path
            if not cur_path.nodes:
                return InteractionQueuePreparationStatus.FAILURE
                yield
        start_node_index = get_start_node_index_for_path(vehicle, cur_path)
        start_node = cur_path.nodes[start_node_index]
        start_location = sims4.math.Location(Transform(Vector3(*start_node.position), Quaternion(*start_node.orientation)), start_node.routing_surface_id)
        if not split_paths and start_node_index == 0 and (start_location.transform.translation - source_goal.location.position).magnitude_squared() < vehicle.vehicle_component.minimum_route_distance:
            return InteractionQueuePreparationStatus.SUCCESS
            yield
        deploy_constraint = Position(start_location.transform.translation, routing_surface=start_location.routing_surface)
        depended_on_si = self._interaction
        affordance = self.get_close_affordance if self.get_close_affordance is not None else VehicleLiability.GET_CLOSE_AFFORDANCE
        aop = AffordanceObjectPair(affordance, None, affordance, None, route_fail_on_transition_fail=False, constraint_to_satisfy=deploy_constraint, allow_posture_changes=True, depended_on_si=depended_on_si)
        context = InteractionContext(sim, InteractionContext.SOURCE_SCRIPT, Priority.High, insert_strategy=QueueInsertStrategy.FIRST, must_run_next=True, group_id=depended_on_si.group_id)
        if not aop.test_and_execute(context):
            return InteractionQueuePreparationStatus.FAILURE
            yield
        return InteractionQueuePreparationStatus.NEEDS_DERAIL
        yield
    def queue_social_mixer_interaction(
        sim_info: SimInfo,
        social_mixer_interaction_id: int,
        social_super_interaction_id: int,
        target: SimInfo=None,
        interaction_context: InteractionContext=None,
        **kwargs
    ) -> EnqueueResult:
        """queue_social_mixer_interaction(\
            sim_info,\
            social_mixer_interaction_id,\
            social_super_interaction_id,\
            target=None,\
            interaction_context=None,\
            **kwargs\
        )

        Push a Social Mixer Interaction into the queue of a Sim.

        :param sim_info: An instance of a Sim.
        :type sim_info: SimInfo
        :param social_mixer_interaction_id: The decimal identifier of a social mixer interaction.
        :type social_mixer_interaction_id: int
        :param social_super_interaction_id: The decimal identifier of a social super interaction to queue the social mixer interaction under.
        :type social_super_interaction_id: int
        :param target: The target of the interaction. Default is None.
        :type target: Any, optional
        :param interaction_context: The context to queue the interaction with. See also :func:`~create_interaction_context`. Default is None.
        :type interaction_context: InteractionContext, optional
        :return: The result of pushing the interaction to the queue of a Sim.
        :rtype: EnqueueResult
        """
        if social_super_interaction_id is not None and social_mixer_interaction_id is None:
            return CommonSimInteractionUtils.queue_super_interaction(social_super_interaction_id, target=target, interaction_context=interaction_context)
        sim = CommonSimUtils.get_sim_instance(sim_info)
        # noinspection PyTypeChecker
        super_affordance_instance = CommonInteractionUtils._load_interaction_instance(social_super_interaction_id)
        if super_affordance_instance is None:
            return EnqueueResult.NONE
        mixer_affordance_instance = CommonInteractionUtils._load_interaction_instance(social_mixer_interaction_id)
        if mixer_affordance_instance is None:
            return EnqueueResult.NONE

        def _get_existing_social_super_interaction(si_iter) -> Interaction:
            for si in si_iter:
                if si.super_affordance != super_affordance_instance:
                    continue
                if si.social_group is None:
                    continue
                target_sim = CommonSimUtils.get_sim_instance(target)
                if target_sim is not None and target_sim not in si.social_group:
                    continue
                return si.super_interaction

        interaction_context = interaction_context or CommonSimInteractionUtils.create_interaction_context(sim_info)
        super_interaction = _get_existing_social_super_interaction(sim.si_state) or _get_existing_social_super_interaction(sim.queue)
        if super_interaction is None:
            si_result = sim.push_super_affordance(
                super_affordance_instance,
                target,
                interaction_context,
                picked_object=target,
                **kwargs
            )
            if not si_result:
                return EnqueueResult.NONE
            super_interaction = si_result.interaction

        pick = super_interaction.context.pick
        preferred_objects = super_interaction.context.preferred_objects
        context = super_interaction.context.clone_for_continuation(
            super_interaction,
            insert_strategy=interaction_context.insert_strategy,
            source_interaction_id=super_interaction.id,
            source_interaction_sim_id=CommonSimUtils.get_sim_id(sim_info),
            pick=pick,
            preferred_objects=preferred_objects,
            must_run_next=interaction_context.must_run_next
        )
        aop = AffordanceObjectPair(
            mixer_affordance_instance,
            target,
            super_affordance_instance,
            super_interaction,
            picked_object=target,
            push_super_on_prepare=True
        )
        return aop.test_and_execute(context)
示例#21
0
def solve_motive(
        stat_type: TunableInstanceParam(sims4.resources.Types.STATISTIC,
                                        exact_match=True),
        opt_sim: OptionalTargetParam = None,
        _connection=None):
    sim = get_optional_target(opt_sim, _connection)
    if sim is None or stat_type is None:
        sims4.commands.output(
            'Unable to identify Sim or Motive - invalid arguments.',
            _connection)
        return
    if sim.commodity_tracker is None:
        sims4.commands.output(
            'Unable to solve motive - sim info has no commodity tracker.',
            _connection)
        return
    stat = sim.commodity_tracker.get_statistic(stat_type)
    if stat is None:
        sims4.commands.output(
            'Unable to solve motive {} on the Sim .'.format(stat_type),
            _connection)
        return
    if not sim.queue.can_queue_visible_interaction():
        sims4.commands.output(
            'Interaction queue is full, cannot add anymore interactions.',
            _connection)
        return
    context = InteractionContext(sim,
                                 InteractionContext.SOURCE_AUTONOMY,
                                 priority.Priority.High,
                                 bucket=InteractionBucketType.DEFAULT)
    autonomy_request = autonomy.autonomy_request.AutonomyRequest(
        sim,
        autonomy_mode=autonomy.autonomy_modes.FullAutonomy,
        commodity_list=[stat],
        context=context,
        consider_scores_of_zero=True,
        posture_behavior=AutonomyPostureBehavior.IGNORE_SI_STATE,
        is_script_request=True,
        allow_opportunity_cost=False,
        autonomy_mode_label_override='AutoSolveMotive')
    selected_interaction = services.autonomy_service().find_best_action(
        autonomy_request)
    if selected_interaction is None:
        commodity_interaction = stat_type.commodity_autosolve_failure_interaction
        if commodity_interaction is None:
            return
        if not sim.queue.has_duplicate_super_affordance(
                commodity_interaction, sim, None):
            failure_aop = AffordanceObjectPair(commodity_interaction, None,
                                               commodity_interaction, None)
            failure_aop.test_and_execute(context)
        sims4.commands.output(
            'Could not find a good interaction to solve {}.'.format(stat_type),
            _connection)
        return
    if sim.queue.has_duplicate_super_affordance(
            selected_interaction.affordance, sim, selected_interaction.target):
        sims4.commands.output('Duplicate Interaction in the queue.',
                              _connection)
        return
    if not AffordanceObjectPair.execute_interaction(selected_interaction):
        sims4.commands.output(
            'Failed to execute SI {}.'.format(selected_interaction),
            _connection)
        return
    sims4.commands.output(
        'Successfully executed SI {}.'.format(selected_interaction),
        _connection)