Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Hanicef/SRB2Classic
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Jisk/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
118 results
Show changes
Commits on Source (92)
...@@ -104,6 +104,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 ...@@ -104,6 +104,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
lua_hudlib_drawlist.c lua_hudlib_drawlist.c
lua_colorlib.c lua_colorlib.c
lua_inputlib.c lua_inputlib.c
lua_interceptlib.c
) )
# This updates the modification time for comptime.c at the # This updates the modification time for comptime.c at the
......
...@@ -98,3 +98,4 @@ lua_hudlib.c ...@@ -98,3 +98,4 @@ lua_hudlib.c
lua_hudlib_drawlist.c lua_hudlib_drawlist.c
lua_inputlib.c lua_inputlib.c
lua_colorlib.c lua_colorlib.c
lua_interceptlib.c
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "m_menu.h" #include "m_menu.h"
#include "filesrch.h" #include "filesrch.h"
#include "m_misc.h" #include "m_misc.h"
#include "lua_libs.h"
#ifdef _WINDOWS #ifdef _WINDOWS
#include "win32/win_main.h" #include "win32/win_main.h"
...@@ -918,6 +919,22 @@ static void CON_InputDelChar(void) ...@@ -918,6 +919,22 @@ static void CON_InputDelChar(void)
// ---- // ----
// //
//
// Same as CON_Responder, but is process before everything else, so it cannot be blocked.
//
boolean CON_PreResponder(event_t *ev)
{
if (ev->type == ev_keydown && shiftdown == 1 && ev->key == KEY_ESCAPE)
{
I_SetTextInputMode(con_destlines == 0 ? true : textinputmodeenabledbylua); // inverse, since this is changed next tic.
consoletoggle = true;
return true;
}
return false;
}
//
// Handles console key input // Handles console key input
// //
boolean CON_Responder(event_t *ev) boolean CON_Responder(event_t *ev)
...@@ -957,7 +974,7 @@ boolean CON_Responder(event_t *ev) ...@@ -957,7 +974,7 @@ boolean CON_Responder(event_t *ev)
if (con_destlines == 0 && I_GetTextInputMode()) if (con_destlines == 0 && I_GetTextInputMode())
return false; // some other component is holding keyboard input, don't hijack it! return false; // some other component is holding keyboard input, don't hijack it!
I_SetTextInputMode(con_destlines == 0); // inverse, since this is changed next tic. I_SetTextInputMode(con_destlines == 0 ? true : textinputmodeenabledbylua); // inverse, since this is changed next tic.
consoletoggle = true; consoletoggle = true;
return true; return true;
} }
...@@ -977,7 +994,7 @@ boolean CON_Responder(event_t *ev) ...@@ -977,7 +994,7 @@ boolean CON_Responder(event_t *ev)
// escape key toggle off console // escape key toggle off console
if (key == KEY_ESCAPE) if (key == KEY_ESCAPE)
{ {
I_SetTextInputMode(false); I_SetTextInputMode(textinputmodeenabledbylua);
consoletoggle = true; consoletoggle = true;
return true; return true;
} }
......
...@@ -19,6 +19,7 @@ void CON_Init(void); ...@@ -19,6 +19,7 @@ void CON_Init(void);
void CON_StartRefresh(void); void CON_StartRefresh(void);
void CON_StopRefresh(void); void CON_StopRefresh(void);
boolean CON_PreResponder(event_t *ev);
boolean CON_Responder(event_t *ev); boolean CON_Responder(event_t *ev);
#ifdef HAVE_THREADS #ifdef HAVE_THREADS
......
...@@ -227,6 +227,9 @@ void D_ProcessEvents(void) ...@@ -227,6 +227,9 @@ void D_ProcessEvents(void)
} }
} }
if (CON_PreResponder(ev))
continue;
// Screenshots over everything so that they can be taken anywhere. // Screenshots over everything so that they can be taken anywhere.
if (M_ScreenshotResponder(ev)) if (M_ScreenshotResponder(ev))
continue; // ate the event continue; // ate the event
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "g_game.h" // Joystick axes (for lua) #include "g_game.h" // Joystick axes (for lua)
#include "i_joy.h" #include "i_joy.h"
#include "g_input.h" // Game controls (for lua) #include "g_input.h" // Game controls (for lua)
#include "p_maputl.h" // P_PathTraverse constants (for lua)
#include "deh_tables.h" #include "deh_tables.h"
...@@ -5829,6 +5830,11 @@ struct int_const_s const INT_CONST[] = { ...@@ -5829,6 +5830,11 @@ struct int_const_s const INT_CONST[] = {
{"MB_BUTTON8",MB_BUTTON8}, {"MB_BUTTON8",MB_BUTTON8},
{"MB_SCROLLUP",MB_SCROLLUP}, {"MB_SCROLLUP",MB_SCROLLUP},
{"MB_SCROLLDOWN",MB_SCROLLDOWN}, {"MB_SCROLLDOWN",MB_SCROLLDOWN},
// P_PathTraverse constants
{"PT_ADDLINES",PT_ADDLINES},
{"PT_ADDTHINGS",PT_ADDTHINGS},
{"PT_EARLYOUT",PT_EARLYOUT},
// screen.h constants // screen.h constants
{"BASEVIDWIDTH",BASEVIDWIDTH}, {"BASEVIDWIDTH",BASEVIDWIDTH},
......
...@@ -598,43 +598,76 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, ...@@ -598,43 +598,76 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// Fills a box of pixels using a flat texture as a pattern // Fills a box of pixels using a flat texture as a pattern
// Fixed to properly align like the other draw functions -luigi budd
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum) void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum)
{ {
FOutVector v[4]; FOutVector v[4];
const size_t len = W_LumpLength(flatlumpnum); const size_t len = W_LumpLength(flatlumpnum);
UINT16 flatflag = R_GetFlatSize(len) - 1; UINT16 flatflag = R_GetFlatSize(len);
double dflatsize = (double)(flatflag + 1); double dflatsize = (double)(flatflag);
// compilers are COOL!
float dup = (float)vid.dup;
float fx = (float)x * dup;
float fy = (float)y * dup;
float fw = (float)w * dup;
float fh = (float)h * dup;
/*
fx *= dup;
fy *= dup;
fw *= dup;
fh *= dup;
*/
if (fw <= 0 || fh <= 0)
return;
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * vid.dup) > 1.0E-36f)
{
fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 2;
}
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * vid.dup) > 1.0E-36f)
{
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 2;
}
if (fx >= vid.width || fy >= vid.height)
return;
fx = -1.0f + (fx / (vid.width / 2.0f));
fy = 1.0f - (fy / (vid.height / 2.0f));
fw /= vid.width / 2;
fh /= vid.height / 2;
// 3--2 // 3--2
// | /| // | /|
// |/ | // |/ |
// 0--1 // 0--1
// position vertices
v[0].x = v[3].x = fx;
v[2].x = v[1].x = fx + fw;
v[0].x = v[3].x = (x - 160.0f)/160.0f; v[0].y = v[1].y = fy;
v[2].x = v[1].x = ((x+w) - 160.0f)/160.0f; v[2].y = v[3].y = fy - fh;
v[0].y = v[1].y = -(y - 100.0f)/100.0f;
v[2].y = v[3].y = -((y+h) - 100.0f)/100.0f;
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
v[0].s = v[3].s = (float)((x & flatflag)/dflatsize); // sides
v[2].s = v[1].s = (float)(v[0].s + w/dflatsize); v[0].s = v[3].s = (float)(flatflag/dflatsize) * 2;
v[0].t = v[1].t = (float)((y & flatflag)/dflatsize); v[2].s = v[1].s = (float)(v[0].s + w/dflatsize) * 2;
v[2].t = v[3].t = (float)(v[0].t + h/dflatsize);
HWR_GetRawFlat(flatlumpnum); // top/bottom
v[0].t = v[1].t = (float)(flatflag/dflatsize) * 2;
v[2].t = v[3].t = (float)(v[0].t + h/dflatsize) * 2;
//Hurdler: Boris, the same comment as above... but maybe for pics // needed to texture the poly
// it not a problem since they don't have any transparent pixel HWR_GetRawFlat(flatlumpnum);
// if I'm right !?
// BTW, I see we put 0 for PFs, and If I'm right, that
// means we take the previous PFs as default
// how can we be sure they are ok?
HWD.pfnDrawPolygon(NULL, v, 4, PF_NoDepthTest); //PF_Translucent); HWD.pfnDrawPolygon(NULL, v, 4, PF_NoDepthTest); //PF_Translucent);
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// Fade down the screen so that the menu drawn on top of it looks brighter // Fade down the screen so that the menu drawn on top of it looks brighter
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
......
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include "lua_hud.h" #include "lua_hud.h"
#include "lua_hudlib_drawlist.h" #include "lua_hudlib_drawlist.h"
#include "lua_hook.h" #include "lua_hook.h"
#include "lua_libs.h"
// coords are scaled // coords are scaled
#define HU_INPUTX 0 #define HU_INPUTX 0
...@@ -395,8 +396,11 @@ void HU_AddChatText(const char *text, boolean playsound) ...@@ -395,8 +396,11 @@ void HU_AddChatText(const char *text, boolean playsound)
if (OLDCHAT) // if we're using oldchat, print directly in console if (OLDCHAT) // if we're using oldchat, print directly in console
CONS_Printf("%s\n", text); CONS_Printf("%s\n", text);
else // if we aren't, still save the message to log.txt else // if we aren't, still save the message to log.txt
CON_LogMessage(va("%s\n", text)); {
CON_LogMessage(text);
CON_LogMessage("\n"); // Add newline. Don't use va for that, since `text` might be refering to va's buffer itself
}
} }
/** Runs a say command, sending an ::XD_SAY message. /** Runs a say command, sending an ::XD_SAY message.
...@@ -1013,7 +1017,7 @@ static void HU_sendChatMessage(void) ...@@ -1013,7 +1017,7 @@ static void HU_sendChatMessage(void)
void HU_clearChatChars(void) void HU_clearChatChars(void)
{ {
memset(w_chat, '\0', sizeof(w_chat)); memset(w_chat, '\0', sizeof(w_chat));
I_SetTextInputMode(false); I_SetTextInputMode(textinputmodeenabledbylua);
chat_on = false; chat_on = false;
c_input = 0; c_input = 0;
...@@ -1150,7 +1154,7 @@ boolean HU_Responder(event_t *ev) ...@@ -1150,7 +1154,7 @@ boolean HU_Responder(event_t *ev)
if (!CHAT_MUTE) if (!CHAT_MUTE)
HU_sendChatMessage(); HU_sendChatMessage();
I_SetTextInputMode(false); I_SetTextInputMode(textinputmodeenabledbylua);
chat_on = false; chat_on = false;
c_input = 0; // reset input cursor c_input = 0; // reset input cursor
chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :) chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :)
...@@ -1161,7 +1165,7 @@ boolean HU_Responder(event_t *ev) ...@@ -1161,7 +1165,7 @@ boolean HU_Responder(event_t *ev)
|| c == gamecontrol[GC_TEAMKEY][0] || c == gamecontrol[GC_TEAMKEY][1]) || c == gamecontrol[GC_TEAMKEY][0] || c == gamecontrol[GC_TEAMKEY][1])
&& c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle. && c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle.
{ {
I_SetTextInputMode(false); I_SetTextInputMode(textinputmodeenabledbylua);
chat_on = false; chat_on = false;
c_input = 0; // reset input cursor c_input = 0; // reset input cursor
I_UpdateMouseGrab(); I_UpdateMouseGrab();
......
...@@ -240,6 +240,8 @@ static const struct { ...@@ -240,6 +240,8 @@ static const struct {
{META_KEYEVENT, "keyevent_t"}, {META_KEYEVENT, "keyevent_t"},
{META_TEXTEVENT, "textevent_t"}, {META_TEXTEVENT, "textevent_t"},
{META_MOUSE, "mouse_t"}, {META_MOUSE, "mouse_t"},
{META_INTERCEPT, "intercept_t"},
{NULL, NULL} {NULL, NULL}
}; };
......
...@@ -467,7 +467,23 @@ static int libd_patchExists(lua_State *L) ...@@ -467,7 +467,23 @@ static int libd_patchExists(lua_State *L)
static int libd_cachePatch(lua_State *L) static int libd_cachePatch(lua_State *L)
{ {
LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); const char *name = luaL_checkstring(L, 1);
patch_t *patch = W_CachePatchLongName(name, PU_PATCH);
#ifdef ROTSPRITE
if (lua_isnumber(L, 2))
{
angle_t rollangle = luaL_checkangle(L, 2);
INT32 rot = R_GetRollAngle(rollangle);
if (rot) {
patch_t *rotpatch = Patch_GetRotated(patch, rot, false);
LUA_PushUserdata(L, rotpatch, META_PATCH);
return 1;
}
}
#endif
LUA_PushUserdata(L, patch, META_PATCH);
return 1; return 1;
} }
......
...@@ -1158,6 +1158,7 @@ enum mobjinfo_e ...@@ -1158,6 +1158,7 @@ enum mobjinfo_e
mobjinfo_activesound, mobjinfo_activesound,
mobjinfo_flags, mobjinfo_flags,
mobjinfo_raisestate, mobjinfo_raisestate,
mobjinfo_name,
}; };
const char *const mobjinfo_opt[] = { const char *const mobjinfo_opt[] = {
...@@ -1185,6 +1186,7 @@ const char *const mobjinfo_opt[] = { ...@@ -1185,6 +1186,7 @@ const char *const mobjinfo_opt[] = {
"activesound", "activesound",
"flags", "flags",
"raisestate", "raisestate",
"name",
NULL, NULL,
}; };
...@@ -1199,6 +1201,8 @@ static int mobjinfo_get(lua_State *L) ...@@ -1199,6 +1201,8 @@ static int mobjinfo_get(lua_State *L)
I_Assert(info != NULL); I_Assert(info != NULL);
I_Assert(info >= mobjinfo); I_Assert(info >= mobjinfo);
mobjtype_t id = info-mobjinfo;
switch (field) switch (field)
{ {
case mobjinfo_doomednum: case mobjinfo_doomednum:
...@@ -1273,6 +1277,21 @@ static int mobjinfo_get(lua_State *L) ...@@ -1273,6 +1277,21 @@ static int mobjinfo_get(lua_State *L)
case mobjinfo_raisestate: case mobjinfo_raisestate:
lua_pushinteger(L, info->raisestate); lua_pushinteger(L, info->raisestate);
break; break;
case mobjinfo_name:
if (id < MT_FIRSTFREESLOT)
{
lua_pushstring(L, MOBJTYPE_LIST[id]+3);
return 1;
}
id -= MT_FIRSTFREESLOT;
if (id < NUMMOBJFREESLOTS && FREE_MOBJS[id])
{
lua_pushstring(L, FREE_MOBJS[id]);
return 1;
}
return 0;
default: default:
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1)); I_Assert(lua_istable(L, -1));
......
...@@ -10,16 +10,19 @@ ...@@ -10,16 +10,19 @@
/// \brief input library for Lua scripting /// \brief input library for Lua scripting
#include "doomdef.h" #include "doomdef.h"
#include "doomstat.h"
#include "fastcmp.h" #include "fastcmp.h"
#include "g_input.h" #include "g_input.h"
#include "g_game.h" #include "g_game.h"
#include "hu_stuff.h" #include "hu_stuff.h"
#include "i_system.h" #include "i_system.h"
#include "console.h"
#include "lua_script.h" #include "lua_script.h"
#include "lua_libs.h" #include "lua_libs.h"
boolean mousegrabbedbylua = true; boolean mousegrabbedbylua = true;
boolean textinputmodeenabledbylua = false;
boolean ignoregameinputs = false; boolean ignoregameinputs = false;
/////////////// ///////////////
...@@ -131,13 +134,15 @@ static int lib_getCursorPosition(lua_State *L) ...@@ -131,13 +134,15 @@ static int lib_getCursorPosition(lua_State *L)
static int lib_setTextInputMode(lua_State *L) static int lib_setTextInputMode(lua_State *L)
{ {
I_SetTextInputMode(luaL_checkboolean(L, 1)); textinputmodeenabledbylua = luaL_checkboolean(L, 1);
if (!(menuactive || CON_Ready() || chat_on))
I_SetTextInputMode(textinputmodeenabledbylua);
return 0; return 0;
} }
static int lib_getTextInputMode(lua_State *L) static int lib_getTextInputMode(lua_State *L)
{ {
lua_pushinteger(L, I_GetTextInputMode()); lua_pushinteger(L, textinputmodeenabledbylua);
return 1; return 1;
} }
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2024-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file lua_interceptlib.c
/// \brief intercept library for Lua scripting
#include "doomdef.h"
#include "fastcmp.h"
#include "p_local.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
enum intercept_e {
intercept_valid = 0,
intercept_frac,
intercept_thing,
intercept_line
};
static const char *const intercept_opt[] = {
"valid",
"frac",
"thing",
"line",
NULL};
static int intercept_fields_ref = LUA_NOREF;
static boolean Lua_PathTraverser(intercept_t *in)
{
boolean traverse = false;
I_Assert(in != NULL);
lua_settop(gL, 6);
lua_pushcfunction(gL, LUA_GetErrorMessage);
I_Assert(lua_isfunction(gL, -2));
lua_pushvalue(gL, -2);
LUA_PushUserdata(gL, in, META_INTERCEPT);
LUA_Call(gL, 1, 1, -3);
traverse = lua_toboolean(gL, -1);
lua_pop(gL, 1);
return !traverse; // Stay consistent with the MobjMoveCollide hook
}
static int intercept_get(lua_State *L)
{
intercept_t *in = *((intercept_t **)luaL_checkudata(L, 1, META_INTERCEPT));
enum intercept_e field = Lua_optoption(L, 2, intercept_valid, intercept_fields_ref);
if (!in)
{
if (field == intercept_valid) {
lua_pushboolean(L, 0);
return 1;
}
return luaL_error(L, "accessed intercept_t doesn't exist anymore.");
}
switch(field)
{
case intercept_valid: // valid
lua_pushboolean(L, 1);
return 1;
case intercept_frac:
lua_pushfixed(L, in->frac);
return 1;
case intercept_thing:
if (in->isaline)
return 0;
LUA_PushUserdata(L, in->d.thing, META_MOBJ);
return 1;
case intercept_line:
if (!in->isaline)
return 0;
LUA_PushUserdata(L, in->d.line, META_LINE);
return 1;
}
return 0;
}
static int lib_pPathTraverse(lua_State *L)
{
fixed_t px1 = luaL_checkfixed(L, 1);
fixed_t py1 = luaL_checkfixed(L, 2);
fixed_t px2 = luaL_checkfixed(L, 3);
fixed_t py2 = luaL_checkfixed(L, 4);
INT32 flags = (INT32)luaL_checkinteger(L, 5);
luaL_checktype(L, 6, LUA_TFUNCTION);
NOHUD
INLEVEL
lua_pushboolean(L, P_PathTraverse(px1, py1, px2, py2, flags, Lua_PathTraverser));
return 1;
}
int LUA_InterceptLib(lua_State *L)
{
LUA_RegisterUserdataMetatable(L, META_INTERCEPT, intercept_get, NULL, NULL);
intercept_fields_ref = Lua_CreateFieldTable(L, intercept_opt);
lua_register(L, "P_PathTraverse", lib_pPathTraverse);
return 0;
}
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
extern lua_State *gL; extern lua_State *gL;
extern boolean mousegrabbedbylua; extern boolean mousegrabbedbylua;
extern boolean textinputmodeenabledbylua;
extern boolean ignoregameinputs; extern boolean ignoregameinputs;
#define MUTABLE_TAGS #define MUTABLE_TAGS
...@@ -97,6 +98,8 @@ extern boolean ignoregameinputs; ...@@ -97,6 +98,8 @@ extern boolean ignoregameinputs;
#define META_KEYEVENT "KEYEVENT_T*" #define META_KEYEVENT "KEYEVENT_T*"
#define META_MOUSE "MOUSE_T*" #define META_MOUSE "MOUSE_T*"
#define META_INTERCEPT "INTERCEPT_T*"
boolean luaL_checkboolean(lua_State *L, int narg); boolean luaL_checkboolean(lua_State *L, int narg);
int LUA_EnumLib(lua_State *L); int LUA_EnumLib(lua_State *L);
...@@ -117,3 +120,4 @@ int LUA_BlockmapLib(lua_State *L); ...@@ -117,3 +120,4 @@ int LUA_BlockmapLib(lua_State *L);
int LUA_HudLib(lua_State *L); int LUA_HudLib(lua_State *L);
int LUA_ColorLib(lua_State *L); int LUA_ColorLib(lua_State *L);
int LUA_InputLib(lua_State *L); int LUA_InputLib(lua_State *L);
int LUA_InterceptLib(lua_State *L);
...@@ -62,6 +62,7 @@ static lua_CFunction liblist[] = { ...@@ -62,6 +62,7 @@ static lua_CFunction liblist[] = {
LUA_HudLib, // HUD stuff LUA_HudLib, // HUD stuff
LUA_ColorLib, // general color functions LUA_ColorLib, // general color functions
LUA_InputLib, // inputs LUA_InputLib, // inputs
LUA_InterceptLib, // intercept_t
NULL NULL
}; };
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "p_setup.h" #include "p_setup.h"
#include "f_finale.h" #include "f_finale.h"
#include "lua_hook.h" #include "lua_hook.h"
#include "lua_libs.h"
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_main.h" #include "hardware/hw_main.h"
...@@ -3793,6 +3794,7 @@ void M_ClearMenus(boolean callexitmenufunc) ...@@ -3793,6 +3794,7 @@ void M_ClearMenus(boolean callexitmenufunc)
hidetitlemap = false; hidetitlemap = false;
I_UpdateMouseGrab(); I_UpdateMouseGrab();
I_SetTextInputMode(textinputmodeenabledbylua);
} }
// //
...@@ -11141,37 +11143,11 @@ static INT32 menuRoomIndex = 0; ...@@ -11141,37 +11143,11 @@ static INT32 menuRoomIndex = 0;
static void M_DrawRoomMenu(void) static void M_DrawRoomMenu(void)
{ {
static fixed_t frame = -(12 << FRACBITS);
int dot_frame;
char text[4];
const char *rmotd; const char *rmotd;
const char *waiting_message; const char *waiting_message;
int dots;
if (m_waiting_mode) if (m_waiting_mode)
{ currentMenu->menuitems[0].text = "...";
dot_frame = (int)(frame >> FRACBITS) / 4;
dots = dot_frame + 3;
strcpy(text, " ");
if (dots > 0)
{
if (dot_frame < 0)
dot_frame = 0;
if (dot_frame != 3)
strncpy(&text[dot_frame], "...", min(dots, 3 - dot_frame));
}
frame += renderdeltatics;
while (frame >= (12 << FRACBITS))
frame -= 12 << FRACBITS;
currentMenu->menuitems[0].text = text;
}
// use generic drawer for cursor, items and title // use generic drawer for cursor, items and title
M_DrawGenericMenu(); M_DrawGenericMenu();
......
...@@ -1720,7 +1720,7 @@ char *va(const char *format, ...) ...@@ -1720,7 +1720,7 @@ char *va(const char *format, ...)
static char string[1024]; static char string[1024];
va_start(argptr, format); va_start(argptr, format);
vsprintf(string, format, argptr); vsnprintf(string, 1024, format, argptr);
va_end(argptr); va_end(argptr);
return string; return string;
......
...@@ -127,8 +127,8 @@ perfstatrow_t commoncounter_rows[] = { ...@@ -127,8 +127,8 @@ perfstatrow_t commoncounter_rows[] = {
}; };
perfstatrow_t interpolation_rows[] = { perfstatrow_t interpolation_rows[] = {
{"intpfrc", "Interp frac: ", &ps_interp_frac, PS_TIME}, {"intpfrc", "Interp frac: ", &ps_interp_frac, 0}, // PS_TIME is not applicable here, as it is meant for I_GetPreciseTime
{"intplag", "Interp lag: ", &ps_interp_lag, PS_TIME}, {"intplag", "Interp lag: ", &ps_interp_lag, 0},
{0} {0}
}; };
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2013-2024 by Sonic Team Junior. // Copyright (C) 2013-2025 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -28,6 +28,7 @@ tokenizer_t *Tokenizer_Open(const char *inputString, size_t len, unsigned numTok ...@@ -28,6 +28,7 @@ tokenizer_t *Tokenizer_Open(const char *inputString, size_t len, unsigned numTok
tokenizer->endPos = 0; tokenizer->endPos = 0;
tokenizer->inputLength = 0; tokenizer->inputLength = 0;
tokenizer->inComment = 0; tokenizer->inComment = 0;
tokenizer->stringNeedsEscaping = false;
tokenizer->inString = 0; tokenizer->inString = 0;
tokenizer->get = Tokenizer_Read; tokenizer->get = Tokenizer_Read;
...@@ -92,6 +93,124 @@ static void DetectComment(tokenizer_t *tokenizer, UINT32 *pos) ...@@ -92,6 +93,124 @@ static void DetectComment(tokenizer_t *tokenizer, UINT32 *pos)
tokenizer->inComment = 2; tokenizer->inComment = 2;
} }
// This function detects escape sequences in a string and attempts to convert them.
static size_t EscapeString(char *output, const char *input, size_t inputLength)
{
const char *end = input + inputLength;
size_t i = 0;
while (input < end)
{
char chr = *input++;
if (chr == '\\')
{
chr = *input++;
switch (chr)
{
case 'n':
output[i] = '\n';
i++;
break;
case 't':
output[i] = '\t';
i++;
break;
case '\\':
output[i] = '\\';
i++;
break;
case '"':
output[i] = '\"';
i++;
break;
case 'x': {
int out = 0, c;
int j = 0;
chr = *input++;
for (j = 0; j < 5 && isxdigit(chr); j++)
{
c = ((chr <= '9') ? (chr - '0') : (tolower(chr) - 'a' + 10));
out = (out << 4) | c;
chr = *input++;
}
input--;
switch (j)
{
case 4:
output[i] = (out >> 8) & 0xFF;
i++;
/* FALLTHRU */
case 2:
output[i] = out & 0xFF;
i++;
break;
default:
// TODO: Displaying parsing errors properly will require
// some refactoring of the tokenizer itself. For now,
// this function will silently return an empty string
// if it encounters a malformed escape sequence.
// This situation cannot happen for i.e. UDMF comments,
// so it's okay to do this right now.
// CONS_Alert(CONS_WARNING, "Escape sequence has wrong size\n");
i = 0;
goto done;
}
break;
}
default:
if (isdigit(chr))
{
int out = 0;
int j = 0;
do
{
out = 10*out + (chr - '0');
chr = *input++;
} while (++j < 3 && isdigit(chr));
input--;
if (out > 255)
{
// CONS_Alert(CONS_WARNING, "Escape sequence is too large\n");
i = 0;
goto done;
}
output[i] = out;
i++;
}
else
{
// CONS_Alert(CONS_WARNING, "Unknown escape sequence '\\%c'\n", chr);
i = 0;
goto done;
}
break;
}
}
else
{
output[i] = chr;
i++;
}
}
done:
output[i] = '\0';
i++;
return i;
}
static void Tokenizer_ReadTokenString(tokenizer_t *tokenizer, UINT32 i) static void Tokenizer_ReadTokenString(tokenizer_t *tokenizer, UINT32 i)
{ {
UINT32 tokenLength = tokenizer->endPos - tokenizer->startPos; UINT32 tokenLength = tokenizer->endPos - tokenizer->startPos;
...@@ -101,10 +220,46 @@ static void Tokenizer_ReadTokenString(tokenizer_t *tokenizer, UINT32 i) ...@@ -101,10 +220,46 @@ static void Tokenizer_ReadTokenString(tokenizer_t *tokenizer, UINT32 i)
// Assign the memory. Don't forget an extra byte for the end of the string! // Assign the memory. Don't forget an extra byte for the end of the string!
tokenizer->token[i] = (char *)Z_Malloc(tokenizer->capacity[i] * sizeof(char), PU_STATIC, NULL); tokenizer->token[i] = (char *)Z_Malloc(tokenizer->capacity[i] * sizeof(char), PU_STATIC, NULL);
} }
// Copy the string. // Copy the string.
M_Memcpy(tokenizer->token[i], tokenizer->input + tokenizer->startPos, (size_t)tokenLength); if (tokenizer->stringNeedsEscaping)
// Make the final character NUL. {
tokenizer->token[i][tokenLength] = '\0'; EscapeString(tokenizer->token[i], tokenizer->input + tokenizer->startPos, (size_t)tokenLength);
}
else
{
M_Memcpy(tokenizer->token[i], tokenizer->input + tokenizer->startPos, (size_t)tokenLength);
// Make the final character NUL.
tokenizer->token[i][tokenLength] = '\0';
}
}
static void ScanString(tokenizer_t *tokenizer)
{
tokenizer->stringNeedsEscaping = false;
while (tokenizer->input[tokenizer->endPos] != '"' && tokenizer->endPos < tokenizer->inputLength)
{
if (!DetectLineBreak(tokenizer, tokenizer->endPos))
{
// Skip one character ahead if this looks like an escape sequence
if (tokenizer->input[tokenizer->endPos] == '\\')
{
tokenizer->stringNeedsEscaping = true;
tokenizer->endPos++;
// Oh. Naughty. We hit the end of the input.
// Stop scanning, then.
if (tokenizer->endPos == tokenizer->inputLength)
return;
DetectLineBreak(tokenizer, tokenizer->endPos);
}
}
tokenizer->endPos++;
}
} }
const char *Tokenizer_Read(tokenizer_t *tokenizer, UINT32 i) const char *Tokenizer_Read(tokenizer_t *tokenizer, UINT32 i)
...@@ -117,11 +272,7 @@ const char *Tokenizer_Read(tokenizer_t *tokenizer, UINT32 i) ...@@ -117,11 +272,7 @@ const char *Tokenizer_Read(tokenizer_t *tokenizer, UINT32 i)
// If in a string, return the entire string within quotes, except without the quotes. // If in a string, return the entire string within quotes, except without the quotes.
if (tokenizer->inString == 1) if (tokenizer->inString == 1)
{ {
while (tokenizer->input[tokenizer->endPos] != '"' && tokenizer->endPos < tokenizer->inputLength) ScanString(tokenizer);
{
DetectLineBreak(tokenizer, tokenizer->endPos);
tokenizer->endPos++;
}
Tokenizer_ReadTokenString(tokenizer, i); Tokenizer_ReadTokenString(tokenizer, i);
tokenizer->inString = 2; tokenizer->inString = 2;
...@@ -134,6 +285,7 @@ const char *Tokenizer_Read(tokenizer_t *tokenizer, UINT32 i) ...@@ -134,6 +285,7 @@ const char *Tokenizer_Read(tokenizer_t *tokenizer, UINT32 i)
tokenizer->token[i][0] = tokenizer->input[tokenizer->startPos]; tokenizer->token[i][0] = tokenizer->input[tokenizer->startPos];
tokenizer->token[i][1] = '\0'; tokenizer->token[i][1] = '\0';
tokenizer->inString = 0; tokenizer->inString = 0;
tokenizer->stringNeedsEscaping = false;
return tokenizer->token[i]; return tokenizer->token[i];
} }
...@@ -281,11 +433,7 @@ const char *Tokenizer_SRB2Read(tokenizer_t *tokenizer, UINT32 i) ...@@ -281,11 +433,7 @@ const char *Tokenizer_SRB2Read(tokenizer_t *tokenizer, UINT32 i)
else if (tokenizer->input[tokenizer->startPos] == '"') else if (tokenizer->input[tokenizer->startPos] == '"')
{ {
tokenizer->endPos = ++tokenizer->startPos; tokenizer->endPos = ++tokenizer->startPos;
while (tokenizer->input[tokenizer->endPos] != '"' && tokenizer->endPos < tokenizer->inputLength) ScanString(tokenizer);
{
DetectLineBreak(tokenizer, tokenizer->endPos);
tokenizer->endPos++;
}
Tokenizer_ReadTokenString(tokenizer, i); Tokenizer_ReadTokenString(tokenizer, i);
tokenizer->endPos++; tokenizer->endPos++;
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 2013-2024 by Sonic Team Junior. // Copyright (C) 2013-2025 by Sonic Team Junior.
// //
// This program is free software distributed under the // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -26,6 +26,7 @@ typedef struct Tokenizer ...@@ -26,6 +26,7 @@ typedef struct Tokenizer
UINT32 inputLength; UINT32 inputLength;
UINT8 inComment; // 0 = not in comment, 1 = // Single-line, 2 = /* Multi-line */ UINT8 inComment; // 0 = not in comment, 1 = // Single-line, 2 = /* Multi-line */
UINT8 inString; // 0 = not in string, 1 = in string, 2 = just left string UINT8 inString; // 0 = not in string, 1 = in string, 2 = just left string
boolean stringNeedsEscaping;
int line; int line;
const char *(*get)(struct Tokenizer*, UINT32); const char *(*get)(struct Tokenizer*, UINT32);
} tokenizer_t; } tokenizer_t;
......