using System.Collections.Generic; using System.Text.Json.Serialization; using Cthangover.Core.Factories; using Cthangover.Core.Utils; using Godot; namespace Cthangover.Mods.Map { /// /// Describes one interactive zone on the world map. Defines its bounding /// polygon (for a semi-transparent highlight), a clickable marker icon, /// a localised title label, and the target scene that opens when clicked. /// /// All coordinate properties ( and ) /// use normalised values in the [0.0 .. 1.0] range, relative to the map /// background image dimensions. This makes zone layouts resolution-independent /// and safe to share across mods. /// /// Maps use the standard {"Items": [...]} JSON envelope in /// mods/<name>/map/. Zones are read per mod in load order, so later /// mods can override zones by . /// /// This type is raw authoring data only. The live open/hidden state of a /// zone is owned by , which seeds itself from /// / and lets scenarios and code /// change it at runtime; only those runtime overrides are saved. /// public class MapZone : IIdentifiable { /// /// Unique zone identifier used as the dictionary key in factory collections. /// Typically equals the target scene name for clarity. /// [JsonPropertyName("ID")] public string ID { get; set; } /// /// Polygon vertices in normalised map coordinates [0..1]. /// Drawn as a semi-transparent colour wash over the map background /// to visually outline the zone. /// [JsonPropertyName("points")] [JsonConverter(typeof(Vector2ListJsonConverter))] public List Points { get; set; } = new(); /// /// Localisation key for the zone name displayed next to the marker. /// Resolved via TranslationServer.Translate. /// [JsonPropertyName("title")] public string Title { get; set; } /// /// Target scene identifier passed directly to /// SceneManager.SwitchScene when the marker is clicked. /// Causes the current visual-novel scene to transition to this zone. /// An empty or unresolved scene marks the zone as closed: the map shows /// its marker and polygon dimmed and blocks the transition button, which /// lets authors sketch future regions without breaking navigation. /// [JsonPropertyName("scene")] public string Scene { get; set; } /// /// Optional localisation key for the flavour text shown in the location /// card. Zones without a description show only the state badge and the /// transition button, so map data can stay minimal. /// [JsonPropertyName("description")] public string Description { get; set; } /// /// Asset ID of the marker icon texture, resolved through the mod texture /// system (e.g. ModManager.ResolveTexture). /// [JsonPropertyName("image")] public string Image { get; set; } /// /// Normalised [0..1] position of the marker icon on the map image. /// Stored as [x, y] in JSON, deserialized into a . /// [JsonPropertyName("image_pos")] [JsonConverter(typeof(Vector2JsonConverter))] public Vector2 ImagePos { get; set; } /// /// Normalised [0..1] position of a free-standing text label drawn /// directly on the map. null (absent in JSON) means the zone has /// no label. A zone with a label but no is a pure /// inscription — it is not a clickable location, does not open the /// location card and is excluded from the zone counter. Used for /// region names that have no icon of their own. /// [JsonPropertyName("label_pos")] [JsonConverter(typeof(Vector2NullableJsonConverter))] public Vector2? LabelPos { get; set; } /// /// Authoring default for the zone being closed to travel. false /// (the default) means the zone is enterable as soon as its scene /// resolves. Runtime state is owned by : /// scenarios open and close zones through the map.open_zone / /// map.close_zone actions, and those overrides are persisted in /// the save, while this field only seeds the state of an untouched zone. /// [JsonPropertyName("locked")] public bool Locked { get; set; } /// /// Authoring default for the zone being completely hidden from the /// map. false (the default) draws the zone. Hidden zones are /// absent from the map until a scenario reveals them with the /// map.show_zone action; like , this is only /// the initial value and the runtime override lives in /// . /// [JsonPropertyName("hidden")] public bool Hidden { get; set; } } }