Documentation
¶
Overview ¶
Package map_state provides light source tinting for visual atmosphere.
This implements colored light tinting for torches, braziers, fireplaces, etc. Light sources tint nearby tiles with warm or cool colors at night.
Original light-source behavior is documented in docs/gamefacts/LIGHTING.md.
Package map_state provides lighthouse rotation system faithful to original Ultima V.
The lighthouse system creates a rotating beam of light that sweeps across the map during nighttime hours. Sixteen predefined cone shapes that cycle to create the rotation effect.
Beam behavior:
- 16 cone shapes, each with storage for 16 offsets
- Each shape has up to 16 x,y offset pairs defining lit tiles
- Beam shows 3 consecutive segments at any time
- Rotation removes trailing edge, advances angle, adds leading edge
- Skipped when sight >= 50 (full daylight; ref:LIGHT-0001) or no lighthouse on map
- Original display updates used approximately 18Hz timing
Index ¶
- Constants
- Variables
- func GetAmbientLightRadius() int
- func GetMapTypeByLocation(location references.Location) references.GeneralMapType
- func SetAmbientLightRadius(radius int)
- type DaylightField
- type DaylightOptions
- type DistanceMap
- type DoorOccupancyProvider
- type DoorOpenState
- type ExposureKind
- type GameDimensions
- type Layer
- type LayerType
- type LayeredMap
- func (l *LayeredMap) ClearMapUnitTiles()
- func (l *LayeredMap) ExposureAt(pos references.Position) ExposureKind
- func (l *LayeredMap) FindLighthousePositions() []references.Position
- func (l *LayeredMap) FindLighthousePositionsInViewport(playerPos references.Position, viewRadius int, tileToFind indexes.SpriteIndex) []references.Position
- func (l *LayeredMap) GetBottomRightExtent() references.Position
- func (l *LayeredMap) GetBottomRightWithoutOverflow() references.Position
- func (l *LayeredMap) GetLastComputedLightSources() LightSources
- func (l *LayeredMap) GetLightSourcesDistanceMap() DistanceMap
- func (l *LayeredMap) GetLiveMapOnlyTile(position *references.Position) *references.Tile
- func (l *LayeredMap) GetPrimaryDistanceMap() DistanceMap
- func (l *LayeredMap) GetSmallMapPersistentTerrainTile(position *references.Position, hour byte) *references.Tile
- func (l *LayeredMap) GetSmallMapTerrainTile(position *references.Position, hour byte) *references.Tile
- func (l *LayeredMap) GetTileByLayer(layer LayerType, position *references.Position) *references.Tile
- func (l *LayeredMap) GetTileTopMapOnlyTile(position *references.Position) *references.Tile
- func (l *LayeredMap) GetTilesVisibleOnScreen() (int, int)
- func (l *LayeredMap) GetTopLeftExtent() references.Position
- func (l *LayeredMap) GetTopTile(position *references.Position) *references.Tile
- func (l *LayeredMap) GetVisibilityFlags() VisibilityCoords
- func (l *LayeredMap) GetVisibleFlags() VisibilityCoords
- func (l *LayeredMap) InvalidateLightSourceCache()
- func (l *LayeredMap) IsPositionVisible(pos *references.Position, timeOfDay datetime.UltimaDate, bIsBasement bool) bool
- func (l *LayeredMap) IsWrappedMap() bool
- func (l *LayeredMap) RecalculateVisibleTilesWithCustomLights(avatarPos references.Position, lighting *Lighting, ...)
- func (l *LayeredMap) RecalculateVisibleTilesWithMoongates(avatarPos references.Position, lighting *Lighting, ...)
- func (l *LayeredMap) SetTileByLayer(layer LayerType, position *references.Position, nIndex indexes.SpriteIndex)
- func (l *LayeredMap) SetVisible(bVisible bool, pos *references.Position)
- func (l *LayeredMap) SpriteIndexByLayer(layer LayerType, position references.Position) indexes.SpriteIndex
- func (l *LayeredMap) SwapTiles(pos1, pos2 *references.Position)
- func (l *LayeredMap) UnSetTileByLayer(layer LayerType, position *references.Position)
- type LayeredMaps
- func (l *LayeredMaps) DiscardDepartedSmallMap(destination references.Location)
- func (l *LayeredMaps) GetLayeredMap(generalMapType references.GeneralMapType, floorNumber references.FloorNumber) *LayeredMap
- func (l *LayeredMaps) GetSmallMapFloorKlimbOffset(position references.Position, nFloor references.FloorNumber) int
- func (l *LayeredMaps) GetTileRefByPosition(mapType references.GeneralMapType, mapLayer LayerType, ...) *references.Tile
- func (l *LayeredMaps) GetTileTopMapOnlyTileByPosition(mapType references.GeneralMapType, pos *references.Position, ...) *references.Tile
- func (l *LayeredMaps) HasLowerFloor(currentFloor references.FloorNumber) bool
- func (l *LayeredMaps) Loaded() []LoadedMap
- func (l *LayeredMaps) RebuildDungeonFloor(cells references.DungeonCells, floor references.FloorNumber)
- func (l *LayeredMaps) ReloadSmallMapFloor(slr *references.SmallLocationReference, tileRefs *references.Tiles, ...)
- func (l *LayeredMaps) ResetAndCreateCombatMap(combatMap *references.CombatMapReference, tileRefs *references.Tiles, ...)
- func (l *LayeredMaps) ResetAndCreateDungeonMap(cells references.DungeonCells, tileRefs *references.Tiles, xTilesInMap int, ...)
- func (l *LayeredMaps) ResetAndCreateMiniMapFromData(tileData *[references.XCombatMapTiles][references.YCombatMapTiles]byte, ...)
- func (l *LayeredMaps) ResetAndCreateSmallMap(slr *references.SmallLocationReference, tileRefs *references.Tiles, ...)
- func (l *LayeredMaps) SetDoorOccupancyProvider(provider DoorOccupancyProvider)
- func (l *LayeredMaps) SetInitialLargeMap(nFloor references.FloorNumber, lrg *references.LargeMapReference)
- type LightContribution
- type LightSource
- type LightSourceProperties
- type LightSourceTintingState
- func (ls *LightSourceTintingState) BuildLitTilesMap(lightSources LightSources, visibleFlags VisibilityCoords)
- func (ls *LightSourceTintingState) Clear()
- func (ls *LightSourceTintingState) ClearLighthouseTiles()
- func (ls *LightSourceTintingState) GetLitTileCount() int
- func (ls *LightSourceTintingState) GetTintScaleFactors(pos references.Position, elapsedMs int64, ambientDarkness float32) *LightTintColor
- func (ls *LightSourceTintingState) GetTintScaleFactorsWithDaylight(pos references.Position, elapsedMs int64, ambientDarkness float32, ...) *LightTintColor
- func (ls *LightSourceTintingState) InjectLighthouseTiles(lighthouseState *LighthouseState)
- func (ls *LightSourceTintingState) IsTileLit(pos references.Position) bool
- func (ls *LightSourceTintingState) SetLargeMapMode(isLargeMap bool)
- func (ls *LightSourceTintingState) UpdatePlayerLight(playerPos references.Position, lightType PlayerLightType)
- type LightSources
- type LightTintColor
- type LighthouseOffset
- type LighthouseState
- func (ls *LighthouseState) GetCurrentAngle() int
- func (ls *LighthouseState) GetLitTiles() map[references.Position]bool
- func (ls *LighthouseState) GetPositions() []references.Position
- func (ls *LighthouseState) HasLighthouses() bool
- func (ls *LighthouseState) IsTileLit(pos references.Position) bool
- func (ls *LighthouseState) SetLargeMapMode(isLargeMap bool)
- func (ls *LighthouseState) SetPositions(positions []references.Position)
- func (ls *LighthouseState) Update(elapsedMs int64, isFullDaylight bool) bool
- type Lighting
- func (l *Lighting) AdvanceMinutes(minutes int)
- func (l *Lighting) AdvanceTurn()
- func (l *Lighting) BuildGameScreenDistanceMap(centrePos references.Position) DistanceMap
- func (l *Lighting) BuildLightSourceDistanceMap(lightSources LightSources, visibleFlags VisibilityCoords, ...) DistanceMap
- func (l *Lighting) ExtendTorchMinutes(minutes, maximum int) int
- func (l *Lighting) ExtinguishTorch()
- func (l *Lighting) GetBaselineRadius() float32
- func (l *Lighting) HasAnyLight() bool
- func (l *Lighting) HasMagicLight() bool
- func (l *Lighting) HasTorchLit() bool
- func (l *Lighting) LightTorch()
- func (l *Lighting) RestoreTorchMinutes(minutes int)
- func (l *Lighting) SetMagicLight(active bool)
- func (l *Lighting) TorchMinutesRemaining() int
- type LoadedMap
- type MapExposure
- type MapState
- func (m *MapState) CloseOpenDoor()
- func (m *MapState) GetLayeredMapByCurrentLocation() *LayeredMap
- func (m *MapState) HasTransientDoor() bool
- func (m *MapState) IsOverworld() bool
- func (m *MapState) IsPositionOpenDoor(pos *references.Position) bool
- func (m *MapState) IsUnderworld() bool
- func (m *MapState) OpenDoor(direction references.Direction) DoorOpenState
- func (m *MapState) ResetTransientDoor()
- func (m *MapState) RestoreOpenDoor(door TrackedOpenDoor) error
- func (m *MapState) RestorePlayerLocation(location references.PlayerLocation)
- func (m *MapState) SavePlayerLocation() references.PlayerLocation
- func (m *MapState) SmallMapProcessTurnDoors(isOccupied func(references.Position, references.FloorNumber) bool) bool
- func (m *MapState) TrackedOpenDoor() *TrackedOpenDoor
- func (m *MapState) UpdateLargeMap()
- type NPCLightInfo
- type NewMapStateInput
- type PlayerLightType
- type QuestItemLightInfo
- type TileChecker
- type TintMode
- type TrackedOpenDoor
- type VisibilityCoords
- type VisibilitySystem
- func (v *VisibilitySystem) ClearOpenDoors()
- func (v *VisibilitySystem) CloseDoor(pos references.Position)
- func (v *VisibilitySystem) DecrementDoorTimers()
- func (v *VisibilitySystem) GetVisibleOnMap() [][]bool
- func (v *VisibilitySystem) IsOpenDoor(pos references.Position) bool
- func (v *VisibilitySystem) IsVisible(x, y int) bool
- func (v *VisibilitySystem) RecalculateVisibleTiles(initialFloodFillPosition references.Position, tileChecker TileChecker)
- func (v *VisibilitySystem) SetOpenDoor(pos references.Position)
- func (v *VisibilitySystem) SetXRayMode(enabled bool)
Constants ¶
const ( // BreathingPeriodMs is the time for one complete breathing cycle. // Higher = slower breathing. 2000-3000ms recommended for visible effect. BreathingPeriodMs = 2250 // BreathingAmplitude controls how much the light intensity varies. // 0.05 = ±5% variation (very subtle), 0.10 = ±10% (more noticeable) BreathingAmplitude = 0.065 )
Breathing animation parameters (slow, gentle oscillation)
const ( // MoongateBreathingPeriodMs is the moongate pulse cycle (matches sprite glow) MoongateBreathingPeriodMs = 1500 // MoongateBreathingAmplitude is the moongate intensity variation (±35%) MoongateBreathingAmplitude = 0.35 )
Moongate breathing animation (faster, more intense than fire-based sources)
const ( // TintStrength controls how strongly the light color affects tiles. // 0.0 = no tinting, 1.0 = full color. 0.15-0.25 recommended for subtle warmth. TintStrength = 0.25 // BaseBrightness is the minimum brightness multiplier at the edge of light. // 1.0 = no darkening. Lower values = darker edges. // 0.55 = 45% darker at edges for moderate falloff BaseBrightness = 0.55 // CenterBrightness is the brightness at the light source itself. // Values > 1.0 make the center slightly brighter. CenterBrightness = 1.05 )
Color tinting intensity parameters
const ( // FalloffExponent controls how quickly light fades with distance. // 1.0 = linear, 2.0 = inverse square (realistic), 1.5 = balanced FalloffExponent = 1.5 // MaxSourcesPerTile limits how many light sources affect a single tile. // More sources = smoother blending but more computation. MaxSourcesPerTile = 4 )
Blending parameters for overlapping light sources
const ( WispMarkerIndex indexes.SpriteIndex = 0xFFFC // Ethereal energy beings SeahorseMarkerIndex indexes.SpriteIndex = 0xFFFB // Magical sea creatures DaemonMarkerIndex indexes.SpriteIndex = 0xFFFA // Demonic fire creatures GhostMarkerIndex indexes.SpriteIndex = 0xFFF9 // Spectral beings )
const ( ShardMarkerIndex indexes.SpriteIndex = 0xFFF8 // Shards of Evil (corrupted virtue gems) ArtifactMarkerIndex indexes.SpriteIndex = 0xFFF7 // Lord British's Artifacts )
const ( // LighthouseUpdateIntervalMs controls rotation speed. // REDUX DEVIATION: Original display timing was approximately 18Hz (55ms); // Redux uses 110ms for smoother visuals. LighthouseUpdateIntervalMs = 110 // MaxLighthouseAngle is the maximum rotation angle (0-15 for 16 positions). MaxLighthouseAngle = 15 // ConeSegmentsLit is the number of consecutive cone segments visible at once. // Original shows segments at currentAngle, currentAngle+1, currentAngle+2. ConeSegmentsLit = 3 // MaxLighthousesPerMap limits lighthouses per map (per original game). MaxLighthousesPerMap = 2 // MaxOffsetsPerShape is the maximum offsets in a single cone shape. MaxOffsetsPerShape = 16 // UninitializedAngle indicates lighthouse hasn't been initialized yet. // Represents an unset rotation direction, encoded originally as byte 0xff. UninitializedAngle = -1 )
Lighthouse timing and rotation constants from original Ultima V.
const ( // TorchTileDistance is the illumination radius of a carried torch. TorchTileDistance = 3 // DefaultTorchDurationMinutes is the initial fuel time of a lit torch. DefaultTorchDurationMinutes = 240 // Moongate light distance MoongateLightDistance = 4 // Moongates emit mystical light with 4 tile radius // Quest item light distances ShardLightDistance = 3 // Shards of Evil emit light with 3 tile radius ArtifactLightDistance = 4 // Lord British's Artifacts emit stronger light with 4 tile radius // MagicLightTileDistance is the original U5 radius for both In Lor and Vas Lor. MagicLightTileDistance = 5 InLorTileDistance = MagicLightTileDistance VasLorTileDistance = MagicLightTileDistance // NPC light distances - magical creatures that emit light // All start at 2 tiles for subtle glow effect WispLightDistance = 2 // Ethereal energy beings - blue-white glow SeahorseLightDistance = 2 // Magical sea creatures - bright blue glow DaemonLightDistance = 2 // Demonic fire creatures - red glow GhostLightDistance = 2 // Spectral beings - pale blue glow )
const DefaultOpenDoorTurns = 2
DefaultOpenDoorTurns is the initial player-open countdown (2, 1, 0, close).
const LighthouseMarkerIndex indexes.SpriteIndex = 0xFFFE
LighthouseMarkerIndex is a special sprite index marker for lighthouse light sources. Used to identify lighthouse contributions in the lit tiles map.
const MoongateMarkerIndex indexes.SpriteIndex = 0xFFFD
MoongateMarkerIndex is a special sprite index marker for moongate light sources. Used to identify moongate contributions in the lit tiles map for purple/blue tinting.
const ( // UnlitDarkeningFactor darkens tiles outside any light source radius. // Applied when there are active light sources to create contrast. // 1.0 = no darkening, 0.75 = 25% darker, 0.40 = 60% darker. // Previous value: 0.55 (45% darker) UnlitDarkeningFactor float32 = 0.40 )
Unlit area parameters
Variables ¶
var ( // TorchWarm adds a warm orange tint for torches and sconces TorchWarm = LightTintColor{R: 1.47, G: 0.93, B: 0.17} // BrazierWarm adds a deeper orange tint (hot coals effect) BrazierWarm = LightTintColor{R: 1.47, G: 0.93, B: 0.17} // FireplaceWarm adds a reddish-orange tint (burning logs) FireplaceWarm = LightTintColor{R: 1.47, G: 0.93, B: 0.17} // CandleWarm adds a soft amber tint (gentler than torch) CandleWarm = LightTintColor{R: 1.47, G: 0.93, B: 0.17} // CookStoveRed adds a redder tint for cooking fires CookStoveRed = LightTintColor{R: 1.55, G: 0.75, B: 0.15} // LampPostWhite adds a whiter/cooler tint for street lamps LampPostWhite = LightTintColor{R: 1.25, G: 1.15, B: 0.90} )
Warm light tint colors (fire-based sources) These add warmth by boosting red/green and reducing blue for orange/amber glow
var ( // BlueFlameCool is a strong distinct blue tint for magical blue flames // Reduces red/green and boosts blue for a clear magical blue glow BlueFlameCool = LightTintColor{R: 0.70, G: 0.85, B: 1.45} // MagicWhite is near-neutral (slight blue for magical feel) MagicWhite = LightTintColor{R: 1.00, G: 1.00, B: 1.02} // MoongatePurpleTint is a mystical blue tint for moongates // Bright, slightly white-shifted blue for a glowing magical feel MoongatePurpleTint = LightTintColor{R: 0.82, G: 0.90, B: 1.50} )
Cool light tint colors (magical sources)
var ( // WispGlow is an ethereal blue-white glow for energy beings WispGlow = LightTintColor{R: 0.90, G: 0.95, B: 1.40} // SeahorseGlow is a bright white-cyan magical glow for mystical sea creatures // Uses high brightness with slight cyan tint to stand out against blue water SeahorseGlow = LightTintColor{R: 1.30, G: 1.45, B: 1.50} // DaemonGlow is a red demonic glow for fire creatures DaemonGlow = LightTintColor{R: 1.40, G: 0.85, B: 0.75} // GhostGlow is a pale blue spectral glow for undead spirits GhostGlow = LightTintColor{R: 0.95, G: 0.98, B: 1.25} )
var ( // AmbientSightDim provides minimal visibility in darkness without a torch. // Neutral gray, slightly brighter than complete darkness but much dimmer than torch. // Used for PlayerLightAmbient to give the avatar basic night vision. AmbientSightDim = LightTintColor{R: 0.55, G: 0.55, B: 0.55} // ShardGlow is a sinister red-purple glow for the corrupted Shards of Evil // These represent corrupted virtue gems and should look ominous ShardGlow = LightTintColor{R: 1.30, G: 0.80, B: 1.20} // ArtifactGlow is a noble golden-white glow for Lord British's Artifacts // Crown, Sceptre, and Amulet should have a regal, pure light ArtifactGlow = LightTintColor{R: 1.22, G: 1.18, B: 0.85} )
var ErrInvalidOpenDoor = errors.New("invalid open-door continuation")
ErrInvalidOpenDoor identifies incompatible tracked-door restoration data.
var LightSourcePropertiesMap = map[indexes.SpriteIndex]LightSourceProperties{ indexes.RightSconce: {TintColor: TorchWarm, HasBreathing: true, BreathingAmplitude: 0.6, IndependentBreathing: true, TintMode: TintHalfDuringDay}, indexes.LeftSconce: {TintColor: TorchWarm, HasBreathing: true, BreathingAmplitude: 0.6, IndependentBreathing: true, TintMode: TintHalfDuringDay}, indexes.Brazier: {TintColor: BrazierWarm, HasBreathing: true, IndependentBreathing: true, TintMode: TintHalfDuringDay}, indexes.Fireplace: {TintColor: FireplaceWarm, HasBreathing: true, IndependentBreathing: true, TintMode: TintHalfDuringDay}, indexes.FireLogs: {TintColor: FireplaceWarm, HasBreathing: true, IndependentBreathing: true, TintMode: TintHalfDuringDay}, indexes.CampFire: {TintColor: TorchWarm, HasBreathing: true, IndependentBreathing: true, TintMode: TintHalfDuringDay}, indexes.CandleOnTable: {TintColor: CandleWarm, HasBreathing: true, IndependentBreathing: true, TintMode: TintHalfDuringDay}, indexes.LampPost: {TintColor: LampPostWhite, HasBreathing: false, TintMode: TintHalfDuringDay}, indexes.BlueFlame: {TintColor: BlueFlameCool, HasBreathing: true, BreathingAmplitude: 0.4, TintMode: TintAlways}, indexes.FireField: {TintColor: TorchWarm, HasBreathing: true, IndependentBreathing: true, TintMode: TintHalfDuringDay}, indexes.CookStove: {TintColor: CookStoveRed, HasBreathing: false, TintMode: TintHalfDuringDay}, indexes.ItemTorch: {TintColor: TorchWarm, HasBreathing: true, IndependentBreathing: true, TintMode: TintHalfDuringDay}, LighthouseMarkerIndex: {TintColor: LighthouseRed, HasBreathing: false, TintMode: TintHalfDuringDay}, MoongateMarkerIndex: { TintColor: MoongatePurpleTint, HasBreathing: true, BreathingPeriodMs: MoongateBreathingPeriodMs, BreathingAmplitude: MoongateBreathingAmplitude, TintMode: TintAlways, }, WispMarkerIndex: { TintColor: WispGlow, HasBreathing: true, BreathingPeriodMs: 1200, BreathingAmplitude: 0.25, TintMode: TintAlways, }, SeahorseMarkerIndex: { TintColor: SeahorseGlow, HasBreathing: true, BreathingPeriodMs: 1800, BreathingAmplitude: 0.45, TintMode: TintHalfDuringDay, }, DaemonMarkerIndex: { TintColor: DaemonGlow, HasBreathing: true, BreathingPeriodMs: 1400, BreathingAmplitude: 0.50, TintMode: TintAlways, }, GhostMarkerIndex: { TintColor: GhostGlow, HasBreathing: true, BreathingPeriodMs: 2000, BreathingAmplitude: 0.15, TintMode: TintHalfDuringDay, }, ShardMarkerIndex: { TintColor: ShardGlow, HasBreathing: true, BreathingPeriodMs: 2500, BreathingAmplitude: 0.20, TintMode: TintAlways, }, ArtifactMarkerIndex: { TintColor: ArtifactGlow, HasBreathing: true, BreathingPeriodMs: 2500, BreathingAmplitude: 0.35, TintMode: TintHalfDuringDay, }, }
LightSourcePropertiesMap maps sprite indexes to their light properties.
var ( // LighthouseRed is the warm red tint for lighthouse beams. // Creates a distinctive red glow for the rotating lighthouse cone. LighthouseRed = LightTintColor{R: 1.15, G: 0.80, B: 0.80} )
Lighthouse tint color (warm red for the rotating beam)
var NeutralTint = LightTintColor{R: 1.0, G: 1.0, B: 1.0}
NeutralTint applies no color change (for reference)
Functions ¶
func GetAmbientLightRadius ¶
func GetAmbientLightRadius() int
GetAmbientLightRadius returns the current ambient light radius.
func GetMapTypeByLocation ¶
func GetMapTypeByLocation(location references.Location) references.GeneralMapType
func SetAmbientLightRadius ¶
func SetAmbientLightRadius(radius int)
SetAmbientLightRadius configures the ambient light radius for night vision. Called during game initialization with value from config. Falls back to 2 if radius < 1.
Types ¶
type DaylightField ¶
type DaylightField struct {
// contains filtered or unexported fields
}
DaylightField holds full-day cosmetic targets. The caller owns world-context eligibility and time-of-day blending. Construct with NewDaylightField. Preparing a previously sized floor reuses storage without retaining its map or callback.
func NewDaylightField ¶
func NewDaylightField(options DaylightOptions) *DaylightField
NewDaylightField validates and copies options, including the falloff slice. Invalid configuration is a programming error and panics.
func (*DaylightField) Clear ¶
func (d *DaylightField) Clear()
Clear deactivates all targets while retaining the values buffer for reuse.
func (*DaylightField) PrepareOutdoor ¶
func (d *DaylightField) PrepareOutdoor()
PrepareOutdoor selects a uniform outdoor target without coordinate bounds.
func (*DaylightField) PrepareSmallMap ¶
func (d *DaylightField) PrepareSmallMap(layer *LayeredMap, isDoorOpen func(*references.Position) bool)
PrepareSmallMap recomputes baselines and live opening activation. Nil maps and unknown exposure produce no targets. isDoorOpen is required, must only observe its position argument, and should be the current MapState.IsPositionOpenDoor. Runtime floor overrides never determine opening identity or orientation.
func (*DaylightField) TargetAt ¶
func (d *DaylightField) TargetAt(pos references.Position) (float32, bool)
TargetAt returns the full-day target, or false for inactive/unknown/out-of-bounds cells.
type DaylightOptions ¶
type DaylightOptions struct {
OutdoorBrightness float32
IndoorBrightness float32
OpeningFalloff []float32
}
DaylightOptions controls cosmetic full-day targets, not visibility or emission. Brightness values must be finite in [0.3, 1], with IndoorBrightness <= OutdoorBrightness. OpeningFalloff contains at most eight finite, nonincreasing weights in [0, 1]. Weight d-1 blends toward outdoor brightness in the Euclidean band (d-1,d]. The pool faces inward and includes structural tiles along the opening plane. An empty slice disables all opening effects.
func DefaultDaylightOptions ¶
func DefaultDaylightOptions() DaylightOptions
DefaultDaylightOptions returns independent options: outdoor 1, indoor 0.75, and inward opening weights 1, 0.6, 0.25 at distances one, two, and three. The indoor baseline remains a visual-tuning choice.
type DistanceMap ¶
type DistanceMap map[references.Position]int
type DoorOccupancyProvider ¶
type DoorOccupancyProvider func(references.Location, references.Position, references.FloorNumber) bool
DoorOccupancyProvider reads authoritative actors, never cached map-unit sprites.
type DoorOpenState ¶
type DoorOpenState int
const ( OpenDoorLocked DoorOpenState = iota OpenDoorLockedMagical OpenDoorNotADoor OpenDoorOpened )
func OpenDoorAt ¶
func OpenDoorAt(theMap *LayeredMap, position *references.Position) DoorOpenState
OpenDoorAt opens one surface-style door without applying map-specific lifecycle rules.
type ExposureKind ¶
type ExposureKind uint8
ExposureKind describes structural exposure, independently of visibility and light.
const ( ExposureUnknown ExposureKind = iota ExposureOutdoor ExposureIndoor ExposureBoundary )
Exposure kinds keep structural boundaries distinct from either side of a wall.
type GameDimensions ¶
type GameDimensions interface {
GetTilesVisibleOnScreen() (int, int)
GetTopLeftExtent() references.Position
GetBottomRightExtent() references.Position
GetBottomRightWithoutOverflow() references.Position
IsWrappedMap() bool
}
type Layer ¶
type Layer [][]indexes.SpriteIndex
Layer represents a 2D array of sprite indices for performance optimization Using triple slice [layer][y][x] instead of maps for 5-8x speedup
type LayeredMap ¶
type LayeredMap struct {
TopLeft, BottomRight references.Position
XMaxTilesPerMap, YMaxTilesPerMap references.Coordinate
// contains filtered or unexported fields
}
LayeredMap represents a map broken into separate layers. These layers are essentially "floors"
func (*LayeredMap) ClearMapUnitTiles ¶
func (l *LayeredMap) ClearMapUnitTiles()
func (*LayeredMap) ExposureAt ¶
func (l *LayeredMap) ExposureAt(pos references.Position) ExposureKind
ExposureAt returns immutable source-floor exposure, independently of runtime tiles and lighting.
func (*LayeredMap) FindLighthousePositions ¶
func (l *LayeredMap) FindLighthousePositions() []references.Position
FindLighthousePositions scans the map for LighthouseLight tiles (beacon, sprite 0x2a). Returns up to MaxLighthousesPerMap positions (per original game limit). This is used when entering a small map to detect lighthouse locations.
func (*LayeredMap) FindLighthousePositionsInViewport ¶
func (l *LayeredMap) FindLighthousePositionsInViewport( playerPos references.Position, viewRadius int, tileToFind indexes.SpriteIndex, ) []references.Position
FindLighthousePositionsInViewport scans a viewport around the player for lighthouse building tiles. Used for large maps (overworld) where lighthouse buildings need to be detected in visible area. Scans the loaded 32x32 region (four 16x16 quadrants) for lighthouse terrain.
Parameters:
- playerPos: Center of viewport (player position)
- viewRadius: Scan radius in tiles (16 for 32x32 area matching original)
- tileToFind: Sprite index to search for (indexes.Lighthouse for overworld)
Returns up to MaxLighthousesPerMap positions.
func (*LayeredMap) GetBottomRightExtent ¶
func (l *LayeredMap) GetBottomRightExtent() references.Position
func (*LayeredMap) GetBottomRightWithoutOverflow ¶
func (l *LayeredMap) GetBottomRightWithoutOverflow() references.Position
func (*LayeredMap) GetLastComputedLightSources ¶
func (l *LayeredMap) GetLastComputedLightSources() LightSources
GetLastComputedLightSources returns the light sources from the most recent visibility calculation. Used by LightSourceTintingState to build the lit tiles map for colored light tinting. The custom-only path excludes invisible static emitters; dynamic inputs retain their supplied order/duplicates and are visibility-filtered by the consumers.
func (*LayeredMap) GetLightSourcesDistanceMap ¶
func (l *LayeredMap) GetLightSourcesDistanceMap() DistanceMap
GetLightSourcesDistanceMap returns the light sources distance map Used by overlay system for secondary light source rendering
func (*LayeredMap) GetLiveMapOnlyTile ¶
func (l *LayeredMap) GetLiveMapOnlyTile(position *references.Position) *references.Tile
GetLiveMapOnlyTile resolves occupancy-held doors for visibility. Persistent terrain/lock consumers continue to use GetTileTopMapOnlyTile.
func (*LayeredMap) GetPrimaryDistanceMap ¶
func (l *LayeredMap) GetPrimaryDistanceMap() DistanceMap
GetPrimaryDistanceMap returns the primary distance mask map Used by overlay system for lighting calculations
func (*LayeredMap) GetSmallMapPersistentTerrainTile ¶
func (l *LayeredMap) GetSmallMapPersistentTerrainTile(position *references.Position, hour byte) *references.Tile
GetSmallMapPersistentTerrainTile preserves NPC traversal and door lock rules; another actor holding a locked doorway open grants no new traversal permission.
func (*LayeredMap) GetSmallMapTerrainTile ¶
func (l *LayeredMap) GetSmallMapTerrainTile(position *references.Position, hour byte) *references.Tile
GetSmallMapTerrainTile is the live player/render terrain contract. Door occupancy is derived on every read, independently of the cached sprite layer.
func (*LayeredMap) GetTileByLayer ¶
func (l *LayeredMap) GetTileByLayer(layer LayerType, position *references.Position) *references.Tile
func (*LayeredMap) GetTileTopMapOnlyTile ¶
func (l *LayeredMap) GetTileTopMapOnlyTile(position *references.Position) *references.Tile
func (*LayeredMap) GetTilesVisibleOnScreen ¶
func (l *LayeredMap) GetTilesVisibleOnScreen() (int, int)
func (*LayeredMap) GetTopLeftExtent ¶
func (l *LayeredMap) GetTopLeftExtent() references.Position
func (*LayeredMap) GetTopTile ¶
func (l *LayeredMap) GetTopTile(position *references.Position) *references.Tile
func (*LayeredMap) GetVisibilityFlags ¶
func (l *LayeredMap) GetVisibilityFlags() VisibilityCoords
GetVisibilityFlags returns the visibility flags map for overlay rendering This is used by the overlay system to check which tiles are visible
func (*LayeredMap) GetVisibleFlags ¶
func (l *LayeredMap) GetVisibleFlags() VisibilityCoords
GetVisibleFlags returns the current visibility flags map. Used by LightSourceTintingState to filter light sources by visibility, ensuring that light from behind walls doesn't bleed through.
func (*LayeredMap) InvalidateLightSourceCache ¶
func (l *LayeredMap) InvalidateLightSourceCache()
InvalidateLightSourceCache invalidates the light source cache, forcing recalculation on next access
func (*LayeredMap) IsPositionVisible ¶
func (l *LayeredMap) IsPositionVisible(pos *references.Position, timeOfDay datetime.UltimaDate, bIsBasement bool) bool
IsPositionVisible returns true if the position is visible based on the time of day.
func (*LayeredMap) IsWrappedMap ¶
func (l *LayeredMap) IsWrappedMap() bool
func (*LayeredMap) RecalculateVisibleTilesWithCustomLights ¶
func (l *LayeredMap) RecalculateVisibleTilesWithCustomLights(avatarPos references.Position, lighting *Lighting, moongatePositions []references.Position, questItemLights []QuestItemLightInfo, npcLights []NPCLightInfo, playerLightType PlayerLightType)
RecalculateVisibleTilesWithCustomLights recalculates visible tiles including moongate, quest item, and NPC light sources
func (*LayeredMap) RecalculateVisibleTilesWithMoongates ¶
func (l *LayeredMap) RecalculateVisibleTilesWithMoongates(avatarPos references.Position, lighting *Lighting, moongatePositions []references.Position, playerLightType PlayerLightType)
RecalculateVisibleTilesWithMoongates recalculates visible tiles including moongate light sources
func (*LayeredMap) SetTileByLayer ¶
func (l *LayeredMap) SetTileByLayer(layer LayerType, position *references.Position, nIndex indexes.SpriteIndex)
func (*LayeredMap) SetVisible ¶
func (l *LayeredMap) SetVisible(bVisible bool, pos *references.Position)
SetVisible sets the visibility of a tile to true or false.
func (*LayeredMap) SpriteIndexByLayer ¶
func (l *LayeredMap) SpriteIndexByLayer(layer LayerType, position references.Position) indexes.SpriteIndex
SpriteIndexByLayer returns the raw persistent layer value at position.
func (*LayeredMap) SwapTiles ¶
func (l *LayeredMap) SwapTiles(pos1, pos2 *references.Position)
func (*LayeredMap) UnSetTileByLayer ¶
func (l *LayeredMap) UnSetTileByLayer(layer LayerType, position *references.Position)
type LayeredMaps ¶
type LayeredMaps struct {
// contains filtered or unexported fields
}
func NewLayeredMaps ¶
func NewLayeredMaps(tileRefs *references.Tiles, overworldRef *references.LargeMapReference, underworldRef *references.LargeMapReference, xTilesInMap int, yTilesInMap int, ) *LayeredMaps
func (*LayeredMaps) DiscardDepartedSmallMap ¶
func (l *LayeredMaps) DiscardDepartedSmallMap(destination references.Location)
DiscardDepartedSmallMap ends a visit only on a different physical destination. Virtual combat/prison/camping scenes suspend the retained source location.
func (*LayeredMaps) GetLayeredMap ¶
func (l *LayeredMaps) GetLayeredMap(generalMapType references.GeneralMapType, floorNumber references.FloorNumber) *LayeredMap
func (*LayeredMaps) GetSmallMapFloorKlimbOffset ¶
func (l *LayeredMaps) GetSmallMapFloorKlimbOffset(position references.Position, nFloor references.FloorNumber) int
func (*LayeredMaps) GetTileRefByPosition ¶
func (l *LayeredMaps) GetTileRefByPosition(mapType references.GeneralMapType, mapLayer LayerType, pos *references.Position, nFloor references.FloorNumber) *references.Tile
func (*LayeredMaps) GetTileTopMapOnlyTileByPosition ¶
func (l *LayeredMaps) GetTileTopMapOnlyTileByPosition(mapType references.GeneralMapType, pos *references.Position, nFloor references.FloorNumber) *references.Tile
func (*LayeredMaps) HasLowerFloor ¶
func (l *LayeredMaps) HasLowerFloor(currentFloor references.FloorNumber) bool
func (*LayeredMaps) Loaded ¶
func (l *LayeredMaps) Loaded() []LoadedMap
Loaded returns all materialized floors. Consumers must sort if stable order is required.
func (*LayeredMaps) RebuildDungeonFloor ¶
func (l *LayeredMaps) RebuildDungeonFloor(cells references.DungeonCells, floor references.FloorNumber)
RebuildDungeonFloor replaces one derived projection floor from semantic authority. Rebuilding 64 cells keeps synchronization simple and explicit.
func (*LayeredMaps) ReloadSmallMapFloor ¶
func (l *LayeredMaps) ReloadSmallMapFloor( slr *references.SmallLocationReference, tileRefs *references.Tiles, floor references.FloorNumber, xTilesInMap int, yTilesInMap int, )
ReloadSmallMapFloor rebuilds one source floor while retaining other floors.
func (*LayeredMaps) ResetAndCreateCombatMap ¶
func (l *LayeredMaps) ResetAndCreateCombatMap( combatMap *references.CombatMapReference, tileRefs *references.Tiles, xTilesInMap int, yTilesInMap int, )
ResetAndCreateCombatMap creates a LayeredMap for a combat map (camping, combat encounters) Combat maps are always 11x11 tiles, single floor (floor 0), non-wrapping
func (*LayeredMaps) ResetAndCreateDungeonMap ¶
func (l *LayeredMaps) ResetAndCreateDungeonMap( cells references.DungeonCells, tileRefs *references.Tiles, xTilesInMap int, yTilesInMap int, )
ResetAndCreateDungeonMap creates the retained top-down compatibility projection for semantic dungeon cells. Gameplay must never read this projection as dungeon authority.
func (*LayeredMaps) ResetAndCreateMiniMapFromData ¶
func (l *LayeredMaps) ResetAndCreateMiniMapFromData( tileData *[references.XCombatMapTiles][references.YCombatMapTiles]byte, tileRefs *references.Tiles, xTilesInMap int, yTilesInMap int, )
ResetAndCreateMiniMapFromData creates a LayeredMap for an 11x11 mini-map (shrine, codex, etc.) Uses raw tile data directly to avoid package dependencies tileData is [x][y] indexed, where (0,0) is top-left
func (*LayeredMaps) ResetAndCreateSmallMap ¶
func (l *LayeredMaps) ResetAndCreateSmallMap( slr *references.SmallLocationReference, tileRefs *references.Tiles, xTilesInMap int, yTilesInMap int, )
func (*LayeredMaps) SetDoorOccupancyProvider ¶
func (l *LayeredMaps) SetDoorOccupancyProvider(provider DoorOccupancyProvider)
SetDoorOccupancyProvider installs the runtime-only small-map terrain resolver. New floors inherit it; already loaded floors are rebound as well.
func (*LayeredMaps) SetInitialLargeMap ¶
func (l *LayeredMaps) SetInitialLargeMap(nFloor references.FloorNumber, lrg *references.LargeMapReference)
type LightContribution ¶
type LightContribution struct {
SourceIndex indexes.SpriteIndex
SourcePos references.Position
Distance float64 // Actual distance (not squared)
Radius int // Max radius of this source
Weight float64 // Computed weight based on distance
}
LightContribution represents one light source's contribution to a tile.
type LightSource ¶
type LightSource struct {
Tile *references.Tile
Pos references.Position
}
LightSource represents a tile that emits light in the game world
type LightSourceProperties ¶
type LightSourceProperties struct {
// TintColor is the color this light adds to tiles (as RGB scale factors > 1.0)
// Values > 1.0 brighten that channel, < 1.0 darken it
TintColor LightTintColor
// HasBreathing enables slow breathing animation for fire-based sources
HasBreathing bool
// BreathingPeriodMs is the custom breathing period in milliseconds.
// 0 = use default BreathingPeriodMs constant (2250ms)
BreathingPeriodMs int
// BreathingAmplitude is the custom breathing intensity variation for emitted light.
// 0 = use default BreathingAmplitude constant (0.065)
BreathingAmplitude float64
// IndependentBreathing varies the breathing period per-source based on position.
// When true, each instance breathes at a slightly different rate (±15% variation).
// When false (default), all sources of this type breathe at the same rate.
// Use for fire sources to create organic flickering; leave false for magical sources.
IndependentBreathing bool
// Radius overrides the tile's LightEmission if non-zero
Radius int
// TintMode controls when this light source applies color tinting.
// TintNightOnly (default): tint only at night
// TintHalfDuringDay: full tint at night, 50% during day
// TintAlways: full tint at all times
TintMode TintMode
}
LightSourceProperties defines visual characteristics of a light source. These properties control how nearby tiles are tinted at night.
func GetLightSourceProperties ¶
func GetLightSourceProperties(spriteIndex indexes.SpriteIndex) LightSourceProperties
GetLightSourceProperties returns the light properties for a sprite index.
func PlayerLightProperties ¶
func PlayerLightProperties(lightType PlayerLightType) LightSourceProperties
PlayerLightProperties returns light properties for player-carried light sources.
type LightSourceTintingState ¶
type LightSourceTintingState struct {
// contains filtered or unexported fields
}
LightSourceTintingState tracks which tiles are lit by light sources for tinting. Supports blending multiple overlapping light sources smoothly.
func NewLightSourceTintingState ¶
func NewLightSourceTintingState() *LightSourceTintingState
NewLightSourceTintingState creates a new light source tinting state.
func (*LightSourceTintingState) BuildLitTilesMap ¶
func (ls *LightSourceTintingState) BuildLitTilesMap( lightSources LightSources, visibleFlags VisibilityCoords, )
BuildLitTilesMap recalculates which tiles are lit by light sources. Only light sources visible to the player (determined by visibleFlags) will contribute. This ensures that light from behind walls doesn't bleed through. Pass nil for visibleFlags to include all light sources (useful for tests).
func (*LightSourceTintingState) Clear ¶
func (ls *LightSourceTintingState) Clear()
Clear removes all lit tiles (used when leaving a map).
func (*LightSourceTintingState) ClearLighthouseTiles ¶
func (ls *LightSourceTintingState) ClearLighthouseTiles()
ClearLighthouseTiles removes all lighthouse contributions from the lit tiles map. Called before re-injecting lighthouse tiles after rotation.
func (*LightSourceTintingState) GetLitTileCount ¶
func (ls *LightSourceTintingState) GetLitTileCount() int
GetLitTileCount returns the number of tiles currently lit (for debugging).
func (*LightSourceTintingState) GetTintScaleFactors ¶
func (ls *LightSourceTintingState) GetTintScaleFactors( pos references.Position, elapsedMs int64, ambientDarkness float32, ) *LightTintColor
GetTintScaleFactors returns the RGB scale factors for a tile at the given position. Returns nil if the tile is not lit by any light source (or all sources are filtered out). The elapsedMs parameter is used for breathing animation. The ambientDarkness parameter controls TintMode filtering and smoothly ranges from 0 during full daylight to 1 at night:
- TintNightOnly sources scale with ambient darkness
- TintHalfDuringDay sources scale from 50% intensity to full intensity
- TintAlways sources apply at full intensity always
Color tint and brightness falloff are handled separately: - Color tint (warm/cool) stays consistent across the lit area - Brightness falls off with distance (darker at edges) This creates the effect of "same color, just dimmer" at edges.
func (*LightSourceTintingState) GetTintScaleFactorsWithDaylight ¶
func (ls *LightSourceTintingState) GetTintScaleFactorsWithDaylight( pos references.Position, elapsedMs int64, ambientDarkness float32, daylightTarget float32, ) *LightTintColor
GetTintScaleFactorsWithDaylight composes source tint with a local daylight target. daylightTarget must be finite and in [0.3, 1]; invalid targets panic. ambientDarkness remains global clock darkness for TintMode and color intensity. Only sources eligible in full daylight can raise daytime brightness above the target, up to 1, before adding color deltas. Target 1 and full night preserve GetTintScaleFactors exactly. Unlit tiles and fully filtered contributions return nil for caller ambient fallback.
func (*LightSourceTintingState) InjectLighthouseTiles ¶
func (ls *LightSourceTintingState) InjectLighthouseTiles(lighthouseState *LighthouseState)
InjectLighthouseTiles adds lighthouse-lit tiles to the tinting state. This integrates the lighthouse's rotating beam with the unified light source system. Each lit tile gets distance-based brightness falloff from the nearest beacon.
func (*LightSourceTintingState) IsTileLit ¶
func (ls *LightSourceTintingState) IsTileLit(pos references.Position) bool
IsTileLit returns true if the tile at the given position is lit by any light source.
func (*LightSourceTintingState) SetLargeMapMode ¶
func (ls *LightSourceTintingState) SetLargeMapMode(isLargeMap bool)
SetLargeMapMode sets whether the tinting operates on a wrapping large map.
func (*LightSourceTintingState) UpdatePlayerLight ¶
func (ls *LightSourceTintingState) UpdatePlayerLight( playerPos references.Position, lightType PlayerLightType, )
UpdatePlayerLight updates the lit tiles map with the player's current light source.
type LightTintColor ¶
type LightTintColor struct {
R, G, B float32
}
LightTintColor represents RGB scale factors for light tinting. Values around 1.0 are neutral. > 1.0 brightens, < 1.0 darkens. These are NOT raw colors but multipliers applied to existing tile colors.
type LighthouseOffset ¶
type LighthouseOffset struct {
X, Y int8
}
LighthouseOffset defines a single x,y offset for the light cone. These offsets are relative to the lighthouse beacon position.
type LighthouseState ¶
type LighthouseState struct {
// contains filtered or unexported fields
}
LighthouseState tracks lighthouse rotation state for a map. Manages up to 2 lighthouses per map, matching original game limit.
func NewLighthouseState ¶
func NewLighthouseState() *LighthouseState
NewLighthouseState creates a new lighthouse state in uninitialized state.
func (*LighthouseState) GetCurrentAngle ¶
func (ls *LighthouseState) GetCurrentAngle() int
GetCurrentAngle returns the current rotation angle (0-15) or UninitializedAngle. Useful for debugging and testing.
func (*LighthouseState) GetLitTiles ¶
func (ls *LighthouseState) GetLitTiles() map[references.Position]bool
GetLitTiles returns a copy of the lit tiles map for external use.
func (*LighthouseState) GetPositions ¶
func (ls *LighthouseState) GetPositions() []references.Position
GetPositions returns the lighthouse beacon positions. Useful for debugging and testing.
func (*LighthouseState) HasLighthouses ¶
func (ls *LighthouseState) HasLighthouses() bool
HasLighthouses returns true if there are any lighthouses on the map.
func (*LighthouseState) IsTileLit ¶
func (ls *LighthouseState) IsTileLit(pos references.Position) bool
IsTileLit returns true if the given position is lit by a lighthouse cone or is the lighthouse beacon position itself.
func (*LighthouseState) SetLargeMapMode ¶
func (ls *LighthouseState) SetLargeMapMode(isLargeMap bool)
SetLargeMapMode sets whether the lighthouse operates on a wrapping large map. When true, lit tile positions are wrapped to handle coordinates near map edges. Should be called after SetPositions when operating on overworld (256x256 map).
func (*LighthouseState) SetPositions ¶
func (ls *LighthouseState) SetPositions(positions []references.Position)
SetPositions sets the lighthouse beacon positions. Accepts up to MaxLighthousesPerMap positions; extras are ignored. Only resets rotation state if positions actually changed, preserving smooth rotation when player moves within range of same lighthouses.
func (*LighthouseState) Update ¶
func (ls *LighthouseState) Update(elapsedMs int64, isFullDaylight bool) bool
Update checks if rotation should occur based on elapsed time and daylight. Returns true if rotation occurred (and lit tiles changed).
Parameters:
- elapsedMs: Current game time in milliseconds
- isFullDaylight: If true, lighthouse is disabled (matches original sight >= 50 check)
type Lighting ¶
type Lighting struct {
// contains filtered or unexported fields
}
func NewLighting ¶
func NewLighting(gameDimensions GameDimensions) Lighting
func (*Lighting) AdvanceMinutes ¶
AdvanceMinutes burns a carried torch by actual elapsed gameplay minutes.
func (*Lighting) AdvanceTurn ¶
func (l *Lighting) AdvanceTurn()
AdvanceTurn is retained for callers that explicitly model one elapsed minute.
func (*Lighting) BuildGameScreenDistanceMap ¶
func (l *Lighting) BuildGameScreenDistanceMap(centrePos references.Position) DistanceMap
func (*Lighting) BuildLightSourceDistanceMap ¶
func (l *Lighting) BuildLightSourceDistanceMap( lightSources LightSources, visibleFlags VisibilityCoords, playerLightType PlayerLightType, centerPos references.Position, ) DistanceMap
func (*Lighting) ExtendTorchMinutes ¶
ExtendTorchMinutes adds carried fuel and saturates at maximum.
func (*Lighting) ExtinguishTorch ¶
func (l *Lighting) ExtinguishTorch()
ExtinguishTorch immediately extinguishes the torch (used by death resurrection).
func (*Lighting) GetBaselineRadius ¶
func (*Lighting) HasAnyLight ¶
HasAnyLight returns true if torch OR magic light is providing illumination.
func (*Lighting) HasMagicLight ¶
HasMagicLight returns true if magic light is active.
func (*Lighting) HasTorchLit ¶
func (*Lighting) LightTorch ¶
func (l *Lighting) LightTorch()
func (*Lighting) RestoreTorchMinutes ¶
RestoreTorchMinutes restores carried fuel without consuming another torch.
func (*Lighting) SetMagicLight ¶
SetMagicLight enables or disables player-carried magical light.
func (*Lighting) TorchMinutesRemaining ¶
TorchMinutesRemaining returns the carried torch's authoritative fuel time.
type LoadedMap ¶
type LoadedMap struct {
MapType references.GeneralMapType
Location references.Location
Floor references.FloorNumber
Map *LayeredMap
}
LoadedMap identifies one currently materialized map floor.
type MapExposure ¶
type MapExposure struct {
// contains filtered or unexported fields
}
MapExposure is an immutable, non-wrapping classification of one source floor. Its zero value reports ExposureUnknown everywhere.
func ClassifyMapExposure ¶
func ClassifyMapExposure(width, height int, boundaries []bool, outdoorSeeds []image.Point) MapExposure
ClassifyMapExposure floods open border cells and explicit outdoor seeds through four-neighbor connections. Unreached open cells are indoor; boundaries retain their own kind. Boundaries are row-major (y*width+x), and inputs are not retained. Invalid dimensions, cell counts, or seeds are programming errors and panic.
func (MapExposure) At ¶
func (m MapExposure) At(x, y int) ExposureKind
At returns ExposureUnknown outside the source floor, without wrapping.
type MapState ¶
type MapState struct {
PlayerLocation references.PlayerLocation
LayeredMaps LayeredMaps
XTilesVisibleOnGameScreen int
YTilesVisibleOnGameScreen int
Lighting Lighting
// contains filtered or unexported fields
}
func NewMapState ¶
func NewMapState(input NewMapStateInput) *MapState
func (*MapState) CloseOpenDoor ¶
func (m *MapState) CloseOpenDoor()
CloseOpenDoor restores the exact unlocked variant on its originating floor. Terrain reconstruction and opening another door also normalize through here.
func (*MapState) GetLayeredMapByCurrentLocation ¶
func (m *MapState) GetLayeredMapByCurrentLocation() *LayeredMap
func (*MapState) HasTransientDoor ¶
HasTransientDoor reports whether a timed open-door mutation is active.
func (*MapState) IsOverworld ¶
IsOverworld returns true if the player is in the overworld
func (*MapState) IsPositionOpenDoor ¶
func (m *MapState) IsPositionOpenDoor(pos *references.Position) bool
IsPositionOpenDoor returns true if the position currently has an open door
func (*MapState) IsUnderworld ¶
IsUnderworld returns true if the player is in the underworld
func (*MapState) OpenDoor ¶
func (m *MapState) OpenDoor(direction references.Direction) DoorOpenState
func (*MapState) ResetTransientDoor ¶
func (m *MapState) ResetTransientDoor()
ResetTransientDoor clears timed door state after source terrain is reloaded.
func (*MapState) RestoreOpenDoor ¶
func (m *MapState) RestoreOpenDoor(door TrackedOpenDoor) error
RestoreOpenDoor installs a validated timer after persistent terrain restoration, without commands, turns, callbacks or randomness. Zero need not be occupied: the final actor can leave after the door phase of the last completed turn.
func (*MapState) RestorePlayerLocation ¶
func (m *MapState) RestorePlayerLocation(location references.PlayerLocation)
RestorePlayerLocation sets all player location fields at once from a saved location
func (*MapState) SavePlayerLocation ¶
func (m *MapState) SavePlayerLocation() references.PlayerLocation
SavePlayerLocation returns a copy of the current player location (Location, Position, Floor)
func (*MapState) SmallMapProcessTurnDoors ¶
func (m *MapState) SmallMapProcessTurnDoors(isOccupied func(references.Position, references.FloorNumber) bool) bool
SmallMapProcessTurnDoors advances the tracked door timer and closes an unoccupied expired door.
func (*MapState) TrackedOpenDoor ¶
func (m *MapState) TrackedOpenDoor() *TrackedOpenDoor
TrackedOpenDoor returns a copy, including the originating floor.
func (*MapState) UpdateLargeMap ¶
func (m *MapState) UpdateLargeMap()
UpdateLargeMap currently doesn't do anything useful. It just checks that the actual map is a large map.
type NPCLightInfo ¶
type NPCLightInfo struct {
Position references.Position
MarkerIndex indexes.SpriteIndex // For tint color lookup in LightSourcePropertiesMap
LightRadius int
}
NPCLightInfo holds information about a magical NPC that emits light. Used for creatures like wisps, seahorses, daemons, and ghosts.
type NewMapStateInput ¶
type NewMapStateInput struct {
GameDimensions GameDimensions
XTilesVisibleOnGameScreen int
YTilesVisibleOnGameScreen int
}
type PlayerLightType ¶
type PlayerLightType int
PlayerLightType identifies the source of player-carried light
const ( PlayerLightNone PlayerLightType = iota PlayerLightAmbient // Minimal night vision, neutral gray, 2 tile radius PlayerLightTorch // Orange light, 3 tile radius PlayerLightInLor // White light, 5 tile radius (In Lor spell) PlayerLightVasLor // Bright white, 6 tile radius (Vas Lor spell) )
type QuestItemLightInfo ¶
type QuestItemLightInfo struct {
Position references.Position
MarkerIndex indexes.SpriteIndex // For tint color lookup in LightSourcePropertiesMap
LightRadius int
}
QuestItemLightInfo holds information about a quest item that emits light
type TileChecker ¶
type TileChecker interface {
// GetTile returns the tile at the given position
GetLiveMapOnlyTile(pos *references.Position) *references.Tile
}
TileChecker interface allows the visibility system to check tile properties
type TintMode ¶
type TintMode int
TintMode controls when a light source applies color tinting to nearby tiles.
const ( // TintNightOnly applies tinting only at night (default for fire-based sources) TintNightOnly TintMode = iota // TintHalfDuringDay applies full tint at night, 50% tint during day (subtle magical glow) TintHalfDuringDay // TintAlways applies full tint at all times (strong magical sources) TintAlways )
type TrackedOpenDoor ¶
type TrackedOpenDoor struct {
Position references.PlayerLocation
RemainingTurns int
ClosedTile indexes.SpriteIndex
}
TrackedOpenDoor is detached continuation state for the single player-open timer. Occupancy-only openings have no timer or persistent terrain mutation.
type VisibilityCoords ¶
type VisibilityCoords map[references.Coordinate]map[references.Coordinate]bool
func (*VisibilityCoords) ResetVisibilityCoords ¶
func (v *VisibilityCoords) ResetVisibilityCoords(bDefault bool)
func (*VisibilityCoords) SetVisibilityCoordsRectangle ¶
func (v *VisibilityCoords) SetVisibilityCoordsRectangle(topLeft, bottomRight *references.Position, xMax, yMax references.Coordinate, bWrap bool)
type VisibilitySystem ¶
type VisibilitySystem struct {
// contains filtered or unexported fields
}
VisibilitySystem manages the flood fill visibility calculation for small maps This is a complete reimplementation based on the C# Ultima 5 Redux code
func (*VisibilitySystem) ClearOpenDoors ¶
func (v *VisibilitySystem) ClearOpenDoors()
ClearOpenDoors closes all open doors immediately
func (*VisibilitySystem) CloseDoor ¶
func (v *VisibilitySystem) CloseDoor(pos references.Position)
CloseDoor immediately closes a door
func (*VisibilitySystem) DecrementDoorTimers ¶
func (v *VisibilitySystem) DecrementDoorTimers()
DecrementDoorTimers decrements the open door timers each turn
func (*VisibilitySystem) GetVisibleOnMap ¶
func (v *VisibilitySystem) GetVisibleOnMap() [][]bool
GetVisibleOnMap returns the visibility map (for external use)
func (*VisibilitySystem) IsOpenDoor ¶
func (v *VisibilitySystem) IsOpenDoor(pos references.Position) bool
IsOpenDoor checks if a door at the given position is currently open
func (*VisibilitySystem) IsVisible ¶
func (v *VisibilitySystem) IsVisible(x, y int) bool
IsVisible returns whether a tile is visible
func (*VisibilitySystem) RecalculateVisibleTiles ¶
func (v *VisibilitySystem) RecalculateVisibleTiles(initialFloodFillPosition references.Position, tileChecker TileChecker)
RecalculateVisibleTiles is the main entry point for visibility calculation. Performs flood fill from the avatar position to determine what tiles are visible.
Process: 1. Handle XRay mode (debug - all tiles visible) 2. Set up viewport boundaries to limit flood fill 3. Execute flood fill algorithm from avatar position
The results are stored in v.visibleOnMap for querying.
func (*VisibilitySystem) SetOpenDoor ¶
func (v *VisibilitySystem) SetOpenDoor(pos references.Position)
SetOpenDoor marks a door as open - it will stay open for a certain number of turns
func (*VisibilitySystem) SetXRayMode ¶
func (v *VisibilitySystem) SetXRayMode(enabled bool)
SetXRayMode enables or disables X-ray vision (see through walls)