Lunatic: document previous additions and more of the existing stuff.

git-svn-id: https://svn.eduke32.com/eduke32@3956 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-07-13 21:05:04 +00:00
parent d63939d820
commit e7e8f00670
2 changed files with 214 additions and 69 deletions

View file

@ -61,9 +61,12 @@ Usage
:LPeg: http://www.inf.puc-rio.br/~roberto/lpeg/
The stand-alone LunaCON script, `lunacon.lua`, needs {LuaJIT}[LuaJIT] for
execution and {LPeg}[LPeg] as additional dependency. It expects one or more
names of root CON files together with any number of options, in any order
(arguments starting with a dash are always interpreted as the latter).
execution and {LPeg}[LPeg] as additional dependency.footnote:[In order to
translate some very large CON files, minor modifications have to be made to
LuaJIT and LPeg. Refer to `lunatic/doc/how_to_build_lunatic.txt` in the EDuke32
source distribution for details.] It expects one or more names of root CON
files together with any number of options, in any order (arguments starting
with a dash are always interpreted as the latter).
.Example usage
----------
@ -166,6 +169,18 @@ initializations in the translated Lua code. Otherwise, per-player gamevars are
treated as global gamevars, which can be useful for code that attempts to
access them in contexts with no current player, yielding errors in Lunatic.
`-ftrapv` (default: off)::
Enable _trapping_ behavior for arithmetic operations whose result overflows the
range of a signed 32-bit integer, i.e. generate an error on overflow. By
default, overflow results in undefined behavior. Currently, only multiplication
is handled.
`-fwrapv` (default: off)::
Enable _wrapping_ behavior for arithmetic operations whose result overflows the
range of a signed 32-bit integer, i.e. after each operation, only the 32 lower
bits of the result are kept. Currently, only multiplication is handled. Only
one of `-ftrapv` or `-fwrapv` may be enabled at the same time.
Differences from C-CON
----------------------
@ -176,6 +191,7 @@ cannot be implemented without unnaturally bending the implementation into
shape. On the other hand, LunaCON sports some features that C-CON lacks, and
does not exhibit some of its strange quirks or outright bugs.
Syntactic and lexical changes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -240,6 +256,15 @@ with the definitions above:
* A hexadecimal constant denoted using only a trailing `h`, for example
`00000000h`.
Miscellaneous
^^^^^^^^^^^^^
* Read array expressions as well as `switch` statements can be arbitrarily
nested.
// XXX: 'Read' is confusing. Need better wording.
Run-time changes
~~~~~~~~~~~~~~~~
@ -254,21 +279,38 @@ link:lunatic.html/#nlcf[transfers control] to the end of the innermost
This is in contrast to C-CON, which for some errors would print a message to
the log, but otherwise would continue execution as if nothing had happened. In
LunaCON, the code following an error is *not* executed, forcing the mod author
to fix the bug and obtaining cleaner code.
LunaCON, the code following an error is *not* executed. This way, the author of
the CON code is notified of the presence of the bug, and by fixing it
eventually obtains cleaner code.
Not Yet Implemented
~~~~~~~~~~~~~~~~~~~
Quote behavior
^^^^^^^^^^^^^^
C-CON's `jump` and `getcurraddress` are not available and will not be implemented.
* The `redefinequote` command can be issued even if the given quote number has
not been previously allocated using the `definequote` directive. This makes
it possible to use a range of quote numbers ``on the fly'' without the need
to declare their future use.
Miscellaneous
^^^^^^^^^^^^^
* Issuing `break` inside a part of an event chain (defined using multiple
`onevent` blocks for one event) does not abort the whole chain.
Unavailable functionality
~~~~~~~~~~~~~~~~~~~~~~~~~
C-CON's `jump` and `getcurraddress` are not available and will not be
implemented.
The following commands are not yet implemented. Those highlighted in bold give
errors, while the others merely warn (sometimes at execution
time). Parenthesized commands are of questionable use.
errors, while the others merely warn either at translation or execution
time. Parenthesized commands are of questionable use.
Directives
^^^^^^^^^^
*`includedefault`*, `setcfgname`, `setgamename`, (`precache`), `definecheat`.
*`includedefault`*, `definecheat`, `setcfgname`, `setgamename`, (`precache`)
Run-time commands
^^^^^^^^^^^^^^^^^
@ -276,7 +318,15 @@ Run-time commands
*`activatecheat`*, *`qstrncat`*, *`qsubstr`*, *`clearmapstate`*, `save`,
`savenn`, *`lineintersect`*, *`rayintersect`*, *`sectorofwall`*, *`ssp`*.
Additionally, various multiplayer-related commands either unconditionally
return results as if no multiplayer game is in progress, or are non-functional
for more than the first player. Also, some MP-related variables are merely
predefined constants.
Miscellaneous
^^^^^^^^^^^^^
Gamevar flags 1024 (```NODEFAULT`'') and 131072 (```NORESET`'').
* gamevar flags 1024 (```NODEFAULT`'') and 131072 (```NORESET`'') are not
handled
* mapstate handling in savegames is not yet implemented
* not LunaCON-specific: `EVENT_INIT` is never reached as it runs before Lua state creation

