Merge branch 'master' of http://git.magicalgirl.moe/STJr/SRB2Internal.git into skin_patch

This commit is contained in:
toasterbabe 2017-03-27 15:57:50 +01:00
commit b73b38c326
38 changed files with 1819 additions and 630 deletions

View File

@ -47,7 +47,7 @@ before_build:
- upx -V - upx -V
- ccache -V - ccache -V
- ccache -s - ccache -s
- set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 GCC53=1 CCACHE=1 - set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 GCC63=1 CCACHE=1
build_script: build_script:
- cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 clean - cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 clean

View File

@ -7,6 +7,23 @@
# and other things # and other things
# #
ifdef GCC63
GCC62=1
endif
ifdef GCC62
GCC61=1
endif
ifdef GCC61
GCC54=1
endif
ifdef GCC54
GCC53=1
endif
ifdef GCC53 ifdef GCC53
GCC52=1 GCC52=1
endif endif
@ -164,19 +181,29 @@ ifdef GCC45
WFLAGS+=-Wunsuffixed-float-constants WFLAGS+=-Wunsuffixed-float-constants
endif endif
endif endif
ifdef NOLDWARNING ifdef NOLDWARNING
LDFLAGS+=-Wl,--as-needed LDFLAGS+=-Wl,--as-needed
endif endif
ifdef ERRORMODE ifdef ERRORMODE
WFLAGS+=-Werror WFLAGS+=-Werror
endif endif
WFLAGS+=$(OLDWFLAGS)
ifdef GCC43 ifdef GCC43
#WFLAGS+=-Wno-error=clobbered #WFLAGS+=-Wno-error=clobbered
endif endif
ifdef GCC46 ifdef GCC46
WFLAGS+=-Wno-error=suggest-attribute=noreturn WFLAGS+=-Wno-error=suggest-attribute=noreturn
endif endif
WFLAGS+=$(OLDWFLAGS) ifdef GCC54
WFLAGS+=-Wno-logical-op -Wno-error=logical-op
endif
ifdef GCC61
WFLAGS+=-Wno-tautological-compare -Wno-error=tautological-compare
endif
#indicate platform and what interface use with #indicate platform and what interface use with

View File

