Repository navigation
CustomMaps Roofs
A player who walks into a building disappears under its roof. There are two ways to
open the roof while they are inside - the client's own behaviour 8 in
MapObjectAnimationInfo, and a map script - and one map can use both.
| Behaviour 8 | Map script | |
|---|---|---|
| Lives in |
MapObjectAnimationInfo<n>.txt inside Lang.mpr
|
Maps\<map>.lua |
| Fades when | the object stands between the camera and the player | the player stands in a box around the roof, the building or a rectangle |
| Applies to | every object of the type in that world | every object of a type, or only those in a rectangle |
| A roof built from several pieces | each piece on its own box | opens as one, with whole
|
| Whatever else hangs over the player | only with rows of its own | opens with it, with upper
|
| After a change | repack Lang.mpr, restart the client |
re-enter the map |
One row per object type, in the world's MapObjectAnimationInfo table. From
MapObjectAnimationInfo146.txt:
17 0 0.16 8 300 250 250 700 0 0 0 7
13 0 0.16 8 300 610 100 345 0 0 150 7
Object 17 fades inside a box 250 x 250 x 700 at its origin, 0.07 of the way per frame. Object 13's box is 610 x 100 x 345 and lifted 150 above its origin. Every column is explained under Behaviour 8.
A custom map reads its own table by world number like any other world, so a row like these works there unchanged, with your own object type.
Helpers has three fades. All three are called from Map.OnObject every frame, and
each brings the object back by itself once the player leaves.
For a model that is a roof wherever it stands. No coordinates: every object of the type opens while the player is under it.
local ROOFS =
{
[94] = { sizeX = 150, sizeY = 150, whole = true },
}
for iType in pairs(ROOFS) do
Map.RegisterObject(iType)
end
Map.OnObject(function(o)
local roof = ROOFS[o.type]
if roof then
Helpers.FadeUnder(o, roof)
end
end)| Key | Default | Meaning |
|---|---|---|
sizeX sizeY
|
350 | how far the box reaches out, in world units - one tile is 100 |
below |
700 | how far under the roof the player still counts |
above |
60 | how far above it - small, so someone standing on the roof keeps it |
alpha |
0.1 | what the roof fades to |
rate |
0.12 | the fraction of the way it moves each frame |
whole |
off | open every piece of a building together |
link |
300 | with whole: how far apart two pieces may stand and still be one building |
upper |
off | with whole: also open everything in the building that hangs over the player |
clear |
100 | with upper: how far above the player's feet an object has to stand to open |
early |
0 | open this much sooner than sizeX / sizeY say - for pieces standing out in front of the roof |
per |
none | with whole: values for one building only - see One building differently
|
A roof stands well above the floor the player walks - in Lost Land of Tarkan the temple
roofs sit at 440 over a floor at 200 - so the box reaches down from the roof. That is
what below is for, and why a small below never opens anything.
Without whole every piece opens on its own box, so a roof made of four slabs opens
only over the slabs the player is under. With whole the pieces are joined into
buildings as they come into view - two pieces of the type no more than link apart
along each axis are the same building - and all of them open together. sizeX and
sizeY then reach out from the building's outermost pieces, so they are the distance
from those pieces to the walls.
A roof is often only one layer of what hangs over the player. The pyramid in Lost Land of
Tarkan has a tier of walls at 400 under its roof slabs at 500 and 700, and more stone and a
gem on top. upper = true opens every other object inside the building's footprint whose
origin stands more than clear above the player's feet; walls standing on the floor the
player walks stay.
Those objects are of any type, and only registered types reach the handler, so a map
using upper registers all of them and hands whatever no other rule took to
Helpers.FadeAboveRoofs:
local ROOFS =
{
[94] = { sizeX = 150, sizeY = 150, whole = true, upper = true },
}
Helpers.RegisterAll()
Map.OnObject(function(o)
local roof = ROOFS[o.type]
if roof then
Helpers.FadeUnder(o, roof)
return
end
Helpers.FadeAboveRoofs(o)
end)Registering everything costs one handler call per visible object per frame.
Keys on a ROOFS entry apply to every building of that type. per gives one building its
own values: each item names a tile inside the building, and whatever it leaves out comes
from the entry around it.
[94] =
{
sizeX = 150, sizeY = 150, whole = true, upper = true,
per =
{
-- The pyramid: a gem and a cobra stand just past its footprint over the entrance.
{ x = 184, y = 23, early = 100 },
},
},early moves both edges at once: the player opens the building that much sooner, and with
upper the footprint of what opens with it grows by the same amount - so pieces standing
just in front of the roof go too.
For a building whose pieces also stand elsewhere as something else, where fading by
type would take them away across the whole map. Helpers.FadeArea(o, area) fades what
stands inside a rectangle of tiles, while the player is inside it too.
local BUILDINGS =
{
{ x1 = 195, y1 = 40, x2 = 199, y2 = 45, types = { [94] = true } },
}| Key | Meaning |
|---|---|
x1 y1 x2 y2
|
the rectangle, in the tile coordinates the position readout shows |
types |
only these types fade; without it everything in the rectangle does |
minZ |
only what stands at least this high, in world units |
alpha rate
|
as above; defaults 0.1 and 0.12 |
FadeArea returns nil for an object that is not its own - outside the rectangle or of
another type - so rectangles can be tried first and the object handed on to the rules by
type:
Map.OnObject(function(o)
for i = 1, #BUILDINGS do
if Helpers.FadeArea(o, BUILDINGS[i]) ~= nil then
return
end
end
local roof = ROOFS[o.type]
if roof then
Helpers.FadeUnder(o, roof)
end
end)The types still have to be registered, as for ROOFS.
-
The type is the model's file number minus one:
Object95.bmdis type 94. -
Heights come from the game itself. Log them once while standing inside:
local hx, hy, hz = Map.HeroPosition() Log.Add(string.format("hero %.0f %.0f %.0f roof %.0f", hx, hy, hz, o.positionZ))
The script writes alpha straight into the object. It only ever brings back what it
faded itself, so every other object keeps the distance fog fade even
on a map that registers all types. Leave alphaEnable off: it puts the object on a
blend path that breaks its shadow and depth.
- Object effects and animations - behaviour 8 and the rest of the table
-
Map scripts -
Map.OnObjectand registering types -
Objects and the sandbox -
alpha,alphaTargetand the other properties
MuLua Scripting Plugin | Home
🖼️ Lua UI
- File map
- Creating windows
- Client and server
- Designing a window
- Protocol
- Scrolling and scrollbars
- Controls
- Custom text
- Text input
- Debug console
- Bitmap Slicer
- Encrypting scripts
Maps
Monsters
Shared
Version 1.14 | 2026-09-09