Rooms module

Module for inspecting and altering the rooms of the current level.

Indexing

Indexing the module reaches a room, and #trx.rooms is how many the level has. pairs() walks them in order, keyed by the room number.

Example:

trx.log.info(#trx.rooms .. " rooms, first is " .. trx.rooms[0].num)
for num, room in pairs(trx.rooms) do
  room.cold = true
end

Properties

  • trx.rooms.flip_group_count (integer). How many flip groups a level can hold. A room belongs to one of them, and a flip moves that group alone. (read-only)
  • trx.rooms.flipped (boolean). Whether the group that moved last is showing its flip pairs. (read-only)
  • trx.rooms.query (trx.rooms.RoomQuery). The identity query over every room in the level. Narrow it and read it. (read-only)

Enums

  • trx.rooms.FlipStatus

    The values trx.rooms.Room.flip_status can take.

    • trx.rooms.FlipStatus.NONE = 0
      This is a normal room.
    • trx.rooms.FlipStatus.UNFLIPPED = 1
      This room is currently reachable by Lara.
    • trx.rooms.FlipStatus.FLIPPED = 2
      This room is currently inactive and unreachable by Lara.

Structures

  • trx.rooms.Num

    Room number, matching the numbers level editors show. Counted from 0.

  • trx.rooms.Room

    A room in the current level.

    Handles are live references: if the underlying object is destroyed, using the handle raises an error rather than silently reading an unrelated one.

    Properties:

    • cold: boolean. Whether Lara's breath is visible in the room.
    • damaging: boolean. Whether the room drains Lara's exposure meter.
    • flip_status: trx.rooms.FlipStatus. Current flip status. (read-only)
    • num: trx.rooms.Num. (read-only)
    • swamp: boolean. Whether the room is filled with swamp water, which Lara wades through and sinks into rather than swimming.
    • underwater: boolean. Whether the room is filled with water.
    • wind: boolean. Whether the room has a breeze. Requires the player to have breeze enabled.

    Computed properties (derived, not stored on the object):

    • bounds: trx.math.Box. Where the room sits in the world.
    • flipped_room: trx.rooms.Room. This room's flip pair, or nil if it has none.
    • internal_bounds: trx.math.Box. As bounds, but excluding the outer ring of sectors, which is solid wall.

    Methods:

    • room:ceiling_height(pos, [opts])
      Returns the ceiling height, using this room as the starting room.

      Parameters:

      • pos (trx.math.Vec3). World position.

      • opts (table, optional). How to read the height.

        Keys:

        • fix_tilts (boolean, optional, default true). Whether a floor tilt that lies inside a wall is taken into account. false gives the flat height read by the original games. Vanilla level geometry can depend on this behaviour.

      Returns: trx.math.Distance or nil. The height, with nil where there is no ceiling.

    • room:floor_height(pos, [opts])
      As trx.rooms.floor_height, looking from this room.

      Parameters:

      • pos (trx.math.Vec3). World position.

      • opts (table, optional). How to read the height.

        Keys:

        • fix_tilts (boolean, optional, default true). Whether a floor tilt that lies inside a wall is taken into account. false gives the flat height read by the original games. Vanilla level geometry can depend on this behaviour.

      Returns: trx.math.Distance or nil. The height, with nil where there is no floor.

    • room:is_valid()
      Whether the handle still refers to a room of the level that is loaded. A level change replaces the rooms, so a handle held across one goes stale rather than naming a different room: reading or writing a field on it raises an error. Check this for a handle held across time.

      Returns: boolean. False once the level that held the room has been left.

      Example:

      local start_room = trx.rooms[0]
      trx.events.after_control(function()
        if start_room:is_valid() then
          trx.log.info(tostring(start_room.underwater))
        end
      end)
      
    • room:on_enter(callback, [opts])
      Happens when something changes rooms into this one.

      Parameters:

      • callback (function). What to run when it happens. Called with:

      • opts (table, optional). What to watch for.

        Keys:

        • watch (string, optional, default "lara"). Either "lara", which reacts to Lara alone, or "all", which reacts to every item.

      Returns: trx.events.Listener. The attached handler.

      Example:

      trx.rooms[7]:on_enter(function(item)
        trx.log.info("entered room 7")
      end)
      
    • room:on_exit(callback, [opts])
      Happens when something changes rooms out of this one.

      Parameters:

      • callback (function). What to run when it happens. Called with:

      • opts (table, optional). What to watch for.

        Keys:

        • watch (string, optional, default "lara"). Either "lara", which reacts to Lara alone, or "all", which reacts to every item.

      Returns: trx.events.Listener. The attached handler.

  • trx.rooms.RoomQuery

    A trx.query.Query over the rooms of the current level, with the narrowings below on top of the ones every query has. Rooms answer to no names, so the name layer is absent.

    Methods:

    • roomquery:at(pos)
      The room contains a world position. Rooms overlap, so a position can be in several at once and every one of them matches, in room order. A room claims a point when the point is within its bounds, the outer ring of solid wall aside, and the column it stands in has a floor - the test the engine itself puts a position through. The hidden half of a flip pair is passed over.

      Parameters:

      Returns: trx.query.Query. The narrowed query.

      Example:

      trx.rooms.query:at(trx.lara.item.pos):first()
      
    • roomquery:dry()
      The room holds neither water nor swamp water.

      Returns: trx.query.Query. The narrowed query.

    • roomquery:flipped()
      The room is the half of a flip pair the level is not showing. Its geometry is still there to inspect, but nothing can be in it.

      Returns: trx.query.Query. The narrowed query.

    • roomquery:reachable()
      The room is part of the level as it stands: an ordinary room, or the half of a flip pair the level is showing. This is what a script asking about the world wants, and what at already applies.

      Returns: trx.query.Query. The narrowed query.

      Example:

      trx.rooms.query:reachable():underwater():count()
      
    • roomquery:swamp()
      The room is filled with swamp water.

      Returns: trx.query.Query. The narrowed query.

    • roomquery:underwater()
      The room is filled with water.

      Returns: trx.query.Query. The narrowed query.

Functions

  • trx.rooms.get(num)
    Retrieves a room by number.

    Parameters:

    Returns: trx.rooms.Room or nil. The room, or nil where the level has no such number.

    Example:

    local room = trx.rooms[14]
    room.underwater = true
    
  • trx.rooms.count()
    Returns the number of rooms in the level. Same as #trx.rooms.

    Returns: integer. How many rooms the loaded level holds.

  • trx.rooms.flip_groups(groups)
    Puts rooms in flip groups. A level script can then move some flip pairs while the rest stay where they are. Each entry names one room and the group it belongs to. Its flip pair joins the same group.

    Call this only from the top level of a level script. Rooms must be grouped before the level starts, so the game can restore flipped groups correctly when it loads a save.

    A level with no groups moves all flip pairs together. After a script names any group, each flip trigger moves only the group with the same number.

    Parameters:

    Example:

    trx.rooms.flip_groups({ [33] = 1, [37] = 2 })
    
  • trx.rooms.flip([group])
    Flips rooms, swapping each with its flip pair. With no group given, every group moves.

    Parameters:

    • group (integer, optional). Which flip group to act on, counted from 0. A level splits its flip pairs into groups and moves one at a time; a game that names no group places every room in the first. Omit this to act on every group.

    Example:

    trx.rooms.flip()
    

    Example:

    trx.rooms.flip(3)
    
  • trx.rooms.is_flipped([group])
    Whether a group of rooms is showing its flip pairs. With no group given, answers for the group that moved last, which is what the world itself reads.

    Parameters:

    • group (integer, optional). Which flip group to act on, counted from 0. A level splits its flip pairs into groups and moves one at a time; a game that names no group places every room in the first. Omit this to act on every group.

    Returns:

    • boolean. Whether that group is showing its pairs.
  • trx.rooms.flip_effect(effect_id, [timer])
    Sets the active flip effect, and optionally its timer.

    Parameters:

    • effect_id (trx.catalog.flip_effects). Use -1 to clear the current effect.
    • timer (integer, optional). Flip timer value.

    Example:

    trx.rooms.flip_effect(trx.catalog.flip_effects.floor_shake, 10)
    
  • trx.rooms.floor_height(pos, [room_num], [opts])
    The height of the floor under a world position. nil where there is no floor at all: inside solid geometry, or off the edge of the level.

    Parameters:

    • pos (trx.math.Vec3). World position.

    • room_num (trx.rooms.Num, optional). The search crosses portals, so a neighbouring room's floor is found too. Without it, the room is looked up from the position, which takes the first room that contains it and passes over the flipped-away ones. Where rooms overlap, name the room, or ask the room itself with trx.rooms.Room:floor_height.

    • opts (table, optional). How to read the height.

      Keys:

      • fix_tilts (boolean, optional, default true). Whether a floor tilt that lies inside a wall is taken into account. false gives the flat height read by the original games. Vanilla level geometry can depend on this behaviour.

    Returns: trx.math.Distance or nil. The height, with nil where there is no floor.

    Example:

    local floor = trx.lara.item.room:floor_height(trx.lara.item.pos)
    
  • trx.rooms.ceiling_height(pos, [room_num], [opts])
    The height of the ceiling over a world position. Returns nil inside solid geometry or outside the level.

    Parameters:

    • pos (trx.math.Vec3). World position.

    • room_num (trx.rooms.Num, optional). The search crosses portals, so a neighbouring room's floor is found too. Without it, the room is looked up from the position, which takes the first room that contains it and passes over the flipped-away ones. Where rooms overlap, name the room, or ask the room itself with trx.rooms.Room:floor_height.

    • opts (table, optional). How to read the height.

      Keys:

      • fix_tilts (boolean, optional, default true). Whether a floor tilt that lies inside a wall is taken into account. false gives the flat height read by the original games. Vanilla level geometry can depend on this behaviour.

    Returns: trx.math.Distance or nil. The height, with nil where there is no ceiling.

    Example:

    local ceiling = trx.lara.item.room:ceiling_height(trx.lara.item.pos)
    
  • trx.rooms.find_valid_pos(pos, room_num)
    Nudges a position into valid room geometry, e.g. to find somewhere an item can legally be placed.

    Parameters:

    Returns: