map_state

package
v0.1.0-preview.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 16, 2026 License: MIT Imports: 11 Imported by: 0

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

View Source
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)

View Source
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)

View Source
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

View Source
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

View Source
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
)
View Source
const (
	ShardMarkerIndex    indexes.SpriteIndex = 0xFFF8 // Shards of Evil (corrupted virtue gems)
	ArtifactMarkerIndex indexes.SpriteIndex = 0xFFF7 // Lord British's Artifacts
)
View Source
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.

View Source
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
)
View Source
const DefaultOpenDoorTurns = 2

DefaultOpenDoorTurns is the initial player-open countdown (2, 1, 0, close).

View Source
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.

View Source
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.

View Source
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

View Source
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

View Source
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)

View Source
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}
)
View Source
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}
)
View Source
var ErrInvalidOpenDoor = errors.New("invalid open-door continuation")

ErrInvalidOpenDoor identifies incompatible tracked-door restoration data.

View Source
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.

View Source
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)

View Source
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 LayerType

type LayerType int
const (
	MapLayer LayerType = iota
	MapOverrideLayer
	MapUnitLayer
)

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 LightSources

type LightSources []LightSource

LightSources is a collection of light sources

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

func (l *Lighting) AdvanceMinutes(minutes int)

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

func (l *Lighting) ExtendTorchMinutes(minutes, maximum int) int

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 (l *Lighting) GetBaselineRadius() float32

func (*Lighting) HasAnyLight

func (l *Lighting) HasAnyLight() bool

HasAnyLight returns true if torch OR magic light is providing illumination.

func (*Lighting) HasMagicLight

func (l *Lighting) HasMagicLight() bool

HasMagicLight returns true if magic light is active.

func (*Lighting) HasTorchLit

func (l *Lighting) HasTorchLit() bool

func (*Lighting) LightTorch

func (l *Lighting) LightTorch()

func (*Lighting) RestoreTorchMinutes

func (l *Lighting) RestoreTorchMinutes(minutes int)

RestoreTorchMinutes restores carried fuel without consuming another torch.

func (*Lighting) SetMagicLight

func (l *Lighting) SetMagicLight(active bool)

SetMagicLight enables or disables player-carried magical light.

func (*Lighting) TorchMinutesRemaining

func (l *Lighting) TorchMinutesRemaining() int

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

func (m *MapState) HasTransientDoor() bool

HasTransientDoor reports whether a timed open-door mutation is active.

func (*MapState) IsOverworld

func (m *MapState) IsOverworld() bool

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

func (m *MapState) IsUnderworld() bool

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)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL