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)
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)
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
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)
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)
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)
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)
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
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
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)
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)
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)
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)
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)