mirror of
https://github.com/ZDoom/raze-gles.git
synced 2025-01-11 18:50:46 +00:00
Lunatic: player method fadecol(), an improved palfrom.
Also, an external 'minitext' with optional shade and pal. args and documentation for ps:padecol(). git-svn-id: https://svn.eduke32.com/eduke32@3893 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
e8c9bf044f
commit
5db04f585e
9 changed files with 234 additions and 21 deletions
|
@ -98,9 +98,15 @@ function bcheck.top_level(funcname)
|
|||
end
|
||||
end
|
||||
|
||||
function bcheck.number(val)
|
||||
if (type(val)~="number") then
|
||||
error("invalid argument: must be a number", 3)
|
||||
function bcheck.number(val, errlev)
|
||||
if (type(val)~="number" or val~=val) then
|
||||
error("invalid argument: must be a non-NaN number", errlev or 3)
|
||||
end
|
||||
end
|
||||
|
||||
function bcheck.type(val, typestr)
|
||||
if (type(val)~=typestr) then
|
||||
error("invalid argument: must be a "..typestr, 3)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -165,6 +165,7 @@ local check_tile_idx = bcheck.tile_idx
|
|||
local check_sprite_idx = bcheck.sprite_idx
|
||||
local check_player_idx = bcheck.player_idx
|
||||
local check_sound_idx = bcheck.sound_idx
|
||||
local check_type = bcheck.type
|
||||
|
||||
-- Will contain [<label>]=number mappings after CON translation.
|
||||
local D = { true }
|
||||
|
@ -793,7 +794,15 @@ function _switch(swtab, testval, aci,pli,dist)
|
|||
end
|
||||
|
||||
|
||||
-- text rendering
|
||||
--== Text rendering ==--
|
||||
|
||||
-- For external use. NOTE: <pal> comes before <shade>.
|
||||
function minitext(x, y, str, pal, shade)
|
||||
check_type(str, "string")
|
||||
ffiC.minitext_(x, y, str, shade or 0, pal or 0, 2+8+16)
|
||||
end
|
||||
|
||||
-- For CON only.
|
||||
function _minitext(x, y, qnum, shade, pal)
|
||||
local cstr = bcheck.quote_idx(qnum)
|
||||
ffiC.minitext_(x, y, cstr, shade, pal, 2+8+16)
|
||||
|
|
|
@ -291,6 +291,7 @@ __attribute__((packed)) struct {
|
|||
|
||||
uint8_t palette;
|
||||
palette_t _pals;
|
||||
int8_t _palsfadespeed, _palsfadenext, _palsfadeprio, _padding2;
|
||||
|
||||
// NOTE: In C, the struct type has no name. We only have it here to define
|
||||
// a metatype later.
|
||||
|
@ -1147,6 +1148,18 @@ local weaponaccess_mt = {
|
|||
}
|
||||
ffi.metatype("weaponaccess_t", weaponaccess_mt)
|
||||
|
||||
|
||||
local function clamp(num, min, max)
|
||||
return num < min and min
|
||||
or num > max and max
|
||||
or num
|
||||
end
|
||||
|
||||
local function clamp0to1(num)
|
||||
check_number(num, 4)
|
||||
return clamp(num, 0, 1)
|
||||
end
|
||||
|
||||
local player_mt = {
|
||||
__index = {
|
||||
-- CON-like addammo/addweapon, but without the non-local control flow
|
||||
|
@ -1188,9 +1201,64 @@ local player_mt = {
|
|||
p.look_ang = n
|
||||
end,
|
||||
|
||||
--- Not fully specified, off-limits to users. Might disappear, change
|
||||
--- signature, etc...
|
||||
-- TODO: need to think about external API: 0-255 based? 0-1 based?
|
||||
-- External, improved 'palfrom'.
|
||||
-- <speed>: possibly fractional speed of tint fading, in pals.f decrements per gametic.
|
||||
-- XXX: exposes internals.
|
||||
-- <prio>: a value from -128 to 127, higher ones trump lower or equal ones
|
||||
fadecol = function(p, fadefrac, r, g, b, speed, prio)
|
||||
-- Validate inargs: clamp f,r,g,b to [0 .. 1] first and multiply by
|
||||
-- 63 for the internal handling.
|
||||
fadefrac = clamp0to1(fadefrac)*63
|
||||
-- NOTE: a fadefrac of now <1 is allowed, e.g. for clearing the tint.
|
||||
r = clamp0to1(r)*63
|
||||
g = clamp0to1(g)*63
|
||||
b = clamp0to1(b)*63
|
||||
|
||||
if (speed ~= nil) then
|
||||
check_number(speed)
|
||||
-- Clamp to sensible values; the speed is stored in an int8_t
|
||||
-- (see below).
|
||||
speed = clamp(speed, 1/128, 127)
|
||||
else
|
||||
speed = 1
|
||||
end
|
||||
|
||||
if (prio ~= nil) then
|
||||
check_number(prio)
|
||||
|
||||
if (not (prio >= -128 and prio < 127)) then
|
||||
error("invalid argument #6 (priority): must be in [-128 .. 127]", 2)
|
||||
end
|
||||
else
|
||||
prio = 0
|
||||
end
|
||||
|
||||
-- Check if a currently active tint has higher priority.
|
||||
if (p._pals.f > 0 and p._palsfadeprio > prio) then
|
||||
return
|
||||
end
|
||||
|
||||
-- The passed tint can be applied now.
|
||||
p:_palfrom(fadefrac, r, g, b)
|
||||
p._palsfadeprio = prio
|
||||
|
||||
-- Calculate .palsfade{speed,next}
|
||||
if (speed >= 1) then
|
||||
-- Will round to the nearest integer ("banker's
|
||||
-- rounding"). NOTE: This is not correct for all numbers, see
|
||||
-- http://blog.frama-c.com/index.php?post/2013/05/02/nearbyintf1
|
||||
p._palsfadespeed = speed + 0.5
|
||||
p._palsfadenext = 0
|
||||
else
|
||||
-- NOTE: Values that round to 0 have are equivalent behavior to
|
||||
-- passing a <speed> of 1.
|
||||
local negspeedrecip = -((1/speed) + 0.5) -- [-128.5 .. 1/127+0.5]
|
||||
p._palsfadespeed = negspeedrecip
|
||||
p._palsfadenext = negspeedrecip
|
||||
end
|
||||
end,
|
||||
|
||||
-- INTERNAL and CON-only.
|
||||
_palfrom = function(p, f, r,g,b)
|
||||
local pals = p._pals
|
||||
pals.f = f
|
||||
|
|
|
@ -138,13 +138,13 @@ 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
|
||||
The loaded module is protected so that write accesses to its table yield
|
||||
errors. Unlike Lua, our `module` does not return *true* when a module is
|
||||
++require++d that has not yet finished loading (that is, the inclusion chain
|
||||
contains a loop). Instead, an error is raised.
|
||||
|
||||
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
|
||||
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`.
|
||||
|
||||
|
||||
|
@ -157,10 +157,10 @@ 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 some
|
||||
``persistent'' state and whose values should be stored in savegames. If such
|
||||
variables are desired, they must initialized between the `module` call in a Lua
|
||||
file and a closing `require("end_gamevars")`. These variables may also be *`local`*.
|
||||
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")`. These variables may also be *`local`*.
|
||||
|
||||
[icon="icons/din_w_collapse.png"]
|
||||
CAUTION: A game variable must contain a non-nil value at any time. Otherwise,
|
||||
|
@ -728,6 +728,39 @@ Contains symbolic names of values applicable to <<gameactor,`gameactor`>>'s
|
|||
|
||||
===== `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`
|
||||
|
|
|
@ -528,6 +528,70 @@ gameevent
|
|||
end
|
||||
}
|
||||
|
||||
local function testbit(num, b)
|
||||
return bit.band(num,b)~=0 and 1 or 0
|
||||
end
|
||||
|
||||
local FADE_SPEED = {
|
||||
[gv.KNEE_WEAPON] = 1/2.5,
|
||||
|
||||
1/128,
|
||||
1/5,
|
||||
1/3,
|
||||
1/2,
|
||||
1, -- pipebomb: ~1 sec
|
||||
2,
|
||||
3,
|
||||
5,
|
||||
127, -- freezer; such a fast fade is not visible, but it clears any
|
||||
-- existing one (if of higher priority)
|
||||
[gv.GROW_WEAPON] = 9.9, -- test banker's rouding -- should be like 10
|
||||
}
|
||||
|
||||
-- Test player[]:fadecol(), a better palfrom.
|
||||
gameevent
|
||||
{
|
||||
"CHANGEWEAPON",
|
||||
|
||||
function (aci, pli)
|
||||
local ps = player[pli]
|
||||
local neww, curw = gv.g_RETURN, ps.curr_weapon
|
||||
|
||||
local r, g, b = testbit(neww, 1), testbit(neww, 2), testbit(neww, 4)
|
||||
local speed = FADE_SPEED[neww] or 1
|
||||
player[pli]:fadecol(0.5, r, g, b, speed, neww)
|
||||
end
|
||||
}
|
||||
|
||||
-- Time the above p:fadecol() test for verification of the <speed> argument.
|
||||
local last_f, last_t = 0, 0
|
||||
local last_secs = nil
|
||||
gameevent
|
||||
{
|
||||
"DISPLAYREST",
|
||||
|
||||
function(aci, pli)
|
||||
local ps = player[pli]
|
||||
-- WARNING: This function uses INTERNAL interfaces.
|
||||
local curf = ps._pals.f
|
||||
if (curf > last_f) then
|
||||
-- Starting a tint
|
||||
last_secs = nil
|
||||
last_f = curf
|
||||
last_t = gv.getticks()
|
||||
elseif (last_t > 0 and curf==0) then
|
||||
-- Fade has ended
|
||||
last_secs = (gv.getticks()-last_t)/1000
|
||||
last_f, last_t = 0, 0
|
||||
end
|
||||
|
||||
if (last_secs ~= nil) then
|
||||
con.minitext(10, 10, string.format("Last fade time: %.03f s (%.03f gametics)",
|
||||
last_secs, last_secs*30))
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
printf("EVENT_INIT = %d", gv.EVENT_INIT) -- tests default defines
|
||||
|
||||
local bittest = require "test.test_bitar"
|
||||
|
|
|
@ -37,8 +37,6 @@ require "end_gamevars"
|
|||
-- refer to locals defined prior to the gamevar section in it.
|
||||
local tag = tag
|
||||
|
||||
local Q = 1200
|
||||
|
||||
gameevent{"JUMP", actor.FLAGS.chain_beg,
|
||||
function(aci, pli)
|
||||
local ps = player[pli]
|
||||
|
@ -85,8 +83,6 @@ gameevent
|
|||
"DISPLAYREST",
|
||||
|
||||
function()
|
||||
con._definequote(Q, string.format("jumped %d times", ournumjumps))
|
||||
-- NOTE: uses INTERNAL interface, don't copy!
|
||||
con._minitext(160, 10, Q, 0,0)
|
||||
con.minitext(160, 10, string.format("jumped %d times", ournumjumps))
|
||||
end
|
||||
}
|
||||
|
|
|
@ -4385,7 +4385,32 @@ void P_ProcessInput(int32_t snum)
|
|||
}
|
||||
|
||||
if (p->pals.f > 0)
|
||||
{
|
||||
#ifndef LUNATIC
|
||||
p->pals.f--;
|
||||
#else
|
||||
if (p->palsfadespeed > 0)
|
||||
{
|
||||
// <palsfadespeed> is the tint fade speed is in
|
||||
// decrements/P_ProcessInput() calls.
|
||||
p->pals.f = max(p->pals.f - p->palsfadespeed, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// <palsfadespeed> is a negated count of how many times we
|
||||
// (P_ProcessInput()) should be called before decrementing the tint
|
||||
// fading by one. <palsfadenext> is the live counter.
|
||||
if (p->palsfadenext < 0)
|
||||
p->palsfadenext++;
|
||||
|
||||
if (p->palsfadenext == 0)
|
||||
{
|
||||
p->palsfadenext = p->palsfadespeed;
|
||||
p->pals.f--;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (p->fta > 0 && --p->fta == 0)
|
||||
{
|
||||
|
|
|
@ -230,6 +230,8 @@ typedef struct {
|
|||
palette_t pals;
|
||||
|
||||
#ifdef LUNATIC
|
||||
int8_t palsfadespeed, palsfadenext, palsfadeprio, padding2_;
|
||||
|
||||
// The player index. Always valid since we have no loose DukePlayer_t's
|
||||
// anywhere (like with spritetype_t): g_player[i].ps->wa.idx == i.
|
||||
struct { int32_t idx; } wa;
|
||||
|
|
|
@ -673,6 +673,14 @@ void P_RandomSpawnPoint(int32_t snum)
|
|||
sprite[p->i].cstat = 1+256;
|
||||
}
|
||||
|
||||
static inline void P_ResetTintFade(DukePlayer_t *ps)
|
||||
{
|
||||
ps->pals.f = 0;
|
||||
#ifdef LUNATIC
|
||||
ps->palsfadeprio = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void P_ResetPlayer(int32_t snum)
|
||||
{
|
||||
vec3_t tmpvect;
|
||||
|
@ -708,7 +716,6 @@ void P_ResetPlayer(int32_t snum)
|
|||
pl->wackedbyactor = -1;
|
||||
pl->inv_amount[GET_SHIELD] = g_startArmorAmount;
|
||||
pl->dead_flag = 0;
|
||||
pl->pals.f = 0;
|
||||
pl->footprintcount = 0;
|
||||
pl->weapreccnt = 0;
|
||||
pl->fta = 0;
|
||||
|
@ -718,6 +725,8 @@ void P_ResetPlayer(int32_t snum)
|
|||
pl->runspeed = g_playerFriction;
|
||||
pl->falling_counter = 0;
|
||||
|
||||
P_ResetTintFade(pl);
|
||||
|
||||
actor[pl->i].extra = -1;
|
||||
actor[pl->i].owner = pl->i;
|
||||
|
||||
|
@ -897,7 +906,6 @@ static void resetprestat(int32_t snum,int32_t g)
|
|||
|
||||
p->hbomb_on = 0;
|
||||
p->cheat_phase = 0;
|
||||
p->pals.f = 0;
|
||||
p->toggle_key_flag = 0;
|
||||
p->secret_rooms = 0;
|
||||
p->max_secret_rooms = 0;
|
||||
|
@ -906,6 +914,8 @@ static void resetprestat(int32_t snum,int32_t g)
|
|||
p->lastrandomspot = 0;
|
||||
p->weapon_pos = 6;
|
||||
|
||||
P_ResetTintFade(p);
|
||||
|
||||
if ((PWEAPON(snum, p->curr_weapon, WorksLike) == PISTOL_WEAPON) &&
|
||||
(PWEAPON(snum, p->curr_weapon, Reload) > PWEAPON(snum, p->curr_weapon, TotalTime)))
|
||||
p->kickback_pic = PWEAPON(snum, p->curr_weapon, TotalTime);
|
||||
|
|
Loading…
Reference in a new issue