Skip to main content
The Side class represents one of the six faces of a Block. Every side has its own identity, spatial vectors, and may hold an item or a decoration. Scripts attached to a side receive it as self in hooks such as OnBallRoll, and the ball’s current ground side is always available via ball.currentGroundSide. RollingQuest defines many typed sub-classes of Side — for example SideButton or SideLaser — each inheriting all base properties while adding their own.

Properties

Identity

PropertyTypeRead-onlyDescription
typeEntityTypeAlways EntityType.Side (2).
idintegerUnique numeric identifier of this side.
namestringName of the side, taken from its template.
tagstringTag used for scripted lookup and grouping.

Transform

PropertyTypeRead-onlyDescription
positionVector3World-space position of the side’s origin corner.
rotationQuaternionWorld-space rotation of the side.
centerPositionVector3World-space position of the side’s centre point.
normalVectorVector3Outward-pointing normal vector of the side.
tangentVectorVector3Tangent vector lying in the plane of the side.
bitangentVectorVector3Bitangent vector perpendicular to both normal and tangent.

Geometry

PropertyTypeRead-onlyDescription
blockBlockThe parent block this side belongs to.
blockSlotBlockSlotGrid slot of the parent block.
faceFaceWhich face of the block this side occupies.
faceNamestringHuman-readable name of the face (e.g. "Up", "Front").
sectionstringID of the level section that contains this side.

Rules

PropertyTypeRead-onlyDescription
isIntangiblebooleantrue when the side has no physical collision.
hasJumpBanbooleantrue when jumping is prohibited while on this side.
hasMoveBanbooleantrue when movement is prohibited while on this side.

Attachments

PropertyTypeRead-onlyDescription
itemItemThe item placed on this side, or nil.
hasItembooleantrue when an item is present on this side.
decorationDecorationThe decoration placed on this side, or nil.
hasDecorationbooleantrue when a decoration is present on this side.
propertiesElementPropertyPoolCustom property pool attached to the side.
localDataRawLocalDataPer-instance local data store for this side.

Methods

getAssociatedBasis

Returns the Basis that corresponds to a ball standing on this side at a given orientation. Three overloads are available:
--- @param orientation Orientation
--- @return Basis
function Side:getAssociatedBasis(orientation)

--- @param orientation integer
--- @return Basis
function Side:getAssociatedBasis(orientation)

--- @return Basis
function Side:getAssociatedBasis()  -- uses default orientation

isDirectionBlocked

--- @param orientation Orientation
--- @return boolean
function Side:isDirectionBlocked(orientation)

--- @param orientation integer
--- @return boolean
function Side:isDirectionBlocked(orientation)
Returns true when the given orientation is a blocked movement direction for the ball on this side.

Type-cast helpers

Use these to narrow a generic entity reference to a concrete type. Each throws an error if the cast is invalid.
function Side:asLevel()      -- returns Level
function Side:asBlock()      -- returns Block
function Side:asSide()       -- returns Side
function Side:asItem()       -- returns Item
function Side:asEnemy()      -- returns Enemy
function Side:asBall()       -- returns Ball
function Side:asDecoration() -- returns Decoration

SideData

SideData is the raw, mutable representation used when constructing level data (e.g. in OnLevelLoad). It carries the optional template, scriptRef, scriptTag, scriptVars, and properties fields, plus references to an ItemData and a DecorationData. The boolean flags hasOwnTemplate, hasValidItem, and hasValidDecoration let you check which optional fields are populated. Key SideData methods: clearItem(), clearDecoration(), clear().

Side Subtypes

The following concrete sub-classes all inherit every property and method from Side. You receive the most-specific type automatically when accessing sides at runtime.
Sub-classDescription
SideNormalA plain, unremarkable side with no special behaviour.
SideButtonA pressable button that triggers signals when the ball rolls over it.
SideCheckpointSaves the ball’s respawn position when touched.
SideExitEnds the level or transitions to the next section when reached.
SideJumpPadLaunches the ball into the air on contact.
SideLaserFires a laser beam that kills the ball on contact.
SideMagnetPulls or pushes the ball with a magnetic force.
SideStaticSpikesPermanently extended spikes that destroy the ball.
SideRetractableSpikeSpikes that extend and retract on a timed cycle.
SideSensorSpikesSpikes that extend when the ball is detected nearby.
SidePatternSpikeSpikes that follow a programmed sequence pattern.
SideTrampolineBounces the ball upward on contact.
SideVentPropels the ball in a fixed direction with air pressure.
SideIcyReduces friction, causing the ball to slide.
SideBurnedApplies a burning effect to the ball on contact.
SideOilSlows the ball and may interact with fire sides.
SideSandSlows movement with a sandy surface effect.
SidePlasmaApplies an energy-based hazard to the ball.
SideSawbladesRotating blades that destroy the ball on contact.
SideTeslaCoilPeriodically discharges electricity.
SideFlamethrowerContinuously or periodically emits flames.
SideTimeStopTemporarily halts the level timer.
SideTeleportTeleports the ball to a linked teleport destination.
SidePortalExitThe exit point of a portal pair.
SideOneWayAllows movement in only one direction.
SideMultiWayAllows movement in multiple specified directions.
SideRotatorRotates the ball’s facing direction.
SideSwitchToggles blocks or other level elements.
SidePressurePlateActivates only when the ball is resting on it.
SideLightSensorDetects light conditions to trigger other elements.

Usage Example

The following OnBallRoll hook is attached to a side script and prints the face name every time the ball rolls onto the side:
function OnBallRoll(self, ball)
    -- self is a Side
    Log.info("Ball rolled onto face: " .. self.faceName)

    -- Grant the ball a shield when it lands on this side
    if self.tag == "safe_pad" then
        ball:enableShield(3.0)
    end

    -- Check whether the side carries an item
    if self.hasItem then
        local item = self.item
        Log.info("Side has item: " .. item.name)
    end
end