@ -187,7 +187,7 @@ UINT8 altdown = 0; // 0x1 left, 0x2 right
// //
static inline void D_ModifierKeyResponder(event_t *ev) static inline void D_ModifierKeyResponder(event_t *ev)
{ {
if (ev->type == ev_keydown) switch (ev->data1) if (ev->type == ev_keydown || ev->type == ev_console) switch (ev->data1)
{ {
case KEY_LSHIFT: shiftdown |= 0x1; return; case KEY_LSHIFT: shiftdown |= 0x1; return;
case KEY_RSHIFT: shiftdown |= 0x2; return; case KEY_RSHIFT: shiftdown |= 0x2; return;

View File

@ -991,12 +991,14 @@ void Command_Droprate(void)
packetdroprate = droprate; packetdroprate = droprate;
} }
#ifndef NONET
static boolean ShouldDropPacket(void) static boolean ShouldDropPacket(void)
{ {
return (packetdropquantity[netbuffer->packettype]) return (packetdropquantity[netbuffer->packettype])
|| (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100; || (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100;
} }
#endif #endif
#endif
// //
// HSendPacket // HSendPacket

View File

@ -1802,6 +1802,7 @@ static actionpointer_t actionpointers[] =
{{A_FlickyCheck}, "A_FLICKYCHECK"}, {{A_FlickyCheck}, "A_FLICKYCHECK"},
{{A_FlickyHeightCheck}, "A_FLICKYHEIGHTCHECK"}, {{A_FlickyHeightCheck}, "A_FLICKYHEIGHTCHECK"},
{{A_FlickyFlutter}, "A_FLICKYFLUTTER"}, {{A_FlickyFlutter}, "A_FLICKYFLUTTER"},
{{A_FlameParticle}, "A_FLAMEPARTICLE"},
{{NULL}, "NONE"}, {{NULL}, "NONE"},
@ -2691,7 +2692,7 @@ static void readpatch(MYFILE *f, const char *name, UINT16 wad)
char *word2; char *word2;
char *tmp; char *tmp;
INT32 i = 0, j = 0, value; INT32 i = 0, j = 0, value;
texpatch_t patch = {0, 0, UINT16_MAX, UINT16_MAX, 0}; texpatch_t patch = {0, 0, UINT16_MAX, UINT16_MAX, 0, 255, AST_COPY};
// Jump to the texture this patch belongs to, which, // Jump to the texture this patch belongs to, which,
// coincidentally, is always the last one on the buffer cache. // coincidentally, is always the last one on the buffer cache.
@ -4078,6 +4079,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_GOOP1", "S_GOOP1",
"S_GOOP2", "S_GOOP2",
"S_GOOP3", "S_GOOP3",
"S_GOOPTRAIL",
// Boss 3 // Boss 3
"S_EGGMOBILE3_STND", "S_EGGMOBILE3_STND",
@ -4450,11 +4452,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_METALSONIC_FLOAT", "S_METALSONIC_FLOAT",
"S_METALSONIC_VECTOR", "S_METALSONIC_VECTOR",
"S_METALSONIC_STUN", "S_METALSONIC_STUN",
"S_METALSONIC_BLOCK",
"S_METALSONIC_RAISE", "S_METALSONIC_RAISE",
"S_METALSONIC_GATHER", "S_METALSONIC_GATHER",
"S_METALSONIC_DASH", "S_METALSONIC_DASH",
"S_METALSONIC_BOUNCE", "S_METALSONIC_BOUNCE",
"S_METALSONIC_BADBOUNCE",
"S_METALSONIC_SHOOT", "S_METALSONIC_SHOOT",
"S_METALSONIC_PAIN", "S_METALSONIC_PAIN",
"S_METALSONIC_DEATH", "S_METALSONIC_DEATH",
@ -4654,7 +4656,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Starpost // Starpost
"S_STARPOST_IDLE", "S_STARPOST_IDLE",
"S_STARPOST_FLASH", "S_STARPOST_FLASH",
"S_STARPOST_STARTSPIN",
"S_STARPOST_SPIN", "S_STARPOST_SPIN",
"S_STARPOST_ENDSPIN",
// Big floating mine // Big floating mine
"S_BIGMINE1", "S_BIGMINE1",
@ -4836,21 +4840,15 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_DEMONFIRE6", "S_DEMONFIRE6",
"S_GFZFLOWERA", "S_GFZFLOWERA",
"S_GFZFLOWERA2", "S_GFZFLOWERB",
"S_GFZFLOWERC",
"S_GFZFLOWERB1",
"S_GFZFLOWERB2",
"S_GFZFLOWERC1",
"S_BERRYBUSH", "S_BERRYBUSH",
"S_BUSH", "S_BUSH",
// THZ Plant // THZ Plant
"S_THZPLANT1", "S_THZFLOWERA",
"S_THZPLANT2", "S_THZFLOWERB",
"S_THZPLANT3",
"S_THZPLANT4",
// THZ Alarm // THZ Alarm
"S_ALARM1", "S_ALARM1",
@ -4895,6 +4893,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLAME2", "S_FLAME2",
"S_FLAME3", "S_FLAME3",
"S_FLAME4", "S_FLAME4",
"S_FLAME5",
"S_FLAME6",
"S_FLAMEPARTICLE",
"S_FLAMEREST",
// Eggman Statue // Eggman Statue
"S_EGGSTATUE1", "S_EGGSTATUE1",
@ -4956,36 +4959,13 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Spinning flame jets // Spinning flame jets
"S_FJSPINAXISA1", // Counter-clockwise "S_FJSPINAXISA1", // Counter-clockwise
"S_FJSPINAXISA2", "S_FJSPINAXISA2",
"S_FJSPINAXISA3",
"S_FJSPINAXISA4",
"S_FJSPINAXISA5",
"S_FJSPINAXISA6",
"S_FJSPINAXISA7",
"S_FJSPINAXISA8",
"S_FJSPINAXISA9",
"S_FJSPINHELPERA1",
"S_FJSPINHELPERA2",
"S_FJSPINHELPERA3",
"S_FJSPINAXISB1", // Clockwise "S_FJSPINAXISB1", // Clockwise
"S_FJSPINAXISB2", "S_FJSPINAXISB2",
"S_FJSPINAXISB3",
"S_FJSPINAXISB4",
"S_FJSPINAXISB5",
"S_FJSPINAXISB6",
"S_FJSPINAXISB7",
"S_FJSPINAXISB8",
"S_FJSPINAXISB9",
"S_FJSPINHELPERB1",
"S_FJSPINHELPERB2",
"S_FJSPINHELPERB3",
// Blade's flame // Blade's flame
"S_FLAMEJETFLAMEB1", "S_FLAMEJETFLAMEB1",
"S_FLAMEJETFLAMEB2", "S_FLAMEJETFLAMEB2",
"S_FLAMEJETFLAMEB3", "S_FLAMEJETFLAMEB3",
"S_FLAMEJETFLAMEB4",
"S_FLAMEJETFLAMEB5",
"S_FLAMEJETFLAMEB6",
// Trapgoyles // Trapgoyles
"S_TRAPGOYLE", "S_TRAPGOYLE",
@ -5080,8 +5060,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_BSZVINE_ORANGE", "S_BSZVINE_ORANGE",
"S_BSZSHRUB", "S_BSZSHRUB",
"S_BSZCLOVER", "S_BSZCLOVER",
"S_BSZFISH", "S_BIG_PALMTREE_TRUNK",
"S_BSZSUNFLOWER", "S_BIG_PALMTREE_TOP",
"S_PALMTREE_TRUNK",
"S_PALMTREE_TOP",
"S_DBALL1", "S_DBALL1",
"S_DBALL2", "S_DBALL2",
@ -5800,20 +5782,19 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FIREBALLEXP2", "S_FIREBALLEXP2",
"S_FIREBALLEXP3", "S_FIREBALLEXP3",
"S_SHELL", "S_SHELL",
"S_SHELL1", "S_PUMA_START1",
"S_SHELL2", "S_PUMA_START2",
"S_SHELL3", "S_PUMA_UP1",
"S_SHELL4", "S_PUMA_UP2",
"S_PUMA1", "S_PUMA_UP3",
"S_PUMA2", "S_PUMA_DOWN1",
"S_PUMA3", "S_PUMA_DOWN2",
"S_PUMA4", "S_PUMA_DOWN3",
"S_PUMA5", "S_PUMATRAIL1",
"S_PUMA6", "S_PUMATRAIL2",
"S_HAMMER1", "S_PUMATRAIL3",
"S_HAMMER2", "S_PUMATRAIL4",
"S_HAMMER3", "S_HAMMER",
"S_HAMMER4",
"S_KOOPA1", "S_KOOPA1",
"S_KOOPA2", "S_KOOPA2",
"S_KOOPAFLAME1", "S_KOOPAFLAME1",
@ -6066,6 +6047,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_BOSSTANK2", "MT_BOSSTANK2",
"MT_BOSSSPIGOT", "MT_BOSSSPIGOT",
"MT_GOOP", "MT_GOOP",
"MT_GOOPTRAIL",
// Boss 3 // Boss 3
"MT_EGGMOBILE3", "MT_EGGMOBILE3",
@ -6235,7 +6217,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_BUSH", "MT_BUSH",
// Techno Hill Scenery // Techno Hill Scenery
"MT_THZPLANT", // THZ Plant "MT_THZFLOWER1",
"MT_THZFLOWER2",
"MT_ALARM", "MT_ALARM",
// Deep Sea Scenery // Deep Sea Scenery
@ -6251,6 +6234,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
// Castle Eggman Scenery // Castle Eggman Scenery
"MT_CHAIN", // CEZ Chain "MT_CHAIN", // CEZ Chain
"MT_FLAME", // Flame (has corona) "MT_FLAME", // Flame (has corona)
"MT_FLAMEPARTICLE",
"MT_EGGSTATUE", // Eggman Statue "MT_EGGSTATUE", // Eggman Statue
"MT_MACEPOINT", // Mace rotation point "MT_MACEPOINT", // Mace rotation point
"MT_SWINGMACEPOINT", // Mace swinging point "MT_SWINGMACEPOINT", // Mace swinging point
@ -6277,9 +6261,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_FLAMEJETFLAME", "MT_FLAMEJETFLAME",
"MT_FJSPINAXISA", // Counter-clockwise "MT_FJSPINAXISA", // Counter-clockwise
"MT_FJSPINHELPERA",
"MT_FJSPINAXISB", // Clockwise "MT_FJSPINAXISB", // Clockwise
"MT_FJSPINHELPERB",
"MT_FLAMEJETFLAMEB", // Blade's flame "MT_FLAMEJETFLAMEB", // Blade's flame
@ -6356,8 +6338,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_BSZVINE_ORANGE", "MT_BSZVINE_ORANGE",
"MT_BSZSHRUB", "MT_BSZSHRUB",
"MT_BSZCLOVER", "MT_BSZCLOVER",
"MT_BSZFISH", "MT_BIG_PALMTREE_TRUNK",
"MT_BSZSUNFLOWER", "MT_BIG_PALMTREE_TOP",
"MT_PALMTREE_TRUNK",
"MT_PALMTREE_TOP",
// Misc scenery // Misc scenery
"MT_DBALL", "MT_DBALL",
@ -6463,6 +6447,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_FIREBALL", "MT_FIREBALL",
"MT_SHELL", "MT_SHELL",
"MT_PUMA", "MT_PUMA",
"MT_PUMATRAIL",
"MT_HAMMER", "MT_HAMMER",
"MT_KOOPA", "MT_KOOPA",
"MT_KOOPAFLAME", "MT_KOOPAFLAME",

View File

@ -2901,7 +2901,7 @@ static void G_DoCompleted(void)
if (nextmap < NUMMAPS && !mapheaderinfo[nextmap]) if (nextmap < NUMMAPS && !mapheaderinfo[nextmap])
P_AllocMapHeader(nextmap); P_AllocMapHeader(nextmap);
if (skipstats) if (skipstats && !modeattacking) // Don't skip stats if we're in record attack
G_AfterIntermission(); G_AfterIntermission();
else else
{ {

View File

@ -296,6 +296,7 @@ light_t *t_lspr[NUMSPRITES] =
// Techno Hill Scenery // Techno Hill Scenery
&lspr[NOLIGHT], // SPR_THZP &lspr[NOLIGHT], // SPR_THZP
&lspr[NOLIGHT], // SPR_FWR5
&lspr[REDBALL_L], // SPR_ALRM &lspr[REDBALL_L], // SPR_ALRM
// Deep Sea Scenery // Deep Sea Scenery

View File

@ -1836,7 +1836,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value)
} }
} }
static inline void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration, UINT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color) static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration, UINT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color)
{ {
INT32 val, count, pindex; INT32 val, count, pindex;
GLfloat s, t; GLfloat s, t;

View File

@ -198,21 +198,6 @@ void HU_LoadGraphics(void)
tny_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX); tny_font[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
} }
// cache the level title font for entire game execution
lt_font[0] = (patch_t *)W_CachePatchName("LTFNT039", PU_HUDGFX); /// \note fake start hack
// Number support
lt_font[9] = (patch_t *)W_CachePatchName("LTFNT048", PU_HUDGFX);
lt_font[10] = (patch_t *)W_CachePatchName("LTFNT049", PU_HUDGFX);
lt_font[11] = (patch_t *)W_CachePatchName("LTFNT050", PU_HUDGFX);
lt_font[12] = (patch_t *)W_CachePatchName("LTFNT051", PU_HUDGFX);
lt_font[13] = (patch_t *)W_CachePatchName("LTFNT052", PU_HUDGFX);
lt_font[14] = (patch_t *)W_CachePatchName("LTFNT053", PU_HUDGFX);
lt_font[15] = (patch_t *)W_CachePatchName("LTFNT054", PU_HUDGFX);
lt_font[16] = (patch_t *)W_CachePatchName("LTFNT055", PU_HUDGFX);
lt_font[17] = (patch_t *)W_CachePatchName("LTFNT056", PU_HUDGFX);
lt_font[18] = (patch_t *)W_CachePatchName("LTFNT057", PU_HUDGFX);
j = LT_FONTSTART; j = LT_FONTSTART;
for (i = 0; i < LT_FONTSIZE; i++) for (i = 0; i < LT_FONTSIZE; i++)
{ {

View File

@ -184,6 +184,7 @@ char sprnames[NUMSPRITES + 1][5] =
// Techno Hill Scenery // Techno Hill Scenery
"THZP", // Techno Hill Zone Plant "THZP", // Techno Hill Zone Plant
"FWR5", // Another one
"ALRM", // THZ2 Alarm "ALRM", // THZ2 Alarm
// Deep Sea Scenery // Deep Sea Scenery
@ -990,9 +991,10 @@ state_t states[NUMSTATES] =
{SPR_SPNK, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSPIGOT {SPR_SPNK, 0, 35, {NULL}, 0, 0, S_NULL}, // S_BOSSSPIGOT
// Boss 2 Goop // Boss 2 Goop
{SPR_GOOP, 0, 2, {NULL}, 0, 0, S_GOOP2}, // S_GOOP1 {SPR_GOOP, 0, 2, {A_SpawnObjectRelative}, 0, MT_GOOPTRAIL, S_GOOP2}, // S_GOOP1
{SPR_GOOP, 1, 2, {NULL}, 0, 0, S_GOOP1}, // S_GOOP2 {SPR_GOOP, 1, 2, {A_SpawnObjectRelative}, 0, MT_GOOPTRAIL, S_GOOP1}, // S_GOOP2
{SPR_GOOP, 2,-1, {NULL}, 0, 0, S_NULL}, // S_GOOP3 {SPR_GOOP, 2, -1, {NULL}, 0, 0, S_NULL}, // S_GOOP3
{SPR_GOOP, FF_ANIMATE|3, 11, {NULL}, 2, 6, S_NULL}, // S_GOOPTRAIL
// Boss 3 // Boss 3
{SPR_EGGO, 0, 1, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_STND {SPR_EGGO, 0, 1, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_STND
@ -1244,12 +1246,12 @@ state_t states[NUMSTATES] =
{SPR_RCKT, 2 + FF_FULLBRIGHT, 6, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_FLAMES + (6<<16), 32 + (16<<16), S_CYBRAKDEMONMISSILE_EXPLODE3}, // S_CYBRAKDEMONMISSILE_EXPLODE2 {SPR_RCKT, 2 + FF_FULLBRIGHT, 6, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_FLAMES + (6<<16), 32 + (16<<16), S_CYBRAKDEMONMISSILE_EXPLODE3}, // S_CYBRAKDEMONMISSILE_EXPLODE2
{SPR_RCKT, 3 + FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_NULL}, // S_CYBRAKDEMONMISSILE_EXPLODE3 {SPR_RCKT, 3 + FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_NULL}, // S_CYBRAKDEMONMISSILE_EXPLODE3
{SPR_FLME, FF_TRANS50|FF_FULLBRIGHT , 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY2}, // S_CYBRAKDEMONFLAMESHOT_FLY1 {SPR_FLME, FF_TRANS20|FF_FULLBRIGHT , 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY2}, // S_CYBRAKDEMONFLAMESHOT_FLY1
{SPR_FLME, FF_TRANS50|FF_FULLBRIGHT|1, 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY2 {SPR_FLME, FF_TRANS20|FF_FULLBRIGHT|1, 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY2
{SPR_FLME, FF_TRANS50|FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY3 {SPR_FLME, FF_TRANS20|FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY3
{SPR_FLME, FF_TRANS50|FF_FULLBRIGHT|2, 0, {A_SpawnObjectRelative}, 0, MT_CYBRAKDEMON_FLAMEREST, S_NULL}, // S_CYBRAKDEMONFLAMESHOT_DIE {SPR_FLME, FF_TRANS20|FF_FULLBRIGHT|2, 0, {A_SpawnObjectRelative}, 0, MT_CYBRAKDEMON_FLAMEREST, S_NULL}, // S_CYBRAKDEMONFLAMESHOT_DIE
{SPR_FLAM, FF_TRANS50|FF_FULLBRIGHT|3, 3, {A_SetFuse}, 10*TICRATE, 0, S_FLAME1}, // S_CYBRAKDEMONFLAMEREST {SPR_FLAM, FF_TRANS20|FF_FULLBRIGHT|5, 3, {A_SetFuse}, 10*TICRATE, 0, S_FLAMEREST}, // S_CYBRAKDEMONFLAMEREST
{SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_INIT2}, // S_CYBRAKDEMONELECTRICBARRIER_INIT1 {SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_INIT2}, // S_CYBRAKDEMONELECTRICBARRIER_INIT1
{SPR_ELEC, 0 + FF_FULLBRIGHT, 0, {A_RemoteAction}, -1, S_CYBRAKDEMON_INVINCIBLERIZE, S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND}, // S_CYBRAKDEMONELECTRICBARRIER_INIT2 {SPR_ELEC, 0 + FF_FULLBRIGHT, 0, {A_RemoteAction}, -1, S_CYBRAKDEMON_INVINCIBLERIZE, S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND}, // S_CYBRAKDEMONELECTRICBARRIER_INIT2
@ -1367,14 +1369,14 @@ state_t states[NUMSTATES] =
{SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT {SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT
{SPR_METL, 12, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR {SPR_METL, 12, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR
{SPR_METL, 0, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN {SPR_METL, 0, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN
{SPR_METL, 13, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BLOCK
{SPR_METL, 13, 40, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE {SPR_METL, 13, 40, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE
{SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER
{SPR_METL, 9, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH
{SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE
{SPR_METL, 16, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE
{SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT {SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT
{SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN {SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN
{SPR_METL, 0, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH {SPR_METL, 11, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH
{SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 {SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1
{SPR_METL, 4, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2 {SPR_METL, 4, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2
{SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3 {SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3
@ -1570,9 +1572,11 @@ state_t states[NUMSTATES] =
{SPR_USPK, 2,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2 {SPR_USPK, 2,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2
// Starpost // Starpost
{SPR_STPT, 0 , -1, {NULL}, 0, 0, S_NULL}, // S_STARPOST_IDLE {SPR_STPT, 0 , -1, {NULL}, 0, 0, S_NULL}, // S_STARPOST_IDLE
{SPR_STPT, FF_ANIMATE , -1, {NULL}, 1, 2, S_NULL}, // S_STARPOST_FLASH {SPR_STPT, FF_ANIMATE|17, -1, {NULL}, 5, 1, S_NULL}, // S_STARPOST_FLASH
{SPR_STPT, FF_ANIMATE|2, 31, {NULL}, 15, 1, S_STARPOST_FLASH}, // S_STARPOST_SPIN {SPR_STPT, FF_ANIMATE|13, 2, {NULL}, 1, 1, S_STARPOST_SPIN}, // S_STARPOST_STARTSPIN
{SPR_STPT, FF_ANIMATE|1 , 23, {NULL}, 11, 1, S_STARPOST_ENDSPIN}, // S_STARPOST_SPIN
{SPR_STPT, FF_ANIMATE|15, 2, {NULL}, 1, 1, S_STARPOST_FLASH}, // S_STARPOST_ENDSPIN
// Big floating mine // Big floating mine
{SPR_BMNE, 0, 5, {NULL}, 0, 0, S_BIGMINE2}, // S_BIGMINE1 {SPR_BMNE, 0, 5, {NULL}, 0, 0, S_BIGMINE2}, // S_BIGMINE1
@ -1753,21 +1757,15 @@ state_t states[NUMSTATES] =
{SPR_CFIR, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_DEMONFIRE1}, // S_DEMONFIRE6 {SPR_CFIR, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_DEMONFIRE1}, // S_DEMONFIRE6
// GFZ Flower // GFZ Flower
{SPR_FWR1, 0, 14, {NULL}, 0, 0, S_GFZFLOWERA2}, // S_GFZFLOWERA {SPR_FWR1, FF_ANIMATE, -1, {NULL}, 7, 3, S_NULL}, // S_GFZFLOWERA
{SPR_FWR1, 1, 14, {NULL}, 0, 0, S_GFZFLOWERA}, // S_GFZFLOWERA2 {SPR_FWR2, FF_ANIMATE, -1, {NULL}, 19, 3, S_NULL}, // S_GFZFLOWERB
{SPR_FWR3, FF_ANIMATE, -1, {NULL}, 11, 4, S_NULL}, // S_GFZFLOWERC
{SPR_FWR2, 0, 7, {NULL}, 0, 0, S_GFZFLOWERB2}, // S_GFZFLOWERB1
{SPR_FWR2, 1, 7, {NULL}, 0, 0, S_GFZFLOWERB1}, // S_GFZFLOWERB1
{SPR_FWR3, 0, -1, {NULL}, 0, 0, S_NULL}, // S_GFZFLOWERC1
{SPR_BUS1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BERRYBUSH {SPR_BUS1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BERRYBUSH
{SPR_BUS2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUSH {SPR_BUS2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUSH
{SPR_THZP, 0, 4, {NULL}, 0, 0, S_THZPLANT2}, // S_THZPLANT1 {SPR_THZP, FF_ANIMATE, -1, {NULL}, 7, 4, S_NULL}, // S_THZFLOWERA
{SPR_THZP, 1, 4, {NULL}, 0, 0, S_THZPLANT3}, // S_THZPLANT1 {SPR_FWR5, FF_ANIMATE, -1, {NULL}, 19, 2, S_NULL}, // S_THZFLOWERB
{SPR_THZP, 2, 4, {NULL}, 0, 0, S_THZPLANT4}, // S_THZPLANT1
{SPR_THZP, 3, 4, {NULL}, 0, 0, S_THZPLANT1}, // S_THZPLANT1
// THZ Alarm // THZ Alarm
{SPR_ALRM, FF_FULLBRIGHT, 35, {A_Scream}, 0, 0, S_ALARM1}, // S_ALARM1 {SPR_ALRM, FF_FULLBRIGHT, 35, {A_Scream}, 0, 0, S_ALARM1}, // S_ALARM1
@ -1808,10 +1806,15 @@ state_t states[NUMSTATES] =
{SPR_CHAN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZCHAIN {SPR_CHAN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZCHAIN
// Flame // Flame
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS50, 3, {NULL}, 0, 0, S_FLAME2}, // S_FLAME1 {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20, 3, {A_FlameParticle}, 3, 0, S_FLAME2}, // S_FLAME1
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS50|1, 3, {NULL}, 0, 0, S_FLAME3}, // S_FLAME2 {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|1, 3, {NULL}, 0, 0, S_FLAME3}, // S_FLAME2
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS50|2, 3, {NULL}, 0, 0, S_FLAME4}, // S_FLAME3 {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|2, 3, {A_FlameParticle}, 3, 0, S_FLAME4}, // S_FLAME3
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS50|3, 3, {NULL}, 0, 0, S_FLAME1}, // S_FLAME4 {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|3, 3, {NULL}, 0, 0, S_FLAME5}, // S_FLAME4
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|4, 3, {A_FlameParticle}, 3, 0, S_FLAME6}, // S_FLAME5
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|5, 3, {NULL}, 0, 0, S_FLAME1}, // S_FLAME6
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS10|6, 24, {NULL}, 0, 0, S_NULL}, // S_FLAMEPARTICLE
{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|FF_ANIMATE, -1, {NULL}, 5, 3, S_FLAME2}, // S_FLAMEREST
// Eggman statue // Eggman statue
{SPR_ESTA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGSTATUE1 {SPR_ESTA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGSTATUE1
@ -1867,48 +1870,23 @@ state_t states[NUMSTATES] =
{SPR_NULL, 0, 2*TICRATE, {NULL}, 0, 0, S_FLAMEJETSTART}, // S_FLAMEJETSTND {SPR_NULL, 0, 2*TICRATE, {NULL}, 0, 0, S_FLAMEJETSTART}, // S_FLAMEJETSTND
{SPR_NULL, 0, 3*TICRATE, {A_ToggleFlameJet}, 0, 0, S_FLAMEJETSTOP}, // S_FLAMEJETSTART {SPR_NULL, 0, 3*TICRATE, {A_ToggleFlameJet}, 0, 0, S_FLAMEJETSTOP}, // S_FLAMEJETSTART
{SPR_NULL, 0, 1, {A_ToggleFlameJet}, 0, 0, S_FLAMEJETSTND}, // S_FLAMEJETSTOP {SPR_NULL, 0, 1, {A_ToggleFlameJet}, 0, 0, S_FLAMEJETSTND}, // S_FLAMEJETSTOP
{SPR_FLME, FF_TRANS50 , 4, {NULL}, 0, 0, S_FLAMEJETFLAME2}, // S_FLAMEJETFLAME1 {SPR_FLME, FF_FULLBRIGHT|FF_TRANS50 , 4, {NULL}, 0, 0, S_FLAMEJETFLAME2}, // S_FLAMEJETFLAME1
{SPR_FLME, FF_TRANS60|1, 5, {NULL}, 0, 0, S_FLAMEJETFLAME3}, // S_FLAMEJETFLAME2 {SPR_FLME, FF_FULLBRIGHT|FF_TRANS60|1, 5, {NULL}, 0, 0, S_FLAMEJETFLAME3}, // S_FLAMEJETFLAME2
{SPR_FLME, FF_TRANS70|2, 11, {NULL}, 0, 0, S_NULL}, // S_FLAMEJETFLAME3 {SPR_FLME, FF_FULLBRIGHT|FF_TRANS70|2, 11, {NULL}, 0, 0, S_NULL}, // S_FLAMEJETFLAME3
// Spinning flame jets // Spinning flame jets
// A: Counter-clockwise // A: Counter-clockwise
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_FJSPINAXISA2}, // S_FJSPINAXISA1 {SPR_NULL, 0, 1, {A_TrapShot}, MT_FLAMEJETFLAMEB, -(16<<16)|(1<<15)|64, S_FJSPINAXISA2}, // S_FJSPINAXISA1
{SPR_NULL, 0, 1, {A_Thrust}, 10, 1, S_FJSPINAXISA3}, // S_FJSPINAXISA2 {SPR_NULL, 0, 2, {A_ChangeAngleRelative}, 6, 6, S_FJSPINAXISA1}, // S_FJSPINAXISA2
{SPR_NULL, 0, 0, {A_Thrust}, 0, 1, S_FJSPINAXISA4}, // S_FJSPINAXISA3
{SPR_NULL, 0, 0, {A_SpawnObjectRelative}, 0, MT_FJSPINHELPERA, S_FJSPINAXISA5}, // S_FJSPINAXISA4
{SPR_NULL, 0, 2, {A_FindTarget}, MT_FJSPINHELPERA, 0, S_FJSPINAXISA6}, // S_FJSPINAXISA5
{SPR_NULL, 0, 1, {A_Thrust}, -10, 1, S_FJSPINAXISA7}, // S_FJSPINAXISA6
{SPR_NULL, 0, 1, {A_Thrust}, 0, 1, S_FJSPINAXISA8}, // S_FJSPINAXISA7
{SPR_NULL, 0, 0, {A_FireShot}, MT_FLAMEJETFLAMEB, -64, S_FJSPINAXISA9}, // S_FJSPINAXISA8
{SPR_NULL, 0, 3, {A_ChangeAngleRelative}, 6, 6, S_FJSPINAXISA8}, // S_FJSPINAXISA9
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_FJSPINHELPERA2}, // S_FJSPINHELPERA1
{SPR_NULL, 0, 0, {A_FindTarget}, MT_FJSPINAXISA, 0, S_FJSPINHELPERA3}, // S_FJSPINHELPERA2
{SPR_NULL, 0, 1, {A_CapeChase}, 0, (64<<16), S_FJSPINHELPERA3}, // S_FJSPINHELPERA3
// B: Clockwise // B: Clockwise
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_FJSPINAXISB2}, // S_FJSPINAXISB1 {SPR_NULL, 0, 1, {A_TrapShot}, MT_FLAMEJETFLAMEB, -(16<<16)|(1<<15)|64, S_FJSPINAXISB2}, // S_FJSPINAXISB1
{SPR_NULL, 0, 1, {A_Thrust}, 10, 1, S_FJSPINAXISB3}, // S_FJSPINAXISB2 {SPR_NULL, 0, 2, {A_ChangeAngleRelative}, -6, -6, S_FJSPINAXISB1}, // S_FJSPINAXISB2
{SPR_NULL, 0, 0, {A_Thrust}, 0, 1, S_FJSPINAXISB4}, // S_FJSPINAXISB3
{SPR_NULL, 0, 0, {A_SpawnObjectRelative}, 0, MT_FJSPINHELPERB, S_FJSPINAXISB5}, // S_FJSPINAXISB4
{SPR_NULL, 0, 2, {A_FindTarget}, MT_FJSPINHELPERB, 0, S_FJSPINAXISB6}, // S_FJSPINAXISB5
{SPR_NULL, 0, 1, {A_Thrust}, -10, 1, S_FJSPINAXISB7}, // S_FJSPINAXISB6
{SPR_NULL, 0, 1, {A_Thrust}, 0, 1, S_FJSPINAXISB8}, // S_FJSPINAXISB7
{SPR_NULL, 0, 0, {A_FireShot}, MT_FLAMEJETFLAMEB, -64, S_FJSPINAXISB9}, // S_FJSPINAXISB8
{SPR_NULL, 0, 3, {A_ChangeAngleRelative}, -6, -6, S_FJSPINAXISB8}, // S_FJSPINAXISB9
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_FJSPINHELPERB2}, // S_FJSPINHELPERB1
{SPR_NULL, 0, 0, {A_FindTarget}, MT_FJSPINAXISB, 0, S_FJSPINHELPERB3}, // S_FJSPINHELPERB2
{SPR_NULL, 0, 1, {A_CapeChase}, 0, (64<<16), S_FJSPINHELPERB3}, // S_FJSPINHELPERB3
// Blade's flame // Blade's flame
{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|1, 1, {A_MoveRelative}, 0, 5, S_FLAMEJETFLAMEB2}, // S_FLAMEJETFLAMEB1 {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40, 1, {A_MoveRelative}, 0, 5, S_FLAMEJETFLAMEB2}, // S_FLAMEJETFLAMEB1
{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|2, 1, {A_MoveRelative}, 0, 7, S_FLAMEJETFLAMEB3}, // S_FLAMEJETFLAMEB2 {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40, 1, {A_MoveRelative}, 0, 7, S_FLAMEJETFLAMEB3}, // S_FLAMEJETFLAMEB2
{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|3,24, {NULL}, 0, 0, S_FLAMEJETFLAMEB4}, // S_FLAMEJETFLAMEB3 {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|FF_ANIMATE, (12*7), {NULL}, 7, 12, S_NULL}, // S_FLAMEJETFLAMEB3
{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|4,24, {NULL}, 0, 0, S_FLAMEJETFLAMEB5}, // S_FLAMEJETFLAMEB4
{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|5,24, {NULL}, 0, 0, S_FLAMEJETFLAMEB6}, // S_FLAMEJETFLAMEB5
{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|6,12, {NULL}, 0, 0, S_NULL}, // S_FLAMEJETFLAMEB6
// Trapgoyles // Trapgoyles
{SPR_GARG, 0, 67, {NULL}, 0, 0, S_TRAPGOYLE_CHECK}, // S_TRAPGOYLE {SPR_GARG, 0, 67, {NULL}, 0, 0, S_TRAPGOYLE_CHECK}, // S_TRAPGOYLE
@ -2006,8 +1984,10 @@ state_t states[NUMSTATES] =
{SPR_BSZ7, 5, -1, {NULL}, 0, 0, S_NULL}, // S_BSZVINE_ORANGE {SPR_BSZ7, 5, -1, {NULL}, 0, 0, S_NULL}, // S_BSZVINE_ORANGE
{SPR_BSZ8, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BSZSHRUB {SPR_BSZ8, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BSZSHRUB
{SPR_BSZ8, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BSZCLOVER {SPR_BSZ8, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BSZCLOVER
{SPR_BSZ8, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BSZFISH {SPR_BSZ8, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BIG_PALMTREE_TRUNK
{SPR_BSZ8, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BSZSUNFLOWER {SPR_BSZ8, 3, -1, {NULL}, 0, 0, S_NULL}, // S_BIG_PALMTREE_TOP
{SPR_BSZ8, 4, -1, {NULL}, 0, 0, S_NULL}, // S_PALMTREE_TRUNK
{SPR_BSZ8, 5, -1, {NULL}, 0, 0, S_NULL}, // S_PALMTREE_TOP
// Disco ball // Disco ball
{SPR_DBAL, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_DBALL2}, // S_DBALL1 {SPR_DBAL, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_DBALL2}, // S_DBALL1
@ -2762,25 +2742,25 @@ state_t states[NUMSTATES] =
{SPR_FBLL, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_NULL}, // S_FIREBALLEXP3 {SPR_FBLL, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_NULL}, // S_FIREBALLEXP3
// Turtle Shell // Turtle Shell
{SPR_SHLL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHELL {SPR_SHLL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHELL
{SPR_SHLL, 0, 2, {NULL}, 0, 0, S_SHELL2}, // S_SHELL1
{SPR_SHLL, 1, 2, {NULL}, 0, 0, S_SHELL3}, // S_SHELL2
{SPR_SHLL, 2, 2, {NULL}, 0, 0, S_SHELL4}, // S_SHELL3
{SPR_SHLL, 3, 2, {NULL}, 0, 0, S_SHELL1}, // S_SHELL4
// Puma (Mario fireball) // Puma (Mario fireball)
{SPR_PUMA, FF_FULLBRIGHT, 3, {A_FishJump}, 0, 0, S_PUMA2}, // S_PUMA1 {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_START2}, // S_PUMA_START1
{SPR_PUMA, FF_FULLBRIGHT|1, 3, {A_FishJump}, 0, 0, S_PUMA3}, // S_PUMA2 {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_PlaySound}, sfx_s3k70, 1, S_PUMA_UP1}, // S_PUMA_START2
{SPR_PUMA, FF_FULLBRIGHT|2, 3, {A_FishJump}, 0, 0, S_PUMA1}, // S_PUMA3 {SPR_PUMA, FF_FULLBRIGHT , 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP2}, // S_PUMA_UP1
{SPR_PUMA, FF_FULLBRIGHT|3, 3, {A_FishJump}, 0, 0, S_PUMA5}, // S_PUMA4 {SPR_PUMA, FF_FULLBRIGHT|1, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP3}, // S_PUMA_UP2
{SPR_PUMA, FF_FULLBRIGHT|4, 3, {A_FishJump}, 0, 0, S_PUMA6}, // S_PUMA5 {SPR_PUMA, FF_FULLBRIGHT|2, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP1}, // S_PUMA_UP3
{SPR_PUMA, FF_FULLBRIGHT|5, 3, {A_FishJump}, 0, 0, S_PUMA4}, // S_PUMA6 {SPR_PUMA, FF_FULLBRIGHT|3, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_DOWN2}, // S_PUMA_DOWN1
{SPR_PUMA, FF_FULLBRIGHT|4, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_DOWN3}, // S_PUMA_DOWN2
{SPR_PUMA, FF_FULLBRIGHT|5, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_DOWN1}, // S_PUMA_DOWN3
{SPR_PUMA, FF_FULLBRIGHT|FF_TRANS20|6, 4, {NULL}, 0, 0, S_PUMATRAIL2}, // S_PUMATRAIL1
{SPR_PUMA, FF_FULLBRIGHT|FF_TRANS40|6, 5, {A_SetScale}, FRACUNIT, 1, S_PUMATRAIL3}, // S_PUMATRAIL2
{SPR_PUMA, FF_FULLBRIGHT|FF_TRANS50|7, 4, {NULL}, 0, 0, S_PUMATRAIL4}, // S_PUMATRAIL3
{SPR_PUMA, FF_FULLBRIGHT|FF_TRANS60|8, 3, {NULL}, 0, 0, S_NULL}, // S_PUMATRAIL4
// Hammer // Hammer
{SPR_HAMM, 0, 3, {NULL}, 0, 0, S_HAMMER2}, // S_HAMMER1 {SPR_HAMM, FF_ANIMATE, -1, {NULL}, 4, 3, S_NULL}, // S_HAMMER
{SPR_HAMM, 1, 3, {NULL}, 0, 0, S_HAMMER3}, // S_HAMMER2
{SPR_HAMM, 2, 3, {NULL}, 0, 0, S_HAMMER4}, // S_HAMMER3
{SPR_HAMM, 3, 3, {NULL}, 0, 0, S_HAMMER1}, // S_HAMMER4
// Koopa // Koopa
{SPR_KOOP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KOOPA1 {SPR_KOOP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KOOPA1
@ -3195,8 +3175,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_pop, // deathsound sfx_pop, // deathsound
4*FRACUNIT, // speed 4*FRACUNIT, // speed
20*FRACUNIT, // radius 28*FRACUNIT, // radius
24*FRACUNIT, // height 40*FRACUNIT, // height
0, // display offset 0, // display offset
100, // mass 100, // mass
0, // damage 0, // damage
@ -3222,8 +3202,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_pop, // deathsound sfx_pop, // deathsound
8*FRACUNIT, // speed 8*FRACUNIT, // speed
20*FRACUNIT, // radius 28*FRACUNIT, // radius
24*FRACUNIT, // height 40*FRACUNIT, // height
0, // display offset 0, // display offset
100, // mass 100, // mass
0, // damage 0, // damage
@ -4339,6 +4319,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_GOOPTRAIL
-1, // doomednum
S_GOOPTRAIL, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
3, // speed
4*FRACUNIT, // radius
4*FRACUNIT, // height
0, // display offset
4, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
{ // MT_EGGMOBILE3 { // MT_EGGMOBILE3
202, // doomednum 202, // doomednum
S_EGGMOBILE3_STND, // spawnstate S_EGGMOBILE3_STND, // spawnstate
@ -4726,7 +4733,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
S_NULL, // painstate S_NULL, // painstate
0, // painchance MT_NULL, // painchance
sfx_None, // painsound sfx_None, // painsound
S_NULL, // meleestate S_NULL, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
@ -4945,7 +4952,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_METALSONIC_PAIN, // painstate S_METALSONIC_PAIN, // painstate
S_METALSONIC_VECTOR,// painchance S_METALSONIC_VECTOR,// painchance
sfx_dmpain, // painsound sfx_dmpain, // painsound
S_METALSONIC_BLOCK, // meleestate S_METALSONIC_BADBOUNCE, // meleestate
S_METALSONIC_SHOOT, // missilestate S_METALSONIC_SHOOT, // missilestate
S_METALSONIC_DEATH, // deathstate S_METALSONIC_DEATH, // deathstate
S_METALSONIC_FLEE1, // xdeathstate S_METALSONIC_FLEE1, // xdeathstate
@ -4954,7 +4961,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
16*FRACUNIT, // radius 16*FRACUNIT, // radius
48*FRACUNIT, // height 48*FRACUNIT, // height
0, // display offset 0, // display offset
sfx_mspogo, // mass sfx_s3k5a, // mass
3, // damage 3, // damage
sfx_mswarp, // activesound sfx_mswarp, // activesound
MF_NOGRAVITY|MF_BOSS|MF_SLIDEME, // flags MF_NOGRAVITY|MF_BOSS|MF_SLIDEME, // flags
@ -5989,7 +5996,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
S_STARPOST_SPIN, // painstate S_STARPOST_STARTSPIN, // painstate
0, // painchance 0, // painchance
sfx_strpst, // painsound sfx_strpst, // painsound
S_NULL, // meleestate S_NULL, // meleestate
@ -5999,7 +6006,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // deathsound sfx_None, // deathsound
8, // speed 8, // speed
64*FRACUNIT, // radius 64*FRACUNIT, // radius
80*FRACUNIT, // height 128*FRACUNIT, // height
0, // display offset 0, // display offset
4, // mass 4, // mass
0, // damage 0, // damage
@ -7927,7 +7934,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_GFZFLOWER2 { // MT_GFZFLOWER2
801, // doomednum 801, // doomednum
S_GFZFLOWERB1, // spawnstate S_GFZFLOWERB, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -7954,7 +7961,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_GFZFLOWER3 { // MT_GFZFLOWER3
802, // doomednum 802, // doomednum
S_GFZFLOWERC1, // spawnstate S_GFZFLOWERC, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -7975,7 +7982,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass 100, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -8033,9 +8040,36 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_THZPLANT { // MT_THZFLOWER1
900, // doomednum 900, // doomednum
S_THZPLANT1, // spawnstate S_THZFLOWERA, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
8*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_THZFLOWER2
902, // doomednum
S_THZFLOWERB, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -8339,7 +8373,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
S_NULL, // painstate S_NULL, // painstate
0, // painchance MT_FLAMEPARTICLE, // painchance
sfx_None, // painsound sfx_None, // painsound
S_NULL, // meleestate S_NULL, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
@ -8357,6 +8391,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_FLAMEPARTICLE
-1, // doomednum
S_FLAMEPARTICLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
FRACUNIT, // radius
FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_EGGSTATUE { // MT_EGGSTATUE
1102, // doomednum 1102, // doomednum
S_EGGSTATUE1, // spawnstate S_EGGSTATUE1, // spawnstate
@ -8924,33 +8985,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_FJSPINHELPERA
-1, // doomednum
S_FJSPINHELPERA1,// spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
10*FRACUNIT, // speed
16*FRACUNIT, // radius
1*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
sfx_None, // activesound
MF_NOCLIP|MF_NOCLIPTHING|MF_NOGRAVITY|MF_NOSECTOR, // flags
S_NULL // raisestate
},
{ // MT_FJSPINAXISB { // MT_FJSPINAXISB
3576, // doomednum 3576, // doomednum
S_FJSPINAXISB1, // spawnstate S_FJSPINAXISB1, // spawnstate
@ -8978,33 +9012,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_FJSPINHELPERB
-1, // doomednum
S_FJSPINHELPERB1,// spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
10*FRACUNIT, // speed
16*FRACUNIT, // radius
1*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
sfx_None, // activesound
MF_NOCLIP|MF_NOCLIPTHING|MF_NOGRAVITY|MF_NOSECTOR, // flags
S_NULL // raisestate
},
{ // MT_FLAMEJETFLAMEB { // MT_FLAMEJETFLAMEB
-1, // doomednum -1, // doomednum
S_FLAMEJETFLAMEB1, // spawnstate S_FLAMEJETFLAMEB1, // spawnstate
@ -10709,9 +10716,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_BSZFISH { // MT_BIG_PALMTREE_TRUNK
1472, // doomednum 1472, // doomednum
S_BSZFISH, // spawnstate S_BIG_PALMTREE_TRUNK, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -10736,9 +10743,63 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_BSZSUNFLOWER { // MT_BIG_PALMTREE_TOP
1473, // doomednum 1473, // doomednum
S_BSZSUNFLOWER, // spawnstate S_BIG_PALMTREE_TOP, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_PALMTREE_TRUNK
1474, // doomednum
S_PALMTREE_TRUNK, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_PALMTREE_TOP
1475, // doomednum
S_PALMTREE_TOP, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -13085,9 +13146,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL, // deathstate S_NULL, // deathstate
S_NULL, // xdeathstate S_NULL, // xdeathstate
sfx_None, // deathsound sfx_None, // deathsound
20*FRACUNIT, // speed 16, // speed
8*FRACUNIT, // radius 16*FRACUNIT, // radius
16*FRACUNIT, // height 20*FRACUNIT, // height
0, // display offset 0, // display offset
100, // mass 100, // mass
1, // damage 1, // damage
@ -13098,19 +13159,19 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
{ // MT_PUMA { // MT_PUMA
1805, // doomednum 1805, // doomednum
S_PUMA1, // spawnstate S_PUMA_START1, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_PUMA1, // seestate S_PUMA_START1, // seestate
sfx_None, // seesound sfx_None, // seesound
8, // reactiontime 8, // reactiontime
sfx_None, // attacksound sfx_None, // attacksound
S_NULL, // painstate S_NULL, // painstate
0, // painchance 0, // painchance
sfx_None, // painsound sfx_None, // painsound
S_PUMA4, // meleestate S_PUMA_DOWN1, // meleestate
S_NULL, // missilestate S_NULL, // missilestate
S_NULL, // deathstate S_NULL, // deathstate
S_PUMA6, // xdeathstate S_PUMA_DOWN3, // xdeathstate
sfx_None, // deathsound sfx_None, // deathsound
0, // speed 0, // speed
8*FRACUNIT, // radius 8*FRACUNIT, // radius
@ -13119,12 +13180,40 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass 100, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_PAIN|MF_FIRE, // flags MF_PAIN|MF_FIRE, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_PUMATRAIL
-1, // doomednum
S_PUMATRAIL1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
2*FRACUNIT, // radius
4*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
{ // MT_HAMMER { // MT_HAMMER
-1, // doomednum -1, // doomednum
S_HAMMER1, // spawnstate S_HAMMER, // spawnstate
1000, // spawnhealth 1000, // spawnhealth
S_NULL, // seestate S_NULL, // seestate
sfx_None, // seesound sfx_None, // seesound
@ -14335,7 +14424,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14362,7 +14451,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14389,7 +14478,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14416,7 +14505,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14443,7 +14532,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14470,7 +14559,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14497,7 +14586,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14524,7 +14613,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14551,7 +14640,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14578,7 +14667,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14605,7 +14694,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14632,7 +14721,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14659,7 +14748,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14686,7 +14775,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14713,7 +14802,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -14740,7 +14829,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
0, // display offset 0, // display offset
1000, // mass 1000, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate S_NULL // raisestate
}, },

View File

@ -224,6 +224,7 @@ void A_FlickyFlounder();
void A_FlickyCheck(); void A_FlickyCheck();
void A_FlickyHeightCheck(); void A_FlickyHeightCheck();
void A_FlickyFlutter(); void A_FlickyFlutter();
void A_FlameParticle();
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1 // ratio of states to sprites to mobj types is roughly 6 : 1 : 1
#define NUMMOBJFREESLOTS 256 #define NUMMOBJFREESLOTS 256
@ -388,7 +389,8 @@ typedef enum sprite
SPR_BUS2, // GFZ Bush w/o berries SPR_BUS2, // GFZ Bush w/o berries
// Techno Hill Scenery // Techno Hill Scenery
SPR_THZP, // Techno Hill Zone Plant SPR_THZP, // THZ1 Flower
SPR_FWR5, // Another flower
SPR_ALRM, // THZ2 Alarm SPR_ALRM, // THZ2 Alarm
// Deep Sea Scenery // Deep Sea Scenery
@ -1200,6 +1202,7 @@ typedef enum state
S_GOOP1, S_GOOP1,
S_GOOP2, S_GOOP2,
S_GOOP3, S_GOOP3,
S_GOOPTRAIL,
// Boss 3 // Boss 3
S_EGGMOBILE3_STND, S_EGGMOBILE3_STND,
@ -1572,11 +1575,11 @@ typedef enum state
S_METALSONIC_FLOAT, S_METALSONIC_FLOAT,
S_METALSONIC_VECTOR, S_METALSONIC_VECTOR,
S_METALSONIC_STUN, S_METALSONIC_STUN,
S_METALSONIC_BLOCK,
S_METALSONIC_RAISE, S_METALSONIC_RAISE,
S_METALSONIC_GATHER, S_METALSONIC_GATHER,
S_METALSONIC_DASH, S_METALSONIC_DASH,
S_METALSONIC_BOUNCE, S_METALSONIC_BOUNCE,
S_METALSONIC_BADBOUNCE,
S_METALSONIC_SHOOT, S_METALSONIC_SHOOT,
S_METALSONIC_PAIN, S_METALSONIC_PAIN,
S_METALSONIC_DEATH, S_METALSONIC_DEATH,
@ -1776,7 +1779,9 @@ typedef enum state
// Starpost // Starpost
S_STARPOST_IDLE, S_STARPOST_IDLE,
S_STARPOST_FLASH, S_STARPOST_FLASH,
S_STARPOST_STARTSPIN,
S_STARPOST_SPIN, S_STARPOST_SPIN,
S_STARPOST_ENDSPIN,
// Big floating mine // Big floating mine
S_BIGMINE1, S_BIGMINE1,
@ -1960,21 +1965,15 @@ typedef enum state
S_DEMONFIRE6, S_DEMONFIRE6,
S_GFZFLOWERA, S_GFZFLOWERA,
S_GFZFLOWERA2, S_GFZFLOWERB,
S_GFZFLOWERC,
S_GFZFLOWERB1,
S_GFZFLOWERB2,
S_GFZFLOWERC1,
S_BERRYBUSH, S_BERRYBUSH,
S_BUSH, S_BUSH,
// THZ Plant // THZ Plant
S_THZPLANT1, S_THZFLOWERA,
S_THZPLANT2, S_THZFLOWERB,
S_THZPLANT3,
S_THZPLANT4,
// THZ Alarm // THZ Alarm
S_ALARM1, S_ALARM1,
@ -2019,6 +2018,11 @@ typedef enum state
S_FLAME2, S_FLAME2,
S_FLAME3, S_FLAME3,
S_FLAME4, S_FLAME4,
S_FLAME5,
S_FLAME6,
S_FLAMEPARTICLE,
S_FLAMEREST,
// Eggman Statue // Eggman Statue
S_EGGSTATUE1, S_EGGSTATUE1,
@ -2080,36 +2084,13 @@ typedef enum state
// Spinning flame jets // Spinning flame jets
S_FJSPINAXISA1, // Counter-clockwise S_FJSPINAXISA1, // Counter-clockwise
S_FJSPINAXISA2, S_FJSPINAXISA2,
S_FJSPINAXISA3,
S_FJSPINAXISA4,
S_FJSPINAXISA5,
S_FJSPINAXISA6,
S_FJSPINAXISA7,
S_FJSPINAXISA8,
S_FJSPINAXISA9,
S_FJSPINHELPERA1,
S_FJSPINHELPERA2,
S_FJSPINHELPERA3,
S_FJSPINAXISB1, // Clockwise S_FJSPINAXISB1, // Clockwise
S_FJSPINAXISB2, S_FJSPINAXISB2,
S_FJSPINAXISB3,
S_FJSPINAXISB4,
S_FJSPINAXISB5,
S_FJSPINAXISB6,
S_FJSPINAXISB7,
S_FJSPINAXISB8,
S_FJSPINAXISB9,
S_FJSPINHELPERB1,
S_FJSPINHELPERB2,
S_FJSPINHELPERB3,
// Blade's flame // Blade's flame
S_FLAMEJETFLAMEB1, S_FLAMEJETFLAMEB1,
S_FLAMEJETFLAMEB2, S_FLAMEJETFLAMEB2,
S_FLAMEJETFLAMEB3, S_FLAMEJETFLAMEB3,
S_FLAMEJETFLAMEB4,
S_FLAMEJETFLAMEB5,
S_FLAMEJETFLAMEB6,
// Trapgoyles // Trapgoyles
S_TRAPGOYLE, S_TRAPGOYLE,
@ -2204,8 +2185,10 @@ typedef enum state
S_BSZVINE_ORANGE, S_BSZVINE_ORANGE,
S_BSZSHRUB, S_BSZSHRUB,
S_BSZCLOVER, S_BSZCLOVER,
S_BSZFISH, S_BIG_PALMTREE_TRUNK,
S_BSZSUNFLOWER, S_BIG_PALMTREE_TOP,
S_PALMTREE_TRUNK,
S_PALMTREE_TOP,
S_DBALL1, S_DBALL1,
S_DBALL2, S_DBALL2,
@ -2924,20 +2907,19 @@ typedef enum state
S_FIREBALLEXP2, S_FIREBALLEXP2,
S_FIREBALLEXP3, S_FIREBALLEXP3,
S_SHELL, S_SHELL,
S_SHELL1, S_PUMA_START1,
S_SHELL2, S_PUMA_START2,
S_SHELL3, S_PUMA_UP1,
S_SHELL4, S_PUMA_UP2,
S_PUMA1, S_PUMA_UP3,
S_PUMA2, S_PUMA_DOWN1,
S_PUMA3, S_PUMA_DOWN2,
S_PUMA4, S_PUMA_DOWN3,
S_PUMA5, S_PUMATRAIL1,
S_PUMA6, S_PUMATRAIL2,
S_HAMMER1, S_PUMATRAIL3,
S_HAMMER2, S_PUMATRAIL4,
S_HAMMER3, S_HAMMER,
S_HAMMER4,
S_KOOPA1, S_KOOPA1,
S_KOOPA2, S_KOOPA2,
S_KOOPAFLAME1, S_KOOPAFLAME1,
@ -3209,6 +3191,7 @@ typedef enum mobj_type
MT_BOSSTANK2, MT_BOSSTANK2,
MT_BOSSSPIGOT, MT_BOSSSPIGOT,
MT_GOOP, MT_GOOP,
MT_GOOPTRAIL,
// Boss 3 // Boss 3
MT_EGGMOBILE3, MT_EGGMOBILE3,
@ -3378,7 +3361,8 @@ typedef enum mobj_type
MT_BUSH, MT_BUSH,
// Techno Hill Scenery // Techno Hill Scenery
MT_THZPLANT, // THZ Plant MT_THZFLOWER1,
MT_THZFLOWER2,
MT_ALARM, MT_ALARM,
// Deep Sea Scenery // Deep Sea Scenery
@ -3394,6 +3378,7 @@ typedef enum mobj_type
// Castle Eggman Scenery // Castle Eggman Scenery
MT_CHAIN, // CEZ Chain MT_CHAIN, // CEZ Chain
MT_FLAME, // Flame (has corona) MT_FLAME, // Flame (has corona)
MT_FLAMEPARTICLE,
MT_EGGSTATUE, // Eggman Statue MT_EGGSTATUE, // Eggman Statue
MT_MACEPOINT, // Mace rotation point MT_MACEPOINT, // Mace rotation point
MT_SWINGMACEPOINT, // Mace swinging point MT_SWINGMACEPOINT, // Mace swinging point
@ -3420,9 +3405,7 @@ typedef enum mobj_type
MT_FLAMEJETFLAME, MT_FLAMEJETFLAME,
MT_FJSPINAXISA, // Counter-clockwise MT_FJSPINAXISA, // Counter-clockwise
MT_FJSPINHELPERA,
MT_FJSPINAXISB, // Clockwise MT_FJSPINAXISB, // Clockwise
MT_FJSPINHELPERB,
MT_FLAMEJETFLAMEB, // Blade's flame MT_FLAMEJETFLAMEB, // Blade's flame
@ -3499,8 +3482,10 @@ typedef enum mobj_type
MT_BSZVINE_ORANGE, MT_BSZVINE_ORANGE,
MT_BSZSHRUB, MT_BSZSHRUB,
MT_BSZCLOVER, MT_BSZCLOVER,
MT_BSZFISH, MT_BIG_PALMTREE_TRUNK,
MT_BSZSUNFLOWER, MT_BIG_PALMTREE_TOP,
MT_PALMTREE_TRUNK,
MT_PALMTREE_TOP,
// Misc scenery // Misc scenery
MT_DBALL, MT_DBALL,
@ -3606,6 +3591,7 @@ typedef enum mobj_type
MT_FIREBALL, MT_FIREBALL,
MT_SHELL, MT_SHELL,
MT_PUMA, MT_PUMA,
MT_PUMATRAIL,
MT_HAMMER, MT_HAMMER,
MT_KOOPA, MT_KOOPA,
MT_KOOPAFLAME, MT_KOOPAFLAME,

View File

@ -25,7 +25,10 @@
#include "lua_libs.h" #include "lua_libs.h"
#include "lua_hud.h" // hud_running errors #include "lua_hud.h" // hud_running errors
#define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); #define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
#define INLEVEL if (gamestate != GS_LEVEL)\
return luaL_error(L, "This function can only be used in a level!");
boolean luaL_checkboolean(lua_State *L, int narg) { boolean luaL_checkboolean(lua_State *L, int narg) {
luaL_checktype(L, narg, LUA_TBOOLEAN); luaL_checktype(L, narg, LUA_TBOOLEAN);
@ -84,6 +87,86 @@ static int lib_print(lua_State *L)
return 0; return 0;
} }
static const struct {
const char *meta;
const char *utype;
} meta2utype[] = {
{META_STATE, "state_t"},
{META_MOBJINFO, "mobjinfo_t"},
{META_SFXINFO, "sfxinfo_t"},
{META_MOBJ, "mobj_t"},
{META_MAPTHING, "mapthing_t"},
{META_PLAYER, "player_t"},
{META_TICCMD, "ticcmd_t"},
{META_SKIN, "skin_t"},
{META_POWERS, "player_t.powers"},
{META_SOUNDSID, "skin_t.soundsid"},
{META_VERTEX, "vertex_t"},
{META_LINE, "line_t"},
{META_SIDE, "side_t"},
{META_SUBSECTOR, "subsector_t"},
{META_SECTOR, "sector_t"},
{META_FFLOOR, "ffloor_t"},
#ifdef HAVE_LUA_SEGS
{META_SEG, "seg_t"},
{META_NODE, "node_t"},
#endif
{META_MAPHEADER, "mapheader_t"},
{META_CVAR, "consvar_t"},
{META_SECTORLINES, "sector_t.lines"},
{META_SIDENUM, "line_t.sidenum"},
#ifdef HAVE_LUA_SEGS
{META_NODEBBOX, "node_t.bbox"},
{META_NODECHILDREN, "node_t.children"},
#endif
{META_BBOX, "bbox"},
{META_HUDINFO, "hudinfo_t"},
{META_PATCH, "patch_t"},
{META_COLORMAP, "colormap"},
{META_CAMERA, "camera_t"},
{NULL, NULL}
};
// goes through the above list and returns the utype string for the userdata type
// returns "unknown" instead if we couldn't find the right userdata type
static const char *GetUserdataUType(lua_State *L)
{
UINT8 i;
lua_getmetatable(L, -1);
for (i = 0; meta2utype[i].meta; i++)
{
luaL_getmetatable(L, meta2utype[i].meta);
if (lua_rawequal(L, -1, -2))
{
lua_pop(L, 2);
return meta2utype[i].utype;
}
lua_pop(L, 1);
}
lua_pop(L, 1);
return "unknown";
}
// Return a string representing the type of userdata the given var is
// e.g. players[0] -> "player_t"
// or players[0].powers -> "player_t.powers"
static int lib_userdataType(lua_State *L)
{
lua_settop(L, 1); // pop everything except arg 1 (in case somebody decided to add more)
luaL_checktype(L, 1, LUA_TUSERDATA);
lua_pushstring(L, GetUserdataUType(L));
return 1;
}
// M_RANDOM // M_RANDOM
////////////// //////////////
@ -246,6 +329,7 @@ static int lib_pCheckMeleeRange(lua_State *L)
{ {
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!actor) if (!actor)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_CheckMeleeRange(actor)); lua_pushboolean(L, P_CheckMeleeRange(actor));
@ -256,6 +340,7 @@ static int lib_pJetbCheckMeleeRange(lua_State *L)
{ {
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!actor) if (!actor)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_JetbCheckMeleeRange(actor)); lua_pushboolean(L, P_JetbCheckMeleeRange(actor));
@ -266,6 +351,7 @@ static int lib_pFaceStabCheckMeleeRange(lua_State *L)
{ {
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!actor) if (!actor)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_FaceStabCheckMeleeRange(actor)); lua_pushboolean(L, P_FaceStabCheckMeleeRange(actor));
@ -276,6 +362,7 @@ static int lib_pSkimCheckMeleeRange(lua_State *L)
{ {
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!actor) if (!actor)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_SkimCheckMeleeRange(actor)); lua_pushboolean(L, P_SkimCheckMeleeRange(actor));
@ -286,6 +373,7 @@ static int lib_pCheckMissileRange(lua_State *L)
{ {
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!actor) if (!actor)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_CheckMissileRange(actor)); lua_pushboolean(L, P_CheckMissileRange(actor));
@ -296,6 +384,7 @@ static int lib_pNewChaseDir(lua_State *L)
{ {
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!actor) if (!actor)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_NewChaseDir(actor); P_NewChaseDir(actor);
@ -309,6 +398,7 @@ static int lib_pLookForPlayers(lua_State *L)
boolean allaround = lua_optboolean(L, 3); boolean allaround = lua_optboolean(L, 3);
boolean tracer = lua_optboolean(L, 4); boolean tracer = lua_optboolean(L, 4);
NOHUD NOHUD
INLEVEL
if (!actor) if (!actor)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_LookForPlayers(actor, allaround, tracer, dist)); lua_pushboolean(L, P_LookForPlayers(actor, allaround, tracer, dist));
@ -325,6 +415,7 @@ static int lib_pSpawnMobj(lua_State *L)
fixed_t z = luaL_checkfixed(L, 3); fixed_t z = luaL_checkfixed(L, 3);
mobjtype_t type = luaL_checkinteger(L, 4); mobjtype_t type = luaL_checkinteger(L, 4);
NOHUD NOHUD
INLEVEL
if (type >= NUMMOBJTYPES) if (type >= NUMMOBJTYPES)
return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type), META_MOBJ); LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type), META_MOBJ);
@ -335,6 +426,7 @@ static int lib_pRemoveMobj(lua_State *L)
{ {
mobj_t *th = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *th = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!th) if (!th)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (th->player) if (th->player)
@ -350,6 +442,7 @@ static int lib_pIsValidSprite2(lua_State *L)
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
UINT8 spr2 = (UINT8)luaL_checkinteger(L, 2); UINT8 spr2 = (UINT8)luaL_checkinteger(L, 2);
//HUDSAFE //HUDSAFE
INLEVEL
if (!mobj) if (!mobj)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, (mobj->skin && (((skin_t *)mobj->skin)->sprites[spr2].numframes > 0))); lua_pushboolean(L, (mobj->skin && (((skin_t *)mobj->skin)->sprites[spr2].numframes > 0)));
@ -362,6 +455,7 @@ static int lib_pSpawnMissile(lua_State *L)
mobj_t *dest = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); mobj_t *dest = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
mobjtype_t type = luaL_checkinteger(L, 3); mobjtype_t type = luaL_checkinteger(L, 3);
NOHUD NOHUD
INLEVEL
if (!source || !dest) if (!source || !dest)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES) if (type >= NUMMOBJTYPES)
@ -379,6 +473,7 @@ static int lib_pSpawnXYZMissile(lua_State *L)
fixed_t y = luaL_checkfixed(L, 5); fixed_t y = luaL_checkfixed(L, 5);
fixed_t z = luaL_checkfixed(L, 6); fixed_t z = luaL_checkfixed(L, 6);
NOHUD NOHUD
INLEVEL
if (!source || !dest) if (!source || !dest)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES) if (type >= NUMMOBJTYPES)
@ -398,6 +493,7 @@ static int lib_pSpawnPointMissile(lua_State *L)
fixed_t y = luaL_checkfixed(L, 7); fixed_t y = luaL_checkfixed(L, 7);
fixed_t z = luaL_checkfixed(L, 8); fixed_t z = luaL_checkfixed(L, 8);
NOHUD NOHUD
INLEVEL
if (!source) if (!source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES) if (type >= NUMMOBJTYPES)
@ -415,6 +511,7 @@ static int lib_pSpawnAlteredDirectionMissile(lua_State *L)
fixed_t z = luaL_checkfixed(L, 5); fixed_t z = luaL_checkfixed(L, 5);
INT32 shiftingAngle = (INT32)luaL_checkinteger(L, 5); INT32 shiftingAngle = (INT32)luaL_checkinteger(L, 5);
NOHUD NOHUD
INLEVEL
if (!source) if (!source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES) if (type >= NUMMOBJTYPES)
@ -428,6 +525,7 @@ static int lib_pColorTeamMissile(lua_State *L)
mobj_t *missile = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *missile = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
player_t *source = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); player_t *source = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!missile) if (!missile)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (!source) if (!source)
@ -444,6 +542,7 @@ static int lib_pSPMAngle(lua_State *L)
UINT8 allowaim = (UINT8)luaL_optinteger(L, 4, 0); UINT8 allowaim = (UINT8)luaL_optinteger(L, 4, 0);
UINT32 flags2 = (UINT32)luaL_optinteger(L, 5, 0); UINT32 flags2 = (UINT32)luaL_optinteger(L, 5, 0);
NOHUD NOHUD
INLEVEL
if (!source) if (!source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES) if (type >= NUMMOBJTYPES)
@ -458,6 +557,7 @@ static int lib_pSpawnPlayerMissile(lua_State *L)
mobjtype_t type = luaL_checkinteger(L, 2); mobjtype_t type = luaL_checkinteger(L, 2);
UINT32 flags2 = (UINT32)luaL_optinteger(L, 3, 0); UINT32 flags2 = (UINT32)luaL_optinteger(L, 3, 0);
NOHUD NOHUD
INLEVEL
if (!source) if (!source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES) if (type >= NUMMOBJTYPES)
@ -470,6 +570,7 @@ static int lib_pMobjFlip(lua_State *L)
{ {
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE //HUDSAFE
INLEVEL
if (!mobj) if (!mobj)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushinteger(L, P_MobjFlip(mobj)); lua_pushinteger(L, P_MobjFlip(mobj));
@ -480,6 +581,7 @@ static int lib_pGetMobjGravity(lua_State *L)
{ {
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE //HUDSAFE
INLEVEL
if (!mobj) if (!mobj)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushfixed(L, P_GetMobjGravity(mobj)); lua_pushfixed(L, P_GetMobjGravity(mobj));
@ -502,6 +604,7 @@ static int lib_pFlashPal(lua_State *L)
UINT16 type = (UINT16)luaL_checkinteger(L, 2); UINT16 type = (UINT16)luaL_checkinteger(L, 2);
UINT16 duration = (UINT16)luaL_checkinteger(L, 3); UINT16 duration = (UINT16)luaL_checkinteger(L, 3);
NOHUD NOHUD
INLEVEL
if (!pl) if (!pl)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_FlashPal(pl, type, duration); P_FlashPal(pl, type, duration);
@ -512,6 +615,7 @@ static int lib_pGetClosestAxis(lua_State *L)
{ {
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE //HUDSAFE
INLEVEL
if (!source) if (!source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
LUA_PushUserdata(L, P_GetClosestAxis(source), META_MOBJ); LUA_PushUserdata(L, P_GetClosestAxis(source), META_MOBJ);
@ -530,6 +634,7 @@ static int lib_pSpawnParaloop(lua_State *L)
statenum_t nstate = luaL_optinteger(L, 8, S_NULL); statenum_t nstate = luaL_optinteger(L, 8, S_NULL);
boolean spawncenter = lua_optboolean(L, 9); boolean spawncenter = lua_optboolean(L, 9);
NOHUD NOHUD
INLEVEL
if (type >= NUMMOBJTYPES) if (type >= NUMMOBJTYPES)
return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
if (nstate >= NUMSTATES) if (nstate >= NUMSTATES)
@ -543,6 +648,7 @@ static int lib_pBossTargetPlayer(lua_State *L)
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
boolean closest = lua_optboolean(L, 2); boolean closest = lua_optboolean(L, 2);
NOHUD NOHUD
INLEVEL
if (!actor) if (!actor)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_BossTargetPlayer(actor, closest)); lua_pushboolean(L, P_BossTargetPlayer(actor, closest));
@ -553,6 +659,7 @@ static int lib_pSupermanLook4Players(lua_State *L)
{ {
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!actor) if (!actor)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_SupermanLook4Players(actor)); lua_pushboolean(L, P_SupermanLook4Players(actor));
@ -564,6 +671,7 @@ static int lib_pSetScale(lua_State *L)
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t newscale = luaL_checkfixed(L, 2); fixed_t newscale = luaL_checkfixed(L, 2);
NOHUD NOHUD
INLEVEL
if (!mobj) if (!mobj)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (newscale < FRACUNIT/100) if (newscale < FRACUNIT/100)
@ -577,6 +685,7 @@ static int lib_pInsideANonSolidFFloor(lua_State *L)
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
//HUDSAFE //HUDSAFE
INLEVEL
if (!mobj) if (!mobj)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (!rover) if (!rover)
@ -589,6 +698,7 @@ static int lib_pCheckDeathPitCollide(lua_State *L)
{ {
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE //HUDSAFE
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_CheckDeathPitCollide(mo)); lua_pushboolean(L, P_CheckDeathPitCollide(mo));
@ -600,6 +710,7 @@ static int lib_pCheckSolidLava(lua_State *L)
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
//HUDSAFE //HUDSAFE
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (!rover) if (!rover)
@ -613,6 +724,7 @@ static int lib_pCanRunOnWater(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
//HUDSAFE //HUDSAFE
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
if (!rover) if (!rover)
@ -628,6 +740,7 @@ static int lib_pGetPlayerHeight(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE //HUDSAFE
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
lua_pushfixed(L, P_GetPlayerHeight(player)); lua_pushfixed(L, P_GetPlayerHeight(player));
@ -638,6 +751,7 @@ static int lib_pGetPlayerSpinHeight(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE //HUDSAFE
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
lua_pushfixed(L, P_GetPlayerSpinHeight(player)); lua_pushfixed(L, P_GetPlayerSpinHeight(player));
@ -648,6 +762,7 @@ static int lib_pGetPlayerControlDirection(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE //HUDSAFE
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
lua_pushinteger(L, P_GetPlayerControlDirection(player)); lua_pushinteger(L, P_GetPlayerControlDirection(player));
@ -659,6 +774,7 @@ static int lib_pAddPlayerScore(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
UINT32 amount = (UINT32)luaL_checkinteger(L, 2); UINT32 amount = (UINT32)luaL_checkinteger(L, 2);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_AddPlayerScore(player, amount); P_AddPlayerScore(player, amount);
@ -670,6 +786,7 @@ static int lib_pStealPlayerScore(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
UINT32 amount = (UINT32)luaL_checkinteger(L, 2); UINT32 amount = (UINT32)luaL_checkinteger(L, 2);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_StealPlayerScore(player, amount); P_StealPlayerScore(player, amount);
@ -680,6 +797,7 @@ static int lib_pPlayerInPain(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE //HUDSAFE
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, P_PlayerInPain(player)); lua_pushboolean(L, P_PlayerInPain(player));
@ -691,6 +809,7 @@ static int lib_pDoPlayerPain(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
mobj_t *source = NULL, *inflictor = NULL; mobj_t *source = NULL, *inflictor = NULL;
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
@ -705,6 +824,7 @@ static int lib_pResetPlayer(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_ResetPlayer(player); P_ResetPlayer(player);
@ -715,6 +835,7 @@ static int lib_pIsObjectInGoop(lua_State *L)
{ {
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE //HUDSAFE
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_IsObjectInGoop(mo)); lua_pushboolean(L, P_IsObjectInGoop(mo));
@ -725,6 +846,7 @@ static int lib_pIsObjectOnGround(lua_State *L)
{ {
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE //HUDSAFE
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_IsObjectOnGround(mo)); lua_pushboolean(L, P_IsObjectOnGround(mo));
@ -735,6 +857,7 @@ static int lib_pInSpaceSector(lua_State *L)
{ {
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE //HUDSAFE
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_InSpaceSector(mo)); lua_pushboolean(L, P_InSpaceSector(mo));
@ -745,6 +868,7 @@ static int lib_pInQuicksand(lua_State *L)
{ {
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE //HUDSAFE
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_InQuicksand(mo)); lua_pushboolean(L, P_InQuicksand(mo));
@ -757,6 +881,7 @@ static int lib_pSetObjectMomZ(lua_State *L)
fixed_t value = luaL_checkfixed(L, 2); fixed_t value = luaL_checkfixed(L, 2);
boolean relative = lua_optboolean(L, 3); boolean relative = lua_optboolean(L, 3);
NOHUD NOHUD
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_SetObjectMomZ(mo, value, relative); P_SetObjectMomZ(mo, value, relative);
@ -767,6 +892,7 @@ static int lib_pRestoreMusic(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_RestoreMusic(player); P_RestoreMusic(player);
@ -777,6 +903,7 @@ static int lib_pSpawnShieldOrb(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_SpawnShieldOrb(player); P_SpawnShieldOrb(player);
@ -787,6 +914,7 @@ static int lib_pSpawnGhostMobj(lua_State *L)
{ {
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!mobj) if (!mobj)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
LUA_PushUserdata(L, P_SpawnGhostMobj(mobj), META_MOBJ); LUA_PushUserdata(L, P_SpawnGhostMobj(mobj), META_MOBJ);
@ -798,6 +926,7 @@ static int lib_pGivePlayerRings(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
INT32 num_rings = (INT32)luaL_checkinteger(L, 2); INT32 num_rings = (INT32)luaL_checkinteger(L, 2);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_GivePlayerRings(player, num_rings); P_GivePlayerRings(player, num_rings);
@ -809,6 +938,7 @@ static int lib_pGivePlayerLives(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
INT32 numlives = (INT32)luaL_checkinteger(L, 2); INT32 numlives = (INT32)luaL_checkinteger(L, 2);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_GivePlayerLives(player, numlives); P_GivePlayerLives(player, numlives);
@ -819,6 +949,7 @@ static int lib_pResetScore(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_ResetScore(player); P_ResetScore(player);
@ -829,6 +960,7 @@ static int lib_pDoJumpShield(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_DoJumpShield(player); P_DoJumpShield(player);
@ -839,6 +971,7 @@ static int lib_pDoBubbleBounce(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_DoBubbleBounce(player); P_DoBubbleBounce(player);
@ -849,6 +982,7 @@ static int lib_pBlackOw(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_BlackOw(player); P_BlackOw(player);
@ -860,6 +994,7 @@ static int lib_pElementalFire(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean cropcircle = lua_optboolean(L, 2); boolean cropcircle = lua_optboolean(L, 2);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_ElementalFire(player, cropcircle); P_ElementalFire(player, cropcircle);
@ -870,6 +1005,7 @@ static int lib_pDoPlayerExit(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_DoPlayerExit(player); P_DoPlayerExit(player);
@ -882,6 +1018,7 @@ static int lib_pInstaThrust(lua_State *L)
angle_t angle = luaL_checkangle(L, 2); angle_t angle = luaL_checkangle(L, 2);
fixed_t move = luaL_checkfixed(L, 3); fixed_t move = luaL_checkfixed(L, 3);
NOHUD NOHUD
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_InstaThrust(mo, angle, move); P_InstaThrust(mo, angle, move);
@ -919,6 +1056,7 @@ static int lib_pLookForEnemies(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean nonenemies = lua_opttrueboolean(L, 2); boolean nonenemies = lua_opttrueboolean(L, 2);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, P_LookForEnemies(player, nonenemies)); lua_pushboolean(L, P_LookForEnemies(player, nonenemies));
@ -931,6 +1069,7 @@ static int lib_pNukeEnemies(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t radius = luaL_checkfixed(L, 3); fixed_t radius = luaL_checkfixed(L, 3);
NOHUD NOHUD
INLEVEL
if (!inflictor || !source) if (!inflictor || !source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_NukeEnemies(inflictor, source, radius); P_NukeEnemies(inflictor, source, radius);
@ -942,6 +1081,7 @@ static int lib_pHomingAttack(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *enemy = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); mobj_t *enemy = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!source || !enemy) if (!source || !enemy)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_HomingAttack(source, enemy); P_HomingAttack(source, enemy);
@ -952,6 +1092,7 @@ static int lib_pSuperReady(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE //HUDSAFE
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, P_SuperReady(player)); lua_pushboolean(L, P_SuperReady(player));
@ -963,6 +1104,7 @@ static int lib_pDoJump(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean soundandstate = (boolean)lua_opttrueboolean(L, 2); boolean soundandstate = (boolean)lua_opttrueboolean(L, 2);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_DoJump(player, soundandstate); P_DoJump(player, soundandstate);
@ -973,6 +1115,7 @@ static int lib_pSpawnThokMobj(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_SpawnThokMobj(player); P_SpawnThokMobj(player);
@ -984,6 +1127,7 @@ static int lib_pSpawnSpinMobj(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
mobjtype_t type = luaL_checkinteger(L, 2); mobjtype_t type = luaL_checkinteger(L, 2);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
if (type >= NUMMOBJTYPES) if (type >= NUMMOBJTYPES)
@ -998,6 +1142,7 @@ static int lib_pTelekinesis(lua_State *L)
fixed_t thrust = luaL_checkfixed(L, 2); fixed_t thrust = luaL_checkfixed(L, 2);
fixed_t range = luaL_checkfixed(L, 3); fixed_t range = luaL_checkfixed(L, 3);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_Telekinesis(player, thrust, range); P_Telekinesis(player, thrust, range);
@ -1014,6 +1159,7 @@ static int lib_pCheckPosition(lua_State *L)
fixed_t x = luaL_checkfixed(L, 2); fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3); fixed_t y = luaL_checkfixed(L, 3);
NOHUD NOHUD
INLEVEL
if (!thing) if (!thing)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_CheckPosition(thing, x, y)); lua_pushboolean(L, P_CheckPosition(thing, x, y));
@ -1030,6 +1176,7 @@ static int lib_pTryMove(lua_State *L)
fixed_t y = luaL_checkfixed(L, 3); fixed_t y = luaL_checkfixed(L, 3);
boolean allowdropoff = lua_optboolean(L, 4); boolean allowdropoff = lua_optboolean(L, 4);
NOHUD NOHUD
INLEVEL
if (!thing) if (!thing)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_TryMove(thing, x, y, allowdropoff)); lua_pushboolean(L, P_TryMove(thing, x, y, allowdropoff));
@ -1044,6 +1191,7 @@ static int lib_pMove(lua_State *L)
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t speed = luaL_checkfixed(L, 2); fixed_t speed = luaL_checkfixed(L, 2);
NOHUD NOHUD
INLEVEL
if (!actor) if (!actor)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_Move(actor, speed)); lua_pushboolean(L, P_Move(actor, speed));
@ -1060,6 +1208,7 @@ static int lib_pTeleportMove(lua_State *L)
fixed_t y = luaL_checkfixed(L, 3); fixed_t y = luaL_checkfixed(L, 3);
fixed_t z = luaL_checkfixed(L, 4); fixed_t z = luaL_checkfixed(L, 4);
NOHUD NOHUD
INLEVEL
if (!thing) if (!thing)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_TeleportMove(thing, x, y, z)); lua_pushboolean(L, P_TeleportMove(thing, x, y, z));
@ -1072,6 +1221,7 @@ static int lib_pSlideMove(lua_State *L)
{ {
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_SlideMove(mo); P_SlideMove(mo);
@ -1082,6 +1232,7 @@ static int lib_pBounceMove(lua_State *L)
{ {
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_BounceMove(mo); P_BounceMove(mo);
@ -1093,6 +1244,7 @@ static int lib_pCheckSight(lua_State *L)
mobj_t *t1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *t1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *t2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); mobj_t *t2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
//HUDSAFE? //HUDSAFE?
INLEVEL
if (!t1 || !t2) if (!t1 || !t2)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_CheckSight(t1, t2)); lua_pushboolean(L, P_CheckSight(t1, t2));
@ -1107,6 +1259,7 @@ static int lib_pCheckHoopPosition(lua_State *L)
fixed_t z = luaL_checkfixed(L, 4); fixed_t z = luaL_checkfixed(L, 4);
fixed_t radius = luaL_checkfixed(L, 5); fixed_t radius = luaL_checkfixed(L, 5);
NOHUD NOHUD
INLEVEL
if (!hoopthing) if (!hoopthing)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_CheckHoopPosition(hoopthing, x, y, z, radius); P_CheckHoopPosition(hoopthing, x, y, z, radius);
@ -1119,6 +1272,7 @@ static int lib_pRadiusAttack(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t damagedist = luaL_checkfixed(L, 3); fixed_t damagedist = luaL_checkfixed(L, 3);
NOHUD NOHUD
INLEVEL
if (!spot || !source) if (!spot || !source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_RadiusAttack(spot, source, damagedist); P_RadiusAttack(spot, source, damagedist);
@ -1132,6 +1286,7 @@ static int lib_pFloorzAtPos(lua_State *L)
fixed_t z = luaL_checkfixed(L, 3); fixed_t z = luaL_checkfixed(L, 3);
fixed_t height = luaL_checkfixed(L, 4); fixed_t height = luaL_checkfixed(L, 4);
//HUDSAFE //HUDSAFE
INLEVEL
lua_pushfixed(L, P_FloorzAtPos(x, y, z, height)); lua_pushfixed(L, P_FloorzAtPos(x, y, z, height));
return 1; return 1;
} }
@ -1141,6 +1296,7 @@ static int lib_pDoSpring(lua_State *L)
mobj_t *spring = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *spring = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *object = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); mobj_t *object = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!spring || !object) if (!spring || !object)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_DoSpring(spring, object)); lua_pushboolean(L, P_DoSpring(spring, object));
@ -1154,6 +1310,7 @@ static int lib_pRemoveShield(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_RemoveShield(player); P_RemoveShield(player);
@ -1166,6 +1323,7 @@ static int lib_pDamageMobj(lua_State *L)
INT32 damage; INT32 damage;
UINT8 damagetype; UINT8 damagetype;
NOHUD NOHUD
INLEVEL
if (!target) if (!target)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
@ -1183,6 +1341,7 @@ static int lib_pKillMobj(lua_State *L)
mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL; mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL;
UINT8 damagetype; UINT8 damagetype;
NOHUD NOHUD
INLEVEL
if (!target) if (!target)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
@ -1199,6 +1358,7 @@ static int lib_pPlayerRingBurst(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
INT32 num_rings = (INT32)luaL_optinteger(L, 2, -1); INT32 num_rings = (INT32)luaL_optinteger(L, 2, -1);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
if (num_rings == -1) if (num_rings == -1)
@ -1211,6 +1371,7 @@ static int lib_pPlayerWeaponPanelBurst(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_PlayerWeaponPanelBurst(player); P_PlayerWeaponPanelBurst(player);
@ -1221,6 +1382,7 @@ static int lib_pPlayerWeaponAmmoBurst(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_PlayerWeaponAmmoBurst(player); P_PlayerWeaponAmmoBurst(player);
@ -1231,6 +1393,7 @@ static int lib_pPlayerWeaponPanelOrAmmoBurst(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_PlayerWeaponPanelOrAmmoBurst(player); P_PlayerWeaponPanelOrAmmoBurst(player);
@ -1242,6 +1405,7 @@ static int lib_pPlayerEmeraldBurst(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean toss = lua_optboolean(L, 2); boolean toss = lua_optboolean(L, 2);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_PlayerEmeraldBurst(player, toss); P_PlayerEmeraldBurst(player, toss);
@ -1253,6 +1417,7 @@ static int lib_pPlayerFlagBurst(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean toss = lua_optboolean(L, 2); boolean toss = lua_optboolean(L, 2);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_PlayerFlagBurst(player, toss); P_PlayerFlagBurst(player, toss);
@ -1264,6 +1429,7 @@ static int lib_pPlayRinglossSound(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
player_t *player = NULL; player_t *player = NULL;
NOHUD NOHUD
INLEVEL
if (!source) if (!source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
@ -1282,6 +1448,7 @@ static int lib_pPlayDeathSound(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
player_t *player = NULL; player_t *player = NULL;
NOHUD NOHUD
INLEVEL
if (!source) if (!source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
@ -1300,6 +1467,7 @@ static int lib_pPlayVictorySound(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
player_t *player = NULL; player_t *player = NULL;
NOHUD NOHUD
INLEVEL
if (!source) if (!source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
@ -1317,6 +1485,7 @@ static int lib_pPlayLivesJingle(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_PlayLivesJingle(player); P_PlayLivesJingle(player);
@ -1328,6 +1497,7 @@ static int lib_pCanPickupItem(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean weapon = lua_optboolean(L, 2); boolean weapon = lua_optboolean(L, 2);
//HUDSAFE //HUDSAFE
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, P_CanPickupItem(player, weapon)); lua_pushboolean(L, P_CanPickupItem(player, weapon));
@ -1338,6 +1508,7 @@ static int lib_pDoNightsScore(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_DoNightsScore(player); P_DoNightsScore(player);
@ -1348,6 +1519,7 @@ static int lib_pDoMatchSuper(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_DoMatchSuper(player); P_DoMatchSuper(player);
@ -1363,6 +1535,7 @@ static int lib_pThrust(lua_State *L)
angle_t angle = luaL_checkangle(L, 2); angle_t angle = luaL_checkangle(L, 2);
fixed_t move = luaL_checkfixed(L, 3); fixed_t move = luaL_checkfixed(L, 3);
NOHUD NOHUD
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_Thrust(mo, angle, move); P_Thrust(mo, angle, move);
@ -1374,6 +1547,7 @@ static int lib_pSetMobjStateNF(lua_State *L)
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
statenum_t state = luaL_checkinteger(L, 2); statenum_t state = luaL_checkinteger(L, 2);
NOHUD NOHUD
INLEVEL
if (!mobj) if (!mobj)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (state >= NUMSTATES) if (state >= NUMSTATES)
@ -1389,6 +1563,7 @@ static int lib_pDoSuperTransformation(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean giverings = lua_optboolean(L, 2); boolean giverings = lua_optboolean(L, 2);
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
P_DoSuperTransformation(player, giverings); P_DoSuperTransformation(player, giverings);
@ -1399,6 +1574,7 @@ static int lib_pExplodeMissile(lua_State *L)
{ {
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_ExplodeMissile(mo); P_ExplodeMissile(mo);
@ -1411,6 +1587,7 @@ static int lib_pPlayerTouchingSectorSpecial(lua_State *L)
INT32 section = (INT32)luaL_checkinteger(L, 2); INT32 section = (INT32)luaL_checkinteger(L, 2);
INT32 number = (INT32)luaL_checkinteger(L, 3); INT32 number = (INT32)luaL_checkinteger(L, 3);
//HUDSAFE //HUDSAFE
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
LUA_PushUserdata(L, P_PlayerTouchingSectorSpecial(player, section, number), META_SECTOR); LUA_PushUserdata(L, P_PlayerTouchingSectorSpecial(player, section, number), META_SECTOR);
@ -1423,6 +1600,7 @@ static int lib_pFindSpecialLineFromTag(lua_State *L)
INT16 line = (INT16)luaL_checkinteger(L, 2); INT16 line = (INT16)luaL_checkinteger(L, 2);
INT32 start = (INT32)luaL_optinteger(L, 3, -1); INT32 start = (INT32)luaL_optinteger(L, 3, -1);
NOHUD NOHUD
INLEVEL
lua_pushinteger(L, P_FindSpecialLineFromTag(special, line, start)); lua_pushinteger(L, P_FindSpecialLineFromTag(special, line, start));
return 1; return 1;
} }
@ -1432,6 +1610,7 @@ static int lib_pSwitchWeather(lua_State *L)
INT32 weathernum = (INT32)luaL_checkinteger(L, 1); INT32 weathernum = (INT32)luaL_checkinteger(L, 1);
player_t *user = NULL; player_t *user = NULL;
NOHUD NOHUD
INLEVEL
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup weather for only the player, otherwise setup weather for all players if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup weather for only the player, otherwise setup weather for all players
user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!user) // global if (!user) // global
@ -1447,6 +1626,7 @@ static int lib_pLinedefExecute(lua_State *L)
mobj_t *actor = NULL; mobj_t *actor = NULL;
sector_t *caller = NULL; sector_t *caller = NULL;
NOHUD NOHUD
INLEVEL
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
@ -1459,6 +1639,7 @@ static int lib_pSpawnLightningFlash(lua_State *L)
{ {
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
NOHUD NOHUD
INLEVEL
if (!sector) if (!sector)
return LUA_ErrInvalid(L, "sector_t"); return LUA_ErrInvalid(L, "sector_t");
P_SpawnLightningFlash(sector); P_SpawnLightningFlash(sector);
@ -1471,6 +1652,7 @@ static int lib_pFadeLight(lua_State *L)
INT32 destvalue = (INT32)luaL_checkinteger(L, 2); INT32 destvalue = (INT32)luaL_checkinteger(L, 2);
INT32 speed = (INT32)luaL_checkinteger(L, 3); INT32 speed = (INT32)luaL_checkinteger(L, 3);
NOHUD NOHUD
INLEVEL
P_FadeLight(tag, destvalue, speed); P_FadeLight(tag, destvalue, speed);
return 0; return 0;
} }
@ -1479,6 +1661,7 @@ static int lib_pThingOnSpecial3DFloor(lua_State *L)
{ {
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!mo) if (!mo)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
LUA_PushUserdata(L, P_ThingOnSpecial3DFloor(mo), META_SECTOR); LUA_PushUserdata(L, P_ThingOnSpecial3DFloor(mo), META_SECTOR);
@ -1489,6 +1672,7 @@ static int lib_pIsFlagAtBase(lua_State *L)
{ {
mobjtype_t flag = luaL_checkinteger(L, 1); mobjtype_t flag = luaL_checkinteger(L, 1);
NOHUD NOHUD
INLEVEL
if (flag >= NUMMOBJTYPES) if (flag >= NUMMOBJTYPES)
return luaL_error(L, "mobj type %d out of range (0 - %d)", flag, NUMMOBJTYPES-1); return luaL_error(L, "mobj type %d out of range (0 - %d)", flag, NUMMOBJTYPES-1);
lua_pushboolean(L, P_IsFlagAtBase(flag)); lua_pushboolean(L, P_IsFlagAtBase(flag));
@ -1500,6 +1684,7 @@ static int lib_pSetupLevelSky(lua_State *L)
INT32 skynum = (INT32)luaL_checkinteger(L, 1); INT32 skynum = (INT32)luaL_checkinteger(L, 1);
player_t *user = NULL; player_t *user = NULL;
NOHUD NOHUD
INLEVEL
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup sky for only the player, otherwise setup sky for all players if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup sky for only the player, otherwise setup sky for all players
user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!user) // global if (!user) // global
@ -1518,6 +1703,7 @@ static int lib_pSetSkyboxMobj(lua_State *L)
int w = 0; int w = 0;
NOHUD NOHUD
INLEVEL
if (!lua_isnil(L,1)) // nil leaves mo as NULL to remove the skybox rendering. if (!lua_isnil(L,1)) // nil leaves mo as NULL to remove the skybox rendering.
{ {
mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); // otherwise it is a skybox mobj. mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); // otherwise it is a skybox mobj.
@ -1564,6 +1750,7 @@ static int lib_pStartQuake(lua_State *L)
static mappoint_t q_epicenter = {0,0,0}; static mappoint_t q_epicenter = {0,0,0};
NOHUD NOHUD
INLEVEL
// While technically we don't support epicenter and radius, // While technically we don't support epicenter and radius,
// we get their values anyway if they exist. // we get their values anyway if they exist.
@ -1625,6 +1812,7 @@ static int lib_evCrumbleChain(lua_State *L)
sector_t *sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); sector_t *sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
NOHUD NOHUD
INLEVEL
if (!sec) if (!sec)
return LUA_ErrInvalid(L, "sector_t"); return LUA_ErrInvalid(L, "sector_t");
if (!rover) if (!rover)
@ -1633,6 +1821,33 @@ static int lib_evCrumbleChain(lua_State *L)
return 0; return 0;
} }
static int lib_evStartCrumble(lua_State *L)
{
sector_t *sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
boolean floating = lua_optboolean(L, 3);
player_t *player = NULL;
fixed_t origalpha;
boolean crumblereturn = lua_optboolean(L, 6);
NOHUD
if (!sec)
return LUA_ErrInvalid(L, "sector_t");
if (!rover)
return LUA_ErrInvalid(L, "ffloor_t");
if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
{
player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER));
if (!player)
return LUA_ErrInvalid(L, "player_t");
}
if (!lua_isnone(L,5))
origalpha = luaL_checkfixed(L, 5);
else
origalpha = rover->alpha;
lua_pushboolean(L, EV_StartCrumble(sec, rover, floating, player, origalpha, crumblereturn) != 0);
return 0;
}
// R_DEFS // R_DEFS
//////////// ////////////
@ -1681,6 +1896,7 @@ static int lib_rPointInSubsector(lua_State *L)
fixed_t x = luaL_checkfixed(L, 1); fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 2);
//HUDSAFE //HUDSAFE
INLEVEL
LUA_PushUserdata(L, R_PointInSubsector(x, y), META_SUBSECTOR); LUA_PushUserdata(L, R_PointInSubsector(x, y), META_SUBSECTOR);
return 1; return 1;
} }
@ -1715,6 +1931,7 @@ static int lib_rSetPlayerSkin(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD NOHUD
INLEVEL
if (!player) if (!player)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
if (lua_isnoneornil(L, 2)) if (lua_isnoneornil(L, 2))
@ -1899,6 +2116,7 @@ static int lib_sOriginPlaying(lua_State *L)
{ {
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD NOHUD
INLEVEL
if (!origin) if (!origin)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, S_OriginPlaying(origin)); lua_pushboolean(L, S_OriginPlaying(origin));
@ -1920,6 +2138,7 @@ static int lib_sSoundPlaying(lua_State *L)
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
sfxenum_t id = luaL_checkinteger(L, 2); sfxenum_t id = luaL_checkinteger(L, 2);
NOHUD NOHUD
INLEVEL
if (!origin) if (!origin)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
if (id >= NUMSFX) if (id >= NUMSFX)
@ -1935,6 +2154,7 @@ static int lib_gBuildMapName(lua_State *L)
{ {
INT32 map = luaL_optinteger(L, 1, gamemap); INT32 map = luaL_optinteger(L, 1, gamemap);
//HUDSAFE //HUDSAFE
INLEVEL
lua_pushstring(L, G_BuildMapName(map)); lua_pushstring(L, G_BuildMapName(map));
return 1; return 1;
} }
@ -1943,6 +2163,7 @@ static int lib_gDoReborn(lua_State *L)
{ {
INT32 playernum = luaL_checkinteger(L, 1); INT32 playernum = luaL_checkinteger(L, 1);
NOHUD NOHUD
INLEVEL
if (playernum >= MAXPLAYERS) if (playernum >= MAXPLAYERS)
return luaL_error(L, "playernum %d out of range (0 - %d)", playernum, MAXPLAYERS-1); return luaL_error(L, "playernum %d out of range (0 - %d)", playernum, MAXPLAYERS-1);
G_DoReborn(playernum); G_DoReborn(playernum);
@ -1953,6 +2174,7 @@ static int lib_gExitLevel(lua_State *L)
{ {
int n = lua_gettop(L); // Num arguments int n = lua_gettop(L); // Num arguments
NOHUD NOHUD
INLEVEL
// LUA EXTENSION: Custom exit like support // LUA EXTENSION: Custom exit like support
// Supported: // Supported:
@ -1979,6 +2201,7 @@ static int lib_gIsSpecialStage(lua_State *L)
{ {
INT32 mapnum = luaL_optinteger(L, 1, gamemap); INT32 mapnum = luaL_optinteger(L, 1, gamemap);
//HUDSAFE //HUDSAFE
INLEVEL
lua_pushboolean(L, G_IsSpecialStage(mapnum)); lua_pushboolean(L, G_IsSpecialStage(mapnum));
return 1; return 1;
} }
@ -1986,6 +2209,7 @@ static int lib_gIsSpecialStage(lua_State *L)
static int lib_gGametypeUsesLives(lua_State *L) static int lib_gGametypeUsesLives(lua_State *L)
{ {
//HUDSAFE //HUDSAFE
INLEVEL
lua_pushboolean(L, G_GametypeUsesLives()); lua_pushboolean(L, G_GametypeUsesLives());
return 1; return 1;
} }
@ -1993,6 +2217,7 @@ static int lib_gGametypeUsesLives(lua_State *L)
static int lib_gGametypeHasTeams(lua_State *L) static int lib_gGametypeHasTeams(lua_State *L)
{ {
//HUDSAFE //HUDSAFE
INLEVEL
lua_pushboolean(L, G_GametypeHasTeams()); lua_pushboolean(L, G_GametypeHasTeams());
return 1; return 1;
} }
@ -2000,6 +2225,7 @@ static int lib_gGametypeHasTeams(lua_State *L)
static int lib_gGametypeHasSpectators(lua_State *L) static int lib_gGametypeHasSpectators(lua_State *L)
{ {
//HUDSAFE //HUDSAFE
INLEVEL
lua_pushboolean(L, G_GametypeHasSpectators()); lua_pushboolean(L, G_GametypeHasSpectators());
return 1; return 1;
} }
@ -2007,6 +2233,7 @@ static int lib_gGametypeHasSpectators(lua_State *L)
static int lib_gRingSlingerGametype(lua_State *L) static int lib_gRingSlingerGametype(lua_State *L)
{ {
//HUDSAFE //HUDSAFE
INLEVEL
lua_pushboolean(L, G_RingSlingerGametype()); lua_pushboolean(L, G_RingSlingerGametype());
return 1; return 1;
} }
@ -2014,6 +2241,7 @@ static int lib_gRingSlingerGametype(lua_State *L)
static int lib_gPlatformGametype(lua_State *L) static int lib_gPlatformGametype(lua_State *L)
{ {
//HUDSAFE //HUDSAFE
INLEVEL
lua_pushboolean(L, G_PlatformGametype()); lua_pushboolean(L, G_PlatformGametype());
return 1; return 1;
} }
@ -2021,6 +2249,7 @@ static int lib_gPlatformGametype(lua_State *L)
static int lib_gTagGametype(lua_State *L) static int lib_gTagGametype(lua_State *L)
{ {
//HUDSAFE //HUDSAFE
INLEVEL
lua_pushboolean(L, G_TagGametype()); lua_pushboolean(L, G_TagGametype());
return 1; return 1;
} }
@ -2068,6 +2297,7 @@ static int lib_gTicsToMilliseconds(lua_State *L)
static luaL_Reg lib[] = { static luaL_Reg lib[] = {
{"print", lib_print}, {"print", lib_print},
{"userdataType", lib_userdataType},
// m_random // m_random
{"P_RandomFixed",lib_pRandomFixed}, {"P_RandomFixed",lib_pRandomFixed},
@ -2203,6 +2433,7 @@ static luaL_Reg lib[] = {
{"P_SetSkyboxMobj",lib_pSetSkyboxMobj}, {"P_SetSkyboxMobj",lib_pSetSkyboxMobj},
{"P_StartQuake",lib_pStartQuake}, {"P_StartQuake",lib_pStartQuake},
{"EV_CrumbleChain",lib_evCrumbleChain}, {"EV_CrumbleChain",lib_evCrumbleChain},
{"EV_StartCrumble",lib_evStartCrumble},
// r_defs // r_defs
{"R_PointToAngle",lib_rPointToAngle}, {"R_PointToAngle",lib_rPointToAngle},

View File

@ -186,6 +186,9 @@ static int lib_searchBlockmap(lua_State *L)
UINT8 funcret = 0; UINT8 funcret = 0;
blockmap_func searchFunc; blockmap_func searchFunc;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
lua_remove(L, 1); // remove searchtype, stack is now function, mobj, [x1, x2, y1, y2] lua_remove(L, 1); // remove searchtype, stack is now function, mobj, [x1, x2, y1, y2]
luaL_checktype(L, 1, LUA_TFUNCTION); luaL_checktype(L, 1, LUA_TFUNCTION);

View File

@ -22,7 +22,10 @@
#include "lua_libs.h" #include "lua_libs.h"
#include "lua_hud.h" // hud_running errors #include "lua_hud.h" // hud_running errors
#define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); #define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
#define INLEVEL if (gamestate != GS_LEVEL)\
return luaL_error(L, "This function can only be used in a level!");
static const char *cvname = NULL; static const char *cvname = NULL;
@ -412,6 +415,7 @@ static int lib_consPrintf(lua_State *L)
if (n < 2) if (n < 2)
return luaL_error(L, "CONS_Printf requires at least two arguments: player and text."); return luaL_error(L, "CONS_Printf requires at least two arguments: player and text.");
//HUDSAFE //HUDSAFE
INLEVEL
plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!plr) if (!plr)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");

View File

@ -45,6 +45,7 @@ enum hook {
hook_PlayerSpawn, hook_PlayerSpawn,
hook_ShieldSpawn, hook_ShieldSpawn,
hook_ShieldSpecial, hook_ShieldSpecial,
hook_MobjMoveBlocked,
hook_MAX // last hook hook_MAX // last hook
}; };
@ -81,5 +82,6 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8
#define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer #define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer
#define LUAh_ShieldSpawn(player) LUAh_PlayerHook(player, hook_ShieldSpawn) // Hook for P_SpawnShieldOrb #define LUAh_ShieldSpawn(player) LUAh_PlayerHook(player, hook_ShieldSpawn) // Hook for P_SpawnShieldOrb
#define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities #define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities
#define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked)
#endif #endif

View File

@ -56,6 +56,7 @@ const char *const hookNames[hook_MAX+1] = {
"PlayerSpawn", "PlayerSpawn",
"ShieldSpawn", "ShieldSpawn",
"ShieldSpecial", "ShieldSpecial",
"MobjMoveBlocked",
NULL NULL
}; };
@ -126,6 +127,7 @@ static int lib_addHook(lua_State *L)
case hook_BossDeath: case hook_BossDeath:
case hook_MobjRemoved: case hook_MobjRemoved:
case hook_HurtMsg: case hook_HurtMsg:
case hook_MobjMoveBlocked:
hook.s.mt = MT_NULL; hook.s.mt = MT_NULL;
if (lua_isnumber(L, 2)) if (lua_isnumber(L, 2))
hook.s.mt = lua_tonumber(L, 2); hook.s.mt = lua_tonumber(L, 2);
@ -184,6 +186,7 @@ static int lib_addHook(lua_State *L)
case hook_MobjDeath: case hook_MobjDeath:
case hook_BossDeath: case hook_BossDeath:
case hook_MobjRemoved: case hook_MobjRemoved:
case hook_MobjMoveBlocked:
lastp = &mobjhooks[hook.s.mt]; lastp = &mobjhooks[hook.s.mt];
break; break;
case hook_JumpSpecial: case hook_JumpSpecial:

View File

@ -264,12 +264,19 @@ static const char *const bbox_opt[] = {
static const char *const array_opt[] ={"iterate",NULL}; static const char *const array_opt[] ={"iterate",NULL};
static const char *const valid_opt[] ={"valid",NULL}; static const char *const valid_opt[] ={"valid",NULL};
///////////////////////////////////
// sector list iterate functions //
///////////////////////////////////
// iterates through a sector's thinglist! // iterates through a sector's thinglist!
static int lib_iterateSectorThinglist(lua_State *L) static int lib_iterateSectorThinglist(lua_State *L)
{ {
mobj_t *state = NULL; mobj_t *state = NULL;
mobj_t *thing = NULL; mobj_t *thing = NULL;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2) if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call sector.thinglist() directly, use it as 'for rover in sector.thinglist do <block> end'."); return luaL_error(L, "Don't call sector.thinglist() directly, use it as 'for rover in sector.thinglist do <block> end'.");
@ -303,6 +310,9 @@ static int lib_iterateSectorFFloors(lua_State *L)
ffloor_t *state = NULL; ffloor_t *state = NULL;
ffloor_t *ffloor = NULL; ffloor_t *ffloor = NULL;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2) if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call sector.ffloors() directly, use it as 'for rover in sector.ffloors do <block> end'."); return luaL_error(L, "Don't call sector.ffloors() directly, use it as 'for rover in sector.ffloors do <block> end'.");
@ -338,6 +348,10 @@ static int sector_iterate(lua_State *L)
return 3; return 3;
} }
////////////////////
// sector.lines[] //
////////////////////
// sector.lines, i -> sector.lines[i] // sector.lines, i -> sector.lines[i]
// sector.lines.valid, for validity checking // sector.lines.valid, for validity checking
static int sectorlines_get(lua_State *L) static int sectorlines_get(lua_State *L)
@ -399,6 +413,10 @@ static int sectorlines_num(lua_State *L)
return 1; return 1;
} }
//////////////
// sector_t //
//////////////
static int sector_get(lua_State *L) static int sector_get(lua_State *L)
{ {
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
@ -540,6 +558,10 @@ static int sector_num(lua_State *L)
return 1; return 1;
} }
/////////////////
// subsector_t //
/////////////////
static int subsector_get(lua_State *L) static int subsector_get(lua_State *L)
{ {
subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR)); subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR));
@ -579,6 +601,10 @@ static int subsector_num(lua_State *L)
return 1; return 1;
} }
////////////
// line_t //
////////////
static int line_get(lua_State *L) static int line_get(lua_State *L)
{ {
line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE)); line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE));
@ -676,6 +702,10 @@ static int line_num(lua_State *L)
return 1; return 1;
} }
////////////////////
// line.sidenum[] //
////////////////////
static int sidenum_get(lua_State *L) static int sidenum_get(lua_State *L)
{ {
UINT16 *sidenum = *((UINT16 **)luaL_checkudata(L, 1, META_SIDENUM)); UINT16 *sidenum = *((UINT16 **)luaL_checkudata(L, 1, META_SIDENUM));
@ -704,6 +734,10 @@ static int sidenum_get(lua_State *L)
return 1; return 1;
} }
////////////
// side_t //
////////////
static int side_get(lua_State *L) static int side_get(lua_State *L)
{ {
side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE)); side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE));
@ -805,6 +839,10 @@ static int side_num(lua_State *L)
return 1; return 1;
} }
//////////////
// vertex_t //
//////////////
static int vertex_get(lua_State *L) static int vertex_get(lua_State *L)
{ {
vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX)); vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX));
@ -845,6 +883,11 @@ static int vertex_num(lua_State *L)
} }
#ifdef HAVE_LUA_SEGS #ifdef HAVE_LUA_SEGS
///////////
// seg_t //
///////////
static int seg_get(lua_State *L) static int seg_get(lua_State *L)
{ {
seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG)); seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG));
@ -902,6 +945,10 @@ static int seg_num(lua_State *L)
return 1; return 1;
} }
////////////
// node_t //
////////////
static int node_get(lua_State *L) static int node_get(lua_State *L)
{ {
node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE)); node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE));
@ -949,6 +996,11 @@ static int node_num(lua_State *L)
lua_pushinteger(L, node-nodes); lua_pushinteger(L, node-nodes);
return 1; return 1;
} }
///////////////
// node.bbox //
///////////////
/* /*
// node.bbox[i][j]: i = 0 or 1, j = 0 1 2 or 3 // node.bbox[i][j]: i = 0 or 1, j = 0 1 2 or 3
// NOTE: 2D arrays are NOT double pointers, // NOTE: 2D arrays are NOT double pointers,
@ -1028,6 +1080,10 @@ static int nodebbox_call(lua_State *L)
return 1; return 1;
} }
/////////////////////
// node.children[] //
/////////////////////
// node.children[i]: i = 0 or 1 // node.children[i]: i = 0 or 1
static int nodechildren_get(lua_State *L) static int nodechildren_get(lua_State *L)
{ {
@ -1063,6 +1119,10 @@ static int nodechildren_get(lua_State *L)
} }
#endif #endif
//////////
// bbox //
//////////
// bounding box (aka fixed_t array with four elements) // bounding box (aka fixed_t array with four elements)
// NOTE: may be useful for polyobjects or other things later // NOTE: may be useful for polyobjects or other things later
static int bbox_get(lua_State *L) static int bbox_get(lua_State *L)
@ -1100,9 +1160,15 @@ static int bbox_get(lua_State *L)
return 1; return 1;
} }
///////////////
// sectors[] //
///////////////
static int lib_iterateSectors(lua_State *L) static int lib_iterateSectors(lua_State *L)
{ {
size_t i = 0; size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2) if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call sectors.iterate() directly, use it as 'for sector in sectors.iterate do <block> end'."); return luaL_error(L, "Don't call sectors.iterate() directly, use it as 'for sector in sectors.iterate do <block> end'.");
lua_settop(L, 2); lua_settop(L, 2);
@ -1120,6 +1186,8 @@ static int lib_iterateSectors(lua_State *L)
static int lib_getSector(lua_State *L) static int lib_getSector(lua_State *L)
{ {
int field; int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2); lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused. lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1)) if (lua_isnumber(L, 1))
@ -1146,9 +1214,15 @@ static int lib_numsectors(lua_State *L)
return 1; return 1;
} }
//////////////////
// subsectors[] //
//////////////////
static int lib_iterateSubsectors(lua_State *L) static int lib_iterateSubsectors(lua_State *L)
{ {
size_t i = 0; size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2) if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call subsectors.iterate() directly, use it as 'for subsector in subsectors.iterate do <block> end'."); return luaL_error(L, "Don't call subsectors.iterate() directly, use it as 'for subsector in subsectors.iterate do <block> end'.");
lua_settop(L, 2); lua_settop(L, 2);
@ -1166,6 +1240,8 @@ static int lib_iterateSubsectors(lua_State *L)
static int lib_getSubsector(lua_State *L) static int lib_getSubsector(lua_State *L)
{ {
int field; int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2); lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused. lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1)) if (lua_isnumber(L, 1))
@ -1192,9 +1268,15 @@ static int lib_numsubsectors(lua_State *L)
return 1; return 1;
} }
/////////////
// lines[] //
/////////////
static int lib_iterateLines(lua_State *L) static int lib_iterateLines(lua_State *L)
{ {
size_t i = 0; size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2) if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call lines.iterate() directly, use it as 'for line in lines.iterate do <block> end'."); return luaL_error(L, "Don't call lines.iterate() directly, use it as 'for line in lines.iterate do <block> end'.");
lua_settop(L, 2); lua_settop(L, 2);
@ -1212,6 +1294,8 @@ static int lib_iterateLines(lua_State *L)
static int lib_getLine(lua_State *L) static int lib_getLine(lua_State *L)
{ {
int field; int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2); lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused. lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1)) if (lua_isnumber(L, 1))
@ -1238,9 +1322,15 @@ static int lib_numlines(lua_State *L)
return 1; return 1;
} }
/////////////
// sides[] //
/////////////
static int lib_iterateSides(lua_State *L) static int lib_iterateSides(lua_State *L)
{ {
size_t i = 0; size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2) if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call sides.iterate() directly, use it as 'for side in sides.iterate do <block> end'."); return luaL_error(L, "Don't call sides.iterate() directly, use it as 'for side in sides.iterate do <block> end'.");
lua_settop(L, 2); lua_settop(L, 2);
@ -1258,6 +1348,8 @@ static int lib_iterateSides(lua_State *L)
static int lib_getSide(lua_State *L) static int lib_getSide(lua_State *L)
{ {
int field; int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2); lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused. lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1)) if (lua_isnumber(L, 1))
@ -1284,9 +1376,15 @@ static int lib_numsides(lua_State *L)
return 1; return 1;
} }
////////////////
// vertexes[] //
////////////////
static int lib_iterateVertexes(lua_State *L) static int lib_iterateVertexes(lua_State *L)
{ {
size_t i = 0; size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2) if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call vertexes.iterate() directly, use it as 'for vertex in vertexes.iterate do <block> end'."); return luaL_error(L, "Don't call vertexes.iterate() directly, use it as 'for vertex in vertexes.iterate do <block> end'.");
lua_settop(L, 2); lua_settop(L, 2);
@ -1304,6 +1402,8 @@ static int lib_iterateVertexes(lua_State *L)
static int lib_getVertex(lua_State *L) static int lib_getVertex(lua_State *L)
{ {
int field; int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2); lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused. lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1)) if (lua_isnumber(L, 1))
@ -1331,9 +1431,16 @@ static int lib_numvertexes(lua_State *L)
} }
#ifdef HAVE_LUA_SEGS #ifdef HAVE_LUA_SEGS
////////////
// segs[] //
////////////
static int lib_iterateSegs(lua_State *L) static int lib_iterateSegs(lua_State *L)
{ {
size_t i = 0; size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2) if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do <block> end'."); return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do <block> end'.");
lua_settop(L, 2); lua_settop(L, 2);
@ -1351,6 +1458,8 @@ static int lib_iterateSegs(lua_State *L)
static int lib_getSeg(lua_State *L) static int lib_getSeg(lua_State *L)
{ {
int field; int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2); lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused. lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1)) if (lua_isnumber(L, 1))
@ -1377,9 +1486,15 @@ static int lib_numsegs(lua_State *L)
return 1; return 1;
} }
/////////////
// nodes[] //
/////////////
static int lib_iterateNodes(lua_State *L) static int lib_iterateNodes(lua_State *L)
{ {
size_t i = 0; size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2) if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do <block> end'."); return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do <block> end'.");
lua_settop(L, 2); lua_settop(L, 2);
@ -1397,6 +1512,8 @@ static int lib_iterateNodes(lua_State *L)
static int lib_getNode(lua_State *L) static int lib_getNode(lua_State *L)
{ {
int field; int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2); lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused. lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1)) if (lua_isnumber(L, 1))
@ -1424,6 +1541,10 @@ static int lib_numnodes(lua_State *L)
} }
#endif #endif
//////////////
// ffloor_t //
//////////////
static int ffloor_get(lua_State *L) static int ffloor_get(lua_State *L)
{ {
ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
@ -1567,6 +1688,10 @@ static int ffloor_set(lua_State *L)
return 0; return 0;
} }
/////////////////////
// mapheaderinfo[] //
/////////////////////
static int lib_getMapheaderinfo(lua_State *L) static int lib_getMapheaderinfo(lua_State *L)
{ {
// i -> mapheaderinfo[i-1] // i -> mapheaderinfo[i-1]
@ -1599,6 +1724,10 @@ static int lib_nummapheaders(lua_State *L)
return 1; return 1;
} }
/////////////////
// mapheader_t //
/////////////////
static int mapheaderinfo_get(lua_State *L) static int mapheaderinfo_get(lua_State *L)
{ {
mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER)); mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER));

View File

@ -751,6 +751,8 @@ static int mapthing_set(lua_State *L)
static int lib_iterateMapthings(lua_State *L) static int lib_iterateMapthings(lua_State *L)
{ {
size_t i = 0; size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2) if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call mapthings.iterate() directly, use it as 'for mapthing in mapthings.iterate do <block> end'."); return luaL_error(L, "Don't call mapthings.iterate() directly, use it as 'for mapthing in mapthings.iterate do <block> end'.");
lua_settop(L, 2); lua_settop(L, 2);
@ -768,6 +770,8 @@ static int lib_iterateMapthings(lua_State *L)
static int lib_getMapthing(lua_State *L) static int lib_getMapthing(lua_State *L)
{ {
int field; int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2); lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused. lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1)) if (lua_isnumber(L, 1))

View File

@ -25,6 +25,8 @@
static int lib_iteratePlayers(lua_State *L) static int lib_iteratePlayers(lua_State *L)
{ {
INT32 i = -1; INT32 i = -1;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2) if (lua_gettop(L) < 2)
{ {
//return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do <block> end'."); //return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do <block> end'.");
@ -51,6 +53,8 @@ static int lib_getPlayer(lua_State *L)
{ {
const char *field; const char *field;
// i -> players[i] // i -> players[i]
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
if (lua_type(L, 2) == LUA_TNUMBER) if (lua_type(L, 2) == LUA_TNUMBER)
{ {
lua_Integer i = luaL_checkinteger(L, 2); lua_Integer i = luaL_checkinteger(L, 2);

View File

@ -29,6 +29,9 @@ static int lib_iterateThinkers(lua_State *L)
actionf_p1 searchFunc; actionf_p1 searchFunc;
const char *searchMeta; const char *searchMeta;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
lua_settop(L, 2); lua_settop(L, 2);
lua_remove(L, 1); // remove state now. lua_remove(L, 1); // remove state now.
@ -84,6 +87,8 @@ static int lib_iterateThinkers(lua_State *L)
static int lib_startIterate(lua_State *L) static int lib_startIterate(lua_State *L)
{ {
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
luaL_checkoption(L, 1, iter_opt[0], iter_opt); luaL_checkoption(L, 1, iter_opt[0], iter_opt);
lua_pushcfunction(L, lib_iterateThinkers); lua_pushcfunction(L, lib_iterateThinkers);
lua_pushvalue(L, 1); lua_pushvalue(L, 1);

View File

@ -252,6 +252,7 @@ void A_FlickyFlounder(mobj_t *actor);
void A_FlickyCheck(mobj_t *actor); void A_FlickyCheck(mobj_t *actor);
void A_FlickyHeightCheck(mobj_t *actor); void A_FlickyHeightCheck(mobj_t *actor);
void A_FlickyFlutter(mobj_t *actor); void A_FlickyFlutter(mobj_t *actor);
void A_FlameParticle(mobj_t *actor);
// //
// ENEMY THINKING // ENEMY THINKING
@ -2134,13 +2135,15 @@ void A_Boss1Laser(mobj_t *actor)
if (!(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) if (!(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH))
{ {
point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET); point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET);
point->angle = actor->angle;
point->fuse = actor->tics+1; point->fuse = actor->tics+1;
P_SetTarget(&point->target, actor->target); P_SetTarget(&point->target, actor->target);
P_SetTarget(&actor->target, point); P_SetTarget(&actor->target, point);
} }
} }
/* -- the following was relevant when the MT_EGGMOBILE_TARGET was allowed to move left and right from its path
else if (actor->target && !(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) else if (actor->target && !(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH))
actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y); actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y);*/
if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH) if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)
angle = FixedAngle(FixedDiv(actor->tics*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT); angle = FixedAngle(FixedDiv(actor->tics*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT);
@ -2190,11 +2193,16 @@ void A_Boss1Laser(mobj_t *actor)
// var1: // var1:
// 0 - accelerative focus with friction // 0 - accelerative focus with friction
// 1 - steady focus with fixed movement speed // 1 - steady focus with fixed movement speed
// var2 = unused // anything else - don't move
// var2:
// 0 - don't trace target, just move forwards
// & 1 - change horizontal angle
// & 2 - change vertical angle
// //
void A_FocusTarget(mobj_t *actor) void A_FocusTarget(mobj_t *actor)
{ {
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_CallAction("A_FocusTarget", actor)) if (LUA_CallAction("A_FocusTarget", actor))
return; return;
@ -2203,9 +2211,9 @@ void A_FocusTarget(mobj_t *actor)
if (actor->target) if (actor->target)
{ {
fixed_t speed = FixedMul(actor->info->speed, actor->scale); fixed_t speed = FixedMul(actor->info->speed, actor->scale);
fixed_t dist = R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y); fixed_t dist = (locvar2 ? R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y) : speed+1);
angle_t vangle = R_PointToAngle2(actor->z , 0, actor->target->z + (actor->target->height>>1), dist); angle_t hangle = ((locvar2 & 1) ? R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) : actor->angle);
angle_t hangle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); angle_t vangle = ((locvar2 & 2) ? R_PointToAngle2(actor->z , 0, actor->target->z + (actor->target->height>>1), dist) : ANGLE_90);
switch(locvar1) switch(locvar1)
{ {
case 0: case 0:
@ -3534,41 +3542,49 @@ void A_ScoreRise(mobj_t *actor)
// Function: A_ParticleSpawn // Function: A_ParticleSpawn
// //
// Description: Spawns a particle at a specified interval // Description: Hyper-specialised function for spawning a particle for MT_PARTICLEGEN.
// //
// var1 = type (if 0, defaults to MT_PARTICLE) // var1 = unused
// var2 = unused // var2 = unused
// //
void A_ParticleSpawn(mobj_t *actor) void A_ParticleSpawn(mobj_t *actor)
{ {
INT32 locvar1 = var1; INT32 i = 0;
fixed_t speed;
mobjtype_t type;
mobj_t *spawn; mobj_t *spawn;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_CallAction("A_ParticleSpawn", actor)) if (LUA_CallAction("A_ParticleSpawn", actor))
return; return;
#endif #endif
if (!actor->spawnpoint) if (!actor->health)
{
P_RemoveMobj(actor);
return; return;
if (!actor->lastlook)
return;
if (!actor->threshold)
return;
for (i = 0; i < actor->lastlook; i++)
{
spawn = P_SpawnMobj(
actor->x + FixedMul(FixedMul(actor->friction, actor->scale), FINECOSINE(actor->angle>>ANGLETOFINESHIFT)),
actor->y + FixedMul(FixedMul(actor->friction, actor->scale), FINESINE(actor->angle>>ANGLETOFINESHIFT)),
actor->z,
(mobjtype_t)actor->threshold);
P_SetScale(spawn, actor->scale);
spawn->momz = FixedMul(actor->movefactor, spawn->scale);
spawn->destscale = spawn->scale/100;
spawn->scalespeed = spawn->scale/actor->health;
spawn->tics = (tic_t)actor->health;
spawn->flags2 |= (actor->flags2 & MF2_OBJECTFLIP);
spawn->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones
if (spawn->frame & FF_ANIMATE)
spawn->frame += P_RandomKey(spawn->state->var1);
actor->angle += actor->movedir;
} }
actor->angle += (angle_t)actor->movecount;
if (locvar1)
type = (mobjtype_t)locvar1;
else
type = MT_PARTICLE;
speed = FixedMul((actor->spawnpoint->angle >> 12)<<FRACBITS, actor->scale);
spawn = P_SpawnMobj(actor->x, actor->y, actor->z, type);
P_SetScale(spawn, actor->scale);
spawn->momz = speed;
spawn->destscale = FixedDiv(spawn->scale<<FRACBITS, 100<<FRACBITS);
spawn->scalespeed = FixedDiv(((actor->spawnpoint->angle >> 8) & 63) << FRACBITS, 100<<FRACBITS);
actor->tics = actor->spawnpoint->extrainfo + 1;
} }
// Function: A_BunnyHop // Function: A_BunnyHop
@ -3882,11 +3898,18 @@ void A_DropMine(mobj_t *actor)
void A_FishJump(mobj_t *actor) void A_FishJump(mobj_t *actor)
{ {
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_CallAction("A_FishJump", actor)) if (LUA_CallAction("A_FishJump", actor))
return; return;
#endif #endif
if (locvar2)
{
fixed_t rad = actor->radius>>FRACBITS;
P_SpawnMobjFromMobj(actor, P_RandomRange(rad, -rad)<<FRACBITS, P_RandomRange(rad, -rad)<<FRACBITS, 0, (mobjtype_t)locvar2);
}
if ((actor->z <= actor->floorz) || (actor->z <= actor->watertop - FixedMul((64 << FRACBITS), actor->scale))) if ((actor->z <= actor->floorz) || (actor->z <= actor->watertop - FixedMul((64 << FRACBITS), actor->scale)))
{ {
fixed_t jumpval; fixed_t jumpval;
@ -9623,14 +9646,19 @@ void A_HomingChase(mobj_t *actor)
// lower 16 bits = object # to fire // lower 16 bits = object # to fire
// upper 16 bits = front offset // upper 16 bits = front offset
// var2: // var2:
// lower 16 bits = vertical angle // lower 15 bits = vertical angle variable
// 16th bit:
// - 0: use vertical angle variable as vertical angle in degrees
// - 1: mimic P_SpawnXYZMissile
// use z of actor minus z of missile as vertical distance to cover during momz calculation
// use vertical angle variable as horizontal distance to cover during momz calculation
// upper 16 bits = height offset // upper 16 bits = height offset
// //
void A_TrapShot(mobj_t *actor) void A_TrapShot(mobj_t *actor)
{ {
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
angle_t vertang = FixedAngle(((INT16)(locvar2 & 65535))*FRACUNIT); boolean oldstyle = (locvar2 & 32768) ? true : false;
mobjtype_t type = (mobjtype_t)(locvar1 & 65535); mobjtype_t type = (mobjtype_t)(locvar1 & 65535);
mobj_t *missile; mobj_t *missile;
INT16 frontoff = (INT16)(locvar1 >> 16); INT16 frontoff = (INT16)(locvar1 >> 16);
@ -9646,10 +9674,7 @@ void A_TrapShot(mobj_t *actor)
y = actor->y + P_ReturnThrustY(actor, actor->angle, FixedMul(frontoff*FRACUNIT, actor->scale)); y = actor->y + P_ReturnThrustY(actor, actor->angle, FixedMul(frontoff*FRACUNIT, actor->scale));
if (actor->eflags & MFE_VERTICALFLIP) if (actor->eflags & MFE_VERTICALFLIP)
{
z = actor->z + actor->height - FixedMul(vertoff*FRACUNIT, actor->scale) - FixedMul(mobjinfo[type].height, actor->scale); z = actor->z + actor->height - FixedMul(vertoff*FRACUNIT, actor->scale) - FixedMul(mobjinfo[type].height, actor->scale);
vertang = InvAngle(vertang); // flip firing angle
}
else else
z = actor->z + FixedMul(vertoff*FRACUNIT, actor->scale); z = actor->z + FixedMul(vertoff*FRACUNIT, actor->scale);
@ -9660,20 +9685,35 @@ void A_TrapShot(mobj_t *actor)
if (actor->eflags & MFE_VERTICALFLIP) if (actor->eflags & MFE_VERTICALFLIP)
missile->flags2 |= MF2_OBJECTFLIP; missile->flags2 |= MF2_OBJECTFLIP;
missile->destscale = actor->destscale;
P_SetScale(missile, missile->destscale); missile->destscale = actor->scale;
P_SetScale(missile, actor->scale);
if (missile->info->seesound) if (missile->info->seesound)
S_StartSound(actor, missile->info->seesound); S_StartSound(missile, missile->info->seesound);
P_SetTarget(&missile->target, actor); P_SetTarget(&missile->target, actor);
missile->angle = actor->angle; missile->angle = actor->angle;
speed = FixedMul(missile->info->speed, missile->scale); speed = FixedMul(missile->info->speed, missile->scale);
missile->momx = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed)); if (oldstyle)
missile->momy = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed)); {
missile->momz = FixedMul(FINESINE(vertang>>ANGLETOFINESHIFT), speed); missile->momx = FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed);
missile->momy = FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed);
// The below line basically mimics P_SpawnXYZMissile's momz calculation.
missile->momz = (actor->z + ((actor->eflags & MFE_VERTICALFLIP) ? actor->height : 0) - z) / ((fixed_t)(locvar2 & 32767)*FRACUNIT / speed);
P_CheckMissileSpawn(missile);
}
else
{
angle_t vertang = FixedAngle(((INT16)(locvar2 & 32767))*FRACUNIT);
if (actor->eflags & MFE_VERTICALFLIP)
vertang = InvAngle(vertang); // flip firing angle
missile->momx = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed));
missile->momy = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed));
missile->momz = FixedMul(FINESINE(vertang>>ANGLETOFINESHIFT), speed);
}
} }
// Function: A_VileTarget // Function: A_VileTarget
@ -10735,3 +10775,32 @@ void A_FlickyFlutter(mobj_t *actor)
} }
#undef FLICKYHITWALL #undef FLICKYHITWALL
// Function: A_FlameParticle
//
// Description: Creates the mobj's painchance at a random position around the object's radius.
//
// var1 = momz of particle.
//
void A_FlameParticle(mobj_t *actor)
{
mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance);
INT32 locvar1 = var1;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FlameParticle", actor))
return;
#endif
if (type)
{
fixed_t rad = 2*actor->radius>>FRACBITS;
fixed_t hei = actor->height>>FRACBITS;
mobj_t *particle = P_SpawnMobjFromMobj(actor,
P_RandomRange(rad, -rad)<<FRACBITS,
P_RandomRange(rad, -rad)<<FRACBITS,
P_RandomRange(hei/2, hei)<<FRACBITS,
type);
P_SetObjectMomZ(particle, locvar1<<FRACBITS, false);
}
}

View File

@ -13,7 +13,11 @@
#include "doomdef.h" #include "doomdef.h"
#include "doomstat.h" #include "doomstat.h"
#include "m_random.h"
#include "p_local.h" #include "p_local.h"
#ifdef ESLOPE
#include "p_slopes.h"
#endif
#include "r_state.h" #include "r_state.h"
#include "s_sound.h" #include "s_sound.h"
#include "z_zone.h" #include "z_zone.h"
@ -1141,6 +1145,7 @@ void T_MarioBlock(levelspecthink_t *block)
block->sector->ceilingdata = NULL; block->sector->ceilingdata = NULL;
block->sector->floorspeed = 0; block->sector->floorspeed = 0;
block->sector->ceilspeed = 0; block->sector->ceilspeed = 0;
block->direction = 0;
} }
for (i = -1; (i = P_FindSectorFromTag((INT16)block->vars[0], i)) >= 0 ;) for (i = -1; (i = P_FindSectorFromTag((INT16)block->vars[0], i)) >= 0 ;)
@ -1800,10 +1805,24 @@ static mobj_t *SearchMarioNode(msecnode_t *node)
void T_MarioBlockChecker(levelspecthink_t *block) void T_MarioBlockChecker(levelspecthink_t *block)
{ {
line_t *masterline = block->sourceline; line_t *masterline = block->sourceline;
if (block->vars[2] == 1) // Don't update the textures when the block's being bumped upwards.
return;
if (SearchMarioNode(block->sector->touching_thinglist)) if (SearchMarioNode(block->sector->touching_thinglist))
sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].bottomtexture; {
sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].bottomtexture; // Update textures
if (masterline->backsector)
{
block->sector->ceilingpic = block->sector->floorpic = masterline->backsector->ceilingpic; // Update flats to be backside's ceiling
}
}
else else
{
sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].toptexture; sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].toptexture;
if (masterline->backsector)
{
block->sector->ceilingpic = block->sector->floorpic = masterline->backsector->floorpic; // Update flats to be backside's floor
}
}
} }
// This is the Thwomp's 'brain'. It looks around for players nearby, and if // This is the Thwomp's 'brain'. It looks around for players nearby, and if
@ -2523,6 +2542,29 @@ void T_CameraScanner(elevator_t *elevator)
} }
} }
void T_PlaneDisplace(planedisplace_t *pd)
{
sector_t *control, *target;
INT32 direction;
fixed_t diff;
control = &sectors[pd->control];
target = &sectors[pd->affectee];
if (control->floorheight == pd->last_height)
return; // no change, no movement
direction = (control->floorheight > pd->last_height) ? 1 : -1;
diff = FixedMul(control->floorheight-pd->last_height, pd->speed);
if (pd->type == pd_floor || pd->type == pd_both)
T_MovePlane(target, INT32_MAX/2, target->floorheight+diff, 0, 0, direction); // move floor
if (pd->type == pd_ceiling || pd->type == pd_both)
T_MovePlane(target, INT32_MAX/2, target->ceilingheight+diff, 0, 1, direction); // move ceiling
pd->last_height = control->floorheight;
}
// //
// EV_DoFloor // EV_DoFloor
// //
@ -2880,18 +2922,41 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
size_t topmostvertex = 0, bottommostvertex = 0; size_t topmostvertex = 0, bottommostvertex = 0;
fixed_t leftx, rightx; fixed_t leftx, rightx;
fixed_t topy, bottomy; fixed_t topy, bottomy;
fixed_t topz; fixed_t topz, bottomz;
fixed_t widthfactor, heightfactor;
fixed_t a, b, c; fixed_t a, b, c;
mobjtype_t type = MT_ROCKCRUMBLE1; mobjtype_t type = MT_ROCKCRUMBLE1;
fixed_t spacing = (32<<FRACBITS);
tic_t lifetime = 3*TICRATE;
INT16 flags = 0;
// If the control sector has a special #define controlsec rover->master->frontsector
// of Section3:7-15, use the custom debris.
if (GETSECSPECIAL(rover->master->frontsector->special, 3) >= 8) if (controlsec->tag != 0)
type = MT_ROCKCRUMBLE1+(GETSECSPECIAL(rover->master->frontsector->special, 3)-7); {
INT32 tagline = P_FindSpecialLineFromTag(14, controlsec->tag, -1);
if (tagline != -1)
{
if (sides[lines[tagline].sidenum[0]].toptexture)
type = (mobjtype_t)sides[lines[tagline].sidenum[0]].toptexture; // Set as object type in p_setup.c...
if (sides[lines[tagline].sidenum[0]].textureoffset)
spacing = sides[lines[tagline].sidenum[0]].textureoffset;
if (sides[lines[tagline].sidenum[0]].rowoffset)
{
if (sides[lines[tagline].sidenum[0]].rowoffset>>FRACBITS != -1)
lifetime = (sides[lines[tagline].sidenum[0]].rowoffset>>FRACBITS);
else
lifetime = 0;
}
flags = lines[tagline].flags;
}
}
#undef controlsec
// soundorg z height never gets set normally, so MEH. // soundorg z height never gets set normally, so MEH.
sec->soundorg.z = sec->floorheight; sec->soundorg.z = sec->floorheight;
S_StartSound(&sec->soundorg, sfx_crumbl); S_StartSound(&sec->soundorg, mobjinfo[type].activesound);
// Find the outermost vertexes in the subsector // Find the outermost vertexes in the subsector
for (i = 0; i < sec->linecount; i++) for (i = 0; i < sec->linecount; i++)
@ -2910,23 +2975,46 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
bottommostvertex = i; bottommostvertex = i;
} }
leftx = sec->lines[leftmostvertex]->v1->x+(16<<FRACBITS); leftx = sec->lines[leftmostvertex]->v1->x+(spacing>>1);
rightx = sec->lines[rightmostvertex]->v1->x; rightx = sec->lines[rightmostvertex]->v1->x;
topy = sec->lines[topmostvertex]->v1->y-(16<<FRACBITS); topy = sec->lines[topmostvertex]->v1->y-(spacing>>1);
bottomy = sec->lines[bottommostvertex]->v1->y; bottomy = sec->lines[bottommostvertex]->v1->y;
topz = *rover->topheight-(16<<FRACBITS);
for (a = leftx; a < rightx; a += (32<<FRACBITS)) topz = *rover->topheight-(spacing>>1);
bottomz = *rover->bottomheight;
if (flags & ML_EFFECT1)
{ {
for (b = topy; b > bottomy; b -= (32<<FRACBITS)) widthfactor = (rightx + topy - leftx - bottomy)>>3;
heightfactor = (topz - *rover->bottomheight)>>2;
}
for (a = leftx; a < rightx; a += spacing)
{
for (b = topy; b > bottomy; b -= spacing)
{ {
if (R_PointInSubsector(a, b)->sector == sec) if (R_PointInSubsector(a, b)->sector == sec)
{ {
mobj_t *spawned = NULL; mobj_t *spawned = NULL;
for (c = topz; c > *rover->bottomheight; c -= (32<<FRACBITS)) #ifdef ESLOPE
if (*rover->t_slope)
topz = P_GetZAt(*rover->t_slope, a, b) - (spacing>>1);
if (*rover->b_slope)
bottomz = P_GetZAt(*rover->b_slope, a, b);
#endif
for (c = topz; c > bottomz; c -= spacing)
{ {
spawned = P_SpawnMobj(a, b, c, type); spawned = P_SpawnMobj(a, b, c, type);
spawned->fuse = 3*TICRATE; spawned->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones
if (flags & ML_EFFECT1)
{
P_InstaThrust(spawned, R_PointToAngle2(sec->soundorg.x, sec->soundorg.y, a, b), FixedDiv(P_AproxDistance(a - sec->soundorg.x, b - sec->soundorg.y), widthfactor));
P_SetObjectMomZ(spawned, FixedDiv((c - bottomz), heightfactor), false);
}
spawned->fuse = lifetime;
} }
} }
} }
@ -3086,8 +3174,10 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
return 1; return 1;
} }
INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mobj_t *puncher) INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
{ {
sector_t *roversec = rover->master->frontsector;
fixed_t topheight = *rover->topheight;
levelspecthink_t *block; levelspecthink_t *block;
mobj_t *thing; mobj_t *thing;
fixed_t oldx = 0, oldy = 0, oldz = 0; fixed_t oldx = 0, oldy = 0, oldz = 0;
@ -3095,11 +3185,14 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
I_Assert(puncher != NULL); I_Assert(puncher != NULL);
I_Assert(puncher->player != NULL); I_Assert(puncher->player != NULL);
if (sec->floordata || sec->ceilingdata) if (roversec->floordata || roversec->ceilingdata)
return 0; return 0;
if (!(rover->flags & FF_SOLID))
rover->flags |= (FF_SOLID|FF_RENDERALL|FF_CUTLEVEL);
// Find an item to pop out! // Find an item to pop out!
thing = SearchMarioNode(sec->touching_thinglist); thing = SearchMarioNode(roversec->touching_thinglist);
// Found something! // Found something!
if (thing) if (thing)
@ -3109,13 +3202,13 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL);
P_AddThinker(&block->thinker); P_AddThinker(&block->thinker);
sec->floordata = block; roversec->floordata = block;
sec->ceilingdata = block; roversec->ceilingdata = block;
block->thinker.function.acp1 = (actionf_p1)T_MarioBlock; block->thinker.function.acp1 = (actionf_p1)T_MarioBlock;
// Set up the fields // Set up the fields
block->sector = sec; block->sector = roversec;
block->vars[0] = roversector->tag; // actionsector block->vars[0] = sector->tag; // actionsector
block->vars[1] = 4*FRACUNIT; // speed block->vars[1] = 4*FRACUNIT; // speed
block->vars[2] = 1; // Up // direction block->vars[2] = 1; // Up // direction
block->vars[3] = block->sector->floorheight; // floorwasheight block->vars[3] = block->sector->floorheight; // floorwasheight
@ -3131,8 +3224,8 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
} }
P_UnsetThingPosition(thing); P_UnsetThingPosition(thing);
thing->x = roversector->soundorg.x; thing->x = sector->soundorg.x;
thing->y = roversector->soundorg.y; thing->y = sector->soundorg.y;
thing->z = topheight; thing->z = topheight;
thing->momz = FixedMul(6*FRACUNIT, thing->scale); thing->momz = FixedMul(6*FRACUNIT, thing->scale);
P_SetThingPosition(thing); P_SetThingPosition(thing);
@ -3149,7 +3242,7 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
{ {
if (thing->type == MT_EMMY && thing->spawnpoint && (thing->spawnpoint->options & MTF_OBJECTSPECIAL)) if (thing->type == MT_EMMY && thing->spawnpoint && (thing->spawnpoint->options & MTF_OBJECTSPECIAL))
{ {
mobj_t *tokenobj = P_SpawnMobj(roversector->soundorg.x, roversector->soundorg.y, topheight, MT_TOKEN); mobj_t *tokenobj = P_SpawnMobj(sector->soundorg.x, sector->soundorg.y, topheight, MT_TOKEN);
P_SetTarget(&thing->tracer, tokenobj); P_SetTarget(&thing->tracer, tokenobj);
P_SetTarget(&tokenobj->target, thing); P_SetTarget(&tokenobj->target, thing);
P_SetMobjState(tokenobj, mobjinfo[MT_TOKEN].seestate); P_SetMobjState(tokenobj, mobjinfo[MT_TOKEN].seestate);

View File

@ -1174,15 +1174,33 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Mario // // Mario //
// ***** // // ***** //
case MT_SHELL: case MT_SHELL:
if (special->state == &states[S_SHELL]) // Resting anim
{ {
// Kick that sucker around! boolean bounceon = ((P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0));
special->angle = toucher->angle; if (special->threshold == TICRATE) // it's moving
P_InstaThrust(special, special->angle, FixedMul(special->info->speed, special->scale)); {
S_StartSound(toucher, sfx_mario2); if (bounceon)
P_SetMobjState(special, S_SHELL1); {
P_SetTarget(&special->target, toucher); // Stop it!
special->threshold = (3*TICRATE)/2; special->momx = special->momy = 0;
S_StartSound(toucher, sfx_mario2);
P_SetTarget(&special->target, NULL);
special->threshold = TICRATE - 1;
toucher->momz = -toucher->momz;
}
else // can't handle in PIT_CheckThing because of landing-on causing it to stop
P_DamageMobj(toucher, special, special->target, 1, 0);
}
else if (special->threshold == 0)
{
// Kick that sucker around!
special->movedir = ((special->movedir == 1) ? -1 : 1);
P_InstaThrust(special, toucher->angle, (special->info->speed*special->scale));
S_StartSound(toucher, sfx_mario2);
P_SetTarget(&special->target, toucher);
special->threshold = (3*TICRATE)/2;
if (bounceon)
toucher->momz = -toucher->momz;
}
} }
return; return;
case MT_AXE: case MT_AXE:

View File

@ -523,23 +523,27 @@ static boolean PIT_CheckThing(mobj_t *thing)
junk.v1 = &v1; junk.v1 = &v1;
junk.v2 = &v2; junk.v2 = &v2;
junk.dx = v2.x - v1.x; junk.dx = 2*cosradius; // v2.x - v1.x;
junk.dy = v2.y - v1.y; junk.dy = 2*sinradius; // v2.y - v1.y;
if (tmthing->flags & MF_PAPERCOLLISION) // more strenuous checking to prevent clipping issues if (tmthing->flags & MF_PAPERCOLLISION) // more strenuous checking to prevent clipping issues
{ {
INT32 check1, check2, check3, check4; INT32 check1, check2, check3, check4;
cosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT)); fixed_t tmcosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT));
sinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT)); fixed_t tmsinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT));
check1 = P_PointOnLineSide(tmx - cosradius, tmy - sinradius, &junk); if (abs(thing->x - tmx) >= (abs(tmcosradius) + abs(cosradius)) || abs(thing->y - tmy) >= (abs(tmsinradius) + abs(sinradius)))
check2 = P_PointOnLineSide(tmx + cosradius, tmy + sinradius, &junk); return true; // didn't hit it
check3 = P_PointOnLineSide(tmx + tmthing->momx - cosradius, tmy + tmthing->momy - sinradius, &junk); check1 = P_PointOnLineSide(tmx - tmcosradius, tmy - tmsinradius, &junk);
check4 = P_PointOnLineSide(tmx + tmthing->momx + cosradius, tmy + tmthing->momy + sinradius, &junk); check2 = P_PointOnLineSide(tmx + tmcosradius, tmy + tmsinradius, &junk);
check3 = P_PointOnLineSide(tmx + tmthing->momx - tmcosradius, tmy + tmthing->momy - tmsinradius, &junk);
check4 = P_PointOnLineSide(tmx + tmthing->momx + tmcosradius, tmy + tmthing->momy + tmsinradius, &junk);
if ((check1 == check2) && (check2 == check3) && (check3 == check4)) if ((check1 == check2) && (check2 == check3) && (check3 == check4))
return true; // the line doesn't cross between collider's start or end return true; // the line doesn't cross between collider's start or end
} }
else else
{ {
if (abs(thing->x - tmx) >= (tmthing->radius + abs(cosradius)) || abs(thing->y - tmy) >= (tmthing->radius + abs(sinradius)))
return true; // didn't hit it
if ((P_PointOnLineSide(tmx - tmthing->radius, tmy - tmthing->radius, &junk) if ((P_PointOnLineSide(tmx - tmthing->radius, tmy - tmthing->radius, &junk)
== P_PointOnLineSide(tmx + tmthing->radius, tmy + tmthing->radius, &junk)) == P_PointOnLineSide(tmx + tmthing->radius, tmy + tmthing->radius, &junk))
&& (P_PointOnLineSide(tmx + tmthing->radius, tmy - tmthing->radius, &junk) && (P_PointOnLineSide(tmx + tmthing->radius, tmy - tmthing->radius, &junk)
@ -549,25 +553,27 @@ static boolean PIT_CheckThing(mobj_t *thing)
} }
else if (tmthing->flags & MF_PAPERCOLLISION) else if (tmthing->flags & MF_PAPERCOLLISION)
{ {
fixed_t cosradius, sinradius; fixed_t tmcosradius, tmsinradius;
vertex_t v1, v2; // fake vertexes vertex_t v1, v2; // fake vertexes
line_t junk; // fake linedef line_t junk; // fake linedef
cosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT)); tmcosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT));
sinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT)); tmsinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT));
v1.x = tmx - cosradius; if (abs(thing->x - tmx) >= (thing->radius + abs(tmcosradius)) || abs(thing->y - tmy) >= (thing->radius + abs(tmsinradius)))
v1.y = tmy - sinradius; return true; // didn't hit it
v2.x = tmx + cosradius;
v2.y = tmy + sinradius; v1.x = tmx - tmcosradius;
v1.y = tmy - tmsinradius;
v2.x = tmx + tmcosradius;
v2.y = tmy + tmsinradius;
junk.v1 = &v1; junk.v1 = &v1;
junk.v2 = &v2; junk.v2 = &v2;
junk.dx = v2.x - v1.x; junk.dx = 2*tmcosradius; // v2.x - v1.x;
junk.dy = v2.y - v1.y; junk.dy = 2*tmsinradius; // v2.y - v1.y;
// no need to check whether thing has MF_PAPERCOLLISION, since checked above
// no need to check whether other thing has MF_PAPERCOLLISION, since would fall under other condition
if ((P_PointOnLineSide(thing->x - thing->radius, thing->y - thing->radius, &junk) if ((P_PointOnLineSide(thing->x - thing->radius, thing->y - thing->radius, &junk)
== P_PointOnLineSide(thing->x + thing->radius, thing->y + thing->radius, &junk)) == P_PointOnLineSide(thing->x + thing->radius, thing->y + thing->radius, &junk))
&& (P_PointOnLineSide(thing->x + thing->radius, thing->y - thing->radius, &junk) && (P_PointOnLineSide(thing->x + thing->radius, thing->y - thing->radius, &junk)
@ -768,8 +774,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
} }
} }
if (tmthing->type == MT_SHELL && tmthing->threshold > TICRATE)
return true;
// damage / explode // damage / explode
if (tmthing->flags & MF_ENEMY) // An actual ENEMY! (Like the deton, for example) if (tmthing->flags & MF_ENEMY) // An actual ENEMY! (Like the deton, for example)
P_DamageMobj(thing, tmthing, tmthing, 1, 0); P_DamageMobj(thing, tmthing, tmthing, 1, 0);
@ -810,7 +814,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmthing->y = thing->y; tmthing->y = thing->y;
P_SetThingPosition(tmthing); P_SetThingPosition(tmthing);
} }
else else if (!(tmthing->type == MT_SHELL && thing->player)) // player collision handled in touchspecial
P_DamageMobj(thing, tmthing, tmthing->target, 1, 0); P_DamageMobj(thing, tmthing, tmthing->target, 1, 0);
// don't traverse any more // don't traverse any more

View File

@ -564,7 +564,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
// Adjust the player's animation speed to match their velocity. // Adjust the player's animation speed to match their velocity.
if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST)) if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST))
{ {
fixed_t speed;// = FixedDiv(player->speed, mobj->scale); fixed_t speed;// = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor));
if (player->panim == PA_FALL) if (player->panim == PA_FALL)
{ {
speed = FixedDiv(abs(mobj->momz), mobj->scale); speed = FixedDiv(abs(mobj->momz), mobj->scale);
@ -590,7 +590,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
} }
else else
{ {
speed = FixedDiv(player->speed, mobj->scale); speed = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor));
if (player->panim == PA_ROLL || player->panim == PA_JUMP) if (player->panim == PA_ROLL || player->panim == PA_JUMP)
{ {
if (speed > 16<<FRACBITS) if (speed > 16<<FRACBITS)
@ -1842,7 +1842,6 @@ void P_CheckGravity(mobj_t *mo, boolean affect)
} }
#define STOPSPEED (FRACUNIT) #define STOPSPEED (FRACUNIT)
#define FRICTION (ORIG_FRICTION) // 0.90625
// //
// P_SceneryXYFriction // P_SceneryXYFriction
@ -1875,7 +1874,6 @@ static void P_SceneryXYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
{ {
// Stolen from P_SpawnFriction // Stolen from P_SpawnFriction
mo->friction = FRACUNIT - 0x100; mo->friction = FRACUNIT - 0x100;
mo->movefactor = ((0x10092 - mo->friction)*(0x70))/0x158;
} }
else else
mo->friction = ORIG_FRICTION; mo->friction = ORIG_FRICTION;
@ -1900,7 +1898,7 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
// spinning friction // spinning friction
if (player->pflags & PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH)) if (player->pflags & PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH))
{ {
const fixed_t ns = FixedDiv(549*FRICTION,500*FRACUNIT); const fixed_t ns = FixedDiv(549*ORIG_FRICTION,500*FRACUNIT);
mo->momx = FixedMul(mo->momx, ns); mo->momx = FixedMul(mo->momx, ns);
mo->momy = FixedMul(mo->momy, ns); mo->momy = FixedMul(mo->momy, ns);
} }
@ -2119,7 +2117,8 @@ void P_XYMovement(mobj_t *mo)
if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE) if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE)
P_PushableCheckBustables(mo); P_PushableCheckBustables(mo);
if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true) && !(mo->eflags & MFE_SPRUNG)) if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true)
&& !(P_MobjWasRemoved(mo) || mo->eflags & MFE_SPRUNG))
{ {
// blocked move // blocked move
moved = false; moved = false;
@ -2129,7 +2128,17 @@ void P_XYMovement(mobj_t *mo)
B_MoveBlocked(player); B_MoveBlocked(player);
} }
if (mo->flags & MF_BOUNCE) #ifdef HAVE_BLUA
if (LUAh_MobjMoveBlocked(mo))
{
if (P_MobjWasRemoved(mo))
return;
}
else
#endif
if (P_MobjWasRemoved(mo))
return;
else if (mo->flags & MF_BOUNCE)
{ {
P_BounceMove(mo); P_BounceMove(mo);
xmove = ymove = 0; xmove = ymove = 0;
@ -2178,8 +2187,39 @@ void P_XYMovement(mobj_t *mo)
} }
else if (player || mo->flags & (MF_SLIDEME|MF_PUSHABLE)) else if (player || mo->flags & (MF_SLIDEME|MF_PUSHABLE))
{ // try to slide along it { // try to slide along it
#ifdef ESLOPE
// Wall transfer part 1.
pslope_t *transferslope = NULL;
fixed_t transfermomz = 0;
if (oldslope && (P_MobjFlip(mo)*(predictedz - mo->z) > 0)) // Only for moving up (relative to gravity), otherwise there's a failed launch when going down slopes and hitting walls
{
transferslope = ((mo->standingslope) ? mo->standingslope : oldslope);
if (((transferslope->zangle < ANGLE_180) ? transferslope->zangle : InvAngle(transferslope->zangle)) >= ANGLE_45) // Prevent some weird stuff going on on shallow slopes.
transfermomz = P_GetWallTransferMomZ(mo, transferslope);
}
#endif
P_SlideMove(mo); P_SlideMove(mo);
xmove = ymove = 0; xmove = ymove = 0;
#ifdef ESLOPE
// Wall transfer part 2.
if (transfermomz && transferslope) // Are we "transferring onto the wall" (really just a disguised vertical launch)?
{
angle_t relation; // Scale transfer momentum based on how head-on it is to the slope.
if (mo->momx || mo->momy) // "Guess" the angle of the wall you hit using new momentum
relation = transferslope->xydirection - R_PointToAngle2(0, 0, mo->momx, mo->momy);
else // Give it for free, I guess.
relation = ANGLE_90;
transfermomz = FixedMul(transfermomz,
abs(FINESINE((relation >> ANGLETOFINESHIFT) & FINEMASK)));
if (P_MobjFlip(mo)*(transfermomz - mo->momz) > 2*FRACUNIT) // Do the actual launch!
{
mo->momz = transfermomz;
mo->standingslope = NULL;
}
}
#endif
} }
else if (mo->type == MT_SPINFIRE) else if (mo->type == MT_SPINFIRE)
{ {
@ -2409,14 +2449,16 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp
topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL);
bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL);
if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should be affected if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should stand on lava or run on water
; ;
else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only
continue; continue;
else if (rover->flags & FF_QUICKSAND) // quicksand else if (rover->flags & FF_QUICKSAND) // quicksand
; ;
else if (!((rover->flags & FF_BLOCKPLAYER && mo->player) // solid to players? else if (!( // if it's not either of the following...
|| (rover->flags & FF_BLOCKOTHERS && !mo->player))) // solid to others? (rover->flags & (FF_BLOCKPLAYER|FF_MARIO) && mo->player) // ...solid to players? (mario blocks are always solid from beneath to players)
|| (rover->flags & FF_BLOCKOTHERS && !mo->player) // ...solid to others?
)) // ...don't take it into account.
continue; continue;
if (rover->flags & FF_QUICKSAND) if (rover->flags & FF_QUICKSAND)
{ {
@ -2441,7 +2483,9 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp
delta1 = mo->z - (bottomheight + ((topheight - bottomheight)/2)); delta1 = mo->z - (bottomheight + ((topheight - bottomheight)/2));
delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2));
if (topheight > mo->floorz && abs(delta1) < abs(delta2) if (topheight > mo->floorz && abs(delta1) < abs(delta2)
&& (rover->flags & FF_SOLID) // Non-FF_SOLID Mario blocks are only solid from bottom
&& !(rover->flags & FF_REVERSEPLATFORM) && !(rover->flags & FF_REVERSEPLATFORM)
&& ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_PLATFORM)))) // In reverse gravity, only clip for FOFs that are intangible from their bottom (the "top" you're falling through) if you're coming from above ("below" in your frame of reference) && ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_PLATFORM)))) // In reverse gravity, only clip for FOFs that are intangible from their bottom (the "top" you're falling through) if you're coming from above ("below" in your frame of reference)
{ {
@ -2449,7 +2493,7 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp
} }
if (bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2) if (bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2)
&& !(rover->flags & FF_PLATFORM) && !(rover->flags & FF_PLATFORM)
&& ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_REVERSEPLATFORM)))) // In normal gravity, only clip for FOFs that are intangible from the top if you're coming from below && ((P_MobjFlip(mo)*mo->momz >= 0) || ((rover->flags & FF_SOLID) && !(rover->flags & FF_REVERSEPLATFORM)))) // In normal gravity, only clip for FOFs that are intangible from the top if you're coming from below
{ {
mo->ceilingz = bottomheight; mo->ceilingz = bottomheight;
} }
@ -2934,7 +2978,6 @@ static boolean P_ZMovement(mobj_t *mo)
// Stolen from P_SpawnFriction // Stolen from P_SpawnFriction
mo->friction = FRACUNIT - 0x100; mo->friction = FRACUNIT - 0x100;
mo->movefactor = ((0x10092 - mo->friction)*(0x70))/0x158;
} }
else if (mo->type == MT_FALLINGROCK) else if (mo->type == MT_FALLINGROCK)
{ {
@ -3389,8 +3432,13 @@ nightsdone:
if (rover->flags & FF_MARIO if (rover->flags & FF_MARIO
&& !(mo->eflags & MFE_VERTICALFLIP) // if you were flipped, your head isn't actually hitting your ceilingz is it? && !(mo->eflags & MFE_VERTICALFLIP) // if you were flipped, your head isn't actually hitting your ceilingz is it?
&& *rover->bottomheight == mo->ceilingz) // The player's head hit the bottom! && *rover->bottomheight == mo->ceilingz) // The player's head hit the bottom!
{
// DO THE MARIO! // DO THE MARIO!
EV_MarioBlock(rover->master->frontsector, node->m_sector, *rover->topheight, mo); if (rover->flags & FF_SHATTERBOTTOM) // Brick block!
EV_CrumbleChain(node->m_sector, rover);
else // Question block!
EV_MarioBlock(rover, node->m_sector, mo);
}
} }
} // Ugly ugly billions of braces! Argh! } // Ugly ugly billions of braces! Argh!
} }
@ -4551,7 +4599,15 @@ static void P_Boss1Thinker(mobj_t *mobj)
return; return;
} }
if (mobj->state != &states[mobj->info->spawnstate] && mobj->health > 0 && mobj->flags & MF_FLOAT && !(mobj->flags2 & MF2_SKULLFLY)) if (mobj->flags2 & MF2_SKULLFLY)
{
fixed_t dist = (mobj->eflags & MFE_VERTICALFLIP)
? ((mobj->ceilingz-(2*mobj->height)) - (mobj->z+mobj->height))
: (mobj->z - (mobj->floorz+(2*mobj->height)));
if (dist > 0 && P_MobjFlip(mobj)*mobj->momz > 0)
mobj->momz = FixedMul(mobj->momz, FRACUNIT - (dist>>12));
}
else if (mobj->state != &states[mobj->info->spawnstate] && mobj->health > 0 && mobj->flags & MF_FLOAT)
mobj->momz = FixedMul(mobj->momz,7*FRACUNIT/8); mobj->momz = FixedMul(mobj->momz,7*FRACUNIT/8);
if (mobj->state == &states[mobj->info->meleestate] if (mobj->state == &states[mobj->info->meleestate]
@ -5596,6 +5652,15 @@ static void P_Boss7Thinker(mobj_t *mobj)
} }
#define vectorise mobj->movedir = ANGLE_11hh - FixedAngle(FixedMul(AngleFixed(ANGLE_11hh), FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS)));\
if (P_RandomChance(FRACUNIT/2))\
mobj->movedir = InvAngle(mobj->movedir);\
mobj->threshold = 6 + (FixedMul(24<<FRACBITS, FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS))>>FRACBITS);\
if (mobj->info->activesound)\
S_StartSound(mobj, mobj->info->activesound);\
if (mobj->info->painchance)\
P_SetMobjState(mobj, mobj->info->painchance)
// Metal Sonic battle boss // Metal Sonic battle boss
// You CAN put multiple Metal Sonics in a single map // You CAN put multiple Metal Sonics in a single map
// because I am a totally competent programmer who can do shit right. // because I am a totally competent programmer who can do shit right.
@ -5640,19 +5705,41 @@ static void P_Boss9Thinker(mobj_t *mobj)
if (mobj->health <= 0) if (mobj->health <= 0)
return; return;
if ((statenum_t)(mobj->state-states) == mobj->info->meleestate)
{
P_InstaThrust(mobj, mobj->angle, -4*FRACUNIT);
P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true);
mobj->momz -= gravity;
if (mobj->z < mobj->watertop)
{
mobj->watertop = mobj->target->floorz + 32*FRACUNIT;
P_SetMobjState(mobj, mobj->info->spawnstate);
}
return;
}
if ((!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))) if ((!mobj->target || !(mobj->target->flags & MF_SHOOTABLE)))
{ {
if (mobj->tracer)
P_RemoveMobj(mobj->tracer);
P_BossTargetPlayer(mobj, false); P_BossTargetPlayer(mobj, false);
if (mobj->target && (!P_IsObjectOnGround(mobj->target) || mobj->target->player->pflags & PF_SPINNING)) if (mobj->target && (!P_IsObjectOnGround(mobj->target) || mobj->target->player->pflags & PF_SPINNING))
P_SetTarget(&mobj->target, NULL); // Wait for them to hit the ground first P_SetTarget(&mobj->target, NULL); // Wait for them to hit the ground first
if (!mobj->target) // Still no target, aww. if (!mobj->target) // Still no target, aww.
{ {
// Reset the boss. // Reset the boss.
if (mobj->tracer)
P_RemoveMobj(mobj->tracer);
P_SetMobjState(mobj, mobj->info->spawnstate); P_SetMobjState(mobj, mobj->info->spawnstate);
mobj->fuse = 0; mobj->fuse = 0;
mobj->momx = FixedDiv(mobj->momx, FRACUNIT + (FRACUNIT>>2)); mobj->momx = FixedDiv(mobj->momx, FRACUNIT + (FRACUNIT>>2));
mobj->momy = FixedDiv(mobj->momy, FRACUNIT + (FRACUNIT>>2)); mobj->momy = FixedDiv(mobj->momy, FRACUNIT + (FRACUNIT>>2));
mobj->momz = FixedDiv(mobj->momz, FRACUNIT + (FRACUNIT>>2)); mobj->momz = FixedDiv(mobj->momz, FRACUNIT + (FRACUNIT>>2));
mobj->watertop = mobj->floorz + 32*FRACUNIT;
mobj->momz = (mobj->watertop - mobj->z)>>3;
mobj->threshold = 0;
mobj->movecount = 0;
mobj->flags = mobj->info->flags;
return; return;
} }
else if (!mobj->fuse) else if (!mobj->fuse)
@ -5700,7 +5787,8 @@ static void P_Boss9Thinker(mobj_t *mobj)
} }
if (spawner) { if (spawner) {
mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER); mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER);
missile->momz = FixedDiv(missile->momz, 7*FRACUNIT/4); if (mobj->health > mobj->info->damage)
missile->momz = FixedDiv(missile->momz, 7*FRACUNIT/5);
if (dist == 0) if (dist == 0)
missile->fuse = 0; missile->fuse = 0;
else else
@ -5712,16 +5800,22 @@ static void P_Boss9Thinker(mobj_t *mobj)
// Pre-threshold reactiontime stuff for attack phases // Pre-threshold reactiontime stuff for attack phases
if (mobj->reactiontime && mobj->movecount == 3) { if (mobj->reactiontime && mobj->movecount == 3) {
mobj->reactiontime--;
if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase
if (mobj->target->player->powers[pw_tailsfly]) // Trying to escape, eh? if (mobj->target->player->powers[pw_tailsfly]) // Trying to escape, eh?
mobj->watertop = mobj->target->z + mobj->target->momz*6; // Readjust your aim. >:3 mobj->watertop = mobj->target->z + mobj->target->momz*6; // Readjust your aim. >:3
else else
mobj->watertop = mobj->target->floorz + 16*FRACUNIT; mobj->watertop = mobj->target->floorz + 16*FRACUNIT;
if (!(mobj->threshold%4))
if (!(mobj->threshold%4)) {
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4);
if (!mobj->reactiontime)
S_StartSound(mobj, sfx_zoom); // zoom!
}
} }
// Pausing between energy ball shots // else -- Pausing between energy ball shots
mobj->reactiontime--;
return; return;
} }
@ -5793,20 +5887,28 @@ static void P_Boss9Thinker(mobj_t *mobj)
P_InstaThrust(mobj, mobj->angle, 30*FRACUNIT); P_InstaThrust(mobj, mobj->angle, 30*FRACUNIT);
if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) { // Hit a wall? Find a direction to bounce if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) { // Hit a wall? Find a direction to bounce
mobj->threshold--; mobj->threshold--;
if (mobj->threshold) { P_SetMobjState(mobj, mobj->state->nextstate);
P_SetMobjState(mobj, mobj->state->nextstate); if (!mobj->threshold) { // failed bounce!
if (mobj->info->mass) S_StartSound(mobj, sfx_mspogo);
S_StartSound(mobj, mobj->info->mass); P_BounceMove(mobj);
if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); mobj->momz = 4*FRACUNIT;
mobj->reactiontime = TICRATE; // targetting time mobj->flags &= ~MF_PAIN;
} else { // No homing, just use P_BounceMove mobj->fuse = 10*TICRATE;
P_BounceMove(mobj); mobj->movecount = 0;
mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy); P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION);
mobj->reactiontime = TICRATE/4; // just a pause before you bounce away P_SetMobjState(mobj, mobj->info->meleestate);
} } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce.
mobj->momx = mobj->momy = 0; S_StartSound(mobj, sfx_s3k5a);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4);
mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time
} else { // No homing, just use P_BounceMove
S_StartSound(mobj, sfx_s3kaa); // make the bounces distinct...
P_BounceMove(mobj);
mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy);
mobj->reactiontime = 1; // TICRATE/4; // just a pause before you bounce away
} }
mobj->momx = mobj->momy = 0;
} }
return; return;
} }
@ -5815,8 +5917,9 @@ static void P_Boss9Thinker(mobj_t *mobj)
mobj->angle += mobj->movedir; mobj->angle += mobj->movedir;
P_InstaThrust(mobj, mobj->angle, -speed); P_InstaThrust(mobj, mobj->angle, -speed);
while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) { while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) {
mobj->angle += mobj->movedir; S_StartSound(mobj, sfx_mspogo);
P_InstaThrust(mobj, mobj->angle, -speed); P_BounceMove(mobj);
mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0);
} }
mobj->momx = mobj->momy = 0; mobj->momx = mobj->momy = 0;
mobj->threshold--; mobj->threshold--;
@ -5933,9 +6036,9 @@ static void P_Boss9Thinker(mobj_t *mobj)
S_StartSound(mobj, mobj->info->seesound); S_StartSound(mobj, mobj->info->seesound);
P_SetMobjState(mobj, mobj->info->seestate); P_SetMobjState(mobj, mobj->info->seestate);
if (mobj->movedir == 2) if (mobj->movedir == 2)
mobj->threshold = 16; // bounce 16 times mobj->threshold = 12; // bounce 12 times
else else
mobj->threshold = 32; // bounce 32 times mobj->threshold = 24; // bounce 24 times
mobj->watertop = mobj->target->floorz + 16*FRACUNIT; mobj->watertop = mobj->target->floorz + 16*FRACUNIT;
P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); P_LinedefExecute(LE_PINCHPHASE, mobj, NULL);
} else { } else {
@ -6018,14 +6121,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
if (danger) { if (danger) {
// An incoming attack is detected! What should we do?! // An incoming attack is detected! What should we do?!
// Go into vector form! // Go into vector form!
mobj->movedir = ANGLE_11hh - FixedAngle(FixedMul(AngleFixed(ANGLE_11hh), FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS))); vectorise;
if (P_RandomChance(FRACUNIT/2))
mobj->movedir = InvAngle(mobj->movedir);
mobj->threshold = 6 + (FixedMul(24<<FRACBITS, FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS))>>FRACBITS);
if (mobj->info->activesound)
S_StartSound(mobj, mobj->info->activesound);
if (mobj->info->painchance)
P_SetMobjState(mobj, mobj->info->painchance);
return; return;
} }
@ -6040,6 +6136,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
} }
} }
} }
#undef vectorise
// //
// P_GetClosestAxis // P_GetClosestAxis
@ -6720,7 +6817,7 @@ void P_MobjThinker(mobj_t *mobj)
} }
} }
if (mobj->type == MT_GHOST && mobj->fuse > 0 // Not guaranteed to be MF_SCENERY or not MF_SCENERY! if ((mobj->type == MT_GHOST || mobj->type == MT_THOK) && mobj->fuse > 0 // Not guaranteed to be MF_SCENERY or not MF_SCENERY!
&& (signed)(mobj->frame >> FF_TRANSSHIFT) < (NUMTRANSMAPS-1) - mobj->fuse / 2) && (signed)(mobj->frame >> FF_TRANSSHIFT) < (NUMTRANSMAPS-1) - mobj->fuse / 2)
// fade out when nearing the end of fuse... // fade out when nearing the end of fuse...
mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - mobj->fuse / 2) << FF_TRANSSHIFT); mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - mobj->fuse / 2) << FF_TRANSSHIFT);
@ -7677,13 +7774,13 @@ void P_MobjThinker(mobj_t *mobj)
P_NightsItemChase(mobj); P_NightsItemChase(mobj);
break; break;
case MT_SHELL: case MT_SHELL:
if (mobj->threshold > TICRATE) if (mobj->threshold && mobj->threshold != TICRATE)
mobj->threshold--; mobj->threshold--;
if (mobj->state != &states[S_SHELL]) if (mobj->threshold >= TICRATE)
{ {
mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); mobj->angle += ((mobj->movedir == 1) ? ANGLE_22h : ANGLE_337h);
P_InstaThrust(mobj, mobj->angle, FixedMul(mobj->info->speed, mobj->scale)); P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), (mobj->info->speed*mobj->scale));
} }
break; break;
case MT_TURRET: case MT_TURRET:
@ -8255,7 +8352,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
mobj->friction = ORIG_FRICTION; mobj->friction = ORIG_FRICTION;
mobj->movefactor = ORIG_FRICTION_FACTOR; mobj->movefactor = FRACUNIT;
// All mobjs are created at 100% scale. // All mobjs are created at 100% scale.
mobj->scale = FRACUNIT; mobj->scale = FRACUNIT;
@ -9766,6 +9863,85 @@ ML_NOCLIMB : Direction not controllable
} }
break; break;
} }
case MT_PARTICLEGEN:
{
fixed_t radius, speed, bottomheight, topheight;
INT32 type, numdivisions, time, anglespeed;
angle_t angledivision;
size_t line;
const size_t mthingi = (size_t)(mthing - mapthings);
for (line = 0; line < numlines; line++)
{
if (lines[line].special == 15 && lines[line].tag == mthing->angle)
break;
}
if (line == numlines)
{
CONS_Debug(DBG_GAMELOGIC, "Particle generator (mapthing #%s) needs tagged to a #15 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle);
return;
}
if (sides[lines[line].sidenum[0]].toptexture)
type = sides[lines[line].sidenum[0]].toptexture; // Set as object type in p_setup.c...
else
type = (INT32)MT_PARTICLE;
speed = abs(sides[lines[line].sidenum[0]].textureoffset);
bottomheight = lines[line].frontsector->floorheight;
topheight = lines[line].frontsector->ceilingheight - mobjinfo[(mobjtype_t)type].height;
numdivisions = (mthing->options >> ZSHIFT);
if (numdivisions)
{
radius = R_PointToDist2(lines[line].v1->x, lines[line].v1->y, lines[line].v2->x, lines[line].v2->y);
anglespeed = (sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) % 360;
angledivision = 360/numdivisions;
}
else
{
numdivisions = 1; // Simple trick to make A_ParticleSpawn simpler.
radius = 0;
anglespeed = 0;
angledivision = 0;
}
if ((speed) && (topheight > bottomheight))
time = (INT32)(FixedDiv((topheight - bottomheight), speed) >> FRACBITS);
else
time = 1; // There's no reasonable way to set it, so just show the object for one tic and move on.
if (mthing->options & MTF_OBJECTFLIP)
{
mobj->z = topheight;
speed *= -1;
}
else
mobj->z = bottomheight;
CONS_Debug(DBG_GAMELOGIC, "Particle Generator (mapthing #%s):\n"
"Radius is %d\n"
"Speed is %d\n"
"Anglespeed is %d\n"
"Numdivisions is %d\n"
"Angledivision is %d\n"
"Time is %d\n"
"Type is %d\n",
sizeu1(mthingi), radius, speed, anglespeed, numdivisions, angledivision, time, type);
mobj->angle = 0;
mobj->movefactor = speed;
mobj->lastlook = numdivisions;
mobj->movedir = angledivision*ANG1;
mobj->movecount = anglespeed*ANG1;
mobj->health = time;
mobj->friction = radius;
mobj->threshold = type;
break;
}
case MT_ROCKSPAWNER: case MT_ROCKSPAWNER:
mobj->threshold = mthing->angle; mobj->threshold = mthing->angle;
mobj->movecount = mthing->extrainfo; mobj->movecount = mthing->extrainfo;

View File

@ -974,6 +974,7 @@ typedef enum
tc_noenemies, tc_noenemies,
tc_eachtime, tc_eachtime,
tc_disappear, tc_disappear,
tc_planedisplace,
#ifdef POLYOBJECTS #ifdef POLYOBJECTS
tc_polyrotate, // haleyjd 03/26/06: polyobjects tc_polyrotate, // haleyjd 03/26/06: polyobjects
tc_polymove, tc_polymove,
@ -1097,7 +1098,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff |= MD_TRACER; diff |= MD_TRACER;
if (mobj->friction != ORIG_FRICTION) if (mobj->friction != ORIG_FRICTION)
diff |= MD_FRICTION; diff |= MD_FRICTION;
if (mobj->movefactor != ORIG_FRICTION_FACTOR) if (mobj->movefactor != FRACUNIT)
diff |= MD_MOVEFACTOR; diff |= MD_MOVEFACTOR;
if (mobj->fuse) if (mobj->fuse)
diff |= MD_FUSE; diff |= MD_FUSE;
@ -1537,6 +1538,21 @@ static void SaveDisappearThinker(const thinker_t *th, const UINT8 type)
WRITEINT32(save_p, ht->exists); WRITEINT32(save_p, ht->exists);
} }
//
// SavePlaneDisplaceThinker
//
// Saves a planedisplace_t thinker
//
static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type)
{
const planedisplace_t *ht = (const void *)th;
WRITEUINT8(save_p, type);
WRITEINT32(save_p, ht->affectee);
WRITEINT32(save_p, ht->control);
WRITEFIXED(save_p, ht->last_height);
WRITEFIXED(save_p, ht->speed);
WRITEUINT8(save_p, ht->type);
}
#ifdef POLYOBJECTS #ifdef POLYOBJECTS
// //
@ -1818,6 +1834,12 @@ static void P_NetArchiveThinkers(void)
SaveDisappearThinker(th, tc_disappear); SaveDisappearThinker(th, tc_disappear);
continue; continue;
} }
else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace)
{
SavePlaneDisplaceThinker(th, tc_planedisplace);
continue;
}
#ifdef POLYOBJECTS #ifdef POLYOBJECTS
else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate) else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate)
{ {
@ -2083,7 +2105,7 @@ static void LoadMobjThinker(actionf_p1 thinker)
if (diff & MD_MOVEFACTOR) if (diff & MD_MOVEFACTOR)
mobj->movefactor = READFIXED(save_p); mobj->movefactor = READFIXED(save_p);
else else
mobj->movefactor = ORIG_FRICTION_FACTOR; mobj->movefactor = FRACUNIT;
if (diff & MD_FUSE) if (diff & MD_FUSE)
mobj->fuse = READINT32(save_p); mobj->fuse = READINT32(save_p);
if (diff & MD_WATERTOP) if (diff & MD_WATERTOP)
@ -2486,6 +2508,23 @@ static inline void LoadDisappearThinker(actionf_p1 thinker)
P_AddThinker(&ht->thinker); P_AddThinker(&ht->thinker);
} }
//
// LoadPlaneDisplaceThinker
//
// Loads a planedisplace_t thinker
//
static inline void LoadPlaneDisplaceThinker(actionf_p1 thinker)
{
planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
ht->thinker.function.acp1 = thinker;
ht->affectee = READINT32(save_p);
ht->control = READINT32(save_p);
ht->last_height = READFIXED(save_p);
ht->speed = READFIXED(save_p);
ht->type = READUINT8(save_p);
P_AddThinker(&ht->thinker);
}
#ifdef POLYOBJECTS #ifdef POLYOBJECTS
// //
@ -2769,6 +2808,10 @@ static void P_NetUnArchiveThinkers(void)
case tc_disappear: case tc_disappear:
LoadDisappearThinker((actionf_p1)T_Disappear); LoadDisappearThinker((actionf_p1)T_Disappear);
break; break;
case tc_planedisplace:
LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace);
break;
#ifdef POLYOBJECTS #ifdef POLYOBJECTS
case tc_polyrotate: case tc_polyrotate:
LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate); LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate);

