From 185f0a8cc484d556500ec6b6a0aa6b742a56c0ea Mon Sep 17 00:00:00 2001
From: helixhorned <helixhorned@1a8010ca-5511-0410-912e-c29ae57300e0>
Date: Mon, 18 Feb 2013 16:07:42 +0000
Subject: [PATCH] Lunatic translator: text rendering and other niceties.

git-svn-id: https://svn.eduke32.com/eduke32@3501 1a8010ca-5511-0410-912e-c29ae57300e0
---
 polymer/eduke32/source/lunatic/bcheck.lua     |  5 +-
 polymer/eduke32/source/lunatic/control.lua    | 34 ++++++++++++
 polymer/eduke32/source/lunatic/defs.ilua      |  7 +++
 .../eduke32/source/lunatic/defs_common.lua    | 21 ++++++++
 polymer/eduke32/source/lunatic/dynsymlist     |  4 ++
 polymer/eduke32/source/lunatic/lunacon.lua    | 53 +++++++++++++------
 polymer/eduke32/source/lunatic/test.elua      | 23 +++++++-
 polymer/eduke32/source/premap.c               | 32 +++++------
 8 files changed, 144 insertions(+), 35 deletions(-)

diff --git a/polymer/eduke32/source/lunatic/bcheck.lua b/polymer/eduke32/source/lunatic/bcheck.lua
index 4635cc2b9..c10a1f5ae 100644
--- a/polymer/eduke32/source/lunatic/bcheck.lua
+++ b/polymer/eduke32/source/lunatic/bcheck.lua
@@ -77,9 +77,12 @@ function bcheck.quote_idx(qnum)
         error("invalid quote number "..qnum, 3)
     end
 
-    if (ffiC.ScriptQuotes[qnum] == nil) then
+    local cstr = ffiC.ScriptQuotes[qnum]
+    if (cstr == nil) then
         error("null quote "..qnum, 3)
     end
+
+    return cstr
 end
 
 
diff --git a/polymer/eduke32/source/lunatic/control.lua b/polymer/eduke32/source/lunatic/control.lua
index b7674db34..db9952926 100644
--- a/polymer/eduke32/source/lunatic/control.lua
+++ b/polymer/eduke32/source/lunatic/control.lua
@@ -439,6 +439,35 @@ function _echo(qnum)
     print(ffi.string(ffiC.ScriptQuotes[qnum]))
 end
 
+-- text rendering
+function _minitext(x, y, qnum, shade, pal)
+    local cstr = bcheck.quote_idx(qnum)
+    ffiC.minitext_(x, y, cstr, shade, pal, 2+8+16)
+end
+
+function _digitalnumber(tilenum, x, y, num, shade, pal,
+                        orientation, cx1, cy1, cx2, cy2, zoom)
+    if (tilenum >= ffiC.MAXTILES-9+0ULL) then
+        error("invalid base tile number "..tilenum, 2)
+    end
+
+    ffiC.G_DrawTXDigiNumZ(tilenum, x, y, num, shade, pal,
+                          orientation, cx1, cy1, cx2, cy2, zoom)
+end
+
+function _gametext(tilenum, x, y, qnum, shade, pal, orientation,
+                   cx1, cy1, cx2, cy2, zoom)
+    if (tilenum >= ffiC.MAXTILES-255+0ULL) then
+        error("invalid base tile number "..tilenum, 2)
+    end
+
+    local cstr = bcheck.quote_idx(qnum)
+
+    orientation = bit.band(orientation, 2047)  -- ROTATESPRITE_MAX-1
+    ffiC.G_PrintGameText(0, tilenum, bit.arshift(x,1), y, cstr, shade, pal,
+                        orientation, cx1, cy1, cx2, cy2, zoom)
+end
+
 local D = {
     -- TODO: dynamic tile remapping
     ACTIVATOR = 2,
@@ -1241,6 +1270,11 @@ function _startlevel(volume, level)
     player[0].gm = bit.bor(player[0].gm, 0x00000008)  -- MODE_EOL
 end
 
+function _setaspect(viewingrange, yxaspect)
+    -- XXX: surely not all values are sane
+    ffiC.setaspect(viewingrange, yxaspect)
+end
+
 
 --- Exported functions ---
 
diff --git a/polymer/eduke32/source/lunatic/defs.ilua b/polymer/eduke32/source/lunatic/defs.ilua
index d9aecbb9d..950395c8b 100644
--- a/polymer/eduke32/source/lunatic/defs.ilua
+++ b/polymer/eduke32/source/lunatic/defs.ilua
@@ -539,6 +539,13 @@ int32_t S_CheckSoundPlaying(int32_t i, int32_t num);
 void S_StopEnvSound(int32_t num, int32_t i);
 int32_t FX_StopAllSounds(void);
 void S_ChangeSoundPitch(int32_t num, int32_t i, int32_t pitchoffset);
+
+int32_t minitext_(int32_t x,int32_t y,const char *t,int32_t s,int32_t p,int32_t sb);
+void G_DrawTXDigiNumZ(int32_t starttile, int32_t x,int32_t y,int32_t n,int32_t s,int32_t pal,
+                      int32_t cs,int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t z);
+int32_t G_PrintGameText(int32_t f,  int32_t tile, int32_t x,  int32_t y,  const char *t,
+                        int32_t s,  int32_t p,    int32_t o,
+                        int32_t x1, int32_t y1,   int32_t x2, int32_t y2, int32_t z);
 ]]
 
 decl[[
diff --git a/polymer/eduke32/source/lunatic/defs_common.lua b/polymer/eduke32/source/lunatic/defs_common.lua
index ddd5779e2..a3c3fd22f 100644
--- a/polymer/eduke32/source/lunatic/defs_common.lua
+++ b/polymer/eduke32/source/lunatic/defs_common.lua
@@ -265,6 +265,8 @@ void updatesectorz(int32_t x, int32_t y, int32_t z, int16_t *sectnum);
 void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
                   int8_t dashade, unsigned char dapalnum, int32_t dastat,
                   int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2);
+
+void setaspect(int32_t daxrange, int32_t daaspect);
 ]]
 
 -- misc. functions
