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.flipped (boolean). Whether the room map is currently flipped. (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: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 floor.

        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 the original games read there, which is what the geometry glitches of the vanilla levels rest on.

      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()
    Flips the current room map, swapping every room with its flip pair.

  • 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 floor.

      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 the original games read there, which is what the geometry glitches of the vanilla levels rest on.

    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.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: