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
Select Git revision
  • 21-installer-nodd
  • 2210-pre1
  • 2210-pre2
  • 2210-rc1
  • 2210-rc2
  • 2210-rc3
  • 2211-pre1
  • 2211-pre2
  • 2211-rc1
  • 2212-pre1
  • 2212-pre2
  • 2212-pre3
  • 2212-rc1
  • 2213
  • 2214-pre1
  • 2214-pre2
  • 2214-pre3
  • 2214-pre4
  • 2_2_12
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • acs
  • action-args
  • alpha-fixes
  • any-resolution
  • appveyor
  • blend-locking
  • blentran
  • blua-unary-not-fix
  • boost-tickrate
  • bustablesoundz
  • cleanup-opengl
  • cleanupmusic
  • clipmidtex
  • cmake-valgrind
  • crawlacommander-sprites
  • custom-map-names
  • custom-teams
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delfile2
  • deprecate-lua-dedicated-server
  • dpl-2
  • dropshadows-spawning
  • dynabsp
  • emblem-drawing
  • exchndl-xp-fix
  • extra-textures
  • few-kart-lua-changes
  • ffloorclip
  • fix-167
  • fix-cvar-conflicts
  • fix-opengl-parameter-crash
  • fix-opengl-shear-roll
  • flipfuncpointers
  • fof-lightlist-fixes
  • font-FUCK
  • frictionrefactor
  • fuck-macros-1
  • gamepad-luakeydown
  • gamepad-morefixes
  • gamepad_experiments
  • gametype-refactor
  • gametype-refactor-1
  • gametype-refactor-player-spawns
  • ghost-networking
  • gif-splitting
  • grr-lj
  • hitboxviewer
  • hwr-texture-cache-refactor
  • hwrender2
  • improve-439
  • increase-maxconditionsets
  • increase-packet-tics
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • just-in-case
  • keycodes-only
  • ksf-wadfiles
  • ld413-mp-fix
  • levelstruct
  • libpng-version-support
  • linedef-actions
  • lj-test
  • lol-states
  • loopedsounds
  • lower-unpegged-fix
  • lua-change-gametype
  • lua-command-netids
  • lua-gfx-2
  • lua-gfx-sprites
  • lua-local
  • makefile-auto-mingw-gcc
  • makefile-tinkering
  • map-components-signedness-fixes
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.12
  • SRB2_release_2.2.13
  • SRB2_release_2.2.15
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
142 results

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
  • 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
  • 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
  • BlueStaggo/SRB2
  • Jisk/srb-2-beef-jerky
  • voltybystorm/SRB2
  • ZenithNeko/srb-2-xp
  • Nep2Disk/SRB2
  • Cloudeon/SRB2
  • mushe/srb-2-ps-b
  • GlassCanonLover77/SRB2
  • PAS/SRB2
  • nothingjust752/SRB2
  • yusufali1009/srb-2-zintaru
  • PacolaYes/SRB2
