def build_basic_elements(self, sequence=()): sequence = super().build_basic_elements(sequence=sequence) if self.super_interaction.social_group is not None: listen_animation_factory = self.super_interaction.listen_animation else: listen_animation_factory = None for group in self.sim.get_groups_for_sim_gen(): si = group.get_si_registered_for_sim(self.sim) while si is not None: listen_animation_factory = si.listen_animation break if listen_animation_factory is not None: for sim in self.required_sims(): if sim is self.sim: pass sequence = listen_animation_factory(sim.animation_interaction, sequence=sequence) sequence = with_skippable_animation_time((sim,), sequence=sequence) def defer_cancel_around_sequence_gen(s, timeline): deferred_sis = [] for sim in self.required_sims(): while not (sim is self.sim or self.social_group is None): if sim not in self.social_group: pass sis = self.social_group.get_sis_registered_for_sim(sim) while sis: deferred_sis.extend(sis) with self.super_interaction.cancel_deferred(deferred_sis): result = yield element_utils.run_child(timeline, s) return result sequence = functools.partial(defer_cancel_around_sequence_gen, sequence) if self.target_type & TargetType.ACTOR: return element_utils.build_element(sequence) if self.target_type & TargetType.TARGET and self.target is not None: sequence = self.social_group.with_target_focus(self.sim, self.sim, self.target, sequence) elif self.social_group is not None: sequence = self.social_group.with_social_focus(self.sim, self.sim, self.required_sims(), sequence) else: for social_group in self.sim.get_groups_for_sim_gen(): sequence = social_group.with_social_focus(self.sim, self.sim, self.required_sims(), sequence) communicable_buffs = collections.defaultdict(list) for sim in self.required_sims(): for buff in sim.Buffs: while buff.communicable: communicable_buffs_sim = communicable_buffs[sim] communicable_buffs_sim.append(buff) for (sim, communicable_buffs_sim) in communicable_buffs.items(): for other_sim in self.required_sims(): if other_sim is sim: pass resolver = DoubleSimResolver(sim.sim_info, other_sim.sim_info) for buff in communicable_buffs_sim: buff.communicable.apply_to_resolver(resolver) return element_utils.build_element(sequence)
def _run(self, timeline): if self.asm_key is None: return True asm = self.get_asm() if asm is None: return False if self.balloon_data is not None: sequence = self.animate_kwargs['sequence'] if sequence is not None: self.animate_kwargs['sequence'] = (sequence, build_element(self.create_balloon_request(self.owner))) else: self.animation_kwargs['sequence'] = build_element(self.create_balloon_request(self.owner)) return timeline.run_child(animate_states(asm, self.begin_states, self.end_states, repeat_begin_states=self.repeat, **self.animate_kwargs))
def build_basic_elements(self, sequence=()): sequence = super().build_basic_elements(sequence=sequence) if self.super_interaction.social_group is not None: listen_animation_factory = self.super_interaction.listen_animation else: listen_animation_factory = None for group in self.sim.get_groups_for_sim_gen(): si = group.get_si_registered_for_sim(self.sim) if si is not None: listen_animation_factory = si.listen_animation break if listen_animation_factory is not None: for sim in self.required_sims(): if sim is self.sim: continue sequence = listen_animation_factory(sim.animation_interaction, sequence=sequence) sequence = with_skippable_animation_time((sim, ), sequence=sequence) def defer_cancel_around_sequence_gen(s, timeline): deferred_sis = [] for sim in self.required_sims(): if not sim is self.sim: if not self.social_group is None: if sim not in self.social_group: continue sis = self.social_group.get_sis_registered_for_sim(sim) if sis: deferred_sis.extend(sis) with self.super_interaction.cancel_deferred(deferred_sis): result = yield from element_utils.run_child(timeline, s) return result yield sequence = functools.partial(defer_cancel_around_sequence_gen, sequence) if self.target_type & TargetType.ACTOR: return element_utils.build_element(sequence) if self.target_type & TargetType.TARGET and self.target is not None: if self.social_group is not None: sequence = self.social_group.with_target_focus( self.sim, self.sim, self.target, sequence) elif self.social_group is not None: sequence = self.social_group.with_social_focus( self.sim, self.sim, self.required_sims(), sequence) else: for social_group in self.sim.get_groups_for_sim_gen(): sequence = social_group.with_social_focus( self.sim, self.sim, self.required_sims(), sequence) return element_utils.build_element(sequence)
def change_age(self, new_age, current_age): self.age_progress = 0 self.apply_age(new_age) self.appearance_tracker.evaluate_appearance_modifiers() self.resend_physical_attributes() self._update_age_trait(new_age, current_age) self.career_tracker.add_ageup_careers() self.career_tracker.remove_invalid_careers() self.trait_tracker.remove_invalid_traits() if self.aspiration_tracker is not None: self.aspiration_tracker.remove_invalid_aspirations() self.update_skills_for_aging() add_quirks(self) sim_instance = self.get_sim_instance( allow_hidden_flags=ALL_HIDDEN_REASONS) if sim_instance is not None: with telemetry_helper.begin_hook(writer_age, TELEMETRY_CHANGE_AGE, sim=sim_instance) as hook: hook.write_enum('agef', current_age) hook.write_enum('aget', new_age) sim_instance.schedule_element( services.time_service().sim_timeline, build_element(sim_instance._update_face_and_posture_gen)) sim_instance._update_multi_motive_buff_trackers() sim_instance.update_portal_locks() sim_instance.update_rig() self.reset_age_progress() if not self.is_npc and self.whim_tracker is not None: self.whim_tracker.validate_goals() client = services.client_manager().get_client_by_household_id( self._household_id) if client is None: return client.selectable_sims.notify_dirty()
def get_visual_effect_sequence(self, vfx_element, sequence): def attach_liability(_): liability = _VisualEffectLifetimeContinuationLiability(vfx_element) vfx_element.interaction.add_liability(liability.LIABILITY_TOKEN, liability) return build_element((attach_liability, sequence))
def schedule_reset_asap(self, reset_reason=ResetReason.RESET_EXPECTED, source=None, cause=None): def call_reset(timeline): self.reset(reset_reason, source=source, cause=cause) element = build_element(call_reset) services.time_service().sim_timeline.schedule_asap(element)
def end_posture_on_same_track(timeline): if self._prev_posture is not None and self._prev_posture is not posture: prev_posture = self._prev_posture self._prev_posture = None result = yield element_utils.run_child(timeline, build_element(prev_posture.end())) return result return True
def _schedule_season_change(self): if self._season_change_handler is not None and not self._season_change_handler.is_active: self._season_change_handler.trigger_hard_stop() self._season_change_handler = self._season_timeline.schedule( build_element(( lambda _: self.advance_season(SeasonSetSource.PROGRESSION), )), self._season_content.end_time)
def get_auto_exit(actors, asm=None, interaction=None, required_actors=()): arb_exit = None contexts_to_release_all = [] for actor in actors: if actor.is_sim: if actor.asm_auto_exit.asm is not None: asm_to_exit = actor.asm_auto_exit.asm[0] if asm_to_exit is asm: continue if required_actors: asm_actors = set(asm_to_exit.actors_gen()) if not all(a in asm_actors for a in required_actors): continue else: if arb_exit is None: arb_exit = animation.arb.Arb() if interaction is not None: if gsi_handlers.interaction_archive_handlers.is_archive_enabled(interaction): prev_state = asm_to_exit.current_state try: asm_to_exit.request('exit', arb_exit, debug_context=(interaction, asm)) finally: if gsi_handlers.interaction_archive_handlers.is_archive_enabled(interaction): gsi_handlers.interaction_archive_handlers.add_animation_data(interaction, asm_to_exit, prev_state, 'exit', 'arb_exit is empty' if arb_exit.empty else arb_exit.get_contents_as_string()) contexts_to_release = release_auto_exit(actor) contexts_to_release_all.extend(contexts_to_release) release_contexts_fn = get_release_contexts_fn(contexts_to_release_all, AUTO_EXIT_REF_TAG) if arb_exit is not None and not arb_exit.empty: element = build_critical_section_with_finally(build_critical_section(create_run_animation(arb_exit), flush_all_animations), release_contexts_fn) return must_run(element) elif contexts_to_release_all: return must_run(build_element(release_contexts_fn))
def _move_objects(self): objects_to_move = services.object_manager().get_objects_matching_tags(self.object_tags, match_any=True) if not objects_to_move: return resolver = self._get_placement_resolver() choices = [(location.weight.get_multiplier(resolver), location.placement_strategy) for location in self.placement_strategy_locations] chosen_strategy = random.weighted_random_item(choices) do_fade = self.fade is not None out_sequence = [] moves = [] in_sequence = [] for object_to_move in objects_to_move: object_to_move.cancel_interactions_running_on_object(FinishingType.OBJECT_CHANGED, cancel_reason_msg='Object changing location.') if self.vfx_on_move is not None: out_sequence.append(lambda _, object_to_move=object_to_move: self.vfx_on_move(object_to_move).start_one_shot()) if do_fade: out_sequence.append(lambda _, object_to_move=object_to_move: object_to_move.fade_out(self.fade.out_time)) moves.append(lambda _, object_to_move=object_to_move: chosen_strategy.try_place_object(object_to_move, resolver)) if do_fade: in_sequence.append(lambda _, object_to_move=object_to_move: object_to_move.fade_in(self.fade.in_time)) sequence = [] if out_sequence: sequence.append(out_sequence) sequence.append(SoftSleepElement(clock.interval_in_sim_minutes(self.fade.out_time))) sequence.append(moves) if in_sequence: sequence.append(in_sequence) element = build_element(sequence, critical=CleanupType.RunAll) services.time_service().sim_timeline.schedule(element)
def _trigger_idle_animation(self, state, new_value, from_init): if self._component_suppressed: return if new_value in self.idle_animation_map: current_zone = services.current_zone() if current_zone is None or from_init and current_zone.is_zone_loading: return False else: new_animation = self.idle_animation_map[new_value] self._stop_animation_element() self._current_idle_state_value = new_value if new_animation is not None: sequence = () if new_animation.repeat: self._wakeable_element = element_utils.soft_sleep_forever( ) sequence = self._wakeable_element animation_element = new_animation(self.owner, sequence=sequence) self._idle_animation_element = build_element( (animation_element, flush_all_animations)) services.time_service().sim_timeline.schedule( self._idle_animation_element) return True return False
def _schedule_mid_season_interpolation_update(self): if self._client_interpolation_handler is not None: self._client_interpolation_handler.trigger_hard_stop() self._client_interpolation_handler = self._season_timeline.schedule( build_element( (lambda _: self._send_interpolation_update(mid_season_op=True), )), self._season_content.midpoint_time)
def execute(self, actor, path=None): previous_posture_state = actor.posture_state origin_posture_spec = get_origin_spec(self.posture_type) var_map = {PostureSpecVariable.HAND: Hand.LEFT} carry_posture_overrides = {previous_posture_state.left.track: previous_posture_state.left, previous_posture_state.right.track: previous_posture_state.right} actor.posture_state = PostureState(actor, actor.posture_state, origin_posture_spec, var_map, carry_posture_overrides=carry_posture_overrides) actor.posture_state.body.source_interaction = actor.create_default_si() final_routing_surface = path.final_location.routing_surface idle_arb = animation.arb.Arb() actor.posture.append_transition_to_arb(idle_arb, None) actor.posture.append_idle_to_arb(idle_arb) distribute_arb_element(idle_arb, master=actor) running_interaction = actor.queue.running if running_interaction is not None: running_interaction.satisfied = True def kickstart_posture(_timeline): result = yield from actor.posture_state.body.kickstart_gen(_timeline, actor.posture_state, final_routing_surface) return result yield def end_body_aspect(_timeline): if previous_posture_state.body: result = yield from element_utils.run_child(_timeline, previous_posture_state.body.end()) if not result: return result yield return True yield timeline = services.time_service().sim_timeline.get_sub_timeline() element = element_utils.build_element(actor.posture.get_idle_behavior()) timeline.schedule(element) if not timeline.simulate(timeline.now): logger.error('Failed trying to run idle behavior on Sim {} during a set posture route event.', actor) element = element_utils.build_element(flush_all_animations) timeline.schedule(element) if not timeline.simulate(timeline.now): logger.error('Failed trying to flush animations on Sim {} during a set posture route event.', actor) element = element_utils.build_element(kickstart_posture) timeline.schedule(element) if not timeline.simulate(timeline.now): logger.error('Failed trying to kickstart a posture on Sim {} during a set posture route event.', actor) element = element_utils.build_element(end_body_aspect) timeline.schedule(element) if not timeline.simulate(timeline.now): logger.error('Failed trying to end previous body aspect on Sim {} during a set posture route event.', actor)
def _run(self, timeline): if self.timing == self.AT_BEGINNING: if self.offset_time is None: sequence = [self._behavior_element, self.sequence] else: delayed_sequence = build_element([elements.SleepElement(clock.interval_in_sim_minutes(self.offset_time)), self._behavior_element]) if self.sequence: sequence = elements.AllElement([delayed_sequence, self.sequence]) else: sequence = delayed_sequence elif self.timing == self.AT_END: sequence = [self.sequence, self._behavior_element] elif self.timing == self.ON_XEVT: sequence = [build_critical_section(self._register_event_handler, self.sequence, self._release_event_handler), self._behavior_element] child_element = build_element(sequence, critical=self.criticality) child_element = self._build_outer_elements(child_element) return timeline.run_child(child_element)
def end_posture_on_same_track(timeline): if self._prev_posture is not None and self._prev_posture is not posture: prev_posture = self._prev_posture self._prev_posture = None result = yield element_utils.run_child( timeline, build_element(prev_posture.end())) return result return True
def _build_baby_age_up_sequence(self, sim_info, sequence, is_external=False): bassinet = self.interaction.get_participant(self.participant) new_bassinet = middle_bassinet = None def _do_spawn_gen(timeline): nonlocal middle_bassinet, new_bassinet self.interaction.add_exit_function(_on_interaction_exit) self.interaction.remove_liability('ReservationLiability') if is_external: middle_bassinet = self.interaction.target target_sim = bassinet else: for handler in bassinet.get_reservation_handlers(): if handler.sim is self.interaction.sim: bassinet.remove_reservation_handler(handler) middle_bassinet = bassinet.replace_for_age_up( interaction=self.interaction) yield timeline.run_child( SleepElement(interval_in_real_seconds(1))) target_sim = self.spawn_for_age_up( sim_info, bassinet.position, sim_location=bassinet.location) self.interaction.context.create_target_override = target_sim yield from target_sim._startup_sim_gen(timeline) master_controller = services.get_master_controller() master_controller.add_global_lock(target_sim) self.interaction.add_exit_function( lambda *_, **__: master_controller.remove_global_lock( target_sim)) self.interaction.add_liability( WorkLockLiability.LIABILITY_TOKEN, WorkLockLiability(sim=target_sim)) def _add_bassinet(obj): obj.location = middle_bassinet.location obj.opacity = 0 new_bassinet = create_object( BabyTuning.get_corresponding_definition( middle_bassinet.definition), init=_add_bassinet) def _on_age_up_event(*_, **__): new_bassinet.opacity = 1 middle_bassinet.remove_from_client() self._action = AgeUpBaby(sim_info, callback=_on_age_up_event) def _on_interaction_exit(): if middle_bassinet is None: return middle_bassinet.make_transient() return build_element((_do_spawn_gen, sequence))
def _run_interaction_gen(self, timeline): result = yield from element_utils.run_child( timeline, element_utils.build_element([ self._cancel_on_state_test_pass(self.cancel_state_test, super()._run_interaction_gen) ])) return result yield
def _schedule_season_screen_slam(self): if self._season_screen_slam_handler is not None: self._season_screen_slam_handler.trigger_hard_stop() scheduled_time = self._season_content.get_screen_slam_trigger_time() if scheduled_time is None: return self._season_screen_slam_handler = self._season_timeline.schedule( build_element((lambda _: self._send_screen_slam_message(), )), scheduled_time)
def create_run_animation(arb): if arb.empty: return def run_animation(_): arb_accumulator = services.current_zone().arb_accumulator_service arb_accumulator.add_arb(arb) return build_element(run_animation)
def _build_outer_elements(self, sequence): def stop_audio(e): if hasattr(self, '_sound'): self._sound.stop() if self.stop_audio_on_end and self.timing is not self.AT_END: return build_element([sequence, stop_audio], critical=CleanupType.OnCancelOrException) return sequence
def _build_outer_elements(self, sequence): if self.rename_dialog is None: return sequence target = self.interaction.get_participant(self.target) if target is None: return sequence rename_dialog = self.rename_dialog( target, resolver=self.interaction.get_resolver()) rename_element = RenameDialogElement(rename_dialog, target.sim_info) return build_element((rename_element, sequence))
def _trigger_idle_animation(self, state, new_value): if new_value in self._idle_animation_map: new_animation = self._idle_animation_map[new_value] self._hard_stop_animation_element() self._current_idle_state_value = new_value if new_animation is not None: animation_element = new_animation(self.owner) self._idle_animation_element = build_element((animation_element, flush_all_animations)) services.time_service().sim_timeline.schedule(self._idle_animation_element) return True return False
def _add_secondary_forward_wraparound_interp(self, seasonal_parameter, start_time, start_value, end_time, end_value, force_loop, sync_end_time=None): target_value = None new_end_value = end_value if end_value < start_value: if end_value == SeasonService.MIN_WRAPPING_SEASONAL_PARAMETER_VALUE: new_end_value = SeasonService.MAX_WRAPPING_SEASONAL_PARAMETER_VALUE elif start_value == SeasonService.MAX_WRAPPING_SEASONAL_PARAMETER_VALUE: start_value = SeasonService.MIN_WRAPPING_SEASONAL_PARAMETER_VALUE else: target_value = SeasonService.MAX_WRAPPING_SEASONAL_PARAMETER_VALUE elif end_value == start_value: if force_loop: if end_value == SeasonService.MIN_WRAPPING_SEASONAL_PARAMETER_VALUE: new_end_value = SeasonService.MAX_WRAPPING_SEASONAL_PARAMETER_VALUE else: target_value = SeasonService.MAX_WRAPPING_SEASONAL_PARAMETER_VALUE if target_value is not None: if sync_end_time is None: delta = start_value - end_value total_dist = SeasonService.WRAPPING_SEASONAL_PARAMETER_RANGE - delta percent_of_interp = ( SeasonService.MAX_WRAPPING_SEASONAL_PARAMETER_VALUE - start_value) / total_dist new_end_time = start_time + (end_time - start_time) * percent_of_interp else: new_end_time = sync_end_time def _regional_set_season_interp(): self._send_regional_season_change_update( seasonal_parameter, -target_value, new_end_time, end_value, end_time) if seasonal_parameter in self._regional_seasonal_parameters_handles: self._regional_seasonal_parameters_handles[ seasonal_parameter].trigger_hard_stop() self._regional_seasonal_parameters_handles[ seasonal_parameter] = self._season_timeline.schedule( build_element((lambda _: _regional_set_season_interp(), )), new_end_time) new_end_value = target_value elif sync_end_time is not None: new_end_time = sync_end_time else: new_end_time = end_time return (start_value, new_end_value, new_end_time)
def _push_adjustment_interaction(self): if self._instanced_stored_interaction: return self.leave_socials() if self._adjustment_interaction is not None: self._adjustment_interaction.cancel(FinishingType.WAIT_IN_LINE, 'Canceled') self._adjustment_interaction = None self._current_adjustment_constraint = self.get_adjustment_constraint() adjust_context = InteractionContext(self.sim, self._stored_context.source, self.priority, insert_strategy=QueueInsertStrategy.FIRST, cancel_if_incompatible_in_queue=True) run_element = element_utils.build_element((self.adjust_sim_behind_me, self.maybe_enter_stored_interaction)) result = self.sim.push_super_affordance(SatisfyConstraintSuperInteraction, None, adjust_context, constraint_to_satisfy=self._current_adjustment_constraint, allow_posture_changes=True, set_work_timestamp=False, name_override='AdjustWaitingLinePosition', run_element=run_element, cancel_incompatible_with_posture_on_transition_shutdown=False) self._adjustment_interaction = result.interaction
def _build_outer_elements(self, sequence): def stop_audio(e): if self._sound is not None: self._sound.stop() if self._stored_audio_component is None: return for target_object in self._target_objects: self._stored_audio_component.remove_audio_effect(target_object) if self.stop_audio_on_end and self.timing is not self.AT_END: return build_element([sequence, stop_audio], critical=CleanupType.OnCancelOrException) return sequence
def build_basic_content(self, *args, **kwargs): self.store_event_handler(self.distribute_fetch_route, handler_id=self.throw_xevent_id) sequence = super().build_basic_content(*args, **kwargs) def plan_fetch_paths(timeline): for target_sim in self.get_participants( ParticipantType.TargetSim | ParticipantType.Listeners): fetch_constraint = self.fetch_constraint.create_constraint( target_sim, target_position=self._distance_placement_transform. translation, routing_surface=self._routing_surface if self._routing_surface is not None else DEFAULT) facing = interactions.constraints.Facing( target_position=self._distance_placement_transform. translation, inner_radius=self.facing_radius) fetch_constraint = fetch_constraint.intersect(facing) if not fetch_constraint.valid: continue goals = [] handles = fetch_constraint.get_connectivity_handles(target_sim) for handle in handles: goals.extend(handle.get_goals()) if not goals: pass else: route = routing.Route( target_sim.routing_location, goals, routing_context=target_sim.routing_context) plan_primitive = PlanRoute(route, target_sim, interaction=self) result = yield from element_utils.run_child( timeline, plan_primitive) if result: if plan_primitive.path.nodes: if plan_primitive.path.nodes.plan_success: if plan_primitive.path.portal_obj is not None: logger.error( 'Need sub interaction to route {} due to portal on path' .format(target_sim)) else: self._plan_primitives.append( plan_primitive) yield from element_utils.run_child(timeline, sequence) return build_element(plan_fetch_paths)
def on_response(dialog): if not dialog.accepted: return name = dialog.text_input_responses.get(self.TEXT_INPUT_NEW_NAME) description = dialog.text_input_responses.get(self.TEXT_INPUT_NEW_DESCRIPTION) target = self.target if target is not None: if name is not None: target.set_custom_name(name) if description is not None: target.set_custom_description(description) self._update_ui_metadata(target) sequence = self._build_outcome_sequence() services.time_service().sim_timeline.schedule(element_utils.build_element(sequence))
def with_skippable_animation_time(actors, sequence=None): def _with_skippable_animation_time(timeline): then = time.monotonic() yield from element_utils.run_child(timeline, sequence) now = time.monotonic() duration = now - then arb_accumulator = services.current_zone().arb_accumulator_service for actor in actors: time_debt = arb_accumulator.get_time_debt((actor,)) new_time_debt = max(0, time_debt - duration) arb_accumulator.set_time_debt((actor,), new_time_debt) return element_utils.build_element(_with_skippable_animation_time)
def _run_gen(self, timeline): if self.pre_route_animation is not None: animation_element = self.pre_route_animation(self._obj) self._element = build_element( (animation_element, flush_all_animations)) result = yield from element_utils.run_child( timeline, self._element) if not result: return result yield def do_routes(timeline): result = False for route in self._route_data.get_routes_gen(): result = yield from self._do_single_route_gen(timeline, route) if not result: break if not result: yield from element_utils.run_child( timeline, element_utils.sleep_until_next_tick_element()) return result yield if self.walkstyle_override is None: yield from do_routes(timeline) else: walkstyle_request = self.walkstyle_override(self._obj) yield from element_utils.run_child( timeline, walkstyle_request(sequence=do_routes)) target = self._route_data.get_target() if target: if target.is_sim: yield from self._route_data.do_target_action_rules_gen( timeline) else: reservation_handler = target.get_reservation_handler(self._obj) if reservation_handler and reservation_handler.may_reserve(): reservation_handler.begin_reservation() try: yield from self._route_data.do_target_action_rules_gen( timeline) finally: reservation_handler.end_reservation() else: self._route_data.on_no_target() resolver = SingleObjectResolver(self._obj) for loot_action in self.completion_loot: loot_action.apply_to_resolver(resolver) return True yield
def next_stage(self): if self._progress == _StageProgress.Init: timeline = services.time_service().sim_timeline self._sim.schedule_element(timeline, self) if self._progress == _StageProgress.Done: raise RuntimeError('StageControllElement is past the point of sleeping') if self._wakeable_element is not None: raise RuntimeError("Attempting to get an element from next_stage on '{}' before consuming the previous one ({})".format(self, self._progress)) self._wakeable_element = element_utils.soft_sleep_forever() if self._progress != _StageProgress.Sleeping: sequence = self._wakeable_element else: sequence = element_utils.build_element([lambda _: self._wake(), self._wakeable_element]) sequence = element_utils.return_true_wrapper(element_utils.must_run(sequence)) return sequence
def _run(self, timeline): if not self._should_do_behavior: return timeline.run_child(build_element(self.sequence)) if self.timing == self.AT_BEGINNING: if self.offset_time is None: sequence = [self._behavior_element, self.sequence] else: sequence = build_delayed_element(self.sequence, clock.interval_in_sim_minutes( self.offset_time), self._behavior_element, soft_sleep=True) elif self.timing == self.AT_END: sequence = [self.sequence, self._behavior_element] elif self.timing == self.ON_XEVT: sequence = [ build_critical_section(self._register_event_handler, self.sequence, self._release_event_handler), self._behavior_element ] child_element = build_element(sequence, critical=self.criticality) child_element = self._build_outer_elements(child_element) return timeline.run_child(child_element)
def with_skippable_animation_time(actors, sequence=None): def _with_skippable_animation_time(timeline): game_clock_service = services.game_clock_service() then = game_clock_service.now() yield element_utils.run_child(timeline, sequence) now = game_clock_service.now() duration = (now - then).in_real_world_seconds() arb_accumulator = services.current_zone().arb_accumulator_service for actor in actors: time_debt = arb_accumulator.get_time_debt((actor,)) new_time_debt = max(0, time_debt - duration) arb_accumulator.set_time_debt((actor,), new_time_debt) return element_utils.build_element(_with_skippable_animation_time)
def route_failure(sim, interaction, failure_reason, failure_object_id): global ROUTE_FAILURE_OVERRIDE_MAP if not sim.should_route_fail: return overrides = None if ROUTE_FAILURE_OVERRIDE_MAP is None: ROUTE_FAILURE_OVERRIDE_MAP = {TransitionFailureReasons.BLOCKING_OBJECT: RouteFailureTunables.route_fail_overrides_object, TransitionFailureReasons.RESERVATION: RouteFailureTunables.route_fail_overrides_reservation, TransitionFailureReasons.BUILD_BUY: RouteFailureTunables.route_fail_overrides_build, TransitionFailureReasons.NO_DESTINATION_NODE: RouteFailureTunables.route_fail_overrides_no_dest_node, TransitionFailureReasons.NO_PATH_FOUND: RouteFailureTunables.route_fail_overrides_no_path_found, TransitionFailureReasons.NO_VALID_INTERSECTION: RouteFailureTunables.route_fail_overrides_no_valid_intersection, TransitionFailureReasons.NO_GOALS_GENERATED: RouteFailureTunables.route_fail_overrides_no_goals_generated, TransitionFailureReasons.NO_CONNECTIVITY_TO_GOALS: RouteFailureTunables.route_fail_overrides_no_connectivity, TransitionFailureReasons.PATH_PLAN_FAILED: RouteFailureTunables.route_fail_overrides_path_plan_fail} if failure_reason is not None and failure_reason in ROUTE_FAILURE_OVERRIDE_MAP: overrides = ROUTE_FAILURE_OVERRIDE_MAP[failure_reason]() if failure_object_id is not None: fail_obj = services.object_manager().get(failure_object_id) if fail_obj is not None: overrides.balloon_target_override = fail_obj route_fail_anim = RouteFailureTunables.route_fail_animation(sim.posture.source_interaction, overrides=overrides, sequence=()) supported_postures = route_fail_anim.get_supported_postures() if supported_postures: return build_element((route_fail_anim, flush_all_animations)) balloon_requests = TunableBalloon.get_balloon_requests(interaction, route_fail_anim.overrides) return balloon_requests
def enter_carry_while_holding(si, obj=None, carry_obj_participant_type=None, callback=None, create_si_fn=DEFAULT, sim_participant_type=ParticipantType.Actor, carry_posture_id=DEFAULT, owning_affordance=DEFAULT, sequence=None, carry_sim=DEFAULT, track=DEFAULT): sim = si.get_participant(sim_participant_type) if carry_sim is DEFAULT else carry_sim context = si.context.clone_for_sim(sim) if carry_obj_participant_type is not None: obj = si.get_participant(carry_obj_participant_type) if obj is None: raise ValueError('[bhill] Attempt to perform an enter carry while holding with None as the carried object. SI: {}'.format(si)) if track is DEFAULT: track = si.carry_track if track is None: raise RuntimeError("[jpollak] enter_carry_while_holding: Interaction does not have a carry_track, which means its animation tuning doesn't have a carry target or create target specified in object editor or the posture manifest from the swing graph does not require a specific object.") if carry_posture_id is DEFAULT: carry_posture_id = CarryPostureStaticTuning.POSTURE_CARRY_OBJECT if create_si_fn is DEFAULT: if owning_affordance is DEFAULT: raise AssertionError("[bhill] No create_si_fn was provided and we don't know how to make one.") def create_si_fn(): aop = AffordanceObjectPair(owning_affordance, obj, owning_affordance, None) return (aop, context) def set_up_transition_gen(timeline): nonlocal sequence (new_posture_state, new_posture, new_source_aop, var_map) = create_enter_carry_posture(sim, sim.posture_state, obj, track) got_callback = False def event_handler_enter_carry(event_data): nonlocal got_callback if got_callback: logger.warn('Animation({}) calling to start a carry multiple times', event_data.event_data.get('clip_name')) return got_callback = True arb = animation.arb.Arb() locked_params = new_posture.get_locked_params(None) old_carry_posture = sim.posture_state.get_aspect(track) if old_carry_posture is not None: old_carry_posture.append_exit_to_arb(arb, new_posture_state, new_posture, var_map) new_posture.append_transition_to_arb(arb, old_carry_posture, locked_params=locked_params, in_xevt_handler=True) ArbElement(arb).distribute() si.animation_context.register_event_handler(event_handler_enter_carry, handler_id=SCRIPT_EVENT_ID_START_CARRY) def maybe_do_transition_gen(timeline): def push_si_gen(timeline): context = InteractionContext(sim, InteractionContext.SOURCE_POSTURE_GRAPH, si.priority, run_priority=si.run_priority, insert_strategy=QueueInsertStrategy.NEXT, must_run_next=True, group_id=si.group_id) result = new_source_aop.interaction_factory(context) if not result: return result source_interaction = result.interaction new_posture.source_interaction = source_interaction owning_interaction = None if create_si_fn is not None: (aop, context) = create_si_fn() if aop is not None and context is not None and aop.test(context): result = aop.interaction_factory(context) if result: owning_interaction = result.interaction owning_interaction.acquire_posture_ownership(new_posture) aop.execute_interaction(owning_interaction) if owning_interaction is None: si.acquire_posture_ownership(new_posture) yield source_interaction.run_direct_gen(timeline) return result def call_callback(_): if callback is not None: callback(new_posture, new_posture.source_interaction) if got_callback: result = yield element_utils.run_child(timeline, must_run([PostureTransition(new_posture, new_posture_state, context, var_map), push_si_gen, call_callback])) return result return True sequence = disable_asm_auto_exit(sim, sequence) with si.cancel_deferred((si,)): yield element_utils.run_child(timeline, must_run(build_critical_section(build_critical_section(sequence, flush_all_animations), maybe_do_transition_gen))) return build_element(set_up_transition_gen)
def _build_sequence_with_callback(self, callback=None, sequence=()): self.animation_context.register_event_handler(callback, handler_id=self.put_down_drink_xevt_id) sequence = self._custom_content_sequence(sequence) return build_element(sequence)
def _run_interaction_gen(self, timeline): result = yield element_utils.run_child(timeline, element_utils.build_element([self._cancel_on_state_test_pass(self.cancel_state_test, super()._run_interaction_gen)])) return result
def _run(self, timeline): first_stage = element_utils.build_element(self._do_perform_gen) self._progress = _StageProgress.FirstStage return timeline.run_child(first_stage)
def _get_behavior(self): posture = self._posture sim = posture.sim multi_sim_posture_transition = posture.multi_sim and not posture.is_puppet prev_posture_state = sim.posture_state self._prev_posture = prev_posture_state.get_aspect(posture.track) animate_in = None if multi_sim_posture_transition or self._animate_in is not None and not self._animate_in.empty: animate_in = create_run_animation(self._animate_in) my_stage = self._stage() def posture_change(timeline): posture.log_info('Change', msg='{}'.format(posture.track.name if posture.track is not None else 'NO TRACK!')) prev_posture_state = sim.posture_state prev_posture = prev_posture_state.get_aspect(posture.track) sim.posture_state = self._dest_state sim.on_posture_event(PostureEvent.POSTURE_CHANGED, self._dest_state, posture.track, prev_posture, posture) yield sim.si_state.notify_posture_change_and_remove_incompatible_gen(timeline, prev_posture_state, self._dest_state) prev_posture.clear_owning_interactions() if multi_sim_posture_transition: linked_posture_begin = posture.linked_posture.begin(self._animate_in, self._dest_state.linked_posture_state, posture._context) self._dest_state = None yield element_utils.run_child(timeline, linked_posture_begin) else: self._dest_state = None return True def end_posture_on_same_track(timeline): if self._prev_posture is not None and self._prev_posture is not posture: prev_posture = self._prev_posture self._prev_posture = None result = yield element_utils.run_child(timeline, build_element(prev_posture.end())) return result return True if services.current_zone().animate_instantly: flush = flush_all_animations_instantly else: flush = flush_all_animations sequence = (posture_change, animate_in, flush, end_posture_on_same_track, my_stage) sequence = build_element(sequence, critical=CleanupType.RunAll) sequence = build_critical_section_with_finally(sequence, lambda _: posture._release_animation_context()) if self._posture.jig is not None and self._posture.target is not None and self._posture.slot_constraint is not None: def create_and_place_jig(_): self._jig = objects.system.create_object(self._posture.jig) for constraint in self._posture.slot_constraint: self._jig.transform = constraint.containment_transform break sim.routing_context.ignore_footprint_contour(self._jig.routing_context.object_footprint_id) def destroy_jig(_): if self._jig is not None: sim.routing_context.remove_footprint_contour_override(self._jig.routing_context.object_footprint_id) self._jig.destroy(source=self, cause='Destroying jig for posture.') sequence = build_critical_section_with_finally(create_and_place_jig, sequence, destroy_jig) sequence = elements.GeneratorElement(self.with_censor_grid(sim, sequence)) if posture.target is not None: reserver = create_reserver(sim, posture.target, reserver=posture, handler=MultiReserveObjectHandler) sequence = reserver.do_reserve(sequence=sequence) def stage_on_fail(timeline): if not self.has_staged: yield element_utils.run_child(timeline, self._stage_fail()) sequence = element_utils.build_critical_section(sequence, stage_on_fail) sequence = maybe(posture.test, sequence) return sequence
def exit_carry_while_holding(interaction, callback=None, sequence=None, sim_participant_type=ParticipantType.Actor, use_posture_animations=False, carry_system_target=None): si = interaction.super_interaction sim = interaction.get_participant(sim_participant_type) target = interaction.carry_target or interaction.target def set_up_transition_gen(timeline): (old_carry_posture, new_posture, _, transition, var_map) = create_exit_carry_posture(sim, target, interaction, use_posture_animations) if transition is None: yield element_utils.run_child(timeline, sequence) return exited_carry = False if not use_posture_animations: def event_handler_exit_carry(event_data): nonlocal exited_carry exited_carry = True arb = animation.arb.Arb() old_carry_posture.append_exit_to_arb(arb, None, new_posture, var_map, exit_while_holding=True) new_posture.append_transition_to_arb(arb, old_carry_posture, in_xevt_handler=True) ArbElement(arb, master=sim).distribute() interaction.animation_context.register_event_handler(event_handler_exit_carry, handler_id=SCRIPT_EVENT_ID_STOP_CARRY) if callback is not None: interaction.animation_context.register_event_handler(callback, handler_id=SCRIPT_EVENT_ID_STOP_CARRY) def maybe_do_transition(timeline): if not use_posture_animations and not exited_carry: event_handler_exit_carry(None) if callback is not None: callback() if use_posture_animations or exited_carry: interaction_target_was_target = False si_target_was_target = False if interaction.target == target: interaction_target_was_target = True interaction.set_target(None) if old_carry_posture.target_is_transient and si.target == target: si_target_was_target = True si.set_target(None) if carry_system_target is not None: old_carry_posture.carry_system_target = carry_system_target def do_transition(timeline): result = yield element_utils.run_child(timeline, transition) if result: interaction_target_was_target = False si_target_was_target = False new_posture.source_interaction = None return True return False def post_transition(_): if interaction_target_was_target: interaction.set_target(target) if si_target_was_target: si.set_target(target) if carry_system_target is not None: old_carry_posture.carry_system_target = None yield element_utils.run_child(timeline, must_run(build_critical_section_with_finally(do_transition, post_transition))) new_sequence = disable_asm_auto_exit(sim, sequence) yield element_utils.run_child(timeline, build_critical_section(build_critical_section(new_sequence, flush_all_animations), maybe_do_transition)) return build_element(set_up_transition_gen)