def get_score(self, position, orientation, routing_surface): target_sim = self._target_sim_ref() if self._target_sim_ref is not None else None if target_sim is None: return 1 accum = accumulator.HarmonicMeanAccumulator() candidate_facing = sims4.math.yaw_quaternion_to_angle(orientation) other_facing = sims4.math.yaw_quaternion_to_angle(target_sim.intended_transform.orientation) delta = target_sim.intended_transform.translation - position socials.geometry.score_facing(accum, candidate_facing, other_facing, delta) return accum.value()
def score_transform(transform, sim, group_geometry, r, base_focus, base_field): accum = accumulator.HarmonicMeanAccumulator() dist = group_geometry.minimum_distance(transform.translation, group_geometry.members, skip=sim) in_group_dist_score = SocialGeometry.GROUP_DISTANCE_CURVE.get(dist) accum.add(in_group_dist_score) if accum.fault(): return 0 candidate_geometry = create_from_transform(transform, base_focus, base_field, r) candidate_area = candidate_geometry.field.area() if candidate_area <= sims4.math.EPSILON: return 0 candidate_facing = sims4.math.yaw_quaternion_to_angle( transform.orientation) for (other_sim, geometry) in group_geometry.members.items(): if other_sim is sim: continue other_facing = sims4.math.yaw_quaternion_to_angle( geometry.transform.orientation) delta = geometry.transform.translation - transform.translation score_facing(accum, candidate_facing, other_facing, delta) intersection = geometry.field.intersect(candidate_geometry.field) fraction = intersection.area() / candidate_area fraction = SocialGeometry.OVERLAP_SCORE_MULTIPLIER * max( fraction, SocialGeometry.NON_OVERLAPPING_SCORE_MULTIPLIER) accum.add(fraction) if accum.fault(): return 0 nearby_non_members = list( placement.get_nearby_sims_gen(transform.translation, sim.routing_surface, exclude=group_geometry, check_all_surfaces_on_level=True)) if sim in nearby_non_members: nearby_non_members.remove(sim) if nearby_non_members: nearest = group_geometry.minimum_distance(transform.translation, nearby_non_members) not_in_group_score = SocialGeometry.NON_GROUP_DISTANCE_CURVE.get( nearest) accum.add(not_in_group_score) return accum.value()
def build_relationship_bonuses(sim, sim_affinity_posture_scoring_data, sims_to_consider=None): bonuses = {} posture_graph = services.current_zone().posture_graph_service if not sims_to_consider: sims_to_consider = ( other_sim_info.get_sim_instance() for other_sim_info in services.sim_info_manager().objects if other_sim_info.is_instanced()) obj_to_cluster = {} clusters = list( services.social_group_cluster_service().get_clusters_gen()) for cluster in clusters: for obj in cluster.objects_gen(): obj_to_cluster[obj] = cluster relationship_tracker = sim.relationship_tracker most_important_ensemble = services.ensemble_service( ).get_most_important_ensemble_for_sim(sim) for other_sim in sims_to_consider: if other_sim is sim: continue if other_sim.posture.unconstrained: continue if other_sim.is_moving: continue if not other_sim.posture.allow_affinity: continue scores = [] zone_director = services.venue_service().get_zone_director() if sim_affinity_posture_scoring_data is not None: if not zone_director.disable_sim_affinity_posture_scoring(sim): tags = set() for si in other_sim.si_state: if si.sim_affinity_posture_scoring_data is not None: tags.update( si.sim_affinity_posture_scoring_data.my_tags) for scoring_strategy in sim_affinity_posture_scoring_data.my_scoring: match_tag = scoring_strategy.running_interaction_tag if match_tag == InteractionPostureAffinityTag.ALL: match = True else: match = (match_tag in tags) != scoring_strategy.negate_tag if not match: continue (affinity, message) = scoring_strategy.affinity_strategy( sim, other_sim) if not affinity: continue scores.append((affinity, message)) if most_important_ensemble is not None and most_important_ensemble.is_sim_in_ensemble( other_sim): scores.append((-PostureScoring.ENSEMBLE_BONUS, PostureScoring.ENSEMBLE_BONUS_MESSAGE)) elif not zone_director.disable_sim_affinity_posture_scoring( sim) and not relationship_tracker.has_bit( other_sim.sim_id, RelationshipGlobalTuning.HAS_MET_RELATIONSHIP_BIT): scores.append((PostureScoring.HAS_NOT_MET_PENALTY, PostureScoring.HAS_NOT_MET_COST_MESSAGE)) if not scores: pass else: other_sim_cluster = None other_sim_body_target = other_sim.posture_state.body_target if other_sim_body_target is not None: if other_sim_body_target.is_part: other_sim_body_target = other_sim_body_target.part_owner other_sim_cluster = obj_to_cluster.get( other_sim_body_target) other_sim_facing = sims4.math.yaw_quaternion_to_angle( other_sim.transform.orientation) distances = {} nodes_in_sight = posture_graph.nodes_matching_constraint_geometry( other_sim.los_constraint) for goal_node in nodes_in_sight: goal_body = goal_node[postures.posture_specs.BODY_INDEX] goal_body_target = goal_body[ postures.posture_specs.BODY_TARGET_INDEX] goal_posture_type = goal_body[ postures.posture_specs.BODY_POSTURE_TYPE_INDEX] if not goal_body_target is None: if goal_posture_type.mobile: continue distance = distances.get(goal_body_target) if distance is None: sim_facing = sims4.math.yaw_quaternion_to_angle( goal_body_target.transform.orientation) accum = accumulator.HarmonicMeanAccumulator() delta = other_sim.transform.translation - goal_body_target.transform.translation socials.geometry.score_facing( accum, sim_facing, other_sim_facing, delta) facing_score = accum.value() if facing_score <= 0: continue distance = (goal_body_target.position - other_sim.position).magnitude_2d() distance = max(distance, 1) distance /= facing_score distances[goal_body_target] = distance bonus = 0 all_messages = [] distance_modifier = RelationshipSimAffinityStrategy.DISTANCE_TO_IMPACT_CURVE.get( distance) for (affinity, message) in scores: affinity_weighted = affinity * distance_modifier bonus += affinity_weighted if not bonus: pass else: if goal_body_target.is_part: goal_object = goal_body_target.part_owner else: goal_object = goal_body_target if goal_object in obj_to_cluster: same_cluster = obj_to_cluster[ goal_object] is other_sim_cluster else: same_cluster = False if same_cluster: bonus *= PostureScoring.SAME_CLUSTER_SIM_MULTIPLIER current_bonus_info = bonuses.get(goal_body_target) if not current_bonus_info is None: if bonus < current_bonus_info[0]: formatted_message = '' bonuses[goal_body_target] = ( bonus, formatted_message) formatted_message = '' bonuses[goal_body_target] = (bonus, formatted_message) obj_to_cluster.clear() return bonuses
def build_relationship_bonuses(sim, sim_affinity_posture_scoring_data, sims_to_consider=None): if sim_affinity_posture_scoring_data is None: return bonuses = {} posture_graph = services.current_zone().posture_graph_service if not sims_to_consider: sims_to_consider = ( other_sim_info.get_sim_instance() for other_sim_info in services.sim_info_manager().objects if other_sim_info.is_instanced()) obj_to_cluster = {} clusters = list( services.social_group_cluster_service().get_clusters_gen()) for cluster in clusters: for obj in cluster.objects_gen(): obj_to_cluster[obj] = cluster for other_sim in sims_to_consider: if other_sim is sim: pass if other_sim.posture.unconstrained: pass if other_sim.is_moving: pass if not other_sim.posture.allow_affinity: pass scores = [] other_sim_cluster = None other_sim_body_target = other_sim.posture_state.body_target if other_sim_body_target.is_part: other_sim_body_target = other_sim_body_target.part_owner other_sim_cluster = obj_to_cluster.get(other_sim_body_target) for scoring_strategy in sim_affinity_posture_scoring_data.my_scoring: match_tag = scoring_strategy.running_interaction_tag if match_tag == InteractionPostureAffinityTag.ALL: match = True else: match = False for si in other_sim.si_state: while si.sim_affinity_posture_scoring_data is not None and match_tag in si.sim_affinity_posture_scoring_data.my_tags: if not scoring_strategy.negate_tag: match = True break if scoring_strategy.negate_tag: match = True if not match: pass (affinity, message) = scoring_strategy.affinity_strategy(sim, other_sim) if not affinity: pass scores.append((affinity, message)) if not (other_sim_body_target is not None and scores): pass other_sim_facing = sims4.math.yaw_quaternion_to_angle( other_sim.transform.orientation) distances = {} nodes_in_sight = posture_graph.nodes_matching_constraint_geometry( other_sim.los_constraint) for goal_node in nodes_in_sight: goal_body = goal_node[BODY_INDEX] goal_body_target = goal_body[BODY_TARGET_INDEX] goal_posture_type = goal_body[BODY_POSTURE_TYPE_INDEX] while not goal_body_target is None: if goal_posture_type.mobile: pass distance = distances.get(goal_body_target) if distance is None: sim_facing = sims4.math.yaw_quaternion_to_angle( goal_body_target.transform.orientation) accum = accumulator.HarmonicMeanAccumulator() delta = other_sim.transform.translation - goal_body_target.transform.translation socials.geometry.score_facing(accum, sim_facing, other_sim_facing, delta) facing_score = accum.value() if facing_score <= 0: pass distance = (goal_body_target.position - other_sim.position).magnitude_2d() distance = max(distance, 1) distance /= facing_score distances[goal_body_target] = distance bonus = 0 all_messages = [] for (affinity, message) in scores: affinity_weighted = affinity / distance bonus += affinity_weighted if not bonus: pass if goal_body_target.is_part: goal_object = goal_body_target.part_owner else: goal_object = goal_body_target if goal_object in obj_to_cluster: same_cluster = obj_to_cluster[ goal_object] is other_sim_cluster else: same_cluster = False if same_cluster: bonus *= PostureScoring.SAME_CLUSTER_SIM_MULTIPLIER current_bonus_info = bonuses.get(goal_body_target) while current_bonus_info is None or bonus < current_bonus_info[ 0]: formatted_message = '' bonuses[goal_body_target] = (bonus, formatted_message) obj_to_cluster.clear() return bonuses