Skip to content
Snippets Groups Projects

Compare revisions

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

Source

Select target project
No results found

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Hanicef/SRB2Classic
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Jisk/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • PAS/SRB2Classic
  • BlueStaggo/SRB2
118 results
Show changes
Commits on Source (18)
......@@ -154,8 +154,8 @@ HW3SOUND for 3D hardware sound support
<Add directory="libs/gme/include" />
</Compiler>
<Linker>
<Add library="SDL" />
<Add library="SDL_mixer" />
<Add library="SDL2" />
<Add library="SDL2_mixer" />
<Add library="advapi32" />
<Add library="kernel32" />
<Add library="msvcrt" />
......@@ -200,8 +200,8 @@ HW3SOUND for 3D hardware sound support
<Add directory="libs/gme/include" />
</Compiler>
<Linker>
<Add library="SDL" />
<Add library="SDL_mixer" />
<Add library="SDL2" />
<Add library="SDL2_mixer" />
<Add library="advapi32" />
<Add library="kernel32" />
<Add library="msvcrt" />
......@@ -4141,283 +4141,170 @@ HW3SOUND for 3D hardware sound support
<Option target="Debug Mingw64/DirectX" />
<Option target="Release Mingw64/DirectX" />
</Unit>
<Unit filename="src/sdl/IMG_xpm.c">
<Unit filename="src/sdl2/IMG_xpm.c">
<Option compilerVar="CC" />
<Option compile="0" />
<Option link="0" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Any/Dummy" />
<Option target="Release Any/Dummy" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/dosstr.c">
<Option compilerVar="CC" />
<Unit filename="src/sdl2/SDL_icon.xpm">
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/endtxt.c">
<Unit filename="src/sdl2/dosstr.c">
<Option compilerVar="CC" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
</Unit>
<Unit filename="src/sdl/endtxt.h">
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Any/Dummy" />
<Option target="Release Any/Dummy" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
</Unit>
<Unit filename="src/sdl/filter/filters.c">
<Unit filename="src/sdl2/endtxt.c">
<Option compilerVar="CC" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/filter/filters.h">
<Unit filename="src/sdl2/endtxt.h">
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Any/Dummy" />
<Option target="Release Any/Dummy" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/filter/hq2x.c">
<Unit filename="src/sdl2/hwsym_sdl.c">
<Option compilerVar="CC" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
</Unit>
<Unit filename="src/sdl/filter/hq2x.h">
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Any/Dummy" />
<Option target="Release Any/Dummy" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
</Unit>
<Unit filename="src/sdl/filter/interp.h">
<Unit filename="src/sdl2/hwsym_sdl.h">
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Any/Dummy" />
<Option target="Release Any/Dummy" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/filter/lq2x.c">
<Unit filename="src/sdl2/i_cdmus.c">
<Option compilerVar="CC" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
</Unit>
<Unit filename="src/sdl/filter/lq2x.h">
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Any/Dummy" />
<Option target="Release Any/Dummy" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
</Unit>
<Unit filename="src/sdl/filter/main.c">
<Unit filename="src/sdl2/i_main.c">
<Option compilerVar="CC" />
<Option compile="0" />
<Option link="0" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Any/Dummy" />
<Option target="Release Any/Dummy" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/hwsym_sdl.c">
<Unit filename="src/sdl2/i_net.c">
<Option compilerVar="CC" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
</Unit>
<Unit filename="src/sdl/hwsym_sdl.h">
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Any/Dummy" />
<Option target="Release Any/Dummy" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
</Unit>
<Unit filename="src/sdl/i_cdmus.c">
<Unit filename="src/sdl2/i_system.c">
<Option compilerVar="CC" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/i_main.c">
<Unit filename="src/sdl2/i_ttf.c">
<Option compilerVar="CC" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/i_net.c">
<Option compilerVar="CC" />
<Unit filename="src/sdl2/i_ttf.h">
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/i_system.c">
<Unit filename="src/sdl2/i_video.c">
<Option compilerVar="CC" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/i_video.c">
<Unit filename="src/sdl2/mixer_sound.c">
<Option compilerVar="CC" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
</Unit>
<Unit filename="src/sdl/mixer_sound.c">
<Option compilerVar="CC" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
</Unit>
<Unit filename="src/sdl/ogl_sdl.c">
<Unit filename="src/sdl2/ogl_sdl.c">
<Option compilerVar="CC" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/ogl_sdl.h">
<Unit filename="src/sdl2/ogl_sdl.h">
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Any/Dummy" />
<Option target="Release Any/Dummy" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/sdl_sound.c">
<Unit filename="src/sdl2/sdl_sound.c">
<Option compilerVar="CC" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sdl/sdlmain.h">
<Unit filename="src/sdl2/sdlmain.h">
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
<Option target="Debug Any/Dummy" />
<Option target="Release Any/Dummy" />
<Option target="Debug Linux/SDL" />
<Option target="Release Linux/SDL" />
<Option target="Debug Mingw64/SDL" />
<Option target="Release Mingw64/SDL" />
<Option target="Debug Mingw/SDL" />
<Option target="Release Mingw/SDL" />
</Unit>
<Unit filename="src/sounds.c">
<Option compilerVar="CC" />
......@@ -4590,13 +4477,13 @@ HW3SOUND for 3D hardware sound support
</Unit>
<Unit filename="src/vid_copy.s">
<Option compilerVar="CC" />
<Option compiler="avrgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="gcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="ppcgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="gnu_gcc_compiler_for_mingw32" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="gnu_gcc_compiler_for_mingw64" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="armelfgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="tricoregcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="ppcgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="gcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="avrgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option compiler="gnu_gcc_compiler_for_mingw64" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
<Option target="Debug Native/SDL" />
<Option target="Release Native/SDL" />
<Option target="Debug Linux/SDL" />
......
......@@ -27,7 +27,6 @@ find_library(SDL2_LIBRARY
"/usr/local/lib"
)
# set include dir variables
set(SDL2_PROCESS_INCLUDES SDL2_INCLUDE_DIR)
set(SDL2_PROCESS_LIBS SDL2_LIBRARY)
......
......@@ -150,6 +150,7 @@ set(SRB2_CORE_GAME_SOURCES
p_saveg.c
p_setup.c
p_sight.c
p_slopes.c
p_spec.c
p_telept.c
p_tick.c
......@@ -162,6 +163,7 @@ set(SRB2_CORE_GAME_SOURCES
p_pspr.h
p_saveg.h
p_setup.h
p_slopes.h
p_spec.h
p_tick.h
)
......
......@@ -454,6 +454,7 @@ OBJS:=$(i_main_o) \
$(OBJDIR)/p_telept.o \
$(OBJDIR)/p_tick.o \
$(OBJDIR)/p_user.o \
$(OBJDIR)/p_slopes.o \
$(OBJDIR)/tables.o \
$(OBJDIR)/r_bsp.o \
$(OBJDIR)/r_data.o \
......
......@@ -11,6 +11,13 @@
#include <limits.h>
#include <stddef.h>
#ifdef _MSC_VER
#define INT32 __int32
#else
#include <stdint.h>
#define INT32 int32_t
#endif
/*
** ==================================================================
......@@ -140,7 +147,7 @@
** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
** machines, ptrdiff_t gives a good choice between int or long.)
*/
#define LUA_INTEGER ptrdiff_t
#define LUA_INTEGER INT32
/*
......@@ -502,13 +509,13 @@
*/
//#define LUA_NUMBER_DOUBLE
#define LUA_NUMBER ptrdiff_t
#define LUA_NUMBER INT32
/*
@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
@* over a number.
*/
#define LUAI_UACNUMBER ptrdiff_t
#define LUAI_UACNUMBER INT32
/*
......@@ -519,14 +526,14 @@
@@ lua_str2number converts a string to a number.
*/
#ifdef LUA_WIN
#define LUA_NUMBER_SCAN "%Ii"
#define LUA_NUMBER_FMT "%Ii"
#define LUA_NUMBER_SCAN "%d"
#define LUA_NUMBER_FMT "%d"
#else
#define LUA_NUMBER_SCAN "%ti"
#define LUA_NUMBER_FMT "%ti"
#define LUA_NUMBER_SCAN "%d"
#define LUA_NUMBER_FMT "%d"
#endif
#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
#define LUAI_MAXNUMBER2STR 12 /* 10 digits, sign, and \0 */
#define lua_str2number(s,p) strtol((s), (p), 10)
......
......@@ -96,6 +96,10 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#include "hardware/hw3sound.h"
#endif
#ifdef HAVE_BLUA
#include "lua_script.h"
#endif
// platform independant focus loss
UINT8 window_notinfocus = false;
......@@ -634,6 +638,10 @@ void D_SRB2Loop(void)
#ifdef HW3SOUND
HW3S_EndFrameUpdate();
#endif
#ifdef HAVE_BLUA
LUA_Step();
#endif
}
}
......@@ -836,6 +844,10 @@ static void IdentifyVersion(void)
// Add our crappy patches to fix our bugs
// D_AddFile(va(pandf,srb2waddir,"patch.dta"));
// Add the thokker WAD
if (M_CheckParm("-nothokker") == 0)
D_AddFile(va(pandf,srb2waddir,"thokker.thk"));
#if !defined (HAVE_SDL) || defined (HAVE_MIXER)
{
#if defined (DC) && 0
......@@ -943,9 +955,9 @@ void D_SRB2Main(void)
#endif
#if defined (_WIN32_WCE) //|| defined (_DEBUG) || defined (GP2X)
devparm = !M_CheckParm("-nodebug");
devparm = M_CheckParm("-nodebug") == 0;
#else
devparm = M_CheckParm("-debug");
devparm = M_CheckParm("-debug") != 0;
#endif
// for dedicated server
......@@ -1118,7 +1130,7 @@ void D_SRB2Main(void)
#endif
D_CleanFile();
#if 1 // md5s last updated 12/14/14
#ifndef DEVELOP // md5s last updated 12/14/14
// Check MD5s of autoloaded files
W_VerifyFileMD5(0, ASSET_HASH_SRB2_SRB); // srb2.srb/srb2.wad
......
......@@ -44,6 +44,7 @@
#include "lua_hook.h"
#include "m_cond.h"
#include "m_anigif.h"
#include "m_argv.h"
#ifdef NETGAME_DEVMODE
#define CV_RESTRICT CV_NETVAR
......@@ -1618,7 +1619,10 @@ static void Command_Map_f(void)
// new gametype value
// use current one by default
i = COM_CheckParm("-gametype");
if (i)
if (M_CheckParm("-nothokker") == 0)
newgametype = GT_TEAMMATCH;
else if (i)
{
if (!multiplayer)
{
......@@ -3193,7 +3197,27 @@ static void Command_ModDetails_f(void)
//
static void Command_ShowGametype_f(void)
{
CONS_Printf(M_GetText("Current gametype is %d\n"), gametype);
INT32 j;
const char *gametypestr = NULL;
if (!(netgame || multiplayer)) // print "Single player" instead of "Co-op"
{
CONS_Printf(M_GetText("Current gametype is %s\n"), M_GetText("Single player"));
return;
}
// find name string for current gametype
for (j = 0; gametype_cons_t[j].strvalue; j++)
{
if (gametype_cons_t[j].value == gametype)
{
gametypestr = gametype_cons_t[j].strvalue;
break;
}
}
if (gametypestr)
CONS_Printf(M_GetText("Current gametype is %s\n"), gametypestr);
else // string for current gametype was not found above (should never happen)
CONS_Printf(M_GetText("Unknown gametype set (%d)\n"), gametype);
}
/** Plays the intro.
......@@ -3351,8 +3375,13 @@ void D_GameTypeChanged(INT32 lastgametype)
if (!cv_timelimit.changed && !cv_pointlimit.changed) // user hasn't changed limits
{
// default settings for match: timelimit 10 mins, no pointlimit
CV_SetValue(&cv_pointlimit, 0);
CV_SetValue(&cv_timelimit, 10);
if (M_CheckParm("-nothokker") != 0) {
CV_SetValue(&cv_pointlimit, 0);
CV_SetValue(&cv_timelimit, 10);
} else {
CV_SetValue(&cv_pointlimit, 3);
CV_SetValue(&cv_timelimit, 0);
}
}
if (!cv_itemrespawntime.changed)
CV_Set(&cv_itemrespawntime, cv_itemrespawntime.defaultvalue); // respawn normally
......
......@@ -473,6 +473,7 @@ static void readPlayer(MYFILE *f, INT32 num)
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
PlayerMenu[num].status = IT_CALL;
for (i = 0; i < MAXLINELEN-3; i++)
{
......@@ -545,6 +546,7 @@ static void readPlayer(MYFILE *f, INT32 num)
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
DEH_WriteUndoline(word, &description[num].picname[0], UNDO_NONE);
PlayerMenu[num].status = IT_CALL;
strncpy(description[num].picname, word2, 8);
}
else if (fastcmp(word, "STATUS"))
......@@ -576,6 +578,8 @@ static void readPlayer(MYFILE *f, INT32 num)
if (!slotfound && (slotfound = findFreeSlot(&num)) == false)
goto done;
DEH_WriteUndoline(word, description[num].skinname, UNDO_NONE);
PlayerMenu[num].status = IT_CALL;
strlcpy(description[num].skinname, word2, sizeof description[num].skinname);
strlwr(description[num].skinname);
}
......@@ -1023,6 +1027,9 @@ static void readlevelheader(MYFILE *f, INT32 num)
if (s == tmp)
continue; // Skip comment lines, but don't break.
// Set / reset word, because some things (Lua.) move it
//word = s;
// Get the part before the " = "
tmp = strchr(s, '=');
*(tmp-1) = '\0';
......@@ -3807,7 +3814,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Blue Crawla
"S_POSS_STND",
"S_POSS_STND2",
"S_POSS_RUN1",
"S_POSS_RUN2",
"S_POSS_RUN3",
......@@ -3817,7 +3823,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Red Crawla
"S_SPOS_STND",
"S_SPOS_STND2",
"S_SPOS_RUN1",
"S_SPOS_RUN2",
"S_SPOS_RUN3",
......@@ -7172,7 +7177,6 @@ static const char *const MOBJFLAG2_LIST[] = {
"EXPLOSION", // Thrown ring has explosive properties
"SCATTER", // Thrown ring has scatter properties
"BEYONDTHEGRAVE",// Source of this missile has died and has since respawned.
"PUSHED", // Mobj was already pushed this tic
"SLIDEPUSH", // MF_PUSHABLE that pushes continuously.
"CLASSICPUSH", // Drops straight down when object has negative Z.
"STANDONME", // While not pushable, stand on me anyway.
......@@ -7201,6 +7205,9 @@ static const char *const MOBJEFLAG_LIST[] = {
"JUSTSTEPPEDDOWN", // used for ramp sectors
"VERTICALFLIP", // Vertically flip sprite/allow upside-down physics
"GOOWATER", // Goo water
"PUSHED", // Mobj was already pushed this tic
"SPRUNG", // Mobj was already sprung this tic
"APPLYPMOMZ", // Platform movement
NULL
};
......@@ -7303,6 +7310,7 @@ static const char *const ML_LIST[16] = {
};
// This DOES differ from r_draw's Color_Names, unfortunately.
// Also includes Super colors
static const char *COLOR_ENUMS[] = {
"NONE", // SKINCOLOR_NONE
"WHITE", // SKINCOLOR_WHITE
......@@ -7329,7 +7337,25 @@ static const char *COLOR_ENUMS[] = {
"ZIM", // SKINCOLOR_ZIM
"OLIVE", // SKINCOLOR_OLIVE
"YELLOW", // SKINCOLOR_YELLOW
"GOLD" // SKINCOLOR_GOLD
"GOLD", // SKINCOLOR_GOLD
// Super special awesome Super flashing colors!
"SUPER1", // SKINCOLOR_SUPER1
"SUPER2", // SKINCOLOR_SUPER2,
"SUPER3", // SKINCOLOR_SUPER3,
"SUPER4", // SKINCOLOR_SUPER4,
"SUPER5", // SKINCOLOR_SUPER5,
// Super Tails
"TSUPER1", // SKINCOLOR_TSUPER1,
"TSUPER2", // SKINCOLOR_TSUPER2,
"TSUPER3", // SKINCOLOR_TSUPER3,
"TSUPER4", // SKINCOLOR_TSUPER4,
"TSUPER5", // SKINCOLOR_TSUPER5,
// Super Knuckles
"KSUPER1", // SKINCOLOR_KSUPER1,
"KSUPER2", // SKINCOLOR_KSUPER2,
"KSUPER3", // SKINCOLOR_KSUPER3,
"KSUPER4", // SKINCOLOR_KSUPER4,
"KSUPER5" // SKINCOLOR_KSUPER5,
};
static const char *const POWERS_LIST[] = {
......@@ -7536,8 +7562,9 @@ struct {
{"EMERALD6",EMERALD6},
{"EMERALD7",EMERALD7},
// SKINCOLOR_ doesn't include this..!
// SKINCOLOR_ doesn't include these..!
{"MAXSKINCOLORS",MAXSKINCOLORS},
{"MAXTRANSLATIONS",MAXTRANSLATIONS},
// Precipitation
{"PRECIP_NONE",PRECIP_NONE},
......@@ -7730,36 +7757,36 @@ struct {
{"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop.
// Angles
{"ANG1",ANG1},
{"ANG2",ANG2},
{"ANG10",ANG10},
{"ANG15",ANG15},
{"ANG20",ANG20},
{"ANG30",ANG30},
{"ANG60",ANG60},
{"ANG64h",ANG64h},
{"ANG105",ANG105},
{"ANG210",ANG210},
{"ANG255",ANG255},
{"ANG340",ANG340},
{"ANG350",ANG350},
{"ANGLE_11hh",ANGLE_11hh},
{"ANGLE_22h",ANGLE_22h},
{"ANGLE_45",ANGLE_45},
{"ANGLE_67h",ANGLE_67h},
{"ANGLE_90",ANGLE_90},
{"ANGLE_112h",ANGLE_112h},
{"ANGLE_135",ANGLE_135},
{"ANGLE_157h",ANGLE_157h},
{"ANGLE_180",ANGLE_180},
{"ANGLE_202h",ANGLE_202h},
{"ANGLE_225",ANGLE_225},
{"ANGLE_247h",ANGLE_247h},
{"ANGLE_270",ANGLE_270},
{"ANGLE_292h",ANGLE_292h},
{"ANGLE_315",ANGLE_315},
{"ANGLE_337h",ANGLE_337h},
{"ANGLE_MAX",ANGLE_MAX},
{"ANG1",ANG1>>0},
{"ANG2",ANG2>>0},
{"ANG10",ANG10>>0},
{"ANG15",ANG15>>0},
{"ANG20",ANG20>>0},
{"ANG30",ANG30>>0},
{"ANG60",ANG60>>0},
{"ANG64h",ANG64h>>0},
{"ANG105",ANG105>>0},
{"ANG210",ANG210>>0},
{"ANG255",ANG255>>0},
{"ANG340",ANG340>>0},
{"ANG350",ANG350>>0},
{"ANGLE_11hh",ANGLE_11hh>>0},
{"ANGLE_22h",ANGLE_22h>>0},
{"ANGLE_45",ANGLE_45>>0},
{"ANGLE_67h",ANGLE_67h>>0},
{"ANGLE_90",ANGLE_90>>0},
{"ANGLE_112h",ANGLE_112h>>0},
{"ANGLE_135",ANGLE_135>>0},
{"ANGLE_157h",ANGLE_157h>>0},
{"ANGLE_180",ANGLE_180>>0},
{"ANGLE_202h",ANGLE_202h>>0},
{"ANGLE_225",ANGLE_225>>0},
{"ANGLE_247h",ANGLE_247h>>0},
{"ANGLE_270",ANGLE_270>>0},
{"ANGLE_292h",ANGLE_292h>>0},
{"ANGLE_315",ANGLE_315>>0},
{"ANGLE_337h",ANGLE_337h>>0},
{"ANGLE_MAX",ANGLE_MAX>>0},
// P_Chase directions (dirtype_t)
{"DI_NODIR",DI_NODIR},
......@@ -8158,7 +8185,7 @@ static fixed_t find_const(const char **rword)
}
else if (fastncmp("SKINCOLOR_",word,10)) {
char *p = word+10;
for (i = 0; i < MAXSKINCOLORS; i++)
for (i = 0; i < MAXTRANSLATIONS; i++)
if (fastcmp(p, COLOR_ENUMS[i])) {
free(word);
return i;
......@@ -8217,8 +8244,8 @@ void DEH_Check(void)
if (dehpowers != NUMPOWERS)
I_Error("You forgot to update the Dehacked powers list, you dolt!\n(%d powers defined, versus %s in the Dehacked list)\n", NUMPOWERS, sizeu1(dehpowers));
if (dehcolors != MAXSKINCOLORS)
I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", MAXSKINCOLORS, sizeu1(dehcolors));
if (dehcolors != MAXTRANSLATIONS)
I_Error("You forgot to update the Dehacked colors list, you dolt!\n(%d colors defined, versus %s in the Dehacked list)\n", MAXTRANSLATIONS, sizeu1(dehcolors));
#endif
}
......@@ -8572,7 +8599,7 @@ static inline int lib_getenum(lua_State *L)
}
else if (fastncmp("SKINCOLOR_",word,10)) {
p = word+10;
for (i = 0; i < MAXSKINCOLORS; i++)
for (i = 0; i < MAXTRANSLATIONS; i++)
if (fastcmp(p, COLOR_ENUMS[i])) {
lua_pushinteger(L, i);
return 1;
......@@ -8697,7 +8724,7 @@ static inline int lib_getenum(lua_State *L)
lua_pushinteger(L, mapmusic);
return 1;
} else if (fastcmp(word,"server")) {
if (!playeringame[serverplayer])
if ((!multiplayer || !netgame) && !playeringame[serverplayer])
return 0;
LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
return 1;
......
......@@ -138,15 +138,17 @@
extern FILE *logstream;
#endif
#if 0
//#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3
#ifdef DEVELOP
#define VERSION 0 // Game version
#define SUBVERSION 0 // more precise version number
#define VERSIONSTRING "Trunk"
#define VERSIONSTRINGW L"Trunk"
#else
#define VERSION 201 // Game version
#define SUBVERSION 14 // more precise version number
#define VERSIONSTRING "v2.1.14"
#define VERSIONSTRINGW L"v2.1.14"
#define VERSION 165 // Game version
#define SUBVERSION 1
#define VERSIONSTRING "v2.1.14 (Thokker 1.0.1)"
#define VERSIONSTRINGW L"v2.1.14 (Thokker 1.0.1)"
// Hey! If you change this, add 1 to the MODVERSION below!
// Otherwise we can't force updates!
#endif
......@@ -162,8 +164,8 @@ extern FILE *logstream;
// The string used in the alert that pops up in the event of an update being available.
// Please change to apply to your modification (we don't want everyone asking where your mod is on SRB2.org!).
#define UPDATE_ALERT_STRING \
"A new update is available for SRB2.\n"\
"Please visit SRB2.org to download it.\n"\
"A new update is available for SRB2 Thokker.\n"\
"Please visit the SRB2MB to download it.\n"\
"\n"\
"You are using version: %s\n"\
"The newest version is: %s\n"\
......@@ -179,8 +181,8 @@ extern FILE *logstream;
// The string used in the I_Error alert upon trying to host through command line parameters.
// Generally less filled with newlines, since Windows gives you lots more room to work with.
#define UPDATE_ALERT_STRING_CONSOLE \
"A new update is available for SRB2.\n"\
"Please visit SRB2.org to download it.\n"\
"A new update is available for SRB2 Thokker.\n"\
"Please visit the SRB2MB to download it.\n"\
"\n"\
"You are using version: %s\n"\
"The newest version is: %s\n"\
......@@ -197,14 +199,14 @@ extern FILE *logstream;
// The Modification ID; must be obtained from Inuyasha ( http://mb.srb2.org/private.php?do=newpm&u=2604 ).
// DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server.
// "12" is the default mod ID for version 2.1
#define MODID 12
// "13" is the default mod ID for Thokker
#define MODID 13
// The Modification Version, starting from 1. Do not follow your version string for this,
// it's only for detection of the version the player is using so the MS can alert them of an update.
// Only set it higher, not lower, obviously.
// Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
#define MODVERSION 19
#define MODVERSION 2
......@@ -437,6 +439,9 @@ extern const char *compdate, *comptime, *comprevision;
/// Fun experimental slope stuff!
//#define SLOPENESS
/// Kalaron/Eternity Engine slope code (SRB2CB ported)
#define ESLOPE
/// Delete file while the game is running.
/// \note EXTREMELY buggy, tends to crash game.
//#define DELFILE
......
......@@ -982,6 +982,7 @@ static const char *credits[] = {
"",
"\1Programming",
"\1Assistance",
"\"chi.miru\"", // Red's secret weapon, the REAL reason slopes exist (also helped port drawing code from ZDoom)
"Andrew \"orospakr\" Clunis",
"Gregor \"Oogaland\" Dick",
"Julio \"Chaos Zero 64\" Guir",
......
......@@ -2180,8 +2180,7 @@ void G_PlayerReborn(INT32 player)
p->health = 1; // 0 rings
p->panim = PA_IDLE; // standing animation
if ((netgame || multiplayer) && !p->spectator
&& gametype != GT_RACE)
if ((netgame || multiplayer) && !p->spectator)
p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent
if (p-players == consoleplayer)
......@@ -4330,20 +4329,10 @@ void G_GhostTicker(void)
switch(g->color)
{
case GHC_SUPER: // Super Sonic (P_DoSuperStuff)
// Yousa yellow now!
g->mo->color = SKINCOLOR_SUPER1 + (leveltime/2) % 5;
if (g->mo->skin)
switch (((skin_t*)g->mo->skin)-skins)
{
case 1: // Golden orange supertails.
g->mo->color = SKINCOLOR_TSUPER1 + (leveltime/2) % 5;
break;
case 2: // Pink superknux.
g->mo->color = SKINCOLOR_KSUPER1 + (leveltime/2) % 5;
break;
default:
break;
}
if (leveltime % 9 < 5)
g->mo->color = SKINCOLOR_SUPER1 + leveltime % 9;
else
g->mo->color = SKINCOLOR_SUPER1 + 9 - leveltime % 9;
break;
case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer)
g->mo->color = (UINT8)(leveltime % MAXSKINCOLORS);
......
......@@ -39,7 +39,9 @@
#include "../st_stuff.h"
#include "../i_system.h"
#include "../m_cheat.h"
#ifdef ESLOPE
#include "../p_slopes.h"
#endif
#include "hw_md2.h"
#define R_FAKEFLOORS
......@@ -519,7 +521,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color, UINT32 fadecolor) // L
// -----------------+
// HWR_RenderPlane : Render a floor or ceiling convex polygon
// -----------------+
static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fixedheight,
static void HWR_RenderPlane(sector_t *shittyUnusedVariable, extrasubsector_t *xsub, fixed_t fixedheight,
FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
{
polyvertex_t * pv;
......@@ -535,14 +537,42 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi
angle_t angle = 0;
FSurfaceInfo Surf;
fixed_t tempxsow, tempytow;
#ifdef ESLOPE
pslope_t *slope = NULL;
#endif
static FOutVector *planeVerts = NULL;
static UINT16 numAllocedPlaneVerts = 0;
(void)shittyUnusedVariable; ///@TODO remove shitty unused variable
// no convex poly were generated for this subsector
if (!xsub->planepoly)
return;
#ifdef ESLOPE
// Get the slope pointer to simplify future code
if (FOFsector)
{
if (FOFsector->f_slope && FOFsector->floorheight == fixedheight)
slope = FOFsector->f_slope;
else if (FOFsector->c_slope && FOFsector->ceilingheight == fixedheight)
slope = FOFsector->c_slope;
}
else
{
// Use fixedheight to determine whether to check floor or ceiling because I hate my life
if (gr_frontsector->f_slope && gr_frontsector->floorheight == fixedheight)
slope = gr_frontsector->f_slope;
else if (gr_frontsector->c_slope && gr_frontsector->ceilingheight == fixedheight)
slope = gr_frontsector->c_slope;
}
// Set fixedheight to the slope's height from our viewpoint, if we have a slope
if (slope)
fixedheight = P_GetZAt(slope, viewx, viewy);
#endif
height = FIXED_TO_FLOAT(fixedheight);
pv = xsub->planepoly->pts;
......@@ -608,7 +638,12 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi
if (FOFsector != NULL)
{
#ifdef ESLOPE
if ((slope && slope == FOFsector->f_slope)
|| fixedheight == FOFsector->floorheight) // it's a floor
#else
if (fixedheight == FOFsector->floorheight) // it's a floor
#endif
{
scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize;
......@@ -623,7 +658,12 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi
}
else if (gr_frontsector)
{
#ifdef ESLOPE
if ((slope && slope == gr_frontsector->f_slope)
|| fixedheight == gr_frontsector->floorheight) // it's a floor
#else
if (fixedheight < dup_viewz) // it's a floor
#endif
{
scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize;
scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize;
......@@ -678,24 +718,13 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi
v3d->x = pv->x;
v3d->y = height;
v3d->z = pv->y;
#ifdef SLOPENESS
if (sector && sector->special == 65535)
#ifdef ESLOPE
if (slope)
{
size_t q;
for (q = 0; q < sector->linecount; q++)
{
if (v3d->x == sector->lines[q]->v1->x>>FRACBITS)
{
if (v3d->z == sector->lines[q]->v1->y>>FRACBITS)
{
v3d->y += sector->lines[q]->v1->z>>FRACBITS;
break;
}
}
}
fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED(pv->x), FLOAT_TO_FIXED(pv->y));
v3d->y = FIXED_TO_FLOAT(fixedheight);
}
#else
(void)sector;
#endif
}
......@@ -714,6 +743,11 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, fixed_t fi
{
sector_t *psector = gr_frontsector;
#ifdef ESLOPE
if (slope)
fixedheight = P_GetZAt(slope, psector->soundorg.x, psector->soundorg.y);
#endif
if (psector->ffloors)
{
ffloor_t *caster = psector->lightlist[R_GetPlaneLight(psector, fixedheight, false)].caster;
......@@ -1050,23 +1084,50 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
lightlist. This may also include leaving out parts
of the wall that can't be seen */
GLTexture_t * glTex;
float realtop, realbot, top, bot;
float pegt, pegb, pegmul;
float height = 0.0f, bheight = 0.0f;
#ifdef ESLOPE
float endrealtop, endrealbot, endtop, endbot;
float endpegt, endpegb, endpegmul;
float endheight = 0.0f, endbheight = 0.0f;
fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x);
fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].y);
fixed_t v2x = FLOAT_TO_FIXED(wallVerts[1].x);
fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].y);
// compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly
// use this as a temp var to store P_GetZAt's return value each time
fixed_t temp;
#endif
INT32 solid, i;
lightlist_t * list = sector->lightlist;
const UINT8 alpha = Surf->FlatColor.s.alpha;
FUINT lightnum;
extracolormap_t *colormap;
realtop = top = wallVerts[2].y;
realtop = top = wallVerts[3].y;
realbot = bot = wallVerts[0].y;
pegt = wallVerts[2].t;
pegt = wallVerts[3].t;
pegb = wallVerts[0].t;
pegmul = (pegb - pegt) / (top - bot);
#ifdef ESLOPE
endrealtop = endtop = wallVerts[2].y;
endrealbot = endbot = wallVerts[1].y;
endpegt = wallVerts[2].t;
endpegb = wallVerts[1].t;
endpegmul = (endpegb - endpegt) / (endtop - endbot);
#endif
for (i = 1; i < sector->numlights; i++)
{
#ifdef ESLOPE
if (endtop < endrealbot)
#endif
if (top < realbot)
return;
......@@ -1099,14 +1160,45 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
if (cutflag == FF_CUTSOLIDS) // These are regular walls sent in from StoreWallRange, they shouldn't be cut from this
solid = false;
#ifdef ESLOPE
if (list[i].slope)
{
temp = P_GetZAt(list[i].slope, v1x, v1y);
height = FIXED_TO_FLOAT(temp);
temp = P_GetZAt(list[i].slope, v2x, v2y);
endheight = FIXED_TO_FLOAT(temp);
}
else
height = endheight = FIXED_TO_FLOAT(list[i].height);
if (solid)
{
if (*list[i].caster->b_slope)
{
temp = P_GetZAt(*list[i].caster->b_slope, v1x, v1y);
bheight = FIXED_TO_FLOAT(temp);
temp = P_GetZAt(*list[i].caster->b_slope, v2x, v2y);
endbheight = FIXED_TO_FLOAT(temp);
}
else
bheight = endbheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight);
}
#else
height = FIXED_TO_FLOAT(list[i].height);
if (solid)
bheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight);
#endif
#ifdef ESLOPE
if (endheight >= endtop)
#endif
if (height >= top)
{
if (solid && top > bheight)
top = bheight;
#ifdef ESLOPE
if (solid && endtop > endbheight)
endtop = endbheight;
#endif
continue;
}
......@@ -1116,6 +1208,13 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
if (bot < realbot)
bot = realbot;
#ifdef ESLOPE
endbot = endheight;
if (endbot < endrealbot)
endbot = endrealbot;
#endif
// colormap test
if (list[i-1].caster)
{
......@@ -1130,13 +1229,25 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
Surf->FlatColor.s.alpha = alpha;
#ifdef ESLOPE
wallVerts[3].t = pegt + ((realtop - top) * pegmul);
wallVerts[2].t = endpegt + ((endrealtop - endtop) * endpegmul);
wallVerts[0].t = pegt + ((realtop - bot) * pegmul);
wallVerts[1].t = endpegt + ((endrealtop - endbot) * endpegmul);
// set top/bottom coords
wallVerts[3].y = top;
wallVerts[2].y = endtop;
wallVerts[0].y = bot;
wallVerts[1].y = endbot;
#else
wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul);
wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul);
// set top/bottom coords
wallVerts[2].y = wallVerts[3].y = top;
wallVerts[0].y = wallVerts[1].y = bot;
#endif
glTex = HWR_GetTexture(texnum);
if (cutflag & FF_TRANSLUCENT)
......@@ -1150,9 +1261,19 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
top = bheight;
else
top = height;
#ifdef ESLOPE
if (solid)
endtop = endbheight;
else
endtop = endheight;
#endif
}
bot = realbot;
#ifdef ESLOPE
endbot = endrealbot;
if (endtop <= endrealbot)
#endif
if (top <= realbot)
return;
......@@ -1168,12 +1289,25 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
}
Surf->FlatColor.s.alpha = alpha;
wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul);
wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul);
#ifdef ESLOPE
wallVerts[3].t = pegt + ((realtop - top) * pegmul);
wallVerts[2].t = endpegt + ((endrealtop - endtop) * endpegmul);
wallVerts[0].t = pegt + ((realtop - bot) * pegmul);
wallVerts[1].t = endpegt + ((endrealtop - endbot) * endpegmul);
// set top/bottom coords
wallVerts[2].y = wallVerts[3].y = top;
wallVerts[0].y = wallVerts[1].y = bot;
wallVerts[3].y = top;
wallVerts[2].y = endtop;
wallVerts[0].y = bot;
wallVerts[1].y = endbot;
#else
wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul);
wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul);
// set top/bottom coords
wallVerts[2].y = wallVerts[3].y = top;
wallVerts[0].y = wallVerts[1].y = bot;
#endif
glTex = HWR_GetTexture(texnum);
if (cutflag & FF_TRANSLUCENT)
......@@ -1321,11 +1455,19 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
fixed_t worldtop, worldbottom;
fixed_t worldhigh = 0, worldlow = 0;
#ifdef ESLOPE
fixed_t worldtopslope, worldbottomslope;
fixed_t worldhighslope = 0, worldlowslope = 0;
fixed_t v1x, v1y, v2x, v2y;
#endif
GLTexture_t *grTex = NULL;
float cliplow = 0.0f, cliphigh = 0.0f;
INT32 gr_midtexture;
fixed_t h, l; // 3D sides and 2s middle textures
#ifdef ESLOPE
fixed_t hS, lS;
#endif
FUINT lightnum = 0; // shut up compiler
extracolormap_t *colormap;
......@@ -1337,22 +1479,56 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
gr_sidedef = gr_curline->sidedef;
gr_linedef = gr_curline->linedef;
vs.x = ((polyvertex_t *)gr_curline->v1)->x;
vs.y = ((polyvertex_t *)gr_curline->v1)->y;
ve.x = ((polyvertex_t *)gr_curline->v2)->x;
ve.y = ((polyvertex_t *)gr_curline->v2)->y;
#ifdef ESLOPE
v1x = FLOAT_TO_FIXED(vs.x);
v1y = FLOAT_TO_FIXED(vs.y);
v2x = FLOAT_TO_FIXED(ve.x);
v2y = FLOAT_TO_FIXED(ve.y);
#endif
if (gr_frontsector->heightsec != -1)
{
#ifdef ESLOPE
worldtop = worldtopslope = sectors[gr_frontsector->heightsec].ceilingheight;
worldbottom = worldbottomslope = sectors[gr_frontsector->heightsec].floorheight;
#else
worldtop = sectors[gr_frontsector->heightsec].ceilingheight;
worldbottom = sectors[gr_frontsector->heightsec].floorheight;
#endif
}
else
{
#ifdef ESLOPE
if (gr_frontsector->c_slope)
{
worldtop = P_GetZAt(gr_frontsector->c_slope, v1x, v1y);
worldtopslope = P_GetZAt(gr_frontsector->c_slope, v2x, v2y);
}
else
{
worldtop = worldtopslope = gr_frontsector->ceilingheight;
}
if (gr_frontsector->f_slope)
{
worldbottom = P_GetZAt(gr_frontsector->f_slope, v1x, v1y);
worldbottomslope = P_GetZAt(gr_frontsector->f_slope, v2x, v2y);
}
else
{
worldbottom = worldbottomslope = gr_frontsector->floorheight;
}
#else
worldtop = gr_frontsector->ceilingheight;
worldbottom = gr_frontsector->floorheight;
#endif
}
vs.x = ((polyvertex_t *)gr_curline->v1)->x;
vs.y = ((polyvertex_t *)gr_curline->v1)->y;
ve.x = ((polyvertex_t *)gr_curline->v2)->x;
ve.y = ((polyvertex_t *)gr_curline->v2)->y;
// remember vertices ordering
// 3--2
// | /|
......@@ -1396,13 +1572,40 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
// two sided line
if (gr_backsector->heightsec != -1)
{
#ifdef ESLOPE
worldhigh = worldhighslope = sectors[gr_backsector->heightsec].ceilingheight;
worldlow = worldlowslope = sectors[gr_backsector->heightsec].floorheight;
#else
worldhigh = sectors[gr_backsector->heightsec].ceilingheight;
worldlow = sectors[gr_backsector->heightsec].floorheight;
#endif
}
else
{
#ifdef ESLOPE
if (gr_backsector->c_slope)
{
worldhigh = P_GetZAt(gr_backsector->c_slope, v1x, v1y);
worldhighslope = P_GetZAt(gr_backsector->c_slope, v2x, v2y);
}
else
{
worldhigh = worldhighslope = gr_backsector->ceilingheight;
}
if (gr_backsector->f_slope)
{
worldlow = P_GetZAt(gr_backsector->f_slope, v1x, v1y);
worldlowslope = P_GetZAt(gr_backsector->f_slope, v2x, v2y);
}
else
{
worldlow = worldlowslope = gr_backsector->floorheight;
}
#else
worldhigh = gr_backsector->ceilingheight;
worldlow = gr_backsector->floorheight;
#endif
}
// hack to allow height changes in outdoor areas
......@@ -1411,10 +1614,18 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
gr_backsector->ceilingpic == skyflatnum)
{
worldtop = worldhigh;
#ifdef ESLOPE
worldtopslope = worldhighslope;
#endif
}
// check TOP TEXTURE
if (worldhigh < worldtop && texturetranslation[gr_sidedef->toptexture])
if ((
#ifdef ESLOPE
worldhighslope < worldtopslope ||
#endif
worldhigh < worldtop
) && texturetranslation[gr_sidedef->toptexture])
{
if (drawtextured)
{
......@@ -1425,8 +1636,15 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
// PEGGING
if (gr_linedef->flags & ML_DONTPEGTOP)
texturevpegtop = 0;
else
#ifdef ESLOPE
else if (gr_linedef->flags & ML_EFFECT1)
texturevpegtop = worldhigh + textureheight[gr_sidedef->toptexture] - worldtop;
else
texturevpegtop = gr_backsector->ceilingheight + textureheight[gr_sidedef->toptexture] - gr_frontsector->ceilingheight;
#else
else
texturevpegtop = worldhigh + textureheight[gr_sidedef->toptexture] - worldtop;
#endif
texturevpegtop += gr_sidedef->rowoffset;
......@@ -1434,14 +1652,46 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
texturevpegtop %= SHORT(textures[texturetranslation[gr_sidedef->toptexture]]->height)<<FRACBITS;
wallVerts[3].t = wallVerts[2].t = texturevpegtop * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (texturevpegtop + worldtop - worldhigh) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (texturevpegtop + gr_frontsector->ceilingheight - gr_backsector->ceilingheight) * grTex->scaleY;
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
#ifdef ESLOPE
// Adjust t value for sloped walls
if (!(gr_linedef->flags & ML_EFFECT1))
{
// Unskewed
wallVerts[3].t -= (worldtop - gr_frontsector->ceilingheight) * grTex->scaleY;
wallVerts[2].t -= (worldtopslope - gr_frontsector->ceilingheight) * grTex->scaleY;
wallVerts[0].t -= (worldhigh - gr_backsector->ceilingheight) * grTex->scaleY;
wallVerts[1].t -= (worldhighslope - gr_backsector->ceilingheight) * grTex->scaleY;
}
else if (gr_linedef->flags & ML_DONTPEGTOP)
{
// Skewed by top
wallVerts[0].t = (texturevpegtop + worldtop - worldhigh) * grTex->scaleY;
wallVerts[1].t = (texturevpegtop + worldtopslope - worldhighslope) * grTex->scaleY;
}
else
{
// Skewed by bottom
wallVerts[0].t = (texturevpegtop + worldhigh - worldtop) * grTex->scaleY;
wallVerts[2].t = wallVerts[3].t - (worldhighslope - worldhigh) * grTex->scaleY;
wallVerts[1].t = wallVerts[2].t - (worldhighslope - worldtopslope) * grTex->scaleY;
}
#endif
}
// set top/bottom coords
#ifdef ESLOPE
wallVerts[3].y = FIXED_TO_FLOAT(worldtop);
wallVerts[0].y = FIXED_TO_FLOAT(worldhigh);
wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope);
wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope);
#else
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop);
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldhigh);
#endif
if (gr_frontsector->numlights)
HWR_SplitWall(gr_frontsector, wallVerts, texturetranslation[gr_sidedef->toptexture], &Surf, FF_CUTSOLIDS);
......@@ -1452,7 +1702,11 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
}
// check BOTTOM TEXTURE
if (worldlow > worldbottom && texturetranslation[gr_sidedef->bottomtexture]) //only if VISIBLE!!!
if ((
#ifdef ESLOPE
worldlowslope > worldbottomslope ||
#endif
worldlow > worldbottom) && texturetranslation[gr_sidedef->bottomtexture]) //only if VISIBLE!!!
{
if (drawtextured)
{
......@@ -1461,10 +1715,19 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
grTex = HWR_GetTexture(texturetranslation[gr_sidedef->bottomtexture]);
// PEGGING
if (gr_linedef->flags & ML_DONTPEGBOTTOM)
#ifdef ESLOPE
if (!(gr_linedef->flags & ML_DONTPEGBOTTOM))
texturevpegbottom = 0;
else if (gr_linedef->flags & ML_EFFECT1)
texturevpegbottom = worldtop - worldlow;
else
texturevpegbottom = 0;
texturevpegbottom = gr_frontsector->ceilingheight - gr_backsector->floorheight;
#else
if (gr_linedef->flags & ML_DONTPEGBOTTOM)
texturevpegbottom = worldtop - worldlow;
else
texturevpegbottom = 0;
#endif
texturevpegbottom += gr_sidedef->rowoffset;
......@@ -1472,14 +1735,46 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
texturevpegbottom %= SHORT(textures[texturetranslation[gr_sidedef->bottomtexture]]->height)<<FRACBITS;
wallVerts[3].t = wallVerts[2].t = texturevpegbottom * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (texturevpegbottom + worldlow - worldbottom) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (texturevpegbottom + gr_backsector->floorheight - gr_frontsector->floorheight) * grTex->scaleY;
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
#ifdef ESLOPE
// Adjust t value for sloped walls
if (!(gr_linedef->flags & ML_EFFECT1))
{
// Unskewed
wallVerts[0].t -= (worldbottom - gr_frontsector->floorheight) * grTex->scaleY;
wallVerts[1].t -= (worldbottomslope - gr_frontsector->floorheight) * grTex->scaleY;
wallVerts[3].t -= (worldlow - gr_backsector->floorheight) * grTex->scaleY;
wallVerts[2].t -= (worldlowslope - gr_backsector->floorheight) * grTex->scaleY;
}
else if (gr_linedef->flags & ML_DONTPEGBOTTOM)
{
// Skewed by bottom
wallVerts[0].t = (texturevpegbottom + worldlow - worldbottom) * grTex->scaleY;
wallVerts[2].t = wallVerts[3].t - (worldlowslope - worldlow) * grTex->scaleY;
wallVerts[1].t = wallVerts[2].t - (worldbottomslope - worldlowslope) * grTex->scaleY;
}
else
{
// Skewed by top
wallVerts[0].t = (texturevpegbottom + worldlow - worldbottom) * grTex->scaleY;
wallVerts[1].t = (texturevpegbottom + worldlowslope - worldbottomslope) * grTex->scaleY;
}
#endif
}
// set top/bottom coords
#ifdef ESLOPE
wallVerts[3].y = FIXED_TO_FLOAT(worldlow);
wallVerts[0].y = FIXED_TO_FLOAT(worldbottom);
wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope);
wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope);
#else
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldlow);
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom);
#endif
if (gr_frontsector->numlights)
HWR_SplitWall(gr_frontsector, wallVerts, texturetranslation[gr_sidedef->bottomtexture], &Surf, FF_CUTSOLIDS);
......@@ -1546,14 +1841,36 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
popentop = back->ceilingheight;
popenbottom = back->floorheight;
}
#endif
else
{
popentop = front->ceilingheight < back->ceilingheight ? front->ceilingheight : back->ceilingheight;
popenbottom = front->floorheight > back->floorheight ? front->floorheight : back->floorheight;
#endif
{
#ifdef ESLOPE
popentop = min(worldtop, worldhigh);
popenbottom = max(worldbottom, worldlow);
#else
popentop = min(front->ceilingheight, back->ceilingheight);
popenbottom = max(front->floorheight, back->floorheight);
#endif
}
if (gr_linedef->flags & ML_DONTPEGBOTTOM)
#ifdef ESLOPE
if (gr_linedef->flags & ML_EFFECT2)
{
if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3))
{
polybottom = max(front->floorheight, back->floorheight) + gr_sidedef->rowoffset;
polytop = polybottom + textureheight[gr_midtexture]*repeats;
}
else
{
polytop = min(front->ceilingheight, back->ceilingheight) + gr_sidedef->rowoffset;
polybottom = polytop - textureheight[gr_midtexture]*repeats;
}
}
else if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3))
#else
if (gr_linedef->flags & ML_DONTPEGBOTTOM)
#endif
{
polybottom = popenbottom + gr_sidedef->rowoffset;
polytop = polybottom + textureheight[gr_midtexture]*repeats;
......@@ -1576,17 +1893,21 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
else
{
// The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector
lowcut = front->floorheight > back->floorheight ? front->floorheight : back->floorheight;
highcut = front->ceilingheight < back->ceilingheight ? front->ceilingheight : back->ceilingheight;
lowcut = popenbottom;
highcut = popentop;
}
h = polytop > highcut ? highcut : polytop;
l = polybottom < lowcut ? lowcut : polybottom;
h = min(highcut, polytop);
l = max(polybottom, lowcut);
if (drawtextured)
{
// PEGGING
#ifdef ESLOPE
if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3))
#else
if (gr_linedef->flags & ML_DONTPEGBOTTOM)
#endif
texturevpeg = textureheight[gr_sidedef->midtexture]*repeats - h + polybottom;
else
texturevpeg = polytop - h;
......@@ -1605,6 +1926,52 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h);
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l);
#ifdef ESLOPE
// Correct to account for slopes
{
fixed_t midtextureslant;
if (gr_linedef->flags & ML_EFFECT2)
midtextureslant = 0;
else if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3))
midtextureslant = worldlow < worldbottom
? worldbottomslope-worldbottom
: worldlowslope-worldlow;
else
midtextureslant = worldtop < worldhigh
? worldtopslope-worldtop
: worldhighslope-worldhigh;
polytop += midtextureslant;
polybottom += midtextureslant;
highcut += worldtop < worldhigh
? worldtopslope-worldtop
: worldhighslope-worldhigh;
lowcut += worldlow < worldbottom
? worldbottomslope-worldbottom
: worldlowslope-worldlow;
// Texture stuff
h = min(highcut, polytop);
l = max(polybottom, lowcut);
if (drawtextured)
{
// PEGGING
if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3))
texturevpeg = textureheight[gr_sidedef->midtexture]*repeats - h + polybottom;
else
texturevpeg = polytop - h;
wallVerts[2].t = texturevpeg * grTex->scaleY;
wallVerts[1].t = (h - l + texturevpeg) * grTex->scaleY;
}
wallVerts[2].y = FIXED_TO_FLOAT(h);
wallVerts[1].y = FIXED_TO_FLOAT(l);
}
#endif
// set alpha for transparent walls (new boom and legacy linedef types)
// ooops ! this do not work at all because render order we should render it in backtofront order
switch (gr_linedef->special)
......@@ -1785,6 +2152,11 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
{
fixed_t texturevpeg;
// PEGGING
#ifdef ESLOPE
if ((gr_linedef->flags & (ML_DONTPEGBOTTOM|ML_EFFECT2)) == (ML_DONTPEGBOTTOM|ML_EFFECT2))
texturevpeg = gr_frontsector->floorheight + textureheight[gr_sidedef->midtexture] - gr_frontsector->ceilingheight + gr_sidedef->rowoffset;
else
#endif
if (gr_linedef->flags & ML_DONTPEGBOTTOM)
texturevpeg = worldbottom + textureheight[gr_sidedef->midtexture] - worldtop + gr_sidedef->rowoffset;
else
......@@ -1794,14 +2166,37 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
grTex = HWR_GetTexture(gr_midtexture);
wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (texturevpeg + worldtop - worldbottom) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (texturevpeg + gr_frontsector->ceilingheight - gr_frontsector->floorheight) * grTex->scaleY;
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
#ifdef ESLOPE
// Texture correction for slopes
if (gr_linedef->flags & ML_EFFECT2) {
wallVerts[3].t += (gr_frontsector->ceilingheight - worldtop) * grTex->scaleY;
wallVerts[2].t += (gr_frontsector->ceilingheight - worldtopslope) * grTex->scaleY;
wallVerts[0].t += (gr_frontsector->floorheight - worldbottom) * grTex->scaleY;
wallVerts[1].t += (gr_frontsector->floorheight - worldbottomslope) * grTex->scaleY;
} else if (gr_linedef->flags & ML_DONTPEGBOTTOM) {
wallVerts[3].t = wallVerts[0].t + (worldbottom-worldtop) * grTex->scaleY;
wallVerts[2].t = wallVerts[1].t + (worldbottomslope-worldtopslope) * grTex->scaleY;
} else {
wallVerts[0].t = wallVerts[3].t - (worldbottom-worldtop) * grTex->scaleY;
wallVerts[1].t = wallVerts[2].t - (worldbottomslope-worldtopslope) * grTex->scaleY;
}
#endif
}
#ifdef ESLOPE
//Set textures properly on single sided walls that are sloped
wallVerts[3].y = FIXED_TO_FLOAT(worldtop);
wallVerts[0].y = FIXED_TO_FLOAT(worldbottom);
wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope);
wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope);
#else
// set top/bottom coords
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop);
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom);
#endif
// I don't think that solid walls can use translucent linedef types...
if (gr_frontsector->numlights)
HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTSOLIDS);
......@@ -1834,6 +2229,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
INT32 texnum;
line_t * newline = NULL; // Multi-Property FOF
///TODO add slope support (fixing cutoffs, proper wall clipping) - maybe just disable highcut/lowcut if either sector or FOF has a slope
/// to allow fun plane intersecting in OGL? But then people would abuse that and make software look bad. :C
highcut = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight;
lowcut = gr_frontsector->floorheight > gr_backsector->floorheight ? gr_frontsector->floorheight : gr_backsector->floorheight;
......@@ -1855,6 +2252,24 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
texnum = texturetranslation[sides[newline->sidenum[0]].midtexture];
}
#ifdef ESLOPE
h = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight;
hS = *rover->t_slope ? P_GetZAt(*rover->t_slope, v2x, v2y) : *rover->topheight;
l = *rover->b_slope ? P_GetZAt(*rover->b_slope, v1x, v1y) : *rover->bottomheight;
lS = *rover->b_slope ? P_GetZAt(*rover->b_slope, v2x, v2y) : *rover->bottomheight;
if (!(*rover->t_slope) && !gr_frontsector->c_slope && !gr_backsector->c_slope && h > highcut)
h = hS = highcut;
if (!(*rover->b_slope) && !gr_frontsector->f_slope && !gr_backsector->f_slope && l < lowcut)
l = lS = lowcut;
//Hurdler: HW code starts here
//FIXME: check if peging is correct
// set top/bottom coords
wallVerts[3].y = FIXED_TO_FLOAT(h);
wallVerts[2].y = FIXED_TO_FLOAT(hS);
wallVerts[0].y = FIXED_TO_FLOAT(l);
wallVerts[1].y = FIXED_TO_FLOAT(lS);
#else
h = *rover->topheight;
l = *rover->bottomheight;
if (h > highcut)
......@@ -1866,6 +2281,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
// set top/bottom coords
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h);
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l);
#endif
if (rover->flags & FF_FOG)
{
wallVerts[3].t = wallVerts[2].t = 0;
......@@ -1875,6 +2291,15 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
}
else if (drawtextured)
{
#ifdef ESLOPE // P.S. this is better-organized than the old version
fixed_t offs = sides[(newline ?: rover->master)->sidenum[0]].rowoffset;
grTex = HWR_GetTexture(texnum);
wallVerts[3].t = (*rover->topheight - h + offs) * grTex->scaleY;
wallVerts[2].t = (*rover->topheight - hS + offs) * grTex->scaleY;
wallVerts[0].t = (*rover->topheight - l + offs) * grTex->scaleY;
wallVerts[1].t = (*rover->topheight - lS + offs) * grTex->scaleY;
#else
grTex = HWR_GetTexture(texnum);
if (newline)
......@@ -1887,6 +2312,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset)) * grTex->scaleY;
}
#endif
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
......@@ -1959,7 +2385,24 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
newline = rover->master->frontsector->lines[0] + linenum;
texnum = texturetranslation[sides[newline->sidenum[0]].midtexture];
}
#ifdef ESLOPE //backsides
h = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight;
hS = *rover->t_slope ? P_GetZAt(*rover->t_slope, v2x, v2y) : *rover->topheight;
l = *rover->b_slope ? P_GetZAt(*rover->b_slope, v1x, v1y) : *rover->bottomheight;
lS = *rover->b_slope ? P_GetZAt(*rover->b_slope, v2x, v2y) : *rover->bottomheight;
if (!(*rover->t_slope) && !gr_frontsector->c_slope && !gr_backsector->c_slope && h > highcut)
h = hS = highcut;
if (!(*rover->b_slope) && !gr_frontsector->f_slope && !gr_backsector->f_slope && l < lowcut)
l = lS = lowcut;
//Hurdler: HW code starts here
//FIXME: check if peging is correct
// set top/bottom coords
wallVerts[3].y = FIXED_TO_FLOAT(h);
wallVerts[2].y = FIXED_TO_FLOAT(hS);
wallVerts[0].y = FIXED_TO_FLOAT(l);
wallVerts[1].y = FIXED_TO_FLOAT(lS);
#else
h = *rover->topheight;
l = *rover->bottomheight;
if (h > highcut)
......@@ -1971,7 +2414,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
// set top/bottom coords
wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h);
wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l);
#endif
if (rover->flags & FF_FOG)
{
wallVerts[3].t = wallVerts[2].t = 0;
......@@ -2465,13 +2908,17 @@ static void HWR_AddLine(seg_t * line)
// and no middle texture.
if (
#ifdef POLYOBJECTS
!line->polyseg
!line->polyseg &&
#endif
gr_backsector->ceilingpic == gr_frontsector->ceilingpic
&& gr_backsector->floorpic == gr_frontsector->floorpic
#ifdef ESLOPE
&& gr_backsector->f_slope == gr_frontsector->f_slope
&& gr_backsector->c_slope == gr_frontsector->c_slope
#endif
&& gr_backsector->ceilingpic == gr_frontsector->ceilingpic
&& gr_backsector->floorpic == gr_frontsector->floorpic
&& gr_backsector->lightlevel == gr_frontsector->lightlevel
&& gr_curline->sidedef->midtexture == 0
&& !gr_backsector->ffloors && !gr_frontsector->ffloors)
&& gr_curline->sidedef->midtexture == 0
&& !gr_backsector->ffloors && !gr_frontsector->ffloors)
// SoM: For 3D sides... Boris, would you like to take a
// crack at rendering 3D sides? You would need to add the
// above check and add code to HWR_StoreWallRange...
......@@ -2865,6 +3312,7 @@ static void HWR_Subsector(size_t num)
INT32 floorlightlevel;
INT32 ceilinglightlevel;
INT32 locFloorHeight, locCeilingHeight;
INT32 cullFloorHeight, cullCeilingHeight;
INT32 light = 0;
extracolormap_t *floorcolormap;
extracolormap_t *ceilingcolormap;
......@@ -2921,26 +3369,41 @@ static void HWR_Subsector(size_t num)
// ----- for special tricks with HW renderer -----
if (gr_frontsector->pseudoSector)
{
locFloorHeight = gr_frontsector->virtualFloorheight;
locCeilingHeight = gr_frontsector->virtualCeilingheight;
cullFloorHeight = locFloorHeight = gr_frontsector->virtualFloorheight;
cullCeilingHeight = locCeilingHeight = gr_frontsector->virtualCeilingheight;
}
else if (gr_frontsector->virtualFloor)
{
locFloorHeight = gr_frontsector->virtualFloorheight;
///@TODO Is this whole virtualFloor mess even useful? I don't think it even triggers ever.
cullFloorHeight = locFloorHeight = gr_frontsector->virtualFloorheight;
if (gr_frontsector->virtualCeiling)
locCeilingHeight = gr_frontsector->virtualCeilingheight;
cullCeilingHeight = locCeilingHeight = gr_frontsector->virtualCeilingheight;
else
locCeilingHeight = gr_frontsector->ceilingheight;
cullCeilingHeight = locCeilingHeight = gr_frontsector->ceilingheight;
}
else if (gr_frontsector->virtualCeiling)
{
locCeilingHeight = gr_frontsector->virtualCeilingheight;
locFloorHeight = gr_frontsector->floorheight;
cullCeilingHeight = locCeilingHeight = gr_frontsector->virtualCeilingheight;
cullFloorHeight = locFloorHeight = gr_frontsector->floorheight;
}
else
{
locFloorHeight = gr_frontsector->floorheight;
locCeilingHeight = gr_frontsector->ceilingheight;
cullFloorHeight = locFloorHeight = gr_frontsector->floorheight;
cullCeilingHeight = locCeilingHeight = gr_frontsector->ceilingheight;
#ifdef ESLOPE
if (gr_frontsector->f_slope)
{
cullFloorHeight = P_GetZAt(gr_frontsector->f_slope, viewx, viewy);
locFloorHeight = P_GetZAt(gr_frontsector->f_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
}
if (gr_frontsector->c_slope)
{
cullCeilingHeight = P_GetZAt(gr_frontsector->c_slope, viewx, viewy);
locCeilingHeight = P_GetZAt(gr_frontsector->c_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
}
#endif
}
// ----- end special tricks -----
......@@ -2971,14 +3434,18 @@ static void HWR_Subsector(size_t num)
// render floor ?
#ifdef DOPLANES
// yeah, easy backface cull! :)
if (locFloorHeight < dup_viewz)
if (cullFloorHeight < dup_viewz)
{
if (gr_frontsector->floorpic != skyflatnum)
{
if (sub->validcount != validcount)
{
HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum);
HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], locFloorHeight, PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, false, floorcolormap);
HWR_RenderPlane(gr_frontsector, &extrasubsectors[num],
// Hack to make things continue to work around slopes.
locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, false, floorcolormap);
}
}
else
......@@ -2989,14 +3456,18 @@ static void HWR_Subsector(size_t num)
}
}
if (locCeilingHeight > dup_viewz)
if (cullCeilingHeight > dup_viewz)
{
if (gr_frontsector->ceilingpic != skyflatnum)
{
if (sub->validcount != validcount)
{
HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum);
HWR_RenderPlane(NULL, &extrasubsectors[num], locCeilingHeight, PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, false, ceilingcolormap);
HWR_RenderPlane(NULL, &extrasubsectors[num],
// Hack to make things continue to work around slopes.
locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight,
// We now return you to your regularly scheduled rendering.
PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, false, ceilingcolormap);
}
}
else
......@@ -3025,22 +3496,34 @@ static void HWR_Subsector(size_t num)
for (rover = gr_frontsector->ffloors;
rover; rover = rover->next)
{
fixed_t cullHeight, centerHeight;
// bottom plane
#ifdef ESLOPE
if (*rover->b_slope)
{
cullHeight = P_GetZAt(*rover->b_slope, viewx, viewy);
centerHeight = P_GetZAt(*rover->b_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
}
else
#endif
cullHeight = centerHeight = *rover->bottomheight;
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES))
continue;
if (sub->validcount == validcount)
continue;
if (*rover->bottomheight <= gr_frontsector->ceilingheight &&
*rover->bottomheight >= gr_frontsector->floorheight &&
((dup_viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) ||
(dup_viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
if (centerHeight <= locCeilingHeight &&
centerHeight >= locFloorHeight &&
((dup_viewz < cullHeight && !(rover->flags & FF_INVERTPLANES)) ||
(dup_viewz > cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
{
if (rover->flags & FF_FOG)
{
UINT8 alpha;
light = R_GetPlaneLight(gr_frontsector, *rover->bottomheight, dup_viewz < *rover->bottomheight ? true : false);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
if (rover->master->frontsector->extra_colormap)
alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba, rover->master->frontsector->extra_colormap->fadergba);
......@@ -3056,7 +3539,7 @@ static void HWR_Subsector(size_t num)
}
else if (rover->flags & FF_TRANSLUCENT) // SoM: Flags are more efficient
{
light = R_GetPlaneLight(gr_frontsector, *rover->bottomheight, dup_viewz < *rover->bottomheight ? true : false);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
#ifndef SORTING
HWR_Add3DWater(levelflats[*rover->bottompic].lumpnum,
&extrasubsectors[num],
......@@ -3075,21 +3558,33 @@ static void HWR_Subsector(size_t num)
else
{
HWR_GetFlat(levelflats[*rover->bottompic].lumpnum);
light = R_GetPlaneLight(gr_frontsector, *rover->bottomheight, dup_viewz < *rover->bottomheight ? true : false);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum,
rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap);
}
}
if (*rover->topheight >= gr_frontsector->floorheight &&
*rover->topheight <= gr_frontsector->ceilingheight &&
((dup_viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) ||
(dup_viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
// top plane
#ifdef ESLOPE
if (*rover->t_slope)
{
cullHeight = P_GetZAt(*rover->t_slope, viewx, viewy);
centerHeight = P_GetZAt(*rover->t_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
}
else
#endif
cullHeight = centerHeight = *rover->topheight;
if (centerHeight >= locFloorHeight &&
centerHeight <= locCeilingHeight &&
((dup_viewz > cullHeight && !(rover->flags & FF_INVERTPLANES)) ||
(dup_viewz < cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
{
if (rover->flags & FF_FOG)
{
UINT8 alpha;
light = R_GetPlaneLight(gr_frontsector, *rover->topheight, dup_viewz < *rover->topheight ? true : false);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
if (rover->master->frontsector->extra_colormap)
alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap->rgba, rover->master->frontsector->extra_colormap->fadergba);
......@@ -3105,7 +3600,7 @@ static void HWR_Subsector(size_t num)
}
else if (rover->flags & FF_TRANSLUCENT)
{
light = R_GetPlaneLight(gr_frontsector, *rover->topheight, dup_viewz < *rover->topheight ? true : false);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
#ifndef SORTING
HWR_Add3DWater(levelflats[*rover->toppic].lumpnum,
&extrasubsectors[num],
......@@ -3125,7 +3620,7 @@ static void HWR_Subsector(size_t num)
else
{
HWR_GetFlat(levelflats[*rover->toppic].lumpnum);
light = R_GetPlaneLight(gr_frontsector, *rover->topheight, dup_viewz < *rover->topheight ? true : false);
light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
HWR_RenderPlane(NULL, &extrasubsectors[num], *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum,
rover->master->frontsector, 255, false, gr_frontsector->lightlist[light].extra_colormap);
}
......@@ -3505,6 +4000,184 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v
return false;
}
static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float this_scale)
{
UINT8 i;
float tr_x, tr_y;
FOutVector *wv;
FOutVector swallVerts[4];
FSurfaceInfo sSurf;
fixed_t floorheight, mobjfloor;
mobjfloor = HWR_OpaqueFloorAtPos(
spr->mobj->x, spr->mobj->y,
spr->mobj->z, spr->mobj->height);
if (cv_shadowoffs.value)
{
angle_t shadowdir;
// Set direction
if (splitscreen && stplyr != &players[displayplayer])
shadowdir = localangle2 + FixedAngle(cv_cam2_rotate.value);
else
shadowdir = localangle + FixedAngle(cv_cam_rotate.value);
// Find floorheight
floorheight = HWR_OpaqueFloorAtPos(
spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - mobjfloor),
spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - mobjfloor),
spr->mobj->z, spr->mobj->height);
// The shadow is falling ABOVE it's mobj?
// Don't draw it, then!
if (spr->mobj->z < floorheight)
return;
else
{
fixed_t floorz;
floorz = HWR_OpaqueFloorAtPos(
spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - floorheight),
spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - floorheight),
spr->mobj->z, spr->mobj->height);
// The shadow would be falling on a wall? Don't draw it, then.
// Would draw midair otherwise.
if (floorz < floorheight)
return;
}
floorheight = FixedInt(spr->mobj->z - floorheight);
}
else
floorheight = FixedInt(spr->mobj->z - mobjfloor);
// create the sprite billboard
//
// 3--2
// | /|
// |/ |
// 0--1
// x1/x2 were already scaled in HWR_ProjectSprite
swallVerts[0].x = swallVerts[3].x = spr->x1;
swallVerts[2].x = swallVerts[1].x = spr->x2;
if (spr->mobj && this_scale != 1.0f)
{
// Always a pixel above the floor, perfectly flat.
swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset * this_scale - (floorheight+3);
swallVerts[0].z = swallVerts[1].z = spr->tz - (gpatch->height-gpatch->topoffset) * this_scale;
swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->topoffset * this_scale;
}
else
{
// Always a pixel above the floor, perfectly flat.
swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset - (floorheight+3);
// Spread out top away from the camera. (Fixme: Make it always move out in the same direction!... somehow.)
swallVerts[0].z = swallVerts[1].z = spr->tz - (gpatch->height-gpatch->topoffset);
swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->topoffset;
}
// transform
wv = swallVerts;
for (i = 0; i < 4; i++,wv++)
{
// Offset away from the camera based on height from floor.
if (cv_shadowoffs.value)
wv->z += floorheight;
wv->z += 3;
//look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
tr_x = wv->z;
tr_y = wv->y;
wv->y = (tr_x * gr_viewludcos) + (tr_y * gr_viewludsin);
wv->z = (tr_x * gr_viewludsin) - (tr_y * gr_viewludcos);
// ---------------------- mega lame test ----------------------------------
//scale y before frustum so that frustum can be scaled to screen height
wv->y *= ORIGINAL_ASPECT * gr_fovlud;
wv->x *= gr_fovlud;
}
if (spr->flip)
{
swallVerts[0].sow = swallVerts[3].sow = gpatch->max_s;
swallVerts[2].sow = swallVerts[1].sow = 0;
}
else
{
swallVerts[0].sow = swallVerts[3].sow = 0;
swallVerts[2].sow = swallVerts[1].sow = gpatch->max_s;
}
// flip the texture coords (look familiar?)
if (spr->vflip)
{
swallVerts[3].tow = swallVerts[2].tow = gpatch->max_t;
swallVerts[0].tow = swallVerts[1].tow = 0;
}
else
{
swallVerts[3].tow = swallVerts[2].tow = 0;
swallVerts[0].tow = swallVerts[1].tow = gpatch->max_t;
}
sSurf.FlatColor.s.red = 0x00;
sSurf.FlatColor.s.blue = 0x00;
sSurf.FlatColor.s.green = 0x00;
/*if (spr->mobj->frame & FF_TRANSMASK || spr->mobj->flags2 & MF2_SHADOW)
{
sector_t *sector = spr->mobj->subsector->sector;
UINT8 lightlevel = 255;
extracolormap_t *colormap = sector->extra_colormap;
if (sector->numlights)
{
INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false);
if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *sector->lightlist[light].lightlevel;
if (sector->lightlist[light].extra_colormap)
colormap = sector->lightlist[light].extra_colormap;
}
else
{
lightlevel = sector->lightlevel;
if (sector->extra_colormap)
colormap = sector->extra_colormap;
}
if (colormap)
sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, colormap->rgba, colormap->fadergba, false, true);
else
sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, NORMALFOG, FADEFOG, false, true);
}*/
// shadow is always half as translucent as the sprite itself
if (!cv_translucency.value) // use default translucency (main sprite won't have any translucency)
sSurf.FlatColor.s.alpha = 0x80; // default
else if (spr->mobj->flags2 & MF2_SHADOW)
sSurf.FlatColor.s.alpha = 0x20;
else if (spr->mobj->frame & FF_TRANSMASK)
{
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &sSurf);
sSurf.FlatColor.s.alpha /= 2; //cut alpha in half!
}
else
sSurf.FlatColor.s.alpha = 0x80; // default
if (sSurf.FlatColor.s.alpha > floorheight/4)
{
sSurf.FlatColor.s.alpha = (UINT8)(sSurf.FlatColor.s.alpha - floorheight/4);
HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip);
}
}
// -----------------+
// HWR_DrawSprite : Draw flat sprites
// : (monsters, bonuses, weapons, lights, ...)
......@@ -3607,7 +4280,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
// Draw shadow BEFORE sprite
if (cv_shadow.value // Shadows enabled
&& !(spr->mobj->flags & MF_SCENERY && spr->mobj->flags & MF_SPAWNCEILING && spr->mobj->flags & MF_NOGRAVITY) // Ceiling scenery have no shadow.
&& (spr->mobj->flags & (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY)) != (MF_SCENERY|MF_SPAWNCEILING|MF_NOGRAVITY) // Ceiling scenery have no shadow.
&& !(spr->mobj->flags2 & MF2_DEBRIS) // Debris have no corona or shadow.
#ifdef ALAM_LIGHTING
&& !(t_lspr[spr->mobj->sprite]->type // Things with dynamic lights have no shadow.
......@@ -3618,187 +4291,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
////////////////////
// SHADOW SPRITE! //
////////////////////
FOutVector swallVerts[4];
FSurfaceInfo sSurf;
fixed_t floorheight, mobjfloor;
mobjfloor = HWR_OpaqueFloorAtPos(
spr->mobj->x, spr->mobj->y,
spr->mobj->z, spr->mobj->height);
if (cv_shadowoffs.value)
{
angle_t shadowdir;
// Set direction
if (splitscreen && stplyr != &players[displayplayer])
shadowdir = localangle2 + FixedAngle(cv_cam2_rotate.value);
else
shadowdir = localangle + FixedAngle(cv_cam_rotate.value);
// Find floorheight
floorheight = HWR_OpaqueFloorAtPos(
spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - mobjfloor),
spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - mobjfloor),
spr->mobj->z, spr->mobj->height);
// The shadow is falling ABOVE it's mobj?
// Don't draw it, then!
if (spr->mobj->z < floorheight)
goto noshadow;
else
{
fixed_t floorz;
floorz = HWR_OpaqueFloorAtPos(
spr->mobj->x + P_ReturnThrustX(spr->mobj, shadowdir, spr->mobj->z - floorheight),
spr->mobj->y + P_ReturnThrustY(spr->mobj, shadowdir, spr->mobj->z - floorheight),
spr->mobj->z, spr->mobj->height);
// The shadow would be falling on a wall? Don't draw it, then.
// Would draw midair otherwise.
if (floorz < floorheight)
goto noshadow;
}
floorheight = FixedInt(spr->mobj->z - floorheight);
}
else
floorheight = FixedInt(spr->mobj->z - mobjfloor);
// create the sprite billboard
//
// 3--2
// | /|
// |/ |
// 0--1
// x1/x2 were already scaled in HWR_ProjectSprite
swallVerts[0].x = swallVerts[3].x = spr->x1;
swallVerts[2].x = swallVerts[1].x = spr->x2;
if (spr->mobj && this_scale != 1.0f)
{
// Always a pixel above the floor, perfectly flat.
swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset * this_scale - (floorheight+3);
swallVerts[0].z = swallVerts[1].z = spr->tz - (gpatch->height-gpatch->topoffset) * this_scale;
swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->topoffset * this_scale;
}
else
{
// Always a pixel above the floor, perfectly flat.
swallVerts[0].y = swallVerts[1].y = swallVerts[2].y = swallVerts[3].y = spr->ty - gpatch->topoffset - (floorheight+3);
// Spread out top away from the camera. (Fixme: Make it always move out in the same direction!... somehow.)
swallVerts[0].z = swallVerts[1].z = spr->tz - (gpatch->height-gpatch->topoffset);
swallVerts[2].z = swallVerts[3].z = spr->tz + gpatch->topoffset;
}
// transform
wv = swallVerts;
for (i = 0; i < 4; i++,wv++)
{
// Offset away from the camera based on height from floor.
if (cv_shadowoffs.value)
wv->z += floorheight;
wv->z += 3;
//look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
tr_x = wv->z;
tr_y = wv->y;
wv->y = (tr_x * gr_viewludcos) + (tr_y * gr_viewludsin);
wv->z = (tr_x * gr_viewludsin) - (tr_y * gr_viewludcos);
// ---------------------- mega lame test ----------------------------------
//scale y before frustum so that frustum can be scaled to screen height
wv->y *= ORIGINAL_ASPECT * gr_fovlud;
wv->x *= gr_fovlud;
}
if (spr->flip)
{
swallVerts[0].sow = swallVerts[3].sow = gpatch->max_s;
swallVerts[2].sow = swallVerts[1].sow = 0;
}
else
{
swallVerts[0].sow = swallVerts[3].sow = 0;
swallVerts[2].sow = swallVerts[1].sow = gpatch->max_s;
}
// flip the texture coords (look familiar?)
if (spr->vflip)
{
swallVerts[3].tow = swallVerts[2].tow = gpatch->max_t;
swallVerts[0].tow = swallVerts[1].tow = 0;
}
else
{
swallVerts[3].tow = swallVerts[2].tow = 0;
swallVerts[0].tow = swallVerts[1].tow = gpatch->max_t;
}
sSurf.FlatColor.s.red = 0x00;
sSurf.FlatColor.s.blue = 0x00;
sSurf.FlatColor.s.green = 0x00;
/*if (spr->mobj->frame & FF_TRANSMASK || spr->mobj->flags2 & MF2_SHADOW)
{
sector_t *sector = spr->mobj->subsector->sector;
UINT8 lightlevel = sector->lightlevel;
extracolormap_t *colormap = sector->extra_colormap;
if (sector->numlights)
{
INT32 light = R_GetPlaneLight(sector, spr->mobj->floorz, false);
if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *sector->lightlist[light].lightlevel;
else
lightlevel = 255;
if (sector->lightlist[light].extra_colormap)
colormap = sector->lightlist[light].extra_colormap;
}
else
{
lightlevel = sector->lightlevel;
if (sector->extra_colormap)
colormap = sector->extra_colormap;
}
if (colormap)
sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, colormap->rgba, colormap->fadergba, false, true);
else
sSurf.FlatColor.rgba = HWR_Lighting(lightlevel/2, NORMALFOG, FADEFOG, false, true);
}*/
// shadow is always half as translucent as the sprite itself
if (!cv_translucency.value)
; // translucency disabled
else if (spr->mobj->flags2 & MF2_SHADOW)
sSurf.FlatColor.s.alpha = 0x20;
else if (spr->mobj->frame & FF_TRANSMASK)
{
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &sSurf);
sSurf.FlatColor.s.alpha /= 2; //cut alpha in half!
}
else
sSurf.FlatColor.s.alpha = 0x80; // default
/// \todo do the test earlier
if (!cv_grmd2.value || (md2_models[spr->mobj->sprite].scale < 0.0f) || (md2_models[spr->mobj->sprite].notfound = true) || (md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) || (md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound = true))
{
if (sSurf.FlatColor.s.alpha > floorheight/4)
{
sSurf.FlatColor.s.alpha = (UINT8)(sSurf.FlatColor.s.alpha - floorheight/4);
HWD.pfnDrawPolygon(&sSurf, swallVerts, 4, PF_Translucent|PF_Modulated|PF_Clip);
}
}
HWR_DrawSpriteShadow(spr, gpatch, this_scale);
}
noshadow:
// This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black.
// sprite lighting by modulating the RGB components
/// \todo coloured
......@@ -3806,7 +4301,7 @@ noshadow:
// colormap test
{
sector_t *sector = spr->mobj->subsector->sector;
UINT8 lightlevel = sector->lightlevel;
UINT8 lightlevel = 255;
extracolormap_t *colormap = sector->extra_colormap;
if (sector->numlights)
......@@ -3817,8 +4312,6 @@ noshadow:
if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *sector->lightlist[light].lightlevel;
else
lightlevel = 255;
if (sector->lightlist[light].extra_colormap)
colormap = sector->lightlist[light].extra_colormap;
......@@ -3827,27 +4320,25 @@ noshadow:
{
if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = sector->lightlevel;
else
lightlevel = 255;
if (sector->extra_colormap)
colormap = sector->extra_colormap;
}
if (spr->mobj->frame & FF_FULLBRIGHT)
lightlevel = 255;
if (colormap)
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
else
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
}
/// \todo do the test earlier
if (!cv_grmd2.value || (md2_models[spr->mobj->sprite].scale < 0.0f))
{
FBITFIELD blend = 0;
if (spr->mobj->flags2 & MF2_SHADOW)
if (!cv_translucency.value) // translucency disabled
{
Surf.FlatColor.s.alpha = 0xFF;
blend = PF_Translucent|PF_Occlude;
}
else if (spr->mobj->flags2 & MF2_SHADOW)
{
Surf.FlatColor.s.alpha = 0x40;
blend = PF_Translucent;
......@@ -4006,10 +4497,10 @@ static void HWR_SortVisSprites(void)
gr_vsprsortedhead.next = gr_vsprsortedhead.prev = &gr_vsprsortedhead;
for (i = 0; i < gr_visspritecount; i++)
{
bestdist = ZCLIP_PLANE-1;
best = NULL;
for (ds = unsorted.next; ds != &unsorted; ds = ds->next)
{
if (ds->tz > bestdist)
if (!best || ds->tz > bestdist)
{
bestdist = ds->tz;
best = ds;
......@@ -4368,10 +4859,10 @@ static void HWR_DrawSprites(void)
#endif
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
{
if (!cv_grmd2.value || (cv_grmd2.value && md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound == true))
if (!cv_grmd2.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f)
HWR_DrawSprite(spr);
}
else if (!cv_grmd2.value || (cv_grmd2.value && md2_models[spr->mobj->sprite].notfound == true))
else if (!cv_grmd2.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f)
HWR_DrawSprite(spr);
}
}
......@@ -4397,7 +4888,7 @@ static void HWR_DrawMD2S(void)
#endif
if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY)
{
if ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound == false) && (md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale > 0.0f))
if (md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound == false && md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale > 0.0f)
HWR_DrawMD2(spr);
}
else if (md2_models[spr->mobj->sprite].notfound == false && md2_models[spr->mobj->sprite].scale > 0.0f)
......@@ -4439,23 +4930,12 @@ static void HWR_AddSprites(sector_t *sec)
// If a limit exists, handle things a tiny bit different.
if ((limit_dist = (fixed_t)((maptol & TOL_NIGHTS) ? cv_drawdist_nights.value : cv_drawdist.value) << FRACBITS))
{
if (!players[displayplayer].mo)
return; // Draw nothing if no player.
// todo: is this really the best option for this situation?
for (thing = sec->thinglist; thing; thing = thing->snext)
{
if (thing->sprite == SPR_NULL || thing->flags2 & MF2_DONTDRAW)
continue;
approx_dist = P_AproxDistance(
players[displayplayer].mo->x - thing->x,
players[displayplayer].mo->y - thing->y);
if (splitscreen && approx_dist > limit_dist && players[secondarydisplayplayer].mo)
approx_dist = P_AproxDistance(
players[secondarydisplayplayer].mo->x - thing->x,
players[secondarydisplayplayer].mo->y - thing->y);
approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y);
if (approx_dist <= limit_dist)
HWR_ProjectSprite(thing);
......@@ -4473,23 +4953,12 @@ static void HWR_AddSprites(sector_t *sec)
// Someone seriously wants infinite draw distance for precipitation?
if ((limit_dist = (fixed_t)cv_drawdist_precip.value << FRACBITS))
{
if (!players[displayplayer].mo)
return; // Draw nothing if no player.
// todo: is this really the best option for this situation?
for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext)
{
if (precipthing->invisible)
if (precipthing->precipflags & PCF_INVISIBLE)
continue;
approx_dist = P_AproxDistance(
players[displayplayer].mo->x - precipthing->x,
players[displayplayer].mo->y - precipthing->y);
if (splitscreen && approx_dist > limit_dist && players[secondarydisplayplayer].mo)
approx_dist = P_AproxDistance(
players[secondarydisplayplayer].mo->x - precipthing->x,
players[secondarydisplayplayer].mo->y - precipthing->y);
approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y);
if (approx_dist <= limit_dist)
HWR_ProjectPrecipitationSprite(precipthing);
......@@ -4499,7 +4968,7 @@ static void HWR_AddSprites(sector_t *sec)
{
// Draw everything in sector, no checks
for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext)
if (!precipthing->invisible)
if (!(precipthing->precipflags & PCF_INVISIBLE))
HWR_ProjectPrecipitationSprite(precipthing);
}
#endif
......@@ -4539,7 +5008,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
// thing is behind view plane?
if (tz < ZCLIP_PLANE)
if (tz < ZCLIP_PLANE && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
return;
tx = (tr_x * gr_viewsin) - (tr_y * gr_viewcos);
......@@ -4560,10 +5029,11 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (rot >= sprdef->numframes)
{
CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid sprite frame %s/%s for %s\n"),
CONS_Alert(CONS_ERROR, M_GetText("HWR_ProjectSprite: invalid sprite frame %s/%s for %s\n"),
sizeu1(rot), sizeu2(sprdef->numframes), sprnames[thing->sprite]);
thing->sprite = states[S_UNKNOWN].sprite;
thing->frame = states[S_UNKNOWN].frame;
sprdef = &sprites[thing->sprite];
rot = thing->frame&FF_FRAMEMASK;
thing->state->sprite = thing->sprite;
thing->state->frame = thing->frame;
......
......@@ -975,24 +975,25 @@ void HWR_InitMD2(void)
}
while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
{
if (stricmp(name, "PLAY") == 0)
{
CONS_Printf("MD2 for sprite PLAY detected in md2.dat, use a player skin instead!\n");
continue;
}
for (i = 0; i < NUMSPRITES; i++)
{
if (stricmp(name, sprnames[i]) == 0)
{
if (stricmp(name, "PLAY") == 0)
continue;
//if (stricmp(name, "PLAY") == 0)
//continue;
//CONS_Debug(DBG_RENDER, " Found: %s %s %f %f\n", name, filename, scale, offset);
md2_models[i].scale = scale;
md2_models[i].offset = offset;
md2_models[i].notfound = false;
strcpy(md2_models[i].filename, filename);
break;
}
if (i == NUMSPRITES)
{
CONS_Printf("MD2 for sprite %s not found\n", name);
md2_models[i].notfound = true;
goto md2found;
}
}
......@@ -1006,15 +1007,14 @@ void HWR_InitMD2(void)
md2_playermodels[s].offset = offset;
md2_playermodels[s].notfound = false;
strcpy(md2_playermodels[s].filename, filename);
break;
}
if (s == MAXSKINS-1)
{
CONS_Printf("MD2 for player skin %s not found\n", name);
md2_playermodels[s].notfound = true;
goto md2found;
}
}
// no sprite/player skin name found?!?
CONS_Printf("Unknown sprite/player skin %s detected in md2.dat\n", name);
md2found:
// move on to next line...
continue;
}
fclose(f);
}
......@@ -1050,17 +1050,14 @@ void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup
md2_playermodels[skin].offset = offset;
md2_playermodels[skin].notfound = false;
strcpy(md2_playermodels[skin].filename, filename);
break;
}
if (skin == MAXSKINS-1)
{
CONS_Printf("MD2 for player skin %s not found\n", name);
md2_playermodels[skin].notfound = true;
goto playermd2found;
}
}
//CONS_Printf("MD2 for player skin %s not found\n", skins[skin].name);
md2_playermodels[skin].notfound = true;
playermd2found:
fclose(f);
}
......@@ -1075,6 +1072,9 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu
if (nomd2s)
return;
if (spritenum == SPR_PLAY) // Handled already NEWMD2: Per sprite, per-skin check
return;
// Read the md2.dat file
f = fopen("md2.dat", "rt");
......@@ -1088,27 +1088,19 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu
// Check for any MD2s that match the names of player skins!
while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4)
{
if (stricmp(name, sprnames[spritenum]) == 0)
{
if (stricmp(name, sprnames[spritenum]) == 0)
{
if (stricmp(name, "PLAY") == 0) // Handled already NEWMD2: Per sprite, per-skin check
continue;
md2_models[spritenum].scale = scale;
md2_models[spritenum].offset = offset;
md2_models[spritenum].notfound = false;
strcpy(md2_models[spritenum].filename, filename);
break;
}
if (spritenum == NUMSPRITES-1)
{
CONS_Printf("MD2 for sprite %s not found\n", name);
md2_models[spritenum].notfound = true;
}
md2_models[spritenum].scale = scale;
md2_models[spritenum].offset = offset;
md2_models[spritenum].notfound = false;
strcpy(md2_models[spritenum].filename, filename);
goto spritemd2found;
}
}
//CONS_Printf("MD2 for sprite %s not found\n", sprnames[spritenum]);
md2_models[spritenum].notfound = true;
spritemd2found:
fclose(f);
}
......@@ -1386,11 +1378,17 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
md2_t *md2;
UINT8 color[4];
if (!cv_grmd2.value)
return;
if (spr->precip)
return;
// MD2 colormap fix
// colormap test
{
sector_t *sector = spr->mobj->subsector->sector;
UINT8 lightlevel = sector->lightlevel;
UINT8 lightlevel = 255;
extracolormap_t *colormap = sector->extra_colormap;
if (sector->numlights)
......@@ -1401,8 +1399,6 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *sector->lightlist[light].lightlevel;
else
lightlevel = 255;
if (sector->lightlist[light].extra_colormap)
colormap = sector->lightlist[light].extra_colormap;
......@@ -1411,24 +1407,18 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
{
if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = sector->lightlevel;
else
lightlevel = 255;
if (sector->extra_colormap)
colormap = sector->extra_colormap;
}
if (spr->mobj->frame & FF_FULLBRIGHT)
lightlevel = 255;
if (colormap)
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
else
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
}
// Look at HWR_ProjetctSprite for more
if (cv_grmd2.value && ((md2_models[spr->mobj->sprite].scale > 0.0f) || (md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale > 0.0f)) && !spr->precip)
// Look at HWR_ProjectSprite for more
{
GLPatch_t *gpatch;
INT32 *buff;
......@@ -1445,15 +1435,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
//durs = tics;
if (spr->mobj->flags2 & MF2_SHADOW)
{
Surf.FlatColor.s.alpha = 0x40;
}
else if (spr->mobj->frame & FF_TRANSMASK)
HWR_TranstableToAlpha((spr->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT, &Surf);
else
{
Surf.FlatColor.s.alpha = 0xFF;
}
// dont forget to enabled the depth test because we can't do this like
// before: polygons models are not sorted
......@@ -1571,8 +1557,6 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
p.flip = false;
HWD.pfnDrawMD2i(buff, curr, durs, tics, next, &p, finalscale, flip, color);
}
}
......
......@@ -1910,6 +1910,13 @@ EXPORT void HWRAPI(DrawMD2i) (INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 d
pglRotatef(pos->anglex, -1.0f, 0.0f, 0.0f);
//pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
// Remove depth mask when the model is transparent so it doesn't cut thorugh sprites // SRB2CBTODO: For all stuff too?!
if (color[3] < 255)
{
pglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha = level of transparency
pglDepthMask(GL_FALSE);
}
val = *gl_cmd_buffer++;
while (val != 0)
......
......@@ -26,7 +26,7 @@
#pragma warning(disable : 4214 4244)
#endif
#include "SDL_opengl.h" //Alam_GBC: Simple, yes?
#include <SDL2/SDL_opengl.h> //Alam_GBC: Simple, yes?
#ifdef _MSC_VER
#pragma warning(default : 4214 4244)
......
......@@ -150,8 +150,7 @@ state_t states[NUMSTATES] =
{SPR_PLAY, 34, 1, {NULL}, 0, 24, S_PLAY_SIGN}, // S_PLAY_SIGN
 
// Blue Crawla
{SPR_POSS, 0, 5, {A_Look}, 0, 0, S_POSS_STND2}, // S_POSS_STND
{SPR_POSS, 0, 5, {A_Look}, 0, 0, S_POSS_STND}, // S_POSS_STND2
{SPR_POSS, 0, 5, {A_Look}, 0, 0, S_POSS_STND}, // S_POSS_STND
{SPR_POSS, 0, 3, {A_Chase}, 0, 0, S_POSS_RUN2}, // S_POSS_RUN1
{SPR_POSS, 1, 3, {A_Chase}, 0, 0, S_POSS_RUN3}, // S_POSS_RUN2
{SPR_POSS, 2, 3, {A_Chase}, 0, 0, S_POSS_RUN4}, // S_POSS_RUN3
......@@ -160,8 +159,7 @@ state_t states[NUMSTATES] =
{SPR_POSS, 5, 3, {A_Chase}, 0, 0, S_POSS_RUN1}, // S_POSS_RUN6
 
// Red Crawla
{SPR_SPOS, 0, 5, {A_Look}, 0, 0, S_SPOS_STND2}, // S_SPOS_STND
{SPR_SPOS, 0, 5, {A_Look}, 0, 0, S_SPOS_STND}, // S_SPOS_STND2
{SPR_SPOS, 0, 5, {A_Look}, 0, 0, S_SPOS_STND}, // S_SPOS_STND
{SPR_SPOS, 0, 1, {A_Chase}, 0, 0, S_SPOS_RUN2}, // S_SPOS_RUN1
{SPR_SPOS, 1, 1, {A_Chase}, 0, 0, S_SPOS_RUN3}, // S_SPOS_RUN2
{SPR_SPOS, 2, 1, {A_Chase}, 0, 0, S_SPOS_RUN4}, // S_SPOS_RUN3
......
......@@ -663,7 +663,6 @@ typedef enum state
// Blue Crawla
S_POSS_STND,
S_POSS_STND2,
S_POSS_RUN1,
S_POSS_RUN2,
S_POSS_RUN3,
......@@ -673,7 +672,6 @@ typedef enum state
// Red Crawla
S_SPOS_STND,
S_SPOS_STND2,
S_SPOS_RUN1,
S_SPOS_RUN2,
S_SPOS_RUN3,
......
......@@ -85,13 +85,6 @@ static int lib_print(lua_State *L)
return 0;
}
static int lib_evalMath(lua_State *L)
{
const char *word = luaL_checkstring(L, 1);
lua_pushinteger(L, LUA_EvalMath(word));
return 1;
}
// M_RANDOM
//////////////
......@@ -138,25 +131,25 @@ static int lib_pRandomRange(lua_State *L)
static int lib_pAproxDistance(lua_State *L)
{
fixed_t dx = (fixed_t)luaL_checkinteger(L, 1);
fixed_t dy = (fixed_t)luaL_checkinteger(L, 2);
fixed_t dx = luaL_checkfixed(L, 1);
fixed_t dy = luaL_checkfixed(L, 2);
//HUDSAFE
lua_pushinteger(L, P_AproxDistance(dx, dy));
lua_pushfixed(L, P_AproxDistance(dx, dy));
return 1;
}
static int lib_pClosestPointOnLine(lua_State *L)
{
fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
line_t *line = *((line_t **)luaL_checkudata(L, 3, META_LINE));
vertex_t result;
//HUDSAFE
if (!line)
return LUA_ErrInvalid(L, "line_t");
P_ClosestPointOnLine(x, y, line, &result);
lua_pushinteger(L, result.x);
lua_pushinteger(L, result.y);
lua_pushfixed(L, result.x);
lua_pushfixed(L, result.y);
return 2;
}
......@@ -241,9 +234,9 @@ static int lib_pLookForPlayers(lua_State *L)
static int lib_pSpawnMobj(lua_State *L)
{
fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
fixed_t z = (fixed_t)luaL_checkinteger(L, 3);
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
fixed_t z = luaL_checkfixed(L, 3);
mobjtype_t type = luaL_checkinteger(L, 4);
NOHUD
if (type > MT_LASTFREESLOT)
......@@ -283,9 +276,9 @@ static int lib_pSpawnXYZMissile(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *dest = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
mobjtype_t type = luaL_checkinteger(L, 3);
fixed_t x = (fixed_t)luaL_checkinteger(L, 4);
fixed_t y = (fixed_t)luaL_checkinteger(L, 5);
fixed_t z = (fixed_t)luaL_checkinteger(L, 6);
fixed_t x = luaL_checkfixed(L, 4);
fixed_t y = luaL_checkfixed(L, 5);
fixed_t z = luaL_checkfixed(L, 6);
NOHUD
if (!source || !dest)
return LUA_ErrInvalid(L, "mobj_t");
......@@ -298,13 +291,13 @@ static int lib_pSpawnXYZMissile(lua_State *L)
static int lib_pSpawnPointMissile(lua_State *L)
{
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t xa = (fixed_t)luaL_checkinteger(L, 2);
fixed_t ya = (fixed_t)luaL_checkinteger(L, 3);
fixed_t za = (fixed_t)luaL_checkinteger(L, 4);
fixed_t xa = luaL_checkfixed(L, 2);
fixed_t ya = luaL_checkfixed(L, 3);
fixed_t za = luaL_checkfixed(L, 4);
mobjtype_t type = luaL_checkinteger(L, 5);
fixed_t x = (fixed_t)luaL_checkinteger(L, 6);
fixed_t y = (fixed_t)luaL_checkinteger(L, 7);
fixed_t z = (fixed_t)luaL_checkinteger(L, 8);
fixed_t x = luaL_checkfixed(L, 6);
fixed_t y = luaL_checkfixed(L, 7);
fixed_t z = luaL_checkfixed(L, 8);
NOHUD
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
......@@ -318,9 +311,9 @@ static int lib_pSpawnAlteredDirectionMissile(lua_State *L)
{
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobjtype_t type = luaL_checkinteger(L, 2);
fixed_t x = (fixed_t)luaL_checkinteger(L, 3);
fixed_t y = (fixed_t)luaL_checkinteger(L, 4);
fixed_t z = (fixed_t)luaL_checkinteger(L, 5);
fixed_t x = luaL_checkfixed(L, 3);
fixed_t y = luaL_checkfixed(L, 4);
fixed_t z = luaL_checkfixed(L, 5);
INT32 shiftingAngle = (INT32)luaL_checkinteger(L, 5);
NOHUD
if (!source)
......@@ -348,7 +341,7 @@ static int lib_pSPMAngle(lua_State *L)
{
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobjtype_t type = luaL_checkinteger(L, 2);
angle_t angle = (angle_t)luaL_checkinteger(L, 3);
angle_t angle = luaL_checkangle(L, 3);
UINT8 allowaim = (UINT8)luaL_optinteger(L, 4, 0);
UINT32 flags2 = (UINT32)luaL_optinteger(L, 5, 0);
NOHUD
......@@ -418,13 +411,13 @@ static int lib_pGetClosestAxis(lua_State *L)
static int lib_pSpawnParaloop(lua_State *L)
{
fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
fixed_t z = (fixed_t)luaL_checkinteger(L, 3);
fixed_t radius = (fixed_t)luaL_checkinteger(L, 4);
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
fixed_t z = luaL_checkfixed(L, 3);
fixed_t radius = luaL_checkfixed(L, 4);
INT32 number = (INT32)luaL_checkinteger(L, 5);
mobjtype_t type = luaL_checkinteger(L, 6);
angle_t rotangle = (angle_t)luaL_checkinteger(L, 7);
angle_t rotangle = luaL_checkangle(L, 7);
statenum_t nstate = luaL_optinteger(L, 8, S_NULL);
boolean spawncenter = lua_optboolean(L, 9);
NOHUD
......@@ -458,7 +451,7 @@ static int lib_pSupermanLook4Players(lua_State *L)
static int lib_pSetScale(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t newscale = (fixed_t)luaL_checkinteger(L, 2);
fixed_t newscale = luaL_checkfixed(L, 2);
NOHUD
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
......@@ -526,7 +519,7 @@ static int lib_pGetPlayerHeight(lua_State *L)
//HUDSAFE
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushinteger(L, P_GetPlayerHeight(player));
lua_pushfixed(L, P_GetPlayerHeight(player));
return 1;
}
......@@ -536,7 +529,7 @@ static int lib_pGetPlayerSpinHeight(lua_State *L)
//HUDSAFE
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushinteger(L, P_GetPlayerSpinHeight(player));
lua_pushfixed(L, P_GetPlayerSpinHeight(player));
return 1;
}
......@@ -639,7 +632,7 @@ static int lib_pInQuicksand(lua_State *L)
static int lib_pSetObjectMomZ(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t value = (fixed_t)luaL_checkinteger(L, 2);
fixed_t value = luaL_checkfixed(L, 2);
boolean relative = lua_optboolean(L, 3);
NOHUD
if (!mo)
......@@ -753,8 +746,8 @@ static int lib_pDoPlayerExit(lua_State *L)
static int lib_pInstaThrust(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
angle_t angle = (angle_t)luaL_checkinteger(L, 2);
fixed_t move = (fixed_t)luaL_checkinteger(L, 3);
angle_t angle = luaL_checkangle(L, 2);
fixed_t move = luaL_checkfixed(L, 3);
NOHUD
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
......@@ -768,10 +761,10 @@ static int lib_pReturnThrustX(lua_State *L)
fixed_t move;
if (lua_isnil(L, 1) || lua_isuserdata(L, 1))
lua_remove(L, 1); // ignore mobj as arg1
angle = (angle_t)luaL_checkinteger(L, 1);
move = (fixed_t)luaL_checkinteger(L, 2);
angle = luaL_checkangle(L, 1);
move = luaL_checkfixed(L, 2);
//HUDSAFE
lua_pushinteger(L, P_ReturnThrustX(NULL, angle, move));
lua_pushfixed(L, P_ReturnThrustX(NULL, angle, move));
return 1;
}
......@@ -781,10 +774,10 @@ static int lib_pReturnThrustY(lua_State *L)
fixed_t move;
if (lua_isnil(L, 1) || lua_isuserdata(L, 1))
lua_remove(L, 1); // ignore mobj as arg1
angle = (angle_t)luaL_checkinteger(L, 1);
move = (fixed_t)luaL_checkinteger(L, 2);
angle = luaL_checkangle(L, 1);
move = luaL_checkfixed(L, 2);
//HUDSAFE
lua_pushinteger(L, P_ReturnThrustY(NULL, angle, move));
lua_pushfixed(L, P_ReturnThrustY(NULL, angle, move));
return 1;
}
......@@ -802,7 +795,7 @@ static int lib_pNukeEnemies(lua_State *L)
{
mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t radius = (fixed_t)luaL_checkinteger(L, 3);
fixed_t radius = luaL_checkfixed(L, 3);
NOHUD
if (!inflictor || !source)
return LUA_ErrInvalid(L, "mobj_t");
......@@ -868,8 +861,8 @@ static int lib_pSpawnSpinMobj(lua_State *L)
static int lib_pTelekinesis(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
fixed_t thrust = (fixed_t)luaL_checkinteger(L, 2);
fixed_t range = (fixed_t)luaL_checkinteger(L, 3);
fixed_t thrust = luaL_checkfixed(L, 2);
fixed_t range = luaL_checkfixed(L, 3);
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
......@@ -884,8 +877,8 @@ static int lib_pCheckPosition(lua_State *L)
{
mobj_t *ptmthing = tmthing;
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t x = (fixed_t)luaL_checkinteger(L, 2);
fixed_t y = (fixed_t)luaL_checkinteger(L, 3);
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
NOHUD
if (!thing)
return LUA_ErrInvalid(L, "mobj_t");
......@@ -899,8 +892,8 @@ static int lib_pTryMove(lua_State *L)
{
mobj_t *ptmthing = tmthing;
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t x = (fixed_t)luaL_checkinteger(L, 2);
fixed_t y = (fixed_t)luaL_checkinteger(L, 3);
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
boolean allowdropoff = lua_optboolean(L, 4);
NOHUD
if (!thing)
......@@ -915,7 +908,7 @@ static int lib_pMove(lua_State *L)
{
mobj_t *ptmthing = tmthing;
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t speed = (fixed_t)luaL_checkinteger(L, 2);
fixed_t speed = luaL_checkfixed(L, 2);
NOHUD
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
......@@ -929,9 +922,9 @@ static int lib_pTeleportMove(lua_State *L)
{
mobj_t *ptmthing = tmthing;
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t x = (fixed_t)luaL_checkinteger(L, 2);
fixed_t y = (fixed_t)luaL_checkinteger(L, 3);
fixed_t z = (fixed_t)luaL_checkinteger(L, 4);
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
fixed_t z = luaL_checkfixed(L, 4);
NOHUD
if (!thing)
return LUA_ErrInvalid(L, "mobj_t");
......@@ -975,10 +968,10 @@ static int lib_pCheckSight(lua_State *L)
static int lib_pCheckHoopPosition(lua_State *L)
{
mobj_t *hoopthing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t x = (fixed_t)luaL_checkinteger(L, 2);
fixed_t y = (fixed_t)luaL_checkinteger(L, 3);
fixed_t z = (fixed_t)luaL_checkinteger(L, 4);
fixed_t radius = (fixed_t)luaL_checkinteger(L, 5);
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
fixed_t z = luaL_checkfixed(L, 4);
fixed_t radius = luaL_checkfixed(L, 5);
NOHUD
if (!hoopthing)
return LUA_ErrInvalid(L, "mobj_t");
......@@ -990,7 +983,7 @@ static int lib_pRadiusAttack(lua_State *L)
{
mobj_t *spot = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t damagedist = (fixed_t)luaL_checkinteger(L, 3);
fixed_t damagedist = luaL_checkfixed(L, 3);
NOHUD
if (!spot || !source)
return LUA_ErrInvalid(L, "mobj_t");
......@@ -1000,12 +993,12 @@ static int lib_pRadiusAttack(lua_State *L)
static int lib_pFloorzAtPos(lua_State *L)
{
fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
fixed_t z = (fixed_t)luaL_checkinteger(L, 3);
fixed_t height = (fixed_t)luaL_checkinteger(L, 4);
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
fixed_t z = luaL_checkfixed(L, 3);
fixed_t height = luaL_checkfixed(L, 4);
//HUDSAFE
lua_pushinteger(L, P_FloorzAtPos(x, y, z, height));
lua_pushfixed(L, P_FloorzAtPos(x, y, z, height));
return 1;
}
......@@ -1016,8 +1009,8 @@ static int lib_pDoSpring(lua_State *L)
NOHUD
if (!spring || !object)
return LUA_ErrInvalid(L, "mobj_t");
P_DoSpring(spring, object);
return 0;
lua_pushboolean(L, P_DoSpring(spring, object));
return 1;
}
// P_INTER
......@@ -1209,8 +1202,8 @@ static int lib_pDoNightsScore(lua_State *L)
static int lib_pThrust(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
angle_t angle = (angle_t)luaL_checkinteger(L, 2);
fixed_t move = (fixed_t)luaL_checkinteger(L, 3);
angle_t angle = luaL_checkangle(L, 2);
fixed_t move = luaL_checkfixed(L, 3);
NOHUD
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
......@@ -1485,48 +1478,48 @@ static int lib_evCrumbleChain(lua_State *L)
static int lib_rPointToAngle(lua_State *L)
{
fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
//HUDSAFE
lua_pushinteger(L, R_PointToAngle(x, y));
lua_pushangle(L, R_PointToAngle(x, y));
return 1;
}
static int lib_rPointToAngle2(lua_State *L)
{
fixed_t px2 = (fixed_t)luaL_checkinteger(L, 1);
fixed_t py2 = (fixed_t)luaL_checkinteger(L, 2);
fixed_t px1 = (fixed_t)luaL_checkinteger(L, 3);
fixed_t py1 = (fixed_t)luaL_checkinteger(L, 4);
fixed_t px2 = luaL_checkfixed(L, 1);
fixed_t py2 = luaL_checkfixed(L, 2);
fixed_t px1 = luaL_checkfixed(L, 3);
fixed_t py1 = luaL_checkfixed(L, 4);
//HUDSAFE
lua_pushinteger(L, R_PointToAngle2(px2, py2, px1, py1));
lua_pushangle(L, R_PointToAngle2(px2, py2, px1, py1));
return 1;
}
static int lib_rPointToDist(lua_State *L)
{
fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
//HUDSAFE
lua_pushinteger(L, R_PointToDist(x, y));
lua_pushfixed(L, R_PointToDist(x, y));
return 1;
}
static int lib_rPointToDist2(lua_State *L)
{
fixed_t px2 = (fixed_t)luaL_checkinteger(L, 1);
fixed_t py2 = (fixed_t)luaL_checkinteger(L, 2);
fixed_t px1 = (fixed_t)luaL_checkinteger(L, 3);
fixed_t py1 = (fixed_t)luaL_checkinteger(L, 4);
fixed_t px2 = luaL_checkfixed(L, 1);
fixed_t py2 = luaL_checkfixed(L, 2);
fixed_t px1 = luaL_checkfixed(L, 3);
fixed_t py1 = luaL_checkfixed(L, 4);
//HUDSAFE
lua_pushinteger(L, R_PointToDist2(px2, py2, px1, py1));
lua_pushfixed(L, R_PointToDist2(px2, py2, px1, py1));
return 1;
}
static int lib_rPointInSubsector(lua_State *L)
{
fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
//HUDSAFE
LUA_PushUserdata(L, R_PointInSubsector(x, y), META_SUBSECTOR);
return 1;
......@@ -1660,7 +1653,7 @@ static int lib_sChangeMusic(lua_State *L)
static int lib_sSpeedMusic(lua_State *L)
{
fixed_t fixedspeed = (fixed_t)luaL_checkinteger(L, 1);
fixed_t fixedspeed = luaL_checkfixed(L, 1);
float speed = FIXED_TO_FLOAT(fixedspeed);
player_t *player = NULL;
NOHUD
......@@ -1861,7 +1854,6 @@ static int lib_gTicsToMilliseconds(lua_State *L)
static luaL_Reg lib[] = {
{"print", lib_print},
{"EvalMath", lib_evalMath},
// m_random
{"P_Random",lib_pRandom},
......
......@@ -14,6 +14,7 @@
#include "r_defs.h"
#include "d_player.h"
#include "blua/lua.h"
enum hook {
hook_NetVars=0,
......@@ -41,12 +42,13 @@ enum hook {
hook_BotAI,
hook_LinedefExecute,
hook_PlayerMsg,
hook_DeathMsg,
hook_HurtMsg,
hook_MAX // last hook
};
extern const char *const hookNames[];
void LUAh_NetArchiveHook(lua_CFunction archFunc);
void LUAh_MapChange(void); // Hook for map change (before load)
void LUAh_MapLoad(void); // Hook for map load
void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer
......@@ -54,8 +56,9 @@ void LUAh_ThinkFrame(void); // Hook for frame (after mobj and player thinkers)
boolean LUAh_MobjHook(mobj_t *mo, enum hook which);
boolean LUAh_PlayerHook(player_t *plr, enum hook which);
#define LUAh_MobjSpawn(mo) LUAh_MobjHook(mo, hook_MobjSpawn) // Hook for P_SpawnMobj by mobj type
UINT8 LUAh_MobjCollide(mobj_t *thing1, mobj_t *thing2); // Hook for PIT_CheckThing by (thing) mobj type
UINT8 LUAh_MobjMoveCollide(mobj_t *thing1, mobj_t *thing2); // Hook for PIT_CheckThing by (tmthing) mobj type
UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which);
#define LUAh_MobjCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjCollide) // Hook for PIT_CheckThing by (thing) mobj type
#define LUAh_MobjMoveCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjMoveCollide) // Hook for PIT_CheckThing by (tmthing) mobj type
boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher); // Hook for P_TouchSpecialThing by mobj type
#define LUAh_MobjFuse(mo) LUAh_MobjHook(mo, hook_MobjFuse) // Hook for mobj->fuse == 0 by mobj type
#define LUAh_MobjThinker(mo) LUAh_MobjHook(mo, hook_MobjThinker) // Hook for P_MobjThinker or P_SceneryThinker by mobj type
......@@ -73,6 +76,6 @@ boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd
boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name
boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors
boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages
boolean LUAh_DeathMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages
boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages
#endif
......@@ -56,23 +56,40 @@ const char *const hookNames[hook_MAX+1] = {
NULL
};
// Hook metadata
struct hook_s
{
struct hook_s *next;
enum hook type;
UINT16 id;
union {
mobjtype_t mt;
char *skinname;
char *funcname;
} s;
boolean error;
};
typedef struct hook_s* hook_p;
#define FMT_HOOKID "hook_%d"
hook_p roothook;
// Takes hook, function, and additional arguments (mobj type to act on, etc.)
static int lib_addHook(lua_State *L)
{
UINT16 hook;
boolean notable = false;
boolean subtable = false;
UINT32 subindex = 0;
char *subfield = NULL;
const char *lsubfield = NULL;
static struct hook_s hook = {NULL, 0, 0, {0}, false};
hook_p hookp, *lastp;
hook.type = luaL_checkoption(L, 1, NULL, hookNames);
lua_remove(L, 1);
hook = (UINT16)luaL_checkoption(L, 1, NULL, hookNames);
luaL_checktype(L, 2, LUA_TFUNCTION);
luaL_checktype(L, 1, LUA_TFUNCTION);
if (hud_running)
return luaL_error(L, "HUD rendering code should not call this function!");
switch(hook)
switch(hook.type)
{
// Take a mobjtype enum which this hook is specifically for.
case hook_MobjSpawn:
......@@ -87,918 +104,696 @@ static int lib_addHook(lua_State *L)
case hook_MobjDeath:
case hook_BossDeath:
case hook_MobjRemoved:
subtable = true;
if (lua_isnumber(L, 3))
subindex = (UINT32)luaL_checkinteger(L, 3);
else
lsubfield = "a";
lua_settop(L, 2);
case hook_HurtMsg:
hook.s.mt = MT_NULL;
if (lua_isnumber(L, 2))
hook.s.mt = lua_tonumber(L, 2);
break;
case hook_BotAI: // Only one AI function per skin, please!
notable = true;
subtable = true;
subfield = ZZ_Alloc(strlen(luaL_checkstring(L, 3))+1);
case hook_BotAI:
hook.s.skinname = NULL;
if (lua_isstring(L, 2))
{ // lowercase copy
char *p = subfield;
const char *s = luaL_checkstring(L, 3);
const char *s = lua_tostring(L, 2);
char *p = hook.s.skinname = ZZ_Alloc(strlen(s)+1);
do {
*p = tolower(*s);
++p;
} while(*(++s));
*p = 0;
}
lua_settop(L, 3);
break;
case hook_LinedefExecute: // Get one linedef executor function by name
notable = true;
subtable = true;
subfield = ZZ_Alloc(strlen(luaL_checkstring(L, 3))+1);
case hook_LinedefExecute: // Linedef executor functions
{ // uppercase copy
char *p = subfield;
const char *s = luaL_checkstring(L, 3);
const char *s = luaL_checkstring(L, 2);
char *p = hook.s.funcname = ZZ_Alloc(strlen(s)+1);
do {
*p = toupper(*s);
++p;
} while(*(++s));
*p = 0;
}
lua_settop(L, 3);
break;
default:
lua_settop(L, 2);
break;
}
lua_settop(L, 1); // lua stack contains only the function now.
lua_getfield(L, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(L, -1));
hooksAvailable[hook.type/8] |= 1<<(hook.type%8);
// This hook type only allows one entry, not an array of hooks.
// New hooks will overwrite the previous ones, and the stack is one table shorter.
if (notable)
// iterate the hook metadata structs
// set hook.id to the highest id + 1
// set lastp to the last hook struct's "next" pointer.
lastp = &roothook;
hook.id = 0;
for (hookp = roothook; hookp; hookp = hookp->next)
{
if (subtable)
{
lua_rawgeti(L, -1, hook);
lua_remove(L, -2); // pop "hook"
I_Assert(lua_istable(L, -1));
lua_pushvalue(L, 2);
if (subfield)
lua_setfield(L, -2, subfield);
else if (lsubfield)
lua_setfield(L, -2, lsubfield);
else
lua_rawseti(L, -2, subindex);
} else {
lua_pushvalue(L, 2);
lua_rawseti(L, -2, hook);
}
hooksAvailable[hook/8] |= 1<<(hook%8);
return 0;
if (hookp->id >= hook.id)
hook.id = hookp->id+1;
lastp = &hookp->next;
}
// Fetch the hook's table from the registry.
// It should always exist, since LUA_HookLib creates a table for every hook.
lua_rawgeti(L, -1, hook);
lua_remove(L, -2); // pop "hook"
I_Assert(lua_istable(L, -1));
if (subtable)
{
// Fetch a subtable based on index
if (subfield)
lua_getfield(L, -1, subfield);
else if (lsubfield)
lua_getfield(L, -1, lsubfield);
else
lua_rawgeti(L, -1, subindex);
// Subtable doesn't exist, make one now.
if (lua_isnil(L, -1))
{
lua_pop(L, 1);
lua_newtable(L);
// Store a link to the subtable for later.
lua_pushvalue(L, -1);
if (subfield)
lua_setfield(L, -3, subfield);
else if (lsubfield)
lua_setfield(L, -3, lsubfield);
else
lua_rawseti(L, -3, subindex);
} }
// Add function to the table.
lua_pushvalue(L, 2);
lua_rawseti(L, -2, (int)(lua_objlen(L, -2) + 1));
if (subfield)
Z_Free(subfield);
hooksAvailable[hook/8] |= 1<<(hook%8);
// allocate a permanent memory struct to stuff hook.
hookp = ZZ_Alloc(sizeof(struct hook_s));
memcpy(hookp, &hook, sizeof(struct hook_s));
// tack it onto the end of the linked list.
*lastp = hookp;
// set the hook function in the registry.
lua_pushfstring(L, FMT_HOOKID, hook.id);
lua_pushvalue(L, 1);
lua_settable(L, LUA_REGISTRYINDEX);
return 0;
}
int LUA_HookLib(lua_State *L)
{
// Create all registry tables
enum hook i;
memset(hooksAvailable,0,sizeof(UINT8[(hook_MAX/8)+1]));
lua_newtable(L);
for (i = 0; i < hook_MAX; i++)
{
lua_newtable(L);
switch(i)
{
default:
break;
case hook_MobjSpawn:
case hook_MobjCollide:
case hook_MobjMoveCollide:
case hook_TouchSpecial:
case hook_MobjFuse:
case hook_MobjThinker:
case hook_BossThinker:
case hook_ShouldDamage:
case hook_MobjDamage:
case hook_MobjDeath:
case hook_BossDeath:
case hook_MobjRemoved:
lua_pushstring(L, "a");
lua_newtable(L);
lua_rawset(L, -3);
break;
}
lua_rawseti(L, -2, i);
}
lua_setfield(L, LUA_REGISTRYINDEX, "hook");
roothook = NULL;
lua_register(L, "addHook", lib_addHook);
return 0;
}
boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
void LUAh_NetArchiveHook(lua_CFunction archFunc)
{
boolean hooked = false;
if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
return false;
int TABLESINDEX;
hook_p hookp;
// clear the stack (just in case)
lua_pop(gL, -1);
if (!gL)
return;
// hook table
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, which);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
TABLESINDEX = lua_gettop(gL);
// generic subtable
lua_pushstring(gL, "a");
lua_rawget(gL, -2);
I_Assert(lua_istable(gL, -1));
lua_settop(gL, 0);
LUA_PushUserdata(gL, mo, META_MOBJ);
lua_pushvalue(gL, TABLESINDEX);
lua_pushcclosure(gL, archFunc, 1);
lua_pushnil(gL);
while (lua_next(gL, -3)) {
CONS_Debug(DBG_LUA, "MobjHook: Calling hook_%s for generic mobj types\n", hookNames[which]);
lua_pushvalue(gL, -3); // mo
// stack is: hook_Mobj table, subtable "a", mobj, i, function, mobj
if (lua_pcall(gL, 1, 1, 0)) {
// A run-time error occurred.
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
lua_pop(gL, 1);
// Remove this function from the hook table to prevent further errors.
lua_pushvalue(gL, -1); // key
lua_pushnil(gL); // value
lua_rawset(gL, -5); // table
CONS_Printf("Hook removed.\n");
}
else
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_NetVars)
{
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -2);
LUA_Call(gL, 1);
}
}
// stack is: hook_Mobj table, subtable "a", mobj
lua_remove(gL, -2); // pop subtable, leave mobj
// mobjtype subtable
// stack is: hook_Mobj table, mobj
lua_rawgeti(gL, -2, mo->type);
if (lua_isnil(gL, -1)) {
lua_pop(gL, 3); // pop hook_Mobj table, mobj, and nil
// the stack should now be empty.
lua_pop(gL, 2);
}
boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
return false;
}
lua_remove(gL, -3); // remove hook table
// stack is: mobj, mobjtype subtable
lua_insert(gL, lua_gettop(gL)-1); // swap subtable with mobj
// stack is: mobjtype subtable, mobj
lua_pushnil(gL);
while (lua_next(gL, -3)) {
CONS_Debug(DBG_LUA, "MobjHook: Calling hook_%s for mobj type %d\n", hookNames[which], mo->type);
lua_pushvalue(gL, -3); // mo
// stack is: mobjtype subtable, mobj, i, function, mobj
if (lua_pcall(gL, 1, 1, 0)) {
// A run-time error occurred.
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
lua_pop(gL, 1);
// Remove this function from the hook table to prevent further errors.
lua_pushvalue(gL, -1); // key
lua_pushnil(gL); // value
lua_rawset(gL, -5); // table
CONS_Printf("Hook removed.\n");
}
else
lua_settop(gL, 0);
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == which
&& (hookp->s.mt == MT_NULL || hookp->s.mt == mo->type))
{
if (lua_gettop(gL) == 0)
LUA_PushUserdata(gL, mo, META_MOBJ);
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -2);
if (lua_pcall(gL, 1, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
}
}
lua_pop(gL, 2); // pop mobj and subtable
// the stack should now be empty.
lua_gc(gL, LUA_GCSTEP, 3);
lua_settop(gL, 0);
return hooked;
}
boolean LUAh_PlayerHook(player_t *plr, enum hook which)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
return false;
// clear the stack (just in case)
lua_pop(gL, -1);
// hook table
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, which);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
LUA_PushUserdata(gL, plr, META_PLAYER);
lua_settop(gL, 0);
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // player
if (lua_pcall(gL, 1, 1, 0)) { // pops hook function, player, pushes 1 return result
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == which)
{
if (lua_gettop(gL) == 0)
LUA_PushUserdata(gL, plr, META_PLAYER);
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -2);
if (lua_pcall(gL, 1, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
continue;
}
if (lua_toboolean(gL, -1)) // if return true,
hooked = true; // override vanilla behavior
lua_pop(gL, 1); // pop return value
}
lua_pop(gL, -1);
lua_gc(gL, LUA_GCSTEP, 1);
lua_settop(gL, 0);
return hooked;
}
// Hook for map change (before load)
void LUAh_MapChange(void)
{
hook_p hookp;
if (!gL || !(hooksAvailable[hook_MapChange/8] & (1<<(hook_MapChange%8))))
return;
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_MapChange);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
lua_settop(gL, 0);
lua_pushinteger(gL, gamemap);
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // gamemap
LUA_Call(gL, 1);
}
lua_pop(gL, 1);
lua_gc(gL, LUA_GCSTEP, 1);
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_MapChange)
{
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -2);
LUA_Call(gL, 1);
}
lua_settop(gL, 0);
}
// Hook for map load
void LUAh_MapLoad(void)
{
hook_p hookp;
if (!gL || !(hooksAvailable[hook_MapLoad/8] & (1<<(hook_MapLoad%8))))
return;
lua_pop(gL, -1);
lua_settop(gL, 0);
lua_pushinteger(gL, gamemap);
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_MapLoad);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_MapLoad)
{
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -2);
LUA_Call(gL, 1);
}
lua_pushinteger(gL, gamemap);
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // gamemap
LUA_Call(gL, 1);
}
lua_pop(gL, -1);
lua_gc(gL, LUA_GCCOLLECT, 0);
lua_settop(gL, 0);
}
// Hook for Got_AddPlayer
void LUAh_PlayerJoin(int playernum)
{
hook_p hookp;
if (!gL || !(hooksAvailable[hook_PlayerJoin/8] & (1<<(hook_PlayerJoin%8))))
return;
lua_pop(gL, -1);
lua_settop(gL, 0);
lua_pushinteger(gL, playernum);
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_PlayerJoin);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_PlayerJoin)
{
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -2);
LUA_Call(gL, 1);
}
lua_pushinteger(gL, playernum);
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // playernum
LUA_Call(gL, 1);
}
lua_pop(gL, -1);
lua_gc(gL, LUA_GCCOLLECT, 0);
lua_settop(gL, 0);
}
// Hook for frame (after mobj and player thinkers)
void LUAh_ThinkFrame(void)
{
hook_p hookp;
if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8))))
return;
lua_pop(gL, -1);
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_ThinkFrame);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
lua_pushnil(gL);
while (lua_next(gL, -2) != 0)
{
//LUA_Call(gL, 0);
if (lua_pcall(gL, 0, 0, 0))
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_ThinkFrame)
{
// A run-time error occurred.
CONS_Alert(CONS_WARNING,"%s\n", lua_tostring(gL, -1));
lua_pop(gL, 1);
// Remove this function from the hook table to prevent further errors.
lua_pushvalue(gL, -1); // key
lua_pushnil(gL); // value
lua_rawset(gL, -4); // table
CONS_Printf("Hook removed.\n");
}
}
lua_pop(gL, -1);
lua_gc(gL, LUA_GCCOLLECT, 0);
}
// Hook for PIT_CheckThing by (thing) mobj type (thing1 = thing, thing2 = tmthing)
UINT8 LUAh_MobjCollide(mobj_t *thing1, mobj_t *thing2)
{
UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no.
if (!gL || !(hooksAvailable[hook_MobjCollide/8] & (1<<(hook_MobjCollide%8))))
return 0;
// clear the stack
lua_pop(gL, -1);
// hook table
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_MobjCollide);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
// mobjtype subtable
lua_rawgeti(gL, -1, thing1->type);
if (lua_isnil(gL, -1)) {
lua_pop(gL, 2);
return 0;
}
lua_remove(gL, -2); // remove hook table
LUA_PushUserdata(gL, thing1, META_MOBJ);
LUA_PushUserdata(gL, thing2, META_MOBJ);
lua_pushnil(gL);
while (lua_next(gL, -4)) {
lua_pushvalue(gL, -4); // thing1
lua_pushvalue(gL, -4); // thing2
if (lua_pcall(gL, 2, 1, 0)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
lua_pop(gL, 1);
continue;
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
if (lua_pcall(gL, 0, 0, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
}
}
if (!lua_isnil(gL, -1))
{ // if nil, leave shouldCollide = 0.
if (lua_toboolean(gL, -1))
shouldCollide = 1; // Force yes
else
shouldCollide = 2; // Force no
}
lua_pop(gL, 1); // pop return value
}
lua_pop(gL, 3); // pop arguments and mobjtype table
lua_gc(gL, LUA_GCSTEP, 1);
return shouldCollide;
}
// Hook for PIT_CheckThing by (tmthing) mobj type (thing1 = tmthing, thing2 = thing)
UINT8 LUAh_MobjMoveCollide(mobj_t *thing1, mobj_t *thing2)
// Hook for mobj collisions
UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
{
hook_p hookp;
UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no.
if (!gL || !(hooksAvailable[hook_MobjMoveCollide/8] & (1<<(hook_MobjMoveCollide%8))))
if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
return 0;
// clear the stack
lua_pop(gL, -1);
lua_settop(gL, 0);
// hook table
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_MobjMoveCollide);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
// mobjtype subtable
lua_rawgeti(gL, -1, thing1->type);
if (lua_isnil(gL, -1)) {
lua_pop(gL, 2);
return 0;
}
lua_remove(gL, -2); // remove hook table
LUA_PushUserdata(gL, thing1, META_MOBJ);
LUA_PushUserdata(gL, thing2, META_MOBJ);
lua_pushnil(gL);
while (lua_next(gL, -4)) {
lua_pushvalue(gL, -4); // thing1
lua_pushvalue(gL, -4); // thing2
if (lua_pcall(gL, 2, 1, 0)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == which
&& (hookp->s.mt == MT_NULL || hookp->s.mt == thing1->type))
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, thing1, META_MOBJ);
LUA_PushUserdata(gL, thing2, META_MOBJ);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -3);
lua_pushvalue(gL, -3);
if (lua_pcall(gL, 2, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (!lua_isnil(gL, -1))
{ // if nil, leave shouldCollide = 0.
if (lua_toboolean(gL, -1))
shouldCollide = 1; // Force yes
else
shouldCollide = 2; // Force no
}
lua_pop(gL, 1);
continue;
}
if (!lua_isnil(gL, -1))
{ // if nil, leave shouldCollide = 0.
if (lua_toboolean(gL, -1))
shouldCollide = 1; // Force yes
else
shouldCollide = 2; // Force no
}
lua_pop(gL, 1); // pop return value
}
lua_pop(gL, 3); // pop arguments and mobjtype table
lua_gc(gL, LUA_GCSTEP, 1);
lua_settop(gL, 0);
return shouldCollide;
}
// Hook for P_TouchSpecialThing by mobj type
boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8))))
return false;
// clear the stack
lua_pop(gL, -1);
// get hook table
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_TouchSpecial);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
// get mobjtype subtable
lua_pushinteger(gL, special->type);
lua_rawget(gL, 1);
if (lua_isnil(gL, -1)) {
lua_pop(gL, 2);
return false;
}
lua_remove(gL, 1); // pop hook table off the stack
return 0;
LUA_PushUserdata(gL, special, META_MOBJ);
LUA_PushUserdata(gL, toucher, META_MOBJ);
lua_settop(gL, 0);
lua_pushnil(gL);
while (lua_next(gL, 1) != 0) {
lua_pushvalue(gL, 2); // special
lua_pushvalue(gL, 3); // toucher
if (lua_pcall(gL, 2, 1, 0)) { // pops hook function, special, toucher, pushes 1 return result
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_TouchSpecial
&& (hookp->s.mt == MT_NULL || hookp->s.mt == special->type))
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, special, META_MOBJ);
LUA_PushUserdata(gL, toucher, META_MOBJ);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -3);
lua_pushvalue(gL, -3);
if (lua_pcall(gL, 2, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
continue;
}
if (lua_toboolean(gL, -1)) // if return true,
hooked = true; // override vanilla behavior
lua_pop(gL, 1); // pop return value
}
lua_pop(gL, -1);
lua_gc(gL, LUA_GCSTEP, 1);
lua_settop(gL, 0);
return hooked;
}
// Hook for P_DamageMobj by mobj type (Should mobj take damage?)
UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage)
{
hook_p hookp;
UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no.
if (!gL || !(hooksAvailable[hook_ShouldDamage/8] & (1<<(hook_ShouldDamage%8))))
return 0;
// clear the stack
lua_pop(gL, -1);
lua_settop(gL, 0);
// hook table
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_ShouldDamage);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
// mobjtype subtable
lua_rawgeti(gL, -1, target->type);
if (lua_isnil(gL, -1)) {
lua_pop(gL, 2);
return 0;
}
lua_remove(gL, -2); // remove hook table
LUA_PushUserdata(gL, target, META_MOBJ);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
lua_pushinteger(gL, damage);
lua_pushnil(gL);
while (lua_next(gL, -6)) {
lua_pushvalue(gL, -6); // target
lua_pushvalue(gL, -6); // inflictor
lua_pushvalue(gL, -6); // source
lua_pushvalue(gL, -6); // damage
if (lua_pcall(gL, 4, 1, 0)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_ShouldDamage
&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, target, META_MOBJ);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
lua_pushinteger(gL, damage);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -5);
lua_pushvalue(gL, -5);
lua_pushvalue(gL, -5);
lua_pushvalue(gL, -5);
if (lua_pcall(gL, 4, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (!lua_isnil(gL, -1))
{
if (lua_toboolean(gL, -1))
shouldDamage = 1; // Force yes
else
shouldDamage = 2; // Force no
}
lua_pop(gL, 1);
continue;
}
if (!lua_isnil(gL, -1))
{ // if nil, leave shouldDamage = 0.
if (lua_toboolean(gL, -1))
shouldDamage = 1; // Force yes
else
shouldDamage = 2; // Force no
}
lua_pop(gL, 1); // pop return value
}
lua_pop(gL, 5); // pop arguments and mobjtype table
lua_gc(gL, LUA_GCSTEP, 1);
lua_settop(gL, 0);
return shouldDamage;
}
// Hook for P_DamageMobj by mobj type (Mobj actually takes damage!)
boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage)
{
boolean handled = false;
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8))))
return false;
// clear the stack
lua_pop(gL, -1);
// hook table
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_MobjDamage);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
return 0;
// mobjtype subtable
lua_rawgeti(gL, -1, target->type);
if (lua_isnil(gL, -1)) {
lua_pop(gL, 2);
return false;
}
lua_remove(gL, -2); // remove hook table
lua_settop(gL, 0);
LUA_PushUserdata(gL, target, META_MOBJ);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
lua_pushinteger(gL, damage);
lua_pushnil(gL);
while (lua_next(gL, -6)) {
lua_pushvalue(gL, -6); // target
lua_pushvalue(gL, -6); // inflictor
lua_pushvalue(gL, -6); // source
lua_pushvalue(gL, -6); // damage
if (lua_pcall(gL, 4, 1, 0)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_MobjDamage
&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, target, META_MOBJ);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
lua_pushinteger(gL, damage);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -5);
lua_pushvalue(gL, -5);
lua_pushvalue(gL, -5);
lua_pushvalue(gL, -5);
if (lua_pcall(gL, 4, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
continue;
}
if (lua_toboolean(gL, -1))
handled = true;
lua_pop(gL, 1); // pop return value
}
lua_pop(gL, 5); // pop arguments and mobjtype table
lua_gc(gL, LUA_GCSTEP, 1);
return handled;
lua_settop(gL, 0);
return hooked;
}
// Hook for P_KillMobj by mobj type
boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source)
{
boolean handled = false;
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8))))
return false;
// clear the stack
lua_pop(gL, -1);
// hook table
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_MobjDeath);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
return 0;
// mobjtype subtable
lua_rawgeti(gL, -1, target->type);
if (lua_isnil(gL, -1)) {
lua_pop(gL, 2);
return false;
}
lua_remove(gL, -2); // remove hook table
lua_settop(gL, 0);
LUA_PushUserdata(gL, target, META_MOBJ);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
lua_pushnil(gL);
while (lua_next(gL, -5)) {
lua_pushvalue(gL, -5); // target
lua_pushvalue(gL, -5); // inflictor
lua_pushvalue(gL, -5); // source
if (lua_pcall(gL, 3, 1, 0)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_MobjDeath
&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, target, META_MOBJ);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
if (lua_pcall(gL, 3, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
continue;
}
if (lua_toboolean(gL, -1))
handled = true;
lua_pop(gL, 1); // pop return value
}
lua_pop(gL, 4); // pop arguments and mobjtype table
lua_gc(gL, LUA_GCSTEP, 1);
return handled;
lua_settop(gL, 0);
return hooked;
}
// Hook for B_BuildTiccmd
boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_BotTiccmd/8] & (1<<(hook_BotTiccmd%8))))
return false;
// clear the stack
lua_pop(gL, -1);
lua_settop(gL, 0);
// hook table
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_BotTiccmd);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
LUA_PushUserdata(gL, bot, META_PLAYER);
LUA_PushUserdata(gL, cmd, META_TICCMD);
lua_pushnil(gL);
while (lua_next(gL, 1)) {
lua_pushvalue(gL, 2); // bot
lua_pushvalue(gL, 3); // cmd
if (lua_pcall(gL, 2, 1, 0)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_BotTiccmd)
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, bot, META_PLAYER);
LUA_PushUserdata(gL, cmd, META_TICCMD);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -3);
lua_pushvalue(gL, -3);
if (lua_pcall(gL, 2, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1); // pop return value
}
lua_pop(gL, -1);
lua_gc(gL, LUA_GCSTEP, 1);
lua_settop(gL, 0);
return hooked;
}
// Hook for B_BuildTailsTiccmd by skin name
boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
{
if (!gL || !tails->skin || !(hooksAvailable[hook_BotAI/8] & (1<<(hook_BotAI%8))))
return false;
// clear the stack
lua_pop(gL, -1);
// hook table
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_BotAI);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
// bot skin ai function
lua_getfield(gL, 1, ((skin_t *)tails->skin)->name);
if (lua_isnil(gL, -1)) {
lua_pop(gL, 2);
return false;
}
lua_remove(gL, 1); // pop the hook table
// Takes sonic, tails
// Returns forward, backward, left, right, jump, spin
LUA_PushUserdata(gL, sonic, META_MOBJ);
LUA_PushUserdata(gL, tails, META_MOBJ);
if (lua_pcall(gL, 2, 8, 0)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
lua_pop(gL,-1);
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_BotAI/8] & (1<<(hook_BotAI%8))))
return false;
}
// This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails.
if (lua_istable(gL, 1)) {
boolean forward=false, backward=false, left=false, right=false, strafeleft=false, straferight=false, jump=false, spin=false;
lua_settop(gL, 0);
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_BotAI
&& (hookp->s.skinname == NULL || !strcmp(hookp->s.skinname, ((skin_t*)tails->skin)->name)))
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, sonic, META_MOBJ);
LUA_PushUserdata(gL, tails, META_MOBJ);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -3);
lua_pushvalue(gL, -3);
if (lua_pcall(gL, 2, 8, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
// This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails.
if (lua_istable(gL, 2+1)) {
boolean forward=false, backward=false, left=false, right=false, strafeleft=false, straferight=false, jump=false, spin=false;
#define CHECKFIELD(field) \
lua_getfield(gL, 1, #field);\
if (lua_toboolean(gL, -1))\
field = true;\
lua_pop(gL, 1);
CHECKFIELD(forward)
CHECKFIELD(backward)
CHECKFIELD(left)
CHECKFIELD(right)
CHECKFIELD(strafeleft)
CHECKFIELD(straferight)
CHECKFIELD(jump)
CHECKFIELD(spin)
lua_getfield(gL, 2+1, #field);\
if (lua_toboolean(gL, -1))\
field = true;\
lua_pop(gL, 1);
CHECKFIELD(forward)
CHECKFIELD(backward)
CHECKFIELD(left)
CHECKFIELD(right)
CHECKFIELD(strafeleft)
CHECKFIELD(straferight)
CHECKFIELD(jump)
CHECKFIELD(spin)
#undef CHECKFIELD
B_KeysToTiccmd(tails, cmd, forward, backward, left, right, strafeleft, straferight, jump, spin);
} else
B_KeysToTiccmd(tails, cmd, lua_toboolean(gL, 2+1), lua_toboolean(gL, 2+2), lua_toboolean(gL, 2+3), lua_toboolean(gL, 2+4), lua_toboolean(gL, 2+5), lua_toboolean(gL, 2+6), lua_toboolean(gL, 2+7), lua_toboolean(gL, 2+8));
B_KeysToTiccmd(tails, cmd, forward, backward, left, right, strafeleft, straferight, jump, spin);
} else
B_KeysToTiccmd(tails, cmd, lua_toboolean(gL, 1), lua_toboolean(gL, 2), lua_toboolean(gL, 3), lua_toboolean(gL, 4), lua_toboolean(gL, 5), lua_toboolean(gL, 6), lua_toboolean(gL, 7), lua_toboolean(gL, 8));
lua_pop(gL, 8);
hooked = true;
}
lua_pop(gL, -1);
lua_gc(gL, LUA_GCSTEP, 1);
return true;
lua_settop(gL, 0);
return hooked;
}
// Hook for linedef executors
boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_LinedefExecute/8] & (1<<(hook_LinedefExecute%8))))
return false;
// clear the stack
lua_pop(gL, -1);
// get hook table
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_LinedefExecute);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
return 0;
// get function by line text
lua_getfield(gL, 1, line->text);
if (lua_isnil(gL, -1)) {
lua_pop(gL, 2);
return false;
}
lua_remove(gL, 1); // pop hook table off the stack
lua_settop(gL, 0);
LUA_PushUserdata(gL, line, META_LINE);
LUA_PushUserdata(gL, mo, META_MOBJ);
LUA_PushUserdata(gL, sector, META_SECTOR);
LUA_Call(gL, 3); // pops hook function, line, mo, sector
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_LinedefExecute
&& !strcmp(hookp->s.funcname, line->text))
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, line, META_LINE);
LUA_PushUserdata(gL, mo, META_MOBJ);
LUA_PushUserdata(gL, sector, META_SECTOR);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
LUA_Call(gL, 3);
hooked = true;
}
lua_pop(gL, -1);
lua_gc(gL, LUA_GCSTEP, 1);
return true;
lua_settop(gL, 0);
return hooked;
}
// Hook for PlayerMsg -Red
// Hook for player chat
boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg)
{
boolean handled = false;
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_PlayerMsg/8] & (1<<(hook_PlayerMsg%8))))
return false;
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_PlayerMsg);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player
if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c
lua_pushinteger(gL, 3); // type
lua_pushnil(gL); // target
} else if (target == -1) { // sayteam
lua_pushinteger(gL, 1); // type
lua_pushnil(gL); // target
} else if (target == 0) { // say
lua_pushinteger(gL, 0); // type
lua_pushnil(gL); // target
} else { // sayto
lua_pushinteger(gL, 2); // type
LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target
}
lua_settop(gL, 0);
lua_pushstring(gL, msg); // msg
lua_pushnil(gL);
while (lua_next(gL, -6)) {
lua_pushvalue(gL, -6); // source
lua_pushvalue(gL, -6); // type
lua_pushvalue(gL, -6); // target
lua_pushvalue(gL, -6); // msg
if (lua_pcall(gL, 4, 1, 0)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_PlayerMsg)
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player
if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c
lua_pushinteger(gL, 3); // type
lua_pushnil(gL); // target
} else if (target == -1) { // sayteam
lua_pushinteger(gL, 1); // type
lua_pushnil(gL); // target
} else if (target == 0) { // say
lua_pushinteger(gL, 0); // type
lua_pushnil(gL); // target
} else { // sayto
lua_pushinteger(gL, 2); // type
LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target
}
lua_pushstring(gL, msg); // msg
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -5);
lua_pushvalue(gL, -5);
lua_pushvalue(gL, -5);
lua_pushvalue(gL, -5);
if (lua_pcall(gL, 4, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
continue;
}
if (lua_toboolean(gL, -1))
handled = true;
lua_pop(gL, 1); // pop return value
}
lua_pop(gL, 4); // pop arguments and mobjtype table
lua_gc(gL, LUA_GCSTEP, 1);
return handled;
lua_settop(gL, 0);
return hooked;
}
// Hook for hurt messages -Red
// The internal name is DeathMsg, but the API name is "HurtMsg". Keep that in mind. (Should this be fixed at some point?)
// @TODO This hook should be fixed to take mobj type at the addHook parameter to compare to inflictor. (I couldn't get this to work without crashing)
boolean LUAh_DeathMsg(player_t *player, mobj_t *inflictor, mobj_t *source)
// Hook for hurt messages
boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source)
{
boolean handled = false;
if (!gL || !(hooksAvailable[hook_DeathMsg/8] & (1<<(hook_DeathMsg%8))))
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_HurtMsg/8] & (1<<(hook_HurtMsg%8))))
return false;
lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, hook_DeathMsg);
lua_remove(gL, -2);
I_Assert(lua_istable(gL, -1));
LUA_PushUserdata(gL, player, META_PLAYER); // Player
LUA_PushUserdata(gL, inflictor, META_MOBJ); // Inflictor
LUA_PushUserdata(gL, source, META_MOBJ); // Source
lua_pushnil(gL);
lua_settop(gL, 0);
while (lua_next(gL, -5)) {
lua_pushvalue(gL, -5); // player
lua_pushvalue(gL, -5); // inflictor
lua_pushvalue(gL, -5); // source
if (lua_pcall(gL, 3, 1, 0)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_HurtMsg
&& (hookp->s.mt == MT_NULL || (inflictor && hookp->s.mt == inflictor->type)))
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
if (lua_pcall(gL, 3, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
continue;
}
if (lua_toboolean(gL, -1))
handled = true;
lua_pop(gL, 1); // pop return value
}
lua_pop(gL, 3); // pop arguments and mobjtype table
lua_gc(gL, LUA_GCSTEP, 1);
return handled;
lua_settop(gL, 0);
return hooked;
}
#endif