View File

@ -1530,6 +1530,8 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
sd->text[6] = 0; sd->text[6] = 0;
break; break;
} }
case 4: // Speed pad parameters
case 414: // Play SFX case 414: // Play SFX
{ {
sd->toptexture = sd->midtexture = sd->bottomtexture = 0; sd->toptexture = sd->midtexture = sd->bottomtexture = 0;
@ -1543,6 +1545,8 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
break; break;
} }
case 14: // Bustable block parameters
case 15: // Fan particle spawner parameters
case 425: // Calls P_SetMobjState on calling mobj case 425: // Calls P_SetMobjState on calling mobj
case 434: // Custom Power case 434: // Custom Power
case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors

View File

@ -804,6 +804,39 @@ void P_SlopeLaunch(mobj_t *mo)
mo->standingslope = NULL; mo->standingslope = NULL;
} }
//
// P_GetWallTransferMomZ
//
// It would be nice to have a single function that does everything necessary for slope-to-wall transfer.
// However, it needs to be seperated out in P_XYMovement to take into account momentum before and after hitting the wall.
// This just performs the necessary calculations for getting the base vertical momentum; the horizontal is already reasonably calculated by P_SlideMove.
fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope)
{
vector3_t slopemom, axis;
angle_t ang;
if (mo->standingslope->flags & SL_NOPHYSICS)
return 0;
// If there's physics, time for launching.
// Doesn't kill the vertical momentum as much as P_SlopeLaunch does.
ang = slope->zangle + ANG15*((slope->zangle > 0) ? 1 : -1);
if (ang > ANGLE_90 && ang < ANGLE_180)
ang = ((slope->zangle > 0) ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards
slopemom.x = mo->momx;
slopemom.y = mo->momy;
slopemom.z = 3*(mo->momz/2);
axis.x = -slope->d.y;
axis.y = slope->d.x;
axis.z = 0;
FV3_Rotate(&slopemom, &axis, ang >> ANGLETOFINESHIFT);
return 2*(slopemom.z/3);
}
// Function to help handle landing on slopes // Function to help handle landing on slopes
void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope)
{ {

View File

@ -37,6 +37,7 @@ fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y);
void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
void P_SlopeLaunch(mobj_t *mo); void P_SlopeLaunch(mobj_t *mo);
fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope);
void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope); void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope);
void P_ButteredSlope(mobj_t *mo); void P_ButteredSlope(mobj_t *mo);

