Lunatic: write more documentation, handle randomangle movflag in a:set_move().

git-svn-id: https://svn.eduke32.com/eduke32@3887 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-06-15 12:52:06 +00:00
parent 40b117a23c
commit e2859cd133
4 changed files with 183 additions and 26 deletions

View file

@ -445,7 +445,7 @@ typedef struct {
vec3_t pos; vec3_t pos;
int32_t dist, clock; int32_t dist, clock;
int16_t ang, horiz; int16_t ang, horiz;
int16_t sect; int16_t sect; // NOTE: protected in camera_mt's __newindex
} camera_t; } camera_t;
enum enum
@ -819,10 +819,12 @@ do
end end
actor_static_members.STAT = defs_c.conststruct(our_STAT) actor_static_members.STAT = defs_c.conststruct(our_STAT)
-- TODO: actor_static_members.movflags? They can be obtained with
-- require('CON.DEFS') now...
end end
-- Delete sprite with index <i>. -- Delete sprite with index <i>.
-- TODO: make this (also?) sprite.delete() even though it's game-side?
function actor_static_members.delete(i) function actor_static_members.delete(i)
check_sprite_idx(i) check_sprite_idx(i)
@ -867,12 +869,13 @@ local g_tile = setmtonce({}, defs_c.GenStructMetatable("g_tile", "MAXTILES", til
-- Among other things, declares struct action and struct move, and their -- Among other things, declares struct action and struct move, and their
-- ID-wrapped types con_action_t and con_move_t -- ID-wrapped types con_action_t and con_move_t
local con = require("control") local con = require("control")
local isenemytile = con.isenemytile
local MV, AC, AI = con.MV, con.AC, con.AI local MV, AC, AI = con.MV, con.AC, con.AI
-- Add game-side metamethods to "spritetype" and register it with "metatype" -- Add game-side metamethods to "spritetype" and register it with "metatype"
local spr_mt_index_add = { local spr_mt_index_add = {
isenemy = function(s) isenemy = function(s)
return con.isenemytile(s.picnum) return isenemytile(s.picnum)
end, end,
} }
defs_c.finish_spritetype(spr_mt_index_add) defs_c.finish_spritetype(spr_mt_index_add)
@ -975,10 +978,14 @@ local actor_mt = {
end end
a.t_data[0] = 0 a.t_data[0] = 0
local i = get_actor_idx(a) local spr = ffiC.sprite[get_actor_idx(a)]
ffiC.sprite[i].hitag = movflags or 0 spr.hitag = movflags or 0
-- TODO: random angle moveflag if (not spr:isenemy() or spr.extra > 0) then
if (bit.band(spr.hitag, 8)) then -- random_angle
spr.ang = bit.band(ffiC.krand(), 2047)
end
end
end, end,
has_move = function(a, mov) has_move = function(a, mov)
@ -1304,7 +1311,7 @@ function gv_access._set_guniqhudid(id)
ffiC.guniqhudid = id ffiC.guniqhudid = id
end end
-- TODO: make return 1-based index -- TODO: make return 1-based index?
function gv_access.currentEpisode() function gv_access.currentEpisode()
return ffiC.ud.volume_number return ffiC.ud.volume_number
end end
@ -1515,7 +1522,7 @@ local function our_require(modname, ...)
table.insert(modname_stack, modname) table.insert(modname_stack, modname)
-- Run the module code! -- Run the module code!
modfunc(modname, ...) -- TODO: call protected and report errors here later modfunc(modname, ...) -- TODO: call protected and report errors here later?
table.remove(modname_stack) table.remove(modname_stack)

View file

@ -765,6 +765,13 @@ static_members.sector.STAT = conststruct
TRANS_BITMASK = 128+256, TRANS_BITMASK = 128+256,
} }
static_members.sector.NEARTAG_FLAGS = conststruct
{
LOTAG = 1,
HITAG = 2,
NOSPRITES = 4,
}
static_members.wall.CSTAT = conststruct static_members.wall.CSTAT = conststruct
{ {
BLOCK = 1, BLOCK = 1,
@ -1036,7 +1043,7 @@ const struct {
]] ]]
local function newar() return ffi.new("int16_t [1]") end local function newar() return ffi.new("int16_t [1]") end
-- TODO: make tagsearch something more convenient -- NOTE: <tagsearch> flags are in sector.NEARTAG_FLAGS
function neartag(pos, sectnum, ang, range, tagsearch) function neartag(pos, sectnum, ang, range, tagsearch)
check_sector_idx(sectnum) check_sector_idx(sectnum)
local a, b, c, d = newar(), newar(), newar(), ffi.new("int32_t [1]") local a, b, c, d = newar(), newar(), newar(), ffi.new("int32_t [1]")

