def _germinate(self): plant = None try: plant = create_object(self.plant) location = self._find_germinate_location(plant) if location is None: logger.warn('Failed to germinate: No location found') plant.destroy(source=self.owner, cause='Failed to germinate: No location found') plant = None return False if self.owner.parent_slot is not None: self.owner.parent_slot.add_child(plant) else: plant.location = location plant.gardening_component.add_fruit(self.owner, sprouted_from=True) created_object_quality = self.owner.get_state(GardeningTuning.QUALITY_STATE_VALUE) current_household = services.owning_household_of_active_lot() if current_household is not None: plant.set_household_owner_id(current_household.id) services.get_event_manager().process_events_for_household(test_events.TestEvent.ItemCrafted, current_household, crafted_object=plant, skill=None, quality=created_object_quality, masterwork=None) if self.owner.in_use: self.owner.transient = True else: self.owner.destroy(source=self.owner, cause='Successfully germinated.') return except: logger.exception('Failed to germinate.') if plant is not None: plant.destroy(source=self.owner, cause='Failed to germinate.') plant = None return False return plant
def on_add(self, *_, **__): services.sim_spawner_service().register_sim_spawned_callback(self._on_sim_spawned) owning_household = services.owning_household_of_active_lot() if owning_household is None: return for sim in owning_household.instanced_sims_gen(allow_hidden_flags=ALL_HIDDEN_REASONS_EXCEPT_UNINITIALIZED): self._add_commodities_to_sims(sim)
def on_cleanup_zone_objects(self): super().on_cleanup_zone_objects() persistence_service = services.get_persistence_service() plex_service = services.get_plex_service() plex_zone_ids = plex_service.get_plex_zones_in_group( services.current_zone_id()) last_save_ticks = None for zone_id in plex_zone_ids: zone_data = persistence_service.get_zone_proto_buff(zone_id) gameplay_zone_data = zone_data.gameplay_zone_data if not gameplay_zone_data.HasField('game_time'): continue if not last_save_ticks is None: if last_save_ticks < gameplay_zone_data.game_time: last_save_ticks = gameplay_zone_data.game_time last_save_ticks = gameplay_zone_data.game_time if last_save_ticks is not None: last_save_time = DateAndTime(last_save_ticks) next_cleanup_time = last_save_time.time_of_next_day_time( ApartmentZoneDirectorMixin.COMMON_AREA_CLEANUP.time_of_day) if next_cleanup_time < services.time_service().sim_now: self._run_common_area_cleanup() owning_household = services.owning_household_of_active_lot() if owning_household is not None and not owning_household.has_home_zone_been_active( ): self._run_new_tenant_cleanup()
def __call__(self, test_targets=None): target_household = None if self.household_to_test.household_source == UtilityTest.ACTIVE_LOT_HOUSEHOLD: target_household = services.owning_household_of_active_lot() elif self.household_to_test.household_source == UtilityTest.ACTIVE_HOUSEHOLD: target_household = services.active_household() elif self.household_to_test.household_source == UtilityTest.PARTICIPANT_HOUSEHOLD: target = next(iter(test_targets), None) if target is not None: if target.is_sim: target_household = target.household else: target_household = services.household_manager().get(target.get_household_owner_id()) if target_household is not None: utilities_manager = services.get_utilities_manager_by_household_id(target_household.id) elif self.household_to_test.household_source == UtilityTest.ACTIVE_LOT_HOUSEHOLD and self.household_to_test.consider_non_household_lot: utilities_manager = services.get_utilities_manager_by_zone_id(services.current_zone_id()) else: return TestResult(False, 'UtilitiesTest: Required to check utility, but there is no household. Check participant tuning.', tooltip=self.tooltip) if utilities_manager is None: return TestResult(False, 'UtilitiesTest: Required to check utility, but utilities manager is None. Check participant tuning.', tooltip=self.tooltip) for utility_state in self.utility_states: if utilities_manager.is_utility_active(utility_state.utility) != utility_state.require_active: return TestResult(False, 'UtilitiesTest: Utility status for the {} is not correct.', utility_state.utility, tooltip=self.tooltip) return TestResult.TRUE
def process_events_for_household(self, event_type, household, exclude_sim=None, **kwargs): if not self._enabled: return if household is None: household = services.owning_household_of_active_lot() if household is None: return caches.clear_all_caches() with sims4.callback_utils.invoke_enter_exit_callbacks( CallbackEvent. ENTER_CONTENT_SET_GEN_OR_PROCESS_HOUSEHOLD_EVENTS, CallbackEvent.EXIT_CONTENT_SET_GEN_OR_PROCESS_HOUSEHOLD_EVENTS ): callbacks = data_store_event_test_event_callback_map.get( event_type) has_not_triggered_achievement_data_object = True for sim_info in household._sim_infos: if sim_info == exclude_sim: continue if callbacks is not None: self._process_data_map_for_aspiration( sim_info, event_type, callbacks, **kwargs) if has_not_triggered_achievement_data_object: if callbacks is not None: self._process_data_map_for_achievement( sim_info, event_type, callbacks, **kwargs) has_not_triggered_achievement_data_object = False self._process_test_event(sim_info, event_type, **kwargs)
def get_particpants_shared(participant_type): if participant_type == ParticipantType.Lot: return (services.active_lot(),) if participant_type == ParticipantType.LotOwners: owning_household = services.owning_household_of_active_lot() if owning_household is not None: return tuple(sim_info for sim_info in owning_household.sim_info_gen()) return ()
def _do_behavior(self): household = services.owning_household_of_active_lot() if household is None: return if not household.bills_manager.can_deliver_bill: return household.bills_manager.trigger_bill_notifications_from_delivery() services.get_event_manager().process_events_for_household(TestEvent.BillsDelivered, household)
def get_particpants_shared(participant_type): if participant_type == ParticipantType.Lot: return (services.active_lot(), ) if participant_type == ParticipantType.LotOwners: owning_household = services.owning_household_of_active_lot() if owning_household is not None: return tuple(sim_info for sim_info in owning_household.sim_info_gen()) return ()
def _do_behavior(self): household = services.owning_household_of_active_lot() household_id = None if household is not None: household_id = household.id transfer_entire_inventory(self.source, self.recipient, interaction=None, household_id=household_id)
def _do_behavior(self): household = services.owning_household_of_active_lot() if household is None: return if not household.bills_manager.can_deliver_bill: return household.bills_manager.trigger_bill_notifications_from_delivery() services.get_event_manager().process_events_for_household( TestEvent.BillsDelivered, household)
def _try_make_always_welcomed(self, sim): if any( sim.sim_info.has_trait(trait) for trait in VisitingTuning.ALWAYS_WELCOME_TRAITS): current_household = services.owning_household_of_active_lot() if current_household is None: logger.error( 'Current household is None when trying to run the ring doorbell interaction for visiting sim {}', sim) return current_household.add_always_welcome_sim(sim.sim_info.id)
def __init__(self, owner, component_interactions=None): super().__init__(owner) self._user_intensity_overrides = None self._owner_stat_tracker = self.owner.get_tracker(self.LIGHT_STATE_STAT) household = services.owning_household_of_active_lot() if household is None or not household.bills_manager.is_utility_delinquent(Utilities.POWER): self.set_light_dimmer_value(self.LIGHT_DIMMER_VALUE_MAX_INTENSITY) else: self.set_light_dimmer_value(self.LIGHT_DIMMER_VALUE_OFF) self._pending_dimmer_value = None self._color = None self._component_interactions = component_interactions
def __init__(self, owner, component_interactions=None): super().__init__(owner) self._user_intensity_overrides = None self._owner_stat_tracker = self.owner.get_tracker( self.LIGHT_STATE_STAT) household = services.owning_household_of_active_lot() if household is None or not household.bills_manager.is_utility_delinquent( Utilities.POWER): self.set_light_dimmer_value(self.LIGHT_DIMMER_VALUE_MAX_INTENSITY) else: self.set_light_dimmer_value(self.LIGHT_DIMMER_VALUE_OFF) self._pending_dimmer_value = None self._color = None self._component_interactions = component_interactions
def _custom_claim_callback(self): if self.phase.object_info_is_final_product: lot_owning_household = services.owning_household_of_active_lot() if lot_owning_household is not None: self.object_to_serve.set_household_owner_id( lot_owning_household.id) elif self.order_sim is not None: self.object_to_serve.set_household_owner_id( self.order_sim.sim_info.household_id) self.process.apply_quality_and_value(self.object_to_serve) self.object_to_serve.on_crafting_process_finished() loot = LootOperationList( self.get_resolver(), self.process.recipe.final_product.loot_list) loot.apply_operations() self.add_exit_function(self._clean_up_cancel_order_entries)
def situation_meets_starting_requirements(cls, **kwargs): owning_household = services.owning_household_of_active_lot() if owning_household is None or not owning_household.get_sims_at_home(): return False neighbor_results = cls.get_filter_results_for_job() if not neighbor_results: return False else: for neighbor_result in neighbor_results: resolver = DoubleSimResolver(services.active_sim_info(), neighbor_result.sim_info) if cls.scheduling_tests.run_tests(resolver): break else: return False return True
def on_all_households_and_sim_infos_loaded(self, client): plex_service = services.get_plex_service() households = { services.owning_household_of_active_lot(), services.active_household() } households.discard(None) def test_household(household): if household is None: return False tests = LandlordTuning.HOUSEHOLD_LANDLORD_EXCEPTION_TESTS if not tests: return True sim_info = next(household.sim_info_gen(), None) if sim_info is None: return False resolver = SingleSimResolver(sim_info) return tests.run_tests(resolver) households = [ household for household in households if test_household(household) ] if any( plex_service.is_zone_a_plex(household.home_zone_id) for household in households): landlord_sim_info = self.get_landlord_sim_info() if landlord_sim_info is None: logger.error('Unable to create landlord for owned apartment', owner='nabaker') return else: landlord_sim_info = self.get_existing_landlord_sim_info() if landlord_sim_info is None or landlord_sim_info.relationship_tracker is None: return for household in households: home_zone_is_plex = plex_service.is_zone_a_plex( household.home_zone_id) self.setup_household_relationships( landlord_sim_info, household, home_zone_is_plex=home_zone_is_plex)
def _germinate(self): plant = None try: plant = create_object(self.plant) location = self._find_germinate_location(plant) if location is None: logger.warn('Failed to germinate: No location found') plant.destroy(source=self.owner, cause='Failed to germinate: No location found') plant = None return False if self.owner.parent_slot is not None: self.owner.parent_slot.add_child(plant) else: plant.location = location plant.gardening_component.add_fruit(self.owner, sprouted_from=True) created_object_quality = self.owner.get_state( GardeningTuning.QUALITY_STATE_VALUE) current_household = services.owning_household_of_active_lot() if current_household is not None: plant.set_household_owner_id(current_household.id) services.get_event_manager().process_events_for_household( test_events.TestEvent.ItemCrafted, current_household, crafted_object=plant, skill=None, quality=created_object_quality, masterwork=None) if self.owner.in_use: self.owner.transient = True else: self.owner.destroy(source=self.owner, cause='Successfully germinated.') return except: logger.exception('Failed to germinate.') if plant is not None: plant.destroy(source=self.owner, cause='Failed to germinate.') plant = None return False return plant
def process_events_for_household(self, event_type, household, exclude_sim=None, **kwargs): if not self._enabled: return if household is None: household = services.owning_household_of_active_lot() if household is None: return caches.clear_all_caches() with sims4.callback_utils.invoke_enter_exit_callbacks(CallbackEvent.ENTER_CONTENT_SET_GEN_OR_PROCESS_HOUSEHOLD_EVENTS, CallbackEvent.EXIT_CONTENT_SET_GEN_OR_PROCESS_HOUSEHOLD_EVENTS): callbacks = data_store_event_test_event_callback_map.get(event_type) has_not_triggered_achievment_data_object = True for sim_info in household._sim_infos: if sim_info == exclude_sim: pass if callbacks is not None: self._process_data_map_for_aspiration(sim_info, event_type, callbacks, **kwargs) if has_not_triggered_achievment_data_object: if callbacks is not None: self._process_data_map_for_achievement(sim_info, event_type, callbacks, **kwargs) has_not_triggered_achievment_data_object = False self._process_test_event(sim_info, event_type, **kwargs)
def _create_pending_urnstones(self): household = services.owning_household_of_active_lot() if household is None: return for sim_info in household.get_pending_urnstone_sim_infos(): resolver = SingleSimResolver(sim_info) urnstone_definition = Ghost.URNSTONE_DEFINITION.get_definition( resolver) urnstone = create_object(urnstone_definition) urnstone.add_dynamic_component(types.STORED_SIM_INFO_COMPONENT, sim_id=sim_info.id) try: placement_helper = CullingTuning.CULLING_OFFLOT_URNSTONE_PLACEMENT if placement_helper.try_place_object(urnstone, resolver): household.pending_urnstone_ids.remove(sim_info.id) continue else: urnstone.destroy() except: urnstone.destroy() raise
def get_particpants_shared(participant_type): if participant_type == ParticipantType.Lot: return (services.active_lot(), ) elif participant_type == ParticipantType.LotOwners: owning_household = services.owning_household_of_active_lot() if owning_household is not None: return tuple(sim_info for sim_info in owning_household.sim_info_gen()) return () return () if participant_type == ParticipantType.LotOwnersOrRenters: owning_household = services.owning_household_of_active_lot() if owning_household is not None: return tuple(sim_info for sim_info in owning_household.sim_info_gen()) else: current_zone = services.current_zone() travel_group = services.travel_group_manager( ).get_travel_group_by_zone_id(current_zone.id) if travel_group is not None: return tuple(sim_info for sim_info in travel_group.sim_info_gen()) return () if participant_type == ParticipantType.LotOwnerSingleAndInstanced: owning_household = services.owning_household_of_active_lot() if owning_household is not None: for sim_info in owning_household.sim_info_gen(): if sim_info.is_instanced(): return (sim_info, ) return () elif participant_type == ParticipantType.ActiveHousehold: active_household = services.active_household() if active_household is not None: return tuple(active_household.sim_info_gen()) return () elif participant_type == ParticipantType.AllInstancedActiveHouseholdSims: active_household = services.active_household() if active_household is not None: return tuple(active_household.instanced_sims_gen()) return () elif participant_type == ParticipantType.CareerEventSim: career = services.get_career_service().get_career_in_career_event() if career is not None: return (career.sim_info.get_sim_instance() or career.sim_info, ) return () return () if participant_type == ParticipantType.AllInstancedActiveHouseholdSims: active_household = services.active_household() if active_household is not None: return tuple(active_household.instanced_sims_gen()) return () elif participant_type == ParticipantType.CareerEventSim: career = services.get_career_service().get_career_in_career_event() if career is not None: return (career.sim_info.get_sim_instance() or career.sim_info, ) return () return () if participant_type == ParticipantType.AllInstancedSims: return tuple(services.sim_info_manager().instanced_sims_gen()) if participant_type == ParticipantType.Street: street = services.current_zone().street street_service = services.street_service() if street_service is None: return () street_civic_policy_provider = street_service.get_provider(street) if street_civic_policy_provider is None: return () return (street_civic_policy_provider, ) if participant_type == ParticipantType.VenuePolicyProvider: venue_service = services.venue_service() if venue_service.source_venue is None or venue_service.source_venue.civic_policy_provider is None: return () else: return (venue_service.source_venue.civic_policy_provider, )
def _place_object(self, created_object): self._setup_created_object(created_object) if self._place_object_no_fallback(created_object): return True if not self.destroy_on_placement_failure: participant = self._get_fallback_location_target(created_object) if participant.is_sim: if isinstance(participant, sims.sim_info.SimInfo): participant = participant.get_sim_instance( allow_hidden_flags=ALL_HIDDEN_REASONS) location_type = getattr(self.location, 'location', None) if location_type == self.INVENTORY and self.location.mark_object_as_stolen_from_career: interaction = self.resolver.interaction if interaction is None: logger.error( 'Mark Object As Stolen From Career is checked on CreateObject loot {}. \n This should only be check on basic extra in a CareerSuperInteraction.', self) return False career_uid = interaction.interaction_parameters.get( 'career_uid') if career_uid is not None: career = interaction.sim.career_tracker.get_career_by_uid( career_uid) if career is not None: name_data = career.get_career_location( ).get_persistable_company_name_data() text = None guid = None if isinstance(name_data, str): text = name_data else: guid = name_data MarkObjectAsStolen.mark_object_as_stolen( created_object, stolen_from_text=text, stolen_from_career_guid=guid) else: logger.error( 'Interaction {} is tuned with a CreateObject basic extra that has mark_object_as_stolen_from_career as True,\n but is not a CareerSuperInteraction. This is not supported.', interaction) if created_object.inventoryitem_component is not None: if created_object.id not in self._assigned_ownership: if participant.is_sim: participant_household_id = participant.household.id else: participant_household_id = participant.get_household_owner_id( ) created_object.set_household_owner_id( participant_household_id) self._assigned_ownership.add(created_object.id) if participant.inventory_component.player_try_add_object( created_object, hidden=location_type == self.INVENTORY and self.location.place_in_hidden_inventory): if self.notification_inventory: notification = self.notification_inventory.participant_inventory( participant, self.resolver) notification.show_dialog() return True sim = self.resolver.get_participant(ParticipantType.Actor) if not (participant is not None and participant.inventory_component is not None and sim is None or not sim.is_sim): owning_household = services.owning_household_of_active_lot() if owning_household is not None: for sim_info in owning_household.sim_info_gen(): if sim_info.is_instanced(): sim = sim_info.get_sim_instance() break if sim is not None: if not sim.is_npc: try: created_object.set_household_owner_id(sim.household.id) if build_buy.move_object_to_household_inventory( created_object): if self.notification_inventory: notification = self.notification_inventory.household_inventory( sim, self.resolver) notification.show_dialog() return True logger.error( 'Creation: Failed to place object {} in household inventory.', created_object, owner='rmccord') except KeyError: pass return False
def recipe_test(cls, target, context, recipe, sim_to_test, price, build_error_list=True, first_phase=DEFAULT, from_resume=False, from_autonomy=False): enabled = True error_list = [] if not (recipe.entitlement is not None and mtx.is_displayable(recipe.entitlement)): return RecipeTestResult(enabled=False, visible=False, errors=error_list) if first_phase is not DEFAULT: first_phases = set([first_phase]) else: if sim_to_test.family_funds.money < price: enabled = False error_list.append(CraftingTuning.INSUFFICIENT_FUNDS_TOOLTIP(sim_to_test)) first_phases = set(recipe.first_phases) if not first_phases: logger.error('No first phases defined in recipe tuning: {}', recipe.__name__) return RecipeTestResult(enabled=False, visible=False, errors=error_list) dest_phases = set() available_phases = set() for phase in recipe.phases.values(): if cls.phase_completable(phase, sim_to_test, context, target, from_autonomy=from_autonomy): available_phases.add(phase) while not phase.next_phases: dest_phases.add(phase) if not dest_phases: logger.error('No destination phases (those with no next phases) defined in recipe tuning: {}', recipe.__name__) return RecipeTestResult(enabled=False, visible=False, errors=error_list) available_first_phases = first_phases & available_phases available_dest_phases = dest_phases & available_phases def dijkstra_adj_available_nodes(current): for phase in current.next_phases: while phase in available_phases: yield phase def dijkstra_adj_nodes_gen(current): for phase in current.next_phases: yield phase def dijkstra_distance_function(current, adjacent): if adjacent is None or adjacent in available_phases: return 0 return 1 path = algos.shortest_path(available_first_phases, available_dest_phases.__contains__, dijkstra_adj_available_nodes) if not path: enabled = False if build_error_list: type_requirements = set() path = algos.shortest_path(first_phases, dest_phases.__contains__, dijkstra_adj_nodes_gen, dijkstra_distance_function) if path: for short_phase in path: if short_phase in available_phases: pass type_requirement = getattr(short_phase.super_affordance, 'crafting_type_requirement', None) while type_requirement is not None and type_requirement.unavailable_tooltip is not None: type_requirements.add(type_requirement) else: logger.error('No valid paths through phases defined in recipe tuning: {}', recipe.__name__) return RecipeTestResult(enabled=False, visible=False, errors=error_list) error_list.extend(type_requirement.unavailable_tooltip() for type_requirement in type_requirements) skill_test = recipe.skill_test resolver = SingleActorAndObjectResolver(sim_to_test.sim_info, target) if skill_test is not None: skill_result = resolver(skill_test) if not skill_result: if recipe.hidden_until_unlock and not from_resume: return RecipeTestResult(enabled=False, visible=False, errors=error_list) enabled = False if skill_result.tooltip is not None: error_list.append(skill_result.tooltip(sim_to_test, target)) if not from_resume or not recipe.additional_tests_ignored_on_resume: additional_tests = recipe.additional_tests if additional_tests: additional_result = additional_tests.run_tests(resolver) if not additional_result: if recipe.hidden_until_unlock and not from_resume: return RecipeTestResult(enabled=False, visible=False, errors=error_list) enabled = False if additional_result.tooltip is not None: error_list.append(additional_result.tooltip(sim_to_test, target)) return RecipeTestResult(enabled=enabled, visible=True, errors=error_list, influence_by_active_mood=additional_result.influence_by_active_mood) else: return RecipeTestResult(enabled=enabled, visible=True, errors=error_list, influence_by_active_mood=additional_result.influence_by_active_mood) utility_info = recipe.utility_info if utility_info is not None: household = services.owning_household_of_active_lot() if household is not None: utility_result = household.bills_manager.test_utility_info(utility_info) if not utility_result: if utility_result.tooltip is not None: error_list.append(utility_result.tooltip()) enabled = False return RecipeTestResult(enabled=enabled, visible=True, errors=error_list)
def on_enter(self): super().on_enter() owning_household = services.owning_household_of_active_lot() if owning_household is not None: owning_household.missing_pet_tracker.restore_missing_state() return _ZoneSpinUpStateResult.DONE