Lunatic: projectiles...

git-svn-id: https://svn.eduke32.com/eduke32@3463 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2013-02-07 21:01:03 +00:00
parent 9bf6115d1f
commit b92edcc798
8 changed files with 213 additions and 96 deletions

View file

@ -2193,6 +2193,73 @@ void C_DefineLevelName(int32_t vol, int32_t lev, const char *fn,
}
#endif
// NOTE: external linkage for Lunatic
void C_DefineProjectile(int32_t j, int32_t what, int32_t val)
{
switch (what)
{
case PROJ_WORKSLIKE:
g_tile[j].defproj.workslike = ProjectileData[j].workslike = val; break;
case PROJ_SPAWNS:
g_tile[j].defproj.spawns = ProjectileData[j].spawns = val; break;
case PROJ_SXREPEAT:
g_tile[j].defproj.sxrepeat = ProjectileData[j].sxrepeat = val; break;
case PROJ_SYREPEAT:
g_tile[j].defproj.syrepeat = ProjectileData[j].syrepeat = val; break;
case PROJ_SOUND:
g_tile[j].defproj.sound = ProjectileData[j].sound = val; break;
case PROJ_ISOUND:
g_tile[j].defproj.isound = ProjectileData[j].isound = val; break;
case PROJ_VEL:
g_tile[j].defproj.vel = ProjectileData[j].vel = val; break;
case PROJ_EXTRA:
g_tile[j].defproj.extra = ProjectileData[j].extra = val; break;
case PROJ_DECAL:
g_tile[j].defproj.decal = ProjectileData[j].decal = val; break;
case PROJ_TRAIL:
g_tile[j].defproj.trail = ProjectileData[j].trail = val; break;
case PROJ_TXREPEAT:
g_tile[j].defproj.txrepeat = ProjectileData[j].txrepeat = val; break;
case PROJ_TYREPEAT:
g_tile[j].defproj.tyrepeat = ProjectileData[j].tyrepeat = val; break;
case PROJ_TOFFSET:
g_tile[j].defproj.toffset = ProjectileData[j].toffset = val; break;
case PROJ_TNUM:
g_tile[j].defproj.tnum = ProjectileData[j].tnum = val; break;
case PROJ_DROP:
g_tile[j].defproj.drop = ProjectileData[j].drop = val; break;
case PROJ_CSTAT:
g_tile[j].defproj.cstat = ProjectileData[j].cstat = val; break;
case PROJ_CLIPDIST:
g_tile[j].defproj.clipdist = ProjectileData[j].clipdist = val; break;
case PROJ_SHADE:
g_tile[j].defproj.shade = ProjectileData[j].shade = val; break;
case PROJ_XREPEAT:
g_tile[j].defproj.xrepeat = ProjectileData[j].xrepeat = val; break;
case PROJ_YREPEAT:
g_tile[j].defproj.yrepeat = ProjectileData[j].yrepeat = val; break;
case PROJ_PAL:
g_tile[j].defproj.pal = ProjectileData[j].pal = val; break;
case PROJ_EXTRA_RAND:
g_tile[j].defproj.extra_rand = ProjectileData[j].extra_rand = val; break;
case PROJ_HITRADIUS:
g_tile[j].defproj.hitradius = ProjectileData[j].hitradius = val; break;
case PROJ_MOVECNT:
g_tile[j].defproj.movecnt = ProjectileData[j].movecnt = val; break;
case PROJ_OFFSET:
g_tile[j].defproj.offset = ProjectileData[j].offset = val; break;
case PROJ_BOUNCES:
g_tile[j].defproj.bounces = ProjectileData[j].bounces = val; break;
case PROJ_BSOUND:
g_tile[j].defproj.bsound = ProjectileData[j].bsound = val; break;
case PROJ_RANGE:
g_tile[j].defproj.range = ProjectileData[j].range = val; break;
default: break;
}
g_tile[j].flags |= SPRITE_PROJECTILE;
}
int32_t C_AllocQuote(int32_t qnum)
{
if (ScriptQuotes[qnum] == NULL)
@ -4298,68 +4365,7 @@ static int32_t C_ParseCommand(int32_t loop)
continue;
}
switch (y)
{
case PROJ_WORKSLIKE:
g_tile[j].defproj.workslike = ProjectileData[j].workslike = z; break;
case PROJ_SPAWNS:
g_tile[j].defproj.spawns = ProjectileData[j].spawns = z; break;
case PROJ_SXREPEAT:
g_tile[j].defproj.sxrepeat = ProjectileData[j].sxrepeat = z; break;
case PROJ_SYREPEAT:
g_tile[j].defproj.syrepeat = ProjectileData[j].syrepeat = z; break;
case PROJ_SOUND:
g_tile[j].defproj.sound = ProjectileData[j].sound = z; break;
case PROJ_ISOUND:
g_tile[j].defproj.isound = ProjectileData[j].isound = z; break;
case PROJ_VEL:
g_tile[j].defproj.vel = ProjectileData[j].vel = z; break;
case PROJ_EXTRA:
g_tile[j].defproj.extra = ProjectileData[j].extra = z; break;
case PROJ_DECAL:
g_tile[j].defproj.decal = ProjectileData[j].decal = z; break;
case PROJ_TRAIL:
g_tile[j].defproj.trail = ProjectileData[j].trail = z; break;
case PROJ_TXREPEAT:
g_tile[j].defproj.txrepeat = ProjectileData[j].txrepeat = z; break;
case PROJ_TYREPEAT:
g_tile[j].defproj.tyrepeat = ProjectileData[j].tyrepeat = z; break;
case PROJ_TOFFSET:
g_tile[j].defproj.toffset = ProjectileData[j].toffset = z; break;
case PROJ_TNUM:
g_tile[j].defproj.tnum = ProjectileData[j].tnum = z; break;
case PROJ_DROP:
g_tile[j].defproj.drop = ProjectileData[j].drop = z; break;
case PROJ_CSTAT:
g_tile[j].defproj.cstat = ProjectileData[j].cstat = z; break;
case PROJ_CLIPDIST:
g_tile[j].defproj.clipdist = ProjectileData[j].clipdist = z; break;
case PROJ_SHADE:
g_tile[j].defproj.shade = ProjectileData[j].shade = z; break;
case PROJ_XREPEAT:
g_tile[j].defproj.xrepeat = ProjectileData[j].xrepeat = z; break;
case PROJ_YREPEAT:
g_tile[j].defproj.yrepeat = ProjectileData[j].yrepeat = z; break;
case PROJ_PAL:
g_tile[j].defproj.pal = ProjectileData[j].pal = z; break;
case PROJ_EXTRA_RAND:
g_tile[j].defproj.extra_rand = ProjectileData[j].extra_rand = z; break;
case PROJ_HITRADIUS:
g_tile[j].defproj.hitradius = ProjectileData[j].hitradius = z; break;
case PROJ_MOVECNT:
g_tile[j].defproj.movecnt = ProjectileData[j].movecnt = z; break;
case PROJ_OFFSET:
g_tile[j].defproj.offset = ProjectileData[j].offset = z; break;
case PROJ_BOUNCES:
g_tile[j].defproj.bounces = ProjectileData[j].bounces = z; break;
case PROJ_BSOUND:
g_tile[j].defproj.bsound = ProjectileData[j].bsound = z; break;
case PROJ_RANGE:
g_tile[j].defproj.range = ProjectileData[j].range = z; break;
default: break;
}
g_tile[j].flags |= SPRITE_PROJECTILE;
C_DefineProjectile(j, y, z);
continue;
}