View file

@ -93,7 +93,9 @@ line number.
*`print(...)`*:: *`print(...)`*::
The messages are printed to the OSD and the log. Color codes available in The messages are printed to the OSD and the log. Color codes available in
EDuke32 (e.g. `^10` for dark red) are interpreted. 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, ...)`*:: *`printf(fmt, ...)`*::
Calls `print` with the result of `string.format(fmt, ...)`. Calls `print` with the result of `string.format(fmt, ...)`.
@ -243,9 +245,13 @@ Contains the following members, which are set from C before entering
`lookhoriz`, `shade`. `lookhoriz`, `shade`.
// TODO: describe // TODO: describe
// TODO: g_logoFlags, g_RETURN? `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: structures such as .cam // TODO: g_logoFlags, g_RETURN?
Functions Functions
^^^^^^^^^ ^^^^^^^^^
@ -634,11 +640,9 @@ units per texel.
`sectnum` (read-only):: `sectnum` (read-only)::
The index of the sector that this sprite is currently contained in. The index of the sector that this sprite is currently contained in.
`statnum` (read-only):: [[sprite_statnum]] `statnum` (read-only)::
The current _status number_ of this sprite. Applicable values are contained in The current _status number_ of this sprite. Applicable values are contained in
`actor.STAT`. <<actor_STAT,`actor.STAT`>>.
// <<gv_STAT,the `gv` object>>.
`owner` (read-only):: `owner` (read-only)::
The index of the sprite from which this sprite was spawned. If this sprite is The index of the sprite from which this sprite was spawned. If this sprite is
@ -665,6 +669,16 @@ claiming them for oneself.
`spr:set_picnum(tilenum)`:: `spr:set_picnum(tilenum)`::
Set the tile number of the sprite. 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` overridden operators
`spr^zofs`:: `spr^zofs`::
@ -688,14 +702,41 @@ while the following denote _bit masks_: `ALIGN_BITMASK`, `TRANS_BITMASK`.
Game-side Game-side
^^^^^^^^^ ^^^^^^^^^
`actor`::
`player`:: ===== `actor`
`projectile`:: ===== `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`
===== `projectile`
===== `g_tile`
===== `g_tile` static data
`g_tile.sizx`, `g_tile.sizy`::
Arrays indexable with tile numbers [`0` .. `gv.MAXTILES-1`] that hold the
horizontal and vertical texel sizes of each tile.
`g_tile`::
TODO
Lunatic functions Lunatic functions
~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~
@ -713,13 +754,113 @@ updatesectorbreadth
updatesectorz updatesectorz
wallsofsect wallsofsect
Game-side Customizing the game
^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^
`gameactor`::
`gameevent`:: 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 between actor `aci` and player `pli`
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 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 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. However, it is not
necessary for an event to be already defined when chaining is requested. In
that case, it is simply registered initially.
The `flags` controlling chaining behavior are provided in `actor.FLAGS` as well
(abbreviated `AF`):
* `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]] [[ext_api]]
Extended API (Lunatic modules) Extended API (Lunatic modules)

View file

@ -242,7 +242,9 @@ gameevent
end end
ps.weapon[gv.PISTOL_WEAPON].firesound = D.LIGHTNING_SLAP ps.weapon[gv.PISTOL_WEAPON].firesound = D.LIGHTNING_SLAP
-- XXX: provide either named constants or methods? -- Set pipebomb and tripbomb to timed mode.
-- XXX: Provide either named constants or methods?
-- XXX: These are probably reset to default on new game.
ps.pipebombControl = 2 ps.pipebombControl = 2
ps.tripbombControl = 2 ps.tripbombControl = 2