View File

@ -51,6 +51,9 @@ mobj_t *skyboxmo[2];
// Amount (dx, dy) vector linedef is shifted right to get scroll amount // Amount (dx, dy) vector linedef is shifted right to get scroll amount
#define SCROLL_SHIFT 5 #define SCROLL_SHIFT 5
// This must be updated whenever we up the max flat size - quicker to assume rather than figuring out the sqrt of the specific flat's filesize.
#define MAXFLATSIZE (2048<<FRACBITS)
/** Animated texture descriptor /** Animated texture descriptor
* This keeps track of an animated texture or an animated flat. * This keeps track of an animated texture or an animated flat.
* \sa P_UpdateSpecials, P_InitPicAnims, animdef_t * \sa P_UpdateSpecials, P_InitPicAnims, animdef_t
@ -108,6 +111,7 @@ static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinker
static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec); static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec);
static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer); static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer);
static void P_AddSpikeThinker(sector_t *sec, INT32 referrer); static void P_AddSpikeThinker(sector_t *sec, INT32 referrer);
static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee);
//SoM: 3/7/2000: New sturcture without limits. //SoM: 3/7/2000: New sturcture without limits.
@ -2440,7 +2444,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
{ {
fixed_t sfxnum; fixed_t sfxnum;
sfxnum = sides[line->sidenum[0]].toptexture; //P_AproxDistance(line->dx, line->dy)>>FRACBITS; sfxnum = sides[line->sidenum[0]].toptexture;
if (line->tag != 0 && line->flags & ML_EFFECT5) if (line->tag != 0 && line->flags & ML_EFFECT5)
{ {
@ -3107,6 +3111,51 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
} }
break; break;
case 446: // Make block fall remotely (acts like FF_CRUMBLE)
{
INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS);
INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS);
sector_t *sec; // Sector that the FOF is visible in
ffloor_t *rover; // FOF that we are going to make fall down
player_t *player = NULL; // player that caused FOF to fall
boolean respawn = true; // should the fallen FOF respawn?
if (mo) // NULL check
player = mo->player;
if (line->flags & ML_NOCLIMB) // don't respawn!
respawn = false;
for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;)
{
sec = sectors + secnum;
if (!sec->ffloors)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Target sector #%d has no FOFs.\n", secnum);
return;
}
for (rover = sec->ffloors; rover; rover = rover->next)
{
if (rover->master->frontsector->tag == foftag)
break;
}
if (!rover)
{
CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Can't find a FOF control sector with tag %d\n", foftag);
return;
}
if (line->flags & ML_BLOCKMONSTERS) // FOF flags determine respawn ability instead?
respawn = !(rover->flags & FF_NORETURN) ^ !!(line->flags & ML_NOCLIMB); // no climb inverts
EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), player, rover->alpha, respawn);
}
}
break;
case 450: // Execute Linedef Executor - for recursion case 450: // Execute Linedef Executor - for recursion
P_LinedefExecute(line->tag, mo, NULL); P_LinedefExecute(line->tag, mo, NULL);
break; break;
@ -3683,14 +3732,13 @@ DoneSection2:
// Process Section 3 // Process Section 3
switch (special) switch (special)
{ {
case 1: // Ice/Sludge case 1: // Unused
case 2: // Wind/Current case 2: // Wind/Current
case 3: // Ice/Sludge and Wind/Current case 3: // Unused
case 4: // Conveyor Belt case 4: // Conveyor Belt
break; break;
case 5: // Speed pad w/o spin case 5: // Speed pad
case 6: // Speed pad w/ spin
if (player->powers[pw_flashing] != 0 && player->powers[pw_flashing] < TICRATE/2) if (player->powers[pw_flashing] != 0 && player->powers[pw_flashing] < TICRATE/2)
break; break;
@ -3700,9 +3748,16 @@ DoneSection2:
{ {
angle_t lineangle; angle_t lineangle;
fixed_t linespeed; fixed_t linespeed;
fixed_t sfxnum;
lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); lineangle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
linespeed = P_AproxDistance(lines[i].v2->x-lines[i].v1->x, lines[i].v2->y-lines[i].v1->y); linespeed = sides[lines[i].sidenum[0]].textureoffset;
if (linespeed == 0)
{
CONS_Debug(DBG_GAMELOGIC, "ERROR: Speed pad (tag %d) at zero speed.\n", sector->tag);
break;
}
player->mo->angle = lineangle; player->mo->angle = lineangle;
@ -3732,7 +3787,7 @@ DoneSection2:
P_InstaThrust(player->mo, player->mo->angle, linespeed); P_InstaThrust(player->mo, player->mo->angle, linespeed);
if (GETSECSPECIAL(sector->special, 3) == 6 && (player->charability2 == CA2_SPINDASH)) if ((lines[i].flags & ML_EFFECT5) && (player->charability2 == CA2_SPINDASH)) // Roll!
{ {
if (!(player->pflags & PF_SPINNING)) if (!(player->pflags & PF_SPINNING))
player->pflags |= PF_SPINNING; player->pflags |= PF_SPINNING;
@ -3741,19 +3796,26 @@ DoneSection2:
} }
player->powers[pw_flashing] = TICRATE/3; player->powers[pw_flashing] = TICRATE/3;
S_StartSound(player->mo, sfx_spdpad);
sfxnum = sides[lines[i].sidenum[0]].toptexture;
if (!sfxnum)
sfxnum = sfx_spdpad;
S_StartSound(player->mo, sfxnum);
} }
break; break;
case 7: // Bustable block sprite parameter case 6: // Unused
case 8: case 7: // Unused
case 9: case 8: // Unused
case 10: case 9: // Unused
case 11: case 10: // Unused
case 12: case 11: // Unused
case 13: case 12: // Unused
case 14: case 13: // Unused
case 15: case 14: // Unused
case 15: // Unused
break; break;
} }
@ -3923,8 +3985,14 @@ DoneSection2:
} }
// Grab speed and sequence values // Grab speed and sequence values
speed = abs(lines[lineindex].dx)/8; speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8;
sequence = abs(lines[lineindex].dy)>>FRACBITS; sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS;
if (speed == 0)
{
CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence);
break;
}
// scan the thinkers // scan the thinkers
// to find the first waypoint // to find the first waypoint
@ -3996,8 +4064,14 @@ DoneSection2:
} }
// Grab speed and sequence values // Grab speed and sequence values
speed = -(abs(lines[lineindex].dx)/8); // Negative means reverse speed = -abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; // Negative means reverse
sequence = abs(lines[lineindex].dy)>>FRACBITS; sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS;
if (speed == 0)
{
CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence);
break;
}
// scan the thinkers // scan the thinkers
// to find the last waypoint // to find the last waypoint
@ -4037,6 +4111,7 @@ DoneSection2:
player->speed = speed; player->speed = speed;
player->pflags |= PF_SPINNING; player->pflags |= PF_SPINNING;
player->pflags &= ~(PF_JUMPED|PF_GLIDING|PF_SLIDING|PF_CANCARRY); player->pflags &= ~(PF_JUMPED|PF_GLIDING|PF_SLIDING|PF_CANCARRY);
player->climbing = 0;
if (player->mo->state-states != S_PLAY_SPIN) if (player->mo->state-states != S_PLAY_SPIN)
{ {
@ -4135,8 +4210,14 @@ DoneSection2:
} }
// Grab speed and sequence values // Grab speed and sequence values
speed = abs(lines[lineindex].dx)/8; speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8;
sequence = abs(lines[lineindex].dy)>>FRACBITS; sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS;
if (speed == 0)
{
CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence);
break;
}
// Find the closest waypoint // Find the closest waypoint
// Find the preceding waypoint // Find the preceding waypoint
@ -4983,7 +5064,8 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
if ((flags & FF_MARIO)) if ((flags & FF_MARIO))
{ {
P_AddBlockThinker(sec2, master); if (!(flags & FF_SHATTERBOTTOM)) // Don't change the textures of a brick block, just a question block
P_AddBlockThinker(sec2, master);
CheckForMarioBlocks = true; CheckForMarioBlocks = true;
} }
@ -5083,6 +5165,33 @@ static inline void P_AddBridgeThinker(line_t *sourceline, sector_t *sec)
} }
*/ */
/**
* Adds a plane displacement thinker.
* Whenever the "control" sector moves,
* the "affectee" sector's floor or ceiling plane moves too!
*
* \param speed Rate of movement relative to control sector
* \param control Control sector.
* \param affectee Target sector.
* \sa P_SpawnSpecials, T_PlaneDisplace
* \author Monster Iestyn
*/
static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee)
{
planedisplace_t *displace;
// create and initialize new displacement thinker
displace = Z_Calloc(sizeof (*displace), PU_LEVSPEC, NULL);
P_AddThinker(&displace->thinker);
displace->thinker.function.acp1 = (actionf_p1)T_PlaneDisplace;
displace->affectee = affectee;
displace->control = control;
displace->last_height = sectors[control].floorheight;
displace->speed = speed;
displace->type = type;
}
/** Adds a Mario block thinker, which changes the block's texture between blank /** Adds a Mario block thinker, which changes the block's texture between blank
* and ? depending on whether it has contents. * and ? depending on whether it has contents.
* Needed in case objects respawn inside. * Needed in case objects respawn inside.
@ -5321,7 +5430,7 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto
elevator->distance = FixedInt(AngleFixed(angle)); elevator->distance = FixedInt(AngleFixed(angle));
} }
static const ffloortype_e laserflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA; static const ffloortype_e laserflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT;
/** Flashes a laser block. /** Flashes a laser block.
* *
@ -5341,10 +5450,12 @@ void T_LaserFlash(laserthink_t *flash)
if (!ffloor || !(ffloor->flags & FF_EXISTS)) if (!ffloor || !(ffloor->flags & FF_EXISTS))
return; return;
if (leveltime & 1) if (leveltime & 2)
ffloor->flags |= FF_RENDERALL; //ffloor->flags |= FF_RENDERALL;
ffloor->alpha = 0xB0;
else else
ffloor->flags &= ~FF_RENDERALL; //ffloor->flags &= ~FF_RENDERALL;
ffloor->alpha = 0x90;
sourcesec = ffloor->master->frontsector; // Less to type! sourcesec = ffloor->master->frontsector; // Less to type!
@ -5572,32 +5683,27 @@ void P_SpawnSpecials(INT32 fromnetsave)
// Init line EFFECTs // Init line EFFECTs
for (i = 0; i < numlines; i++) for (i = 0; i < numlines; i++)
{ {
// set line specials to 0 here too, same reason as above if (lines[i].special != 7) // This is a hack. I can at least hope nobody wants to prevent flat alignment with arbitrary skin setups...
if (netgame || multiplayer)
{ {
// future: nonet flag? // set line specials to 0 here too, same reason as above
} if (netgame || multiplayer)
else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) {
{ // future: nonet flag?
lines[i].special = 0; }
continue; else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY)
}
else
{
if (players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC))
{ {
lines[i].special = 0; lines[i].special = 0;
continue; continue;
} }
if (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) else
{ {
lines[i].special = 0; if ((players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC))
continue; || (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS))
} || (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX)))
if (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX)) {
{ lines[i].special = 0;
lines[i].special = 0; continue;
continue; }
} }
} }
@ -5643,47 +5749,53 @@ void P_SpawnSpecials(INT32 fromnetsave)
break; break;
#endif #endif
case 7: // Flat alignment case 7: // Flat alignment - redone by toast
if (lines[i].flags & ML_EFFECT4) // Align angle if ((lines[i].flags & (ML_NOSONIC|ML_NOTAILS)) != (ML_NOSONIC|ML_NOTAILS)) // If you can do something...
{ {
if (!(lines[i].flags & ML_EFFECT5)) // Align floor unless ALLTRIGGER flag is set angle_t flatangle = InvAngle(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y));
fixed_t xoffs;
fixed_t yoffs;
if (lines[i].flags & ML_NOKNUX) // Set offset through x and y texture offsets if NOKNUX flag is set
{ {
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) xoffs = sides[lines[i].sidenum[0]].textureoffset;
sectors[s].spawn_flrpic_angle = sectors[s].floorpic_angle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y); yoffs = sides[lines[i].sidenum[0]].rowoffset;
}
else // Otherwise, set calculated offsets such that line's v1 is the apparent origin
{
fixed_t cosinecomponent = FINECOSINE(flatangle>>ANGLETOFINESHIFT);
fixed_t sinecomponent = FINESINE(flatangle>>ANGLETOFINESHIFT);
xoffs = (-FixedMul(lines[i].v1->x, cosinecomponent) % MAXFLATSIZE) + (FixedMul(lines[i].v1->y, sinecomponent) % MAXFLATSIZE); // No danger of overflow thanks to the strategically placed modulo operations.
yoffs = (FixedMul(lines[i].v1->x, sinecomponent) % MAXFLATSIZE) + (FixedMul(lines[i].v1->y, cosinecomponent) % MAXFLATSIZE); // Ditto.
} }
if (!(lines[i].flags & ML_BOUNCY)) // Align ceiling unless BOUNCY flag is set for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
{ {
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) if (!(lines[i].flags & ML_NOSONIC)) // Modify floor flat alignment unless NOSONIC flag is set
sectors[s].spawn_ceilpic_angle = sectors[s].ceilingpic_angle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y);
}
}
else // Do offsets
{
if (!(lines[i].flags & ML_BLOCKMONSTERS)) // Align floor unless BLOCKMONSTERS flag is set
{
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
{ {
sectors[s].floor_xoffs += lines[i].dx; sectors[s].spawn_flrpic_angle = sectors[s].floorpic_angle = flatangle;
sectors[s].floor_yoffs += lines[i].dy; sectors[s].floor_xoffs += xoffs;
sectors[s].floor_yoffs += yoffs;
// saved for netgames // saved for netgames
sectors[s].spawn_flr_xoffs = sectors[s].floor_xoffs; sectors[s].spawn_flr_xoffs = sectors[s].floor_xoffs;
sectors[s].spawn_flr_yoffs = sectors[s].floor_yoffs; sectors[s].spawn_flr_yoffs = sectors[s].floor_yoffs;
} }
}
if (!(lines[i].flags & ML_NOCLIMB)) // Align ceiling unless NOCLIMB flag is set if (!(lines[i].flags & ML_NOTAILS)) // Modify ceiling flat alignment unless NOTAILS flag is set
{
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
{ {
sectors[s].ceiling_xoffs += lines[i].dx; sectors[s].spawn_ceilpic_angle = sectors[s].ceilingpic_angle = flatangle;
sectors[s].ceiling_yoffs += lines[i].dy; sectors[s].ceiling_xoffs += xoffs;
sectors[s].ceiling_yoffs += yoffs;
// saved for netgames // saved for netgames
sectors[s].spawn_ceil_xoffs = sectors[s].ceiling_xoffs; sectors[s].spawn_ceil_xoffs = sectors[s].ceiling_xoffs;
sectors[s].spawn_ceil_yoffs = sectors[s].ceiling_yoffs; sectors[s].spawn_ceil_yoffs = sectors[s].ceiling_yoffs;
} }
} }
} }
else // Otherwise, print a helpful warning. Can I do no less?
CONS_Alert(CONS_WARNING,
M_GetText("Flat alignment linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"),
lines[i].tag);
break; break;
case 8: // Sector Parameters case 8: // Sector Parameters
@ -5795,6 +5907,19 @@ void P_SpawnSpecials(INT32 fromnetsave)
P_AddBridgeThinker(&lines[i], &sectors[s]);*/ P_AddBridgeThinker(&lines[i], &sectors[s]);*/
break; break;
case 66: // Displace floor by front sector
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
P_AddPlaneDisplaceThinker(pd_floor, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s);
break;
case 67: // Displace ceiling by front sector
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
P_AddPlaneDisplaceThinker(pd_ceiling, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s);
break;
case 68: // Displace both floor AND ceiling by front sector
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
P_AddPlaneDisplaceThinker(pd_both, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s);
break;
case 100: // FOF (solid, opaque, shadows) case 100: // FOF (solid, opaque, shadows)
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
break; break;
@ -5809,11 +5934,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
// Draw the 'insides' of the block too // Draw the 'insides' of the block too
if (lines[i].flags & ML_NOCLIMB) if (lines[i].flags & ML_NOCLIMB)
{ {
ffloorflags |= FF_CUTLEVEL; ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES;
ffloorflags |= FF_BOTHPLANES; ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA);
ffloorflags |= FF_ALLSIDES;
ffloorflags &= ~FF_EXTRA;
ffloorflags &= ~FF_CUTEXTRA;
} }
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
@ -5920,11 +6042,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
// Draw the 'insides' of the block too // Draw the 'insides' of the block too
if (lines[i].flags & ML_EFFECT2) if (lines[i].flags & ML_EFFECT2)
{ {
ffloorflags |= FF_CUTLEVEL; ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES;
ffloorflags |= FF_BOTHPLANES; ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA);
ffloorflags |= FF_ALLSIDES;
ffloorflags &= ~FF_EXTRA;
ffloorflags &= ~FF_CUTEXTRA;
} }
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
@ -5938,11 +6057,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
// Draw the 'insides' of the block too // Draw the 'insides' of the block too
if (lines[i].flags & ML_EFFECT2) if (lines[i].flags & ML_EFFECT2)
{ {
ffloorflags |= FF_CUTLEVEL; ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES;
ffloorflags |= FF_BOTHPLANES; ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA);
ffloorflags |= FF_ALLSIDES;
ffloorflags &= ~FF_EXTRA;
ffloorflags &= ~FF_CUTEXTRA;
} }
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
@ -5966,11 +6082,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
// Draw the 'insides' of the block too // Draw the 'insides' of the block too
if (lines[i].flags & ML_EFFECT2) if (lines[i].flags & ML_EFFECT2)
{ {
ffloorflags |= FF_CUTLEVEL; ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES;
ffloorflags |= FF_BOTHPLANES; ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA);
ffloorflags |= FF_ALLSIDES;
ffloorflags &= ~FF_EXTRA;
ffloorflags &= ~FF_CUTEXTRA;
} }
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
@ -5984,11 +6097,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
// Draw the 'insides' of the block too // Draw the 'insides' of the block too
if (lines[i].flags & ML_EFFECT2) if (lines[i].flags & ML_EFFECT2)
{ {
ffloorflags |= FF_CUTLEVEL; ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES;
ffloorflags |= FF_BOTHPLANES; ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA);
ffloorflags |= FF_ALLSIDES;
ffloorflags &= ~FF_EXTRA;
ffloorflags &= ~FF_CUTEXTRA;
} }
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
@ -6166,7 +6276,13 @@ void P_SpawnSpecials(INT32 fromnetsave)
break; break;
case 250: // Mario Block case 250: // Mario Block
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO, secthinkers); ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO;
if (lines[i].flags & ML_NOCLIMB)
ffloorflags |= FF_SHATTERBOTTOM;
if (lines[i].flags & ML_EFFECT1)
ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL);
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
break; break;
case 251: // A THWOMP! case 251: // A THWOMP!
@ -6180,10 +6296,11 @@ void P_SpawnSpecials(INT32 fromnetsave)
break; break;
case 252: // Shatter block (breaks when touched) case 252: // Shatter block (breaks when touched)
ffloorflags = FF_EXISTS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER;
if (lines[i].flags & ML_NOCLIMB) if (lines[i].flags & ML_NOCLIMB)
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_SHATTER|FF_SHATTERBOTTOM, secthinkers); ffloorflags |= FF_SOLID|FF_SHATTERBOTTOM;
else
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
break; break;
case 253: // Translucent shatter block (see 76) case 253: // Translucent shatter block (see 76)
@ -6191,10 +6308,11 @@ void P_SpawnSpecials(INT32 fromnetsave)
break; break;
case 254: // Bustable block case 254: // Bustable block
ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP;
if (lines[i].flags & ML_NOCLIMB) if (lines[i].flags & ML_NOCLIMB)
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_ONLYKNUX, secthinkers); ffloorflags |= FF_ONLYKNUX;
else
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
break; break;
case 255: // Spin bust block (breaks when jumped or spun downwards onto) case 255: // Spin bust block (breaks when jumped or spun downwards onto)
@ -6206,10 +6324,11 @@ void P_SpawnSpecials(INT32 fromnetsave)
break; break;
case 257: // Quicksand case 257: // Quicksand
ffloorflags = FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES;
if (lines[i].flags & ML_EFFECT5) if (lines[i].flags & ML_EFFECT5)
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES|FF_RIPPLE, secthinkers); ffloorflags |= FF_RIPPLE;
else
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES, secthinkers); P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
break; break;
case 258: // Laser block case 258: // Laser block
@ -6970,7 +7089,6 @@ void T_Disappear(disappear_t *d)
/** Adds friction thinker. /** Adds friction thinker.
* *
* \param friction Friction value, 0xe800 is normal. * \param friction Friction value, 0xe800 is normal.
* \param movefactor Inertia factor.
* \param affectee Target sector. * \param affectee Target sector.
* \param roverfriction FOF or not * \param roverfriction FOF or not
* \sa T_Friction, P_SpawnFriction * \sa T_Friction, P_SpawnFriction
@ -7008,22 +7126,10 @@ void T_Friction(friction_t *f)
sec = sectors + f->affectee; sec = sectors + f->affectee;
// Make sure the sector type hasn't changed // Get FOF control sector
if (f->roverfriction) if (f->roverfriction)
{
referrer = sectors + f->referrer; referrer = sectors + f->referrer;
if (!(GETSECSPECIAL(referrer->special, 3) == 1
|| GETSECSPECIAL(referrer->special, 3) == 3))
return;
}
else
{
if (!(GETSECSPECIAL(sec->special, 3) == 1
|| GETSECSPECIAL(sec->special, 3) == 3))
return;
}
// Assign the friction value to players on the floor, non-floating, // Assign the friction value to players on the floor, non-floating,
// and clipped. Normally the object's friction value is kept at // and clipped. Normally the object's friction value is kept at
// ORIG_FRICTION and this thinker changes it for icy or muddy floors. // ORIG_FRICTION and this thinker changes it for icy or muddy floors.
@ -7053,14 +7159,16 @@ void T_Friction(friction_t *f)
|| (f->friction < thing->friction)) || (f->friction < thing->friction))
{ {
thing->friction = f->friction; thing->friction = f->friction;
thing->movefactor = f->movefactor; if (thing->player)
thing->movefactor = f->movefactor;
} }
} }
else if (P_GetSpecialBottomZ(thing, sec, sec) == thing->floorz && (thing->friction == ORIG_FRICTION // normal friction? else if (P_GetSpecialBottomZ(thing, sec, sec) == thing->floorz && (thing->friction == ORIG_FRICTION // normal friction?
|| f->friction < thing->friction)) || f->friction < thing->friction))
{ {
thing->friction = f->friction; thing->friction = f->friction;
thing->movefactor = f->movefactor; if (thing->player)
thing->movefactor = f->movefactor;
} }
} }
node = node->m_thinglist_next; node = node->m_thinglist_next;
@ -7076,33 +7184,32 @@ static void P_SpawnFriction(void)
size_t i; size_t i;
line_t *l = lines; line_t *l = lines;
register INT32 s; register INT32 s;
fixed_t length; // line length controls magnitude fixed_t strength; // frontside texture offset controls magnitude
fixed_t friction; // friction value to be applied during movement fixed_t friction; // friction value to be applied during movement
INT32 movefactor; // applied to each player move to simulate inertia INT32 movefactor; // applied to each player move to simulate inertia
for (i = 0; i < numlines; i++, l++) for (i = 0; i < numlines; i++, l++)
if (l->special == 540) if (l->special == 540)
{ {
length = P_AproxDistance(l->dx, l->dy)>>FRACBITS; strength = sides[l->sidenum[0]].textureoffset>>FRACBITS;
friction = (0x1EB8*length)/0x80 + 0xD000; if (strength > 0) // sludge
strength = strength*2; // otherwise, the maximum sludginess value is +967...
// The following might seem odd. At the time of movement,
// the move distance is multiplied by 'friction/0x10000', so a
// higher friction value actually means 'less friction'.
friction = ORIG_FRICTION - (0x1EB8*strength)/0x80; // ORIG_FRICTION is 0xE800
if (friction > FRACUNIT) if (friction > FRACUNIT)
friction = FRACUNIT; friction = FRACUNIT;
if (friction < 0) if (friction < 0)
friction = 0; friction = 0;
// The following check might seem odd. At the time of movement, movefactor = FixedDiv(ORIG_FRICTION, friction);
// the move distance is multiplied by 'friction/0x10000', so a if (movefactor < FRACUNIT)
// higher friction value actually means 'less friction'. movefactor = 8*movefactor - 7*FRACUNIT;
if (friction > ORIG_FRICTION) // ice
movefactor = ((0x10092 - friction)*(0x70))/0x158;
else else
movefactor = ((friction - 0xDB34)*(0xA))/0x80; movefactor = FRACUNIT;
// killough 8/28/98: prevent odd situations
if (movefactor < 32)
movefactor = 32;
for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
Add_Friction(friction, movefactor, s, -1); Add_Friction(friction, movefactor, s, -1);
@ -7352,12 +7459,10 @@ void T_Pusher(pusher_t *p)
{ {
referrer = &sectors[p->referrer]; referrer = &sectors[p->referrer];
if (!(GETSECSPECIAL(referrer->special, 3) == 2 if (GETSECSPECIAL(referrer->special, 3) != 2)
|| GETSECSPECIAL(referrer->special, 3) == 3))
return; return;
} }
else if (!(GETSECSPECIAL(sec->special, 3) == 2 else if (GETSECSPECIAL(sec->special, 3) != 2)
|| GETSECSPECIAL(sec->special, 3) == 3))
return; return;
// For constant pushers (wind/current) there are 3 situations: // For constant pushers (wind/current) there are 3 situations:

View File

@ -325,7 +325,7 @@ INT32 EV_StartCrumble(sector_t *sector, ffloor_t *rover,
INT32 EV_DoContinuousFall(sector_t *sec, sector_t *pbacksector, fixed_t spd, boolean backwards); INT32 EV_DoContinuousFall(sector_t *sec, sector_t *pbacksector, fixed_t spd, boolean backwards);
INT32 EV_MarioBlock(sector_t *sector, sector_t *roversector, fixed_t topheight, mobj_t *puncher); INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher);
void T_MoveFloor(floormove_t *movefloor); void T_MoveFloor(floormove_t *movefloor);
@ -388,7 +388,7 @@ typedef struct
{ {
thinker_t thinker; ///< Thinker structure for friction. thinker_t thinker; ///< Thinker structure for friction.
INT32 friction; ///< Friction value, 0xe800 = normal. INT32 friction; ///< Friction value, 0xe800 = normal.
INT32 movefactor; ///< Inertia factor when adding to momentum. INT32 movefactor; ///< Inertia factor when adding to momentum, FRACUNIT = normal.
INT32 affectee; ///< Number of affected sector. INT32 affectee; ///< Number of affected sector.
INT32 referrer; ///< If roverfriction == true, then this will contain the sector # of the control sector where the effect was applied. INT32 referrer; ///< If roverfriction == true, then this will contain the sector # of the control sector where the effect was applied.
UINT8 roverfriction; ///< flag for whether friction originated from a FOF or not UINT8 roverfriction; ///< flag for whether friction originated from a FOF or not
@ -450,6 +450,26 @@ void T_Disappear(disappear_t *d);
void T_Pusher(pusher_t *p); void T_Pusher(pusher_t *p);
mobj_t *P_GetPushThing(UINT32 s); mobj_t *P_GetPushThing(UINT32 s);
// Plane displacement
typedef struct
{
thinker_t thinker; ///< Thinker structure for plane displacement effect.
INT32 affectee; ///< Number of affected sector.
INT32 control; ///< Control sector used to control plane positions.
fixed_t last_height; ///< Last known height of control sector.
fixed_t speed; ///< Plane movement speed.
/** Types of plane displacement effects.
*/
enum
{
pd_floor, ///< Displace floor.
pd_ceiling, ///< Displace ceiling.
pd_both, ///< Displace both floor AND ceiling.
} type;
} planedisplace_t;
void T_PlaneDisplace(planedisplace_t *pd);
void P_CalcHeight(player_t *player); void P_CalcHeight(player_t *player);
sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo); sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo);