View file

@ -533,6 +533,7 @@ enum InputLabel_t
INPUT_END
};
#endif
// KEEPINSYNC lunatic/con_lang.lua
enum ProjectileLabel_t
{
@ -567,6 +568,7 @@ enum ProjectileLabel_t
PROJ_FLASH_COLOR,
PROJ_END
};
#if !defined LUNATIC
enum ScriptKeywords_t
{

View file

@ -55,7 +55,7 @@ PROJ = {
PROJ_PAL = 20,
PROJ_EXTRA_RAND = 21,
PROJ_HITRADIUS = 22,
PROJ_VEL_MULT = 23,
PROJ_VEL_MULT = 23, -- NAME (PROJ_MOVECNT)
PROJ_OFFSET = 24,
PROJ_BOUNCES = 25,
PROJ_BSOUND = 26,
@ -63,6 +63,39 @@ PROJ = {
PROJ_FLASH_COLOR = 28,
}
-- PROJ_* define -> projectile_t member name
PROJ_MEMBNAME = {
[PROJ.PROJ_WORKSLIKE] = "workslike",
[PROJ.PROJ_SPAWNS] = "spawns",
[PROJ.PROJ_SXREPEAT] = "sxrepeat",
[PROJ.PROJ_SYREPEAT] = "syrepeat",
[PROJ.PROJ_SOUND] = "sound",
[PROJ.PROJ_ISOUND] = "isound",
[PROJ.PROJ_VEL] = "vel",
[PROJ.PROJ_EXTRA] = "extra",
[PROJ.PROJ_DECAL] = "decal",
[PROJ.PROJ_TRAIL] = "trail",
[PROJ.PROJ_TXREPEAT] = "txrepeat",
[PROJ.PROJ_TYREPEAT] = "tyrepeat",
[PROJ.PROJ_TOFFSET] = "toffset",
[PROJ.PROJ_TNUM] = "tnum",
[PROJ.PROJ_DROP] = "drop",
[PROJ.PROJ_CSTAT] = "cstat",
[PROJ.PROJ_CLIPDIST] = "clipdist",
[PROJ.PROJ_SHADE] = "shade",
[PROJ.PROJ_XREPEAT] = "xrepeat",
[PROJ.PROJ_YREPEAT] = "yrepeat",
[PROJ.PROJ_PAL] = "pal",
[PROJ.PROJ_EXTRA_RAND] = "extra_rand",
[PROJ.PROJ_HITRADIUS] = "hitradius",
[PROJ.PROJ_VEL_MULT] = "movecnt", -- NAME
[PROJ.PROJ_OFFSET] = "offset",
[PROJ.PROJ_BOUNCES] = "bounces",
[PROJ.PROJ_BSOUND] = "bsound",
[PROJ.PROJ_RANGE] = "range",
[PROJ.PROJ_FLASH_COLOR] = "flashcolor", -- NAME
}
-- TODO: EVENT_INIT currently can't run since we init Lunatic state only afterwards
EVENT = {
EVENT_INIT = 0,
@ -698,6 +731,40 @@ StructAccessCode =
player = PlayerLabels,
}
local PROJ = function(memb) return "projectile[%s]"..memb end
local ProjectileLabels = {
workslike = PROJ"workslike",
cstat = PROJ"cstat",
hitradius = PROJ"hitradius",
range = PROJ"range",
flashcolor = PROJ"flashcolor",
spawns = { PROJ"spawns" },
sound = PROJ"sound",
isound = PROJ"isound",
vel = PROJ"vel",
decal = { PROJ"decal" },
trail = { PROJ"trail" },
tnum = PROJ"tnum",
drop = PROJ"drop",
offset = PROJ"offset",
bounces = PROJ"bounces",
bsound = PROJ"bsound",
toffset = PROJ"toffset",
extra = PROJ"extra",
extra_rand = PROJ"extra_rand",
sxrepeat = PROJ"sxrepeat",
syrepeat = PROJ"syrepeat",
txrepeat = PROJ"txrepeat",
tyrepeat = PROJ"tyrepeat",
shade = PROJ"shade",
xrepeat = PROJ"xrepeat",
yrepeat = PROJ"yrepeat",
pal = PROJ"pal",
velmult = PROJ"movecnt", -- NAME
clipdist = PROJ"clipdist",
}
-- These structs cannot be accessed by inline array exprs in CON:
StructAccessCode2 =
{

View file

@ -102,7 +102,6 @@ enum {
]]
ffi.cdef[[
#pragma pack(push,1)
struct action {
int16_t startframe, numframes;
int16_t viewtype, incval, delay;
@ -112,8 +111,10 @@ struct move {
int16_t hvel, vvel;
};
#pragma pack(push,1)
typedef struct { int32_t id; struct move mv; } con_move_t;
typedef struct { int32_t id; struct action ac; } con_action_t;
#pragma pack(pop)
typedef struct {
int32_t id;
@ -121,7 +122,6 @@ typedef struct {
con_move_t mov;
int32_t movflags;
} con_ai_t;
#pragma pack(pop)
]]
-- Struct template for actor_t. It already has 'const' fields (TODO: might need
@ -300,7 +300,6 @@ typedef struct {
int8_t extbits, filler; // 2b
} input_t;
#pragma pack(push, 1)
typedef
]].. mangle_arrays(ACTOR_STRUCT) ..[[
actor_t;
@ -309,7 +308,7 @@ typedef
]].. mangle_arrays(DUKEPLAYER_STRUCT) ..[[
DukePlayer_t;
typedef struct {
typedef __attribute__((packed)) struct {
DukePlayer_t *ps;
input_t *sync;
@ -322,7 +321,6 @@ typedef struct {
char user_name[32];
uint32_t revision;
} playerdata_t;
#pragma pack(pop)
typedef struct {
int32_t cur, count;
@ -332,18 +330,20 @@ typedef struct {
} hudweapon_t;
typedef struct {
int32_t workslike, cstat; // 8b
int32_t hitradius, range, flashcolor; // 12b
int16_t spawns, sound, isound, vel; // 8b
int16_t decal, trail, tnum, drop; // 8b
int16_t offset, bounces, bsound; // 6b
int16_t toffset; // 2b
int16_t extra, extra_rand; // 4b
int8_t sxrepeat, syrepeat, txrepeat, tyrepeat; // 4b
int8_t shade, xrepeat, yrepeat, pal; // 4b
int8_t movecnt; // 1b
uint8_t clipdist; // 1b
int8_t filler[6]; // 6b
int32_t workslike, cstat;
int32_t hitradius, range, flashcolor;
const int16_t spawns;
int16_t sound, isound, vel;
const int16_t decal, trail;
int16_t tnum, drop;
int16_t offset, bounces, bsound;
int16_t toffset;
int16_t extra, extra_rand;
int8_t sxrepeat, syrepeat, txrepeat, tyrepeat;
int8_t shade, xrepeat, yrepeat, pal;
int8_t movecnt;
uint8_t clipdist;
int8_t filler[6];
} projectile_t;
typedef struct {
@ -372,7 +372,6 @@ enum
NUMGAMEFUNCTIONS = 56,
};
// NOTE: not packed!
typedef struct {
int32_t const_visibility,uw_framerate;
int32_t camera_time,folfvel,folavel,folx,foly,fola;
@ -488,6 +487,8 @@ user_defs ud;
playerdata_t g_player[MAXPLAYERS];
weapondata_t g_playerWeapon[MAXPLAYERS][MAX_WEAPONS];
tiledata_t g_tile[MAXTILES];
projectile_t ProjectileData[MAXTILES];
projectile_t SpriteProjectile[MAXSPRITES];
char *ScriptQuotes[];
@ -543,6 +544,7 @@ void C_DefineSkillName(int32_t skill, const char *name);
void C_DefineLevelName(int32_t vol, int32_t lev, const char *fn,
int32_t partime, int32_t designertime,
const char *levelname);
void C_DefineProjectile(int32_t j, int32_t what, int32_t val);
]]
@ -586,6 +588,8 @@ player = setmtonce({}, tmpmt)
-- needed by "control"
actor = defs_c.creategtab(ffiC.actor, ffiC.MAXSPRITES, "actor[]")
local projectile = defs_c.creategtab(ffiC.ProjectileData, ffiC.MAXTILES, "projectile[]")
--== Custom operations for BUILD data structures ==--
-- Among other things, declares struct action and struct move, and their
-- ID-wrapped types con_action_t and con_move_t
@ -780,17 +784,17 @@ ffi.metatype("actor_t", actor_mt)
--- PER-PLAYER WEAPON SETTINGS
local weapondata_mt = {
__newindex = function(wd, member, val)
if (string.match(member, "sound")) then
-- TODO: set to 0 if oob? (e.g. CrackDown)
check_sound_idx(val)
elseif (member=="workslike") then
check_weapon_idx(val)
elseif (member=="shoots" or member=="spawn") then
-- TODO: set to 0 if oob? (e.g. AMC TC)
check_tile_idx(val)
end
if (string.match(member, "sound")) then
-- TODO: set to 0 if oob? (e.g. CrackDown)
check_sound_idx(val)
elseif (member=="workslike") then
check_weapon_idx(val)
elseif (member=="shoots" or member=="spawn") then
-- TODO: set to 0 if oob? (e.g. AMC TC)
check_tile_idx(val)
end
wd[member] = val
wd[member] = val
end,
}
ffi.metatype("weapondata_t", weapondata_mt)
@ -1254,8 +1258,10 @@ end
--- non-default data and functions
G_.gameevent = our_gameevent
G_.gameactor = our_gameactor
G_.player = player -- from above
G_.actor = actor -- from above
-- These come from above:
G_.player = player
G_.actor = actor
G_.projectile = projectile
---=== Lunatic interpreter setup ===---

View file

@ -82,6 +82,7 @@ C_DefineQuote;
C_DefineVolumeName;
C_DefineSkillName;
C_DefineLevelName;
C_DefineProjectile;
actor;
g_camera;
@ -89,6 +90,8 @@ ud;
g_player;
g_playerWeapon;
g_tile;
ProjectileData;
SpriteProjectile;
ScriptQuotes;

View file

@ -743,6 +743,18 @@ function Cmd.definequote(qnum, quotestr)
g_data.quote[qnum] = quotestr
end
function Cmd.defineprojectile(tilenum, what, val)
if (not (tilenum >= 0 and tilenum < (ffiC and ffiC.MAXTILES or 30720))) then
errprintf("invalid tile number %d", tilenum)
return
end
if (ffi) then
-- TODO: potentially bound-check some members?
ffiC.C_DefineProjectile(tilenum, what, val)
end
end
function Cmd.gamestartup(...)
local args = {...}
@ -1026,7 +1038,7 @@ local Couter = {
definevolumename = sp1 * tok.define * newline_term_string / Cmd.definevolumename,
definequote = sp1 * tok.define * newline_term_string / Cmd.definequote,
defineprojectile = cmd(D,D,D),
defineprojectile = cmd(D,D,D) / Cmd.defineprojectile,
definesound = sp1 * tok.define * sp1 * maybe_quoted_filename * n_defines(5) / Cmd.definesound,
-- NOTE: gamevar.ogg and the like is OK, too
@ -1180,6 +1192,7 @@ local Access =
player = function(...) return StructAccess("player", ...) end,
tspr = function(...) return StructAccess("tspr", ...) end,
projectile = function(...) return StructAccess("projectile", ...) end,
}
local function GetStructCmd(accessfunc)
@ -1278,7 +1291,7 @@ local Cinner = {
getplayer = GetStructCmd(Access.player),
getinput = getstructcmd / handle.NYI,
getprojectile = getstructcmd / handle.NYI,
getprojectile = GetStructCmd(Access.projectile),
getthisprojectile = getstructcmd / handle.NYI,
gettspr = GetStructCmd(Access.tspr),
-- NOTE: {get,set}userdef is the only struct that can be accessed without
@ -1300,7 +1313,7 @@ local Cinner = {
setplayer = SetStructCmd(Access.player),
setinput = setstructcmd / handle.NYI,
setprojectile = setstructcmd / handle.NYI,
setprojectile = SetStructCmd(Access.projectile),
setthisprojectile = setstructcmd / handle.NYI,
settspr = SetStructCmd(Access.tspr),
setuserdef = (arraypat + sp1)/{} * singlememberpat * sp1 * tok.rvar / handle.NYI,

View file

@ -261,6 +261,10 @@ gameevent(gv.EVENT_ENTERLEVEL,
pl:give_weapon(gv.RPG_WEAPON)
pl.ammo_amount[gv.RPG_WEAPON] = 54
-- MORTER2 from test/weaponvars.con
player[0].weapon.SHOTGUN.shoots = 1653
projectile[1653].drop = -200
checkfail("gameevent('GAME', function() print('qwe') end)",
"must be called from top level")
end

View file

@ -3,6 +3,22 @@ gamevar shoots 2605 2 // RPG
gamevar WEAPON1_SHOOTS 2605 0
define MORTER2 1653
defineprojectile MORTER2 PROJ_WORKSLIKE 6150
defineprojectile MORTER2 PROJ_SPAWNS EXPLOSION2
defineprojectile MORTER2 PROJ_SOUND MORTER2_SHOOT
defineprojectile MORTER2 PROJ_VEL 600
defineprojectile MORTER2 PROJ_EXTRA 165
defineprojectile MORTER2 PROJ_EXTRA_RAND 10
defineprojectile MORTER2 PROJ_DROP 0 // tested in test.elua
defineprojectile MORTER2 PROJ_ISOUND PIPEBOMB_EXPLODE
defineprojectile MORTER2 PROJ_HITRADIUS 2800
defineprojectile MORTER2 PROJ_BOUNCES 4
defineprojectile MORTER2 PROJ_OFFSET 128
defineprojectile MORTER2 PROJ_CLIPDIST 24
defineprojectile MORTER2 PROJ_TRAIL SMALLSMOKE
defineprojectile MORTER2 PROJ_TNUM 6
onevent EVENT_GAME
setvarvar WEAPON1_FIRESOUND snd
// setvarvar WEAPON1_SHOOTS shoots