mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-16 17:31:27 +00:00
bb71052cb7
git-svn-id: https://svn.eduke32.com/eduke32@3907 1a8010ca-5511-0410-912e-c29ae57300e0
1123 lines
42 KiB
Text
1123 lines
42 KiB
Text
Lunatic User Manual
|
|
===================
|
|
Helixhorned <contact: Duke4.net forums>
|
|
:max-width: 56em
|
|
:numbered:
|
|
:icons:
|
|
|
|
|
|
|
|
Introduction
|
|
------------
|
|
|
|
|
|
Language
|
|
--------
|
|
:Lua51: http://www.lua.org/about.html
|
|
:Lua51Ref: http://www.lua.org/manual/5.1/
|
|
:PiL: http://www.lua.org/docs.html
|
|
|
|
:LuaJIT: http://luajit.org
|
|
:LuaJIText: http://luajit.org/extensions.html
|
|
|
|
The base language for writing Lunatic user code is {Lua51}[Lua 5.1]. It is
|
|
extensively documented in a {Lua51Ref}[Reference Manual], as well as described
|
|
more broadly and accessibly in the {PiL}[Programming in Lua] books.
|
|
// TODO: describe Lua a bit
|
|
// TODO: give hints which PiL to read / how
|
|
|
|
Because Lunatic is implemented using {LuaJIT}[LuaJIT], a just-in-time compiler
|
|
for the Lua language, some {LuaJIText}[extensions] to the core language are
|
|
automatically available. They may be used if no compatibility with Rio Lua 5.1
|
|
is desired.footnote:[Not all extensions from LuaJIT are available, since some
|
|
like the FFI are targeted at C programmers rather than scripting coders.]
|
|
|
|
NOTE: The length operator (`#`) for table arguments should be taken to be
|
|
defined by the http://www.lua.org/manual/5.2/manual.html#3.4.6[stricter wording
|
|
of Lua 5.2].
|
|
|
|
|
|
Environment and Usage
|
|
---------------------
|
|
|
|
Lunatic aims to provide a _safe_ scripting environment for EDuke32. Thus, not
|
|
all of Lua's functionality is available in Lunatic, and some is slightly
|
|
altered to play well with being embedded into a game, or to prevent commonly
|
|
occurring mistakes.
|
|
|
|
.Differences from default Lua environment
|
|
- Creating new global variables in the global environment is forbidden.
|
|
- In module context, referencing a non-existent variable (i.e. one that has
|
|
value *nil*) is an error.
|
|
|
|
EDuke32 can load multiple Lunatic _modules_ when starting up. This is always
|
|
done after translating CON code to Lua and loading it. Such modules must be
|
|
named `*.lua` (case-sensitive) and should be passed directly, without any
|
|
option letters, at the command line. Directory separators must be forward
|
|
slashes.
|
|
|
|
.Invocation example
|
|
====================
|
|
`eduke32 -nologo MYTC.CON -mx addition.con test.lua weapons/nuke.lua -v1 -l1`
|
|
====================
|
|
|
|
|
|
Global Environment
|
|
------------------
|
|
|
|
When a Lua module is loaded, its global environment contains both selected
|
|
functions from core Lua, as well as Lunatic's own pre-defined variables.
|
|
These allow access and manipulation of EDuke32 engine and game data.
|
|
|
|
[icon="icons/din_w_explosive.png"]
|
|
CAUTION: If an attempt is made to create a new variable in the global
|
|
environment or to assign any value to an existing variable, the behavior is
|
|
undefined.
|
|
|
|
Lua functions
|
|
~~~~~~~~~~~~~
|
|
|
|
The following base Lua functions are available in Lunatic's global environment:
|
|
|
|
`assert`, *`error`*, `ipairs`, `pairs`, `pcall`, *`print`*, *`module`*, `next`,
|
|
*`require`*, `select`, `tostring`, `tonumber`, `type`, `unpack`, `xpcall`.
|
|
|
|
The bold ones add functionality or behave slightly differently, described below.
|
|
Additionally, `printf` is provided for convenience.
|
|
|
|
[[error]] *`error(message [, level])`*::
|
|
In Lunatic, errors also print to the on-screen display (OSD) and are written to
|
|
the log (unless a maximum error count is exceeded). These also have a
|
|
_backtrace_ added. Additionally, errors not caught by a `pcall` result a
|
|
permanent message to appear on the screen, containing the source file name and
|
|
line number.
|
|
|
|
*`print(...)`*::
|
|
The messages are printed to the OSD and the log. Color codes available in
|
|
EDuke32 (e.g. `^10` for dark red) are interpreted. Overriding `tostring` has no
|
|
effect on Lunatic's `print` as it uses the initial, built-in `tostring`
|
|
function instead of looking it up in the global environment.
|
|
|
|
*`printf(fmt, ...)`*::
|
|
Calls `print` with the result of `string.format(fmt, ...)`.
|
|
|
|
Writing and using modules
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
In Lunatic, like in Lua, a _module_ is a conceptually a sort of package that
|
|
unites related bits of functionality. Language-wise, it is simply a Lua
|
|
table holding its contents, as described and motivated at length in
|
|
_Programming in Lua_.
|
|
|
|
The ``creation'' and ``usage'' sides of the modularity concept are reflected in
|
|
two functions known from Lua 5.1, `module` and `require`. The former is a
|
|
convenient way of separating the _import_, potential _gamevar_, and main body
|
|
sections when writing a package. It is not required to use `module`, but it is
|
|
the only way to declare _game variables_, that is, variables that EDuke32
|
|
stores within savegames, recreating their values when they are loaded.
|
|
|
|
The other side of the coin, `require`, is also used like in Lua: ``including''
|
|
a named module is requested by passing its name to `require`. This searches for
|
|
a matching module, loading and running it if the request happens for the first
|
|
time.
|
|
|
|
==== The function `require(modname, ...)`
|
|
|
|
Attempts to find a Lua or Lunatic module named `modname`. The name can refer to
|
|
a _built-in_ module, of which the following ones are allowed:
|
|
|
|
* The http://bitop.luajit.org/[`bit`] module for bitwise operations
|
|
* `math`, `string` and `table`, base modules from Lua
|
|
* Lua's `os` module, containing a single function, `clock`. Like the
|
|
<<timing_funcs,timing functions>>, it should only be used to profile bits of
|
|
code.
|
|
* Modules provided by Lunatic, which will be described in <<ext_api,their own
|
|
section>>.
|
|
|
|
If `modname` does not designate a built-in module, Lunatic first replaces every
|
|
dot contained in it with a directory separator. Then, it looks for a file with
|
|
that base name suffixed with `.lua` in the EDuke32 search path (virtual file
|
|
system, GRP, ZIP). Using directory separators directly is not allowed.
|
|
|
|
The loaded module is protected so that write accesses to its table yield
|
|
errors. Unlike in Lua, our `require` does not return *true* when a module is
|
|
requested that has not yet finished loading (that is, the inclusion chain
|
|
contains a loop). Instead, an error is raised.
|
|
|
|
Lunatic's `require` allows passing additional arguments to the module to load.
|
|
On the module side, they can be obtained by examining the vararg expression
|
|
``++\...++'' at file scope. Given a definition of `args` as `{...}`, its
|
|
first element `args[1]` would contain `modname` and the following entries the
|
|
values passed in addition to `require`. This feature is useful for
|
|
parametrizing a module: for example, it could provide a way alter the starting
|
|
tile number of an actor it defines.
|
|
|
|
Issuing `require` for ```end_gamevars`'' has a special meaning that is
|
|
described below. A `require` for ```CON.DEFS`'' returns a table mapping labels
|
|
++define++d from CON to their values, except for `NO`.
|
|
|
|
|
|
==== The `module()` function
|
|
|
|
Initiates a _module_ environment by creating a new empty table and setting it
|
|
as the global environment of the chunk. Unlike Lua 5.1, our `module` takes
|
|
neither a name argument nor ``option'' varargs. A Lunatic file may have at most
|
|
one call to `module`, which (if there is one) *must* be called at file scope.
|
|
|
|
===== Game variables
|
|
|
|
Lunatic has a special mechanism to mark variables that represent persistent
|
|
state and whose values should be stored in savegames. If such variables are
|
|
desired, they must be initialized between the `module` call in a Lua file and a
|
|
closing `require("end_gamevars")`.footnote:[The reason that the initialization
|
|
has to happen between the `module` and the `require('end_gamevars')` is that on
|
|
savegame loading, gamevars are restored from the latter.] These variables may
|
|
also be *`local`*.
|
|
|
|
Game variables may take on only values of types that Lunatic knows how to
|
|
serialize into savegames. These are the following:
|
|
|
|
* booleans, numbers, and strings
|
|
* tables, but with restrictions on their contents and topology described below (TODO)
|
|
* custom Lunatic types that are labeled _serializeable_ in their documentation
|
|
|
|
// [icon="icons/din_w_collapse.png"]
|
|
|
|
// TODO: example?
|
|
|
|
// TODO: the rest
|
|
|
|
|
|
The ``gv'' variable
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
Some constants, global C variables, and miscellaneous functions and structures
|
|
are accessible via the global `gv` variable.
|
|
|
|
Constants
|
|
^^^^^^^^^
|
|
`gv.MAXSECTORS`, `gv.MAXWALLS`, `gv.MAXSPRITES`::
|
|
The hard engine limits on the number of sectors, walls, and sprites. These
|
|
constants *must* be used instead of any literal numeric values because they
|
|
can change depending on how EDuke32 was configured and built.
|
|
|
|
//////////
|
|
`gv.MAXSTATUS`, `gv.MAXTILES`, `gv.MAXSPRITESONSCREEN`::
|
|
TODO
|
|
|
|
`gv.MAXBUNCHES`, `gv.CEILING`, `gv.FLOOR`::
|
|
TODO
|
|
//////////
|
|
|
|
`gv.CLIPMASK0`::
|
|
A clipping (collision detection) mask specifying to consider only _blocking_
|
|
walls and sprites.
|
|
|
|
`gv.CLIPMASK1`::
|
|
A clipping (collision detection) mask specifying to consider only _hitscan
|
|
sensitive_ walls and sprites.
|
|
|
|
// Game-side
|
|
`gv.*` inventory indices::
|
|
`GET_STEROIDS`, `GET_SHIELD`, `GET_SCUBA`, `GET_HOLODUKE`, `GET_JETPACK`,
|
|
`GET_DUMMY1`, `GET_ACCESS`, `GET_HEATS`, `GET_DUMMY2`, `GET_FIRSTAID`, `GET_BOOTS`.
|
|
`GET_MAX`.
|
|
|
|
`gv.*` weapon indices::
|
|
`KNEE_WEAPON`, `PISTOL_WEAPON`, `SHOTGUN_WEAPON`, `CHAINGUN_WEAPON`, `RPG_WEAPON`,
|
|
`HANDBOMB_WEAPON`, `SHRINKER_WEAPON`, `DEVISTATOR_WEAPON`, `TRIPBOMB_WEAPON`,
|
|
`FREEZE_WEAPON`, `HANDREMOTE_WEAPON`, `GROW_WEAPON`. `MAX_WEAPONS`.
|
|
|
|
// TODO: the others, like EVENT_*.
|
|
//////////
|
|
[[gv_STAT]]
|
|
`gv.*` sprite status numbers::
|
|
`STAT_DEFAULT`, `STAT_ACTOR`, `STAT_ZOMBIEACTOR`, `STAT_EFFECTOR`,
|
|
`STAT_PROJECTILE`, `STAT_MISC`, `STAT_STANDABLE`, `STAT_LOCATOR`,
|
|
`STAT_ACTIVATOR`, `STAT_TRANSPORT`, `STAT_PLAYER`, `STAT_FX`, `STAT_FALLER`,
|
|
`STAT_DUMMYPLAYER`, `STAT_LIGHT`.
|
|
//////////
|
|
|
|
//////////
|
|
`gv.MAXPLAYERS`::
|
|
TODO
|
|
//////////
|
|
|
|
Variables
|
|
^^^^^^^^^
|
|
|
|
`gv.totalclock` (read-only)::
|
|
The current value of the engine timer that increments at a rate of 120 per
|
|
second under default settings. (Thus, one game tic corresponds to four
|
|
`totalclock` increments.) When staying within one ``mode'' such as in-menu or
|
|
in-game, it is guaranteed to not decrease. However, going from one mode to
|
|
another may produce discontinuities.
|
|
|
|
`gv.screenpeek` (read-only)::
|
|
The player index of the player from whose position the scene is being displayed.
|
|
|
|
`gv.hudweap`::
|
|
A structure containing information about the currently displayed HUD weapon.
|
|
Contains the following members, which are set from C before entering
|
|
`EVENT_DISPLAYWEAPONS`: `cur`, `count`, `gunposx`, `gunposy`, `lookhalfang`,
|
|
`lookhoriz`, `shade`.
|
|
// TODO: describe
|
|
|
|
`gv.cam`::
|
|
A structure that, prior to entering `EVENT_DISPLAYROOMS`, is populated with the
|
|
position and orientation of the ``camera'' from which the scene would be drawn.
|
|
Contains the following members: `pos`, `dist`, `clock`, `ang`, `horiz`, `sect`.
|
|
// TODO: describe
|
|
|
|
// TODO: g_logoFlags, g_RETURN?
|
|
|
|
Functions
|
|
^^^^^^^^^
|
|
[[timing_funcs]]
|
|
`gv.getticks()`, `gv.gethiticksms()`::
|
|
Each of these functions return a number that increases at a rate of 1 per
|
|
millisecond. Their only intended application is to profile bits of code; they
|
|
should not be used to control the game world. The two functions differ in their
|
|
precision: `getticks()` always returns integral values, while the result of
|
|
`gethiticksms()` also has an unspecified precision in the fractional part. (It
|
|
can be expected to give a time precision of at least one microsecond.)
|
|
|
|
`gv.doQuake(gametics [, snd])`::
|
|
Requests from the game to perform the ``quake'' effect that shakes the screen
|
|
etc. for the next `gametics` game tics. If a sound index `snd` is passed, also
|
|
start playing that sound.
|
|
// TODO: Play sound how? ("globalsound")
|
|
|
|
//////////
|
|
`gv.currentEpisode()`::
|
|
TODO
|
|
`gv.currentLevel()`::
|
|
TODO
|
|
`gv.currentRenderMode()`::
|
|
TODO
|
|
//////////
|
|
|
|
Lunatic structures
|
|
~~~~~~~~~~~~~~~~~~
|
|
|
|
The primary means of effecting game state in Lunatic is via _composite
|
|
variables_ defined in the global environment. These provide direct, but
|
|
restricted, access to C _structure arrays_ of the EDuke32 engine or game.
|
|
|
|
[icon="icons/din_w_toxic.png"]
|
|
CAUTION: If an attempt is made to access any composite variable outside of
|
|
event or actor code, the behavior is undefined.
|
|
|
|
Composite variables can be used in various ways. All of them allow indexing
|
|
with an integer value from `0` to some maximum (sometimes the size of the array
|
|
minus one, but occasionally less). For example, the code snippet
|
|
----------
|
|
local sec = sector[0]
|
|
----------
|
|
gets a _reference_ to the first sector of the loaded map into the local `sec`.
|
|
This reference can then be used to both read and write its members.
|
|
|
|
Various structures also provide _methods_ in Lunatic to modify their state,
|
|
usable with Lua's `v:func(args...)` syntax. Building on the previous example,
|
|
----------
|
|
local cz = sec:ceilingzat(wall[sec.wallptr])
|
|
----------
|
|
would get into `cz` the ceiling z position at the first sector's first
|
|
wall-point.
|
|
|
|
Finally, some composite variables offer _static data_, which can contain
|
|
functions or tables of constants. These are accessed using the dot notation on
|
|
the composite variable, *not* its constituents. For instance, the following can
|
|
be used to change the sector number of the sprite with index `i` manually:
|
|
----------
|
|
sprite.changesect(i, sectnum)
|
|
----------
|
|
|
|
|
|
Type of structure members
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
In the following, some structure members will be annotated with their _integer
|
|
type_, for example _`i16`_ or _`u8`_. The letter _`i`_ denotes a _signed_
|
|
integer whereas a _`u`_ designates an _unsigned_ one. The number following that
|
|
letter indicates the _bit width_ of that integer.
|
|
|
|
.Representable values
|
|
* A member of signed integer type and bit width _B_ can contain any whole
|
|
number from --2^_B_--1^ to 2^_B_--1^--1. +
|
|
|
|
* A member of unsigned integer type and bit width _B_ can contain any whole
|
|
number from 0 to 2^_B_^--1.
|
|
|
|
[[int_assignment]]
|
|
.Assignment
|
|
* If an assignment to a member having signed integer type is made, the
|
|
``right-hand side'' value must be a number in the closed interval
|
|
[--2^31^ .. 2^31^--1].
|
|
|
|
* If an assignment to a member having unsigned integer type and bit width _B_
|
|
is made, the ``right-hand side'' value must be in the closed interval
|
|
[--2^31^ .. 2^31^--1] if _B_ is less than 32, or in [0 .. 2^32^--1] otherwise.
|
|
|
|
* If the appropriate requirements hold, an assignment from a Lua number to a
|
|
member having integer type begins by discarding the fractional part
|
|
(``truncation''). Otherwise, the behavior is undefined. +
|
|
|
|
* If the truncated value is outside the range of representable values for the
|
|
corresponding integer type of bit width _B_, the final value is obtained by
|
|
successively adding or subtracting 2^B^, until the value falls inside that
|
|
range.
|
|
|
|
//////////
|
|
NOTE to self: this is stricter than C99 (which has first truncation, then range
|
|
check). Also, it may be tempting to assign 0x80000000 to an int32_t to mean
|
|
INT32_MIN, but this is wrong because it's out of range.
|
|
Also see:
|
|
http://lua-users.org/lists/lua-l/2011-09/msg00534.html
|
|
//////////
|
|
|
|
.Examples
|
|
1. Assignments to _`u8`_ member `visibility`
|
|
* `sec.visibility=3.94159` results the member to contain the integer `3`
|
|
* `sec.visibility=1/0` is undefined (attempt to assign an infinity)
|
|
* `sec.visibility=-1` results the member to contain the integer `255`
|
|
|
|
2. Assignments to _`i16`_ member `lotag`
|
|
* `sec.lotag=32768` results the member to contain `-32768`
|
|
* `sec.lotag=2^32` is undefined
|
|
|
|
Bit fields
|
|
^^^^^^^^^^
|
|
|
|
Some structures contain members that represent a collection of _flags_, for
|
|
example `sprite[].cstat` or `actor[].flags`. These flags can be toggled by
|
|
setting or clearing their respective _bits_ (integer numbers that are powers of
|
|
two).
|
|
|
|
For convenience, Lunatic provides alternative names for some of these members,
|
|
together with methods to examine or modify any number of bits of such a member
|
|
in one expression. Whenever there is such an alternative name available, it is
|
|
declared as having type _`bitfield`_ in the listings of the structure members.
|
|
|
|
===== methods of the _`bitfield`_ type
|
|
|
|
`bf:set(bits)`::
|
|
_Sets_ (toggles to an ``on'' state in a boolean sense) those bits of `bf`
|
|
that are set in `bits`.
|
|
|
|
`bf:clear(bits)`::
|
|
_Clears_ (toggles to an ``off'' state in a boolean sense) those bits of `bf`
|
|
that are set in `bits`.
|
|
|
|
`bf:flip(bits)`::
|
|
_Flips_ those bits of `bf` that are set in `bits`, that is, reverses their
|
|
boolean state.
|
|
|
|
`bf:test(bits)`::
|
|
Returns a boolean that indicates whether `bf` has *any* of the bits set in
|
|
`bits` set.
|
|
|
|
.Examples
|
|
==========
|
|
After the lines setting sprite `i` to 33% translucent and blocking,
|
|
----------
|
|
local CS = sprite.CSTAT
|
|
local spr = sprite[i]
|
|
spr.cstat = CS.TRANS1 + CS.BLOCK
|
|
----------
|
|
one could proceed as follows for the sake of example:
|
|
|
|
* `spr.cstatbits:set(CS.TRANS2)`, make the sprite 66% translucent now
|
|
* `spr.cstatbits:flip(CS.BLOCK + CS.HITSCAN)`, make it hitscan-sensitive but not blocking
|
|
* `spr.cstatbits:test(CS.FLIP_BITMASK)`, check whether it is flipped (no)
|
|
==========
|
|
|
|
Engine-side
|
|
^^^^^^^^^^^
|
|
|
|
The composite variables described in this subsection provide access to
|
|
engine-side structures. The first three, `sector`, `wall`, and `sprite`,
|
|
are part of a BUILD map saved to disk. The other ones only exist when
|
|
running the game.
|
|
|
|
===== `sector`
|
|
Accessible from `0` to `gv.numsectors-1`. Each element has the following
|
|
members:
|
|
|
|
`wallptr`, `wallnum` (read-only)::
|
|
The index of the sector's first wall and the number of walls in the sector,
|
|
respectively.
|
|
|
|
_`u8`_ `visibility`::
|
|
Determines the amount of distance fading. In the range [`0` .. `239`], the
|
|
``darkening'' increases with rising values. The range [`240` .. `255`] should
|
|
be thought of as [`-16` .. `-1`].
|
|
// TODO: better wording?
|
|
|
|
_`i16`_ `lotag`, `hitag`, `extra`::
|
|
General-purpose ``tags'' provided for game programming. They may be used by
|
|
various EDuke32 sector effects, so it's not recommended to use them in
|
|
scripting code.
|
|
|
|
In addition to the members described above, each sector has two sets of members
|
|
for its ceiling and floor. A sector reference can be indexed with the strings
|
|
`ceiling` or `floor` to get references to the respective ``parts'', or one can
|
|
access the consituent members by prefixing `ceiling` or `floor` to the base
|
|
member names given below.
|
|
|
|
.Different ways of accessing the same member
|
|
==========
|
|
After the code lines
|
|
----------
|
|
local sec = sector[0]
|
|
local ceil = sec.ceiling
|
|
----------
|
|
the following expressions all denote the same location, both if read or written
|
|
to: `sec.ceilingheinum`, `ceil.heinum`, `sector[0].ceiling.heinum`,
|
|
`sector[0].ceilingheinum`.
|
|
==========
|
|
|
|
In the following, `cf` will stand for a ceiling or floor reference, while `sec`
|
|
will label a sector reference.
|
|
|
|
`cf.picnum` (read-only)::
|
|
The tile number of the ceiling or floor.
|
|
|
|
[[cf_stat]] _`u16`_ `cf.stat`, {nbsp} _`bitfield`_ `cf.statbits`::
|
|
A bit field holding various flags about how the ceiling or floor shoud be
|
|
displayed, how collision detection should be handled, etc.
|
|
The <<sector_STAT,`sector.STAT`>>
|
|
object should be used to obtain the values for applicable flags.
|
|
|
|
_`i16`_ `cf.heinum`::
|
|
If `cf.stat` has bit `sector.STAT.SLOPE` set, the tangent of the slope angle
|
|
multiplied by 4096. Positive values make the ceiling or floor slope towards
|
|
the floor, negative ones slope upward.
|
|
|
|
[[cf_z]] _`i32`_ `cf.z`::
|
|
The BUILD z coordinate (scaled by 16 compared to the x and y directions) of the
|
|
pivoting line of the ceiling or floor.
|
|
|
|
`cf.bunch` (read-only)::
|
|
The ``bunch'' number of the ceiling or floor used for True Room over Room. One
|
|
bunch comprises _N_ ceilings and _M_ floors (_N_ ≥ 1, _M_ ≥ 1) such that
|
|
each set covers the same planar, connected area.
|
|
|
|
_`i8`_ `cf.shade`::
|
|
The shade of the ceiling or floor. Larger values mean a more darker appearance.
|
|
|
|
_`u8`_ `cf.pal`::
|
|
The ``palette swap'' index of the ceiling or floor.
|
|
|
|
_`u8`_ `cf.xpanning`, `cf.ypanning`::
|
|
The panning values of the ceiling or floor. One full cycle is covered by values
|
|
from `0` to `255`.
|
|
|
|
===== `sector` methods
|
|
|
|
`sec:set_ceilingpicnum(tilenum)`, `sec:set_floorpicnum(tilenum)`::
|
|
Set the tile number of the ceiling or floor.
|
|
|
|
`sec:ceilingzat(pos)`, `sec:floorzat(pos)`::
|
|
Return the z coordinate of sector `sec`'s ceiling or floor at position `pos`,
|
|
which can be anything indexable with the strings `x` and `y`.
|
|
|
|
//////////
|
|
`zrangeat(pos, walldist, cliptype)`::
|
|
TODO
|
|
//////////
|
|
|
|
===== `sector` static data
|
|
|
|
[[sector_STAT]] `sector.STAT`::
|
|
Provides a mapping of symbolic names to values applicable to <<cf_stat,`cf.stat`>>.
|
|
These name single bits:
|
|
`PARALLAX`, `SLOPE`, `SWAPXY`, `SMOOSH`, `FLIPX`, `FLIPY`, `RELATIVE`, `MASK`,
|
|
`TRANS1`, `TRANS2`, `BLOCK`, `HITSCAN`, while the following denote _bit masks_:
|
|
`FLIP_BITMASK`, `ORIENT_BITMASK`, `TRANS_BITMASK`.
|
|
|
|
'''
|
|
[[wall]]
|
|
===== `wall`
|
|
Accessible from `0` to `gv.numwalls-1`. Each element has the following
|
|
members:
|
|
|
|
`x`, `y`::
|
|
The 2D coordinates or this wall point. Should not be set directly.
|
|
|
|
`z` (read-only)::
|
|
Always yields `0`. The primary purpose of this field is to make wall references
|
|
permissible as arguments to <<vector_types,`xmath` vector>> operations.
|
|
|
|
`point2` (read-only)::
|
|
The index of the second wall point.
|
|
|
|
`nextwall`, `nextsector` (read-only)::
|
|
If the wall is ``white'', these members equal `-1`. For ``red'' walls, they
|
|
contain the wall and sector indices (respectively) of the wall on the other side.
|
|
|
|
`upwall`, `dnwall` (read-only)::
|
|
For walls constrained by TROR extension, the upper and lower neighbor walls,
|
|
respectively. Any of them may be `-1`, meaning that the wall is not attached to
|
|
a neighbor in this direction.
|
|
|
|
[[wall_cstat]] _`u16`_ `cstat`, {nbsp} _`bitfield`_ `cstatbits`::
|
|
A bit field holding various flags about how the wall shoud be
|
|
displayed, how collision detection should be handled, etc.
|
|
The <<wall_CSTAT,`wall.CSTAT`>>
|
|
object should be used to obtain the values for applicable flags.
|
|
|
|
[[wall_picnum]]`picnum` (read-only)::
|
|
The tile number of the non-masked portion of the wall. If
|
|
`wall.CSTAT.BOTTOMSWAP` is set on this wall's `.cstat`, it is only displayed in
|
|
the upper portion. (The lower portion takes it from this wall's `.nextwall`
|
|
then; this will be labeled _use-other-bottom_ in the following.)
|
|
|
|
`overpicnum` (read-only)::
|
|
The tile number of the masked portion of the wall, i.e. that which is drawn if
|
|
this wall's `.cstat` has bit `wall.CSTAT.MASK` or `wall.CSTAT.ONEWAY` set.
|
|
|
|
_`i8`_ `shade` (<<wall_picnum,_use-other-bottom_>>)::
|
|
The shade of the wall for both non-masked and masked portions. Larger values mean a more darker appearance.
|
|
|
|
_`u8`_ `pal` (<<wall_picnum,_use-other-bottom_>>)::
|
|
The ``palette swap'' index of the wall.
|
|
|
|
_`u8`_ `xrepeat`, `yrepeat`::
|
|
Values that are proportional to the number of times that the wall's texture
|
|
repeats in each direction per given wall length/height. A value of `8` renders
|
|
64 texels across a length of 1024 x/y map units or a height of 16384 z units.
|
|
|
|
_`u8`_ `xpanning`, `ypanning` (<<wall_picnum,_use-other-bottom_>>)::
|
|
The panning values of both masked and non-masked portions of the wall. One full
|
|
cycle is covered by values from `0` to `255`.
|
|
|
|
_`i16`_ `lotag`, `hitag`, `extra`::
|
|
General-purpose ``tags'' provided for game programming. They may be used by
|
|
various EDuke32 effects internally, so it is advised to do some research before
|
|
claiming them for oneself.
|
|
|
|
===== `wall` methods
|
|
|
|
`wal:set_picnum(tilenum)`, `wal:set_overpicnum(tilenum)`::
|
|
Set the tile number of the wall or its masked portion.
|
|
|
|
===== `wall` static functions
|
|
|
|
`wall.dragto(i, pos)`::
|
|
Set the position of the point of the wall with index `i` to `pos`, which can be
|
|
anything indexable with `x` and `y`. This function is the preferred way of
|
|
changing wall coordinates, since it takes care to reposition dependent wall
|
|
points, too.
|
|
|
|
===== `wall` static data
|
|
|
|
[[wall_CSTAT]] `wall.CSTAT`::
|
|
Provides a mapping of symbolic names to values applicable to <<wall_cstat,`wall[i].cstat`>>.
|
|
These name single bits:
|
|
`BLOCK`, `BOTTOMSWAP`, `ALIGNBOTTOM`, `FLIPX`, `MASK`, `ONEWAY`, `HITSCAN`,
|
|
`TRANS1`, `FLIPY`, `TRANS2`,
|
|
while the following denote _bit masks_:
|
|
`FLIP_BITMASK`, `TRANS_BITMASK`.
|
|
|
|
'''
|
|
===== `sprite`
|
|
|
|
The `sprite` composite is accessible with indices from `0` to
|
|
`gv.MAXSPRITES-1`, but accesses to sprites that do not exist in the game world
|
|
have no meaning. Each element has the following members:
|
|
|
|
`x`, `y`, `z`::
|
|
The BUILD coordinates of the sprite. It is not advisable to set these directly.
|
|
|
|
//////////
|
|
_`i16`_ `ang`::
|
|
TODO (make set_ang() out of that which always ANDs with 2047?)
|
|
//////////
|
|
|
|
[[sprite_cstat]] _`u16`_ `cstat`, {nbsp} _`bitfield`_ `cstatbits`::
|
|
A bit field holding various flags about how the sprite shoud be
|
|
displayed, how collision detection should be handled, etc.
|
|
The <<sprite_CSTAT,`sprite.CSTAT`>>
|
|
object should be used to obtain the values for applicable flags.
|
|
|
|
`picnum` (read-only)::
|
|
The tile number of the sprite, also used to determine which _actor_ code is run
|
|
if this sprite has a `statnum` of `actor.STAT.ACTOR`.
|
|
|
|
_`i8`_ `shade`::
|
|
The shade of the sprite. This may not be the shade that this sprite is
|
|
ultimately drawn with, though.
|
|
|
|
_`u8`_ `pal`::
|
|
The ``palette swap'' index of the sprite. This may not be the palette swap that
|
|
this sprite is ultimately drawn with, though.
|
|
|
|
_`u8`_ `clipdist`::
|
|
If this sprite is _view-aligned_, controls the distance at which another moving
|
|
object is considered to be in collision with this *stationary* sprite. (It does
|
|
not control the inverse case.) More precisely, it designates half the
|
|
side-length of the bounding square divided by 4. Thus, a value of `255` keeps
|
|
moving objects away from this one at a max-norm distance
|
|
footnote:[The max-norm distance between points _p_~1~=(x~1~, y~1~) and
|
|
_p_~2~=(x~2~, y~2~) is defined as max(abs(x~2~ -- x~1~), abs(y~2~ -- y~1~)).]
|
|
of at least 1020
|
|
BUILD x/y units.
|
|
|
|
_`u8`_ `xrepeat`, `yrepeat`::
|
|
The size of the sprite in each dimension. For wall- and floor- aligned sprites,
|
|
a value of `64` means a width of 16 x/y BUILD units or a height of 256 z BUILD
|
|
units per texel.
|
|
|
|
`sectnum` (read-only)::
|
|
The index of the sector that this sprite is currently contained in.
|
|
|
|
[[sprite_statnum]] `statnum` (read-only)::
|
|
The current _status number_ of this sprite. Applicable values are contained in
|
|
<<actor_STAT,`actor.STAT`>>.
|
|
|
|
`owner` (read-only)::
|
|
The index of the sprite from which this sprite was spawned. If this sprite is
|
|
not a ``child'' of another one, then `owner` is the index of this sprite itself.
|
|
//Occasionally, game effects may use this member for their particular purposes,
|
|
//so research is recommended before claiming it for oneself.
|
|
|
|
_`i16`_ `xvel`, `zvel`::
|
|
For _actors_ and other moving sprite types, the horizontal and vertical
|
|
components of the current velocity.
|
|
//It is not advisable to set these directly
|
|
//unless one knows how they are processed.
|
|
|
|
//`yvel` (read-only)::
|
|
//A general-purpose member of which the game has exclusive control.
|
|
|
|
_`i16`_ `lotag`, `hitag`, `extra`::
|
|
General-purpose ``tags'' provided for game programming. They may be used by
|
|
hard-coded actors internally, so it is advised to do some research before
|
|
claiming them for oneself.
|
|
|
|
===== `sprite` methods
|
|
|
|
`spr:set_picnum(tilenum)`::
|
|
Set the tile number of the sprite.
|
|
|
|
===== `sprite` static functions
|
|
|
|
`sprite.changesect(i, sectnum)`::
|
|
Allows to manually change the sector number of the sprite with index `i` to
|
|
`sectnum`.
|
|
|
|
`sprite.changestat(i, statnum)`::
|
|
Allows to manually change the status number of the sprite with index `i` to
|
|
`statnum`.
|
|
|
|
===== `sprite` overridden operators
|
|
|
|
[[sprite_power]] `spr^zofs`::
|
|
Returns an <<vector_types,`xmath.ivec3`>> object that contains the position of
|
|
this sprite, diminished by `zofs` in the z direction. Because in BUILD, z
|
|
coordinates increase toward the floor, the `^` can be thought of as ``raise the
|
|
sprite by `zofs` units''.
|
|
|
|
===== `sprite` static data
|
|
|
|
[[sprite_CSTAT]] `sprite.CSTAT`::
|
|
Provides a mapping of symbolic names to values applicable to <<sprite_cstat,`sprite[i].cstat`>>.
|
|
These name single bits:
|
|
`BLOCK`, `TRANS1`, `XFLIP`, `YFLIP`, `ALIGNWALL`, `ALIGNFLOOR`, `ONESIDE`,
|
|
`CENTER`, `HITSCAN`, `TRANS2`,
|
|
while the following denote _bit masks_: `ALIGN_BITMASK`, `TRANS_BITMASK`.
|
|
|
|
===== `spriteext`
|
|
|
|
===== `atsprite`
|
|
|
|
|
|
Game-side
|
|
^^^^^^^^^
|
|
|
|
===== `actor`
|
|
|
|
===== `actor` methods
|
|
|
|
===== `actor` static data
|
|
|
|
[[actor_STAT]]
|
|
`actor.STAT`::
|
|
Provides a mapping of symbolic names to values applicable as sprite
|
|
<<sprite_statnum,status numbers>>. +
|
|
`DEFAULT`, `ACTOR`, `ZOMBIEACTOR`, `EFFECTOR`, `PROJECTILE`, `MISC`,
|
|
`STANDABLE`, `LOCATOR`, `ACTIVATOR`, `TRANSPORT`, `PLAYER`, `FX`, `FALLER`,
|
|
`DUMMYPLAYER`, `LIGHT`.
|
|
|
|
[[actor_FLAGS]] `actor.FLAGS`::
|
|
Contains symbolic names of values applicable to <<gameactor,`gameactor`>>'s
|
|
`flags` input argument, most of which are described there. +
|
|
`SHADOW`, `NVG`, `NOSHADE`, `NOPAL`, `NOEVENTS`, `NOLIGHT`,
|
|
`USEACTIVATOR`, `NOCLIP`, `SMOOTHMOVE`, `NOTELEPORT`.
|
|
|
|
//`BADGUY`,
|
|
|
|
===== `player`
|
|
|
|
===== `player` methods
|
|
|
|
`ps:fadecol(fadefrac, r, g, b [, speed [, prio]])`::
|
|
|
|
Initiates a tinting that linearly fades over time and is blended with the whole
|
|
screen contents whenever player `ps`'s view is displayed.footnote:[The behavior
|
|
is unspecified should more than one player's view be displayed at one time.]
|
|
The first argument `fadefrac` specifies the starting blending coefficient; `r`,
|
|
`g` and `b` specify the intensities of the red, green and blue color
|
|
components, respectively.
|
|
+
|
|
Both `fadefrac` and the component intensities are first clamped to the range
|
|
[0.0 .. 1.0]. The resulting values are interpreted as a fraction, 0.0 meaning
|
|
no blending/no color and 1.0 meaning full blending/full
|
|
color.footnote:[Currently, for implementation reasons, a value of 1.0 results
|
|
in only _almost_ full blending or presence of the specified color component.]
|
|
+
|
|
The fourth, optional argument `speed` controls the rate at which the tinting
|
|
diminishes. At a value of `1` (the default), a tint with a `fadefrac` of 0.5
|
|
finishes in approximately one second.
|
|
+
|
|
The last, optional argument `prio` must be an integer in the range [`-128`
|
|
.. `127`], the default being `0`. When a `fadecol` is issued in the presence of
|
|
another tint fading in progress, and the `prio` given by the arriving `fadecol`
|
|
is greater or equal than the `prio` of the ongoing one, the latter is canceled
|
|
and the arriving fading is initiated in its place. (There is no support for
|
|
tint fades that overlap in time.)
|
|
+
|
|
[icon="icons/din_w_crushing.png"]
|
|
CAUTION: If Lunatic code that uses `fadecol` is loaded together with CON code
|
|
that writes to the player's `pals` members directly at any point, the behavior
|
|
is undefined.
|
|
|
|
===== `projectile`
|
|
|
|
===== `g_tile`
|
|
|
|
===== `g_tile` static data
|
|
|
|
`g_tile.sizx`, {nbsp} `g_tile.sizy`::
|
|
Arrays indexable with tile numbers [`0` .. `gv.MAXTILES-1`] that hold the
|
|
horizontal and vertical texel sizes of each tile.
|
|
|
|
|
|
Lunatic functions
|
|
~~~~~~~~~~~~~~~~~
|
|
|
|
Engine-side
|
|
^^^^^^^^^^^
|
|
|
|
===== Iterators
|
|
|
|
+*for* w *in* wallsofsect(sectnum)+::
|
|
Iterates over the indices of all walls of the sector with index `sectnum`.
|
|
|
|
+*for* s *in* spritesofstat(statnum)+::
|
|
Iterates over the indices of all sprites with status number `statnum`.
|
|
|
|
+*for* s *in* spritesofsect(sectnum)+::
|
|
Iterates over the indices of all sprites contained in the sector with index `sectnum`.
|
|
|
|
cansee
|
|
hitscan
|
|
inside
|
|
neartag
|
|
sectorsofbunch
|
|
updatesector
|
|
updatesectorbreadth
|
|
updatesectorz
|
|
|
|
Customizing the game
|
|
^^^^^^^^^^^^^^^^^^^^
|
|
|
|
In Lunatic, there are two main ways of customizing the game's behavior. Both
|
|
involve the user providing functions that are _called back_ at certain points
|
|
in the execution of EDuke32. Game _actors_ are simply sprites that run a
|
|
particular piece of code based on their tile number each game tic, unless they
|
|
are in a ``dormant'' state. Game _events_ are invoked at predetermined points
|
|
in the program flow.
|
|
|
|
To register custom actor and event code with the game (and define additional
|
|
actor information), Lunatic provides two functions in the global environment,
|
|
`gameactor` and `gameevent`. As their sole argument, they take a table
|
|
containing the appropriate data.
|
|
|
|
[[gameactor]]
|
|
===== The function `gameactor{tilenum [, ...], func}`
|
|
|
|
Registers custom code for the actor given by tile number `tilenum`. For each
|
|
non-sleeping actor, the function `func` is called every game tic with three
|
|
input arguments: `func(aci, pli, dist)`.
|
|
|
|
* `aci`: the sprite number of the actor invoking `func`
|
|
* `pli`: the index of the player that is nearest to this actor
|
|
* `dist`: the 3D Manhattan distance
|
|
footnoteref:[mhdist_def,The Manhattan distance between points
|
|
_p_~1~=(x~1~, y~1~, z~1~) and _p_~2~=(x~2~, y~2~, z~2~) is
|
|
defined as abs(x~2~ -- x~1~) + abs(y~2~ -- y~1~) + abs(z~2~ -- z~1~).]
|
|
between actor `aci` and player `pli`
|
|
|
|
// NOTE: , is the comma; the footnote would be truncated at it otherwise.
|
|
// For a related issue, see
|
|
// http://www.methods.co.nz/asciidoc/faq.html#_why_am_i_having_trouble_getting_nested_macros_to_work
|
|
|
|
Additionally, `gameactor` accepts optional input arguments. They can be
|
|
specifyed positionally by following `tilenum`, or be given as values to string
|
|
keys of the argument table. Each such input argument may be provided in at most
|
|
one of these two forms. Furthermore, `func` may be provided as value to the
|
|
key `'func'` as well.
|
|
|
|
`[2] flags`::
|
|
A number that controls both certain aspects of the `gameactor` call as well as
|
|
the run-time behavior of the actor itself. A couple of bits for the latter type
|
|
are listed in <<actor_FLAGS,`actor.FLAGS`>>, abbreviated `AF` in the following.
|
|
+
|
|
These values describe the ``type'' of the actor: `AF.enemy`, `AF.enemystayput`
|
|
and `AF.rotfixed`. Except for `enemystayput`, they name single bits
|
|
(`enemystayput` implies `enemy`).
|
|
+
|
|
In Lunatic, game actors can be _chained_, that is, a callback function can be
|
|
either appended to the end of an already registered one, or prefixed at its
|
|
front. In this case, a previous `gameactor` call must have taken place for that
|
|
actor (this may have happened from a CON `useractor` block, which gets
|
|
translated to `gameactor`). Moreover, this mechanism allows to add run-time
|
|
flags to the actor in question.
|
|
+
|
|
Several flags in `AF` are provided to control how a `gameactor` invocation
|
|
handles chaining.
|
|
+
|
|
* `AF.replace_hard`: Completely replace the actor's callback function and
|
|
run-time flags. This is the default.
|
|
* `AF.replace_soft`: Replace the callback function, but bitwise-OR the existing
|
|
run-time flags with the provided ones. This is the way CON's `useractor`
|
|
behaves.
|
|
* `AF.chain_beg`: Prepend the provided `func` to the exising callback function,
|
|
bitwise-OR in flags.
|
|
* `AF.chain_end`: Append the provided `func` to the exising callback function,
|
|
bitwise-OR in flags.
|
|
|
|
`[3] strength`::
|
|
The initial strength or health of the actor. Default: `0`.
|
|
|
|
`[4] action`::
|
|
|
|
`[5] move`::
|
|
|
|
`[6] movflags`::
|
|
TODO
|
|
|
|
===== The function `gameevent{evtlabel [, flags], func}`
|
|
|
|
:wiki: http://wiki.eduke32.com
|
|
:wiki_eventlist: http://wiki.eduke32.com/wiki/EDuke32_event_list
|
|
|
|
Registers custom code to be run at specific points in the program. The first
|
|
argument `evtlabel` should be a string naming the event. A complete
|
|
{wiki_eventlist}[list of events] can be found at the {wiki}[EDuke32 wiki]. The
|
|
label may be stripped of the leading ```EVENT_`'', so that e.g. `EVENT_JUMP`
|
|
and simply `JUMP` denote the same event.
|
|
|
|
The arguments `flags` and `func` can alternatively be passed as values to the
|
|
same-named keys of the input argument table to `gameevent`. Like with
|
|
`gameactor`, each may be provided in at most one of the two forms.
|
|
|
|
The callback `func` is invoked with the same arguments and meaning as for
|
|
<<gameactor,`gameactor`>>, but certain events are run in contexts where no
|
|
meaningful `aci` and/or `pli` value can be assigned. In this case, `func`
|
|
receives `-1` for the respective input arguments.
|
|
|
|
Like with actors, game events may be chained or replaced by passing an
|
|
appropriate `flags` value. However, it is not necessary for an event to be
|
|
already defined when chaining is requested. In that case, it is simply
|
|
registered initially. Permissible values for these flags are provided in
|
|
`actor.FLAGS` as well (abbreviated `AF` here):
|
|
|
|
* `AF.replace`: Replace any previously defined event code with the given one.
|
|
* `AF.chain_beg`: Prepend the provided `func` to the exising callback
|
|
function. This is the behavior of CON's `onevent`.
|
|
* `AF.chain_end`: Append the provided `func` to the exising callback
|
|
function. This is the default.
|
|
|
|
// TODO: RETURN handling...
|
|
|
|
|
|
[[ext_api]]
|
|
Extended API (Lunatic modules)
|
|
------------------------------
|
|
|
|
The `xmath` module
|
|
~~~~~~~~~~~~~~~~~~
|
|
|
|
Mathematical functions
|
|
^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Lunatic, being a Lua-based scripting system, provides the user with a single
|
|
numeric data type that variables can contain on the Lua side --
|
|
double-precision floating point.footnote:[In LuaJIT, variables additionaly can
|
|
take on ``boxed'' 64-bit integer numeric types, but these should not be used
|
|
for numeric calculations.] However, since BUILD, and in turn, EDuke32, almost
|
|
exclusively use integer types to represent quantities such as angles or carry
|
|
out e.g. trigonometrical calculations, there is a need for convenient
|
|
interoperability between the two ``worlds''.
|
|
|
|
Two pairs of functions calculate the trigonometric sine and cosine, both
|
|
accepting a BUILD angle as input argument, but differing in the scaling of
|
|
their result. Using these functions is recommended over Lua's `math.sin` or
|
|
`math.cos` in cases where the argument is a BUILD angle in the first place, for
|
|
example because it is read from an engine or game structure. The computation is
|
|
both faster (because it is essentially only a bitwise-AND operation followed by
|
|
a table lookup) and the results have the symmetry expected from the
|
|
mathematical counterparts.
|
|
|
|
`xmath.sinb(bang)`, {nbsp} `xmath.cosb(bang)`::
|
|
Returns the sine/cosine of the given BUILD angle `bang`, which can be any
|
|
whole number in [--2^31^ .. 2^31^--1]. In BUILD, one full cycle is covered by
|
|
values from 0 to 2047; in other words, an angle of 2048 corresponds to 360
|
|
degrees.
|
|
+
|
|
The `sinb` and `cosb` functions return values in the range [--1 .. 1], just
|
|
like their mathematical counterparts.
|
|
+
|
|
The following guarantees are made for `sinb` whereever its argument expression
|
|
is permissible:
|
|
+
|
|
* `sinb(-a) == -sinb(a)` (point symmetry around the origin)
|
|
* `sinb(a + i*2048) == sinb(a)`, where `i` is any whole number (periodicity)
|
|
* `sinb(1024 - a) == sinb(a)` (mirror symmetry around `a`=512)
|
|
* `sinb(a - 1024) == -sinb(a)` (point symmetry around `a`=1024)
|
|
* The value for `cosb(a)` is derived as `sinb(a + 512)`.
|
|
|
|
`xmath.ksin(bang)`, {nbsp} `xmath.kcos(bang)`::
|
|
Returns the sine/cosine of the given BUILD angle `bang`, multiplied with 16384
|
|
and rounded towards zero. The same guarantees as for the `sinb`/`cosb` pair
|
|
apply.
|
|
|
|
`xmath.dist(pos1, pos2)`::
|
|
Returns an approximation of the 3D Euclidean distance between points `pos1` and
|
|
`pos2`, both of which can be any object indexable with `x`, `y` and `z`.
|
|
<<cf_z,BUILD z units>> are assumed.
|
|
|
|
`xmath.ldist(pos1, pos2)`::
|
|
Returns an approximation of the 2D Euclidean distance between points `pos1` and
|
|
`pos2`, both of which can be any object indexable with `x` and `y`.
|
|
|
|
[[vector_types]]
|
|
The types `xmath.vec3` and `xmath.ivec3`
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
Another purpose of the `xmath` module is to provide _vector_ types that allow
|
|
writing concise and clear code involving geometrical calculations. There are
|
|
two types, both containing three components (`x`, `y` and `z`), but differing
|
|
in their numeric type. For the most part, `vec3` should be used, whose
|
|
components are Lua numbers, i.e. floating point. The other type, `ivec3`, is
|
|
part of some game structures, and consequently uses 32-bit integers for its
|
|
components. With minor differences, the `vec3` and `ivec3` types share the same
|
|
operations and methods.
|
|
|
|
The constructors of the vector types can be called in several ways. In the
|
|
following, they are only described for `vec3`. The conventions for `ivec3` are
|
|
completely analogous, but since their creation involves a number type
|
|
conversion, the rules about <<int_assignment,assignment to integer types>>
|
|
apply.
|
|
|
|
`v = xmath.vec3([x [, y [, z]]])`::
|
|
Create a 3-element vector `v` by passing the `x`, `y` and `z` components
|
|
separately. Trailing components can be omitted, in which case they are
|
|
initialized to 0.
|
|
|
|
`v = xmath.vec3(t)`::
|
|
Create a 3-element vector `v` by passing `t`, which can be any variable
|
|
indexable with the strings `x`, `y` and `z` (and yielding numbers for these
|
|
lookups). For example, `t` can be another (`i`)`vec3`, a `sprite` or even
|
|
<<wall,`wall`>> reference, as each of them can be indexed with these three
|
|
keys.
|
|
|
|
Since the vector types are compound objects, they are always passed around by
|
|
reference. For example, consider executing
|
|
----------
|
|
v = xmath.vec3(0, 1)
|
|
w = v
|
|
w.y = 2
|
|
----------
|
|
After this code, the expression `v.x` yields `2` instead of `v`'s initial value
|
|
`1`.
|
|
|
|
===== Operations for `vec3` and `ivec3`
|
|
|
|
In the following, `v` denotes a `vec3` or `ivec3` object reference while `t`
|
|
denotes any object indexable with `x`, `y` and `z`. Note that for binary
|
|
operations, Lua looks for overridden operators in the left operand first and
|
|
the right one next. So, where `t` appears on the left hand side of an
|
|
arithmetic expression, it is assumed that `t`'s type does not overload the
|
|
corresponding operation or provides the same semantics. Arithmetic operations
|
|
always return a (reference to a) new `vec3` object, even if any or both of the
|
|
operands have `ivec3` type.
|
|
|
|
`v + t`, {nbsp} `t + v`::
|
|
Returns a new `vec3` object whose components are the sum of the respective
|
|
components of `v` and `t`.
|
|
|
|
`v - t`, {nbsp} `t - v`::
|
|
Returns a new `vec3` object whose components are the difference of the
|
|
respective components of `v` and `t` (in the first case) or `t` and `v` (in the
|
|
second case).
|
|
|
|
`-v`::
|
|
Returns a new `vec3` object with the components of `v` negated.
|
|
|
|
`a*v`, {nbsp} `v*a`::
|
|
For a scalar number `a`, returns a new `vec3` object whose components are those
|
|
of `v` mutiplied with `a`.
|
|
|
|
`v/a`::
|
|
For a scalar number `a`, returns a new `vec3` object whose components are those
|
|
of `v` divided by `a`.
|
|
|
|
`v^zofs`::
|
|
Returns an object of the same type as `v` and with the same components, except
|
|
that `v.z` is diminished by `zofs`. Also see the <<sprite_power,power
|
|
operation>> for `sprite` objects.
|
|
|
|
`tostring(v)`::
|
|
Returns a string representation of `v` for display purposes: ```vec3`'' or
|
|
```ivec3`'', followed by the components of `v` in parentheses.
|
|
|
|
===== Methods for `vec3` and `ivec3`
|
|
|
|
`v:len()`::
|
|
Returns the Euclidean length of `v` in three dimensions.
|
|
|
|
`v:lensq()`::
|
|
Returns the squared Euclidean length of `v` in three dimensions.
|
|
|
|
`v:len2()`::
|
|
Returns the Euclidean length of `v`, taking only the `x` and `y` components
|
|
into account.
|
|
|
|
`v:len2sq()`::
|
|
Returns the squared Euclidean length of `v`, taking only the `x` and `y`
|
|
components into account.
|
|
|
|
`v:mhlen()`::
|
|
Returns the length of `v` calculated using the Manhattan distance
|
|
footnoteref:[mhdist_def] in three dimensions between the origin and the
|
|
endpoint.
|
|
|
|
`v:toivec3()`::
|
|
Returns a new `ivec3` object with the same components as `v`, but converted
|
|
<<int_assignment,to integers>>.
|
|
|
|
`v:touniform()`::
|
|
Returns a new vector of the same type as `v` which has the same `x` and `y`
|
|
components as `v`, but the `z` element divided by 16 (if `v` is a `vec3`) or
|
|
arithmetically right-shifted by 4 (if `v` is an
|
|
`ivec3`).footnote:[Right-shifting by 4 can be seen as a division by 16 with
|
|
subsequent rounding to an integer towards negative infinity.] Also see the
|
|
description of the ceiling/floor <<cf_z,`z` member>>.
|
|
|
|
`v:tobuild()`::
|
|
Returns a new vector of the same type as `v` which has the same `x` and `y`
|
|
components as `v`, but the `z` element multiplied with 16.
|