using Content.Shared.Holopad; using Content.Shared.Mobs; using Robust.Shared.Player; using Robust.Shared.Prototypes; using Robust.Shared.Utility; using System.Diagnostics.CodeAnalysis; namespace Content.Shared.Silicons.StationAi; public abstract partial class SharedStationAiSystem { private ProtoId _stationAiCoreCustomGroupProtoId = "StationAiCoreIconography"; private ProtoId _stationAiHologramCustomGroupProtoId = "StationAiHolograms"; private readonly SpriteSpecifier.Rsi _stationAiRebooting = new(new ResPath("Mobs/Silicon/station_ai.rsi"), "ai_fuzz"); private void InitializeCustomization() { SubscribeLocalEvent(OnStationAiCustomization); SubscribeLocalEvent(OnPlayerAttached); SubscribeLocalEvent(OnPlayerDetached); SubscribeLocalEvent(OnMobStateChanged); } private void OnStationAiCustomization(Entity entity, ref StationAiCustomizationMessage args) { if (!_protoManager.Resolve(args.GroupProtoId, out var groupPrototype) || !_protoManager.Resolve(args.CustomizationProtoId, out var customizationProto)) return; if (!TryGetHeld((entity, entity.Comp), out var held)) return; if (!TryComp(held, out var stationAiCustomization)) return; if (stationAiCustomization.ProtoIds.TryGetValue(args.GroupProtoId, out var protoId) && protoId == args.CustomizationProtoId) return; stationAiCustomization.ProtoIds[args.GroupProtoId] = args.CustomizationProtoId; Dirty(held.Value, stationAiCustomization); // Update hologram if (groupPrototype.Category == StationAiCustomizationType.Hologram) UpdateHolographicAvatar((held.Value, stationAiCustomization)); // Update core iconography if (groupPrototype.Category == StationAiCustomizationType.CoreIconography && TryComp(entity, out var stationAiHolder)) UpdateAppearance((entity, stationAiHolder)); } private void OnPlayerAttached(Entity ent, ref PlayerAttachedEvent args) { var state = _mobState.IsDead(ent) ? StationAiState.Dead : StationAiState.Occupied; SetStationAiState(ent, state); } private void OnPlayerDetached(Entity ent, ref PlayerDetachedEvent args) { var state = _mobState.IsDead(ent) ? StationAiState.Dead : StationAiState.Rebooting; SetStationAiState(ent, state); } protected virtual void OnMobStateChanged(Entity ent, ref MobStateChangedEvent args) { var state = (args.NewMobState == MobState.Dead) ? StationAiState.Dead : StationAiState.Rebooting; SetStationAiState(ent, state); } protected void SetStationAiState(Entity ent, StationAiState state) { if (ent.Comp.State != state) { ent.Comp.State = state; Dirty(ent); var ev = new StationAiCustomizationStateChanged(state); RaiseLocalEvent(ent, ref ev); } if (_containers.TryGetContainingContainer(ent.Owner, out var container) && TryComp(container.Owner, out var holder)) { UpdateAppearance((container.Owner, holder)); } } private void UpdateHolographicAvatar(Entity entity) { if (!TryComp(entity, out var avatar)) return; if (!entity.Comp.ProtoIds.TryGetValue(_stationAiHologramCustomGroupProtoId, out var protoId)) return; if (!_protoManager.Resolve(protoId, out var prototype)) return; if (!prototype.LayerData.TryGetValue(StationAiState.Hologram.ToString(), out var layerData)) return; avatar.LayerData = [layerData]; Dirty(entity, avatar); } private void CustomizeAppearance(Entity entity, StationAiState state) { var stationAi = GetInsertedAI(entity); if (!TryComp(stationAi, out var stationAiCustomization) || !TryGetCustomizedAppearanceData((stationAi.Value, stationAiCustomization), out var layerData) || !layerData.TryGetValue(state.ToString(), out var stateData)) { return; } // This data is handled manually in the client StationAiSystem _appearance.SetData(entity.Owner, StationAiVisualLayers.Icon, stateData); } /// /// Returns a dictionary containing the station AI's appearance for different states. /// /// The station AI. /// The apperance data, indexed by possible AI states. /// True if the apperance data was found. public bool TryGetCustomizedAppearanceData(Entity entity, [NotNullWhen(true)] out Dictionary? layerData) { layerData = null; if (!entity.Comp.ProtoIds.TryGetValue(_stationAiCoreCustomGroupProtoId, out var protoId) || !_protoManager.Resolve(protoId, out var prototype) || prototype.LayerData.Count == 0) { return false; } layerData = prototype.LayerData; return true; } }