View file

@ -60,9 +60,9 @@ occurring mistakes.
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
done after translating CON code to Lua and loading it. Such modules must reside
in files 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
@ -70,6 +70,13 @@ slashes.
`eduke32 -nologo MYTC.CON -mx addition.con test.lua weapons/nuke.lua -v1 -l1`
====================
If the environment variable `LUNATIC_TIMING_BASEFN` is defined, EDuke32 will
write out arregate timing results for actors and events in a comma-separated
value format, obtained by suffixing the base name with ```.actors.csv`'' and
```.events.csv`''.
// XXX: it's confusing that there are two kinds of 'environment' mentioned here
Global Environment
------------------
@ -165,7 +172,7 @@ Issuing `require` for some special names listed below has a predefined meaning
that cannot be overridden by the user.
* `CON.DEFS`: returns a table mapping labels ++define++d from CON to their
values, except for `NO`.
values. Values pre-defined by the system are not included.
* `CON.ACTION`: returns a table mapping labels of ++action++s defined from CON
to immutable <<con_action,`con.action`>> objects.
@ -217,8 +224,8 @@ are not allowed to take on the value *nil*.
// TODO: the rest
The ``gv'' variable
[[gv]]
The `gv` variable
~~~~~~~~~~~~~~~~~~~
Some constants, global C variables, and miscellaneous functions and structures
@ -402,22 +409,22 @@ 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].
1. 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.
2. 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. +
3. 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.
4. 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
@ -488,8 +495,8 @@ one could proceed as follows for the sake of example:
* `spr.cstatbits:test(CS.FLIP_BITMASK)`, check whether it is flipped (no)
==========
Engine-side
^^^^^^^^^^^
Engine-side composites
^^^^^^^^^^^^^^^^^^^^^^
The composite variables described in this subsection provide access to
engine-side structures. The first three, `sector`, `wall`, and `sprite`,
@ -512,7 +519,7 @@ be thought of as [`-16` .. `-1`].
_`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
various EDuke32 sector effects, so it is not recommended to use them in
scripting code.
In addition to the members described above, each sector has two sets of members
@ -593,7 +600,8 @@ Provides a mapping of symbolic names to values applicable to
`FLIP_BITMASK`, `ORIENT_BITMASK`, `TRANS_BITMASK`.
[[sector_UPDATE_FLAGS]] `sector.UPDATE_FLAGS`::
Contains a flag `BREADTH` permissible to <<updatesector,`updatesector`>>.
Contains flags permissible to <<updatesector,`updatesector`>> and other sector
updating functions. `BREADTH`, `Z`.
'''
[[wall]]
@ -767,15 +775,55 @@ offset to `spr.z` yields the z coordinate at the bottom of the
sprite. Subtracting from that the height results the z coordinate at its
top. However, the per-tile z offset is not taken into account.
===== `sprite` static functions
`spr:setpos(pos [, newsect])`::
Unconditionally sets the position of `spr` to `pos`, which can be anything
indexable with `x`, `y` and `z`. Thus, in effect a shorthand for
+
----------
spr.x, spr.y, spr.z = pos.x, pos.y, pos.z
----------
+
If `newsect` is passed, additionally calls `spr:changesect(newsect)`. +
Returns `spr`.
`sprite.changesect(i, sectnum)`::
Allows to manually change the sector number of the sprite with index `i` to
`sectnum`.
`spr:changesect(sectnum)`::
An alternative way to call
+<<sprite_changesect,sprite.changesect>>(_index_of_spr_, sectnum)+, where
_`index_of_spr`_ is the sprite index corresponding to `spr`. This method is
provided for convenience, but may be slower than the static function
`changesect`.
`spr:updatesect([flags])`::
An alternative way to call
+<<sprite_updatesect,sprite.updatesect>>(_index_of_spr_, flags)+, where
_`index_of_spr`_ is the sprite index corresponding to `spr`. This method is
provided for convenience, but may be slower than the static function
`updatesect`.
===== `sprite` static functions
`sprite.changestat(i, statnum)`::
Allows to manually change the status number of the sprite with index `i` to
`statnum`.
`statnum`. If `i` is an invalid sprite index or the index of a sprite not in
the game world, or `statnum` is an invalid status number, an error is thrown.
[[sprite_changesect]] `sprite.changesect(i, sectnum)`::
Allows to manually change the sector number of the sprite with index `i` to
`sectnum`. If `i` is an invalid sprite index or the index of a sprite not in
the game world, or `sectnum` is an invalid sector index, an error is thrown.
[[sprite_updatesect]] `sprite.updatesect(i [, flags])`::
Updates the sector number of the sprite with index `i`, in effect setting
`sprite[i]`'s sector number to the result of
+
----------
updatesector(sprite[i].pos, sprite[i].sectnum, flags)
----------
+
If the <<updatesector,`updatesector`>> call returns `-1`, the sprite's sector
number remains unchanged. +
Returns the result of the `updatesector` call.
===== `sprite` overridden operators
@ -799,19 +847,21 @@ while the following denote _bit masks_: `ALIGN_BITMASK`, `TRANS_BITMASK`.
Accessible with the same indices and with the same restrictions as
<<sprite,`sprite`>>.
`angoff`::
The BUILD angle that is added to that of a drawn voxel or model.
//`angoff`::
//The BUILD angle that is added to that of a drawn voxel or model.
// XXX: needs better wording to express this: tspr->ang + spriteext[tspr->owner].angoff
Game-side
^^^^^^^^^
Game-side composites
^^^^^^^^^^^^^^^^^^^^
===== `actor`
The `actor` composite holds various run-time data about a sprite. Like
<<sprite,`sprite`>>, it is accessible with indices from `0` to
`gv.MAXSPRITES-1`, but accesses to actors that do not exist in the game world
have no meaning.
have no meaning. Each element has the following members:
_`u16`_ `movflags`, {nbsp} _`bitfield`_ `movflagsbits`::
The actor's current <<actor_MOVFLAGS,movement flags>>.
@ -941,11 +991,44 @@ Contains symbolic names of values applicable <<gameactor,`gameactor`>>'s
`faceplayersmart`, `fleeenemy`, `jumptoplayer`, `seekplayer`, `furthestdir`,
`dodgebullet`.
'''
===== `player`
Accessible with the index 0 and any nonnegative `pli` index passed to a
<<gameactor,game actor>> or event callback function.
.Arrays with named elements
The structures obtained by indexing `player` contain arrays whose elements may
be referred to either by index of by a particular name. Thus, the array can be
thought to be overlaid with a structure containing as many members as the array
has elements, all having the element's type.
Currently, there are with two kinds of names: weapon names and inventory
names. In the following, they will be marked using a the following notation:
==========
_`i16`_ +ammo_amount[_weapon_]+
means that the structure member `ammo_amount` is an array with named elements,
themselves being of signed 16-bit integer type. The array can be indexed with
valid weapon numbers, or weapon names. In the following (constructed) example,
the first player's current pistol ammo count is set to that of the currently
selected weapon:
----------
local ps = player[0]
ps.ammo_amount.PISTOL = ps.ammo_amount[ps.curr_weapon]
----------
==========
The weapon names are: `KNEE`, `PISTOL`, `SHOTGUN`, `CHAINGUN`, `RPG`,
`HANDBOMB`, `SHRINKER`, `DEVISTATOR`, `TRIPBOMB`, `FREEZE`, `HANDREMOTE`,
`GROW`.
The inventory names are: `STEROIDS`, `SHIELD`, `SCUBA`, `HOLODUKE`, `JETPACK`,
`DUMMY1`, `ACCESS`, `HEATS`, `DUMMY2`, `FIRSTAID`, `BOOTS`.
Each `player` element has the following members:
<<vector_types,_`xmath.ivec3`_>> `vel`::
The vector of the player's current velocity, accounted each time a player's
input is processed. The x and y components are in BUILD x/y units per game tic,
@ -956,8 +1039,11 @@ tic. Processing a player's input and other EDuke32 game code may change `vel`
_`i32`_ `runspeed`::
The factor, scaled by 2^16^, with which the player's current horizontal
velocity is multiplied before calculating its new position. On various
occasions, `runspeed` may additionally be diminished by at most 8192 by the
game.
occasions, the ultimate scaled factor is the difference of `runspeed` and at
most 8192.
_`i8`_ `curr_weapon`::
The index of the player's currently selected weapon.
===== `player` methods
@ -1076,6 +1162,10 @@ For this reason, the optional argument `flags` accepts
`updatesector` to look for matching sectors in a _breadth-first_ search
starting from `sectnum`, and following all nextwall links. With this strategy,
there is *no* fallback to a linear search if no matching sector is found.
+
Passing `sector.UPDATE_FLAGS.Z` to `flags` makes the sector updating behave as
if `updatesectorz` was called. This is mainly useful if `updatesector` is
called via the <<sprite_updatesect,sector updating functions>> of sprites.
`updatesectorz(pos, sectnum)`::
@ -1594,45 +1684,48 @@ values for sprites that have been deleted. Moreover, per-actor variables tend
to be ``topical'', one such variable being potentially only used for a very
specific actor tile. For this reason, per-actor variables are implemented in a
``sparse'' fashion in Lunatic, but provide to the user the illusion of having a
value for every sprite index. They also ``clean'' themselves at unspecified
value for every sprite index. They are also ``cleaned'' at unspecified
intervals.
===== The type `con.actorvar(defaultval)` [_serializable_]
Creates and returns a new per-actor variable with default value `defaultval`
which can be indexed for reading or assignment in the range
[0{nbsp}..{nbsp}`gv.MAXSPRITES-1`]. The same restrictions as with
<<sprite,`sprite`>> etc. apply; values of sprites not in the game world may be
cleared (reset to `defaultval`) at any point.
[0{nbsp}..{nbsp}`gv.MAXSPRITES-1`], but access to it is subject to the same
restrictions as to <<sprite,`sprite`>> and other per-sprite structures.
When a sprite is created using `con.insertsprite()`, its value at the index of
this new sprite is cleared.
When a sprite is created using `con.insertsprite` or `con.spawn`, its value at
the index of this new sprite is cleared (reset to `defaultval`). After a sprite
has been deleted, the value of a per-actor variable is indeterminate -- it may
be cleared by Lunatic at any point.
Per-actor variables may contain values of any permitted type, which currently
are boolean and number. Mixing values of different types is allowed,
i.e. per-actor variables are heterogenous containers.
are boolean and number. Mixing values of different types is allowed: per-actor
variables are heterogenous containers.
Sprite insertion
^^^^^^^^^^^^^^^^
In Lunatic, there are two functions that insert a sprite into the game world,
differing in their amount of ``hard-codedness'' and in how they are used.
In Lunatic, there are two functions that insert a sprite into the game world.
They mainly differ in how they are used, and to which extent they imply
``hard-coded'' behavior.
===== The function `con.insertsprite{tilenum, pos, sectnum [, owner [, statnum]] [key=val...]}`
Inserts a new sprite into the game with the properties given as input
arguments. If the world already contains `gv.MAXSPRITES` sprites, currently the
game is aborted and EDuke32 exits.footnote:[This is subject to change and must
not be relied on.] Otherwise, relevant per-sprite data for the newly inserted
sprite is cleared. No additional ``hard-wired'' C code is run.
arguments. If the world already contains the maximum number of sprites
(<<gv,`gv.MAXSPRITES`>>), currently the game is aborted and EDuke32
exits.footnote:[This is subject to change and must not be relied on.]
Otherwise, relevant per-sprite data for the newly inserted sprite is
cleared. No additional ``hard-wired'' C code is run.
The return value is the index of the inserted sprite.
The function `con.insertsprite` expects a single table ``container'' input
argument, whose values are taken as the actual arguments. The first three,
`tilenum`, `pos` and `sectnum`, are passed positionally. All other input
arguments are passed as key-value pairs, but `owner` and `statnum` may be
passed in both forms (but only one form in one call).
The function `con.insertsprite` is called with a single table whose values are
taken as the actual arguments. The first three, `tilenum`, `pos` and `sectnum`,
are passed positionally. All other input arguments are passed as key-value
pairs, but `owner` and `statnum` may be provided in both forms (but only one
form in one call).
`[1]` (`tilenum`)::
The tile number of the sprite to insert.
@ -1643,7 +1736,7 @@ The position at which to insert the sprite (anything indexable with `x`, `y` and
`[3]` (`sectnum`)::
The index of the sector in which to insert the sprite.
`[4] owner` (default: -1)::
`[4] owner` (default: --1)::
The index of the sprite that is in some sense the ``parent'' of the newly
created one.
@ -1658,7 +1751,9 @@ All optional arguments passed this way except for the repeats default to 0.
===== The function `con.spawn(tilenum, parentspritenum)`
Spawns a new sprite with tile number `tilenum` from a given ``parent'' sprite
with index `parentspritenum`, which must be valid. May run addition
``hard-wired'' code.
with index `parentspritenum`, which must be valid. The sprite is spawned at the
same position as its parent and with its `owner` member set to
`parentspritenum`. Additional ``hard-wired'' code dependent on `tilenum` may be
run afterwards that modifies the sprite.
Returns the index of the spawned sprite on success.