1-- CON language definitions
2
3local lpeg = require("lpeg")
4
5local pairs = pairs
6local print = print
7local setmetatable = setmetatable
8local type = type
9
10
11module(...)
12
13
14MAXVOLUMES = 7
15MAXLEVELS = 64
16MAXGAMETYPES = 16
17
18MAXSKILLS = 7
19
20MAXSOUNDS = 4096
21
22MAXSESSIONVARS = 8  -- KEEPINSYNC lunatic_game.c
23
24-- KEEPINSYNC quotes.h
25
26-- For Lunatic, MAXQUOTES is OBITQUOTEINDEX because starting from that index
27-- are obituary and suicide quotes which are passed as *format strings* to
28-- sprintf() in C.
29REALMAXQUOTES = 16384
30MAXQUOTES = REALMAXQUOTES-128
31MAXQUOTELEN = 128
32
33local STR = {
34    STR_MAPNAME = 0,
35    STR_MAPFILENAME = 1,
36    STR_PLAYERNAME = 2,
37    STR_VERSION = 3,
38    STR_GAMETYPE = 4,
39    STR_VOLUMENAME = 5,
40    STR_YOURTIME = 6,
41    STR_PARTIME = 7,
42    STR_DESIGNERTIME = 8,
43    STR_BESTTIME = 9,
44}
45
46PROJ = {
47    PROJ_WORKSLIKE = 0,
48    PROJ_SPAWNS = 1,
49    PROJ_SXREPEAT = 2,
50    PROJ_SYREPEAT = 3,
51    PROJ_SOUND = 4,
52    PROJ_ISOUND = 5,
53    PROJ_VEL = 6,
54    PROJ_EXTRA = 7,
55    PROJ_DECAL = 8,
56    PROJ_TRAIL = 9,
57    PROJ_TXREPEAT = 10,
58    PROJ_TYREPEAT = 11,
59    PROJ_TOFFSET = 12,
60    PROJ_TNUM = 13,
61    PROJ_DROP = 14,
62    PROJ_CSTAT = 15,
63    PROJ_CLIPDIST = 16,
64    PROJ_SHADE = 17,
65    PROJ_XREPEAT = 18,
66    PROJ_YREPEAT = 19,
67    PROJ_PAL = 20,
68    PROJ_EXTRA_RAND = 21,
69    PROJ_HITRADIUS = 22,
70    PROJ_VEL_MULT = 23,  -- NAME (PROJ_MOVECNT)
71    PROJ_OFFSET = 24,
72    PROJ_BOUNCES = 25,
73    PROJ_BSOUND = 26,
74    PROJ_RANGE = 27,
75    PROJ_FLASH_COLOR = 28,
76    PROJ_USERDATA = 29,
77}
78
79EVENT = {
80    EVENT_INIT = 0,
81    EVENT_ENTERLEVEL = 1,
82    EVENT_RESETWEAPONS = 2,
83    EVENT_RESETINVENTORY = 3,
84    EVENT_HOLSTER = 4,
85    EVENT_LOOKLEFT = 5,
86    EVENT_LOOKRIGHT = 6,
87    EVENT_SOARUP = 7,
88    EVENT_SOARDOWN = 8,
89    EVENT_CROUCH = 9,
90    EVENT_JUMP = 10,
91    EVENT_RETURNTOCENTER = 11,
92    EVENT_LOOKUP = 12,
93    EVENT_LOOKDOWN = 13,
94    EVENT_AIMUP = 14,
95    EVENT_FIRE = 15,
96    EVENT_CHANGEWEAPON = 16,
97    EVENT_GETSHOTRANGE = 17,
98    EVENT_GETAUTOAIMANGLE = 18,
99    EVENT_GETLOADTILE = 19,
100    EVENT_CHEATGETSTEROIDS = 20,
101    EVENT_CHEATGETHEAT = 21,
102    EVENT_CHEATGETBOOT = 22,
103    EVENT_CHEATGETSHIELD = 23,
104    EVENT_CHEATGETSCUBA = 24,
105    EVENT_CHEATGETHOLODUKE = 25,
106    EVENT_CHEATGETJETPACK = 26,
107    EVENT_CHEATGETFIRSTAID = 27,
108    EVENT_QUICKKICK = 28,
109    EVENT_INVENTORY = 29,
110    EVENT_USENIGHTVISION = 30,
111    EVENT_USESTEROIDS = 31,
112    EVENT_INVENTORYLEFT = 32,
113    EVENT_INVENTORYRIGHT = 33,
114    EVENT_HOLODUKEON = 34,
115    EVENT_HOLODUKEOFF = 35,
116    EVENT_USEMEDKIT = 36,
117    EVENT_USEJETPACK = 37,
118    EVENT_TURNAROUND = 38,
119    EVENT_DISPLAYWEAPON = 39,
120    EVENT_FIREWEAPON = 40,
121    EVENT_SELECTWEAPON = 41,
122    EVENT_MOVEFORWARD = 42,
123    EVENT_MOVEBACKWARD = 43,
124    EVENT_TURNLEFT = 44,
125    EVENT_TURNRIGHT = 45,
126    EVENT_STRAFELEFT = 46,
127    EVENT_STRAFERIGHT = 47,
128    EVENT_WEAPKEY1 = 48,
129    EVENT_WEAPKEY2 = 49,
130    EVENT_WEAPKEY3 = 50,
131    EVENT_WEAPKEY4 = 51,
132    EVENT_WEAPKEY5 = 52,
133    EVENT_WEAPKEY6 = 53,
134    EVENT_WEAPKEY7 = 54,
135    EVENT_WEAPKEY8 = 55,
136    EVENT_WEAPKEY9 = 56,
137    EVENT_WEAPKEY10 = 57,
138    EVENT_DRAWWEAPON = 58,
139    EVENT_DISPLAYCROSSHAIR = 59,
140    EVENT_DISPLAYREST = 60,
141    EVENT_DISPLAYSBAR = 61,
142    EVENT_RESETPLAYER = 62,
143    EVENT_INCURDAMAGE = 63,
144    EVENT_AIMDOWN = 64,
145    EVENT_GAME = 65,
146    EVENT_PREVIOUSWEAPON = 66,
147    EVENT_NEXTWEAPON = 67,
148    EVENT_SWIMUP = 68,
149    EVENT_SWIMDOWN = 69,
150    EVENT_GETMENUTILE = 70,
151    EVENT_SPAWN = 71,
152    EVENT_LOGO = 72,
153    EVENT_EGS = 73,
154    EVENT_DOFIRE = 74,
155    EVENT_PRESSEDFIRE = 75,
156    EVENT_USE = 76,
157    EVENT_PROCESSINPUT = 77,
158    EVENT_FAKEDOMOVETHINGS = 78,
159    EVENT_DISPLAYROOMS = 79,
160    EVENT_KILLIT = 80,
161    EVENT_LOADACTOR = 81,
162    EVENT_DISPLAYBONUSSCREEN = 82,
163    EVENT_DISPLAYMENU = 83,
164    EVENT_DISPLAYMENUREST = 84,
165    EVENT_DISPLAYLOADINGSCREEN = 85,
166    EVENT_ANIMATESPRITES = 86,
167    EVENT_NEWGAME = 87,
168    EVENT_SOUND = 88,
169    EVENT_CHECKTOUCHDAMAGE = 89,
170    EVENT_CHECKFLOORDAMAGE = 90,
171    EVENT_LOADGAME = 91,
172    EVENT_SAVEGAME = 92,
173    EVENT_PREGAME = 93,
174    EVENT_CHANGEMENU = 94,
175    EVENT_DAMAGEHPLANE = 95,
176    EVENT_ACTIVATECHEAT = 96,
177    EVENT_DISPLAYINACTIVEMENU = 97,
178    EVENT_DISPLAYINACTIVEMENUREST = 98,
179    EVENT_CUTSCENE = 99,
180    EVENT_DISPLAYCURSOR = 100,
181    EVENT_DISPLAYLEVELSTATS = 101,
182    EVENT_DISPLAYCAMERAOSD = 102,
183    EVENT_DISPLAYROOMSCAMERA = 103,
184    EVENT_DISPLAYSTART = 104,
185    EVENT_WORLD = 105,
186    EVENT_PREWORLD = 106,
187    EVENT_PRELEVEL = 107,
188    EVENT_DISPLAYSPIT = 108,
189    EVENT_DISPLAYFIST = 109,
190    EVENT_DISPLAYKNEE = 110,
191    EVENT_DISPLAYKNUCKLES = 111,
192    EVENT_DISPLAYSCUBA = 112,
193    EVENT_DISPLAYTIP = 113,
194    EVENT_DISPLAYACCESS = 114,
195--    EVENT_ANIMATEALLSPRITES = previous+1,  -- internal
196-- KEEPINSYNC with MAXEVENTS below
197}
198
199MAXEVENTS = 115  -- KEEPINSYNC with above EVENT_* list
200
201-- NOTE: negated values are not exported to the ffi.C namespace or CON.
202-- See TWEAK_SFLAG below.
203SFLAG = {
204    SFLAG_SHADOW           = 0x00000001,
205    SFLAG_NVG              = 0x00000002,
206    SFLAG_NOSHADE          = 0x00000004,
207    SFLAG_PROJECTILE       = -0x00000008,
208    SFLAG_DECAL            = -0x00000010,
209    SFLAG_BADGUY           = 0x00000020,
210    SFLAG_NOPAL            = 0x00000040,
211    SFLAG_NOEVENTS         = 0x00000080,  -- NAME
212    SFLAG_NOLIGHT          = 0x00000100,
213    SFLAG_USEACTIVATOR     = 0x00000200,
214    SFLAG_NULL             = -0x00000400,
215    SFLAG_NOCLIP           = 0x00000800,
216    SFLAG_NOFLOORSHADOW    = -0x00001000,
217    SFLAG_SMOOTHMOVE       = 0x00002000,
218    SFLAG_NOTELEPORT       = 0x00004000,
219    SFLAG_BADGUYSTAYPUT    = -0x00008000,
220    SFLAG_CACHE            = -0x00010000,
221    SFLAG_ROTFIXED         = -0x00020000,
222    SFLAG_HARDCODED_BADGUY = -0x00040000,
223    SFLAG_DIDNOSE7WATER    = -0x00080000,
224    SFLAG_NODAMAGEPUSH     = 0x00100000,
225    SFLAG_NOWATERDIP       = 0x00200000,
226    SFLAG_HURTSPAWNBLOOD   = 0x00400000,
227    -- RESERVED for actor.FLAGS.chain_*/replace_*:
228    -- 0x08000000, 0x10000000, 0x20000000, 0x40000000
229}
230
231STAT = {
232    STAT_DEFAULT = 0,
233    STAT_ACTOR = 1,
234    STAT_ZOMBIEACTOR = 2,
235    STAT_EFFECTOR = 3,
236    STAT_PROJECTILE = 4,
237    STAT_MISC = 5,
238    STAT_STANDABLE = 6,
239    STAT_LOCATOR = 7,
240    STAT_ACTIVATOR = 8,
241    STAT_TRANSPORT = 9,
242    STAT_PLAYER = 10,
243    STAT_FX = 11,
244    STAT_FALLER = 12,
245    STAT_DUMMYPLAYER = 13,
246    STAT_LIGHT = 14,
247--    STAT_NETALLOC = 1023,  -- MAXSTATUS-1
248}
249
250local GAMEFUNC = {
251    GAMEFUNC_MOVE_FORWARD = 0,
252    GAMEFUNC_MOVE_BACKWARD = 1,
253    GAMEFUNC_TURN_LEFT = 2,
254    GAMEFUNC_TURN_RIGHT = 3,
255    GAMEFUNC_STRAFE = 4,
256    GAMEFUNC_FIRE = 5,
257    GAMEFUNC_OPEN = 6,
258    GAMEFUNC_RUN = 7,
259    GAMEFUNC_AUTORUN = 8,
260    GAMEFUNC_JUMP = 9,
261    GAMEFUNC_CROUCH = 10,
262    GAMEFUNC_LOOK_UP = 11,
263    GAMEFUNC_LOOK_DOWN = 12,
264    GAMEFUNC_LOOK_LEFT = 13,
265    GAMEFUNC_LOOK_RIGHT = 14,
266    GAMEFUNC_STRAFE_LEFT = 15,
267    GAMEFUNC_STRAFE_RIGHT = 16,
268    GAMEFUNC_AIM_UP = 17,
269    GAMEFUNC_AIM_DOWN = 18,
270    GAMEFUNC_WEAPON_1 = 19,
271    GAMEFUNC_WEAPON_2 = 20,
272    GAMEFUNC_WEAPON_3 = 21,
273    GAMEFUNC_WEAPON_4 = 22,
274    GAMEFUNC_WEAPON_5 = 23,
275    GAMEFUNC_WEAPON_6 = 24,
276    GAMEFUNC_WEAPON_7 = 25,
277    GAMEFUNC_WEAPON_8 = 26,
278    GAMEFUNC_WEAPON_9 = 27,
279    GAMEFUNC_WEAPON_10 = 28,
280    GAMEFUNC_INVENTORY = 29,
281    GAMEFUNC_INVENTORY_LEFT = 30,
282    GAMEFUNC_INVENTORY_RIGHT = 31,
283    GAMEFUNC_HOLO_DUKE = 32,
284    GAMEFUNC_JETPACK = 33,
285    GAMEFUNC_NIGHTVISION = 34,
286    GAMEFUNC_MEDKIT = 35,
287    GAMEFUNC_TURNAROUND = 36,
288    GAMEFUNC_SENDMESSAGE = 37,
289    GAMEFUNC_MAP = 38,
290    GAMEFUNC_SHRINK_SCREEN = 39,
291    GAMEFUNC_ENLARGE_SCREEN = 40,
292    GAMEFUNC_CENTER_VIEW = 41,
293    GAMEFUNC_HOLSTER_WEAPON = 42,
294    GAMEFUNC_SHOW_OPPONENTS_WEAPON = 43,
295    GAMEFUNC_MAP_FOLLOW_MODE = 44,
296    GAMEFUNC_SEE_COOP_VIEW = 45,
297    GAMEFUNC_MOUSE_AIMING = 46,
298    GAMEFUNC_TOGGLE_CROSSHAIR = 47,
299    GAMEFUNC_STEROIDS = 48,
300    GAMEFUNC_QUICK_KICK = 49,
301    GAMEFUNC_NEXT_WEAPON = 50,
302    GAMEFUNC_PREVIOUS_WEAPON = 51,
303--    GAMEFUNC_SHOW_CONSOLE = 52,
304    GAMEFUNC_SHOW_DUKEMATCH_SCORES = 53,
305    GAMEFUNC_DPAD_SELECT = 54,
306    GAMEFUNC_DPAD_AIMING = 55,
307}
308
309local function shallow_copy(tab)
310    local t = {}
311    for k,v in pairs(tab) do
312        t[k] = v
313    end
314    return t
315end
316
317-- KEEPINSYNC with gamedef.c:C_AddDefaultDefinitions() and the respective
318-- defines. These are exported to the ffi.C namespace (except STAT) and as
319-- literal defines in lunacon.lua.
320labels =
321{
322    STR,
323    PROJ,
324    EVENT,
325    shallow_copy(SFLAG),
326    setmetatable(STAT, { __metatable="noffiC" }),
327    GAMEFUNC,
328}
329
330user_sflags = 0
331-- TWEAK_SFLAG
332for name, flag in pairs(SFLAG) do
333    if (flag > 0) then
334        user_sflags = user_sflags + flag
335    else
336        SFLAG[name] = -flag
337        labels[4][name] = nil
338    end
339end
340
341-- KEEPINSYNC player.h
342wdata_members =
343{
344    -- NOTE: they are lowercased for Lunatic
345    -- NOTE: members _*sound*, _spawn and _shoots assume *zero* to mean "none"
346    --  (-1 would be more logical).
347    "const int32_t _workslike",
348    "int32_t clip",
349    "int32_t reload",
350    "int32_t firedelay",
351    "int32_t totaltime",
352    "int32_t holddelay",
353    "int32_t flags",
354    "const int32_t _shoots",
355    "int32_t spawntime",
356    "const int32_t _spawn",
357    "int32_t shotsperburst",
358    "const int32_t _initialsound",
359    "const int32_t _firesound",
360    "int32_t sound2time",  -- NOTE: this is a time number, not a sound
361    "const int32_t _sound2sound",
362    "const int32_t _reloadsound1",
363    "const int32_t _reloadsound2",
364    "const int32_t _selectsound",
365    "int32_t flashcolor",
366}
367
368
369local SP = function(memb) return "sprite[%s]"..memb end
370local ATSP = function(memb) return "_atsprite[%s]"..memb end
371local AC = function(memb) return "actor[%s]"..memb end
372local SX = function(memb) return "spriteext[%s]"..memb end
373
374-- Generate code to access a signed member as unsigned.
375local function s2u(label)
376    return "(_band("..label.."+65536,65535))"
377end
378
379local function S2U(label)
380    return { s2u(label), label }
381end
382
383-- Some literal checker functions (LITERAL_CHECKING).
384-- KEEPINSYNC with the actual setter code.
385local function litok_gem1(lit)
386    return (lit >= -1)
387end
388
389local function litok_ge0(lit)
390    return (lit >= 0)
391end
392
393local ActorLabels = {
394    x = SP".x",
395    y = SP".y",
396    z = SP".z",
397    cstat = SP".cstat",
398    picnum = { SP".picnum", SP":set_picnum(%%s)", litok_ge0 },
399    shade = SP".shade",
400    pal = SP".pal",
401    clipdist = SP".clipdist",
402--    filler = SP".filler",
403--    detail = SP".filler",  -- NAME
404    blend = SP".blend",
405    xrepeat = SP".xrepeat",
406    yrepeat = SP".yrepeat",
407    xoffset = SP".xoffset",
408    yoffset = SP".yoffset",
409    sectnum = { SP".sectnum", SP":changesect(%%s)", litok_ge0 },  -- set: for tsprite
410    statnum = { SP".statnum" },
411    ang = SP".ang",
412    owner = { SP".owner", SP":_set_owner(%%s)", litok_ge0 },
413    xvel = SP".xvel",
414    yvel = { SP".yvel", SP":set_yvel(%%s)" },
415    zvel = SP".zvel",
416    lotag = SP".lotag",
417    hitag = SP".hitag",
418    extra = SP".extra",
419
420    ulotag = S2U(SP".lotag"),
421    uhitag = S2U(SP".hitag"),
422
423    -- ActorExtra labels...
424    htcgg = AC".cgg",
425    -- XXX: why <0 allowed?
426    htpicnum = { AC".picnum", AC":set_picnum(%%s)" },
427    htang = AC".ang",
428    htextra = AC".extra",
429    htowner = { AC".owner", AC":set_owner(%%s)", litok_ge0 },
430    htmovflag = AC"._movflag",
431    httempang = AC".tempang",
432    htactorstayput = AC".stayputsect",  -- NAME
433    htdispicnum = { AC".dispicnum" },
434    -- NOTE: no access for .shootzvel
435    httimetosleep = AC".timetosleep",
436    htfloorz = AC".floorz",
437    htceilingz = AC".ceilingz",
438    htlastvx = AC".lastvx",
439    htlastvy = AC".lastvy",
440    htbposx = AC".bpos.x",
441    htbposy = AC".bpos.y",
442    htbposz = AC".bpos.z",
443    -- Read access differs from write ({ get, set }):
444    htg_t = { AC":_get_t_data(%s)", AC":_set_t_data(%s,%%s)" },
445    htflags = AC".flags",
446    movflags = AC".movflags",
447
448    -- (mostly) model-related flags
449    angoff = SX".angoff",
450    pitch = SX".pitch",
451    roll = SX".roll",
452    mdxoff = SX".mdoff.x",  -- NAME
453    mdyoff = SX".mdoff.y",
454    mdzoff = SX".mdoff.z",
455    posxoff = SX".mdposoff.x",
456    posyoff = SX".mdposoff.y",
457    poszoff = SX".mdposoff.z",
458    mdflags = SX".flags",
459    xpanning = SX".xpanning",
460    ypanning = SX".ypanning",
461
462    alpha = { "_math.floor(spriteext[%s].alpha*255)", "spriteext[%s].alpha=(%%s)/255" },
463
464    isvalid = { "_con._isvalid(%s)" },
465}
466
467local function spr2tspr(code)
468    if (code and code:find(SP"", 1, true)==1) then
469        return ATSP(code:sub(#SP"" + 1))
470    end
471    -- else return nothing
472end
473
474local TspriteLabels = {}
475
476for member, code in pairs(ActorLabels) do
477    if (type(code)=="string") then
478        TspriteLabels["tspr"..member] = spr2tspr(code)
479    else
480        TspriteLabels["tspr"..member] = { spr2tspr(code[1]), spr2tspr(code[2]) }
481    end
482end
483
484-- Sprites set stat- and sectnum via sprite.change{stat,sect} functions.
485ActorLabels.sectnum[2] = "sprite.changesect(%s,%%s,true)"
486ActorLabels.statnum[2] = "sprite.changestat(%s,%%s,true)"
487
488local PL = function(memb) return "player[%s]"..memb end
489-- Access to DukePlayer_t's bool members: they must be read as numbers.
490local PLBOOL = function(memb) return { "("..PL(memb).." and 1 or 0)", PL(memb) } end
491
492local empty_table = {}
493local DISABLED_PL = function() return empty_table end
494local DISABLED = DISABLED_PL
495
496local PlayerLabels = {
497    posx = PL".pos.x",
498    posy = PL".pos.y",
499    posz = PL".pos.z",
500    oposx = PL".opos.x",
501    oposy = PL".opos.y",
502    oposz = PL".opos.z",
503    posxv = PL".vel.x",  -- NAME
504    posyv = PL".vel.y",
505    poszv = PL".vel.z",
506    -- NOTE: no access for .npos
507    bobposx = DISABLED_PL".bobposx",
508    bobposy = DISABLED_PL".bobposy",
509
510    truefz = DISABLED_PL".truefz",
511    truecz = DISABLED_PL".truecz",
512    player_par = PL".player_par",
513
514    randomflamex = DISABLED_PL".randomflamex",
515    exitx = DISABLED_PL".exitx",
516    exity = DISABLED_PL".exity",
517
518    runspeed = PL".runspeed",
519    max_player_health = PL".max_player_health",
520    max_shield_amount = PL".max_shield_amount",
521
522    autostep = PL".autostep",
523    autostep_sbw = PL".autostep_sbw",
524
525    interface_toggle_flag = DISABLED_PL".interface_toggle_flag",
526
527    -- NOTE: *bombControl etc. are accessed by gamevars in CON
528
529    max_actors_killed = PL".max_actors_killed",
530    actors_killed = PL".actors_killed",
531
532    -- NOTE the special case; "%%s" is used to mark settable members
533    -- with METHOD_MEMBER syntax, it's the value to be set.
534    gotweapon = { "("..PL":has_weapon(%s) and 1 or 0)", PL":_gt_weapon(%s,%%s)" },
535    zoom = PL".zoom",
536
537    loogiex = {},
538    loogiey = {},
539
540    sbs = PL".sbs",
541    sound_pitch = PL".sound_pitch",
542
543    ang = PL".ang",
544    oang = PL".oang",
545    angvel = PL".angvel",
546
547    cursectnum = PL".cursectnum",
548
549    look_ang = PL".look_ang",
550    last_extra = PL".last_extra",
551    subweapon = PL".subweapon",
552
553    max_ammo_amount = PL".max_ammo_amount[%s]",
554    ammo_amount = PL".ammo_amount[%s]",
555    -- NOTE: no direct access for .inv_amount (but see end)
556
557    wackedbyactor = PL".wackedbyactor",
558    pyoff = PL".pyoff",
559    opyoff = PL".opyoff",
560
561    horiz = PL".horiz",
562    horizoff = PL".horizoff",
563    ohoriz = PL".ohoriz",
564    ohorizoff = PL".ohorizoff",
565
566    newowner = PL".newowner",
567
568    jumping_counter = PL".jumping_counter",
569    airleft = PL".airleft",
570
571    fta = PL".fta",
572    ftq = PL".ftq",
573    access_wallnum = { PL".access_wallnum" },
574    access_spritenum = { PL".access_spritenum" },
575
576    got_access = PL".got_access",
577    weapon_ang = PL".weapon_ang",
578    visibility = PL".visibility",
579
580    somethingonplayer = PL".somethingonplayer",
581    on_crane = PL".on_crane",
582
583    i = { PL".i" },
584    index = { "%s" },
585
586    one_parallax_sectnum = DISABLED{ PL".one_parallax_sectnum" },
587
588    random_club_frame = PL".random_club_frame",
589    one_eighty_count = PL".one_eighty_count",
590
591    dummyplayersprite = DISABLED_PL".dummyplayersprite",
592    extra_extra8 = PL".extra_extra8",
593
594    actorsqu = PL".actorsqu",
595    timebeforeexit = PL".timebeforeexit",
596    customexitsound = { PL".customexitsound" },
597
598    last_pissed_time = PL".last_pissed_time",
599
600    weaprecs = PL".weaprecs[%s]",
601
602    weapon_sway = PL".weapon_sway",
603    crack_time = PL".crack_time",
604    bobcounter = PL".bobcounter",
605
606    -- NOTE: no access for .orotscrnang
607    rotscrnang = PL".rotscrnang",
608    dead_flag = PL".dead_flag",
609
610    holoduke_on = PL".holoduke_on",
611    pycount = PL".pycount",
612    transporter_hold = PL".transporter_hold",
613
614    max_secret_rooms = PL".max_secret_rooms",
615    secret_rooms = PL".secret_rooms",
616
617    frag = PL".frag",
618    fraggedself = PL".fraggedself",
619    quick_kick = PL".quick_kick",
620    last_quick_kick = PL".last_quick_kick",
621
622    return_to_center = DISABLED_PL".return_to_center",
623    reloading = PLBOOL".reloading",
624    weapreccnt = { PL".weapreccnt" },
625
626    aim_mode = PL".aim_mode",
627    auto_aim = PL".auto_aim",
628    weaponswitch = PL".weaponswitch",
629    movement_lock = PL".movement_lock",
630    team = PL".team",
631
632    tipincs = PL".tipincs",
633    hbomb_hold_delay = PL".hbomb_hold_delay",
634    frag_ps = PL".frag_ps",
635    kickback_pic = PL".kickback_pic",
636
637    gm = PL".gm",
638    on_warping_sector = PLBOOL".on_warping_sector",
639    footprintcount = PL".footprintcount",
640    hurt_delay = PL".hurt_delay",
641
642    hbomb_on = PLBOOL".hbomb_on",
643    jumping_toggle = PLBOOL".jumping_toggle",
644    rapid_fire_hold = PLBOOL".rapid_fire_hold",
645    on_ground = PLBOOL".on_ground",
646
647    inven_icon = PL".inven_icon",
648    buttonpalette = PL".buttonpalette",
649    over_shoulder_on = PLBOOL".over_shoulder_on",
650    show_empty_weapon = PL".show_empty_weapon",
651
652    jetpack_on = PLBOOL".jetpack_on",
653    spritebridge = PLBOOL".spritebridge",
654    lastrandomspot = DISABLED_PL".lastrandomspot",
655
656    scuba_on = PLBOOL".scuba_on",
657    footprintpal = PL".footprintpal",
658    heat_on = PLBOOL".heat_on",
659    invdisptime = PL".invdisptime",
660    holster_weapon = PLBOOL".holster_weapon",
661    falling_counter = PL".falling_counter",
662    footprintshade = PL".footprintshade",
663
664    refresh_inventory = PL".refresh_inventory",
665    last_full_weapon = PL".last_full_weapon",
666
667    walking_snd_toggle = PL".walking_snd_toggle",
668    palookup = PL".palookup",
669    hard_landing = PL".hard_landing",
670    fist_incs = PL".fist_incs",
671
672    toggle_key_flag = { PL".toggle_key_flag" },
673    knuckle_incs = PL".knuckle_incs",
674    knee_incs = PL".knee_incs",
675    access_incs = PL".access_incs",
676
677    numloogs = DISABLED_PL".numloogs",
678    loogcnt = PL".loogcnt",
679    scream_voice = { PL".scream_voice" },
680
681    last_weapon = PL".last_weapon",
682    cheat_phase = { PL".cheat_phase" },
683    weapon_pos = PL".weapon_pos",
684    wantweaponfire = PL".wantweaponfire",
685
686    curr_weapon = PL".curr_weapon",
687
688    palette = { PL".palette" },
689
690    -- NOTE the special case:
691    pals = PL"._pals[%s]",
692    pals_time = PL"._pals.f",
693
694    name = {},
695
696    -- Access to .inv_amount
697    steroids_amount = PL".inv_amount[0]",
698    shield_amount = PL".inv_amount[1]",
699    scuba_amount = PL".inv_amount[2]",
700    holoduke_amount = PL".inv_amount[3]",
701    jetpack_amount = PL".inv_amount[4]",
702    -- 5: dummy
703    -- 6: no "access_amount"
704    heat_amount = PL".inv_amount[7]",
705    -- 8: dummy
706    firstaid_amount = PL".inv_amount[9]",
707    boot_amount = PL".inv_amount[10]",
708}
709
710local SEC = function(memb) return "sector[%s]"..memb end
711local SECRO = function(memb) return { "sector[%s]"..memb } end
712
713local SectorLabels = {
714    wallptr = SECRO".wallptr",
715    wallnum = SECRO".wallnum",
716
717    ceilingz = SEC".ceilingz",
718    floorz = SEC".floorz",
719
720    ceilingstat = SEC".ceilingstat",
721    floorstat = SEC".floorstat",
722
723    -- CEILING
724    ceilingpicnum = { SEC".ceilingpicnum", SEC":set_ceilingpicnum(%%s)", litok_ge0 },
725
726    ceilingslope = SEC".ceilingheinum",  -- NAME
727    ceilingshade = SEC".ceilingshade",
728
729    ceilingpal = SEC".ceilingpal",
730    ceilingxpanning = SEC".ceilingxpanning",
731    ceilingypanning = SEC".ceilingypanning",
732
733    -- FLOOR
734    floorpicnum = { SEC".floorpicnum", SEC":set_floorpicnum(%%s)", litok_ge0 },
735
736    floorslope = SEC".floorheinum",  -- NAME
737    floorshade = SEC".floorshade",
738
739    floorpal = SEC".floorpal",
740    floorxpanning = SEC".floorxpanning",
741    floorypanning = SEC".floorypanning",
742
743    visibility = SEC".visibility",
744    fogpal = SEC".fogpal",
745    alignto = SEC".fogpal",  -- NAME
746
747    lotag = SEC".lotag",
748    hitag = SEC".hitag",
749    extra = SEC".extra",
750
751    ceilingbunch = { SEC".ceilingbunch" },
752    floorbunch = { SEC".floorbunch" },
753
754    ulotag = S2U(SEC".lotag"),
755    uhitag = S2U(SEC".hitag"),
756}
757
758local WAL = function(memb) return "wall[%s]"..memb end
759local WALRO = function(memb) return { "wall[%s]"..memb } end
760
761local WallLabels = {
762    x = WAL".x",
763    y = WAL".y",
764    point2 = WALRO".point2",
765    nextwall = { WAL".nextwall", WAL":_set_nextwall(%%s)" },
766    nextsector = { WAL".nextsector", WAL":_set_nextsector(%%s)" },
767    cstat = WAL".cstat",
768    picnum = { WAL".picnum", WAL":set_picnum(%%s)", litok_ge0 },
769    overpicnum = { WAL".overpicnum", WAL":set_overpicnum(%%s)", litok_ge0 },
770    shade = WAL".shade",
771    pal = WAL".pal",
772    xrepeat = WAL".xrepeat",
773    yrepeat = WAL".yrepeat",
774    xpanning = WAL".xpanning",
775    ypanning = WAL".ypanning",
776    lotag = WAL".lotag",
777    hitag = WAL".hitag",
778    extra = WAL".extra",
779    blend = WAL".blend",
780
781    ulotag = S2U(WAL".lotag"),
782    uhitag = S2U(WAL".hitag"),
783}
784
785local function tonegtag(LabelsTab, member, funcname)
786    local memb = LabelsTab[member]
787    LabelsTab[member] = { memb, memb.."="..funcname.."(%%s)" }
788end
789
790function setup_negative_tag_check(funcname)
791    tonegtag(TspriteLabels, "tsprlotag", funcname)
792    tonegtag(TspriteLabels, "tsprhitag", funcname)
793    tonegtag(ActorLabels, "lotag", funcname)
794    tonegtag(ActorLabels, "hitag", funcname)
795    tonegtag(WallLabels, "lotag", funcname)
796    tonegtag(WallLabels, "hitag", funcname)
797    tonegtag(SectorLabels, "lotag", funcname)
798    tonegtag(SectorLabels, "hitag", funcname)
799end
800
801local PROJ = function(memb) return "projectile[%s]"..memb end
802local THISPROJ = function(memb) return "actor[%s].proj"..memb end
803
804local ProjectileLabels = {
805    workslike = PROJ".workslike",
806    cstat = PROJ".cstat",
807    hitradius = PROJ".hitradius",
808    range = PROJ".range",
809    flashcolor = PROJ".flashcolor",
810    spawns = { PROJ".spawns", PROJ":set_spawns(%%s)", litok_gem1 },
811    sound = { PROJ".sound", PROJ":set_sound(%%s)", litok_gem1 },
812    isound = { PROJ".isound", PROJ":set_isound(%%s)", litok_gem1 },
813    vel = PROJ".vel",
814    decal = { PROJ".decal", PROJ":set_decal(%%s)", litok_gem1 },
815    trail = { PROJ".trail", PROJ":set_trail(%%s)", litok_gem1 },
816    tnum = PROJ".tnum",
817    drop = PROJ".drop",
818    offset = PROJ".offset",
819    bounces = PROJ".bounces",
820    bsound = { PROJ".bsound", PROJ":set_bsound(%%s)", litok_gem1 },
821    toffset = PROJ".toffset",
822    extra = PROJ".extra",
823    extra_rand = PROJ".extra_rand",
824    sxrepeat = PROJ".sxrepeat",
825    syrepeat = PROJ".syrepeat",
826    txrepeat = PROJ".txrepeat",
827    tyrepeat = PROJ".tyrepeat",
828    shade = PROJ".shade",
829    xrepeat = PROJ".xrepeat",
830    yrepeat = PROJ".yrepeat",
831    pal = PROJ".pal",
832    velmult = PROJ".movecnt",  -- NAME
833    clipdist = PROJ".clipdist",
834    userdata = PROJ".userdata",
835}
836
837-- XXX: kind of CODEDUP form spr2tspr
838local function proj2thisproj(code)
839    if (code and code:find(PROJ"", 1, true)==1) then
840        return THISPROJ(code:sub(#PROJ"" + 1))
841    end
842    -- else return nothing
843end
844
845local SpriteProjectileLabels = {}
846
847for member, code in pairs(ProjectileLabels) do
848    if (type(code)=="string") then
849        SpriteProjectileLabels[member] = proj2thisproj(code)
850    else
851        SpriteProjectileLabels[member] = { proj2thisproj(code[1]), proj2thisproj(code[2]) }
852    end
853end
854
855local UD = function(memb) return "_gud(_pli)"..memb end
856local UDRO = function(memb) return { UD(memb) } end
857
858-- NOTE: Only members that are actually encountered in existing mods are added here.
859-- TODO: r5043, r5044
860local UserdefLabels = {
861    althud = UD".althud",
862    auto_run = UD".auto_run",
863    camerasprite = UDRO".camerasprite",
864    cashman = UDRO".cashman",
865    clipping = UD".noclip",  -- NAME
866    color = UD".color",
867    const_visibility = UD".const_visibility",
868    crosshair = UD".crosshair",
869    crosshairscale = UDRO".crosshairscale",
870    detail = { "1" },
871    display_bonus_screen = UD".display_bonus_screen",
872    drawweapon = UDRO".drawweapon",
873    eog = UD".eog",
874    ffire = UDRO".ffire",
875    fta_on = UD".fta_on",
876    god = UD".god",
877    idplayers = UDRO".idplayers",
878    last_level = UDRO".last_level",
879    level_number = { UD".level_number", UD":set_level_number(%%s)", {0, MAXLEVELS-1} },
880    levelstats = UD".levelstats",
881    lockout = UDRO".lockout",
882    m_origin_x = UD".m_origin.x",
883    m_origin_y = UD".m_origin.y",
884    m_player_skill = UDRO".m_player_skill",
885    m_volume_number = { UD".m_volume_number", UD":set_m_volume_number(%%s)", {0, MAXVOLUMES} },
886    mouseaiming = UD".mouseaiming",
887    pause_on = UDRO".pause_on",
888    player_skill = UD".player_skill",
889    playerbest = UDRO".playerbest",
890    mouseflip = UDRO".mouseflip",
891    multimode = { "1" },
892    musictoggle = UDRO".config.MusicToggle",
893    noexits = UDRO".noexits",
894    overhead_on = UD".overhead_on",
895    recstat = UDRO".recstat",
896    runkey_mode = UD".runkey_mode",
897    show_level_text = UD".show_level_text",
898    screen_size = { UD".screen_size", UD":set_screen_size(%%s)" },
899    screen_tilting = UD".screen_tilting",
900    showallmap = UD".showallmap",
901    showweapons = UDRO".showweapons",
902    statusbarmode = UDRO".statusbarmode",
903    statusbarscale = UDRO".statusbarscale",
904    volume_number = { UD".volume_number", UD":set_volume_number(%%s)", {0, MAXVOLUMES} },
905    weaponscale = UDRO".weaponscale",
906    weaponswitch = UD".weaponswitch",
907}
908
909local INP = function(memb) return PL"._input"..memb end
910
911local InputLabels = {
912    avel = INP".avel",
913    horz = INP".horz",
914    fvel = INP".fvel",
915    svel = INP".svel",
916    bits = INP".bits",
917    extbits = INP".extbits",
918}
919
920local TileDataLabels = {
921    -- tilesiz[]
922    xsize = "g_tile.sizx[%s]",
923    ysize = "g_tile.sizy[%s]",
924
925    -- picanm[]
926--    "animframes",
927--    "xoffset",
928--    "yoffset",
929--    "animspeed",
930--    "animtype",
931
932    -- g_tile[]
933    gameflags = { "g_tile[%s]._flags" },
934}
935
936StructAccessCode =
937{
938    sector = SectorLabels,
939    wall = WallLabels,
940    sprite = ActorLabels,
941    player = PlayerLabels,
942    tspr = TspriteLabels,
943    projectile = ProjectileLabels,
944    thisprojectile = SpriteProjectileLabels,
945    userdef = UserdefLabels,
946    input = InputLabels,
947    tiledata = TileDataLabels,
948-- TODO: tiledata picanm[] members, paldata
949}
950
951-- NOTE: These MUST be in reverse lexicographical order!
952-- Per CON syntax, valid identifiers names are disjoint from keywords,
953-- so that a rule like
954--      t_identifier = -con_keyword * (sp1 + "[") * t_identifier_all
955-- (from the final grammar in lunacon.lua) must match the longest
956-- possible keyword name, else the negation might wrongly not fail.
957
958keyword =
959
960lpeg.P(false) +
961"}" +
962"{" +
963"zshootvar" +
964"zshoot" +
965"xorvarvar" +
966"xorvar" +
967"writearraytofile" +
968"whilevarvarn" +
969"whilevarn" +
970"wackplayer" +
971"userquote" +
972"useractor" +
973"updatesectorz" +
974"updatesector" +
975"undefinevolume" +
976"undefineskill" +
977"undefinelevel" +
978"tossweapon" +
979"tip" +
980"time" +
981"switch" +
982"subvarvar" +
983"subvar" +
984"strength" +
985"stopsoundvar" +
986"stopsound" +
987"stopallsounds" +
988"stopactorsound" +
989"state" +
990"starttrackvar" +
991"starttrack" +
992"startlevel" +
993"startcutscene" +
994"ssp" +
995"sqrt" +
996"spriteshadow" +
997"spritepal" +
998"spritenvg" +
999"spritenoshade" +
1000"spritenopal" +
1001"spriteflags" +
1002"spgetlotag" +
1003"spgethitag" +
1004"spawn" +
1005"soundvar" +
1006"soundoncevar" +
1007"soundonce" +
1008"sound" +
1009"smaxammo" +
1010"sleeptime" +
1011"sizeto" +
1012"sizeat" +
1013"sin" +
1014"showviewunbiased" +
1015"showview" +
1016"shootvar" +
1017"shoot" +
1018"shiftvarr" +
1019"shiftvarl" +
1020"shadeto" +
1021"setwall" +
1022"setvarvar" +
1023"setvar" +
1024"setuserdef" +
1025"settspr" +
1026"setthisprojectile" +
1027"setsprite" +
1028"setsector" +
1029"setprojectile" +
1030"setplayervar" +
1031"setplayerangle" +
1032"setplayer" +
1033"setmusicposition" +
1034"setinput" +
1035"setgamepalette" +
1036"setgamename" +
1037"setdefname" +
1038"setcfgname" +
1039"setaspect" +
1040"setarray" +
1041"setactorvar" +
1042"setactorsoundpitch" +
1043"setactorangle" +
1044"setactor" +
1045"sectsetinterpolation" +
1046"sectorofwall" +
1047"sectgetlotag" +
1048"sectgethitag" +
1049"sectclearinterpolation" +
1050"scriptsize" +
1051"screentext" +
1052"screensound" +
1053"savenn" +
1054"savemapstate" +
1055"savegamevar" +
1056"save" +
1057"rotatespritea" +
1058"rotatesprite16" +
1059"rotatesprite" +
1060"rotatepoint" +
1061"return" +
1062"respawnhitag" +
1063"resizearray" +
1064"resetplayerflags" +
1065"resetplayer" +
1066"resetcount" +
1067"resetactioncount" +
1068"redefinequote" +
1069"readgamevar" +
1070"readarrayfromfile" +
1071"rayintersect" +
1072"randvarvar" +
1073"randvar" +
1074"quote" +
1075"quake" +
1076"qsubstr" +
1077"qstrncat" +
1078"qstrlen" +
1079"qstrdim" +
1080"qstrcpy" +
1081"qstrcat" +
1082"qsprintf" +
1083"qspawnvar" +
1084"qspawn" +
1085"qgetsysstr" +
1086"pstomp" +
1087"prevspritestat" +
1088"prevspritesect" +
1089"precache" +
1090"pkick" +
1091"paper" +
1092"palfrom" +
1093"orvarvar" +
1094"orvar" +
1095"operatesectors" +
1096"operaterespawns" +
1097"operatemasterswitches" +
1098"operateactivators" +
1099"operate" +
1100"onevent" +
1101"nullop" +
1102"nextspritestat" +
1103"nextspritesect" +
1104"neartag" +
1105"myosx" +
1106"myospalx" +
1107"myospal" +
1108"myos" +
1109"music" +
1110"mulvarvar" +
1111"mulvar" +
1112"mulscale" +
1113"movesprite" +
1114"move" +
1115"money" +
1116"modvarvar" +
1117"modvar" +
1118"minitext" +
1119"mikesnd" +
1120"mail" +
1121"lotsofglass" +
1122"lockplayer" +
1123"loadmapstate" +
1124"lineintersect" +
1125"ldist" +
1126"killit" +
1127"jump" +
1128"insertspriteq" +
1129"inittimer" +
1130"includedefault" +
1131"include" +
1132"ifwasweapon" +
1133"ifvarxor" +
1134"ifvarvarxor" +
1135"ifvarvaror" +
1136"ifvarvarn" +
1137"ifvarvarl" +
1138"ifvarvarg" +
1139"ifvarvareither" +
1140"ifvarvare" +
1141"ifvarvarand" +
1142"ifvaror" +
1143"ifvarn" +
1144"ifvarl" +
1145"ifvarg" +
1146"ifvareither" +
1147"ifvare" +
1148"ifvarand" +
1149"ifstrength" +
1150"ifsquished" +
1151"ifspritepal" +
1152"ifspawnedby" +
1153"ifsound" +
1154"ifserver" +
1155"ifrnd" +
1156"ifrespawn" +
1157"ifplayersl" +
1158"ifpinventory" +
1159"ifphealthl" +
1160"ifpdistl" +
1161"ifpdistg" +
1162"ifp" +
1163"ifoutside" +
1164"ifonwater" +
1165"ifnotmoving" +
1166"ifnosounds" +
1167"ifmultiplayer" +
1168"ifmove" +
1169"ifinwater" +
1170"ifinspace" +
1171"ifinouterspace" +
1172"ifhitweapon" +
1173"ifhitspace" +
1174"ifgotweaponce" +
1175"ifgapzl" +
1176"iffloordistl" +
1177"ifdead" +
1178"ifcutscene" +
1179"ifcount" +
1180"ifclient" +
1181"ifceilingdistl" +
1182"ifcanshoottarget" +
1183"ifcanseetarget" +
1184"ifcansee" +
1185"ifbulletnear" +
1186"ifawayfromwall" +
1187"ifangdiffl" +
1188"ifai" +
1189"ifactorsound" +
1190"ifactornotstayput" +
1191"ifactor" +
1192"ifactioncount" +
1193"ifaction" +
1194"hitscan" +
1195"hitradiusvar" +
1196"hitradius" +
1197"headspritestat" +
1198"headspritesect" +
1199"guts" +
1200"guniqhudid" +
1201"gmaxammo" +
1202"globalsoundvar" +
1203"globalsound" +
1204"getzrange" +
1205"getwall" +
1206"getuserdef" +
1207"gettspr" +
1208"gettimedate" +
1209"getticks" +
1210"getthisprojectile" +
1211"gettexturefloor" +
1212"gettextureceiling" +
1213"getsector" +
1214"getprojectile" +
1215"getpname" +
1216"getplayervar" +
1217"getplayerangle" +
1218"getplayer" +
1219"getmusicposition" +
1220"getlastpal" +
1221"getkeyname" +
1222"getinput" +
1223"getincangle" +
1224"getflorzofslope" +
1225"getcurraddress" +
1226"getceilzofslope" +
1227"getarraysize" +
1228"getangletotarget" +
1229"getangle" +
1230"getactorvar" +
1231"getactorangle" +
1232"getactor" +
1233"gamevar" +
1234"gametextz" +
1235"gametext" +
1236"gamestartup" +
1237"gamearray" +
1238"flash" +
1239"findplayer" +
1240"findotherplayer" +
1241"findnearspritezvar" +
1242"findnearspritez" +
1243"findnearspritevar" +
1244"findnearsprite3dvar" +
1245"findnearsprite3d" +
1246"findnearsprite" +
1247"findnearactorzvar" +
1248"findnearactorz" +
1249"findnearactorvar" +
1250"findnearactor3dvar" +
1251"findnearactor3d" +
1252"findnearactor" +
1253"fall" +
1254"ezshootvar" +
1255"ezshoot" +
1256"eventloadactor" +
1257"espawnvar" +
1258"espawn" +
1259"eshootvar" +
1260"eshoot" +
1261"eqspawnvar" +
1262"eqspawn" +
1263"enhanced" +
1264"endswitch" +
1265"ends" +
1266"endoflevel" +
1267"endofgame" +
1268"endevent" +
1269"enda" +
1270"else" +
1271"echo" +
1272"dynamicsoundremap" +
1273"dynamicremap" +
1274"dragpoint" +
1275"divvarvar" +
1276"divvar" +
1277"dist" +
1278"displayrandvarvar" +
1279"displayrandvar" +
1280"displayrand" +
1281"digitalnumberz" +
1282"digitalnumber" +
1283"defstate" +
1284"definevolumename" +
1285"definevolumeflags" +
1286"definesound" +
1287"defineskillname" +
1288"definequote" +
1289"defineprojectile" +
1290"definelevelname" +
1291"definegametype" +
1292"definegamefuncname" +
1293"definecheat" +
1294"define" +
1295"default" +
1296"debug" +
1297"debris" +
1298"cstator" +
1299"cstat" +
1300"count" +
1301"cos" +
1302"copy" +
1303"cmenu" +
1304"clipmovenoslide" +
1305"clipmove" +
1306"clipdist" +
1307"clearmapstate" +
1308"checkavailweapon" +
1309"checkavailinven" +
1310"checkactivatormotion" +
1311"cheatkeys" +
1312"changespritestat" +
1313"changespritesect" +
1314"case" +
1315"canseespr" +
1316"cansee" +
1317"calchypotenuse" +
1318"cactor" +
1319"break" +
1320"betaname" +
1321"appendevent" +
1322"angoffvar" +
1323"angoff" +
1324"andvarvar" +
1325"andvar" +
1326"ai" +
1327"addweaponvar" +
1328"addweapon" +
1329"addvarvar" +
1330"addvar" +
1331"addstrength" +
1332"addphealth" +
1333"addlogvar" +
1334"addlog" +
1335"addkills" +
1336"addinventory" +
1337"addammo" +
1338"actor" +
1339"activatecheat" +
1340"activatebysector" +
1341"activate" +
1342"action" +
1343lpeg.P(false)
1344