View File

@ -1624,6 +1624,12 @@ void P_SpawnSpinMobj(player_t *player, mobjtype_t type)
// scale // scale
P_SetScale(mobj, player->mo->scale); P_SetScale(mobj, player->mo->scale);
mobj->destscale = player->mo->scale; mobj->destscale = player->mo->scale;
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
{
mobj->frame = FF_TRANS70;
mobj->fuse = mobj->tics;
}
} }
P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do
@ -4791,6 +4797,9 @@ static void P_3dMovement(player_t *player)
acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration; acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration;
} }
if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration...
acceleration = FixedMul(acceleration<<FRACBITS, player->mo->movefactor)>>FRACBITS;
// Forward movement // Forward movement
if (player->climbing) if (player->climbing)
{ {
@ -6447,7 +6456,7 @@ static void P_SkidStuff(player_t *player)
// If your push angle is more than this close to a full 180 degrees, trigger a skid. // If your push angle is more than this close to a full 180 degrees, trigger a skid.
if (dang > ANGLE_157h) if (dang > ANGLE_157h)
{ {
player->skidtime = TICRATE/2; player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS;
S_StartSound(player->mo, sfx_skid); S_StartSound(player->mo, sfx_skid);
if (player->panim != PA_WALK) if (player->panim != PA_WALK)
P_SetPlayerMobjState(player->mo, S_PLAY_WALK); P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
@ -6484,6 +6493,9 @@ static void P_MovePlayer(player_t *player)
cmd = &player->cmd; cmd = &player->cmd;
runspd = FixedMul(player->runspeed, player->mo->scale); runspd = FixedMul(player->runspeed, player->mo->scale);
// Let's have some movement speed fun on low-friction surfaces, JUST for players... (high friction surfaces shouldn't have any adjustment, since the acceleration in this game is super high and that ends up cheesing high-friction surfaces.)
runspd = FixedMul(runspd, player->mo->movefactor);
// Control relinquishing stuff! // Control relinquishing stuff!
if (player->powers[pw_ingoop]) if (player->powers[pw_ingoop])
player->pflags |= PF_FULLSTASIS; player->pflags |= PF_FULLSTASIS;
@ -6674,6 +6686,7 @@ static void P_MovePlayer(player_t *player)
if (!player->mo->momx && !player->mo->momy && !player->mo->momz && player->panim == PA_WALK) if (!player->mo->momx && !player->mo->momy && !player->mo->momz && player->panim == PA_WALK)
P_SetPlayerMobjState(player->mo, S_PLAY_STND); P_SetPlayerMobjState(player->mo, S_PLAY_STND);
player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame.
////////////////// //////////////////
//GAMEPLAY STUFF// //GAMEPLAY STUFF//
@ -6895,7 +6908,7 @@ static void P_MovePlayer(player_t *player)
P_ResetScore(player); P_ResetScore(player);
// Show the "THOK!" graphic when spinning quickly across the ground. (even applies to non-spinners, in the case of zoom tubes) // Show the "THOK!" graphic when spinning quickly across the ground. (even applies to non-spinners, in the case of zoom tubes)
if (player->pflags & PF_SPINNING && player->speed > FixedMul(15<<FRACBITS, player->mo->scale) && !(player->pflags & PF_JUMPED)) if (player->pflags & PF_SPINNING && P_AproxDistance(player->speed, player->mo->momz) > FixedMul(15<<FRACBITS, player->mo->scale) && !(player->pflags & PF_JUMPED))
{ {
P_SpawnSpinMobj(player, player->spinitem); P_SpawnSpinMobj(player, player->spinitem);
if (demorecording) if (demorecording)

View File

@ -141,11 +141,14 @@ static INT32 tidcachelen = 0;
// R_DrawColumnInCache // R_DrawColumnInCache
// Clip and draw a column from a patch into a cached post. // Clip and draw a column from a patch into a cached post.
// //
static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 originy, INT32 cacheheight) static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight)
{ {
INT32 count, position; INT32 count, position;
UINT8 *source; UINT8 *source;
INT32 topdelta, prevdelta = -1; INT32 topdelta, prevdelta = -1;
INT32 originy = originPatch->originy;
(void)patchheight; // This parameter is unused
while (patch->topdelta != 0xff) while (patch->topdelta != 0xff)
{ {
@ -174,11 +177,16 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig
} }
} }
static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, INT32 originy, INT32 cacheheight, INT32 patchheight) //
// R_DrawFlippedColumnInCache
// Similar to R_DrawColumnInCache; it draws the column inverted, however.
//
static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight)
{ {
INT32 count, position; INT32 count, position;
UINT8 *source, *dest; UINT8 *source, *dest;
INT32 topdelta, prevdelta = -1; INT32 topdelta, prevdelta = -1;
INT32 originy = originPatch->originy;
while (patch->topdelta != 0xff) while (patch->topdelta != 0xff)
{ {
@ -212,6 +220,95 @@ static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, INT
} }
} }
//
// R_DrawTransColumnInCache
// Draws a translucent column into the cache, applying a half-cooked equation to get a proper translucency value (Needs code in R_GenerateTexture()).
//
static inline void R_DrawTransColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight)
{
INT32 count, position;
UINT8 *source, *dest;
UINT8 *mytransmap = transtables + ((8*(originPatch->alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); // The equation's not exact but it works as intended. I'll call it a day for now.
INT32 topdelta, prevdelta = -1;
INT32 originy = originPatch->originy;
(void)patchheight; // This parameter is unused
while (patch->topdelta != 0xff)
{
topdelta = patch->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
source = (UINT8 *)patch + 3;
count = patch->length;
position = originy + topdelta;
if (position < 0)
{
count += position;
source -= position; // start further down the column
position = 0;
}
if (position + count > cacheheight)
count = cacheheight - position;
dest = cache + position;
if (count > 0)
{
for (; dest < cache + position + count; source++, dest++)
if (*dest != 0xFF) *dest = *(mytransmap + ((*dest)<<8) + (*source));
}
patch = (column_t *)((UINT8 *)patch + patch->length + 4);
}
}
//
// R_DrawTransColumnInCache
// Similar to the one above except that the column is inverted.
//
static inline void R_DrawTransFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight)
{
INT32 count, position;
UINT8 *source, *dest;
UINT8 *mytransmap = transtables + ((8*(originPatch->alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); // The equation's not exact but it works as intended. I'll call it a day for now.
INT32 topdelta, prevdelta = -1;
INT32 originy = originPatch->originy;
while (patch->topdelta != 0xff)
{
topdelta = patch->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
topdelta = patchheight-patch->length-topdelta;
source = (UINT8 *)patch + 2 + patch->length; // patch + 3 + (patch->length-1)
count = patch->length;
position = originy + topdelta;
if (position < 0)
{
count += position;
source += position; // start further UP the column
position = 0;
}
if (position + count > cacheheight)
count = cacheheight - position;
dest = cache + position;
if (count > 0)
{
for (; dest < cache + position + count; --source, dest++)
if (*dest != 0xFF) *dest = *(mytransmap + ((*dest)<<8) + (*source));
}
patch = (column_t *)((UINT8 *)patch + patch->length + 4);
}
}
// //
// R_GenerateTexture // R_GenerateTexture
// //
@ -324,6 +421,18 @@ static UINT8 *R_GenerateTexture(size_t texnum)
// Composite the columns together. // Composite the columns together.
for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++)
{ {
static void (*ColumnDrawerPointer)(column_t *, UINT8 *, texpatch_t *, INT32, INT32); // Column drawing function pointer.
if ((patch->style == AST_TRANSLUCENT) && (patch->alpha <= (10*255/11))) // Alpha style set to translucent? Is the alpha small enough for translucency?
{
if (patch->alpha < 255/11) // Is the patch way too translucent? Don't render then.
continue;
ColumnDrawerPointer = (patch->flip & 2) ? R_DrawTransFlippedColumnInCache : R_DrawTransColumnInCache;
}
else
{
ColumnDrawerPointer = (patch->flip & 2) ? R_DrawFlippedColumnInCache : R_DrawColumnInCache;
}
realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
x1 = patch->originx; x1 = patch->originx;
width = SHORT(realpatch->width); width = SHORT(realpatch->width);
@ -347,10 +456,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
// generate column ofset lookup // generate column ofset lookup
colofs[x] = LONG((x * texture->height) + (texture->width*4)); colofs[x] = LONG((x * texture->height) + (texture->width*4));
if (patch->flip & 2) ColumnDrawerPointer(patchcol, block + LONG(colofs[x]), patch, texture->height, height);
R_DrawFlippedColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height, height);
else
R_DrawColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height);
} }
} }
@ -490,11 +596,11 @@ void R_LoadTextures(void)
// Allocate texture column offset table. // Allocate texture column offset table.
texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *))); texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *)));
// Allocate texture referencing cache. // Allocate texture referencing cache.
texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2));
// Allocate texture width mask table. // Allocate texture width mask table.
texturewidthmask = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); texturewidthmask = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3));
// Allocate texture height mask table. // Allocate texture height mask table.
textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4));
// Create translation table for global animation. // Create translation table for global animation.
texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL); texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL);
@ -588,6 +694,8 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
INT16 patchXPos; INT16 patchXPos;
INT16 patchYPos; INT16 patchYPos;
UINT8 flip = 0; UINT8 flip = 0;
UINT8 alpha = 255;
enum patchalphastyle style = AST_COPY;
texpatch_t *resultPatch = NULL; texpatch_t *resultPatch = NULL;
lumpnum_t patchLumpNum; lumpnum_t patchLumpNum;
@ -703,7 +811,20 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
} }
while (strcmp(texturesToken,"}")!=0) while (strcmp(texturesToken,"}")!=0)
{ {
if (stricmp(texturesToken, "FLIPX")==0) if (stricmp(texturesToken, "ALPHA")==0)
{
Z_Free(texturesToken);
texturesToken = M_GetToken(NULL);
alpha = 255*strtof(texturesToken, NULL);
}
else if (stricmp(texturesToken, "STYLE")==0)
{
Z_Free(texturesToken);
texturesToken = M_GetToken(NULL);
if(stricmp(texturesToken, "TRANSLUCENT")==0)
style = AST_TRANSLUCENT;
}
else if (stricmp(texturesToken, "FLIPX")==0)
flip |= 1; flip |= 1;
else if (stricmp(texturesToken, "FLIPY")==0) else if (stricmp(texturesToken, "FLIPY")==0)
flip |= 2; flip |= 2;
@ -736,6 +857,8 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
resultPatch->lump = patchLumpNum & 65535; resultPatch->lump = patchLumpNum & 65535;
resultPatch->wad = patchLumpNum>>16; resultPatch->wad = patchLumpNum>>16;
resultPatch->flip = flip; resultPatch->flip = flip;
resultPatch->alpha = alpha;
resultPatch->style = style;
// Clean up a little after ourselves // Clean up a little after ourselves
Z_Free(patchName); Z_Free(patchName);
// Then return it // Then return it

View File

@ -21,6 +21,9 @@
#pragma interface #pragma interface
#endif #endif
// Possible alpha types for a patch.
enum patchalphastyle {AST_COPY, AST_TRANSLUCENT}; // , AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY};
// moved here for r_sky.c (texpatch_t is used) // moved here for r_sky.c (texpatch_t is used)
// A single patch from a texture definition, // A single patch from a texture definition,
@ -32,6 +35,8 @@ typedef struct
INT16 originx, originy; INT16 originx, originy;
UINT16 wad, lump; UINT16 wad, lump;
UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both
UINT8 alpha; // Translucency value
enum patchalphastyle style;
} texpatch_t; } texpatch_t;
// A maptexturedef_t describes a rectangular texture, // A maptexturedef_t describes a rectangular texture,