126 results
Select Git revision
  • fix-opengl-black-background-color
  • fix-player-ping-being-writeable
  • fix-soundplay-fix
  • mobj-gravity-field
  • next
  • port-namechange-srb2classic
  • reconsider-usable-by-lua
  • restore-timeout-fix-from-hanicef
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.12
  • SRB2_release_2.2.13
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
49 results
Show changes
Showing with 5199 additions and 3743 deletions
......@@ -2671,7 +2671,7 @@ fixed_t *hwbbox;
static void HWR_RenderBSPNode(INT32 bspnum)
{
node_t *bsp;
bspnode_t *bsp;
INT32 side;
ps_numbspcalls.value.i++;
......@@ -3137,7 +3137,13 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
if (!occlusion) use_linkdraw_hack = true;
}
Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha);
if (cv_translucency.value && newalpha < FRACUNIT)
{
// TODO: The ternary operator is a hack to make alpha values roughly match what their FF_TRANSMASK equivalent would be
// See if there's a better way of doing this
Surf.PolyColor.s.alpha = min(FixedMul(newalpha, Surf.PolyColor.s.alpha == 0xFF ? 256 : Surf.PolyColor.s.alpha), 0xFF);
blend = HWR_GetBlendModeFlag(blendmode);
}
if (HWR_UseShader())
{
......@@ -3168,7 +3174,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
if (h <= temp)
{
if (!lightset)
lightlevel = *list[i-1].lightlevel > 255 ? 255 : *list[i-1].lightlevel;
lightlevel = max(min(*list[i-1].lightlevel, 255), 0);
if (!(spr->mobj->renderflags & RF_NOCOLORMAPS))
colormap = *list[i-1].extra_colormap;
break;
......@@ -3187,7 +3193,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
if (!(list[i].flags & FOF_NOSHADE) && (list[i].flags & FOF_CUTSPRITES))
{
if (!lightset)
lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel;
lightlevel = max(min(*list[i].lightlevel, 255), 0);
if (!(spr->mobj->renderflags & RF_NOCOLORMAPS))
colormap = *list[i].extra_colormap;
}
......@@ -3295,6 +3301,7 @@ static void HWR_DrawBoundingBox(gl_vissprite_t *vis)
{
FOutVector v[24];
FSurfaceInfo Surf = {0};
RGBA_t *palette = HWR_GetTexturePalette();
//
// create a cube (side view)
......@@ -3334,7 +3341,7 @@ static void HWR_DrawBoundingBox(gl_vissprite_t *vis)
v[ 3].y = v[ 4].y = v[ 5].y = v[ 9].y = v[10].y = v[11].y =
v[15].y = v[16].y = v[17].y = v[21].y = v[22].y = v[23].y = vis->gzt; // top
Surf.PolyColor = V_GetColor(R_GetBoundingBoxColor(vis->mobj));
Surf.PolyColor = palette[R_GetBoundingBoxColor(vis->mobj)];
HWR_ProcessPolygon(&Surf, v, 24, (cv_renderhitboxgldepth.value ? 0 : PF_NoDepthTest)|PF_Modulated|PF_NoTexture|PF_WireFrame, SHADER_NONE, false);
}
......@@ -3568,13 +3575,13 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
INT32 light = R_GetPlaneLight(sector, spr->mobj->z, false);
if (!lightset)
lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel;
lightlevel = max(min(*sector->lightlist[light].lightlevel, 255), 0);
if (*sector->lightlist[light].extra_colormap && !(spr->mobj->renderflags & RF_NOCOLORMAPS))
colormap = *sector->lightlist[light].extra_colormap;
}
else if (!lightset)
lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
lightlevel = max(min(sector->lightlevel, 255), 0);
if (R_ThingIsSemiBright(spr->mobj))
lightlevel = 128 + (lightlevel>>1);
......@@ -3632,7 +3639,13 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
if (!occlusion) use_linkdraw_hack = true;
}
Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha);
if (cv_translucency.value && newalpha < FRACUNIT)
{
// TODO: The ternary operator is a hack to make alpha values roughly match what their FF_TRANSMASK equivalent would be
// See if there's a better way of doing this
Surf.PolyColor.s.alpha = min(FixedMul(newalpha, Surf.PolyColor.s.alpha == 0xFF ? 256 : Surf.PolyColor.s.alpha), 0xFF);
blend = HWR_GetBlendModeFlag(blendmode);
}
if (spr->renderflags & RF_SHADOWEFFECTS)
{
......@@ -5290,7 +5303,7 @@ static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean
//
static void HWR_SetShaderState(void)
{
HWD.pfnSetSpecialState(HWD_SET_SHADERS, (INT32)HWR_UseShader());
HWD.pfnSetSpecialState(HWD_SET_SHADERS, HWR_UseShader());
}
static void HWR_SetupView(player_t *player, INT32 viewnumber, float fpov, boolean skybox)
......
......@@ -1319,7 +1319,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
else if (R_ThingIsSemiBright(spr->mobj))
lightlevel = 128 + (*sector->lightlist[light].lightlevel>>1);
else if (!R_ThingIsFullBright(spr->mobj))
lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel;
lightlevel = max(min(255, *sector->lightlist[light].lightlevel), 0);
if (*sector->lightlist[light].extra_colormap)
colormap = *sector->lightlist[light].extra_colormap;
......@@ -1331,7 +1331,7 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
else if (R_ThingIsSemiBright(spr->mobj))
lightlevel = 128 + (sector->lightlevel>>1);
else if (!R_ThingIsFullBright(spr->mobj))
lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
lightlevel = max(min(255, sector->lightlevel), 0);
if (sector->extra_colormap)
colormap = sector->extra_colormap;
......@@ -1389,7 +1389,12 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
Surf.PolyFlags = HWR_GetBlendModeFlag(blendmode);
}
Surf.PolyColor.s.alpha = FixedMul(newalpha, Surf.PolyColor.s.alpha);
if (newalpha < FRACUNIT)
{
// TODO: The ternary operator is a hack to make alpha values roughly match what their FF_TRANSMASK equivalent would be
// See if there's a better way of doing this
Surf.PolyColor.s.alpha = min(FixedMul(newalpha, Surf.PolyColor.s.alpha == 0xFF ? 256 : Surf.PolyColor.s.alpha), 0xFF);
}
// don't forget to enable the depth test because we can't do this
// like before: model polygons are not sorted
......
......@@ -75,7 +75,7 @@ typedef struct mesh_s
typedef struct tag_s
{
char name[64];
// matrix_t transform;
// oldmatrix_t transform;
} tag_t;
#define MODEL_INTERPOLATION_FLAG "+i"
......
......@@ -155,23 +155,24 @@ static const GLfloat byte2float[256] = {
// -----------------+
#ifdef DEBUG_TO_FILE
FILE *gllogstream;
FILE *gllogstream = NULL;
#endif
FUNCPRINTF void GL_DBG_Printf(const char *format, ...)
{
#ifdef DEBUG_TO_FILE
char str[4096] = "";
va_list arglist;
if (!gllogstream)
gllogstream = fopen("ogllog.txt", "w");
if (gllogstream)
{
va_start(arglist, format);
vsnprintf(str, 4096, format, arglist);
va_end(arglist);
fwrite(str, strlen(str), 1, gllogstream);
}
#else
(void)format;
#endif
......@@ -227,7 +228,6 @@ FUNCPRINTF static void GL_MSG_Error(const char *format, ...)
/* 1.0 functions */
/* Miscellaneous */
#define pglClearColor glClearColor
//glClear
#define pglColorMask glColorMask
#define pglAlphaFunc glAlphaFunc
#define pglBlendFunc glBlendFunc
......@@ -237,9 +237,7 @@ FUNCPRINTF static void GL_MSG_Error(const char *format, ...)
#define pglEnable glEnable
#define pglDisable glDisable
#define pglGetFloatv glGetFloatv
//glGetIntegerv
//glGetString
#define pglHint glHint
#define pglPolygonMode glPolygonMode
/* Depth Buffer */
#define pglClearDepth glClearDepth
......@@ -283,6 +281,7 @@ FUNCPRINTF static void GL_MSG_Error(const char *format, ...)
/* Texture mapping */
#define pglTexEnvi glTexEnvi
#define pglTexParameteri glTexParameteri
#define pglTexImage1D glTexImage1D
#define pglTexImage2D glTexImage2D
#define pglTexSubImage2D glTexSubImage2D
......@@ -668,6 +667,7 @@ void SetupGLFunc4(void)
{
/* 1.2 funcs */
pglTexImage3D = GetGLFunc("glTexImage3D");
/* 1.3 funcs */
pglActiveTexture = GetGLFunc("glActiveTexture");
pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f");
......
......@@ -378,7 +378,7 @@ static void HU_removeChatText_Log(void)
void HU_AddChatText(const char *text, boolean playsound)
{
if (playsound && cv_consolechat.value != 2) // Don't play the sound if we're using hidden chat.
S_StartSound(NULL, sfx_radio);
S_StartSoundFromEverywhere(sfx_radio);
// reguardless of our preferences, put all of this in the chat buffer in case we decide to change from oldchat mid-game.
if (chat_nummsg_log >= CHAT_BUFSIZE) // too many messages!
......@@ -495,7 +495,7 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
//CONS_Printf("%d\n", target);
// check for target player, if it doesn't exist then we can't send the message!
if (target < MAXPLAYERS && playeringame[target]) // player exists
if (target < MAXPLAYERS && players[target].ingame) // player exists
target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
else
{
......@@ -994,7 +994,7 @@ static void HU_sendChatMessage(void)
target = atoi(playernum); // turn that into a number
// check for target player, if it doesn't exist then we can't send the message!
if (target < MAXPLAYERS && playeringame[target]) // player exists
if (target < MAXPLAYERS && players[target].ingame) // player exists
target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
else
{
......@@ -1566,7 +1566,7 @@ static void HU_DrawChat(void)
if (i != n) continue;
}
if (playeringame[i])
if (players[i].ingame)
{
char name[MAXPLAYERNAME+1];
strlcpy(name, player_names[i], 7); // shorten name to 7 characters.
......@@ -1862,7 +1862,7 @@ void HU_Drawer(void)
//
// HU_drawPing
//
void HU_drawPing(INT32 x, INT32 y, UINT32 ping, boolean notext, INT32 flags)
void HU_drawPing(INT32 x, INT32 y, UINT32 ping, UINT32 pl, boolean notext, INT32 flags)
{
UINT8 numbars = 0; // how many ping bars do we draw?
UINT8 barcolor = 31; // color we use for the bars (green, yellow, red or black)
......@@ -1890,6 +1890,9 @@ void HU_drawPing(INT32 x, INT32 y, UINT32 ping, boolean notext, INT32 flags)
if (ping < UINT32_MAX && (!notext || vid.width >= 640)) // how sad, we're using a shit resolution.
V_DrawSmallString(dx, y+4, V_ALLOWLOWERCASE|flags, va("%dms", ping));
if (pl < UINT32_MAX && (!notext || vid.width >= 640))
V_DrawSmallString(dx, y+8, V_ALLOWLOWERCASE|flags, va("%d%%", pl)); // TODO: this is for testing, make a proper indicator soon
for (i=0; (i<3); i++) // Draw the ping bar
{
V_DrawFill(x+2 *(i-1), y+yoffset-4, 2, 8-yoffset, 31|flags);
......@@ -1928,7 +1931,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I
if (!splitscreen) // don't draw it on splitscreen,
{
if (tab[i].num != serverplayer)
HU_drawPing(x + 253, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], false, 0);
HU_drawPing(x + 253, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], playerpacketlosstable[tab[i].num], false, 0);
//else
// V_DrawSmallString(x+ 246, y+4, V_YELLOWMAP, "SERVER");
}
......@@ -2129,7 +2132,7 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer)
if (!splitscreen)
{
if (tab[i].num != serverplayer)
HU_drawPing(x + 135, y+1, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], true, 0);
HU_drawPing(x + 135, y+1, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], playerpacketlosstable[tab[i].num], true, 0);
//else
//V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
}
......@@ -2254,7 +2257,7 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer)
if (!splitscreen)
{
if (tab[i].num != serverplayer)
HU_drawPing(x+ 113, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], false, 0);
HU_drawPing(x+ 113, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], playerpacketlosstable[tab[i].num], false, 0);
//else
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
}
......@@ -2285,7 +2288,7 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline
strlcpy(name, tab[i].name, 7);
if (tab[i].num != serverplayer)
HU_drawPing(x+ 113, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], false, 0);
HU_drawPing(x+ 113, y, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], playerpacketlosstable[tab[i].num], false, 0);
//else
// V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER");
......@@ -2394,7 +2397,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor
if (!splitscreen) // don't draw it on splitscreen,
{
if (tab[i].num != serverplayer)
HU_drawPing(x+ 135, y+1, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], true, 0);
HU_drawPing(x+ 135, y+1, players[tab[i].num].quittime ? UINT32_MAX : playerpingtable[tab[i].num], playerpacketlosstable[tab[i].num], true, 0);
//else
// V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST");
}
......@@ -2517,14 +2520,14 @@ static inline void HU_DrawSpectatorTicker(void)
int totallength = 0;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].spectator)
if (players[i].ingame && players[i].spectator)
totallength += (signed)strlen(player_names[i]) * 8 + 16;
length -= (leveltime % (totallength + (vid.width / vid.dup)));
length += (vid.width / vid.dup);
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].spectator)
if (players[i].ingame && players[i].spectator)
{
if (length >= -((signed)strlen(player_names[i]) * 8 + 16) && length <= (vid.width / vid.dup))
V_DrawString(length, height + 8, V_TRANSLUCENT|V_ALLOWLOWERCASE|V_SNAPTOLEFT, player_names[i]);
......@@ -2589,7 +2592,7 @@ static void HU_DrawRankings(void)
for (j = 0; j < MAXPLAYERS; j++)
{
if (!playeringame[j])
if (!players[j].ingame)
continue;
if (!G_PlatformGametype() && players[j].spectator)
......@@ -2597,7 +2600,7 @@ static void HU_DrawRankings(void)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
continue;
if (!G_PlatformGametype() && players[i].spectator)
......
......@@ -108,7 +108,7 @@ void HU_Ticker(void);
void HU_Drawer(void);
char HU_dequeueChatChar(void);
void HU_clearChatChars(void);
void HU_drawPing(INT32 x, INT32 y, UINT32 ping, boolean notext, INT32 flags); // Lat': Ping drawer for scoreboard.
void HU_drawPing(INT32 x, INT32 y, UINT32 ping, UINT32 pl, boolean notext, INT32 flags); // Lat': Ping drawer for scoreboard.
void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer);
void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer);
void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer);
......
......@@ -9,20 +9,21 @@
/// \file i_threads.h
/// \brief Multithreading abstraction
#ifdef HAVE_THREADS
#ifndef I_THREADS_H
#define I_THREADS_H
#include "doomtype.h"
typedef void (*I_thread_fn)(void *userdata);
typedef void * I_mutex;
typedef void * I_cond;
int I_can_thread (void) FUNCWARNRV;
void I_start_threads (void);
void I_stop_threads (void);
void I_spawn_thread (const char *name, I_thread_fn, void *userdata);
int I_spawn_thread (const char *name, I_thread_fn, void *userdata) FUNCWARNRV;
/* check in your thread whether to return early */
int I_thread_is_stopped (void);
......@@ -36,4 +37,3 @@ void I_wake_one_cond (I_cond *);
void I_wake_all_cond (I_cond *);
#endif/*I_THREADS_H*/
#endif/*HAVE_THREADS*/
Source diff could not be displayed: it is too large. Options to address this: view the blob.
......@@ -302,274 +302,274 @@ struct mobj_s;
// IMPORTANT NOTE: If you add/remove from this list of action
// functions, don't forget to update them in deh_tables.c!
void A_Explode(struct mobj_s *actor);
void A_Pain(struct mobj_s *actor);
void A_Fall(struct mobj_s *actor);
void A_MonitorPop(struct mobj_s *actor);
void A_GoldMonitorPop(struct mobj_s *actor);
void A_GoldMonitorRestore(struct mobj_s *actor);
void A_GoldMonitorSparkle(struct mobj_s *actor);
void A_Look(struct mobj_s *actor);
void A_Chase(struct mobj_s *actor);
void A_FaceStabChase(struct mobj_s *actor);
void A_FaceStabRev(struct mobj_s *actor);
void A_FaceStabHurl(struct mobj_s *actor);
void A_FaceStabMiss(struct mobj_s *actor);
void A_StatueBurst(struct mobj_s *actor);
void A_FaceTarget(struct mobj_s *actor);
void A_FaceTracer(struct mobj_s *actor);
void A_Scream(struct mobj_s *actor);
void A_BossDeath(struct mobj_s *actor);
void A_SetShadowScale(struct mobj_s *actor);
void A_ShadowScream(struct mobj_s *actor); // MARIA!!!!!!
void A_CustomPower(struct mobj_s *actor); // Use this for a custom power
void A_GiveWeapon(struct mobj_s *actor); // Gives the player weapon(s)
void A_RingBox(struct mobj_s *actor); // Obtained Ring Box Tails
void A_Invincibility(struct mobj_s *actor); // Obtained Invincibility Box
void A_SuperSneakers(struct mobj_s *actor); // Obtained Super Sneakers Box
void A_BunnyHop(struct mobj_s *actor); // have bunny hop tails
void A_BubbleSpawn(struct mobj_s *actor); // Randomly spawn bubbles
void A_FanBubbleSpawn(struct mobj_s *actor);
void A_BubbleRise(struct mobj_s *actor); // Bubbles float to surface
void A_BubbleCheck(struct mobj_s *actor); // Don't draw if not underwater
void A_AwardScore(struct mobj_s *actor);
void A_ExtraLife(struct mobj_s *actor); // Extra Life
void A_GiveShield(struct mobj_s *actor); // Obtained Shield
void A_GravityBox(struct mobj_s *actor);
void A_ScoreRise(struct mobj_s *actor); // Rise the score logo
void A_AttractChase(struct mobj_s *actor); // Ring Chase
void A_DropMine(struct mobj_s *actor); // Drop Mine from Skim or Jetty-Syn Bomber
void A_FishJump(struct mobj_s *actor); // Fish Jump
void A_ThrownRing(struct mobj_s *actor); // Sparkle trail for red ring
void A_SetSolidSteam(struct mobj_s *actor);
void A_UnsetSolidSteam(struct mobj_s *actor);
void A_SignSpin(struct mobj_s *actor);
void A_SignPlayer(struct mobj_s *actor);
void A_OverlayThink(struct mobj_s *actor);
void A_JetChase(struct mobj_s *actor);
void A_JetbThink(struct mobj_s *actor); // Jetty-Syn Bomber Thinker
void A_JetgThink(struct mobj_s *actor); // Jetty-Syn Gunner Thinker
void A_JetgShoot(struct mobj_s *actor); // Jetty-Syn Shoot Function
void A_ShootBullet(struct mobj_s *actor); // JetgShoot without reactiontime setting
void A_MinusDigging(struct mobj_s *actor);
void A_MinusPopup(struct mobj_s *actor);
void A_MinusCheck(struct mobj_s *actor);
void A_ChickenCheck(struct mobj_s *actor);
void A_MouseThink(struct mobj_s *actor); // Mouse Thinker
void A_DetonChase(struct mobj_s *actor); // Deton Chaser
void A_CapeChase(struct mobj_s *actor); // Fake little Super Sonic cape
void A_RotateSpikeBall(struct mobj_s *actor); // Spike ball rotation
void A_SlingAppear(struct mobj_s *actor);
void A_UnidusBall(struct mobj_s *actor);
void A_RockSpawn(struct mobj_s *actor);
void A_SetFuse(struct mobj_s *actor);
void A_CrawlaCommanderThink(struct mobj_s *actor); // Crawla Commander
void A_SmokeTrailer(struct mobj_s *actor);
void A_RingExplode(struct mobj_s *actor);
void A_OldRingExplode(struct mobj_s *actor);
void A_MixUp(struct mobj_s *actor);
void A_RecyclePowers(struct mobj_s *actor);
void A_BossScream(struct mobj_s *actor);
void A_Boss2TakeDamage(struct mobj_s *actor);
void A_GoopSplat(struct mobj_s *actor);
void A_Boss2PogoSFX(struct mobj_s *actor);
void A_Boss2PogoTarget(struct mobj_s *actor);
void A_EggmanBox(struct mobj_s *actor);
void A_TurretFire(struct mobj_s *actor);
void A_SuperTurretFire(struct mobj_s *actor);
void A_TurretStop(struct mobj_s *actor);
void A_JetJawRoam(struct mobj_s *actor);
void A_JetJawChomp(struct mobj_s *actor);
void A_PointyThink(struct mobj_s *actor);
void A_CheckBuddy(struct mobj_s *actor);
void A_HoodFire(struct mobj_s *actor);
void A_HoodThink(struct mobj_s *actor);
void A_HoodFall(struct mobj_s *actor);
void A_ArrowBonks(struct mobj_s *actor);
void A_SnailerThink(struct mobj_s *actor);
void A_SharpChase(struct mobj_s *actor);
void A_SharpSpin(struct mobj_s *actor);
void A_SharpDecel(struct mobj_s *actor);
void A_CrushstaceanWalk(struct mobj_s *actor);
void A_CrushstaceanPunch(struct mobj_s *actor);
void A_CrushclawAim(struct mobj_s *actor);
void A_CrushclawLaunch(struct mobj_s *actor);
void A_VultureVtol(struct mobj_s *actor);
void A_VultureCheck(struct mobj_s *actor);
void A_VultureHover(struct mobj_s *actor);
void A_VultureBlast(struct mobj_s *actor);
void A_VultureFly(struct mobj_s *actor);
void A_SkimChase(struct mobj_s *actor);
void A_SkullAttack(struct mobj_s *actor);
void A_LobShot(struct mobj_s *actor);
void A_FireShot(struct mobj_s *actor);
void A_SuperFireShot(struct mobj_s *actor);
void A_BossFireShot(struct mobj_s *actor);
void A_Boss7FireMissiles(struct mobj_s *actor);
void A_Boss1Laser(struct mobj_s *actor);
void A_FocusTarget(struct mobj_s *actor);
void A_Boss4Reverse(struct mobj_s *actor);
void A_Boss4SpeedUp(struct mobj_s *actor);
void A_Boss4Raise(struct mobj_s *actor);
void A_SparkFollow(struct mobj_s *actor);
void A_BuzzFly(struct mobj_s *actor);
void A_GuardChase(struct mobj_s *actor);
void A_EggShield(struct mobj_s *actor);
void A_SetReactionTime(struct mobj_s *actor);
void A_Boss1Spikeballs(struct mobj_s *actor);
void A_Boss3TakeDamage(struct mobj_s *actor);
void A_Boss3Path(struct mobj_s *actor);
void A_Boss3ShockThink(struct mobj_s *actor);
void A_Shockwave(struct mobj_s *actor);
void A_LinedefExecute(struct mobj_s *actor);
void A_LinedefExecuteFromArg(struct mobj_s *actor);
void A_PlaySeeSound(struct mobj_s *actor);
void A_PlayAttackSound(struct mobj_s *actor);
void A_PlayActiveSound(struct mobj_s *actor);
void A_1upThinker(struct mobj_s *actor);
void A_BossZoom(struct mobj_s *actor); //Unused
void A_Boss1Chase(struct mobj_s *actor);
void A_Boss2Chase(struct mobj_s *actor);
void A_Boss2Pogo(struct mobj_s *actor);
void A_Boss7Chase(struct mobj_s *actor);
void A_BossJetFume(struct mobj_s *actor);
void A_SpawnObjectAbsolute(struct mobj_s *actor);
void A_SpawnObjectRelative(struct mobj_s *actor);
void A_ChangeAngleRelative(struct mobj_s *actor);
void A_ChangeAngleAbsolute(struct mobj_s *actor);
void A_RollAngle(struct mobj_s *actor);
void A_ChangeRollAngleRelative(struct mobj_s *actor);
void A_ChangeRollAngleAbsolute(struct mobj_s *actor);
void A_PlaySound(struct mobj_s *actor);
void A_FindTarget(struct mobj_s *actor);
void A_FindTracer(struct mobj_s *actor);
void A_SetTics(struct mobj_s *actor);
void A_SetRandomTics(struct mobj_s *actor);
void A_ChangeColorRelative(struct mobj_s *actor);
void A_ChangeColorAbsolute(struct mobj_s *actor);
void A_Dye(struct mobj_s *actor);
void A_SetTranslation(struct mobj_s *actor);
void A_MoveRelative(struct mobj_s *actor);
void A_MoveAbsolute(struct mobj_s *actor);
void A_Thrust(struct mobj_s *actor);
void A_ZThrust(struct mobj_s *actor);
void A_SetTargetsTarget(struct mobj_s *actor);
void A_SetObjectFlags(struct mobj_s *actor);
void A_SetObjectFlags2(struct mobj_s *actor);
void A_RandomState(struct mobj_s *actor);
void A_RandomStateRange(struct mobj_s *actor);
void A_StateRangeByAngle(struct mobj_s *actor);
void A_StateRangeByParameter(struct mobj_s *actor);
void A_DualAction(struct mobj_s *actor);
void A_RemoteAction(struct mobj_s *actor);
void A_ToggleFlameJet(struct mobj_s *actor);
void A_OrbitNights(struct mobj_s *actor);
void A_GhostMe(struct mobj_s *actor);
void A_SetObjectState(struct mobj_s *actor);
void A_SetObjectTypeState(struct mobj_s *actor);
void A_KnockBack(struct mobj_s *actor);
void A_PushAway(struct mobj_s *actor);
void A_RingDrain(struct mobj_s *actor);
void A_SplitShot(struct mobj_s *actor);
void A_MissileSplit(struct mobj_s *actor);
void A_MultiShot(struct mobj_s *actor);
void A_InstaLoop(struct mobj_s *actor);
void A_Custom3DRotate(struct mobj_s *actor);
void A_SearchForPlayers(struct mobj_s *actor);
void A_CheckRandom(struct mobj_s *actor);
void A_CheckTargetRings(struct mobj_s *actor);
void A_CheckRings(struct mobj_s *actor);
void A_CheckTotalRings(struct mobj_s *actor);
void A_CheckHealth(struct mobj_s *actor);
void A_CheckRange(struct mobj_s *actor);
void A_CheckHeight(struct mobj_s *actor);
void A_CheckTrueRange(struct mobj_s *actor);
void A_CheckThingCount(struct mobj_s *actor);
void A_CheckAmbush(struct mobj_s *actor);
void A_CheckCustomValue(struct mobj_s *actor);
void A_CheckCusValMemo(struct mobj_s *actor);
void A_SetCustomValue(struct mobj_s *actor);
void A_UseCusValMemo(struct mobj_s *actor);
void A_RelayCustomValue(struct mobj_s *actor);
void A_CusValAction(struct mobj_s *actor);
void A_ForceStop(struct mobj_s *actor);
void A_ForceWin(struct mobj_s *actor);
void A_SpikeRetract(struct mobj_s *actor);
void A_InfoState(struct mobj_s *actor);
void A_Repeat(struct mobj_s *actor);
void A_SetScale(struct mobj_s *actor);
void A_RemoteDamage(struct mobj_s *actor);
void A_HomingChase(struct mobj_s *actor);
void A_TrapShot(struct mobj_s *actor);
void A_VileTarget(struct mobj_s *actor);
void A_VileAttack(struct mobj_s *actor);
void A_VileFire(struct mobj_s *actor);
void A_BrakChase(struct mobj_s *actor);
void A_BrakFireShot(struct mobj_s *actor);
void A_BrakLobShot(struct mobj_s *actor);
void A_NapalmScatter(struct mobj_s *actor);
void A_SpawnFreshCopy(struct mobj_s *actor);
void A_FlickySpawn(struct mobj_s *actor);
void A_FlickyCenter(struct mobj_s *actor);
void A_FlickyAim(struct mobj_s *actor);
void A_FlickyFly(struct mobj_s *actor);
void A_FlickySoar(struct mobj_s *actor);
void A_FlickyCoast(struct mobj_s *actor);
void A_FlickyHop(struct mobj_s *actor);
void A_FlickyFlounder(struct mobj_s *actor);
void A_FlickyCheck(struct mobj_s *actor);
void A_FlickyHeightCheck(struct mobj_s *actor);
void A_FlickyFlutter(struct mobj_s *actor);
void A_FlameParticle(struct mobj_s *actor);
void A_FadeOverlay(struct mobj_s *actor);
void A_Boss5Jump(struct mobj_s *actor);
void A_LightBeamReset(struct mobj_s *actor);
void A_MineExplode(struct mobj_s *actor);
void A_MineRange(struct mobj_s *actor);
void A_ConnectToGround(struct mobj_s *actor);
void A_SpawnParticleRelative(struct mobj_s *actor);
void A_MultiShotDist(struct mobj_s *actor);
void A_WhoCaresIfYourSonIsABee(struct mobj_s *actor);
void A_ParentTriesToSleep(struct mobj_s *actor);
void A_CryingToMomma(struct mobj_s *actor);
void A_CheckFlags2(struct mobj_s *actor);
void A_Boss5FindWaypoint(struct mobj_s *actor);
void A_DoNPCSkid(struct mobj_s *actor);
void A_DoNPCPain(struct mobj_s *actor);
void A_PrepareRepeat(struct mobj_s *actor);
void A_Boss5ExtraRepeat(struct mobj_s *actor);
void A_Boss5Calm(struct mobj_s *actor);
void A_Boss5CheckOnGround(struct mobj_s *actor);
void A_Boss5CheckFalling(struct mobj_s *actor);
void A_Boss5PinchShot(struct mobj_s *actor);
void A_Boss5MakeItRain(struct mobj_s *actor);
void A_Boss5MakeJunk(struct mobj_s *actor);
void A_LookForBetter(struct mobj_s *actor);
void A_Boss5BombExplode(struct mobj_s *actor);
void A_DustDevilThink(struct mobj_s *actor);
void A_TNTExplode(struct mobj_s *actor);
void A_DebrisRandom(struct mobj_s *actor);
void A_TrainCameo(struct mobj_s *actor);
void A_TrainCameo2(struct mobj_s *actor);
void A_CanarivoreGas(struct mobj_s *actor);
void A_KillSegments(struct mobj_s *actor);
void A_SnapperSpawn(struct mobj_s *actor);
void A_SnapperThinker(struct mobj_s *actor);
void A_SaloonDoorSpawn(struct mobj_s *actor);
void A_MinecartSparkThink(struct mobj_s *actor);
void A_ModuloToState(struct mobj_s *actor);
void A_LavafallRocks(struct mobj_s *actor);
void A_LavafallLava(struct mobj_s *actor);
void A_FallingLavaCheck(struct mobj_s *actor);
void A_FireShrink(struct mobj_s *actor);
void A_SpawnPterabytes(struct mobj_s *actor);
void A_PterabyteHover(struct mobj_s *actor);
void A_RolloutSpawn(struct mobj_s *actor);
void A_RolloutRock(struct mobj_s *actor);
void A_DragonbomberSpawn(struct mobj_s *actor);
void A_DragonWing(struct mobj_s *actor);
void A_DragonSegment(struct mobj_s *actor);
void A_ChangeHeight(struct mobj_s *actor);
void A_Explode(void *actor);
void A_Pain(void *actor);
void A_Fall(void *actor);
void A_MonitorPop(void *actor);
void A_GoldMonitorPop(void *actor);
void A_GoldMonitorRestore(void *actor);
void A_GoldMonitorSparkle(void *actor);
void A_Look(void *actor);
void A_Chase(void *actor);
void A_FaceStabChase(void *actor);
void A_FaceStabRev(void *actor);
void A_FaceStabHurl(void *actor);
void A_FaceStabMiss(void *actor);
void A_StatueBurst(void *actor);
void A_FaceTarget(void *actor);
void A_FaceTracer(void *actor);
void A_Scream(void *actor);
void A_BossDeath(void *actor);
void A_SetShadowScale(void *actor);
void A_ShadowScream(void *actor); // MARIA!!!!!!
void A_CustomPower(void *actor); // Use this for a custom power
void A_GiveWeapon(void *actor); // Gives the player weapon(s)
void A_RingBox(void *actor); // Obtained Ring Box Tails
void A_Invincibility(void *actor); // Obtained Invincibility Box
void A_SuperSneakers(void *actor); // Obtained Super Sneakers Box
void A_BunnyHop(void *actor); // have bunny hop tails
void A_BubbleSpawn(void *actor); // Randomly spawn bubbles
void A_FanBubbleSpawn(void *actor);
void A_BubbleRise(void *actor); // Bubbles float to surface
void A_BubbleCheck(void *actor); // Don't draw if not underwater
void A_AwardScore(void *actor);
void A_ExtraLife(void *actor); // Extra Life
void A_GiveShield(void *actor); // Obtained Shield
void A_GravityBox(void *actor);
void A_ScoreRise(void *actor); // Rise the score logo
void A_AttractChase(void *actor); // Ring Chase
void A_DropMine(void *actor); // Drop Mine from Skim or Jetty-Syn Bomber
void A_FishJump(void *actor); // Fish Jump
void A_ThrownRing(void *actor); // Sparkle trail for red ring
void A_SetSolidSteam(void *actor);
void A_UnsetSolidSteam(void *actor);
void A_SignSpin(void *actor);
void A_SignPlayer(void *actor);
void A_OverlayThink(void *actor);
void A_JetChase(void *actor);
void A_JetbThink(void *actor); // Jetty-Syn Bomber Thinker
void A_JetgThink(void *actor); // Jetty-Syn Gunner Thinker
void A_JetgShoot(void *actor); // Jetty-Syn Shoot Function
void A_ShootBullet(void *actor); // JetgShoot without reactiontime setting
void A_MinusDigging(void *actor);
void A_MinusPopup(void *actor);
void A_MinusCheck(void *actor);
void A_ChickenCheck(void *actor);
void A_MouseThink(void *actor); // Mouse Thinker
void A_DetonChase(void *actor); // Deton Chaser
void A_CapeChase(void *actor); // Fake little Super Sonic cape
void A_RotateSpikeBall(void *actor); // Spike ball rotation
void A_SlingAppear(void *actor);
void A_UnidusBall(void *actor);
void A_RockSpawn(void *actor);
void A_SetFuse(void *actor);
void A_CrawlaCommanderThink(void *actor); // Crawla Commander
void A_SmokeTrailer(void *actor);
void A_RingExplode(void *actor);
void A_OldRingExplode(void *actor);
void A_MixUp(void *actor);
void A_RecyclePowers(void *actor);
void A_BossScream(void *actor);
void A_Boss2TakeDamage(void *actor);
void A_GoopSplat(void *actor);
void A_Boss2PogoSFX(void *actor);
void A_Boss2PogoTarget(void *actor);
void A_EggmanBox(void *actor);
void A_TurretFire(void *actor);
void A_SuperTurretFire(void *actor);
void A_TurretStop(void *actor);
void A_JetJawRoam(void *actor);
void A_JetJawChomp(void *actor);
void A_PointyThink(void *actor);
void A_CheckBuddy(void *actor);
void A_HoodFire(void *actor);
void A_HoodThink(void *actor);
void A_HoodFall(void *actor);
void A_ArrowBonks(void *actor);
void A_SnailerThink(void *actor);
void A_SharpChase(void *actor);
void A_SharpSpin(void *actor);
void A_SharpDecel(void *actor);
void A_CrushstaceanWalk(void *actor);
void A_CrushstaceanPunch(void *actor);
void A_CrushclawAim(void *actor);
void A_CrushclawLaunch(void *actor);
void A_VultureVtol(void *actor);
void A_VultureCheck(void *actor);
void A_VultureHover(void *actor);
void A_VultureBlast(void *actor);
void A_VultureFly(void *actor);
void A_SkimChase(void *actor);
void A_SkullAttack(void *actor);
void A_LobShot(void *actor);
void A_FireShot(void *actor);
void A_SuperFireShot(void *actor);
void A_BossFireShot(void *actor);
void A_Boss7FireMissiles(void *actor);
void A_Boss1Laser(void *actor);
void A_FocusTarget(void *actor);
void A_Boss4Reverse(void *actor);
void A_Boss4SpeedUp(void *actor);
void A_Boss4Raise(void *actor);
void A_SparkFollow(void *actor);
void A_BuzzFly(void *actor);
void A_GuardChase(void *actor);
void A_EggShield(void *actor);
void A_SetReactionTime(void *actor);
void A_Boss1Spikeballs(void *actor);
void A_Boss3TakeDamage(void *actor);
void A_Boss3Path(void *actor);
void A_Boss3ShockThink(void *actor);
void A_Shockwave(void *actor);
void A_LinedefExecute(void *actor);
void A_LinedefExecuteFromArg(void *actor);
void A_PlaySeeSound(void *actor);
void A_PlayAttackSound(void *actor);
void A_PlayActiveSound(void *actor);
void A_1upThinker(void *actor);
void A_BossZoom(void *actor); //Unused
void A_Boss1Chase(void *actor);
void A_Boss2Chase(void *actor);
void A_Boss2Pogo(void *actor);
void A_Boss7Chase(void *actor);
void A_BossJetFume(void *actor);
void A_SpawnObjectAbsolute(void *actor);
void A_SpawnObjectRelative(void *actor);
void A_ChangeAngleRelative(void *actor);
void A_ChangeAngleAbsolute(void *actor);
void A_RollAngle(void *actor);
void A_ChangeRollAngleRelative(void *actor);
void A_ChangeRollAngleAbsolute(void *actor);
void A_PlaySound(void *actor);
void A_FindTarget(void *actor);
void A_FindTracer(void *actor);
void A_SetTics(void *actor);
void A_SetRandomTics(void *actor);
void A_ChangeColorRelative(void *actor);
void A_ChangeColorAbsolute(void *actor);
void A_Dye(void *actor);
void A_SetTranslation(void *actor);
void A_MoveRelative(void *actor);
void A_MoveAbsolute(void *actor);
void A_Thrust(void *actor);
void A_ZThrust(void *actor);
void A_SetTargetsTarget(void *actor);
void A_SetObjectFlags(void *actor);
void A_SetObjectFlags2(void *actor);
void A_RandomState(void *actor);
void A_RandomStateRange(void *actor);
void A_StateRangeByAngle(void *actor);
void A_StateRangeByParameter(void *actor);
void A_DualAction(void *actor);
void A_RemoteAction(void *actor);
void A_ToggleFlameJet(void *actor);
void A_OrbitNights(void *actor);
void A_GhostMe(void *actor);
void A_SetObjectState(void *actor);
void A_SetObjectTypeState(void *actor);
void A_KnockBack(void *actor);
void A_PushAway(void *actor);
void A_RingDrain(void *actor);
void A_SplitShot(void *actor);
void A_MissileSplit(void *actor);
void A_MultiShot(void *actor);
void A_InstaLoop(void *actor);
void A_Custom3DRotate(void *actor);
void A_SearchForPlayers(void *actor);
void A_CheckRandom(void *actor);
void A_CheckTargetRings(void *actor);
void A_CheckRings(void *actor);
void A_CheckTotalRings(void *actor);
void A_CheckHealth(void *actor);
void A_CheckRange(void *actor);
void A_CheckHeight(void *actor);
void A_CheckTrueRange(void *actor);
void A_CheckThingCount(void *actor);
void A_CheckAmbush(void *actor);
void A_CheckCustomValue(void *actor);
void A_CheckCusValMemo(void *actor);
void A_SetCustomValue(void *actor);
void A_UseCusValMemo(void *actor);
void A_RelayCustomValue(void *actor);
void A_CusValAction(void *actor);
void A_ForceStop(void *actor);
void A_ForceWin(void *actor);
void A_SpikeRetract(void *actor);
void A_InfoState(void *actor);
void A_Repeat(void *actor);
void A_SetScale(void *actor);
void A_RemoteDamage(void *actor);
void A_HomingChase(void *actor);
void A_TrapShot(void *actor);
void A_VileTarget(void *actor);
void A_VileAttack(void *actor);
void A_VileFire(void *actor);
void A_BrakChase(void *actor);
void A_BrakFireShot(void *actor);
void A_BrakLobShot(void *actor);
void A_NapalmScatter(void *actor);
void A_SpawnFreshCopy(void *actor);
void A_FlickySpawn(void *actor);
void A_FlickyCenter(void *actor);
void A_FlickyAim(void *actor);
void A_FlickyFly(void *actor);
void A_FlickySoar(void *actor);
void A_FlickyCoast(void *actor);
void A_FlickyHop(void *actor);
void A_FlickyFlounder(void *actor);
void A_FlickyCheck(void *actor);
void A_FlickyHeightCheck(void *actor);
void A_FlickyFlutter(void *actor);
void A_FlameParticle(void *actor);
void A_FadeOverlay(void *actor);
void A_Boss5Jump(void *actor);
void A_LightBeamReset(void *actor);
void A_MineExplode(void *actor);
void A_MineRange(void *actor);
void A_ConnectToGround(void *actor);
void A_SpawnParticleRelative(void *actor);
void A_MultiShotDist(void *actor);
void A_WhoCaresIfYourSonIsABee(void *actor);
void A_ParentTriesToSleep(void *actor);
void A_CryingToMomma(void *actor);
void A_CheckFlags2(void *actor);
void A_Boss5FindWaypoint(void *actor);
void A_DoNPCSkid(void *actor);
void A_DoNPCPain(void *actor);
void A_PrepareRepeat(void *actor);
void A_Boss5ExtraRepeat(void *actor);
void A_Boss5Calm(void *actor);
void A_Boss5CheckOnGround(void *actor);
void A_Boss5CheckFalling(void *actor);
void A_Boss5PinchShot(void *actor);
void A_Boss5MakeItRain(void *actor);
void A_Boss5MakeJunk(void *actor);
void A_LookForBetter(void *actor);
void A_Boss5BombExplode(void *actor);
void A_DustDevilThink(void *actor);
void A_TNTExplode(void *actor);
void A_DebrisRandom(void *actor);
void A_TrainCameo(void *actor);
void A_TrainCameo2(void *actor);
void A_CanarivoreGas(void *actor);
void A_KillSegments(void *actor);
void A_SnapperSpawn(void *actor);
void A_SnapperThinker(void *actor);
void A_SaloonDoorSpawn(void *actor);
void A_MinecartSparkThink(void *actor);
void A_ModuloToState(void *actor);
void A_LavafallRocks(void *actor);
void A_LavafallLava(void *actor);
void A_FallingLavaCheck(void *actor);
void A_FireShrink(void *actor);
void A_SpawnPterabytes(void *actor);
void A_PterabyteHover(void *actor);
void A_RolloutSpawn(void *actor);
void A_RolloutRock(void *actor);
void A_DragonbomberSpawn(void *actor);
void A_DragonWing(void *actor);
void A_DragonSegment(void *actor);
void A_ChangeHeight(void *actor);
extern int actionsoverridden[NUMACTIONS][MAX_ACTION_RECURSION];
......@@ -4410,7 +4410,7 @@ typedef struct
spritenum_t sprite;
UINT32 frame; // we use the upper 16 bits for translucency and other shade effects
INT32 tics;
actionf_t action;
actionf_p1 action;
INT32 var1;
INT32 var2;
statenum_t nextstate;
......
#define LONESHA256_IMPLEMENTATION
#include "lonesha256.h"
/*
lonesha256.h - Portable, endian-proof, single-file, single-function sha256 implementation, originally based on LibTomCrypt
To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring
rights to this software to the public domain worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along with this software.
If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
/*
lonesha256 supports the following three configurations:
#define LONESHA256_EXTERN
Default, should be used when using lonesha256 in multiple compilation units within the same project.
#define LONESHA256_IMPLEMENTATION
Must be defined in exactly one source file within a project for lonesha256 to be found by the linker.
#define LONESHA256_STATIC
Defines the lonesha256() function as static, useful if lonesha256 is only used in a single compilation unit.
lonesha256 function:
(static|extern) int lonesha256 (unsigned char out[32], const unsigned char* in, size_t len)
writes the sha256 hash of the first "len" bytes in buffer "in" to buffer "out"
returns 0 on success, may return non-zero in future versions to indicate error
*/
//header section
#ifndef LONESHA256_H
#define LONESHA256_H
//process configuration
#ifdef LONESHA256_STATIC
#define LONESHA256_IMPLEMENTATION
#define LSHA256DEF static
#else //LONESHA256_EXTERN
#define LSHA256DEF extern
#endif
//includes
#include <stddef.h> //size_t
//lonesha256 declaration
LSHA256DEF int lonesha256(unsigned char[32], const unsigned char*, size_t);
#endif //LONESHA256_H
//implementation section
#ifdef LONESHA256_IMPLEMENTATION
#undef LONESHA256_IMPLEMENTATION
//macros
#define S(x, n) (((((uint32_t)(x)&0xFFFFFFFFUL)>>(uint32_t)((n)&31))|((uint32_t)(x)<<(uint32_t)((32-((n)&31))&31)))&0xFFFFFFFFUL)
#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
#define RND(a,b,c,d,e,f,g,h,i) \
t0 = h + (S(e, 6) ^ S(e, 11) ^ S(e, 25)) + (g ^ (e & (f ^ g))) + K[i] + W[i]; \
t1 = (S(a, 2) ^ S(a, 13) ^ S(a, 22)) + (((a | b) & c) | (a & b)); \
d += t0; \
h = t0 + t1;
#define STORE32H(x, y) \
(y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
(y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255);
#define LOAD32H(x, y) \
x = ((uint32_t)((y)[0]&255)<<24)|((uint32_t)((y)[1]&255)<<16)|((uint32_t)((y)[2]&255)<<8)|((uint32_t)((y)[3]&255));
#define STORE64H(x, y) \
(y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
(y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
(y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
(y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255);
#define SHA256_COMPRESS(buff) \
for (int i = 0; i < 8; i++) S[i] = sha256_state[i]; \
for (int i = 0; i < 16; i++) LOAD32H(W[i], buff + (4*i)); \
for (int i = 16; i < 64; i++) W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; \
for (int i = 0; i < 64; i++) { \
RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],i); \
t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; \
S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; \
} \
for (int i = 0; i < 8; i++) sha256_state[i] = sha256_state[i] + S[i];
//includes
#include <stdint.h> //uint32_t, uint64_t
#include <string.h> //memcpy
//lonesha256 function
LSHA256DEF int lonesha256 (unsigned char out[32], const unsigned char* in, size_t len) {
//writes the sha256 hash of the first "len" bytes in buffer "in" to buffer "out"
//returns 0 on success, may return non-zero in future versions to indicate error
const uint32_t K[64] = {
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
};
uint64_t sha256_length = 0;
uint32_t sha256_state[8] = {
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
}, S[8], W[64], t0, t1, t;
unsigned char sha256_buf[64];
//process input in 64 byte chunks
while (len >= 64) {
SHA256_COMPRESS(in);
sha256_length += 64 * 8;
in += 64;
len -= 64;
}
//copy remaining bytes into sha256_buf
memcpy(sha256_buf, in, len);
//finish up (len now number of bytes in sha256_buf)
sha256_length += len * 8;
sha256_buf[len++] = 0x80;
//pad then compress if length is above 56 bytes
if (len > 56) {
while (len < 64) sha256_buf[len++] = 0;
SHA256_COMPRESS(sha256_buf);
len = 0;
}
//pad up to 56 bytes
while (len < 56) sha256_buf[len++] = 0;
//store length and compress
STORE64H(sha256_length, sha256_buf + 56);
SHA256_COMPRESS(sha256_buf);
//copy output
for (int i = 0; i < 8; i++) {
STORE32H(sha256_state[i], out + 4*i);
}
//return
return 0;
}
#endif //LONESHA256_IMPLEMENTATION
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2012-2016 by John "JTE" Muniz.
// Copyright (C) 2012-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_archive.c
/// \brief Lua gamestate archival
#include "lua_archive.h"
#include "doomtype.h"
#include "fastcmp.h"
#include "g_game.h"
#include "g_input.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "matrix.h"
#include "p_saveg.h"
#include "p_setup.h"
#include "p_slopes.h"
#include "p_spec.h"
#include "quaternion.h"
#include "r_skins.h"
#include "r_state.h"
enum
{
ARCH_NULL=0,
ARCH_TRUE,
ARCH_FALSE,
ARCH_INT8,
ARCH_INT16,
ARCH_INT32,
ARCH_SMALLSTRING,
ARCH_LARGESTRING,
ARCH_TABLE,
ARCH_MOBJINFO,
ARCH_STATE,
ARCH_MOBJ,
ARCH_PLAYER,
ARCH_MAPTHING,
ARCH_VERTEX,
ARCH_LINE,
ARCH_SIDE,
ARCH_SUBSECTOR,
ARCH_SECTOR,
ARCH_FFLOOR,
ARCH_POLYOBJ,
ARCH_SLOPE,
ARCH_MAPHEADER,
ARCH_SKINCOLOR,
ARCH_MOUSE,
ARCH_SKIN,
ARCH_VECTOR2,
ARCH_VECTOR3,
ARCH_MATRIX,
ARCH_QUATERNION,
ARCH_TEND=0xFF,
};
static const struct {
const char *meta;
UINT8 arch;
} meta2arch[] = {
{META_MOBJINFO, ARCH_MOBJINFO},
{META_STATE, ARCH_STATE},
{META_MOBJ, ARCH_MOBJ},
{META_PLAYER, ARCH_PLAYER},
{META_MAPTHING, ARCH_MAPTHING},
{META_VERTEX, ARCH_VERTEX},
{META_LINE, ARCH_LINE},
{META_SIDE, ARCH_SIDE},
{META_SUBSECTOR,ARCH_SUBSECTOR},
{META_SECTOR, ARCH_SECTOR},
{META_FFLOOR, ARCH_FFLOOR},
{META_POLYOBJ, ARCH_POLYOBJ},
{META_SLOPE, ARCH_SLOPE},
{META_MAPHEADER, ARCH_MAPHEADER},
{META_SKINCOLOR, ARCH_SKINCOLOR},
{META_MOUSE, ARCH_MOUSE},
{META_SKIN, ARCH_SKIN},
{META_VECTOR2, ARCH_VECTOR2},
{META_VECTOR3, ARCH_VECTOR3},
{META_MATRIX, ARCH_MATRIX},
{META_QUATERNION, ARCH_QUATERNION},
{NULL, ARCH_NULL}
};
static UINT8 GetUserdataArchType(int index)
{
UINT8 i;
lua_getmetatable(gL, index);
for (i = 0; meta2arch[i].meta; i++)
{
luaL_getmetatable(gL, meta2arch[i].meta);
if (lua_rawequal(gL, -1, -2))
{
lua_pop(gL, 2);
return meta2arch[i].arch;
}
lua_pop(gL, 1);
}
lua_pop(gL, 1);
return ARCH_NULL;
}
static void *PrepareArchiveLuaUserdata(lua_State *L, save_t *save_p, int myindex, int archtype, int USERDATAINDEX)
{
boolean found = false;
INT32 i;
UINT16 t = (UINT16)lua_objlen(gL, USERDATAINDEX);
for (i = 1; i <= t && !found; i++)
{
lua_rawgeti(gL, USERDATAINDEX, i);
if (lua_rawequal(gL, myindex, -1))
{
t = i;
found = true;
}
lua_pop(gL, 1);
}
if (!found)
{
t++;
if (t == 0)
{
CONS_Alert(CONS_ERROR, "Too much userdata to archive!\n");
P_WriteUINT8(save_p, ARCH_NULL);
return NULL;
}
}
P_WriteUINT8(save_p, archtype);
P_WriteUINT16(save_p, t);
if (found)
{
return NULL;
}
else
{
lua_pushvalue(gL, myindex);
lua_rawseti(gL, USERDATAINDEX, t);
return lua_touserdata(L, myindex);
}
}
static UINT8 ArchiveValue(save_t *save_p, int TABLESINDEX, int USERDATAINDEX, int myindex)
{
if (myindex < 0)
myindex = lua_gettop(gL)+1+myindex;
switch (lua_type(gL, myindex))
{
case LUA_TNONE:
case LUA_TNIL:
P_WriteUINT8(save_p, ARCH_NULL);
break;
// This might be a problem. D:
case LUA_TLIGHTUSERDATA:
case LUA_TTHREAD:
case LUA_TFUNCTION:
P_WriteUINT8(save_p, ARCH_NULL);
return 2;
case LUA_TBOOLEAN:
P_WriteUINT8(save_p, lua_toboolean(gL, myindex) ? ARCH_TRUE : ARCH_FALSE);
break;
case LUA_TNUMBER:
{
lua_Integer number = lua_tointeger(gL, myindex);
if (number >= INT8_MIN && number <= INT8_MAX)
{
P_WriteUINT8(save_p, ARCH_INT8);
P_WriteSINT8(save_p, number);
}
else if (number >= INT16_MIN && number <= INT16_MAX)
{
P_WriteUINT8(save_p, ARCH_INT16);
P_WriteINT16(save_p, number);
}
else
{
P_WriteUINT8(save_p, ARCH_INT32);
P_WriteFixed(save_p, number);
}
break;
}
case LUA_TSTRING:
{
UINT32 len = (UINT32)lua_objlen(gL, myindex); // get length of string, including embedded zeros
const char *s = lua_tostring(gL, myindex);
UINT32 i = 0;
// if you're wondering why we're writing a string to save_p this way,
// it turns out that Lua can have embedded zeros ('\0') in the strings,
// so we can't use P_WriteString as that cuts off when it finds a '\0'.
// Saving the size of the string also allows us to get the size of the string on the other end,
// fixing the awful crashes previously encountered for reading strings longer than 1024
// (yes I know that's kind of a stupid thing to care about, but it'd be evil to trim or ignore them?)
// -- Monster Iestyn 05/08/18
if (len < 255)
{
P_WriteUINT8(save_p, ARCH_SMALLSTRING);
P_WriteUINT8(save_p, len); // save size of string
}
else
{
P_WriteUINT8(save_p, ARCH_LARGESTRING);
P_WriteUINT32(save_p, len); // save size of string
}
while (i < len)
P_WriteChar(save_p, s[i++]); // write chars individually, including the embedded zeros
break;
}
case LUA_TTABLE:
{
boolean found = false;
INT32 i;
UINT16 t = (UINT16)lua_objlen(gL, TABLESINDEX);
for (i = 1; i <= t && !found; i++)
{
lua_rawgeti(gL, TABLESINDEX, i);
if (lua_rawequal(gL, myindex, -1))
{
t = i;
found = true;
}
lua_pop(gL, 1);
}
if (!found)
{
t++;
if (t == 0)
{
CONS_Alert(CONS_ERROR, "Too many tables to archive!\n");
P_WriteUINT8(save_p, ARCH_NULL);
return 0;
}
}
P_WriteUINT8(save_p, ARCH_TABLE);
P_WriteUINT16(save_p, t);
if (!found)
{
lua_pushvalue(gL, myindex);
lua_rawseti(gL, TABLESINDEX, t);
return 1;
}
break;
}
case LUA_TUSERDATA:
switch (GetUserdataArchType(myindex))
{
case ARCH_MOBJINFO:
{
mobjinfo_t *info = *((mobjinfo_t **)lua_touserdata(gL, myindex));
P_WriteUINT8(save_p, ARCH_MOBJINFO);
P_WriteUINT16(save_p, info - mobjinfo);
break;
}
case ARCH_STATE:
{
state_t *state = *((state_t **)lua_touserdata(gL, myindex));
P_WriteUINT8(save_p, ARCH_STATE);
P_WriteUINT16(save_p, state - states);
break;
}
case ARCH_MOBJ:
{
mobj_t *mobj = *((mobj_t **)lua_touserdata(gL, myindex));
if (!mobj)
{
P_WriteUINT8(save_p, ARCH_NULL);
return 3;
}
else {
P_WriteUINT8(save_p, ARCH_MOBJ);
P_WriteUINT32(save_p, mobj->mobjnum);
}
break;
}
case ARCH_PLAYER:
{
player_t *player = *((player_t **)lua_touserdata(gL, myindex));
if (!player)
{
P_WriteUINT8(save_p, ARCH_NULL);
return 3;
}
else {
P_WriteUINT8(save_p, ARCH_PLAYER);
P_WriteUINT8(save_p, player - players);
}
break;
}
case ARCH_MAPTHING:
{
mapthing_t *mapthing = *((mapthing_t **)lua_touserdata(gL, myindex));
if (!mapthing)
{
P_WriteUINT8(save_p, ARCH_NULL);
return 3;
}
else {
P_WriteUINT8(save_p, ARCH_MAPTHING);
P_WriteUINT16(save_p, mapthing - mapthings);
}
break;
}
case ARCH_VERTEX:
{
vertex_t *vertex = *((vertex_t **)lua_touserdata(gL, myindex));
if (!vertex)
{
P_WriteUINT8(save_p, ARCH_NULL);
return 3;
}
else {
P_WriteUINT8(save_p, ARCH_VERTEX);
P_WriteUINT16(save_p, vertex - vertexes);
}
break;
}
case ARCH_LINE:
{
line_t *line = *((line_t **)lua_touserdata(gL, myindex));
if (!line)
{
P_WriteUINT8(save_p, ARCH_NULL);
return 3;
}
else {
P_WriteUINT8(save_p, ARCH_LINE);
P_WriteUINT16(save_p, line - lines);
}
break;
}
case ARCH_SIDE:
{
side_t *side = *((side_t **)lua_touserdata(gL, myindex));
if (!side)
{
P_WriteUINT8(save_p, ARCH_NULL);
return 3;
}
else {
P_WriteUINT8(save_p, ARCH_SIDE);
P_WriteUINT16(save_p, side - sides);
}
break;
}
case ARCH_SUBSECTOR:
{
subsector_t *subsector = *((subsector_t **)lua_touserdata(gL, myindex));
if (!subsector)
{
P_WriteUINT8(save_p, ARCH_NULL);
return 3;
}
else {
P_WriteUINT8(save_p, ARCH_SUBSECTOR);
P_WriteUINT16(save_p, subsector - subsectors);
}
break;
}
case ARCH_SECTOR:
{
sector_t *sector = *((sector_t **)lua_touserdata(gL, myindex));
if (!sector)
{
P_WriteUINT8(save_p, ARCH_NULL);
return 3;
}
else {
P_WriteUINT8(save_p, ARCH_SECTOR);
P_WriteUINT16(save_p, sector - sectors);
}
break;
}
case ARCH_FFLOOR:
{
ffloor_t *rover = *((ffloor_t **)lua_touserdata(gL, myindex));
if (!rover)
{
P_WriteUINT8(save_p, ARCH_NULL);
return 3;
}
else {
UINT16 i = P_GetFFloorID(rover);
if (i == UINT16_MAX) // invalid ID
P_WriteUINT8(save_p, ARCH_NULL);
else
{
P_WriteUINT8(save_p, ARCH_FFLOOR);
P_WriteUINT16(save_p, rover->target - sectors);
P_WriteUINT16(save_p, i);
}
}
break;
}
case ARCH_POLYOBJ:
{
polyobj_t *polyobj = *((polyobj_t **)lua_touserdata(gL, myindex));
if (!polyobj)
{
P_WriteUINT8(save_p, ARCH_NULL);
return 3;
}
else {
P_WriteUINT8(save_p, ARCH_POLYOBJ);
P_WriteUINT16(save_p, polyobj-PolyObjects);
}
break;
}
case ARCH_SLOPE:
{
pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex));
if (!slope)
{
P_WriteUINT8(save_p, ARCH_NULL);
return 3;
}
else {
P_WriteUINT8(save_p, ARCH_SLOPE);
P_WriteUINT16(save_p, slope->id);
}
break;
}
case ARCH_MAPHEADER:
{
mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex));
if (!header)
{
P_WriteUINT8(save_p, ARCH_NULL);
return 3;
}
else {
P_WriteUINT8(save_p, ARCH_MAPHEADER);
P_WriteUINT16(save_p, header - *mapheaderinfo);
}
break;
}
case ARCH_SKINCOLOR:
{
skincolor_t *info = *((skincolor_t **)lua_touserdata(gL, myindex));
P_WriteUINT8(save_p, ARCH_SKINCOLOR);
P_WriteUINT16(save_p, info - skincolors);
break;
}
case ARCH_MOUSE:
{
mouse_t *m = *((mouse_t **)lua_touserdata(gL, myindex));
P_WriteUINT8(save_p, ARCH_MOUSE);
P_WriteUINT8(save_p, m == &mouse ? 1 : 2);
break;
}
case ARCH_SKIN:
{
skin_t *skin = *((skin_t **)lua_touserdata(gL, myindex));
P_WriteUINT8(save_p, ARCH_SKIN);
P_WriteUINT8(save_p, skin->skinnum); // UINT8 because MAXSKINS must be <= 256
break;
}
case ARCH_VECTOR2:
{
vector2_t *vector = PrepareArchiveLuaUserdata(gL, save_p, myindex, ARCH_VECTOR2, USERDATAINDEX);
if (vector)
{
P_WriteFixed(save_p, vector->x);
P_WriteFixed(save_p, vector->y);
}
break;
}
case ARCH_VECTOR3:
{
vector3_t *vector = PrepareArchiveLuaUserdata(gL, save_p, myindex, ARCH_VECTOR3, USERDATAINDEX);
if (vector)
{
P_WriteFixed(save_p, vector->x);
P_WriteFixed(save_p, vector->y);
P_WriteFixed(save_p, vector->z);
}
break;
}
case ARCH_MATRIX:
{
matrix_t *matrix = PrepareArchiveLuaUserdata(gL, save_p, myindex, ARCH_MATRIX, USERDATAINDEX);
if (matrix)
{
for (size_t r = 0; r < 4; r++)
for (size_t c = 0; c < 4; c++)
P_WriteFixed(save_p, matrix->matrix[r][c]);
}
break;
}
case ARCH_QUATERNION:
{
quaternion_t *quat = PrepareArchiveLuaUserdata(gL, save_p, myindex, ARCH_QUATERNION, USERDATAINDEX);
if (quat)
{
P_WriteFixed(save_p, quat->x);
P_WriteFixed(save_p, quat->y);
P_WriteFixed(save_p, quat->z);
P_WriteFixed(save_p, quat->w);
}
break;
}
default:
P_WriteUINT8(save_p, ARCH_NULL);
return 2;
}
break;
}
return 0;
}
static void ArchiveExtVars(save_t *save_p, void *pointer, const char *ptype)
{
int TABLESINDEX;
int USERDATAINDEX;
UINT16 i;
if (!gL) {
if (fastcmp(ptype,"player")) // players must always be included, even if no vars
P_WriteUINT16(save_p, 0);
return;
}
TABLESINDEX = lua_gettop(gL) - 1;
USERDATAINDEX = lua_gettop(gL);
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(gL, -1));
lua_pushlightuserdata(gL, pointer);
lua_rawget(gL, -2);
lua_remove(gL, -2); // pop LREG_EXTVARS
if (!lua_istable(gL, -1))
{ // no extra values table
lua_pop(gL, 1);
if (fastcmp(ptype,"player")) // players must always be included, even if no vars
P_WriteUINT16(save_p, 0);
return;
}
lua_pushnil(gL);
for (i = 0; lua_next(gL, -2); i++)
lua_pop(gL, 1);
// skip anything that has an empty table and isn't a player.
if (i == 0)
{
if (fastcmp(ptype,"player")) // always include players even if they have no extra variables
P_WriteUINT16(save_p, 0);
lua_pop(gL, 1);
return;
}
if (fastcmp(ptype,"mobj")) // mobjs must write their mobjnum as a header
P_WriteUINT32(save_p, ((mobj_t *)pointer)->mobjnum);
P_WriteUINT16(save_p, i);
lua_pushnil(gL);
while (lua_next(gL, -2))
{
I_Assert(lua_type(gL, -2) == LUA_TSTRING);
P_WriteString(save_p, lua_tostring(gL, -2));
if (ArchiveValue(save_p, TABLESINDEX, USERDATAINDEX, -1) == 2)
CONS_Alert(CONS_ERROR, "Type of value for %s entry '%s' (%s) could not be archived!\n", ptype, lua_tostring(gL, -2), luaL_typename(gL, -1));
lua_pop(gL, 1);
}
lua_pop(gL, 1);
}
// FIXME: remove and pass as local variable
static save_t *lua_save_p;
static int NetArchive(lua_State *L)
{
int TABLESINDEX = lua_upvalueindex(1);
int USERDATAINDEX = lua_upvalueindex(2);
int i, n = lua_gettop(L);
for (i = 1; i <= n; i++)
ArchiveValue(lua_save_p, TABLESINDEX, USERDATAINDEX, i);
return n;
}
static void ArchiveTables(save_t *save_p)
{
int TABLESINDEX;
int USERDATAINDEX;
UINT16 i, n;
UINT8 e;
if (!gL)
return;
TABLESINDEX = lua_gettop(gL) - 1;
USERDATAINDEX = lua_gettop(gL);
n = (UINT16)lua_objlen(gL, TABLESINDEX);
for (i = 1; i <= n; i++)
{
lua_rawgeti(gL, TABLESINDEX, i);
lua_pushnil(gL);
while (lua_next(gL, -2))
{
// Write key
e = ArchiveValue(save_p, TABLESINDEX, USERDATAINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this.
if (e == 1)
n++; // the table contained a new table we'll have to archive. :(
else if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise)
CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -2), luaL_typename(gL, -2), i);
else if (e == 3) // nil key due to invalid userdata. NOT an error.
{
lua_pop(gL, 1);
continue;
}
// Write value
e = ArchiveValue(save_p, TABLESINDEX, USERDATAINDEX, -1);
if (e == 1)
n++; // the table contained a new table we'll have to archive. :(
else if (e == 2) // invalid value type
CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -2), luaL_typename(gL, -1));
lua_pop(gL, 1);
}
P_WriteUINT8(save_p, ARCH_TEND);
// Write metatable ID
if (lua_getmetatable(gL, -1))
{
// registry.metatables[metatable]
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
lua_pushvalue(gL, -2);
lua_gettable(gL, -2);
P_WriteUINT16(save_p, lua_isnil(gL, -1) ? 0 : lua_tointeger(gL, -1));
lua_pop(gL, 3);
}
else
P_WriteUINT16(save_p, 0);
lua_pop(gL, 1);
}
}
static void *PrepareUnarchiveLuaUserdata(lua_State *L, save_t *save_p, const char *meta, size_t size, int USERDATAINDEX)
{
UINT16 tid = P_ReadUINT16(save_p);
lua_rawgeti(L, USERDATAINDEX, tid);
if (lua_isnil(L, -1))
{
lua_pop(L, 1);
void *ud = lua_newuserdata(L, size);
luaL_getmetatable(L, meta);
lua_setmetatable(L, -2);
lua_pushvalue(L, -1);
lua_rawseti(L, USERDATAINDEX, tid);
return ud;
}
else
{
return NULL;
}
}
static UINT8 UnArchiveValue(save_t *save_p, int TABLESINDEX, int USERDATAINDEX)
{
UINT8 type = P_ReadUINT8(save_p);
switch (type)
{
case ARCH_NULL:
lua_pushnil(gL);
break;
case ARCH_TRUE:
lua_pushboolean(gL, true);
break;
case ARCH_FALSE:
lua_pushboolean(gL, false);
break;
case ARCH_INT8:
lua_pushinteger(gL, P_ReadSINT8(save_p));
break;
case ARCH_INT16:
lua_pushinteger(gL, P_ReadINT16(save_p));
break;
case ARCH_INT32:
lua_pushinteger(gL, P_ReadFixed(save_p));
break;
case ARCH_SMALLSTRING:
case ARCH_LARGESTRING:
{
UINT32 len;
char *value;
UINT32 i = 0;
// See my comments in the ArchiveValue function;
// it's much the same for reading strings as writing them!
// (i.e. we can't use P_ReadString either)
// -- Monster Iestyn 05/08/18
if (type == ARCH_SMALLSTRING)
len = P_ReadUINT8(save_p); // length of string, including embedded zeros
else
len = P_ReadUINT32(save_p); // length of string, including embedded zeros
value = malloc(len); // make temp buffer of size len
// now read the actual string
while (i < len)
value[i++] = P_ReadChar(save_p); // read chars individually, including the embedded zeros
lua_pushlstring(gL, value, len); // push the string (note: this function supports embedded zeros)
free(value); // free the buffer
break;
}
case ARCH_TABLE:
{
UINT16 tid = P_ReadUINT16(save_p);
lua_rawgeti(gL, TABLESINDEX, tid);
if (lua_isnil(gL, -1))
{
lua_pop(gL, 1);
lua_newtable(gL);
lua_pushvalue(gL, -1);
lua_rawseti(gL, TABLESINDEX, tid);
return 2;
}
break;
}
case ARCH_MOBJINFO:
LUA_PushUserdata(gL, &mobjinfo[P_ReadUINT16(save_p)], META_MOBJINFO);
break;
case ARCH_STATE:
LUA_PushUserdata(gL, &states[P_ReadUINT16(save_p)], META_STATE);
break;
case ARCH_MOBJ:
LUA_PushUserdata(gL, P_FindNewPosition(P_ReadUINT32(save_p)), META_MOBJ);
break;
case ARCH_PLAYER:
LUA_PushUserdata(gL, &players[P_ReadUINT8(save_p)], META_PLAYER);
break;
case ARCH_MAPTHING:
LUA_PushUserdata(gL, &mapthings[P_ReadUINT16(save_p)], META_MAPTHING);
break;
case ARCH_VERTEX:
LUA_PushUserdata(gL, &vertexes[P_ReadUINT16(save_p)], META_VERTEX);
break;
case ARCH_LINE:
LUA_PushUserdata(gL, &lines[P_ReadUINT16(save_p)], META_LINE);
break;
case ARCH_SIDE:
LUA_PushUserdata(gL, &sides[P_ReadUINT16(save_p)], META_SIDE);
break;
case ARCH_SUBSECTOR:
LUA_PushUserdata(gL, &subsectors[P_ReadUINT16(save_p)], META_SUBSECTOR);
break;
case ARCH_SECTOR:
LUA_PushUserdata(gL, &sectors[P_ReadUINT16(save_p)], META_SECTOR);
break;
case ARCH_FFLOOR:
{
sector_t *sector = &sectors[P_ReadUINT16(save_p)];
UINT16 id = P_ReadUINT16(save_p);
ffloor_t *rover = P_GetFFloorByID(sector, id);
if (rover)
LUA_PushUserdata(gL, rover, META_FFLOOR);
break;
}
case ARCH_POLYOBJ:
LUA_PushUserdata(gL, &PolyObjects[P_ReadUINT16(save_p)], META_POLYOBJ);
break;
case ARCH_SLOPE:
LUA_PushUserdata(gL, P_SlopeById(P_ReadUINT16(save_p)), META_SLOPE);
break;
case ARCH_MAPHEADER:
LUA_PushUserdata(gL, mapheaderinfo[P_ReadUINT16(save_p)], META_MAPHEADER);
break;
case ARCH_SKINCOLOR:
LUA_PushUserdata(gL, &skincolors[P_ReadUINT16(save_p)], META_SKINCOLOR);
break;
case ARCH_MOUSE:
LUA_PushUserdata(gL, P_ReadUINT16(save_p) == 1 ? &mouse : &mouse2, META_MOUSE);
break;
case ARCH_SKIN:
LUA_PushUserdata(gL, skins[P_ReadUINT8(save_p)], META_SKIN);
break;
case ARCH_VECTOR2:
{
vector2_t *vector = PrepareUnarchiveLuaUserdata(gL, save_p, META_VECTOR2, sizeof(vector2_t), USERDATAINDEX);
if (vector)
{
vector->x = P_ReadFixed(save_p);
vector->y = P_ReadFixed(save_p);
}
break;
}
case ARCH_VECTOR3:
{
vector3_t *vector = PrepareUnarchiveLuaUserdata(gL, save_p, META_VECTOR3, sizeof(vector3_t), USERDATAINDEX);
if (vector)
{
vector->x = P_ReadFixed(save_p);
vector->y = P_ReadFixed(save_p);
vector->z = P_ReadFixed(save_p);
}
break;
}
case ARCH_MATRIX:
{
matrix_t *matrix = PrepareUnarchiveLuaUserdata(gL, save_p, META_MATRIX, sizeof(matrix_t), USERDATAINDEX);
if (matrix)
{
for (size_t r = 0; r < 4; r++)
for (size_t c = 0; c < 4; c++)
matrix->matrix[r][c] = P_ReadFixed(save_p);
}
break;
}
case ARCH_QUATERNION:
{
quaternion_t *quat = PrepareUnarchiveLuaUserdata(gL, save_p, META_QUATERNION, sizeof(quaternion_t), USERDATAINDEX);
if (quat)
{
quat->x = P_ReadFixed(save_p);
quat->y = P_ReadFixed(save_p);
quat->z = P_ReadFixed(save_p);
quat->w = P_ReadFixed(save_p);
}
break;
}
case ARCH_TEND:
return 1;
}
return 0;
}
static void UnArchiveExtVars(save_t *save_p, void *pointer)
{
int TABLESINDEX;
int USERDATAINDEX;
UINT16 field_count = P_ReadUINT16(save_p);
UINT16 i;
char field[1024];
if (field_count == 0)
return;
I_Assert(gL != NULL);
TABLESINDEX = lua_gettop(gL) - 1;
USERDATAINDEX = lua_gettop(gL);
lua_createtable(gL, 0, field_count); // pointer's ext vars subtable
for (i = 0; i < field_count; i++)
{
P_ReadString(save_p, field);
UnArchiveValue(save_p, TABLESINDEX, USERDATAINDEX);
lua_setfield(gL, -2, field);
}
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(gL, -1));
lua_pushlightuserdata(gL, pointer);
lua_pushvalue(gL, -3); // pointer's ext vars subtable
lua_rawset(gL, -3);
lua_pop(gL, 2); // pop LREG_EXTVARS and pointer's subtable
}
static int NetUnArchive(lua_State *L)
{
int TABLESINDEX = lua_upvalueindex(1);
int USERDATAINDEX = lua_upvalueindex(2);
int i, n = lua_gettop(L);
for (i = 1; i <= n; i++)
UnArchiveValue(lua_save_p, TABLESINDEX, USERDATAINDEX);
return n;
}
static void UnArchiveTables(save_t *save_p)
{
int TABLESINDEX;
int USERDATAINDEX;
UINT16 i, n;
UINT16 metatableid;
if (!gL)
return;
TABLESINDEX = lua_gettop(gL) - 1;
USERDATAINDEX = lua_gettop(gL);
n = (UINT16)lua_objlen(gL, TABLESINDEX);
for (i = 1; i <= n; i++)
{
lua_rawgeti(gL, TABLESINDEX, i);
while (true)
{
UINT8 e = UnArchiveValue(save_p, TABLESINDEX, USERDATAINDEX); // read key
if (e == 1) // End of table
break;
else if (e == 2) // Key contains a new table
n++;
if (UnArchiveValue(save_p, TABLESINDEX, USERDATAINDEX) == 2) // read value
n++;
if (lua_isnil(gL, -2)) // if key is nil (if a function etc was accidentally saved)
{
CONS_Alert(CONS_ERROR, "A nil key in table %d was found! (Invalid key type or corrupted save?)\n", i);
lua_pop(gL, 2); // pop key and value instead of setting them in the table, to prevent Lua panic errors
}
else
lua_rawset(gL, -3);
}
metatableid = P_ReadUINT16(save_p);
if (metatableid)
{
// setmetatable(table, registry.metatables[metatableid])
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_METATABLES);
lua_rawgeti(gL, -1, metatableid);
if (lua_isnil(gL, -1))
I_Error("Unknown metatable ID %d\n", metatableid);
lua_setmetatable(gL, -3);
lua_pop(gL, 1);
}
lua_pop(gL, 1);
}
}
void LUA_Archive(save_t *save_p)
{
INT32 i;
thinker_t *th;
if (gL)
{
lua_newtable(gL); // tables to be archived.
lua_newtable(gL); // userdata to be archived.
}
for (i = 0; i < MAXPLAYERS; i++)
{
if (!players[i].ingame && i > 0) // dedicated servers...
continue;
// all players in game will be archived, even if they just add a 0.
ArchiveExtVars(save_p, &players[i], "player");
}
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->removing)
continue;
// archive function will determine when to skip mobjs,
// and write mobjnum in otherwise.
ArchiveExtVars(save_p, th, "mobj");
}
P_WriteUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
lua_save_p = save_p;
LUA_HookNetArchive(NetArchive); // call the NetArchive hook in archive mode
ArchiveTables(save_p);
if (gL)
lua_pop(gL, 2); // pop tables
}
void LUA_UnArchive(save_t *save_p)
{
UINT32 mobjnum;
INT32 i;
thinker_t *th;
if (gL)
{
lua_newtable(gL); // tables to be read
lua_newtable(gL); // userdata to be read
}
for (i = 0; i < MAXPLAYERS; i++)
{
if (!players[i].ingame && i > 0) // dedicated servers...
continue;
UnArchiveExtVars(save_p, &players[i]);
}
do {
mobjnum = P_ReadUINT32(save_p); // read a mobjnum
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->removing)
continue;
if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj
continue;
UnArchiveExtVars(save_p, th); // apply variables
}
} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.
lua_save_p = save_p;
LUA_HookNetArchive(NetUnArchive); // call the NetArchive hook in unarchive mode
UnArchiveTables(save_p);
if (gL)
lua_pop(gL, 2); // pop tables
}
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2012-2016 by John "JTE" Muniz.
// Copyright (C) 2012-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_archive.h
/// \brief Lua gamestate archival
#ifndef LUA_ARCHIVE_H
#define LUA_ARCHIVE_H
#include "lua_script.h"
#include "p_saveg.h"
void LUA_Archive(save_t *save_p);
void LUA_UnArchive(save_t *save_p);
void LUA_HookNetArchive(lua_CFunction archFunc);
#endif/*LUA_ARCHIVE_H*/
......@@ -171,6 +171,8 @@ static const struct {
{META_SKINCOLOR, "skincolor_t"},
{META_COLORRAMP, "skincolor_t.ramp"},
{META_SPRITEINFO, "spriteinfo_t"},
{META_SPRITEINFOFRAMELIST,"spriteinfoframe_t[]"},
{META_SPRITEINFOFRAME,"spriteinfoframe_t"},
{META_PIVOTLIST, "spriteframepivot_t[]"},
{META_FRAMEPIVOT, "spriteframepivot_t"},
......@@ -197,13 +199,7 @@ static const struct {
{META_SUBSECTOR, "subsector_t"},
{META_SECTOR, "sector_t"},
{META_FFLOOR, "ffloor_t"},
#ifdef HAVE_LUA_SEGS
{META_SEG, "seg_t"},
{META_NODE, "node_t"},
#endif
{META_SLOPE, "slope_t"},
{META_VECTOR2, "vector2_t"},
{META_VECTOR3, "vector3_t"},
{META_MAPHEADER, "mapheader_t"},
{META_POLYOBJ, "polyobj_t"},
......@@ -222,10 +218,6 @@ static const struct {
{META_THINGARGS, "mapthing.args"},
{META_THINGSTRINGARGS, "mapthing.stringargs"},
#ifdef HAVE_LUA_SEGS
{META_NODEBBOX, "node_t.bbox"},
{META_NODECHILDREN, "node_t.children"},
#endif
{META_BBOX, "bbox"},
......@@ -244,6 +236,12 @@ static const struct {
{META_MOUSE, "mouse_t"},
{META_INTERCEPT, "intercept_t"},
{META_VECTOR2, "vector2_t"},
{META_VECTOR3, "vector3_t"},
{META_MATRIX, "matrix_t"},
{META_QUATERNION, "quaternion_t"},
{NULL, NULL}
};
......@@ -1166,6 +1164,128 @@ static int lib_pPlayerZMovement(lua_State *L)
return 0;
}
static int lib_pGetMobjDistance2D(lua_State *L)
{
mobj_t *mobj1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *mobj2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
//HUDSAFE
INLEVEL
if (!(mobj1 && mobj2))
return LUA_ErrInvalid(L, "mobj_t");
lua_pushfixed(L, P_GetMobjDistance2D(mobj1, mobj2));
return 1;
}
static int lib_pGetMobjDistance3D(lua_State *L)
{
mobj_t *mobj1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *mobj2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
//HUDSAFE
INLEVEL
if (!(mobj1 && mobj2))
return LUA_ErrInvalid(L, "mobj_t");
lua_pushfixed(L, P_GetMobjDistance3D(mobj1, mobj2));
return 1;
}
static int lib_pGetMobjLargeDistance2D(lua_State *L)
{
mobj_t *mobj1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *mobj2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
//HUDSAFE
INLEVEL
if (!(mobj1 && mobj2))
return LUA_ErrInvalid(L, "mobj_t");
lua_pushinteger(L, P_GetMobjLargeDistance2D(mobj1, mobj2));
return 1;
}
static int lib_pGetMobjLargeDistance3D(lua_State *L)
{
mobj_t *mobj1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *mobj2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
//HUDSAFE
INLEVEL
if (!(mobj1 && mobj2))
return LUA_ErrInvalid(L, "mobj_t");
lua_pushinteger(L, P_GetMobjLargeDistance3D(mobj1, mobj2));
return 1;
}
static int lib_pAreMobjsClose2D(lua_State *L)
{
mobj_t *mobj1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *mobj2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t maxdist = luaL_checkfixed(L, 3);
//HUDSAFE
INLEVEL
if (!(mobj1 && mobj2))
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_AreMobjsClose2D(mobj1, mobj2, maxdist));
return 1;
}
static int lib_pAreMobjsClose3D(lua_State *L)
{
mobj_t *mobj1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *mobj2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t maxdist = luaL_checkfixed(L, 3);
//HUDSAFE
INLEVEL
if (!(mobj1 && mobj2))
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_AreMobjsClose3D(mobj1, mobj2, maxdist));
return 1;
}
static int lib_pAreMobjsFar2D(lua_State *L)
{
mobj_t *mobj1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *mobj2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t mindist = luaL_checkfixed(L, 3);
//HUDSAFE
INLEVEL
if (!(mobj1 && mobj2))
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_AreMobjsFar2D(mobj1, mobj2, mindist));
return 1;
}
static int lib_pAreMobjsFar3D(lua_State *L)
{
mobj_t *mobj1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *mobj2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t mindist = luaL_checkfixed(L, 3);
//HUDSAFE
INLEVEL
if (!(mobj1 && mobj2))
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_AreMobjsFar3D(mobj1, mobj2, mindist));
return 1;
}
static int lib_pGetMobjMomentum2D(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushfixed(L, P_GetMobjMomentum2D(mobj));
return 1;
}
static int lib_pGetMobjMomentum3D(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushfixed(L, P_GetMobjMomentum3D(mobj));
return 1;
}
// P_USER
////////////
......@@ -2930,6 +3050,119 @@ static int lib_evStartCrumble(lua_State *L)
return 0;
}
static int lib_pStartMoveFloor(lua_State *L)
{
NOHUD
INLEVEL
sector_t* sec = NULL;
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
sec = *((sector_t**)luaL_checkudata(L, 1, META_SECTOR));
if (!sec)
return LUA_ErrInvalid(L, "sector_t");
fixed_t destheight = luaL_checkfixed(L, 2);
fixed_t speed = luaL_checkfixed(L, 3);
if (speed <= 0)
return luaL_error(L, "argument #3 must be greater than 0");
floormove_t* floor;
if (sec->floordata == NULL)
{
floor = Z_Calloc(sizeof(*floor), PU_LEVSPEC, NULL);
sec->floordata = floor;
P_AddThinker(THINK_MAIN, &floor->thinker);
floor->thinker.function = (actionf_p1)T_MoveFloor;
R_CreateInterpolator_SectorPlane(&floor->thinker, sec, false);
}
else
floor = sec->floordata;
floor->sector = sec;
floor->speed = speed;
floor->texture = -1;
floor->type = -1;
floor->floordestheight = destheight;
floor->direction = destheight >= sec->floorheight ? 1 : -1;
return 0;
}
static int lib_pStopMoveFloor(lua_State *L)
{
NOHUD
INLEVEL
sector_t* sec = NULL;
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
sec = *((sector_t**)luaL_checkudata(L, 1, META_SECTOR));
if (!sec)
return LUA_ErrInvalid(L, "sector_t");
if (sec->floordata != NULL) // Override movement on new lua call.
{
P_RemoveThinker(sec->floordata);
sec->floorspeed = 0;
sec->floordata = NULL;
}
return 0;
}
static int lib_pStartMoveCeiling(lua_State *L)
{
NOHUD
INLEVEL
sector_t* sec = NULL;
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
sec = *((sector_t**)luaL_checkudata(L, 1, META_SECTOR));
if (!sec)
return LUA_ErrInvalid(L, "sector_t");
fixed_t destheight = luaL_checkfixed(L, 2);
fixed_t speed = luaL_checkfixed(L, 3);
if (speed <= 0)
return luaL_error(L, "argument #3 must be greater than 0");
ceiling_t* ceiling;
if (sec->ceilingdata == NULL)
{
ceiling = Z_Calloc(sizeof(*ceiling), PU_LEVSPEC, NULL);
sec->ceilingdata = ceiling;
P_AddThinker(THINK_MAIN, &ceiling->thinker);
ceiling->thinker.function = (actionf_p1)T_MoveCeiling;
R_CreateInterpolator_SectorPlane(&ceiling->thinker, sec, true);
}
else
ceiling = sec->ceilingdata;
ceiling->sector = sec;
ceiling->speed = speed;
ceiling->texture = -1;
ceiling->type = -1;
ceiling->direction = destheight >= sec->ceilingheight ? 1 : -1;
ceiling->topheight = ceiling->bottomheight = destheight;
return 0;
}
static int lib_pStopMoveCeiling(lua_State *L)
{
NOHUD
INLEVEL
sector_t* sec = NULL;
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
sec = *((sector_t**)luaL_checkudata(L, 1, META_SECTOR));
if (!sec)
return LUA_ErrInvalid(L, "sector_t");
if (sec->ceilingdata != NULL)
{
P_RemoveThinker(sec->ceilingdata);
sec->ceilspeed = 0;
sec->ceilingdata = NULL;
}
return 0;
}
// P_SLOPES
////////////
......@@ -2986,6 +3219,7 @@ static int lib_rPointToAngle2(lua_State *L)
return 1;
}
// TODO: 2.3: Delete
static int lib_rPointToDist(lua_State *L)
{
fixed_t x = luaL_checkfixed(L, 1);
......@@ -2995,6 +3229,7 @@ static int lib_rPointToDist(lua_State *L)
return 1;
}
// TODO: 2.3: Delete
static int lib_rPointToDist2(lua_State *L)
{
fixed_t px2 = luaL_checkfixed(L, 1);
......@@ -3002,7 +3237,7 @@ static int lib_rPointToDist2(lua_State *L)
fixed_t px1 = luaL_checkfixed(L, 3);
fixed_t py1 = luaL_checkfixed(L, 4);
//HUDSAFE
lua_pushfixed(L, R_PointToDist2(px2, py2, px1, py1));
lua_pushfixed(L, GetDistance2D(px2, py2, px1, py1));
return 1;
}
......@@ -3210,6 +3445,38 @@ static int lib_rTextureNameForNum(lua_State *L)
return 1;
}
// Not a real function.
static int lib_rGetTextureDimensions(lua_State *L)
{
INT32 num = -1;
if (lua_isnoneornil(L, 1))
return luaL_error(L, "argument #1 not given (expected number or string)");
else if (lua_type(L, 1) == LUA_TNUMBER)
{
num = (INT32)luaL_checkinteger(L, 1);
if (num < 1 || num >= numtextures)
return luaL_error(L, "texture %d (argument #1) out of range (1 - %d)", num, numtextures-1);
}
else
{
const char *name = luaL_checkstring(L, 1);
num = R_CheckTextureNumForName(name, TEXTURETYPE_TEXTURE);
// Didn't find it, so look for a flat
if (num == -1)
{
num = R_CheckTextureNumForName(name, TEXTURETYPE_FLAT);
if (num == -1)
return luaL_error(L, "texture %s (argument #1) is not loaded", name);
}
}
//HUDSAFE
lua_pushinteger(L, textures[num]->width);
lua_pushinteger(L, textures[num]->height);
return 2;
}
// R_DRAW
////////////
static int lib_rGetColorByName(lua_State *L)
......@@ -3262,10 +3529,10 @@ static int GetValidSoundOrigin(lua_State *L, void **origin)
return LUA_ErrInvalid(L, "sector_t");
*origin = &((sector_t *)(*origin))->soundorg;
return 1;
return 2;
}
return LUA_ErrInvalid(L, "mobj_t/sector_t");
return 0;
}
static int lib_sStartSound(lua_State *L)
......@@ -3284,15 +3551,23 @@ static int lib_sStartSound(lua_State *L)
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!lua_isnil(L, 1))
if (!GetValidSoundOrigin(L, &origin))
return 0;
if (!player || P_IsLocalPlayer(player))
if (player == NULL || P_IsLocalPlayer(player))
{
if (hud_running || hook_cmd_running)
origin = NULL; // HUD rendering and CMD building startsound shouldn't have an origin, just remove it instead of having a retarded error.
S_StartSound(origin, sound_id);
if (lua_isnil(L, 1))
S_StartSoundFromEverywhere(sound_id);
else
{
int origintype = GetValidSoundOrigin(L, &origin);
if (origintype == 1)
S_StartSoundFromMobj(origin, sound_id);
else if (origintype == 2)
{
origin = *((sector_t**)luaL_checkudata(L, 1, META_SECTOR)); // Restore this (other functions still use soundorg outright)
S_StartSoundFromSector(origin, sound_id);
}
else
return LUA_ErrInvalid(L, "mobj_t/sector_t");
}
}
return 0;
}
......@@ -3313,12 +3588,25 @@ static int lib_sStartSoundAtVolume(lua_State *L)
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!lua_isnil(L, 1))
if (!GetValidSoundOrigin(L, &origin))
if (player == NULL || P_IsLocalPlayer(player))
{
if (lua_isnil(L, 1))
S_StartSoundFromEverywhereVol(sound_id, volume);
else
{
int origintype = GetValidSoundOrigin(L, &origin);
if (origintype == 1)
S_StartSoundFromMobjVol(origin, sound_id, volume);
else if (origintype == 2)
{
origin = *((sector_t**)luaL_checkudata(L, 1, META_SECTOR)); // Restore this (other functions still use soundorg outright)
S_StartSoundFromSectorVol(origin, sound_id, volume);
}
else
return LUA_ErrInvalid(L, "mobj_t/sector_t");
}
if (!player || P_IsLocalPlayer(player))
S_StartSoundAtVolume(origin, sound_id, volume);
}
return 0;
}
......@@ -3952,6 +4240,34 @@ static int lib_gAddGametype(lua_State *L)
return 0;
}
// Lua exclusive function to unlock Lua Conditions
// Up to Lua scripter
static int lib_gUnlockCondition(lua_State* L)
{
int id = luaL_checkinteger(L, 1) - 1;
boolean global = luaL_checkboolean(L, 2);
if (id <= 0 || id > MAXLUACONDITIONS)
{
luaL_error(L, "Lua condition %d out of range (1 - %d)", id + 1, MAXLUACONDITIONS);
return 0;
}
if (global)
{
serverGamedata->lua[id] = true;
M_SilentUpdateUnlockablesAndEmblems(serverGamedata);
}
clientGamedata->lua[id] = true;
if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata))
{
S_StartSoundFromEverywhere(sfx_s3k68);
}
return 0;
}
// Bot adding function!
// Partly lifted from Got_AddPlayer
static int lib_gAddPlayer(lua_State *L)
......@@ -3962,7 +4278,7 @@ static int lib_gAddPlayer(lua_State *L)
for (i = 1; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
break;
}
......@@ -3976,7 +4292,7 @@ static int lib_gAddPlayer(lua_State *L)
CL_ClearPlayer(newplayernum);
playeringame[newplayernum] = true;
players[newplayernum].ingame = true;
G_AddPlayer(newplayernum);
newplayer = &players[newplayernum];
......@@ -4044,7 +4360,7 @@ static int lib_gRemovePlayer(lua_State *L)
return luaL_error(L, "argument #1 not given (expected number)");
if (pnum >= MAXPLAYERS) // Out of range
return luaL_error(L, "playernum %d out of range (0 - %d)", pnum, MAXPLAYERS-1);
if (playeringame[pnum]) // Found player
if (players[pnum].ingame) // Found player
{
if (players[pnum].bot == BOT_NONE) // Can't remove clients.
return luaL_error(L, "G_RemovePlayer can only be used on players with a bot value other than BOT_NONE.");
......@@ -4251,16 +4567,21 @@ static int lib_gSetCustomExitVars(lua_State *L)
// G_SetCustomExitVars(nil, int) [skipstats only]
// G_SetCustomExitVars(int, int) [both of the above]
// G_SetCustomExitVars(int, int, int) [nextmapoverride, skipstats and nextgametype]
// G_SetCustomExitVars(int, int, int, int) [nextmapoverride, skipstats, nextgametype and keepcutscenes]
nextmapoverride = 0;
skipstats = 0;
nextgametype = -1;
keepcutscene = false;
if (n >= 1)
{
nextmapoverride = (INT16)luaL_optinteger(L, 1, 0);
skipstats = (INT16)luaL_optinteger(L, 2, 0);
nextgametype = (INT16)luaL_optinteger(L, 3, -1);
if (!lua_isnil(L, 4))
keepcutscene = luaL_checkboolean(L, 4);
}
return 0;
......@@ -4449,7 +4770,7 @@ static luaL_Reg lib[] = {
{"P_RandomChance",lib_pRandomChance}, // MACRO
// p_maputil
{"P_AproxDistance",lib_pAproxDistance},
{"P_AproxDistance",lib_pAproxDistance}, // TODO: 2.3: Delete
{"P_ClosestPointOnLine",lib_pClosestPointOnLine},
{"P_PointOnLineSide",lib_pPointOnLineSide},
......@@ -4501,6 +4822,16 @@ static luaL_Reg lib[] = {
{"P_RingZMovement",lib_pRingZMovement},
{"P_SceneryZMovement",lib_pSceneryZMovement},
{"P_PlayerZMovement",lib_pPlayerZMovement},
{"P_GetMobjDistance2D",lib_pGetMobjDistance2D},
{"P_GetMobjDistance3D",lib_pGetMobjDistance3D},
{"P_GetMobjLargeDistance2D",lib_pGetMobjLargeDistance2D},
{"P_GetMobjLargeDistance3D",lib_pGetMobjLargeDistance3D},
{"P_AreMobjsClose2D",lib_pAreMobjsClose2D},
{"P_AreMobjsClose3D",lib_pAreMobjsClose3D},
{"P_AreMobjsFar2D",lib_pAreMobjsFar2D},
{"P_AreMobjsFar3D",lib_pAreMobjsFar3D},
{"P_GetMobjMomentum2D",lib_pGetMobjMomentum2D},
{"P_GetMobjMomentum3D",lib_pGetMobjMomentum3D},
// p_user
{"P_GetPlayerHeight",lib_pGetPlayerHeight},
......@@ -4631,6 +4962,10 @@ static luaL_Reg lib[] = {
{"P_StartQuake",lib_pStartQuake},
{"EV_CrumbleChain",lib_evCrumbleChain},
{"EV_StartCrumble",lib_evStartCrumble},
{"P_StartMoveFloor",lib_pStartMoveFloor},
{"P_StopMoveFloor",lib_pStopMoveFloor},
{"P_StartMoveCeiling",lib_pStartMoveCeiling},
{"P_StopMoveCeiling",lib_pStopMoveCeiling},
// p_slopes
{"P_GetZAt",lib_pGetZAt},
......@@ -4639,8 +4974,8 @@ static luaL_Reg lib[] = {
// r_defs
{"R_PointToAngle",lib_rPointToAngle},
{"R_PointToAngle2",lib_rPointToAngle2},
{"R_PointToDist",lib_rPointToDist},
{"R_PointToDist2",lib_rPointToDist2},
{"R_PointToDist",lib_rPointToDist}, // TODO: 2.3: Delete
{"R_PointToDist2",lib_rPointToDist2}, // TODO: 2.3: Delete
{"R_PointInSubsector",lib_rPointInSubsector},
{"R_PointInSubsectorOrNil",lib_rPointInSubsectorOrNil},
......@@ -4661,6 +4996,7 @@ static luaL_Reg lib[] = {
{"R_TextureNumForName",lib_rTextureNumForName},
{"R_CheckTextureNameForNum", lib_rCheckTextureNameForNum},
{"R_TextureNameForNum", lib_rTextureNameForNum},
{"R_GetTextureDimensions", lib_rGetTextureDimensions},
// r_draw
{"R_GetColorByName", lib_rGetColorByName},
......@@ -4701,6 +5037,7 @@ static luaL_Reg lib[] = {
{"G_AddGametype", lib_gAddGametype},
{"G_AddPlayer", lib_gAddPlayer},
{"G_RemovePlayer", lib_gRemovePlayer},
{"G_UnlockCondition", lib_gUnlockCondition},
{"G_SetUsedCheats", lib_gSetUsedCheats},
{"G_BuildMapName",lib_gBuildMapName},
{"G_BuildMapTitle",lib_gBuildMapTitle},
......
......@@ -22,6 +22,11 @@
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
// Included for the custom options menu
#include "netcode/d_netfil.h"
#include "m_menu.h"
#include "w_wad.h"
// for functions not allowed in hud.add hooks
#define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
......@@ -508,7 +513,7 @@ static int lib_cvRegisterVar(lua_State *L)
lua_pop(L, 1);
cvar->func = Lua_OnChange;
}
else if (cvar->flags & CV_CALL && (k && fasticmp(k, "can_change")))
else if (cvar->flags & CV_CALL && (i == 6 || (k && fasticmp(k, "can_change"))))
{
if (!lua_isfunction(L, 4))
{
......@@ -522,6 +527,29 @@ static int lib_cvRegisterVar(lua_State *L)
lua_pop(L, 1);
cvar->can_change = Lua_CanChange;
}
else if (((i == 5 && !(cvar->flags & CV_CALL))
|| (cvar->flags & CV_CALL && i == 7))
|| (k && fasticmp(k, "category")))
{
if (!lua_isstring(L, 4))
{
TYPEERROR("category", LUA_TSTRING)
}
cvar->category = Z_StrDup(lua_tostring(L, 4));
}
else if (((i == 6 && !(cvar->flags & CV_CALL))
|| (cvar->flags & CV_CALL && i == 8))
|| (k && fasticmp(k, "displayname")))
{
if (!lua_isstring(L, 4))
{
TYPEERROR("displayname", LUA_TSTRING)
}
cvar->displayname = Z_StrDup(lua_tostring(L, 4));
}
lua_pop(L, 1);
}
......@@ -548,6 +576,19 @@ static int lib_cvRegisterVar(lua_State *L)
return luaL_error(L, M_GetText("Variable %s has CV_CALL without any callbacks"), cvar->name);
}
if (!cvar->displayname || cvar->displayname[0] == '\0')
{
cvar->displayname = cvar->name;
}
if (!cvar->category || cvar->category[0] == '\0')
{
char* temp = wadfiles[numwadfiles - 1]->filename;
temp += strlen(temp) - nameonlylength(temp);
cvar->category = temp;
}
cvar->flags |= CV_ALLOWLUA;
// actually time to register it to the console now! Finally!
cvar->flags |= CV_MODIFIED;
......@@ -558,6 +599,9 @@ static int lib_cvRegisterVar(lua_State *L)
return luaL_error(L, "failed to register cvar (probable conflict with internal variable/command names)");
}
if (cvar->flags & CV_MENU)
M_RegisterCustomCVOption(cvar);
// return cvar userdata
return 1;
}
......@@ -672,6 +716,8 @@ enum cvar_e
cvar_value,
cvar_string,
cvar_changed,
cvar_displayname,
cvar_category,
};
static const char *const cvar_opt[] = {
......@@ -681,6 +727,8 @@ static const char *const cvar_opt[] = {
"value",
"string",
"changed",
"displayname",
"category",
NULL,
};
......@@ -711,6 +759,12 @@ static int cvar_get(lua_State *L)
case cvar_changed:
lua_pushboolean(L, cvar->changed);
break;
case cvar_displayname:
lua_pushstring(L, cvar->displayname);
break;
case cvar_category:
lua_pushstring(L, cvar->category);
break;
default:
if (devparm)
return luaL_error(L, LUA_QL("consvar_t") " has no field named " LUA_QS ".", lua_tostring(L, 2));
......
......@@ -62,6 +62,7 @@ automatically.
X (ShieldSpecial),/* shield abilities */\
X (PlayerCanDamage),/* P_PlayerCanDamage */\
X (PlayerQuit),\
X (NameChange),\
X (IntermissionThinker),/* Y_Ticker */\
X (TeamSwitch),/* team switching in... uh... *what* speak, spit it the fuck out */\
X (ViewpointSwitch),/* spy mode (no trickstabs) */\
......@@ -72,6 +73,7 @@ automatically.
X (GameEnd),\
X (PlayerCmd),/* building the player's ticcmd struct (Ported from SRB2Kart) */\
X (MusicChange),\
X (SoundPlay),\
X (PlayerHeight),/* override player height */\
X (PlayerCanEnterSpinGaps),\
X (AddonLoaded),\
......@@ -89,6 +91,7 @@ automatically.
X (scores),/* emblems/multiplayer list */\
X (title),/* titlescreen */\
X (titlecard),\
X (escpanel) /* rings/time/score/emblem panel in pause menu */,\
X (intermission),\
X (continue),\
X (playersetup),\
......@@ -130,6 +133,10 @@ int LUA_HookCharacterHUD
INT32 skinIndex, UINT8 sprite2, UINT8 frame, UINT8 rotation, skincolornum_t color,
INT32 ticker, boolean mode
);
boolean LUA_HookEscapePanel(
int hook, huddrawlist_h drawlist,
int x, int y, int width, int height
);
int LUA_HookMobj(mobj_t *, int hook);
int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook);
......@@ -157,11 +164,13 @@ int LUA_HookMapThingSpawn(mobj_t *, mapthing_t *);
int LUA_HookFollowMobj(player_t *, mobj_t *);
int LUA_HookPlayerCanDamage(player_t *, mobj_t *);
void LUA_HookPlayerQuit(player_t *, kickreason_t);
int LUA_HookNameChange(player_t *plr, const char *name);
int LUA_HookTeamSwitch(player_t *, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble);
int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced);
int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend);
int LUA_HookShouldJingleContinue(player_t *, const char *musname);
int LUA_HookPlayerCmd(player_t *, ticcmd_t *);
int LUA_HookMusicChange(const char *oldname, struct MusicChange *);
int LUA_HookSoundPlay(sfxenum_t sfx_id, void *origin, const int origintype);
fixed_t LUA_HookPlayerHeight(player_t *player);
int LUA_HookPlayerCanEnterSpinGaps(player_t *player);
......@@ -22,6 +22,7 @@
#include "lua_libs.h"
#include "lua_hook.h"
#include "lua_hud.h" // hud_running errors
#include "lua_archive.h"
#include "m_perfstats.h"
#include "netcode/d_netcmd.h" // for cv_perfstats
......@@ -738,6 +739,22 @@ int LUA_HookCharacterHUD
return hook.status;
}
boolean LUA_HookEscapePanel(int hook, huddrawlist_h drawlist, int x, int y, int width, int height)
{
Hook_State hookstate;
if (prepare_hud_hook(&hookstate, false, hook))
{
LUA_SetHudHook(hook, drawlist);
lua_pushinteger(gL, x);
lua_pushinteger(gL, y);
lua_pushinteger(gL, width);
lua_pushinteger(gL, height);
call_hud_hooks(&hookstate, 1, res_true);
}
return hookstate.status;
}
/* =========================================================================
SPECIALIZED HOOKS
========================================================================= */
......@@ -1027,9 +1044,10 @@ void LUA_HookNetArchive(lua_CFunction archFunc)
begin_hook_values(&hook);
// tables becomes an upvalue of archFunc
lua_pushvalue(gL, -1);
lua_pushcclosure(gL, archFunc, 1);
// tables and userdata becomes an upvalue of archFunc
lua_pushvalue(gL, -2);
lua_pushvalue(gL, -2);
lua_pushcclosure(gL, archFunc, 2);
// stack: tables, archFunc
init_hook_call(&hook, 0, res_none);
......@@ -1088,6 +1106,18 @@ void LUA_HookPlayerQuit(player_t *plr, kickreason_t reason)
}
}
int LUA_HookNameChange(player_t *plr, const char *name)
{
Hook_State hook;
if (prepare_hook(&hook, true, HOOK(NameChange)))
{
LUA_PushUserdata(gL, plr, META_PLAYER); // Player that changed name
lua_pushstring(gL, name); // New player name
call_hooks(&hook, 1, res_false);
}
return hook.status;
}
int LUA_HookTeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble)
{
Hook_State hook;
......@@ -1238,6 +1268,47 @@ int LUA_HookMusicChange(const char *oldname, struct MusicChange *param)
return hook.status;
}
static void res_soundplay(Hook_State* hook)
{
if (!lua_isnil(gL, -1))
{
UINT32 sfx_id = lua_tonumber(gL, -1);
if (lua_isboolean(gL, -1) && lua_toboolean(gL, -1))
hook->status = 0; //sfx_None if returning True
//Make sure number is in range
else if (!lua_isboolean(gL, -1)
&& (sfx_id < NUMSFX))
hook->status = sfx_id;
if (sfx_id >= NUMSFX)
CONS_Alert(CONS_WARNING, "sfx %d out of range (0 - %d)\n", sfx_id, NUMSFX-1);
}
}
int LUA_HookSoundPlay(sfxenum_t sfx_id, void *origin, const int origintype)
{
Hook_State hook;
if (prepare_hook(&hook, sfx_id, HOOK(SoundPlay)))
{
lua_pushinteger(gL, sfx_id);
if (origin != NULL)
{
if (origintype == 0)
LUA_PushUserdata(gL, (mobj_t*)origin, META_MOBJ);
else if (origintype == 1)
LUA_PushUserdata(gL, (sector_t*)origin, META_SECTOR);
lua_pushinteger(gL, origintype);
}
hud_running = true; // local hook
call_hooks(&hook, 1, res_soundplay);
hud_running = false;
}
return hook.status;
}
static void res_playerheight(Hook_State *hook)
{
if (!lua_isnil(gL, -1))
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Kart Krew.
// Copyright (C) 2012-2016 by John "JTE" Muniz.
// Copyright (C) 2012-2024 by Sonic Team Junior.
// Copyright (C) 2012-2025 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -82,7 +83,7 @@ static int lib_getSprname(lua_State *L)
i = lua_tonumber(L, 1);
if (i > NUMSPRITES)
return 0;
lua_pushlstring(L, sprnames[i], 4);
lua_pushstring(L, sprnames[i]);
return 1;
}
else if (lua_isstring(L, 1))
......@@ -236,6 +237,38 @@ static int lib_spr2namelen(lua_State *L)
// SPRITE INFO //
/////////////////
struct SpriteInfoFrame {
spriteinfo_t *sprinfo;
UINT16 frame;
};
static UINT16 GetSpriteInfoFrameIndex(lua_State *L, int idx)
{
if (lua_type(L, idx) == LUA_TSTRING)
{
const char *field = luaL_checkstring(L, idx);
if (fastcmp("default", field))
{
return SPRINFO_DEFAULT_FRAME;
}
else
{
UINT8 frame = R_Char2Frame(field[0]);
if (frame == 255)
return luaL_error(L, "invalid frame %s", field);
return (UINT16)frame;
}
}
else
{
int frameID = luaL_checknumber(L, idx);
if (frameID < 0 || frameID >= MAXFRAMENUM)
return luaL_error(L, "frame %d out of range (0 - %d)", frameID, MAXFRAMENUM - 1);
return (UINT16)frameID;
}
}
// spriteinfo[]
static int lib_getSpriteInfo(lua_State *L)
{
......@@ -263,9 +296,72 @@ static int lib_getSpriteInfo(lua_State *L)
#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to spriteinfo[] (%s)", e);
#define TYPEERROR(f, t1, t2) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t1), lua_typename(L, t2)))
static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, int idx)
static int PopPivotSubTable(spriteinfoframe_t *frame, lua_State *L, int stk);
static int PopFrameSubTable(spriteinfoframe_t *frame, lua_State *L, int stk)
{
int okcool = 0;
switch (lua_type(L, stk))
{
case LUA_TTABLE:
lua_pushnil(L);
while (lua_next(L, stk))
{
const char *key = luaL_checkstring(L, stk+1);
if (fastcmp(key, "pivot"))
{
if (PopPivotSubTable(frame, L, stk+2))
okcool = 1;
}
else
{
FIELDERROR("sprite info frame key", va("invalid option %s", key));
}
okcool = 1;
lua_pop(L, 1);
}
break;
default:
TYPEERROR("sprite info frame", LUA_TTABLE, lua_type(L, stk))
}
return okcool;
}
static int PopFrameTable(spriteinfo_t *info, lua_State *L, int stk)
{
lua_pushnil(L);
while (lua_next(L, stk))
{
int idx = 0;
switch (lua_type(L, stk+1))
{
case LUA_TSTRING:
case LUA_TNUMBER:
idx = GetSpriteInfoFrameIndex(L, stk+1);
break;
default:
TYPEERROR("sprite info frame", LUA_TNUMBER, lua_type(L, stk+1));
}
// the values in frames[] are also tables
if (PopFrameSubTable(&info->frames[idx], L, stk+2))
set_bit_array(info->available, idx);
lua_pop(L, 1);
}
return 0;
}
static int PopPivotSubTable(spriteinfoframe_t *frame, lua_State *L, int stk)
{
int okcool = 0;
switch (lua_type(L, stk))
{
case LUA_TTABLE:
......@@ -275,6 +371,7 @@ static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, in
const char *key = NULL;
lua_Integer ikey = -1;
lua_Integer value = 0;
// x or y?
switch (lua_type(L, stk+1))
{
......@@ -287,6 +384,7 @@ static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, in
default:
FIELDERROR("pivot key", va("string or number expected, got %s", luaL_typename(L, stk+1)))
}
// then get value
switch (lua_type(L, stk+2))
{
......@@ -299,59 +397,60 @@ static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, in
default:
TYPEERROR("pivot value", LUA_TNUMBER, lua_type(L, stk+2))
}
// finally set omg!!!!!!!!!!!!!!!!!!
// Set it
if (ikey == 1 || (key && fastcmp(key, "x")))
pivot[idx].x = (INT32)value;
frame->pivot.x = (INT32)value;
else if (ikey == 2 || (key && fastcmp(key, "y")))
pivot[idx].y = (INT32)value;
frame->pivot.y = (INT32)value;
// TODO: 2.3: Delete
else if (ikey == 3 || (key && fastcmp(key, "rotaxis")))
LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.")
else if (ikey == -1 && (key != NULL))
FIELDERROR("pivot key", va("invalid option %s", key));
okcool = 1;
lua_pop(L, 1);
}
break;
default:
TYPEERROR("sprite pivot", LUA_TTABLE, lua_type(L, stk))
}
if (okcool)
frame->pivot.available = true;
return okcool;
}
static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk)
{
// Just in case?
if (!lua_istable(L, stk))
TYPEERROR("pivot table", LUA_TTABLE, lua_type(L, stk));
lua_pushnil(L);
// stk = 0 has the pivot table
// stk = 1 has the frame key
// stk = 2 has the frame table
// stk = 3 has either a string or a number as key
// stk = 4 has the value for the key mentioned above
while (lua_next(L, stk))
{
int idx = 0;
const char *framestr = NULL;
switch (lua_type(L, stk+1))
{
case LUA_TSTRING:
framestr = lua_tostring(L, stk+1);
idx = R_Char2Frame(framestr[0]);
break;
case LUA_TNUMBER:
idx = lua_tonumber(L, stk+1);
idx = GetSpriteInfoFrameIndex(L, stk+1);
break;
default:
TYPEERROR("pivot frame", LUA_TNUMBER, lua_type(L, stk+1));
}
if ((idx < 0) || (idx >= MAXFRAMENUM))
return luaL_error(L, "pivot frame %d out of range (0 - %d)", idx, MAXFRAMENUM - 1);
// the values in pivot[] are also tables
if (PopPivotSubTable(info->pivot, L, stk+2, idx))
info->available = true;
if (PopPivotSubTable(&info->frames[idx], L, stk+2))
{
set_bit_array(info->available, idx);
// TODO: 2.3: Delete
info->frames[SPRINFO_DEFAULT_FRAME].pivot.available = true;
set_bit_array(info->available, SPRINFO_DEFAULT_FRAME);
}
lua_pop(L, 1);
}
......@@ -397,6 +496,14 @@ static int lib_setSpriteInfo(lua_State *L)
else
FIELDERROR("pivot", va("%s expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1)))
}
else if (str && fastcmp(str, "frames"))
{
// frames[] is a table
if (lua_istable(L, 3))
return PopFrameTable(info, L, 3);
else
FIELDERROR("frames", va("%s expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1)))
}
lua_pop(L, 1);
}
......@@ -422,17 +529,26 @@ static int spriteinfo_get(lua_State *L)
I_Assert(sprinfo != NULL);
// push spriteframepivot_t userdata
// TODO: 2.3: delete
if (fastcmp(field, "pivot"))
{
// bypass LUA_PushUserdata
void **userdata = lua_newuserdata(L, sizeof(void *));
*userdata = &sprinfo->pivot;
*userdata = sprinfo;
luaL_getmetatable(L, META_PIVOTLIST);
lua_setmetatable(L, -2);
// stack is left with the userdata on top, as if getting it had originally succeeded.
return 1;
}
else if (fastcmp(field, "frames"))
{
void **userdata = lua_newuserdata(L, sizeof(void *));
*userdata = sprinfo;
luaL_getmetatable(L, META_SPRITEINFOFRAMELIST);
lua_setmetatable(L, -2);
return 1;
}
else
return luaL_error(L, LUA_QL("spriteinfo_t") " has no field named " LUA_QS, field);
......@@ -465,9 +581,28 @@ static int spriteinfo_set(lua_State *L)
// pivot[] is userdata
else if (lua_isuserdata(L, 1))
{
spriteframepivot_t *pivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_PIVOTLIST));
memcpy(&sprinfo->pivot, pivot, sizeof(spriteframepivot_t));
sprinfo->available = true; // Just in case?
spriteinfo_t *copyinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST));
for (UINT16 i = 0; i <= MAXFRAMENUM; i++)
{
if (in_bit_array(copyinfo->available, i))
memcpy(&sprinfo->frames[i].pivot, &copyinfo->frames[i].pivot, sizeof(spriteframepivot_t));
}
}
}
else if (fastcmp(field, "frames"))
{
// frames[] is a table
if (lua_istable(L, 1))
return PopFrameTable(sprinfo, L, 1);
// frames[] is userdata
else if (lua_isuserdata(L, 1))
{
spriteinfo_t *copyinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEINFOFRAMELIST));
for (UINT16 i = 0; i <= MAXFRAMENUM; i++)
{
if (in_bit_array(copyinfo->available, i))
memcpy(&sprinfo->frames[i], &copyinfo->frames[i], sizeof(spriteinfoframe_t));
}
}
}
else
......@@ -487,21 +622,138 @@ static int spriteinfo_num(lua_State *L)
return 1;
}
// framepivot_t
static int pivotlist_get(lua_State *L)
// spriteinfoframe_t
static int framelist_get(lua_State *L)
{
struct SpriteInfoFrame *container;
spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEINFOFRAMELIST));
UINT16 frame = GetSpriteInfoFrameIndex(L, 2);
container = lua_newuserdata(L, sizeof *container);
container->sprinfo = sprinfo;
container->frame = frame;
luaL_getmetatable(L, META_SPRITEINFOFRAME);
lua_setmetatable(L, -2);
// stack is left with the userdata on top, as if getting it had originally succeeded.
return 1;
}
static int framelist_set(lua_State *L)
{
void **userdata;
spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_PIVOTLIST));
spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEINFOFRAMELIST));
UINT16 frame;
int okcool = 0;
if (!lua_lumploading)
return luaL_error(L, "Do not alter spriteinfoframe_t from within a hook or coroutine!");
if (hud_running)
return luaL_error(L, "Do not alter spriteinfoframe_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteinfoframe_t in CMD building code!");
frame = GetSpriteInfoFrameIndex(L, 2);
// frames[] is a table
if (lua_istable(L, 3))
okcool = PopFrameSubTable(&sprinfo->frames[frame], L, 3);
// frames[] is userdata
else if (lua_isuserdata(L, 3))
{
struct SpriteInfoFrame *container = luaL_checkudata(L, 3, META_SPRITEINFOFRAME);
memcpy(&sprinfo->frames[frame],
&container->sprinfo->frames[container->frame],
sizeof(spriteinfoframe_t));
okcool = 1;
}
if (okcool)
set_bit_array(sprinfo->available, frame);
return 0;
}
static int framelist_num(lua_State *L)
{
lua_pushinteger(L, MAXFRAMENUM);
return 1;
}
// spriteinfoframe_t
static int sprinfoframe_get(lua_State *L)
{
struct SpriteInfoFrame *container = luaL_checkudata(L, 1, META_SPRITEINFOFRAME);
const char *field = luaL_checkstring(L, 2);
UINT8 frame;
frame = R_Char2Frame(field[0]);
if (frame == 255)
luaL_error(L, "invalid frame %s", field);
if (fastcmp("pivot", field))
{
struct SpriteInfoFrame *other_container = lua_newuserdata(L, sizeof *container);
memcpy(other_container, container, sizeof *container);
luaL_getmetatable(L, META_FRAMEPIVOT);
lua_setmetatable(L, -2);
}
else
return luaL_error(L, "Field %s does not exist in spriteinfoframe_t", field);
return 1;
}
static int sprinfoframe_set(lua_State *L)
{
struct SpriteInfoFrame *container = luaL_checkudata(L, 1, META_SPRITEINFOFRAME);
spriteinfoframe_t *frame = &container->sprinfo->frames[container->frame];
UINT8 *available = container->sprinfo->available;
const char *field = luaL_checkstring(L, 2);
boolean is_available = false;
if (!lua_lumploading)
return luaL_error(L, "Do not alter spriteinfoframe_t from within a hook or coroutine!");
if (hud_running)
return luaL_error(L, "Do not alter spriteinfoframe_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteinfoframe_t in CMD building code!");
I_Assert(frame != NULL);
if (fastcmp("pivot", field))
{
// pivot[] is a table
if (lua_istable(L, 3))
{
if (PopPivotSubTable(frame, L, 3))
is_available = true;
}
// pivot[] is userdata
else if (lua_isuserdata(L, 3))
{
struct SpriteInfoFrame *other_container = luaL_checkudata(L, 3, META_FRAMEPIVOT);
memcpy(&frame->pivot,
&other_container->sprinfo->frames[other_container->frame].pivot,
sizeof(spriteframepivot_t));
is_available = true;
}
}
else
return luaL_error(L, "Field %s does not exist in spriteframepivot_t", field);
if (is_available)
{
set_bit_array(available, container->frame);
}
return 0;
}
// bypass LUA_PushUserdata
userdata = lua_newuserdata(L, sizeof(void *));
*userdata = &framepivot[frame];
// framepivot_t
static int pivotlist_get(lua_State *L)
{
struct SpriteInfoFrame *container;
spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST));
UINT16 frame = GetSpriteInfoFrameIndex(L, 2);
container = lua_newuserdata(L, sizeof *container);
container->sprinfo = sprinfo;
container->frame = frame;
luaL_getmetatable(L, META_FRAMEPIVOT);
lua_setmetatable(L, -2);
......@@ -511,11 +763,9 @@ static int pivotlist_get(lua_State *L)
static int pivotlist_set(lua_State *L)
{
// Because I already know it's a spriteframepivot_t anyway
spriteframepivot_t *pivotlist = *((spriteframepivot_t **)lua_touserdata(L, 1));
//spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_FRAMEPIVOT));
const char *field = luaL_checkstring(L, 2);
UINT8 frame;
spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_PIVOTLIST));
UINT16 frame;
int okcool = 0;
if (!lua_lumploading)
return luaL_error(L, "Do not alter spriteframepivot_t from within a hook or coroutine!");
......@@ -524,20 +774,24 @@ static int pivotlist_set(lua_State *L)
if (hook_cmd_running)
return luaL_error(L, "Do not alter spriteframepivot_t in CMD building code!");
frame = R_Char2Frame(field[0]);
if (frame == 255)
luaL_error(L, "invalid frame %s", field);
frame = GetSpriteInfoFrameIndex(L, 2);
// pivot[] is a table
if (lua_istable(L, 3))
return PopPivotSubTable(pivotlist, L, 3, frame);
okcool = PopPivotSubTable(&sprinfo->frames[frame], L, 3);
// pivot[] is userdata
else if (lua_isuserdata(L, 3))
{
spriteframepivot_t *copypivot = *((spriteframepivot_t **)luaL_checkudata(L, 3, META_FRAMEPIVOT));
memcpy(&pivotlist[frame], copypivot, sizeof(spriteframepivot_t));
struct SpriteInfoFrame *container = luaL_checkudata(L, 3, META_FRAMEPIVOT);
memcpy(&sprinfo->frames[frame].pivot,
&container->sprinfo->frames[container->frame].pivot,
sizeof(spriteframepivot_t));
okcool = 1;
}
if (okcool)
set_bit_array(sprinfo->available, frame);
return 0;
}
......@@ -549,7 +803,8 @@ static int pivotlist_num(lua_State *L)
static int framepivot_get(lua_State *L)
{
spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_FRAMEPIVOT));
struct SpriteInfoFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT);
spriteframepivot_t *framepivot = &container->sprinfo->frames[container->frame].pivot;
const char *field = luaL_checkstring(L, 2);
I_Assert(framepivot != NULL);
......@@ -572,7 +827,9 @@ static int framepivot_get(lua_State *L)
static int framepivot_set(lua_State *L)
{
spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_FRAMEPIVOT));
struct SpriteInfoFrame *container = luaL_checkudata(L, 1, META_FRAMEPIVOT);
spriteframepivot_t *framepivot = &container->sprinfo->frames[container->frame].pivot;
UINT8 *available = container->sprinfo->available;
const char *field = luaL_checkstring(L, 2);
if (!lua_lumploading)
......@@ -585,9 +842,15 @@ static int framepivot_set(lua_State *L)
I_Assert(framepivot != NULL);
if (fastcmp("x", field))
{
framepivot->x = luaL_checkinteger(L, 3);
set_bit_array(available, container->frame);
}
else if (fastcmp("y", field))
{
framepivot->y = luaL_checkinteger(L, 3);
set_bit_array(available, container->frame);
}
// TODO: 2.3: delete
else if (fastcmp("rotaxis", field))
LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.")
......@@ -714,21 +977,19 @@ static int lib_setState(lua_State *L)
switch(lua_type(L, 3))
{
case LUA_TNIL: // Null? Set the action to nothing, then.
state->action.acp1 = NULL;
state->action = NULL;
break;
case LUA_TSTRING: // It's a string, expect the name of a built-in action
LUA_SetActionByName(state, lua_tostring(L, 3));
break;
case LUA_TUSERDATA: // It's a userdata, expect META_ACTION of a built-in action
{
actionf_t *action = *((actionf_t **)luaL_checkudata(L, 3, META_ACTION));
actionf_p1 *action = *((actionf_p1 **)luaL_checkudata(L, 3, META_ACTION));
if (!action)
return luaL_error(L, "not a valid action?");
state->action = *action;
state->action.acv = action->acv;
state->action.acp1 = action->acp1;
break;
}
case LUA_TFUNCTION: // It's a function (a Lua function or a C function? either way!)
......@@ -738,7 +999,7 @@ static int lib_setState(lua_State *L)
lua_pushvalue(L, 3); // Bring it to the top of the stack
lua_rawset(L, -3); // Set it in the registry
lua_pop(L, 1); // pop LREG_STATEACTION
state->action.acp1 = (actionf_p1)A_Lua; // Set the action for the userdata.
state->action = (actionf_p1)A_Lua; // Set the action for the userdata.
break;
default: // ?!
return luaL_typerror(L, 3, "function");
......@@ -796,7 +1057,7 @@ boolean LUA_SetLuaAction(void *stv, const char *action)
lua_pop(gL, 1); // pop LREG_STATEACTION
lua_pop(gL, 2); // pop the function and LREG_ACTIONS
st->action.acp1 = (actionf_p1)A_Lua; // Set the action for the userdata.
st->action = (actionf_p1)A_Lua; // Set the action for the userdata.
return true; // action successfully set.
}
......@@ -901,9 +1162,9 @@ static int state_get(lua_State *L)
number = st->tics;
else if (fastcmp(field,"action")) {
const char *name;
if (!st->action.acp1) // Action is NULL.
if (!st->action) // Action is NULL.
return 0; // return nil.
if (st->action.acp1 == (actionf_p1)A_Lua) { // This is a Lua function?
if (st->action == (actionf_p1)A_Lua) { // This is a Lua function?
lua_getfield(L, LUA_REGISTRYINDEX, LREG_STATEACTION);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, st); // Push the state pointer and
......@@ -958,21 +1219,19 @@ static int state_set(lua_State *L)
switch(lua_type(L, 3))
{
case LUA_TNIL: // Null? Set the action to nothing, then.
st->action.acp1 = NULL;
st->action = NULL;
break;
case LUA_TSTRING: // It's a string, expect the name of a built-in action
LUA_SetActionByName(st, lua_tostring(L, 3));
break;
case LUA_TUSERDATA: // It's a userdata, expect META_ACTION of a built-in action
{
actionf_t *action = *((actionf_t **)luaL_checkudata(L, 3, META_ACTION));
actionf_p1 *action = *((actionf_p1 **)luaL_checkudata(L, 3, META_ACTION));
if (!action)
return luaL_error(L, "not a valid action?");
st->action = *action;
st->action.acv = action->acv;
st->action.acp1 = action->acp1;
break;
}
case LUA_TFUNCTION: // It's a function (a Lua function or a C function? either way!)
......@@ -982,7 +1241,7 @@ static int state_set(lua_State *L)
lua_pushvalue(L, 3); // Bring it to the top of the stack
lua_rawset(L, -3); // Set it in the registry
lua_pop(L, 1); // pop LREG_STATEACTION
st->action.acp1 = (actionf_p1)A_Lua; // Set the action for the userdata.
st->action = (actionf_p1)A_Lua; // Set the action for the userdata.
break;
default: // ?!
return luaL_typerror(L, 3, "function");
......@@ -1928,6 +2187,8 @@ int LUA_InfoLib(lua_State *L)
LUA_RegisterUserdataMetatable(L, META_COLORRAMP, colorramp_get, colorramp_set, colorramp_len);
LUA_RegisterUserdataMetatable(L, META_SFXINFO, sfxinfo_get, sfxinfo_set, sfxinfo_num);
LUA_RegisterUserdataMetatable(L, META_SPRITEINFO, spriteinfo_get, spriteinfo_set, spriteinfo_num);
LUA_RegisterUserdataMetatable(L, META_SPRITEINFOFRAMELIST, framelist_get, framelist_set, framelist_num);
LUA_RegisterUserdataMetatable(L, META_SPRITEINFOFRAME, sprinfoframe_get, sprinfoframe_set, NULL);
LUA_RegisterUserdataMetatable(L, META_PIVOTLIST, pivotlist_get, pivotlist_set, pivotlist_num);
LUA_RegisterUserdataMetatable(L, META_FRAMEPIVOT, framepivot_get, framepivot_set, framepivot_num);
LUA_RegisterUserdataMetatable(L, META_LUABANKS, lib_getluabanks, lib_setluabanks, lib_luabankslen);
......
......@@ -30,6 +30,8 @@ extern boolean ignoregameinputs;
#define META_SKINCOLOR "SKINCOLOR_T*"
#define META_COLORRAMP "SKINCOLOR_T*RAMP"
#define META_SPRITEINFO "SPRITEINFO_T*"
#define META_SPRITEINFOFRAMELIST "SPRITEINFOFRAME_T[]"
#define META_SPRITEINFOFRAME "SPRITEINFOFRAME_T*"
#define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]"
#define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*"
......@@ -55,13 +57,7 @@ extern boolean ignoregameinputs;
#define META_SUBSECTOR "SUBSECTOR_T*"
#define META_SECTOR "SECTOR_T*"
#define META_FFLOOR "FFLOOR_T*"
#ifdef HAVE_LUA_SEGS
#define META_SEG "SEG_T*"
#define META_NODE "NODE_T*"
#endif
#define META_SLOPE "PSLOPE_T*"
#define META_VECTOR2 "VECTOR2_T"
#define META_VECTOR3 "VECTOR3_T"
#define META_MAPHEADER "MAPHEADER_T*"
#define META_POLYOBJ "POLYOBJ_T*"
......@@ -83,10 +79,6 @@ extern boolean ignoregameinputs;
#define META_THINGCUSTOMARGS "MAPTHING_T*CUSTOMARGS"
#define META_POLYOBJVERTICES "POLYOBJ_T*VERTICES"
#define META_POLYOBJLINES "POLYOBJ_T*LINES"
#ifdef HAVE_LUA_SEGS
#define META_NODEBBOX "NODE_T*BBOX"
#define META_NODECHILDREN "NODE_T*CHILDREN"
#endif
#define META_BBOX "BOUNDING_BOX"
......@@ -106,6 +98,11 @@ extern boolean ignoregameinputs;
#define META_INTERCEPT "INTERCEPT_T*"
#define META_VECTOR2 "VECTOR2_T"
#define META_VECTOR3 "VECTOR3_T"
#define META_MATRIX "MATRIX_T"
#define META_QUATERNION "QUATERNION_T"
boolean luaL_checkboolean(lua_State *L, int narg);
int LUA_EnumLib(lua_State *L);
......@@ -127,3 +124,6 @@ int LUA_HudLib(lua_State *L);
int LUA_ColorLib(lua_State *L);
int LUA_InputLib(lua_State *L);
int LUA_InterceptLib(lua_State *L);
int LUA_MatrixLib(lua_State *L);
int LUA_QuaternionLib(lua_State *L);
int LUA_VectorLib(lua_State *L);
......@@ -360,72 +360,6 @@ static const char *const ffloor_opt[] = {
static int ffloor_fields_ref = LUA_NOREF;
#ifdef HAVE_LUA_SEGS
enum seg_e {
seg_valid = 0,
seg_v1,
seg_v2,
seg_side,
seg_offset,
seg_angle,
seg_sidedef,
seg_linedef,
seg_frontsector,
seg_backsector,
seg_polyseg
};
static const char *const seg_opt[] = {
"valid",
"v1",
"v2",
"side",
"offset",
"angle",
"sidedef",
"linedef",
"frontsector",
"backsector",
"polyseg",
NULL};
static int seg_fields_ref = LUA_NOREF;
enum node_e {
node_valid = 0,
node_x,
node_y,
node_dx,
node_dy,
node_bbox,
node_children,
};
static const char *const node_opt[] = {
"valid",
"x",
"y",
"dx",
"dy",
"bbox",
"children",
NULL};
static int node_fields_ref = LUA_NOREF;
enum nodechild_e {
nodechild_valid = 0,
nodechild_right,
nodechild_left,
};
static const char *const nodechild_opt[] = {
"valid",
"right",
"left",
NULL};
#endif
enum bbox_e {
bbox_valid = 0,
bbox_top,
......@@ -466,19 +400,6 @@ static const char *const slope_opt[] = {
static int slope_fields_ref = LUA_NOREF;
// shared by both vector2_t and vector3_t
enum vector_e {
vector_x = 0,
vector_y,
vector_z
};
static const char *const vector_opt[] = {
"x",
"y",
"z",
NULL};
static const char *const array_opt[] ={"iterate",NULL};
static const char *const valid_opt[] ={"valid",NULL};
......@@ -1623,246 +1544,6 @@ static int vertex_num(lua_State *L)
return 1;
}
#ifdef HAVE_LUA_SEGS
///////////
// seg_t //
///////////
static int seg_get(lua_State *L)
{
seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG));
enum seg_e field = Lua_optoption(L, 2, seg_valid, seg_fields_ref);
if (!seg)
{
if (field == seg_valid) {
lua_pushboolean(L, 0);
return 1;
}
return luaL_error(L, "accessed seg_t doesn't exist anymore.");
}
switch(field)
{
case seg_valid: // valid
lua_pushboolean(L, 1);
return 1;
case seg_v1:
LUA_PushUserdata(L, seg->v1, META_VERTEX);
return 1;
case seg_v2:
LUA_PushUserdata(L, seg->v2, META_VERTEX);
return 1;
case seg_side:
lua_pushinteger(L, seg->side);
return 1;
case seg_offset:
lua_pushfixed(L, seg->offset);
return 1;
case seg_angle:
lua_pushangle(L, seg->angle);
return 1;
case seg_sidedef:
LUA_PushUserdata(L, seg->sidedef, META_SIDE);
return 1;
case seg_linedef:
LUA_PushUserdata(L, seg->linedef, META_LINE);
return 1;
case seg_frontsector:
LUA_PushUserdata(L, seg->frontsector, META_SECTOR);
return 1;
case seg_backsector:
LUA_PushUserdata(L, seg->backsector, META_SECTOR);
return 1;
case seg_polyseg:
LUA_PushUserdata(L, seg->polyseg, META_POLYOBJ);
return 1;
}
return 0;
}
static int seg_num(lua_State *L)
{
seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG));
lua_pushinteger(L, seg-segs);
return 1;
}
////////////
// node_t //
////////////
static int node_get(lua_State *L)
{
node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE));
enum node_e field = Lua_optoption(L, 2, node_valid, node_fields_ref);
if (!node)
{
if (field == node_valid) {
lua_pushboolean(L, 0);
return 1;
}
return luaL_error(L, "accessed node_t doesn't exist anymore.");
}
switch(field)
{
case node_valid: // valid
lua_pushboolean(L, 1);
return 1;
case node_x:
lua_pushfixed(L, node->x);
return 1;
case node_y:
lua_pushfixed(L, node->y);
return 1;
case node_dx:
lua_pushfixed(L, node->x);
return 1;
case node_dy:
lua_pushfixed(L, node->x);
return 1;
case node_bbox:
LUA_PushUserdata(L, node->bbox, META_NODEBBOX);
return 1;
case node_children:
LUA_PushUserdata(L, node->children, META_NODECHILDREN);
return 1;
}
return 0;
}
static int node_num(lua_State *L)
{
node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE));
lua_pushinteger(L, node-nodes);
return 1;
}
///////////////
// node.bbox //
///////////////
/*
// node.bbox[i][j]: i = 0 or 1, j = 0 1 2 or 3
// NOTE: 2D arrays are NOT double pointers,
// the second bbox will be directly after the first in memory (hence the way the bbox is pushed here)
// this function handles the [i] part, bbox_get handles the [j] part
static int nodebbox_get(lua_State *L)
{
fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_NODEBBOX));
int i;
lua_settop(L, 2);
if (!lua_isnumber(L, 2))
{
int field = luaL_checkoption(L, 2, NULL, valid_opt);
if (!bbox)
{
if (field == 0) {
lua_pushboolean(L, 0);
return 1;
}
return luaL_error(L, "accessed node_t doesn't exist anymore.");
} else if (field == 0) {
lua_pushboolean(L, 1);
return 1;
}
}
i = lua_tointeger(L, 2);
if (i < 0 || i > 1)
return 0;
LUA_PushUserdata(L, bbox + i*4*sizeof(fixed_t), META_BBOX);
return 1;
}
*/
static int nodebbox_call(lua_State *L)
{
fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_NODEBBOX));
int i, j;
int n = lua_gettop(L);
if (!bbox)
return luaL_error(L, "accessed node bbox doesn't exist anymore.");
if (n < 3)
return luaL_error(L, "arguments 2 and/or 3 not given (expected node.bbox(child, coord))");
// get child
if (!lua_isnumber(L, 2)) {
enum nodechild_e field = luaL_checkoption(L, 2, nodechild_opt[0], nodechild_opt);
switch (field) {
case nodechild_right: i = 0; break;
case nodechild_left: i = 1; break;
default:
return luaL_error(L, "invalid node child \"%s\".", lua_tostring(L, 2));
}
}
else {
i = lua_tointeger(L, 2);
if (i < 0 || i > 1)
return 0;
}
// get bbox coord
if (!lua_isnumber(L, 3)) {
enum bbox_e field = luaL_checkoption(L, 3, bbox_opt[0], bbox_opt);
switch (field) {
case bbox_top: j = BOXTOP; break;
case bbox_bottom: j = BOXBOTTOM; break;
case bbox_left: j = BOXLEFT; break;
case bbox_right: j = BOXRIGHT; break;
default:
return luaL_error(L, "invalid bbox coordinate \"%s\".", lua_tostring(L, 3));
}
}
else {
j = lua_tointeger(L, 3);
if (j < 0 || j > 3)
return 0;
}
lua_pushinteger(L, bbox[i*4 + j]);
return 1;
}
/////////////////////
// node.children[] //
/////////////////////
// node.children[i]: i = 0 or 1
static int nodechildren_get(lua_State *L)
{
UINT16 *children = *((UINT16 **)luaL_checkudata(L, 1, META_NODECHILDREN));
int i;
lua_settop(L, 2);
if (!lua_isnumber(L, 2))
{
enum nodechild_e field = luaL_checkoption(L, 2, nodechild_opt[0], nodechild_opt);
if (!children)
{
if (field == nodechild_valid) {
lua_pushboolean(L, 0);
return 1;
}
return luaL_error(L, "accessed node_t doesn't exist anymore.");
} else if (field == nodechild_valid) {
lua_pushboolean(L, 1);
return 1;
} else switch (field) {
case nodechild_right: i = 0; break;
case nodechild_left: i = 1; break;
default: return 0;
}
}
else {
i = lua_tointeger(L, 2);
if (i < 0 || i > 1)
return 0;
}
lua_pushinteger(L, children[i]);
return 1;
}
#endif
//////////
// bbox //
//////////
......@@ -2144,113 +1825,6 @@ static int lib_numvertexes(lua_State *L)
return 1;
}
#ifdef HAVE_LUA_SEGS
////////////
// segs[] //
////////////
static int lib_iterateSegs(lua_State *L)
{
size_t i = 0;
INLEVEL
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do <block> end'.");
lua_settop(L, 2);
lua_remove(L, 1); // state is unused.
if (!lua_isnil(L, 1))
i = (size_t)(*((seg_t **)luaL_checkudata(L, 1, META_SEG)) - segs)+1;
if (i < numsegs)
{
LUA_PushUserdata(L, &segs[i], META_SEG);
return 1;
}
return 0;
}
static int lib_getSeg(lua_State *L)
{
int field;
INLEVEL
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
{
size_t i = lua_tointeger(L, 1);
if (i >= numsegs)
return 0;
LUA_PushUserdata(L, &segs[i], META_SEG);
return 1;
}
field = luaL_checkoption(L, 1, NULL, array_opt);
switch(field)
{
case 0: // iterate
lua_pushcfunction(L, lib_iterateSegs);
return 1;
}
return 0;
}
static int lib_numsegs(lua_State *L)
{
lua_pushinteger(L, numsegs);
return 1;
}
/////////////
// nodes[] //
/////////////
static int lib_iterateNodes(lua_State *L)
{
size_t i = 0;
INLEVEL
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do <block> end'.");
lua_settop(L, 2);
lua_remove(L, 1); // state is unused.
if (!lua_isnil(L, 1))
i = (size_t)(*((node_t **)luaL_checkudata(L, 1, META_NODE)) - nodes)+1;
if (i < numsegs)
{
LUA_PushUserdata(L, &nodes[i], META_NODE);
return 1;
}
return 0;
}
static int lib_getNode(lua_State *L)
{
int field;
INLEVEL
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
{
size_t i = lua_tointeger(L, 1);
if (i >= numnodes)
return 0;
LUA_PushUserdata(L, &nodes[i], META_NODE);
return 1;
}
field = luaL_checkoption(L, 1, NULL, array_opt);
switch(field)
{
case 0: // iterate
lua_pushcfunction(L, lib_iterateNodes);
return 1;
}
return 0;
}
static int lib_numnodes(lua_State *L)
{
lua_pushinteger(L, numnodes);
return 1;
}
#endif
//////////////
// ffloor_t //
//////////////
......@@ -2795,47 +2369,6 @@ static int slope_set(lua_State *L)
return 0;
}
///////////////
// vector*_t //
///////////////
static int vector2_get(lua_State *L)
{
vector2_t *vec = *((vector2_t **)luaL_checkudata(L, 1, META_VECTOR2));
enum vector_e field = luaL_checkoption(L, 2, vector_opt[0], vector_opt);
if (!vec)
return luaL_error(L, "accessed vector2_t doesn't exist anymore.");
switch(field)
{
case vector_x: lua_pushfixed(L, vec->x); return 1;
case vector_y: lua_pushfixed(L, vec->y); return 1;
default: break;
}
return 0;
}
static int vector3_get(lua_State *L)
{
vector3_t *vec = *((vector3_t **)luaL_checkudata(L, 1, META_VECTOR3));
enum vector_e field = luaL_checkoption(L, 2, vector_opt[0], vector_opt);
if (!vec)
return luaL_error(L, "accessed vector3_t doesn't exist anymore.");
switch(field)
{
case vector_x: lua_pushfixed(L, vec->x); return 1;
case vector_y: lua_pushfixed(L, vec->y); return 1;
case vector_z: lua_pushfixed(L, vec->z); return 1;
default: break;
}
return 0;
}
/////////////////////
// mapheaderinfo[] //
/////////////////////
......@@ -3156,8 +2689,6 @@ int LUA_MapLib(lua_State *L)
LUA_RegisterUserdataMetatable(L, META_FFLOOR, ffloor_get, ffloor_set, NULL);
LUA_RegisterUserdataMetatable(L, META_BBOX, bbox_get, NULL, NULL);
LUA_RegisterUserdataMetatable(L, META_SLOPE, slope_get, slope_set, NULL);
LUA_RegisterUserdataMetatable(L, META_VECTOR2, vector2_get, NULL, NULL);
LUA_RegisterUserdataMetatable(L, META_VECTOR3, vector3_get, NULL, NULL);
LUA_RegisterUserdataMetatable(L, META_MAPHEADER, mapheaderinfo_get, NULL, NULL);
LUA_RegisterUserdataMetatable(L, META_THINGCUSTOMARGS, thingcustomargs_get, NULL, NULL);
......@@ -3191,22 +2722,5 @@ int LUA_MapLib(lua_State *L)
&numlines, &lines,
sizeof (line_t), META_LINE);
#ifdef HAVE_LUA_SEGS
LUA_RegisterUserdataMetatable(L, META_SEG, seg_get, NULL, seg_num);
LUA_RegisterUserdataMetatable(L, META_NODE, node_get, NULL, node_num);
LUA_RegisterUserdataMetatable(L, META_NODECHILDREN, nodechildren_get, NULL, NULL);
seg_fields_ref = Lua_CreateFieldTable(L, seg_opt);
node_fields_ref = Lua_CreateFieldTable(L, node_opt);
luaL_newmetatable(L, META_NODEBBOX);
//LUA_SetCFunctionField(L, "__index", nodebbox_get);
LUA_SetCFunctionField(L, "__call", nodebbox_call);
lua_pop(L, 1);
LUA_RegisterGlobalUserdata(L, "segs", lib_getSeg, NULL, lib_numsegs);
LUA_RegisterGlobalUserdata(L, "nodes", lib_getNode, NULL, lib_numnodes);
#endif
return 0;
}