mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-16 01:11:44 +00:00
Scripting: Add EVENT_DAMAGEHPLANE and document it in Lunatic doc Appendix B.
Also add test/damagehplane.lua with these demonstrations: - custom breakable ceilings - breakable TROR glass git-svn-id: https://svn.eduke32.com/eduke32@4206 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
f10e1b1a16
commit
0c69779b98
9 changed files with 187 additions and 9 deletions
|
@ -695,6 +695,7 @@ const char *EventNames[MAXEVENTS] =
|
|||
"EVENT_SAVEGAME",
|
||||
"EVENT_PREGAME",
|
||||
"EVENT_CHANGEMENU",
|
||||
"EVENT_DAMAGEHPLANE",
|
||||
#ifdef LUNATIC
|
||||
"EVENT_ANIMATEALLSPRITES",
|
||||
#endif
|
||||
|
|
|
@ -125,8 +125,9 @@ enum GameEvent_t {
|
|||
EVENT_SAVEGAME,
|
||||
EVENT_PREGAME,
|
||||
EVENT_CHANGEMENU,
|
||||
EVENT_DAMAGEHPLANE, // 95
|
||||
#ifdef LUNATIC
|
||||
EVENT_ANIMATEALLSPRITES, // 95
|
||||
EVENT_ANIMATEALLSPRITES,
|
||||
#endif
|
||||
MAXEVENTS
|
||||
};
|
||||
|
|
|
@ -17,7 +17,7 @@ MAXGAMETYPES = 16
|
|||
|
||||
MAXSKILLS = 7
|
||||
|
||||
MAXEVENTS = 95 -- KEEPINSYNC with EVENT_* list
|
||||
MAXEVENTS = 96 -- KEEPINSYNC with EVENT_* list
|
||||
MAXSOUNDS = 4096
|
||||
|
||||
MAXSESSIONVARS = 8 -- KEEPINSYNC lunatic_game.c
|
||||
|
@ -170,7 +170,8 @@ EVENT = {
|
|||
EVENT_SAVEGAME = 92,
|
||||
EVENT_PREGAME = 93,
|
||||
EVENT_CHANGEMENU = 94,
|
||||
-- EVENT_ANIMATEALLSPRITES = 95, -- internal
|
||||
EVENT_DAMAGEHPLANE = 95,
|
||||
-- EVENT_ANIMATEALLSPRITES = 96, -- internal
|
||||
}
|
||||
|
||||
-- NOTE: negated values are not exported to the ffi.C namespace or CON.
|
||||
|
|
|
@ -272,6 +272,8 @@ end
|
|||
function insertsprite(tab_or_tilenum, ...)
|
||||
local tilenum, pos, sectnum -- mandatory
|
||||
-- optional with defaults:
|
||||
-- TODO: swap order of owner and statnum?
|
||||
-- XXX: owner -1 valid???
|
||||
local owner, statnum
|
||||
local shade, xrepeat, yrepeat, ang, xvel, zvel = 0, 48, 48, 0, 0, 0
|
||||
|
||||
|
|
|
@ -2091,7 +2091,7 @@ local function our_gameactor(args)
|
|||
|
||||
-- Register our EVENT_ANIMATEALLSPRITES only now so that it is not
|
||||
-- called if there are no 'animate' definitions.
|
||||
gameevent_internal(95, animate_all_sprites) -- EVENT_ANIMATEALLSPRITES
|
||||
gameevent_internal(96, animate_all_sprites) -- EVENT_ANIMATEALLSPRITES
|
||||
end
|
||||
|
||||
-- All good, set the tile bits in initial run and register the actor!
|
||||
|
|
|
@ -884,7 +884,7 @@ static_members.sector.STAT = conststruct
|
|||
TRANS2 = 128,
|
||||
TRANS1 = 256,
|
||||
BLOCK = 512,
|
||||
HITSCAN = 1024,
|
||||
HITSCAN = 2048,
|
||||
|
||||
FLIP_BITMASK = 16+32,
|
||||
ORIENT_BITMASK = 4+16+32,
|
||||
|
@ -936,6 +936,8 @@ static_members.sprite.CSTAT = conststruct
|
|||
|
||||
ALIGN_BITMASK = 16+32,
|
||||
TRANS_BITMASK = 2+512,
|
||||
|
||||
INVISIBLE = 32768,
|
||||
}
|
||||
|
||||
local bitar = require("bitar")
|
||||
|
@ -944,6 +946,19 @@ local bitar = require("bitar")
|
|||
-- machines. This sucks.
|
||||
static_members.sector.showbitmap = bitar.new(ffiC.MAXSECTORS-1, ffi.cast("int32_t *", ffiC.show2dsector))
|
||||
|
||||
static_members.sector.DAMAGEHPLANE = conststruct
|
||||
{
|
||||
SUPPRESS = -1,
|
||||
DEFAULT = 0,
|
||||
GLASSBREAK = 2^20,
|
||||
}
|
||||
|
||||
function static_members.sector.damagehplane_whatsect(RETURN)
|
||||
local what = (band(RETURN, 65536)~=0) and "ceiling" or "floor"
|
||||
local sectnum = band(RETURN, ffiC.MAXSECTORS-1)
|
||||
return what, sectnum
|
||||
end
|
||||
|
||||
local function iter_allsprites(_, curi)
|
||||
for i=curi+1,ffiC.MAXSPRITES-1 do
|
||||
if (ffiC.sprite[i].statnum ~= ffiC.MAXSTATUS) then
|
||||
|
|
|
@ -942,7 +942,7 @@ sprite by `zofs` units''.
|
|||
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`,
|
||||
`CENTER`, `HITSCAN`, `TRANS2`, `INVISIBLE`,
|
||||
while the following denote _bit masks_: `ALIGN_BITMASK`, `TRANS_BITMASK`.
|
||||
|
||||
===== `spriteext`
|
||||
|
@ -2232,6 +2232,45 @@ cheat give a different ``full'' amount. A negative value is ignored.
|
|||
`CHEATGETSTEROIDS`, `CHEATGETHEAT`, `CHEATGETBOOT`, `CHEATGETSHIELD`,
|
||||
`CHEATGETSCUBA`, `CHEATGETHOLODUKE`, `CHEATGETJETPACK`, `CHEATGETFIRSTAID`.
|
||||
|
||||
[float]
|
||||
`EVENT_DAMAGEHPLANE`
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Triggered when a ceiling or a floor (collectively called ``hplane'') is
|
||||
determined as being damaged. The event receives `RETURN` as a value that can be
|
||||
decoded into two parts by passing it to `sector.damagehplane_whatsect`:
|
||||
|
||||
[source]
|
||||
----------
|
||||
local what, sectnum = sector.damagehplane_whatsect(gv.RETURN)
|
||||
----------
|
||||
Then,
|
||||
|
||||
* `what` is one of the strings `'ceiling'` or `'floor'` and
|
||||
* `sectnum` is the sector whose hplane is considered to be damaged.
|
||||
|
||||
When `EVENT_DAMAGEHPLANE` is left, `RETURN` is examined to determine the
|
||||
further action. It may be one of three values given by `sector.DAMAGEHPLANE`
|
||||
(abbreviated `DHP` in the following):
|
||||
|
||||
* `DHP.SUPPRESS`: the hard-wired code that would subsequently be run is
|
||||
suppressed entirely
|
||||
|
||||
* `DHP.DEFAULT`: The default code for hplane damaging is run. For floors, it
|
||||
does nothing. For ceilings, it checks whether it has a tile number in a
|
||||
hard-coded set of values depicting a breakable light. In that case, the tile
|
||||
number is changed to the ``broken'' version and a ``glass breaking'' effect
|
||||
consisting of playing a sound and spawning glass sprites is started. Also,
|
||||
certain code related to SE3 and SE12 effects is run.
|
||||
|
||||
* `DHP.GLASSBREAK`: The light-breaking effect described above is run
|
||||
unconditionally, but *without* changing the hplane's tile number, which is
|
||||
assumed to have been done by the event.
|
||||
|
||||
If value last assigned to `RETURN` is not one in the above-mentioned set when
|
||||
`EVENT_DAMAGEHPLANE` is left, the behavior is undefined.
|
||||
|
||||
|
||||
[float]
|
||||
TODO
|
||||
~~~~
|
||||
|
|
105
polymer/eduke32/source/lunatic/test/damagehplane.lua
Normal file
105
polymer/eduke32/source/lunatic/test/damagehplane.lua
Normal file
|
@ -0,0 +1,105 @@
|
|||
|
||||
local bit = require("bit")
|
||||
local band = bit.band
|
||||
|
||||
local tostring = tostring
|
||||
|
||||
local gv = gv
|
||||
local actor = actor
|
||||
local sector, wall, sprite = sector, wall, sprite
|
||||
|
||||
local printf = printf
|
||||
local sectorsofbunch = sectorsofbunch
|
||||
|
||||
local con = require("con")
|
||||
|
||||
local D = require("CON.DEFS")
|
||||
|
||||
----------
|
||||
|
||||
local TROR_GLASSBREAKER = 2959 -- red 'T'
|
||||
-- Actor controlling the timing of a TROR hplane breaking.
|
||||
gameactor
|
||||
{
|
||||
TROR_GLASSBREAKER,
|
||||
|
||||
function(aci, pli, dist)
|
||||
local spr = sprite[aci]
|
||||
if (not (spr.lotag == 712 and spr.hitag == 119)) then -- check BREAKER_MAGIC
|
||||
sprite.changestat(aci, actor.STAT.DEFAULT)
|
||||
return
|
||||
end
|
||||
|
||||
local cnt = actor[aci]:get_count()
|
||||
local finish = (cnt >= 6)
|
||||
|
||||
if (cnt == 0) then
|
||||
-- NOTE: INTERNAL interface, DON'T USE!
|
||||
con._sound(aci, D.GLASS_BREAKING)
|
||||
end
|
||||
|
||||
local bunchnum = spr.extra
|
||||
for sectnum, what in sectorsofbunch(bunchnum, gv.BOTH_CF) do
|
||||
local cf = sector[sectnum][what]
|
||||
|
||||
-- TODO: provide cf:set_picnum()
|
||||
if (what=="ceiling") then
|
||||
sector[sectnum]:set_ceilingpicnum(D.GLASS2 + cnt)
|
||||
else
|
||||
sector[sectnum]:set_floorpicnum(D.GLASS2 + cnt)
|
||||
end
|
||||
|
||||
cf.statbits:clear(sector.STAT.BLOCK + sector.STAT.HITSCAN)
|
||||
if (finish) then
|
||||
cf.statbits:clear(sector.STAT.TRANS_BITMASK)
|
||||
end
|
||||
end
|
||||
|
||||
if (finish) then
|
||||
con.killit()
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
|
||||
local DHP = sector.DAMAGEHPLANE
|
||||
|
||||
gameevent
|
||||
{
|
||||
gv.EVENT_DAMAGEHPLANE,
|
||||
|
||||
function(aci, pli, dist)
|
||||
local what, sectnum = sector.damagehplane_whatsect(gv.RETURN)
|
||||
local sec = sector[sectnum]
|
||||
|
||||
-- Part I: make various screens breakable when it's a ceiling picnum.
|
||||
if (what == "ceiling") then
|
||||
-- hit ceiling
|
||||
if (sec.ceilingpicnum >= 263 and sec.ceilingpicnum <= 275) then
|
||||
sec:set_ceilingpicnum(D.W_SCREENBREAK + gv.krand()%3)
|
||||
gv.RETURN = DHP.GLASSBREAK
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- Part II: breakable TROR hplanes
|
||||
local cf = sec[what]
|
||||
-- printf("damage %s of sector %d (pic %d, bunch %d, hittable: %s)", what, sectnum,
|
||||
-- cf.picnum, cf.bunch, tostring(cf.statbits:test(sector.STAT.HITSCAN)))
|
||||
|
||||
if (cf.bunch >= 0 and (cf.picnum==198 or cf.picnum==D.GLASS2) and
|
||||
cf.statbits:test(sector.STAT.HITSCAN)) then
|
||||
local bi = con.insertsprite(TROR_GLASSBREAKER, wall[sec.wallptr], sectnum, aci, actor.STAT.ACTOR)
|
||||
local breaker = sprite[bi]
|
||||
|
||||
breaker.cstat = sprite.CSTAT.INVISIBLE
|
||||
breaker.lotag, breaker.hitag = 712, 119 -- BREAKER_MAGIC
|
||||
breaker.extra = cf.bunch
|
||||
|
||||
gv.RETURN = DHP.SUPPRESS
|
||||
return
|
||||
end
|
||||
|
||||
gv.RETURN = DHP.DEFAULT
|
||||
end
|
||||
}
|
|
@ -1874,13 +1874,27 @@ void A_DamageWall(int32_t spr,int32_t dawallnum,const vec3_t *pos,int32_t atwith
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE: return value never examined in any of the callers.
|
||||
int32_t Sect_DamageCeilingOrFloor(int32_t floorp, int32_t sn)
|
||||
{
|
||||
int32_t i, j;
|
||||
|
||||
const int32_t RETURN_in = floorp ? 131072+sn : 65536+sn;
|
||||
int32_t ret = VM_OnEvent(EVENT_DAMAGEHPLANE, g_player[screenpeek].ps->i, screenpeek, -1, RETURN_in);
|
||||
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
if (floorp)
|
||||
return 0;
|
||||
|
||||
if (ret == (1<<20))
|
||||
{
|
||||
// Execute the hard-coded stuff without changing picnum (expected to
|
||||
// have been done by the event).
|
||||
goto GLASSBREAK_CODE;
|
||||
}
|
||||
|
||||
switch (DYNAMICTILEMAP(sector[sn].ceilingpicnum))
|
||||
{
|
||||
case WALLLIGHT1__STATIC:
|
||||
|
@ -1890,9 +1904,6 @@ int32_t Sect_DamageCeilingOrFloor(int32_t floorp, int32_t sn)
|
|||
case TECHLIGHT2__STATIC:
|
||||
case TECHLIGHT4__STATIC:
|
||||
|
||||
A_SpawnCeilingGlass(g_player[myconnectindex].ps->i,sn,10);
|
||||
A_PlaySound(GLASS_BREAKING,g_player[screenpeek].ps->i);
|
||||
|
||||
if (sector[sn].ceilingpicnum == WALLLIGHT1)
|
||||
sector[sn].ceilingpicnum = WALLLIGHTBUST1;
|
||||
|
||||
|
@ -1911,6 +1922,9 @@ int32_t Sect_DamageCeilingOrFloor(int32_t floorp, int32_t sn)
|
|||
if (sector[sn].ceilingpicnum == TECHLIGHT4)
|
||||
sector[sn].ceilingpicnum = TECHLIGHTBUST4;
|
||||
|
||||
GLASSBREAK_CODE:
|
||||
A_SpawnCeilingGlass(g_player[myconnectindex].ps->i,sn,10);
|
||||
A_PlaySound(GLASS_BREAKING,g_player[screenpeek].ps->i);
|
||||
|
||||
if (sector[sn].hitag == 0)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue