def transfer_entire_inventory(source, recipient): if source is None or recipient is None: raise ValueError('Attempt to transfer items from {} to {}.'.format(source, recipient)) lot = services.active_lot() if isinstance(source, InventoryType): source_inventory = lot.get_object_inventory(source) else: source_inventory = source.inventory_component if source_inventory is None: raise ValueError('Failed to find inventory component for source of inventory transfer: {}'.format(source)) recipient_is_inventory_type = isinstance(recipient, InventoryType) if recipient_is_inventory_type: recipient_inventory = lot.get_object_inventory(recipient) else: recipient_inventory = recipient.inventory_component if recipient_inventory is None: raise ValueError('Attempt to transfer items to an object that has no inventory component: {}'.format(recipient)) for obj in list(source_inventory): if not source_inventory.try_remove_object_by_id(obj.id, force_remove_stack=True): logger.warn('Failed to remove object {} from {} inventory', obj, source) if recipient_inventory.can_add(obj): if not recipient_is_inventory_type and recipient.is_sim: obj.update_ownership(recipient) recipient_inventory.system_add_object(obj, None if recipient_is_inventory_type else recipient) else: obj.set_household_owner_id(services.active_household_id()) build_buy.move_object_to_household_inventory(obj, object_location_type=ObjectOriginLocation.SIM_INVENTORY)
def _do_behavior(timeline): target = self.interaction.get_participant(self.participant) if target is None: return False target.fade_out() timespan = date_and_time.create_time_span( minutes=target.FADE_DURATION) yield element_utils.run_child(timeline, elements.SleepElement(timespan)) sim = self.interaction.sim target.set_household_owner_id(sim.household_id) replace_reserve = False if target.in_use_by(sim, owner=self.interaction): target.release(sim, self.interaction) replace_reserve = True try: if target == self.interaction.target: self.interaction.set_target(None) if self.use_sim_inventory: sim.inventory_component.system_add_object(target, sim) else: build_buy.move_object_to_household_inventory(target) finally: target.opacity = 1 if replace_reserve: target.reserve(sim, self.interaction) return True
def _drop_carried_object(self): if self.target is None: return if self.target_is_transient or self.target.parent is not self.sim: return if self.snap_to_good_location_on_floor(self.target): return if self.sim.household.id is self.target.get_household_owner_id( ) and self.sim.inventory_component.player_try_add_object(self.target): return placement_flags = build_buy.get_object_placement_flags( self.target.definition.id) if placement_flags & build_buy.PlacementFlags.NON_DELETEABLE and placement_flags & build_buy.PlacementFlags.NON_INVENTORYABLE: logger.error( "Failed to find a location to place {}, which cannot be deleted or moved to the household inventory. Object will be placed at the Sim's feet, but this is unsafe and will probably result in the object being destroyed on load.", self.target, owner='tastle') return if placement_flags & build_buy.PlacementFlags.NON_INVENTORYABLE: self.target.destroy( source=self.sim, cause= 'Failed to find location to drop non inventoryable object.') else: build_buy.move_object_to_household_inventory(self.target)
def release(self): target_object = self._target_object carry_component = target_object.get_component(CARRYABLE_COMPONENT) if carry_component is None: logger.error( 'Interaction ({0}) has a target ({1}) without a Carryable Component', self._interaction, target_object) return if target_object.parent is not self._parent: carry_component.reset_put_down_count() return if not carry_component.attempted_putdown or not carry_component.attempted_alternative_putdown or target_object.transient: new_context = self._interaction.context.clone_for_continuation( self._interaction) aop = target_object.get_put_down_aop(self._interaction, new_context) aop.test_and_execute(new_context) return if not CarryingObject.snap_to_good_location_on_floor(target_object): sim = self._interaction.sim if sim.household.id is not target_object.get_household_owner_id( ) or not sim.inventory_component.player_try_add_object( target_object): target_object.release_sim(sim) build_buy.move_object_to_household_inventory( target_object, failure_flags=HouseholdInventoryFlags.FORCE_OWNERSHIP)
def _do_behavior(timeline): target = self.interaction.get_participant(self.participant) if target is None: return False target.fade_out() timespan = date_and_time.create_time_span(minutes=target.FADE_DURATION) yield element_utils.run_child(timeline, elements.SleepElement(timespan)) sim = self.interaction.sim target.set_household_owner_id(sim.household_id) replace_reserve = False if target.in_use_by(sim, owner=self.interaction): target.release(sim, self.interaction) replace_reserve = True try: if target == self.interaction.target: self.interaction.set_target(None) if self.use_sim_inventory: sim.inventory_component.system_add_object(target, sim) else: build_buy.move_object_to_household_inventory(target) finally: target.opacity = 1 if replace_reserve: target.reserve(sim, self.interaction) return True
def create_and_place_baby(sim_info, **kwargs): bassinet = create_object(Baby.get_default_baby_def(), obj_id=sim_info.sim_id) bassinet.set_sim_info(sim_info, **kwargs) def try_to_place_bassinet(position, **kwargs): fgl_context = placement.FindGoodLocationContext(starting_position=position, object_id=sim_info.sim_id, search_flags=placement.FGLSearchFlagsDefault | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY, object_footprints=(bassinet.get_footprint(),), **kwargs) (translation, orientation) = placement.find_good_location(fgl_context) if translation is not None and orientation is not None: bassinet.move_to(translation=translation, orientation=orientation) return True return False lot = services.active_lot() for tag in Baby.BABY_PLACEMENT_TAGS: for (attempt, obj) in enumerate(services.object_manager().get_objects_with_tag_gen(tag)): position = obj.position if lot.is_position_on_lot(position) and try_to_place_bassinet(position, max_distance=10): return while attempt >= Baby.MAX_PLACEMENT_ATTEMPTS: break position = lot.get_default_position() if not try_to_place_bassinet(position): bassinet.update_ownership(sim_info, make_sim_owner=False) build_buy.move_object_to_household_inventory(bassinet) if sim_info.is_selectable: failed_placement_notification = Baby.FAILED_PLACEMENT_NOTIFICATION(sim_info, SingleSimResolver(sim_info)) failed_placement_notification.show_dialog()
def _place_object(self, created_object): if self._place_object_no_fallback(created_object): return True if not self.destroy_on_placement_failure: participant = self.interaction.get_participant( self.location.location_target) if participant.inventory_component is not None and created_object.inventoryitem_component is not None: 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) participant.inventory_component.system_add_object( created_object, participant) return True sim = self.interaction.sim if sim is not None: if not sim.household.is_npc_household: try: created_object.set_household_owner_id(sim.household.id) build_buy.move_object_to_household_inventory( created_object) return True except KeyError: pass self._placement_failed = True return False
def _transfer_object(self, target_household, obj, inventory_available, target_household_msg): obj.set_household_owner_id(target_household.id) if inventory_available: build_buy.move_object_to_household_inventory(obj) else: if target_household_msg is not None: object_data = obj.save_object(target_household_msg.inventory.objects) if object_data is not None: object_data.object_id = id_generator.generate_object_id() obj.destroy(cause='Merge/Transfer to New Household Inventory')
def push_items_to_household_inventory(self): client = services.client_manager().get_first_client() for obj in list(self._inventory_items.values()): if obj in client.live_drag_objects: client.cancel_live_drag(obj) while not obj.consumable_component is not None: if obj.has_servings_statistic(): pass try: while self.try_remove_object_by_id(obj.id, force_remove_stack=True): build_buy.move_object_to_household_inventory(obj, object_location_type=ObjectOriginLocation.SIM_INVENTORY) except Exception: logger.exception('{} failed to push object from inventory to household inventory', obj)
def open_reward(self, sim_info, is_household): obj = create_object(self._definition) if obj is None: logger.error('Trying to give an object reward to a Sim, {}, and the object created was None. Definition: {}'.format(sim_info, self._definition), owner='trevorlindsey') return if not is_household: sim = sim_info.get_sim_instance(allow_hidden_flags=ALL_HIDDEN_REASONS) if sim is None: logger.warn("Trying to give a sim an object, but the sim isn't instantiated. Adding object to household inventory instead", owner='trevorlindsey') elif sim.inventory_component.player_try_add_object(obj): obj.update_ownership(sim_info) return obj.update_ownership(sim_info, make_sim_owner=False) obj.set_post_bb_fixup_needed() build_buy.move_object_to_household_inventory(obj)
def _place_object (self, created_object, resolver = None, subject = None, placement_override_func = None): subject_to_apply = subject if subject is not None else resolver.get_participant(ParticipantType.Actor) created_object.update_ownership(subject_to_apply, make_sim_owner = self._make_sim_owner) if self._store_sim_info_on_reward is not None: stored_sim_source = resolver.get_participant(self._store_sim_info_on_reward.participant) if self._store_sim_info_on_reward.transfer_from_stored_sim_info: sim_id = stored_sim_source.get_stored_sim_id() else: sim_id = stored_sim_source.id if sim_id is not None: created_object.add_dynamic_component(types.STORED_SIM_INFO_COMPONENT, sim_id = sim_id) if self._store_sim_info_on_reward.transfer_from_stored_sim_info: stored_sim_source.remove_component(types.STORED_SIM_INFO_COMPONENT) created_object.update_object_tooltip() if placement_override_func is not None: placement_override_func(subject_to_apply, created_object) return if self._place_in_mailbox: sim_household = subject_to_apply.household if sim_household is not None: zone = services.get_zone(sim_household.home_zone_id) if zone is not None: lot_hidden_inventory = zone.lot.get_hidden_inventory() if lot_hidden_inventory is not None and lot_hidden_inventory.player_try_add_object(created_object): return if not self._force_family_inventory: instanced_sim = subject_to_apply.get_sim_instance(allow_hidden_flags = ALL_HIDDEN_REASONS) if instanced_sim is not None and instanced_sim.inventory_component.can_add(created_object) and instanced_sim.inventory_component.player_try_add_object(created_object): return if not build_buy.move_object_to_household_inventory(created_object): logger.error('Failed to add object reward {} to household inventory.', created_object, owner = 'rmccord')
def on_reservation_change(*_, **__): if not obj.in_use: obj.unregister_on_use_list_changed(on_reservation_change) object_location_type = ObjectOriginLocation.SIM_INVENTORY if obj.is_in_sim_inventory else ObjectOriginLocation.ON_LOT if not build_buy.move_object_to_household_inventory( obj, object_location_type=object_location_type): obj.schedule_destroy_asap()
def _do_behavior(self): obj = self.interaction.get_participant(self.participant) if obj is None: return sim = self.interaction.sim if sim is None: return stolen_component = obj.get_component( objects.components.types.STOLEN_COMPONENT) if stolen_component is None: logger.error( "Interaction: {} is attempting to use the ReturnStolenObject basic extra on an object that doesn't have the stolen component.", self.interaction) return obj.remove_from_client(fade_duration=obj.FADE_DURATION) stolen_from_household_id = stolen_component.stolen_from_household_id household = services.household_manager().get(stolen_from_household_id) if household is not None: obj.set_household_owner_id(household.id) def on_reservation_change(*_, **__): if not obj.in_use: obj.unregister_on_use_list_changed(on_reservation_change) object_location_type = ObjectOriginLocation.SIM_INVENTORY if obj.is_in_sim_inventory else ObjectOriginLocation.ON_LOT if not build_buy.move_object_to_household_inventory( obj, object_location_type=object_location_type): obj.schedule_destroy_asap() if obj.in_use: obj.register_on_use_list_changed(on_reservation_change) elif not build_buy.move_object_to_household_inventory(obj): obj.schedule_destroy_asap() else: obj.make_transient()
def on_choice_selected(self, choice_tag, **kwargs): mother = choice_tag if mother is None: return father = self.target transferable_states = {} for state in self._combine_data.states_to_combine: mother_state = mother.get_state(state) father_state = father.get_state(state) transferable_states[state] = [mother_state, father_state] for combine_data in self._combine_data.combination_mapping: if combine_data.father_state == father_state and combine_data.mother_state == mother_state: transferable_states[state].append( combine_data.resulting_state) if not transferable_states: logger.error( 'CollectionPickerInteraction: {} and {} collectibles have no transferable states', mother, father, owner='camilogarcia') return states_to_transfer = [] for states in transferable_states.values(): states_to_transfer.append(sims4.random.random.choice(states)) target_match = len(states_to_transfer) possible_outcomes = [] for collectable in self._collectible_data: match = 0 for target_states in collectable.collectable_item.cls._components.state._tuned_values.states: if target_states.default_value in states_to_transfer: match += 1 if match == target_match: possible_outcomes.append(collectable.collectable_item) if not possible_outcomes: logger.error( 'CollectionPickerInteraction: No possible result when combining {} and {}', mother, father, owner='camilogarcia') return definition_to_create = sims4.random.random.choice(possible_outcomes) obj = create_object(definition_to_create) if obj is None: logger.error( 'CollectionPickerInteraction: Failed to create object when combining {} and {}', mother, father, owner='camilogarcia') return obj.update_ownership(self.sim.sim_info) if not self.sim.inventory_component.player_try_add_object(obj): obj.set_household_owner_id(services.active_household_id()) if not build_buy.move_object_to_household_inventory( obj, object_location_type=ObjectOriginLocation.SIM_INVENTORY): logger.error( 'CollectionPickerInteraction: Failed to add object {} to household inventory.', obj, owner='rmccord') self._push_continuation(obj)
def end(_): sim = self.sim if object_to_create is not None and sim.is_selectable: obj = objects.system.create_object(object_to_create) if outcome_type == self.OUTCOME_TYPE_FISH: obj.initialize_fish(sim) self._apply_caught_fish_buff(obj) self._show_catch_fish_notification(sim, obj) self.super_interaction.kill_and_try_reapply_bait() elif outcome_type == self.OUTCOME_TYPE_TREASURE: self._show_catch_treasure_notification(sim, obj) obj.update_ownership(sim) if sim.inventory_component.can_add(obj): sim.inventory_component.player_try_add_object(obj) else: build_buy.move_object_to_household_inventory(obj)
def _fallback_placement(self, participant_to_unparent, parent_target): if not build_buy.move_object_to_household_inventory( participant_to_unparent): logger.error( 'Object {} failed to be moved to the household inventory', participant_to_unparent) participant_to_unparent.location = parent_target.location
def end(_): sim = self.sim if object_to_create is not None and sim.is_selectable: obj = objects.system.create_object(object_to_create) if outcome_type == self.OUTCOME_TYPE_FISH: obj.initialize_fish(sim) self._apply_caught_fish_buff(obj) self._show_catch_fish_notification(sim, obj) self.super_interaction.kill_and_try_reapply_bait() elif outcome_type == self.OUTCOME_TYPE_TREASURE: self._show_catch_treasure_notification(sim, obj) obj.update_ownership(sim) if sim.inventory_component.can_add(obj): sim.inventory_component.player_try_add_object(obj) else: build_buy.move_object_to_household_inventory(obj)
def _handle_children_of_sold_object(self, obj): retail_manager = services.business_service( ).get_retail_manager_for_zone() active_household_is_owner = retail_manager.is_owner_household_active should_show_notification = False for child in tuple(obj.children): if child.has_component(types.RETAIL_COMPONENT): child.retail_component.set_not_for_sale() if active_household_is_owner: should_show_notification = True build_buy.move_object_to_household_inventory(child) else: child.schedule_destroy_asap() if should_show_notification: notification = retail_manager.ITEMS_SENT_TO_HH_INVENTORY_NOTIFICATION( obj) notification.show_dialog()
def _drop_carried_object(self): if self.target is None: return if self.target_is_transient or self.target.parent is not self.sim: return if self.snap_to_good_location_on_floor(self.target): return if self.sim.household.id is self.target.get_household_owner_id() and self.sim.inventory_component.player_try_add_object(self.target): return placement_flags = build_buy.get_object_placement_flags(self.target.definition.id) if placement_flags & build_buy.PlacementFlags.NON_DELETEABLE and placement_flags & build_buy.PlacementFlags.NON_INVENTORYABLE: logger.error("Failed to find a location to place {}, which cannot be deleted or moved to the household inventory. Object will be placed at the Sim's feet, but this is unsafe and will probably result in the object being destroyed on load.", self.target, owner='tastle') return if placement_flags & build_buy.PlacementFlags.NON_INVENTORYABLE: self.target.destroy(source=self.sim, cause='Failed to find location to drop non inventoryable object.') else: build_buy.move_object_to_household_inventory(self.target)
def _add_fish_to_inventory(self, fish_object): if self.sim.inventory_component.can_add(fish_object): self.sim.inventory_component.player_try_add_object(fish_object) elif not build_buy.move_object_to_household_inventory(fish_object): logger.error( 'FishingInteractions: Failed to add object {} to household inventory.', fish_object, owner='rmccord')
def _finalize_death(self): if self._has_finalized_death: return self._has_finalized_death = True sim_info = self.sim.sim_info current_household = sim_info.household death_object = self._death_object_data[0] if death_object is not None: death_object.add_dynamic_component( types.STORED_SIM_INFO_COMPONENT.instance_attr, sim_id=sim_info.id) death_object.update_object_tooltip() death_object.set_household_owner_id(sim_info.household.id) if self._death_object_data[1]: build_buy.move_object_to_household_inventory(death_object) death_tracker = sim_info.death_tracker death_tracker.set_death_type(self.death_type) if self._client is not None: self._client.set_next_sim_or_none( only_if_this_active_sim_info=sim_info) self._client.selectable_sims.remove_selectable_sim_info(sim_info) if not any(sim.is_teen_or_older for sim in self._client.selectable_sims): self._show_death_dialog() persistence_service = services.get_persistence_service() sim_info_manager = services.sim_info_manager() for selectable_sim_info in self._client.selectable_sims: sim_id = selectable_sim_info.id sim_to_destroy = selectable_sim_info.get_sim_instance( allow_hidden_flags=ALL_HIDDEN_REASONS) if sim_to_destroy is not None: sim_to_destroy.destroy( source=sim_to_destroy, cause= 'Last adult sim dieing, destroying dependent sims.' ) persistence_service.del_sim_proto_buff(sim_id) sim_info_manager.remove_permanently(selectable_sim_info) self._client.clear_selectable_sims() zone_id = services.current_zone_id() current_household.clear_household_lot_ownership(zone_id) current_household.hidden = True fire_service = services.get_fire_service() if fire_service is not None: fire_service.kill()
def transfer_inactive_household_inventory(self, source_household, target_household): if build_buy.is_household_inventory_available(source_household.id): object_ids = build_buy.get_object_ids_in_household_inventory(source_household.id) for object_id in object_ids: object_data_raw = _buildbuy.get_object_data_in_household_inventory(object_id, source_household.id) obj = self._create_object_from_raw_inv_data(object_id, object_data_raw) build_buy.remove_object_from_household_inventory(object_id, source_household) obj.set_household_owner_id(target_household.id) build_buy.move_object_to_household_inventory(obj) else: del household_msg.inventory.objects[:] else: household_msg = services.get_persistence_service().get_household_proto_buff(source_household.id) if household_msg is not None: for object_msg in household_msg.inventory.objects: obj = self._create_object_from_object_data(object_msg.object_id, object_msg) obj.set_household_owner_id(target_household.id) build_buy.move_object_to_household_inventory(obj) del household_msg.inventory.objects[:]
def on_choice_selected(self, choice_tag, **kwargs): mother = choice_tag if mother is None: return father = self.target transferable_states = {} for state in self._combine_data.states_to_combine: mother_state = mother.get_state(state) father_state = father.get_state(state) transferable_states[state] = [mother_state, father_state] for combine_data in self._combine_data.combination_mapping: while combine_data.father_state == father_state and combine_data.mother_state == mother_state: transferable_states[state].append(combine_data.resulting_state) if not transferable_states: logger.error('CollectionPickerInteraction: {} and {} collectibles have no transferable states', mother, father, owner='camilogarcia') return states_to_transfer = [] for states in transferable_states.values(): states_to_transfer.append(sims4.random.random.choice(states)) target_match = len(states_to_transfer) possible_outcomes = [] for collectable in self._collectible_data: match = 0 for target_states in collectable.collectable_item.cls._components.state._tuned_values.states: while target_states.default_value in states_to_transfer: match += 1 while match == target_match: possible_outcomes.append(collectable.collectable_item) if not possible_outcomes: logger.error('CollectionPickerInteraction: No possible result when combining {} and {}', mother, father, owner='camilogarcia') return definition_to_create = sims4.random.random.choice(possible_outcomes) obj = create_object(definition_to_create) if obj is None: logger.error('CollectionPickerInteraction: Failed to create object when combining {} and {}', mother, father, owner='camilogarcia') return obj.update_ownership(self.sim.sim_info) if not self.sim.inventory_component.player_try_add_object(obj): obj.set_household_owner_id(services.active_household_id()) build_buy.move_object_to_household_inventory(obj, object_location_type=ObjectOriginLocation.SIM_INVENTORY) self._push_continuation(obj)
def release(self): target_object = self._interaction.target if target_object is None: return carry_component = target_object.get_component(CARRYABLE_COMPONENT) if carry_component is None: logger.error('Interaction ({0}) has a target ({1}) without a Carryable Component', self._interaction, self._interaction.target) return if target_object.parent is not self._parent: carry_component.reset_put_down_count() return if not carry_component.attempted_putdown or not carry_component.attempted_alternative_putdown or target_object.transient: new_context = self._interaction.context.clone_for_continuation(self._interaction) aop = target_object.get_put_down_aop(self._interaction, new_context) aop.test_and_execute(new_context) return if not CarryingObject.snap_to_good_location_on_floor(target_object): sim = self._interaction.sim if sim.household.id is not target_object.get_household_owner_id() or not sim.inventory_component.player_try_add_object(target_object): target_object.release_sim(sim) build_buy.move_object_to_household_inventory(target_object)
def _place_object(self, created_object, resolver=None): actor = resolver.get_participant( ParticipantType.Actor).get_sim_instance( allow_hidden_flags=ALL_HIDDEN_REASONS) created_object.update_ownership(actor, make_sim_owner=False) if self._transfer_stored_sim_info_to_reward is not None: stored_sim_source = resolver.get_participant( self._transfer_stored_sim_info_to_reward) sim_id = stored_sim_source.get_stored_sim_id() if sim_id is not None: created_object.add_dynamic_component( types.STORED_SIM_INFO_COMPONENT.instance_attr, sim_id=sim_id) stored_sim_source.remove_component( types.STORED_SIM_INFO_COMPONENT.instance_attr) created_object.update_object_tooltip() if self._force_family_inventory or actor.inventory_component.can_add( created_object): if actor.inventory_component.player_try_add_object(created_object): return build_buy.move_object_to_household_inventory(created_object)
def place_in_good_location(self, position=None, routing_surface=None): plex_service = services.get_plex_service() is_active_zone_a_plex = plex_service.is_active_zone_a_plex() def try_to_place_bassinet(position, routing_surface=None, **kwargs): starting_location = placement.create_starting_location( position=position, routing_surface=routing_surface) fgl_context = placement.create_fgl_context_for_object( starting_location, self, **kwargs) (translation, orientation) = placement.find_good_location(fgl_context) if translation is not None and orientation is not None: if is_active_zone_a_plex and ( routing_surface is None or plex_service.get_plex_zone_at_position( translation, routing_surface.secondary_id) is None): return False else: self.move_to(translation=translation, orientation=orientation) if routing_surface is not None: self.move_to(routing_surface=routing_surface) return True return False if position is not None and try_to_place_bassinet( position, routing_surface=routing_surface): return True lot = services.active_lot() for tag in Baby.BABY_PLACEMENT_TAGS: for (attempt, obj) in enumerate( services.object_manager().get_objects_with_tag_gen(tag)): position = obj.position routing_surface = obj.routing_surface if lot.is_position_on_lot(position) and try_to_place_bassinet( position, routing_surface=routing_surface, max_distance=10): return if attempt >= Baby.MAX_PLACEMENT_ATTEMPTS: break position = lot.get_default_position() if not try_to_place_bassinet(position): self.update_ownership(self.sim_info, make_sim_owner=False) if not build_buy.move_object_to_household_inventory(self): logger.error( 'Failed to place bassinet in household inventory.', owner='rmccord') if self.is_selectable: failed_placement_notification = Baby.FAILED_PLACEMENT_NOTIFICATION( self.sim_info, SingleSimResolver(self.sim_info)) failed_placement_notification.show_dialog()
def _finalize_death(self): if self._has_finalized_death: return self._has_finalized_death = True sim_info = self.sim.sim_info current_household = sim_info.household death_object = self._death_object_data[0] if death_object is not None: death_object.add_dynamic_component(types.STORED_SIM_INFO_COMPONENT, sim_id=sim_info.id) death_object.update_object_tooltip() active_household = services.active_household() death_object.set_household_owner_id(active_household.id) if self._death_object_data[1]: try: if not build_buy.move_object_to_household_inventory( death_object): logger.error( 'Failed to place an urnstone for {} in household inventory: {}', sim_info, sim_info.household.id) except KeyError: logger.exception( 'Failed to place an urnstone for {} in household inventory: {}', sim_info, sim_info.household.id) death_tracker = sim_info.death_tracker death_type = None if self.death_info is not None: death_type = self.death_info.death_type death_tracker.set_death_type(death_type) if self.death_info is None or self.death_info.set_to_minimum_lod: sim_info.request_lod(SimInfoLODLevel.MINIMUM) if self._client is not None: self._client.set_next_sim_or_none( only_if_this_active_sim_info=sim_info) self._client.selectable_sims.remove_selectable_sim_info(sim_info) kill_all_fires = False if any(sim.can_live_alone for sim in self._client.selectable_sims): if self._show_off_lot_death_notification(): kill_all_fires = True else: kill_all_fires = True self._disband_travel_group() self._show_death_dialog() self._client.clear_selectable_sims() if kill_all_fires: fire_service = services.get_fire_service() if fire_service is not None: fire_service.kill() current_household.handle_adultless_household() services.daycare_service().refresh_household_daycare_nanny_status( sim_info)
def create_and_place_baby(sim_info, **kwargs): bassinet = create_object(Baby.get_default_baby_def(), obj_id=sim_info.sim_id) bassinet.set_sim_info(sim_info, **kwargs) def try_to_place_bassinet(position, **kwargs): fgl_context = placement.FindGoodLocationContext( starting_position=position, object_id=sim_info.sim_id, search_flags=placement.FGLSearchFlagsDefault | placement.FGLSearchFlag.SHOULD_TEST_BUILDBUY, object_footprints=(bassinet.get_footprint(), ), **kwargs) (translation, orientation) = placement.find_good_location(fgl_context) if translation is not None and orientation is not None: bassinet.move_to(translation=translation, orientation=orientation) return True return False lot = services.active_lot() for tag in Baby.BABY_PLACEMENT_TAGS: for (attempt, obj) in enumerate( services.object_manager().get_objects_with_tag_gen(tag)): position = obj.position if lot.is_position_on_lot(position) and try_to_place_bassinet( position, max_distance=10): return while attempt >= Baby.MAX_PLACEMENT_ATTEMPTS: break position = lot.get_default_position() if not try_to_place_bassinet(position): bassinet.update_ownership(sim_info, make_sim_owner=False) build_buy.move_object_to_household_inventory(bassinet) if sim_info.is_selectable: failed_placement_notification = Baby.FAILED_PLACEMENT_NOTIFICATION( sim_info, SingleSimResolver(sim_info)) failed_placement_notification.show_dialog()
def _do_behavior(self): objects = self.objects_to_transfer.get_objects(self.interaction) if not objects: return False transfer_extra = self.transfer_extra_objects should_transfer_extra = False if transfer_extra: resolver = self.interaction.get_resolver() if transfer_extra.tests.run_tests(resolver): should_transfer_extra = True objects_to_transfer = [] num_extra_objects = 0 for obj in objects: has_extra_to_transfer = False for child_inst in obj.children: interaction_parameters = {'picked_item_ids': (child_inst.id, )} resolver = self.interaction.get_resolver( **interaction_parameters) if self.object_tests.run_tests(resolver): objects_to_transfer.append(child_inst) has_extra_to_transfer = True if should_transfer_extra: if has_extra_to_transfer: num_extra_objects += transfer_extra.count.random_int() stacked_objects = self._stack_objects_transfer(objects_to_transfer, num_extra_objects) sim = self.interaction.sim sim_inventory = sim.inventory_component for (obj, _) in stacked_objects: obj.update_ownership(sim) if sim_inventory.can_add(obj): if obj.live_drag_component is not None: obj.live_drag_component.resolve_live_drag_household_permission( ) sim_inventory.player_try_add_object(obj) elif self.fallback_to_household_inventory: build_buy.move_object_to_household_inventory(obj)
def _place_object(self, created_object): if self._place_object_no_fallback(created_object): return True if not self.destroy_on_placement_failure: participant = self.interaction.get_participant(self.location.location_target) if participant.inventory_component is not None and created_object.inventoryitem_component is not None: 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) participant.inventory_component.system_add_object(created_object, participant) return True sim = self.interaction.sim if sim is not None: if not sim.household.is_npc_household: try: created_object.set_household_owner_id(sim.household.id) build_buy.move_object_to_household_inventory(created_object) return True except KeyError: pass self._placement_failed = True return False
def _finalize_death(self): if self._has_finalized_death: return self._has_finalized_death = True sim_info = self.sim.sim_info current_household = sim_info.household death_object = self._death_object_data[0] if death_object is not None: death_object.add_dynamic_component(types.STORED_SIM_INFO_COMPONENT.instance_attr, sim_id=sim_info.id) death_object.update_object_tooltip() death_object.set_household_owner_id(sim_info.household.id) if self._death_object_data[1]: build_buy.move_object_to_household_inventory(death_object) death_tracker = sim_info.death_tracker death_tracker.set_death_type(self.death_type) if self._client is not None: self._client.set_next_sim_or_none(only_if_this_active_sim_info=sim_info) self._client.selectable_sims.remove_selectable_sim_info(sim_info) if not any(sim.is_teen_or_older for sim in self._client.selectable_sims): self._show_death_dialog() persistence_service = services.get_persistence_service() sim_info_manager = services.sim_info_manager() for selectable_sim_info in self._client.selectable_sims: sim_id = selectable_sim_info.id sim_to_destroy = selectable_sim_info.get_sim_instance(allow_hidden_flags=ALL_HIDDEN_REASONS) if sim_to_destroy is not None: sim_to_destroy.destroy(source=sim_to_destroy, cause='Last adult sim dieing, destroying dependent sims.') persistence_service.del_sim_proto_buff(sim_id) sim_info_manager.remove_permanently(selectable_sim_info) self._client.clear_selectable_sims() zone_id = services.current_zone_id() current_household.clear_household_lot_ownership(zone_id) current_household.hidden = True fire_service = services.get_fire_service() if fire_service is not None: fire_service.kill()
def _try_create_in_household_inventory(self, sim_info, obj=None): obj = create_object( self._definition, loc_type=ItemLocation.HOUSEHOLD_INVENTORY) if obj is None else obj if obj is None: logger.error( 'Trying to give an object reward to a Sim, {}, and the object created was None. Definition: {}', sim_info, self._definition) return (False, None) obj.update_ownership(sim_info, make_sim_owner=False) obj.set_post_bb_fixup_needed() if not build_buy.move_object_to_household_inventory(obj): logger.error( 'Failed to add reward definition object {} to household inventory.', self._definition, owner='rmccord')
def create_object_and_add_to_inventory(self, sim, object_to_create, is_fish): if object_to_create is not None and sim.is_selectable: created_object = objects.system.create_object(object_to_create) if created_object is not None: created_object.update_ownership(sim) if is_fish: created_object.initialize_fish(sim) if sim.inventory_component.can_add(created_object): sim.inventory_component.player_try_add_object( created_object) elif not build_buy.move_object_to_household_inventory( created_object): logger.error( 'FishingInteractions: Failed to add object {} to household inventory.', created_object, owner='rmccord') return created_object
def _give_objects_for_collection_type(self, **kwargs): for obj_def in self._object_definitions_gen(): obj = create_object(obj_def) if obj is None: logger.error( 'AwardCollectiblesInteraction: Failed to create object {}', obj_def, owner='jdimailig') else: obj.update_ownership(self.sim.sim_info) if not self.sim.inventory_component.player_try_add_object(obj): obj.set_household_owner_id(services.active_household_id()) if not build_buy.move_object_to_household_inventory( obj, object_location_type=ObjectOriginLocation. SIM_INVENTORY): logger.error( 'AwardCollectiblesInteraction: Failed to add object {} to household inventory.', obj, owner='jdimailig')
def _handle_parented_objects(self, obj): objects_in_household_inventory = [] for child_obj in tuple(obj.children): if self._allow_destruction_on_inventory_transfer(child_obj): child_obj.destroy(source=self.owner, cause='Parent is being inventoried.') else: if self.player_try_add_object(child_obj): continue if build_buy.move_object_to_household_inventory(child_obj): objects_in_household_inventory.append(child_obj) else: world_obj = self.owner fgl_context_fn = create_fgl_context_for_object if world_obj.is_on_active_lot( ) else create_fgl_context_for_object_off_lot fgl_starting_location = create_starting_location( position=world_obj.position) (translation, orientation) = find_good_location( fgl_context_fn(fgl_starting_location, child_obj)) if translation is not None and orientation is not None: child_obj.set_parent( None, transform=sims4.math.Transform( translation, orientation), routing_surface=world_obj.routing_surface) else: child_obj.destroy( source=self.owner, cause= "Parent is being inventoried and object can't be placed anywhere." ) if objects_in_household_inventory and self.PARENTED_OBJECT_MOVED_TO_HOUSEHOLD_INVENTORY_NOTIFICATION is not None: sim_info = self.owner.sim_info if self.owner.is_sim else services.active_sim_info( ) notification = self.PARENTED_OBJECT_MOVED_TO_HOUSEHOLD_INVENTORY_NOTIFICATION( sim_info, resolver=SingleObjectResolver(obj)) notification.show_dialog( additional_tokens=(LocalizationHelperTuning.get_bulleted_list( None, *(LocalizationHelperTuning.get_object_name(obj) for obj in objects_in_household_inventory)), ))
def push_items_to_household_inventory(self): client = services.client_manager().get_first_client() for obj in list(self._storage): if obj in client.live_drag_objects: client.cancel_live_drag(obj) if self._allow_destruction_on_inventory_transfer(obj): continue try: if self.try_remove_object_by_id( obj.id, count=obj.stack_count() ) and not build_buy.move_object_to_household_inventory( obj, object_location_type=ObjectOriginLocation.SIM_INVENTORY ): logger.error( '{} failed to push object from inventory to household inventory', obj) except Exception: logger.exception( '{} failed to push object from inventory to household inventory', obj)
def _return_lost_object(self, locator): sim_info = services.sim_info_manager().get(locator.sim_id) object_id = locator.object_data.object_id if sim_info is not None and sim_info.is_instanced(): if sim_info.zone_id != locator.zone_id and not self._any_household_member_on_lot( locator.zone_id, sim_info.household.id, sim_info.id): sim = sim_info.get_sim_instance( allow_hidden_flags=ALL_HIDDEN_REASONS) if sim is None: return (None, None) obj = create_object(locator.object_data.guid, loc_type=ItemLocation.SIM_INVENTORY) if obj is not None: obj.attributes = locator.object_data.SerializeToString() obj.scale = locator.object_data.scale if sim.inventory_component.player_try_add_object(obj): obj.update_ownership(sim_info) self.remove_object(object_id) self.add_clone_id(locator.zone_id, locator.open_street_id, object_id) return (obj, sim) obj.destroy( source=self, cause='Failed to add object to Sim Inv, try later') return (None, None) elif sim_info is None and not self._any_household_member_on_lot( locator.zone_id, locator.household_id, locator.sim_id): obj = create_object(locator.object_data.guid, loc_type=ItemLocation.HOUSEHOLD_INVENTORY) if obj is not None: obj.attributes = locator.object_data.SerializeToString() obj.scale = locator.object_data.scale if build_buy.move_object_to_household_inventory( obj, HouseholdInventoryFlags.FORCE_OWNERSHIP): self.remove_object(object_id) self.add_clone_id(locator.zone_id, locator.open_street_id, object_id) return (obj, locator.household_id) return (None, None)
def transfer_entire_inventory(source, recipient, interaction=None, object_tests=None, household_id=None): if source is None or recipient is None: raise ValueError('Attempt to transfer items from {} to {}.'.format( source, recipient)) lot = services.active_lot() if isinstance(source, InventoryType): source_inventories = lot.get_object_inventories(source) else: source_inventories = (source.inventory_component, ) if len(source_inventories) == 0 or None in source_inventories: raise ValueError( 'Failed to find inventory component for source of inventory transfer: {}' .format(source)) recipient_is_inventory_type = isinstance(recipient, InventoryType) if recipient_is_inventory_type: recipient_inventories = lot.get_object_inventories(recipient) if len(recipient_inventories) > 1: if InventoryTypeTuning.is_shared_between_objects(recipient): raise ValueError( 'Attempt to transfer into inventory type with multiple nonshared inventories: {}' .format(recipient)) if household_id is not None: recipient_inventories = [ inventory for inventory in recipient_inventories if inventory.owner.get_household_owner_id() == household_id ] if len(recipient_inventories) != 1: raise ValueError( 'Attempt to transfer into inventory type with multiple nonshared inventories: {}' .format(recipient)) recipient_inventory = recipient_inventories[0] else: recipient_inventory = recipient.inventory_component if recipient_inventory is None: raise ValueError( 'Attempt to transfer items to an object that has no inventory component: {}' .format(recipient)) for source_inventory in source_inventories: for obj in list(source_inventory): if interaction is not None and object_tests: interaction.interaction_parameters[ 'picked_item_ids'] = frozenset((obj.id, )) resolver = interaction.get_resolver() if not object_tests.run_tests(resolver): continue elif not source_inventory.try_remove_object_by_id( obj.id, count=obj.stack_count()): logger.warn('Failed to remove object {} from {} inventory', obj, source) elif recipient_inventory.can_add(obj): if not recipient_is_inventory_type and recipient.is_sim: obj.update_ownership(recipient) recipient_inventory.system_add_object(obj) else: obj.set_household_owner_id(services.active_household_id()) build_buy.move_object_to_household_inventory( obj, object_location_type=ObjectOriginLocation.SIM_INVENTORY)
def _do_behavior(self): sim = self.interaction.sim target = self.interaction.get_participant(self.participant) if target is None: return False should_fallback = False inventory_participant = sim if target.is_in_inventory(): inventory = target.get_inventory() inventory.try_remove_object_by_id(target.id) if self.inventory.inventory_type == SendToInventory.PARTICIPANT_INVENTORY: inventory_participant = self.interaction.get_participant( self.inventory.participant) if inventory_participant.is_sim: target.update_ownership(inventory_participant, make_sim_owner=self.give_sim_ownership) inventory_component = inventory_participant.inventory_component if not inventory_component.player_try_add_object(target): should_fallback = self.inventory.fallback_to_household else: for interaction in tuple(target.interaction_refs): if not interaction.running: if interaction.is_finishing: continue if inventory_participant.is_sim: if not interaction.allow_from_sim_inventory: interaction.cancel( FinishingType.OBJECT_CHANGED, cancel_reason_msg= 'Object moved to inventory') if not interaction.allow_from_object_inventory: interaction.cancel( FinishingType.OBJECT_CHANGED, cancel_reason_msg= 'Object moved to inventory') elif not interaction.allow_from_object_inventory: interaction.cancel( FinishingType.OBJECT_CHANGED, cancel_reason_msg='Object moved to inventory') if self.inventory.inventory_type == SendToInventory.MAILBOX_INVENTORY: if not inventory_participant.is_sim: logger.error( 'Trying to add an item [{}] to a mailbox but the participant [{}] is not a sim', target.definition, inventory_participant) return False target.set_household_owner_id(inventory_participant.household_id) zone = services.get_zone( inventory_participant.household.home_zone_id) if zone is None: logger.error( 'Trying to add an item [{}] to a mailbox but the provided sim [{}] has no home zone.', target.definition, inventory_participant) return False lot_hidden_inventory = zone.lot.get_hidden_inventory() if lot_hidden_inventory is None: logger.error( "Trying to add an item [{}] to the lot's hidden inventory but the provided sim [{}] has no hidden inventory for their lot.", target.definition, inventory_participant) return False lot_hidden_inventory.system_add_object(target) for interaction in tuple(target.interaction_refs): if not interaction.running: if interaction.is_finishing: continue interaction.cancel( FinishingType.OBJECT_CHANGED, cancel_reason_msg='Object moved to inventory') elif self.inventory.inventory_type == SendToInventory.HOUSEHOLD_INVENTORY or should_fallback: def on_reservation_change(*_, **__): if not target.in_use: target.unregister_on_use_list_changed( on_reservation_change) build_buy.move_object_to_household_inventory(target) if target is self.interaction.target: self.interaction.set_target(None) if inventory_participant is not None and inventory_participant.is_sim: target.set_household_owner_id( inventory_participant.household_id) target.remove_from_client(fade_duration=target.FADE_DURATION) if target.in_use: target.register_on_use_list_changed(on_reservation_change) else: build_buy.move_object_to_household_inventory(target)
def on_reservation_change(*_, **__): if not target.in_use: target.unregister_on_use_list_changed( on_reservation_change) build_buy.move_object_to_household_inventory(target)