sub_schema.add_field('type', label='Type', width=25) sub_schema.add_field('data', label='Data', width=25) with animation_archive_schema.add_has_many('Events', GsiGridSchema) as sub_schema: sub_schema.add_field('clip_name', label='Clip Name', width=20) sub_schema.add_field('type', label='Type', width=15) sub_schema.add_field('event_id', label='ID', width=5, visualizer=GsiFieldVisualizers.INT) sub_schema.add_field('callbacks', label='Callbacks', width=30) sub_schema.add_field('event_data', label='Event Data', width=30) sub_schema.add_field('tag', label='Tag', width=5) sub_schema.add_field('errors', label='Errors', width=10) archiver = GameplayArchiver('animation_archive', animation_archive_schema, add_to_archive_enable_functions=True) def get_animation_log(arb, clear=False): animation_log = setdefault_callable(animation_archive, id(arb), AnimationArchiveGSILog) if clear: del animation_archive[id(arb)] return animation_log def process_actors(animation_log, asm): actors = [] if asm not in animation_log.asm_requests: for (name, obj, suffix) in asm.actors_info_gen():
with interaction_archive_schema.add_has_many('cancel_callstack', GsiGridSchema) as sub_schema: sub_schema.add_field('code', label='Code', width=6) sub_schema.add_field('file', label='File', width=2) sub_schema.add_field('full_file', label='Full File', hidden=True) sub_schema.add_field('line', label='Line') with interaction_archive_schema.add_has_many('exit_reasons', GsiGridSchema) as sub_schema: sub_schema.add_field('event_type', label='Type') sub_schema.add_field('event_data', label='Reason', width=2) with interaction_archive_schema.add_has_many('constraints', GsiGridSchema) as sub_schema: sub_schema.add_field('sim', label='Sim') sub_schema.add_field('constraint', label='Constraint') archiver = GameplayArchiver('interaction_archive', interaction_archive_schema, add_to_archive_enable_functions=True) interaction_archive_schema_mixer = interaction_archive_schema.copy( 'Interaction Archive (Mixer)') archiver_mixer = GameplayArchiver('interaction_archive_mixer', interaction_archive_schema_mixer, add_to_archive_enable_functions=True) def is_archive_enabled(interaction): if interaction.is_super: return archiver.enabled else: return archiver_mixer.enabled
from gsi_handlers.gameplay_archiver import GameplayArchiver from sims4.gsi.schema import GsiFieldVisualizers, GsiGridSchema import gsi_handlers import services skill_change_log_archive_schema = GsiGridSchema(label='Skill Change Log', sim_specific=True) skill_change_log_archive_schema.add_field('skill_name', label='Skill Name', width=3) skill_change_log_archive_schema.add_field('current_game_time', label='Game Time', width=1.5) skill_change_log_archive_schema.add_field('old_skill_value', label='Old Value', type=GsiFieldVisualizers.FLOAT) skill_change_log_archive_schema.add_field('new_skill_value', label='New Value', type=GsiFieldVisualizers.FLOAT) skill_change_log_archive_schema.add_field('new_level', label='New Level', type=GsiFieldVisualizers.INT) skill_change_log_archive_schema.add_field('time_delta', label='Time Change', type=GsiFieldVisualizers.INT) skill_change_log_archive_schema.add_field('skill_delta', label='Skill Per Min', type=GsiFieldVisualizers.INT) skill_change_archiver = GameplayArchiver('skill_change_log', skill_change_log_archive_schema, add_to_archive_enable_functions=True) def archive_skill_change(sim, skill, time_delta, old_skill_value, new_skill_value, new_level, last_update): if time_delta != 0: skill_per_time = (new_skill_value - old_skill_value)/time_delta else: skill_per_time = 0 archive_data = {'skill_name': skill.skill_type.__name__, 'current_game_time': str(services.time_service().sim_now), 'old_skill_value': old_skill_value, 'new_skill_value': new_skill_value, 'new_level': new_level, 'time_delta': str(time_delta), 'skill_delta': skill_per_time} skill_change_archiver.archive(data=archive_data, object_id=sim.id) environment_score_archive_schema = GsiGridSchema(label='Environment Score Log', sim_specific=True) environment_score_archive_schema.add_field('primary_mood', label='Primary Mood') environment_score_archive_schema.add_field('score', label='Total Mood Score', type=GsiFieldVisualizers.FLOAT) environment_score_archive_schema.add_field('mood_commodity', label='Mood Commodity') environment_score_archive_schema.add_field('negative_score', label='Total Negative Score', type=GsiFieldVisualizers.FLOAT) environment_score_archive_schema.add_field('negative_commodity', label='Negative Commodity') environment_score_archive_schema.add_field('positive_score', label='Total Positive Score', type=GsiFieldVisualizers.FLOAT) environment_score_archive_schema.add_field('positive_commodity', label='Positive Commodity') with environment_score_archive_schema.add_has_many('contributing_objects', GsiGridSchema, label='Contributing Objects') as sub_schema:
global sim_motive_graph_alarm if enableLog and sim_motive_graph_alarm is None: sim_motive_graph_alarm = alarms.add_alarm(sim_motive_archiver, TimeSpan(5000), lambda _: archive_sim_motives(), repeating=True) else: alarms.cancel_alarm(sim_motive_graph_alarm) sim_motive_graph_alarm = None sim_motives_graph_schema = GsiLineGraphSchema(label='Motives Graph', x_axis_label='X-Axis', y_axis_label='Y-Axis', sim_specific=True, y_min=-100, y_max=100) sim_motives_graph_schema.add_field('motive_fun', axis=GsiLineGraphSchema.Axis.Y, type=GsiFieldVisualizers.FLOAT) sim_motives_graph_schema.add_field('motive_social', axis=GsiLineGraphSchema.Axis.Y, type=GsiFieldVisualizers.FLOAT) sim_motives_graph_schema.add_field('motive_hygiene', axis=GsiLineGraphSchema.Axis.Y, type=GsiFieldVisualizers.FLOAT) sim_motives_graph_schema.add_field('motive_hunger', axis=GsiLineGraphSchema.Axis.Y, type=GsiFieldVisualizers.FLOAT) sim_motives_graph_schema.add_field('motive_energy', axis=GsiLineGraphSchema.Axis.Y, type=GsiFieldVisualizers.FLOAT) sim_motives_graph_schema.add_field('motive_bladder', axis=GsiLineGraphSchema.Axis.Y, type=GsiFieldVisualizers.FLOAT) sim_motives_graph_schema.add_field('timestamp', axis=GsiLineGraphSchema.Axis.X, type=GsiFieldVisualizers.TIME) sim_motive_archiver = GameplayArchiver('sim_motive_schema', sim_motives_graph_schema, custom_enable_fn=enable_sim_motive_graph_logging) def archive_sim_motives(): sim_info_manager = services.sim_info_manager() if sim_info_manager is None: logger.error('Archiving sim motives when the sim_info_manager is absent.') return all_motives = ['motive_fun', 'motive_social', 'motive_hygiene', 'motive_hunger', 'motive_energy', 'motive_bladder'] sim_infos = list(sim_info_manager.values()) for sim_info in sim_infos: sim = sim_info.get_sim_instance() while sim is not None: archive_data = {} for motive in all_motives: cur_stat = get_tunable_instance(sims4.resources.Types.STATISTIC, motive, exact_match=True) tracker = sim.get_tracker(cur_stat)
entry['teams'] = [{ 'team_name': game.get_team_name(i), 'team_members': ';'.join(str(sim) for sim in team.players), 'team_score': team.score, 'team_rounds_taken': team.rounds_taken } for (i, team) in enumerate(game._teams)] game_info.append(entry) return game_info game_log_schema = GsiGridSchema(label='Game Component Log') game_log_schema.add_field('game_object', label='Game Object', type=GsiFieldVisualizers.STRING) game_log_schema.add_field('log', label='Log', type=GsiFieldVisualizers.STRING, width=10) game_log_archiver = GameplayArchiver('game_log', game_log_schema, add_to_archive_enable_functions=True) def archive_game_log_entry(game_object, log_entry_str): entry = {'game_object': str(game_object), 'log': log_entry_str} game_log_archiver.archive(data=entry)
else: winning_sims = 'None' entry = { 'current_game': str(game.current_game), 'target_object': str(game.target_object), 'active_sims': active_sims, 'number_of_players': str(game.number_of_players), 'winning_sims': winning_sims, 'joinable': str(game.is_joinable()), 'requires_setup': str(game.requires_setup), 'game_over': str(game.game_has_ended) } game_info.append(entry) return game_info game_log_schema = GsiGridSchema(label='Game Component Log') game_log_schema.add_field('game_object', label='Game Object', type=GsiFieldVisualizers.STRING) game_log_schema.add_field('log', label='Log', type=GsiFieldVisualizers.STRING, width=10) game_log_archiver = GameplayArchiver('game_log', game_log_schema) def archive_game_log_entry(game_object, log_entry_str): entry = {'game_object': str(game_object), 'log': log_entry_str} game_log_archiver.archive(data=entry)
sub_schema.add_field('bucket_name', label='State', width=2) sub_schema.add_field('group_id', label='Group Id', width=1) sub_schema.add_field('running', label='Running', width=1) sub_schema.add_field('priority', label='Priority', width=1) sub_schema.add_field('isFinishing', label='Finishing', width=1) sub_schema.add_field('isSuper', label='Is Super', width=1) sub_schema.add_field('isExpressed', label='Is Expressed', width=1, hidden=True) sub_schema.add_field('allowAuto', label='Allow Auto', width=1, hidden=True) sub_schema.add_field('allowUser', label='Allow User', width=1, hidden=True) sub_schema.add_field('visible', label='Visible', width=1) sub_schema.add_field('is_guaranteed', label='Guaranteed', width=1) archiver = GameplayArchiver( 'autonomy', autonomy_archive_schema, custom_enable_fn=autonomy.autonomy_modes.enable_gsi_logging) def archive_autonomy_data(sim, result, mode_name, gsi_data): archive_data = { 'sim_name': sim.full_name, 'result': str(result), 'type': mode_name } if gsi_data is not None: archive_data['Affordances'] = [{ 'affordance': interaction_result.interaction.affordance.__name__, 'target': str(interaction_result.interaction.target),
import contextlib from gsi_handlers.gameplay_archiver import GameplayArchiver from sims4.gsi.schema import GsiGridSchema, GsiFieldVisualizers import services sim_timeline_archive_schema = GsiGridSchema(label='Sim Time Line', sim_specific=True) sim_timeline_archive_schema.add_field('game_time', label='GameTime', width=40) sim_timeline_archive_schema.add_field('module', label='Module', width=35) sim_timeline_archive_schema.add_field('status', label='Status', width=40) sim_timeline_archive_schema.add_field('message', label='Message', width=35) sim_timeline_archive_schema.add_field('interaction_id', label='Interaction ID', hidden=True, type=GsiFieldVisualizers.INT) sim_timeline_archive_schema.add_field('interaction', label='Interaction', width=40) sim_timeline_archive_schema.add_field('target', label='Target', width=40) sim_timeline_archive_schema.add_field('initiator', label='Initiator', width=30) sim_timeline_archive_schema.add_field('duration', label='Duration(Sim Game Time Minutes)', width=50) archiver = GameplayArchiver('sim_time_line_archive', sim_timeline_archive_schema) @contextlib.contextmanager def archive_sim_timeline_context_manager(sim, module, log_message, interaction=None): if not archiver.enabled: yield None else: services_time_service = services.time_service() if services_time_service is not None and services_time_service.sim_timeline is not None: start_time = services_time_service.sim_timeline.now else: start_time = None try: archive_sim_timeline(sim, module, 'Start', log_message, interaction=interaction) yield None finally: duration = None
greeting_archive_schema.add_field('target', label='Target', width=7) greeting_archive_schema.add_field('chosen_greeting', label='Chosen Greeting', width=20) greeting_archive_schema.add_field('greeting_type', label='Greeting Type', width=7) greeting_archive_schema.add_field('source_interaction', label='Source', width=20) with greeting_archive_schema.add_has_many('Results', GsiGridSchema) as sub_schema: sub_schema.add_field('greeting', label='Greeting', width=25) sub_schema.add_field('test_result', label='Result', width=40) archiver = GameplayArchiver('greeting_archive', greeting_archive_schema, max_records=200, add_to_archive_enable_functions=True) def get_greeting_log(sim_id, clear=False): greeting_log = setdefault_callable(greeting_archive, sim_id, GreetingsArchiveLog) if clear: del greeting_archive[sim_id] return greeting_log def archive_greeting_request(actor_id, target_id, greeting_request_data): new_data = greeting_request_data.get_gsi_data() def log_greeting_request(data, sim_id):
from gsi_handlers.gameplay_archiver import GameplayArchiver from sims4.gsi.schema import GsiGridSchema ambient_archive_schema = GsiGridSchema(label='Ambient Log') ambient_archive_schema.add_field('sources', label='Sources') archiver = GameplayArchiver('ambient', ambient_archive_schema) def archive_ambient_data(description): entry = {} entry['sources'] = description archiver.archive(data=entry)
width=20) sub_schema.add_field('resource_time_debt', label='Time Debt', width=20) sub_schema.add_field('resource_added_time_debt', label='Added Time Debt', width=20) with animation_drift_archive_schema.add_has_many('ARBs', GsiGridSchema) as sub_schema: sub_schema.add_field('arb', label='Contents', width=20) sub_schema.add_field('timeline_contents', label='Client Timeline Contents', width=20) sub_schema.add_field('timestamp_client_completed', label='Client Completed', width=35) sub_schema.add_field('duration_client', label='Client Duration', width=35) archiver = GameplayArchiver('animation_drift_archive', animation_drift_archive_schema) def is_archive_enabled(): return archiver.enabled def _animation_drift_monitor_archive(record): object_manager = services.object_manager() relevant_objects = record.get_relevant_objects() all_resources = set(relevant_objects) for resource_id in record.resource_ids: resource = object_manager.get(resource_id) if resource is not None: if resource.is_sim: all_resources.add(resource)
sub_schema.add_field('affordance', label='Affordance', width=3) sub_schema.add_field('target', label='Target', width=3) sub_schema.add_field('test', label='Test Result', width=2) sub_schema.add_field('total_score', label='Total Score', type=GsiFieldVisualizers.INT, width=1) with content_set_archive_schema.add_has_many('Results', GsiGridSchema) as sub_schema: sub_schema.add_field('result_affordance', label='Affordance', width=3) sub_schema.add_field('result_target', label='Target', width=3) sub_schema.add_field('result_loc_key', label='Localization Key', width=3) sub_schema.add_field('result_target_loc_key', label='Target Loc Key', width=3) archiver = GameplayArchiver('content_set', content_set_archive_schema, add_to_archive_enable_functions=True) def archive_content_set(sim, si, considered, results, topics): entry = {} entry['sim'] = str(sim) entry['super_interaction'] = str(si) entry['considered_count'] = len(considered) entry['result_count'] = len(results) entry['topics'] = ', '.join(str(topic) for topic in topics) entry['Considered'] = list(considered.values()) entry['Results'] = list(results.values()) archiver.archive(data=entry, object_id=sim.id)
width=1) distributor_archive_schema.add_field('account', label='Client Account', width=2) distributor_archive_schema.add_field('target_name', label='Target Name', width=2) distributor_archive_schema.add_field('type', label='Type', width=1) distributor_archive_schema.add_field('size', label='Size', width=1) distributor_archive_schema.add_field('manager_id', label='Manager Id', type=GsiFieldVisualizers.INT, width=1) distributor_archive_schema.add_field('blockers', label='Blockers', width=5) distributor_archive_schema.add_field('tags', label='Tags', width=2) archiver = GameplayArchiver('Distributor', distributor_archive_schema) def archive_operation(target_id, target_name, manager_id, message, index, client): message_type = '? UNKNOWN ?' for (enum_name, enum_value) in message.DESCRIPTOR.enum_values_by_name.items(): while enum_value.number == message.type: message_type = enum_name break blocker_entries = [] tag_entries = [] for channel in message.additional_channels: if channel.id.manager_id == MGR_UNMANAGED: tag_entries.append(str(channel.id.object_id))
appearance_modifier_schema.add_field('request_type', label='Request Type', width=2) appearance_modifier_schema.add_field('source', label='Source', width=2) appearance_modifier_schema.add_field('priority', label='Priority', width=2) appearance_modifier_schema.add_field('apply_to_all_outfits', label='Apply To All Outfits', width=2) with appearance_modifier_schema.add_has_many('Breakdown', GsiGridSchema) as sub_schema: sub_schema.add_field('appearance_modifier', label='Appearance Modifier', width=2) sub_schema.add_field('is_permanent', label='Is Permanent', width=2) sub_schema.add_field('chosen_modifier', label='Chosen Modifier', width=2) archiver = GameplayArchiver('appearance_modifier', appearance_modifier_schema) def add_appearance_modifier_data(sim_info, appearance_modifiers, priority, apply_to_all_outfits, source, chosen_modifier): entry = {} entry['sim_id'] = sim_info.id entry['request_type'] = 'Add Appearance Modifier' entry['source'] = str(source) entry['priority'] = str(priority) entry['apply_to_all_outfits'] = apply_to_all_outfits modifiers = [] for item in appearance_modifiers: modifiers.append({ 'appearance_modifier':
from gsi_handlers.gameplay_archiver import GameplayArchiver from sims4.gsi.schema import GsiGridSchema from sims4.log import generate_message_with_callstack import services gsi_dump_schema = GsiGridSchema(label='GSI Dump Log') gsi_dump_schema.add_field('game_time', label='Game Time') gsi_dump_schema.add_field('gsi_filename', label='Filename') gsi_dump_schema.add_field('error_log_or_exception', label='Error', width=4) gsi_dump_schema.add_field('callstack', label='Callstack', width=4) gsi_dump_archiver = GameplayArchiver('gsi_dump_log', gsi_dump_schema, add_to_archive_enable_functions=True) def archive_gsi_dump(filename_str, error_str): callstack = generate_message_with_callstack('GSI Dump') archive_data = {'game_time': str(services.time_service().sim_now), 'gsi_filename': filename_str, 'error_log_or_exception': error_str, 'callstack': callstack} gsi_dump_archiver.archive(data=archive_data)
sub_schema.add_field('build_pass', label='Pass', width=0.15) sub_schema.add_field('path', label='Path', width=10) sub_schema.add_field('type', label='Type') sub_schema.add_field('cost', label='Cost', type=GsiFieldVisualizers.FLOAT) sub_schema.add_field('constraint', label='Constraint') with trans_path_archive_schema.add_has_many('all_goal_costs', GsiGridSchema) as sub_schema: sub_schema.add_field('build_pass', label='Pass', width=0.15) sub_schema.add_field('path', label='Path', width=10) sub_schema.add_field('location', label='Loc', width=6) sub_schema.add_field('type', label='Type') sub_schema.add_field('cost', label='Cost', type=GsiFieldVisualizers.FLOAT) sub_schema.add_field('source_dest_id', label='Set Id', type=GsiFieldVisualizers.INT) archiver = GameplayArchiver('transition_path', trans_path_archive_schema) def get_sim_transition_log(sim, interaction=None): all_transition_logs = setdefault_callable(posture_transition_logs, sim, weakref.WeakKeyDictionary) if interaction is None: interaction_ref = current_transition_interactions.get(sim, None) if interaction_ref is None: return interaction = interaction_ref() if interaction is None: del current_transition_interactions[sim] return posture_log = setdefault_callable(all_transition_logs, interaction, PostureTransitionGSILog)
sub_schema.add_field('cost', label='Cost', type=GsiFieldVisualizers.FLOAT, width=2) sub_schema.add_field('result', label='Result', width=2) with planner_archive_schema.add_has_many('Nodes', GsiGridSchema) as sub_schema: sub_schema.add_field('x', label='X', type=GsiFieldVisualizers.FLOAT, width=2) sub_schema.add_field('z', label='Z', type=GsiFieldVisualizers.FLOAT, width=2) sub_schema.add_field('level', label='Level', type=GsiFieldVisualizers.INT, width=2) sub_schema.add_field('qx', label='QX', type=GsiFieldVisualizers.FLOAT, width=2, hidden=True) sub_schema.add_field('qy', label='QY', type=GsiFieldVisualizers.FLOAT, width=2, hidden=True) sub_schema.add_field('qz', label='QZ', type=GsiFieldVisualizers.FLOAT, width=2, hidden=True) sub_schema.add_field('qw', label='QW', type=GsiFieldVisualizers.FLOAT, width=2, hidden=True) with planner_archive_schema.add_has_many('Details', GsiGridSchema) as sub_schema: sub_schema.add_field('name', label='Name', type=GsiFieldVisualizers.STRING, width=2) sub_schema.add_field('value', label='Value', type=GsiFieldVisualizers.FLOAT, width=2) with planner_archive_schema.add_has_many('Callstack', GsiGridSchema) as sub_schema: sub_schema.add_field('callstack', label='Callstack', width=2) archiver = GameplayArchiver('Planner', planner_archive_schema) def archive_plan(planner, path, ticks, time): result = 'Success' if path.is_route_fail() or path.status != routing.Path.PLANSTATUS_READY: result = 'Failed' plan_time = 0.0 plan_record = path.nodes.record if plan_record is not None: plan_time = plan_record['total_time_ms'] entry = {'planner_name': str(planner), 'planner_id': str(hex(planner.id)), 'result': result, 'x': round(path.route.origin.position.x, 4), 'y': round(path.route.origin.position.y, 4), 'z': round(path.route.origin.position.z, 4), 'qx': round(path.route.origin.orientation.x, 4), 'qy': round(path.route.origin.orientation.y, 4), 'qz': round(path.route.origin.orientation.z, 4), 'qw': round(path.route.origin.orientation.w, 4), 'level': path.route.origin.routing_surface.secondary_id, 'ticks': ticks, 'time': round(time*1000, 4), 'plan_time': round(plan_time, 4), 'dist': round(path.nodes.length, 4), 'num_goals': len(path.route.goals), 'num_starts': len(path.route.origins)} goal_mask_success = routing.GOAL_STATUS_SUCCESS | routing.GOAL_STATUS_SUCCESS_TRIVIAL | routing.GOAL_STATUS_SUCCESS_LOCAL goal_mask_input_error = routing.GOAL_STATUS_INVALID_SURFACE | routing.GOAL_STATUS_INVALID_POINT goal_mask_unreachable = routing.GOAL_STATUS_CONNECTIVITY_GROUP_UNREACHABLE | routing.GOAL_STATUS_COMPONENT_DIFFERENT | routing.GOAL_STATUS_IMPASSABLE | routing.GOAL_STATUS_BLOCKED goals = [] index = 0
with drama_scheduler_archive_schema.add_has_many('Potential Nodes', GsiGridSchema) as sub_schema: sub_schema.add_field('drama_node', label='Drama Node') sub_schema.add_field('score', label='Score') sub_schema.add_field('receiver', label='Receiver') sub_schema.add_field('sender', label='Sender') sub_schema.add_field('score_details', label='Score Details', width=6) with drama_scheduler_archive_schema.add_has_many('Chosen Nodes', GsiGridSchema) as sub_schema: sub_schema.add_field('drama_node', label='Drama Node') sub_schema.add_field('score', label='Score') sub_schema.add_field('receiver', label='Receiver') sub_schema.add_field('sender', label='Sender') sub_schema.add_field('score_details', label='Score Details', width=6) scoring_archiver = GameplayArchiver('drama_scoring_archive', drama_scheduler_archive_schema, add_to_archive_enable_functions=True) def is_scoring_archive_enabled(): return scoring_archiver.enabled def archive_drama_scheduler_scoring(scoring_data): time_service = services.time_service() if time_service.sim_timeline is None: time = 'zone not running' else: time = time_service.sim_now entry = { 'game_time':
width=1) balloon_archive_schema.add_field('total_weight', label='Total Weight', type=GsiFieldVisualizers.INT, width=1) with balloon_archive_schema.add_has_many('Considered', GsiGridSchema) as sub_schema: sub_schema.add_field('test_result', label='Test Result', width=2) sub_schema.add_field('balloon_type', label='Type', width=2) sub_schema.add_field('icon', label='Icon', width=2) sub_schema.add_field('weight', label='Weight', type=GsiFieldVisualizers.INT, width=1) sub_schema.add_field('balloon_category', label='Category', width=2) archiver = GameplayArchiver('balloon', balloon_archive_schema) def archive_balloon_data(sim, interaction, result, icon, entries): if result is not None: weight = result.weight balloon_type = str(result.balloon_type) gsi_category = result.gsi_category else: weight = 0 balloon_type = 'None' gsi_category = 'None' entry = {} entry['sim'] = str(sim) entry['interaction'] = str(interaction) entry['weight'] = weight
from gsi_handlers.gameplay_archiver import GameplayArchiver from sims4.gsi.schema import GsiGridSchema import gsi_handlers state_trigger_schema = GsiGridSchema(label='State Triggers/State Trigger Log') state_trigger_schema.add_field('objId', label='Object Id', unique_field=True, width=1.2) state_trigger_schema.add_field('def', label='Definition', width=2) state_trigger_schema.add_field('parent', label='Parent', width=1.5) state_trigger_schema.add_field('state', label='Trigger State', width=1.5) state_trigger_schema.add_field('state_value', label='Trigger State Value', width=2) state_trigger_schema.add_field('at_state', label='Triggered At State', width=2.5) state_trigger_schema.add_field('at_states', label='At States', width=2.5) state_trigger_schema.add_field('src', label='Source', width=1.3) state_trigger_archiver = GameplayArchiver('StateTriggerLog', state_trigger_schema) def archive_state_trigger(obj, triggered_state, at_state, at_states, source=''): archive_data = {'objId': hex(obj.id), 'def': obj.definition.name, 'state': str(triggered_state.state), 'state_value': str(triggered_state), 'at_state': str(at_state), 'at_states': str(at_states), 'src': source} if obj.parent is not None: archive_data['parent'] = gsi_handlers.gsi_utils.format_object_name(obj.parent) state_trigger_archiver.archive(data=archive_data) timed_state_trigger_schema = GsiGridSchema(label='State Triggers/Timed State Trigger Log') timed_state_trigger_schema.add_field('objId', label='Object Id', unique_field=True) timed_state_trigger_schema.add_field('def', label='Definition', width=2) timed_state_trigger_schema.add_field('state', label='Trigger State', width=2) timed_state_trigger_schema.add_field('state_value', label='Trigger State Value', width=2) timed_state_trigger_schema.add_field('at_state', label='At State', width=2) timed_state_trigger_schema.add_field('trigger_time', label='Trigger Time') timed_state_trigger_archiver = GameplayArchiver('TimedStateTriggerLog', timed_state_trigger_schema) def archive_timed_state_trigger(obj, triggered_state, at_state, trigger_time): archive_data = {'objId': hex(obj.id), 'def': obj.definition.name, 'state': str(triggered_state.state), 'state_value': str(triggered_state), 'at_state': str(at_state), 'trigger_time': trigger_time}
schema.add_field('blockers', label='Blockers(Mgr:Obj:Mask)', width=2.5) schema.add_field('tags', label='Barriers(Tag:Mask)', width=1.75) schema.add_field('details', label='Message Details', width=5) schema.add_view_cheat('distributor.gsi.toggle_op_details', label='Toggle Details') with schema.add_view_cheat('distributor.gsi.hide_op', label='Hide Selected Type') as cheat: cheat.add_token_param('type') schema.add_view_cheat('distributor.gsi.show_all_ops', label='Show All Types') distributor_archive_schema = GsiGridSchema(label='Distributor Log') _configure_distributor_schema(distributor_archive_schema) archiver = GameplayArchiver('Distributor', distributor_archive_schema, max_records=250) sim_distributor_archive_schema = GsiGridSchema(label='Distributor Log Sim', sim_specific=True) _configure_distributor_schema(sim_distributor_archive_schema) sim_archiver = GameplayArchiver('SimDistributor', sim_distributor_archive_schema, max_records=150) with sims4.reload.protected(globals()): LOG_OP_DETAILS = False EXCLUDE_OP_TYPES = { DistributorOps_pb2.Operation.HEARTBEAT, DistributorOps_pb2.Operation.SET_GAME_TIME }
sub_schema.add_field('filter_term', label='Filter Fail', width=2) with sim_filter_service_archive_schema.add_has_many( 'Metadata', GsiGridSchema) as sub_schema: sub_schema.add_field('club', label='Club', width=1) sub_schema.add_field('blacklist_sim_ids', label='Blacklist Sim Ids', width=1) sub_schema.add_field('optional', label='Optional', width=1) sub_schema.add_field('num_sims_seeking', label='Number of Sims Seeking', type=GsiFieldVisualizers.INT, width=1) sub_schema.add_field('allow_instanced_sims', label='Allow Instanced Sims', width=1) archiver = GameplayArchiver('sim_filter_service_archive', sim_filter_service_archive_schema) def archive_filter_request(filter_results, gsi_logging_data): entry = {} entry['game_time'] = str(services.time_service().sim_now) entry['request_type'] = str(gsi_logging_data.request_type) entry['yielding'] = str(gsi_logging_data.yielding) entry['filter_type'] = str(gsi_logging_data.sim_filter_type) entry['matching_results'] = len(filter_results) entry['created_sims'] = len(gsi_logging_data.created_sim_infos) if gsi_logging_data.gsi_source_fn is not None: entry['source'] = gsi_logging_data.gsi_source_fn() else: entry['source'] = 'Not Specified' filter_results_list = []
sim_filter_archive_schema.add_field('sim_id', label='simID', type=GsiFieldVisualizers.INT, hidden=True) sim_filter_archive_schema.add_field('source', label='Source', width=3) sim_filter_archive_schema.add_field('request_type', label='Request Type') sim_filter_archive_schema.add_field('filter_type', label='Filter Type', width=2.5) sim_filter_archive_schema.add_field('rejected', label='Is Rejected', width=1) sim_filter_archive_schema.add_field('reason', label='Reason', width=1) with sim_filter_archive_schema.add_has_many('Filter Breakdown', GsiGridSchema) as sub_schema: sub_schema.add_field('filter', label='Filter', width=1) sub_schema.add_field('score', label='Score', width=1) archiver = GameplayArchiver('sim_filter', sim_filter_archive_schema) def archive_filter_request(sim_info, gsi_logging_data, *, rejected, reason): entry = {} entry['sim_id'] = sim_info.id entry['request_type'] = str(gsi_logging_data.request_type) if gsi_logging_data.gsi_source_fn is not None: entry['source'] = gsi_logging_data.gsi_source_fn() else: entry['source'] = 'Not Specified' entry['filter_type'] = str(gsi_logging_data.sim_filter_type) entry['rejected'] = rejected entry['reason'] = reason filter_list = [] for (key, value) in gsi_logging_data.filters.items():
sub_schema.add_field('description', label='Description') with zone_director_schema.add_has_many('spawn objects', GsiGridSchema) as sub_schema: sub_schema.add_field('obj_id', label='Obj Id') sub_schema.add_field('obj_def', label='Obj Def') sub_schema.add_field('parent_id', label='Parent Id') sub_schema.add_field('position', label='Position') sub_schema.add_field('states', label='States') with zone_director_schema.add_has_many('civic_policies', GsiGridSchema, label='Civic Policies') as sub_schema: sub_schema.add_field('civic_policy', label='Civic Policy') sub_schema.add_field('enacted', label='Enacted') sub_schema.add_field('votes', label='Votes') archiver = GameplayArchiver('zone_director', zone_director_schema, max_records=100, add_to_archive_enable_functions=True) def log_zone_director_event(zone_director, zone, op): if not archiver.enabled: return venue_service = services.venue_service() (_, _, _, neighborhood_data) = services.current_zone_info() archive_data = { 'zone_director_type': zone_director.instance_name, 'zone_id': zone.id, 'op': op, 'neighborhood': neighborhood_data.name, 'lot_id': zone.lot.lot_id, 'active_venue': type(venue_service.active_venue).__name__,
type=GsiFieldVisualizers.INT, width=0.2) sub_schema.add_field('rel_bits', label='Relationship Bits') with relationship_culling_archive_schema.add_has_many( 'culled_relationships', GsiGridSchema) as sub_schema: sub_schema.add_field('culled_status', label='Culled Status') sub_schema.add_field('culled_reason', label='Culled Reason') sub_schema.add_field('sim_info', label='Sim A') sub_schema.add_field('target_sim_info', label='Sim B') sub_schema.add_field('total_depth', label='Total Depth', type=GsiFieldVisualizers.INT, width=0.2) sub_schema.add_field('rel_bits', label='Relationship Bits') archiver = GameplayArchiver('relationship_culling', relationship_culling_archive_schema, add_to_archive_enable_functions=True) def is_archive_enabled(): return archiver.enabled RelationshipGSIData = namedtuple( 'RelationshipGSIData', ('sim_info', 'target_sim_info', 'total_depth', 'formated_rel_bits', 'culled_status', 'culled_reason')) def _add_rel_data(rel_data: RelationshipGSIData, relationships_data): rel_entry = {
type=GsiFieldVisualizers.STRING) sim_info_lifetime_archive_schema.add_field('situations', label='Situations', type=GsiFieldVisualizers.STRING) sim_info_lifetime_archive_schema.add_field('household_id', label='Household Id', type=GsiFieldVisualizers.INT) sim_info_lifetime_archive_schema.add_field('household_name', label='Household Name', type=GsiFieldVisualizers.STRING) with sim_info_lifetime_archive_schema.add_has_many( 'creation_sources', GsiGridSchema) as sub_schema: sub_schema.add_field('creation_source', label='Creation Source') sub_schema.add_field('count', label='Count', type=GsiFieldVisualizers.INT) archiver = GameplayArchiver('sim_info_lifetime', sim_info_lifetime_archive_schema, add_to_archive_enable_functions=True, enable_archive_by_default=True) def is_archive_enabled(): return archiver.enabled def archive_sim_info_event(sim_info, event_type): sim_info_manager = services.sim_info_manager() if sim_info_manager is None: return if sim_info is None: return household = sim_info.household household_id = household.id if household is not None else 0
from gsi_handlers.gameplay_archiver import GameplayArchiver from sims4.gsi.schema import GsiGridSchema outfit_change_archive_schema = GsiGridSchema(label='Outfit Change Archive', sim_specific=True) outfit_change_archive_schema.add_field('change_from', label='Change From') outfit_change_archive_schema.add_field('change_to', label='Change To') outfit_change_archive_schema.add_field('change_reason', label='Change Reason') archiver = GameplayArchiver('OutfitChanges', outfit_change_archive_schema, add_to_archive_enable_functions=True) def log_outfit_change(sim_info, change_to, change_reason): if sim_info is None: return entry = { 'change_from': repr(sim_info._current_outfit), 'change_to': repr(change_to), 'change_reason': repr(change_reason) } archiver.archive(data=entry, object_id=sim_info.id)
label='Duration', type=GsiFieldVisualizers.FLOAT, width=2) sub_schema.add_field('event_cls', label='Event Class', width=3) sub_schema.add_field('event_type', label='Event Type', width=3) sub_schema.add_field('tag', label='Tag', type=GsiFieldVisualizers.INT, width=1) sub_schema.add_field('executed', label='Executed', width=1) route_event_archive_schema.add_view_cheat('route_events.toggle_gsi_update_log', label='Toggle Update Log', dbl_click=True, refresh_view=False) archiver = GameplayArchiver('RouteEvents', route_event_archive_schema, add_to_archive_enable_functions=True) def gsi_fill_route_event_data(route_event, path_log, additional_data=None): event_dict = { 'time': route_event.time, 'duration': route_event.duration, 'event_cls': str(type(route_event)), 'event_type': str(type(route_event.event_data)), 'tag': route_event.tag } if additional_data is not None: event_dict.update(additional_data) if route_event.id in path_log.route_events: path_log.route_events[route_event.id].update(event_dict)
type=GsiFieldVisualizers.STRING, width=1) live_drag_schema.add_field('live_drag_target', label='Drop Target', width=1) live_drag_schema.add_field('live_drag_stack_id', label='Stack ID', type=GsiFieldVisualizers.INT, width=1, hidden=True) live_drag_schema.add_field('live_drag_stack_count', label='Stack Count', type=GsiFieldVisualizers.INT, width=1) live_drag_schema.add_field('live_drag_object_inventory', label='Inventory', width=1) live_drag_archiver = GameplayArchiver('live_drag', live_drag_schema) with sims4.reload.protected(globals()): _live_drag_index = UniqueIdGenerator() def archive_live_drag(op_or_command, message_type, location_from, location_to, live_drag_object=None, live_drag_object_id: int = 0, live_drag_target=None): definition_id = 0 stack_id = 0 stack_count = 1 can_live_drag = False
sub_schema.add_field('phase_type', label='Phase Type') with crafting_archive_schema.add_has_many('quality applied', GsiGridSchema) as sub_schema: sub_schema.add_field('skill', label='Skill adjustment') sub_schema.add_field('ingredient', label='Ingredient adjustment') sub_schema.add_field('base', label='Base quality') sub_schema.add_field('multiplied', label='Multiplied quality') sub_schema.add_field('final', label='Final quality') with crafting_archive_schema.add_has_many('ingredient consumption', GsiGridSchema) as sub_schema: sub_schema.add_field('ingredient', label='Ingredient consumed') sub_schema.add_field('quality', label='Ingredient quality') sub_schema.add_field('count', label='Ingredient count') archiver = GameplayArchiver('crafting', crafting_archive_schema, enable_archive_by_default=True, max_records=200, add_to_archive_enable_functions=True) def log_process(process, sim_id, interaction, logger_crafting): interaction_name = '{}({})'.format(interaction.affordance.__name__, interaction.id) archive_data = { 'recipe': process.recipe.__name__, 'affordance': interaction_name, 'phase': str(process.phase), 'crafter': _get_sim_name(process.crafter) } archive_data['ingredients'] = [] archive_data['quality applied'] = []