View File

@ -723,10 +723,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
// Loop through R_DrawMaskedColumn calls // Loop through R_DrawMaskedColumn calls
static void R_DrawRepeatMaskedColumn(column_t *col) static void R_DrawRepeatMaskedColumn(column_t *col)
{ {
do { while (sprtopscreen < sprbotscreen) {
R_DrawMaskedColumn(col); R_DrawMaskedColumn(col);
sprtopscreen += dc_texheight*spryscale; if ((INT64)sprtopscreen + dc_texheight*spryscale > (INT64)INT32_MAX) // prevent overflow
} while (sprtopscreen < sprbotscreen); sprtopscreen = INT32_MAX;
else
sprtopscreen += dc_texheight*spryscale;
}
} }
static void R_DrawRepeatFlippedMaskedColumn(column_t *col) static void R_DrawRepeatFlippedMaskedColumn(column_t *col)

View File

@ -848,12 +848,18 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
#endif #endif
fixed_t frac; fixed_t frac;
patch_t *patch; patch_t *patch;
INT64 overflow_test;
//Fab : R_InitSprites now sets a wad lump number //Fab : R_InitSprites now sets a wad lump number
patch = W_CacheLumpNum(vis->patch, PU_CACHE); patch = W_CacheLumpNum(vis->patch, PU_CACHE);
if (!patch) if (!patch)
return; return;
// Check for overflow
overflow_test = (INT64)centeryfrac - (((INT64)vis->texturemid*vis->scale)>>FRACBITS);
if (overflow_test < 0) overflow_test = -overflow_test;
if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // fixed point mult would overflow
if (vis->transmap) if (vis->transmap)
{ {
colfunc = fuzzcolfunc; colfunc = fuzzcolfunc;

View File

@ -67,7 +67,7 @@ static patch_t *sborings;
static patch_t *sboover; static patch_t *sboover;
static patch_t *timeover; static patch_t *timeover;
static patch_t *stlivex; static patch_t *stlivex;
static patch_t *rrings; static patch_t *sboredrings;
static patch_t *getall; // Special Stage HUD static patch_t *getall; // Special Stage HUD
static patch_t *timeup; // Special Stage HUD static patch_t *timeup; // Special Stage HUD
static patch_t *hunthoming[6]; static patch_t *hunthoming[6];
@ -143,7 +143,7 @@ hudinfo_t hudinfo[NUMHUDITEMS] =
{ 16, 10}, // HUD_SCORE { 16, 10}, // HUD_SCORE
{ 128, 10}, // HUD_SCORENUM { 128, 10}, // HUD_SCORENUM
{ 17, 26}, // HUD_TIME { 16, 26}, // HUD_TIME
{ 136, 10}, // HUD_TIMESPLIT { 136, 10}, // HUD_TIMESPLIT
{ 88, 26}, // HUD_MINUTES { 88, 26}, // HUD_MINUTES
{ 188, 10}, // HUD_MINUTESSPLIT { 188, 10}, // HUD_MINUTESSPLIT
@ -251,16 +251,19 @@ void ST_LoadGraphics(void)
// but load them in R_AddSkins, that gets called // but load them in R_AddSkins, that gets called
// first anyway // first anyway
// cache the status bar overlay icons (fullscreen mode) // cache the status bar overlay icons (fullscreen mode)
sborings = W_CachePatchName("SBORINGS", PU_HUDGFX);
sboscore = W_CachePatchName("SBOSCORE", PU_HUDGFX); // Prefix "STT" is whitelisted (doesn't trigger ISGAMEMODIFIED), btw
sborings = W_CachePatchName("STTRINGS", PU_HUDGFX);
sboredrings = W_CachePatchName("STTRRING", PU_HUDGFX);
sboscore = W_CachePatchName("STTSCORE", PU_HUDGFX);
sbotime = W_CachePatchName("STTTIME", PU_HUDGFX); // Time logo
sbocolon = W_CachePatchName("STTCOLON", PU_HUDGFX); // Colon for time
sboperiod = W_CachePatchName("STTPERIO", PU_HUDGFX); // Period for time centiseconds
sboover = W_CachePatchName("SBOOVER", PU_HUDGFX); sboover = W_CachePatchName("SBOOVER", PU_HUDGFX);
timeover = W_CachePatchName("TIMEOVER", PU_HUDGFX); timeover = W_CachePatchName("TIMEOVER", PU_HUDGFX);
stlivex = W_CachePatchName("STLIVEX", PU_HUDGFX); stlivex = W_CachePatchName("STLIVEX", PU_HUDGFX);
livesback = W_CachePatchName("STLIVEBK", PU_HUDGFX); livesback = W_CachePatchName("STLIVEBK", PU_HUDGFX);
rrings = W_CachePatchName("RRINGS", PU_HUDGFX);
sbotime = W_CachePatchName("SBOTIME", PU_HUDGFX); // Time logo
sbocolon = W_CachePatchName("SBOCOLON", PU_HUDGFX); // Colon for time
sboperiod = W_CachePatchName("SBOPERIO", PU_HUDGFX); // Period for time centiseconds
nrec_timer = W_CachePatchName("NGRTIMER", PU_HUDGFX); // Timer for NiGHTS nrec_timer = W_CachePatchName("NGRTIMER", PU_HUDGFX); // Timer for NiGHTS
getall = W_CachePatchName("GETALL", PU_HUDGFX); // Special Stage HUD getall = W_CachePatchName("GETALL", PU_HUDGFX); // Special Stage HUD
timeup = W_CachePatchName("TIMEUP", PU_HUDGFX); // Special Stage HUD timeup = W_CachePatchName("TIMEUP", PU_HUDGFX); // Special Stage HUD
@ -672,7 +675,7 @@ static inline void ST_drawRings(void)
{ {
INT32 ringnum = max(stplyr->rings, 0); INT32 ringnum = max(stplyr->rings, 0);
ST_DrawPatchFromHudWS(HUD_RINGS, ((stplyr->rings <= 0 && leveltime/5 & 1) ? rrings : sborings)); ST_DrawPatchFromHudWS(HUD_RINGS, ((stplyr->rings <= 0 && leveltime/5 & 1) ? sboredrings : sborings));
if (objectplacing) if (objectplacing)
ringnum = op_currentdoomednum; ringnum = op_currentdoomednum;

View File

@ -1183,15 +1183,25 @@ int W_VerifyNMUSlumps(const char *filename)
// ENDOOM text and palette lumps // ENDOOM text and palette lumps
lumpchecklist_t NMUSlist[] = lumpchecklist_t NMUSlist[] =
{ {
{"D_", 2}, {"D_", 2}, // MIDI music
{"O_", 2}, {"O_", 2}, // Digital music
{"DS", 2}, {"DS", 2}, // Sound effects
{"ENDOOM", 6},
{"PLAYPAL", 7}, {"ENDOOM", 6}, // ENDOOM text lump
{"COLORMAP", 8},
{"PAL", 3}, {"PLAYPAL", 7}, // Palette changes
{"CLM", 3}, {"PAL", 3}, // Palette changes
{"TRANS", 5}, {"COLORMAP", 8}, // Colormap changes
{"CLM", 3}, // Colormap changes
{"TRANS", 5}, // Translucency map changes
{"LTFNT", 5}, // Level title font changes
{"TTL", 3}, // Act number changes
{"STCFN", 5}, // Console font changes
{"TNYFN", 5}, // Tiny console font changes
{"STT", 3}, // Acceptable HUD changes (Score Time Rings)
{"YB_", 3}, // Intermission graphics, goes with the above
{NULL, 0}, {NULL, 0},
}; };
return W_VerifyFile(filename, NMUSlist, false); return W_VerifyFile(filename, NMUSlist, false);