@@ -472,6 +474,25 @@ end
 
 local tspritetype_mt = deep_copy(spritetype_mt)
 
+local function get_sprite_idx(spr)
+    local i = ffi.cast(spritetype_ptr_ct, spr)-ffi.cast(spritetype_ptr_ct, ffiC.sprite)
+    assert(not (i >= ffiC.MAXSPRITES+0ULL))
+    return i
+end
+
+-- Methods that are specific to sprites
+function spritetype_mt.__index.setpos(spr, pos)  -- setsprite() clone
+    spr.x, spr.y, spr.z = pos.x, pos.y, pos.z
+
+    local newsect = updatesector(spr, spr.sectnum)
+    if (newsect < 0) then
+        return -1
+    end
+
+    ffiC.changespritesect(get_sprite_idx(spr), newsect)
+    return newsect
+end
+
 -- Methods that are specific to tsprites
 function tspritetype_mt.__index.dup(tspr)
     if (ffiC.spritesortcnt >= ffiC.MAXSPRITESONSCREEN+0ULL) then
diff --git a/polymer/eduke32/source/lunatic/dynsymlist b/polymer/eduke32/source/lunatic/dynsymlist
index 1393b35ec..bc3d22e0f 100644
--- a/polymer/eduke32/source/lunatic/dynsymlist
+++ b/polymer/eduke32/source/lunatic/dynsymlist
@@ -157,4 +157,8 @@ S_CheckSoundPlaying;
 S_StopEnvSound;
 FX_StopAllSounds;
 S_ChangeSoundPitch;
+
+minitext_;
+G_DrawTXDigiNumZ;
+G_PrintGameText;
 };
diff --git a/polymer/eduke32/source/lunatic/lunacon.lua b/polymer/eduke32/source/lunatic/lunacon.lua
index 76f137abe..dd0554a11 100644
--- a/polymer/eduke32/source/lunatic/lunacon.lua
+++ b/polymer/eduke32/source/lunatic/lunacon.lua
@@ -138,7 +138,7 @@ local function new_initial_codetab()
         "local _xmath, _geom = require'xmath', require'geom';",
         "local sector, sprite, actor, player = sector, sprite, actor, player;",
         "local gameactor, gameevent, _gv = gameactor, gameevent, gv;",
-        "local cansee = cansee;"
+        "local updatesector, updatesectorz, cansee = updatesector, updatesectorz, cansee;"
            }
 end
 
@@ -1343,6 +1343,10 @@ local handle =
     soundonce = "_con._soundonce(_aci,%1)",
 }
 
+local function n_s_fmt(n)
+    return string.rep("%s,", n-1).."%s"
+end
+
 local userdef_common_pat = (arraypat + sp1)/{} * lpeg.Cc(0) * lpeg.Ct(singlememberpat) * sp1
 
 -- NOTE about prefixes: most is handled by all_alt_pattern(), however commands
@@ -1395,8 +1399,6 @@ local Cinner = {
     setplayervar = GetOrSetPerxvarCmd(true, false),
     setactorvar = GetOrSetPerxvarCmd(true, true),
 
-    setsprite = cmd(R,R,R,R),
-
     setvarvar = varvarop / "%1=%2",
     addvarvar = varvaropf "+",
     subvarvar = varvaropf "-",
@@ -1732,11 +1734,24 @@ local Cinner = {
         / handle.NYI,
 
     -- screen text and numbers display
-    gametext = cmd(R,R,R,R,R,R,R,R,R,R,R),  -- 11 R
-    gametextz = cmd(R,R,R,R,R,R,R,R,R,R,R,R),  -- 12 R
-    digitalnumber = cmd(R,R,R,R,R,R,R,R,R,R,R),  -- 11R
-    digitalnumberz = cmd(R,R,R,R,R,R,R,R,R,R,R,R),  -- 12R
-    minitext = cmd(R,R,R,R,R),
+    gametext = cmd(R,R,R,R,R,R,R,R,R,R,R)  -- 11 R
+        / function(...)
+              return format("_con._gametext("..n_s_fmt(11)..",65536)", ...)
+          end,
+    gametextz = cmd(R,R,R,R,R,R,R,R,R,R,R,R)  -- 12 R
+        / function(...)
+              return format("_con._gametext("..n_s_fmt(12)..")", ...)
+          end,
+    digitalnumber = cmd(R,R,R,R,R,R,R,R,R,R,R)  -- 11R
+        / function(...)
+              return format("_con._digitalnumber("..n_s_fmt(11)..",65536)", ...)
+          end,
+    digitalnumberz = cmd(R,R,R,R,R,R,R,R,R,R,R,R)  -- 12R
+        / function(...)
+              return format("_con._digitalnumber("..n_s_fmt(12)..")", ...)
+          end,
+    minitext = cmd(R,R,R,R,R)
+        / "_con._minitext(%1,%2,%3,%4,%5)",
 
     palfrom = (sp1 * tok.define)^-4
         / handle.palfrom,
@@ -1812,6 +1827,8 @@ local Cinner = {
     starttrackvar = cmd(R)
         / "_con._starttrack(%1)",
 
+    setaspect = cmd(R,R)
+        / "_con._setaspect(%1,%2)",
     showview = cmd(R,R,R,R,R,R,R,R,R,R),  -- 10R
     showviewunbiased = cmd(R,R,R,R,R,R,R,R,R,R),  -- 10R
     smaxammo = cmd(R,R)
@@ -1822,8 +1839,12 @@ local Cinner = {
         / ACS".flags=%1",
     ssp = cmd(R,R)
         / handle.NYI,
-    updatesector = cmd(R,R,W),
-    updatesectorz = cmd(R,R,R,W),
+    setsprite = cmd(R,R,R,R)
+        / "sprite[%1]:setpos(_geom.ivec3(%1,%2,%3))",
+    updatesector = cmd(R,R,W)
+        / format("%%3=updatesector(_geom.ivec3(%%1,%%2),%s)", SPS".sectnum"),
+    updatesectorz = cmd(R,R,R,W)
+        / format("%%4=updatesectorz(_geom.ivec3(%%1,%%2,%%3),%s)", SPS".sectnum"),
 
     getactorangle = cmd(W)
         / ("%1="..SPS".ang"),
@@ -1837,17 +1858,15 @@ local Cinner = {
         / "%1=_con._angtotarget(_aci)",
 
     getceilzofslope = cmd(R,R,R,W)
-        / "%4=sector[%1]:ceilingzat(%2,%3)",
+        / "%4=sector[%1]:ceilingzat(_geom.ivec3(%2,%3))",
     getflorzofslope = cmd(R,R,R,W)
-        / "%4=sector[%1]:floorzat(%2,%3)",
+        / "%4=sector[%1]:floorzat(_geom.ivec3(%2,%3))",
     getcurraddress = cmd(W)
         / handle.NYI,  -- will never be
     getticks = cmd(W)
         / "%1=_gv.getticks()",
     gettimedate = cmd(W,W,W,W,W,W,W,W)
         / "%1,%2,%3,%4,%5,%6,%7,%8=_con._gettimedate()",
-
-    setaspect = cmd(R,R),
 }
 
 local Cif = {
@@ -1937,7 +1956,8 @@ local Cif = {
         / function (...) return format("_con._ifp(%d,_pli,_aci)", bit.bor(...)) end,
     ifsquished = cmd()
         / "false",  -- TODO
-    ifserver = cmd(),
+    ifserver = cmd()
+        / "false",  -- TODO_MP
     ifrespawn = cmd()
         / format("_con._checkrespawn(%s)", SPS""),
     ifoutside = cmd()
@@ -1963,7 +1983,8 @@ local Cif = {
         / "_con._testkey(_pli,29)",  -- XXX
     ifdead = cmd()
         / SPS".extra<=0",
-    ifclient = cmd(),
+    ifclient = cmd()
+        / "false",  -- TODO_MP
     ifcanshoottarget = cmd()
         / "_con._canshoottarget(_dist,_aci)",
     ifcanseetarget = cmd()  -- XXX: 1536 is SLEEPTIME
diff --git a/polymer/eduke32/source/lunatic/test.elua b/polymer/eduke32/source/lunatic/test.elua
index 43f1e816a..966be30ba 100644
--- a/polymer/eduke32/source/lunatic/test.elua
+++ b/polymer/eduke32/source/lunatic/test.elua
@@ -311,9 +311,9 @@ gameevent(gv.EVENT_ENTERLEVEL,
               -- N=10: 190-210 us * 10 = 1.9-2.1 ms
               -- N=100: about 160 us * 100 = about 16 ms
 
-              -- Make the DUKECAR in E1L1 into a static object
+              -- Make the DUKECAR in E1L1 into a zombie actor (temporarily)
               if (sprite[24].picnum==2491) then
-                  sprite.changestat(24, gv.STAT_DEFAULT)
+                  sprite.changestat(24, gv.STAT_ZOMBIEACTOR)
               end
 
               checkfail("gameevent('GAME', function() print('qwe') end)",
@@ -321,6 +321,25 @@ gameevent(gv.EVENT_ENTERLEVEL,
           end
          )
 
+local geom = require "geom"
+
+gameevent("LOADACTOR", function(i)
+    local spr = sprite[i]
+    if (i==614 and spr.picnum==930) then
+        -- "police line" ribbon in E1L1
+        -- clear the hitag so that it doesn't spawn as FALLER from premap
+        spr.hitag = 0
+    end
+end)
+
+gameactor(930, 1, function(i)  -- "police line" ribbon
+    local spr = sprite[i]
+    local r = math.random
+    local d = 20
+    local v = geom.tovec3(spr) + geom.vec3(r(-d,d), r(-d,d))
+    spr:setpos(v)
+end)
+
 local stat = require("stat")
 local hs = stat.new()
 
diff --git a/polymer/eduke32/source/premap.c b/polymer/eduke32/source/premap.c
index aeb8f7988..8aab2a3a9 100644
--- a/polymer/eduke32/source/premap.c
+++ b/polymer/eduke32/source/premap.c
@@ -1120,6 +1120,22 @@ static inline void prelevel(char g)
         }
     }
 
+#ifdef LUNATIC
+    if (g_testLua)
+    {
+        if (L_IsInitialized(&g_ElState))
+        {
+            i = L_RunOnce(&g_ElState, "test.elua");
+            if (i)
+                OSD_Printf(OSD_ERROR "Error running the test ELua script (code %d)\n", i);
+            else
+                initprintf("ELua test script run ok!\n");
+        }
+        else
+            initprintf("ELua test script: not inited!\n");
+    }
+#endif
+
     i = headspritestat[STAT_DEFAULT];
     while (i >= 0)
     {
@@ -1391,22 +1407,6 @@ static inline void prelevel(char g)
                 wall[j].pal = 4;
         }
     }
-
-#ifdef LUNATIC
-    if (g_testLua)
-    {
-        if (L_IsInitialized(&g_ElState))
-        {
-            i = L_RunOnce(&g_ElState, "test.elua");
-            if (i)
-                OSD_Printf(OSD_ERROR "Error running the test ELua script (code %d)\n", i);
-            else
-                initprintf("ELua test script run ok!\n");
-        }
-        else
-            initprintf("ELua test script: not inited!\n");
-    }
-#endif
 }