Merge branch 'next' of https://git.magicalgirl.moe/STJr/SRB2/ into udmf-next

This commit is contained in:
Nev3r 2020-07-06 11:13:27 +02:00
commit fd5b05cafc
37 changed files with 757 additions and 312 deletions

View File

@ -675,6 +675,7 @@ void D_RegisterClientCommands(void)
// GIF variables // GIF variables
CV_RegisterVar(&cv_gif_optimize); CV_RegisterVar(&cv_gif_optimize);
CV_RegisterVar(&cv_gif_downscale); CV_RegisterVar(&cv_gif_downscale);
CV_RegisterVar(&cv_gif_dynamicdelay);
CV_RegisterVar(&cv_gif_localcolortable); CV_RegisterVar(&cv_gif_localcolortable);
#ifdef WALLSPLATS #ifdef WALLSPLATS

View File

@ -49,6 +49,8 @@ typedef enum
SF_MULTIABILITY = 1<<13, // Revenge of Final Demo. SF_MULTIABILITY = 1<<13, // Revenge of Final Demo.
SF_NONIGHTSROTATION = 1<<14, // Disable sprite rotation for NiGHTS SF_NONIGHTSROTATION = 1<<14, // Disable sprite rotation for NiGHTS
SF_NONIGHTSSUPER = 1<<15, // Disable super colors for NiGHTS (if you have SF_SUPER) SF_NONIGHTSSUPER = 1<<15, // Disable super colors for NiGHTS (if you have SF_SUPER)
SF_NOSUPERSPRITES = 1<<16, // Don't use super sprites while super
SF_NOSUPERJUMPBOOST = 1<<17, // Disable the jump boost given while super (i.e. Knuckles)
// free up to and including 1<<31 // free up to and including 1<<31
} skinflags_t; } skinflags_t;
@ -285,6 +287,8 @@ typedef enum
pw_justlaunched, // Launched off a slope this tic (0=none, 1=standard launch, 2=half-pipe launch) pw_justlaunched, // Launched off a slope this tic (0=none, 1=standard launch, 2=half-pipe launch)
pw_ignorelatch, // Don't grab onto CR_GENERIC, add 32768 (powers[pw_ignorelatch] & 1<<15) to avoid ALL not-NiGHTS CR_ types
NUMPOWERS NUMPOWERS
} powertype_t; } powertype_t;

View File

@ -5334,6 +5334,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_JETJAW_CHOMP14", "S_JETJAW_CHOMP14",
"S_JETJAW_CHOMP15", "S_JETJAW_CHOMP15",
"S_JETJAW_CHOMP16", "S_JETJAW_CHOMP16",
"S_JETJAW_SOUND",
// Snailer // Snailer
"S_SNAILER1", "S_SNAILER1",
@ -8148,6 +8149,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_GFZDEBRIS", "S_GFZDEBRIS",
"S_BRICKDEBRIS", "S_BRICKDEBRIS",
"S_WOODDEBRIS", "S_WOODDEBRIS",
"S_REDBRICKDEBRIS",
"S_BLUEBRICKDEBRIS",
"S_YELLOWBRICKDEBRIS",
#ifdef SEENAMES #ifdef SEENAMES
"S_NAMECHECK", "S_NAMECHECK",
@ -8927,6 +8931,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_GFZDEBRIS", "MT_GFZDEBRIS",
"MT_BRICKDEBRIS", "MT_BRICKDEBRIS",
"MT_WOODDEBRIS", "MT_WOODDEBRIS",
"MT_REDBRICKDEBRIS",
"MT_BLUEBRICKDEBRIS",
"MT_YELLOWBRICKDEBRIS",
#ifdef SEENAMES #ifdef SEENAMES
"MT_NAMECHECK", "MT_NAMECHECK",
@ -9313,7 +9320,9 @@ static const char *const POWERS_LIST[] = {
//for dyes //for dyes
"DYE", "DYE",
"JUSTLAUNCHED" "JUSTLAUNCHED",
"IGNORELATCH"
}; };
static const char *const HUDITEMS_LIST[] = { static const char *const HUDITEMS_LIST[] = {
@ -9505,6 +9514,7 @@ struct {
{"FF_GLOBALANIM",FF_GLOBALANIM}, {"FF_GLOBALANIM",FF_GLOBALANIM},
{"FF_FULLBRIGHT",FF_FULLBRIGHT}, {"FF_FULLBRIGHT",FF_FULLBRIGHT},
{"FF_VERTICALFLIP",FF_VERTICALFLIP}, {"FF_VERTICALFLIP",FF_VERTICALFLIP},
{"FF_HORIZONTALFLIP",FF_HORIZONTALFLIP},
{"FF_PAPERSPRITE",FF_PAPERSPRITE}, {"FF_PAPERSPRITE",FF_PAPERSPRITE},
{"FF_TRANSMASK",FF_TRANSMASK}, {"FF_TRANSMASK",FF_TRANSMASK},
{"FF_TRANSSHIFT",FF_TRANSSHIFT}, {"FF_TRANSSHIFT",FF_TRANSSHIFT},
@ -9654,6 +9664,8 @@ struct {
{"SF_MULTIABILITY",SF_MULTIABILITY}, {"SF_MULTIABILITY",SF_MULTIABILITY},
{"SF_NONIGHTSROTATION",SF_NONIGHTSROTATION}, {"SF_NONIGHTSROTATION",SF_NONIGHTSROTATION},
{"SF_NONIGHTSSUPER",SF_NONIGHTSSUPER}, {"SF_NONIGHTSSUPER",SF_NONIGHTSSUPER},
{"SF_NOSUPERSPRITES",SF_NOSUPERSPRITES},
{"SF_NOSUPERJUMPBOOST",SF_NOSUPERJUMPBOOST},
// Dashmode constants // Dashmode constants
{"DASHMODE_THRESHOLD",DASHMODE_THRESHOLD}, {"DASHMODE_THRESHOLD",DASHMODE_THRESHOLD},

View File

@ -1118,9 +1118,6 @@ static const char *credits[] = {
"\1Sonic Robo Blast II", "\1Sonic Robo Blast II",
"\1Credits", "\1Credits",
"", "",
"\1Producer",
"Rob Tisdell",
"",
"\1Game Design", "\1Game Design",
"Ben \"Mystic\" Geyer", "Ben \"Mystic\" Geyer",
"\"SSNTails\"", "\"SSNTails\"",
@ -1151,11 +1148,13 @@ static const char *credits[] = {
"", "",
"\1Programming", "\1Programming",
"\1Assistance", "\1Assistance",
"Colette \"fickleheart\" Bordelon",
"\"chi.miru\"", // helped port slope drawing code from ZDoom "\"chi.miru\"", // helped port slope drawing code from ZDoom
"Andrew \"orospakr\" Clunis", "Andrew \"orospakr\" Clunis",
"Sally \"TehRealSalt\" Cochenour", "Sally \"TehRealSalt\" Cochenour",
"Gregor \"Oogaland\" Dick", "Gregor \"Oogaland\" Dick",
"Julio \"Chaos Zero 64\" Guir", "Julio \"Chaos Zero 64\" Guir",
"\"Hannu_Hanhi\"", // For many OpenGL performance improvements!
"\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog "\"Kalaron\"", // Coded some of Sryder13's collection of OpenGL fixes, especially fog
"\"Lat'\"", // SRB2-CHAT, the chat window from Kart "\"Lat'\"", // SRB2-CHAT, the chat window from Kart
"Matthew \"Shuffle\" Marsalko", "Matthew \"Shuffle\" Marsalko",
@ -1166,6 +1165,7 @@ static const char *credits[] = {
"Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible "Tasos \"tatokis\" Sahanidis", // Corrected C FixedMul, making 64-bit builds netplay compatible
"Wessel \"sphere\" Smit", "Wessel \"sphere\" Smit",
"Ben \"Cue\" Woodford", "Ben \"Cue\" Woodford",
"\"VelocitOni\"", // Wrote the original dashmode script
"Ikaro \"Tatsuru\" Vinhas", "Ikaro \"Tatsuru\" Vinhas",
// Git contributors with 5+ approved merges of substantive quality, // Git contributors with 5+ approved merges of substantive quality,
// or contributors with at least one groundbreaking merge, may be named. // or contributors with at least one groundbreaking merge, may be named.
@ -1174,6 +1174,7 @@ static const char *credits[] = {
"\1Art", "\1Art",
"Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D: "Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D:
"Ryan \"Blaze Hedgehog\" Bloom", "Ryan \"Blaze Hedgehog\" Bloom",
"\"ChrispyPixels\"",
"Paul \"Boinciel\" Clempson", "Paul \"Boinciel\" Clempson",
"Sally \"TehRealSalt\" Cochenour", "Sally \"TehRealSalt\" Cochenour",
"\"Dave Lite\"", "\"Dave Lite\"",
@ -1220,6 +1221,7 @@ static const char *credits[] = {
"\"SSNTails\"", "\"SSNTails\"",
"", "",
"\1Level Design", "\1Level Design",
"Colette \"fickleheart\" Bordelon",
"Hank \"FuriousFox\" Brannock", "Hank \"FuriousFox\" Brannock",
"Matthew \"Fawfulfan\" Chapman", "Matthew \"Fawfulfan\" Chapman",
"Paul \"Boinciel\" Clempson", "Paul \"Boinciel\" Clempson",
@ -1255,6 +1257,7 @@ static const char *credits[] = {
"Johnny \"Sonikku\" Wallbank", "Johnny \"Sonikku\" Wallbank",
"", "",
"\1Testing", "\1Testing",
"Discord Community Testers",
"Hank \"FuriousFox\" Brannock", "Hank \"FuriousFox\" Brannock",
"Cody \"SRB2 Playah\" Koester", "Cody \"SRB2 Playah\" Koester",
"Skye \"OmegaVelocity\" Meredith", "Skye \"OmegaVelocity\" Meredith",

View File

@ -720,14 +720,14 @@ void G_SetNightsRecords(void)
I_Error("Out of memory for replay filepath\n"); I_Error("Out of memory for replay filepath\n");
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
snprintf(lastdemo, 255, "%s-last.lmp", gpath); snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, skins[cv_chooseskin.value-1].name);
if (FIL_FileExists(lastdemo)) if (FIL_FileExists(lastdemo))
{ {
UINT8 *buf; UINT8 *buf;
size_t len = FIL_ReadFile(lastdemo, &buf); size_t len = FIL_ReadFile(lastdemo, &buf);
snprintf(bestdemo, 255, "%s-time-best.lmp", gpath); snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, skins[cv_chooseskin.value-1].name);;
if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1)
{ // Better time, save this demo. { // Better time, save this demo.
if (FIL_FileExists(bestdemo)) if (FIL_FileExists(bestdemo))
@ -736,7 +736,7 @@ void G_SetNightsRecords(void)
CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo);
} }
snprintf(bestdemo, 255, "%s-score-best.lmp", gpath); snprintf(bestdemo, 255, "%s-%s-score-best.lmp", gpath, skins[cv_chooseskin.value-1].name);
if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))) if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)))
{ // Better score, save this demo. { // Better score, save this demo.
if (FIL_FileExists(bestdemo)) if (FIL_FileExists(bestdemo))

View File

@ -50,7 +50,7 @@ EXPORT void HWRAPI(ClearMipMapCache) (void);
EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value);
//Hurdler: added for new development //Hurdler: added for new development
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface); EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface);
EXPORT void HWRAPI(CreateModelVBOs) (model_t *model); EXPORT void HWRAPI(CreateModelVBOs) (model_t *model);
EXPORT void HWRAPI(SetTransform) (FTransform *ptransform); EXPORT void HWRAPI(SetTransform) (FTransform *ptransform);
EXPORT INT32 HWRAPI(GetTextureUsed) (void); EXPORT INT32 HWRAPI(GetTextureUsed) (void);

View File

@ -605,6 +605,9 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_GFZD &lspr[NOLIGHT], // SPR_GFZD
&lspr[NOLIGHT], // SPR_BRIC &lspr[NOLIGHT], // SPR_BRIC
&lspr[NOLIGHT], // SPR_WDDB &lspr[NOLIGHT], // SPR_WDDB
&lspr[NOLIGHT], // SPR_BRIR
&lspr[NOLIGHT], // SPR_BRIB
&lspr[NOLIGHT], // SPR_BRIY
// Gravity Well Objects // Gravity Well Objects
&lspr[NOLIGHT], // SPR_GWLG &lspr[NOLIGHT], // SPR_GWLG

View File

@ -4613,6 +4613,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
unsigned rot; unsigned rot;
UINT16 flip; UINT16 flip;
boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP)); boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP));
boolean mirrored = thing->mirrored;
boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored);
angle_t ang; angle_t ang;
INT32 heightsec, phs; INT32 heightsec, phs;
@ -4701,6 +4703,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
#endif #endif
ang = R_PointToAngle (thing->x, thing->y) - mobjangle; ang = R_PointToAngle (thing->x, thing->y) - mobjangle;
if (mirrored)
ang = InvAngle(ang);
if (sprframe->rotate == SRF_SINGLE) if (sprframe->rotate == SRF_SINGLE)
{ {
@ -4773,6 +4777,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
rightcos = FIXED_TO_FLOAT(FINECOSINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); rightcos = FIXED_TO_FLOAT(FINECOSINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT));
} }
flip = !flip != !hflip;
if (flip) if (flip)
{ {
x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_scale); x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_scale);

View File

@ -1242,6 +1242,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
//mdlframe_t *next = NULL; //mdlframe_t *next = NULL;
const boolean papersprite = (spr->mobj->frame & FF_PAPERSPRITE); const boolean papersprite = (spr->mobj->frame & FF_PAPERSPRITE);
const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP)); const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP));
const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !(spr->mobj->frame & FF_HORIZONTALFLIP));
spritedef_t *sprdef; spritedef_t *sprdef;
spriteframe_t *sprframe; spriteframe_t *sprframe;
spriteinfo_t *sprinfo; spriteinfo_t *sprinfo;
@ -1514,7 +1515,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
#endif #endif
HWD.pfnSetShader(4); // model shader HWD.pfnSetShader(4); // model shader
HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, &Surf); HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf);
} }
return true; return true;

View File

@ -2615,7 +2615,7 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model)
#define BUFFER_OFFSET(i) ((void*)(i)) #define BUFFER_OFFSET(i) ((void*)(i))
static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface) static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
{ {
static GLRGBAFloat poly = {0,0,0,0}; static GLRGBAFloat poly = {0,0,0,0};
static GLRGBAFloat tint = {0,0,0,0}; static GLRGBAFloat tint = {0,0,0,0};
@ -2708,12 +2708,13 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
pglEnable(GL_NORMALIZE); pglEnable(GL_NORMALIZE);
#ifdef USE_FTRANSFORM_MIRROR #ifdef USE_FTRANSFORM_MIRROR
// flipped is if the object is flipped // flipped is if the object is vertically flipped
// hflipped is if the object is horizontally flipped
// pos->flip is if the screen is flipped vertically // pos->flip is if the screen is flipped vertically
// pos->mirror is if the screen is flipped horizontally // pos->mirror is if the screen is flipped horizontally
// XOR all the flips together to figure out what culling to use! // XOR all the flips together to figure out what culling to use!
{ {
boolean reversecull = (flipped ^ pos->flip ^ pos->mirror); boolean reversecull = (flipped ^ hflipped ^ pos->flip ^ pos->mirror);
if (reversecull) if (reversecull)
pglCullFace(GL_FRONT); pglCullFace(GL_FRONT);
else else
@ -2721,7 +2722,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
} }
#else #else
// pos->flip is if the screen is flipped too // pos->flip is if the screen is flipped too
if (flipped != pos->flip) // If either are active, but not both, invert the model's culling if (flipped ^ hflipped ^ pos->flip) // If one or three of these are active, but not two, invert the model's culling
{ {
pglCullFace(GL_FRONT); pglCullFace(GL_FRONT);
} }
@ -2736,6 +2737,8 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
pglTranslatef(pos->x, pos->z, pos->y); pglTranslatef(pos->x, pos->z, pos->y);
if (flipped) if (flipped)
scaley = -scaley; scaley = -scaley;
if (hflipped)
scalez = -scalez;
#ifdef USE_FTRANSFORM_ANGLEZ #ifdef USE_FTRANSFORM_ANGLEZ
pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); // rotate by slope from Kart pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); // rotate by slope from Kart
@ -2882,9 +2885,9 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32
// -----------------+ // -----------------+
// HWRAPI DrawModel : Draw a model // HWRAPI DrawModel : Draw a model
// -----------------+ // -----------------+
EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface) EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface)
{ {
DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, Surface); DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, hflipped, Surface);
} }
// -----------------+ // -----------------+

View File

@ -2240,7 +2240,7 @@ void HU_Erase(void)
// IN-LEVEL MULTIPLAYER RANKINGS // IN-LEVEL MULTIPLAYER RANKINGS
//====================================================================== //======================================================================
#define supercheckdef ((players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS1] || players[tab[i].num].mo->state >= &states[S_PLAY_SUPER_TRANS6])) || (players[tab[i].num].powers[pw_carry] == CR_NIGHTSMODE && skins[players[tab[i].num].skin].flags & SF_SUPER)) #define supercheckdef (!(players[tab[i].num].charflags & SF_NOSUPERSPRITES) && ((players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS1] || players[tab[i].num].mo->state >= &states[S_PLAY_SUPER_TRANS6])) || (players[tab[i].num].powers[pw_carry] == CR_NIGHTSMODE && skins[players[tab[i].num].skin].flags & SF_SUPER)))
#define greycheckdef (players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD || (G_IsSpecialStage(gamemap) && players[tab[i].num].exiting)) #define greycheckdef (players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD || (G_IsSpecialStage(gamemap) && players[tab[i].num].exiting))
// //
@ -2798,7 +2798,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor
if (tab[i].color == 0) if (tab[i].color == 0)
{ {
colormap = colormaps; colormap = colormaps;
if (players[tab[i].num].powers[pw_super]) if (players[tab[i].num].powers[pw_super] && !(players[tab[i].num].charflags & SF_NOSUPERSPRITES))
V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, 0, superprefix[players[tab[i].num].skin], 0); V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, 0, superprefix[players[tab[i].num].skin], 0);
else else
{ {

View File

@ -510,6 +510,9 @@ char sprnames[NUMSPRITES + 1][5] =
"GFZD", // GFZ debris "GFZD", // GFZ debris
"BRIC", // Bricks "BRIC", // Bricks
"WDDB", // Wood Debris "WDDB", // Wood Debris
"BRIR", // CEZ3 colored bricks
"BRIB", // CEZ3 colored bricks
"BRIY", // CEZ3 colored bricks
// Gravity Well Objects // Gravity Well Objects
"GWLG", "GWLG",
@ -724,7 +727,7 @@ state_t states[NUMSTATES] =
// CA_GLIDEANDCLIMB // CA_GLIDEANDCLIMB
{SPR_PLAY, SPR2_GLID, 2, {NULL}, 0, 0, S_PLAY_GLIDE}, // S_PLAY_GLIDE {SPR_PLAY, SPR2_GLID, 2, {NULL}, 0, 0, S_PLAY_GLIDE}, // S_PLAY_GLIDE
{SPR_PLAY, SPR2_LAND, 9, {NULL}, 0, 0, S_PLAY_STND}, // S_PLAY_GLIDE_LANDING {SPR_PLAY, SPR2_LAND, 7, {NULL}, 0, 0, S_PLAY_STND}, // S_PLAY_GLIDE_LANDING
{SPR_PLAY, SPR2_CLNG|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_CLING {SPR_PLAY, SPR2_CLNG|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_CLING
{SPR_PLAY, SPR2_CLMB, 5, {NULL}, 0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB {SPR_PLAY, SPR2_CLMB, 5, {NULL}, 0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB
@ -966,30 +969,31 @@ state_t states[NUMSTATES] =
{SPR_CSPR, 1, 1, {A_CrushclawAim}, 50, 20, S_CDIAG1}, // S_CDIAG8 {SPR_CSPR, 1, 1, {A_CrushclawAim}, 50, 20, S_CDIAG1}, // S_CDIAG8
// Jet Jaw // Jet Jaw
{SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM2}, // S_JETJAW_ROAM1 {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM2}, // S_JETJAW_ROAM1
{SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM3}, // S_JETJAW_ROAM2 {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM3}, // S_JETJAW_ROAM2
{SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM4}, // S_JETJAW_ROAM3 {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM4}, // S_JETJAW_ROAM3
{SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM5}, // S_JETJAW_ROAM4 {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM5}, // S_JETJAW_ROAM4
{SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM6}, // S_JETJAW_ROAM5 {SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM6}, // S_JETJAW_ROAM5
{SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM7}, // S_JETJAW_ROAM6 {SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM7}, // S_JETJAW_ROAM6
{SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM8}, // S_JETJAW_ROAM7 {SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM8}, // S_JETJAW_ROAM7
{SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM1}, // S_JETJAW_ROAM8 {SPR_JJAW, 1, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM1}, // S_JETJAW_ROAM8
{SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP2}, // S_JETJAW_CHOMP1 {SPR_JJAW, 0, 1, {A_DualAction}, S_JETJAW_CHOMP16, S_JETJAW_SOUND, S_JETJAW_CHOMP2}, // S_JETJAW_CHOMP1
{SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP3}, // S_JETJAW_CHOMP2 {SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP3}, // S_JETJAW_CHOMP2
{SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP4}, // S_JETJAW_CHOMP3 {SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP4}, // S_JETJAW_CHOMP3
{SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP5}, // S_JETJAW_CHOMP4 {SPR_JJAW, 0, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP5}, // S_JETJAW_CHOMP4
{SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP6}, // S_JETJAW_CHOMP5 {SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP6}, // S_JETJAW_CHOMP5
{SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP7}, // S_JETJAW_CHOMP6 {SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP7}, // S_JETJAW_CHOMP6
{SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP8}, // S_JETJAW_CHOMP7 {SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP8}, // S_JETJAW_CHOMP7
{SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP9}, // S_JETJAW_CHOMP8 {SPR_JJAW, 1, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP9}, // S_JETJAW_CHOMP8
{SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP10}, // S_JETJAW_CHOMP9 {SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP10}, // S_JETJAW_CHOMP9
{SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP11}, // S_JETJAW_CHOMP10 {SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP11}, // S_JETJAW_CHOMP10
{SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP12}, // S_JETJAW_CHOMP11 {SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP12}, // S_JETJAW_CHOMP11
{SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP13}, // S_JETJAW_CHOMP12 {SPR_JJAW, 2, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP13}, // S_JETJAW_CHOMP12
{SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP14}, // S_JETJAW_CHOMP13 {SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP14}, // S_JETJAW_CHOMP13
{SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP15}, // S_JETJAW_CHOMP14 {SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP15}, // S_JETJAW_CHOMP14
{SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP16}, // S_JETJAW_CHOMP15 {SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP16}, // S_JETJAW_CHOMP15
{SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP1}, // S_JETJAW_CHOMP16 {SPR_JJAW, 3, 1, {A_JetJawChomp}, 0, 0, S_JETJAW_CHOMP1}, // S_JETJAW_CHOMP16
{SPR_JJAW, 0, 1, {A_PlayAttackSound}, 0, 0, S_JETJAW_SOUND}, // S_JETJAW_SOUND
// Snailer // Snailer
{SPR_SNLR, 0, 1, {A_SnailerThink}, 0, 0, S_SNAILER1}, // S_SNAILER1 {SPR_SNLR, 0, 1, {A_SnailerThink}, 0, 0, S_SNAILER1}, // S_SNAILER1
@ -2929,11 +2933,11 @@ state_t states[NUMSTATES] =
{SPR_IVSP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL}, // S_IVSP {SPR_IVSP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL}, // S_IVSP
// Super Sonic Spark // Super Sonic Spark
{SPR_SSPK, 0, 2, {NULL}, 0, 0, S_SSPK2}, // S_SSPK1 {SPR_SSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK2}, // S_SSPK1
{SPR_SSPK, 1, 2, {NULL}, 0, 0, S_SSPK3}, // S_SSPK2 {SPR_SSPK, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK3}, // S_SSPK2
{SPR_SSPK, 2, 2, {NULL}, 0, 0, S_SSPK4}, // S_SSPK3 {SPR_SSPK, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK4}, // S_SSPK3
{SPR_SSPK, 1, 2, {NULL}, 0, 0, S_SSPK5}, // S_SSPK4 {SPR_SSPK, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_SSPK5}, // S_SSPK4
{SPR_SSPK, 0, 2, {NULL}, 0, 0, S_NULL}, // S_SSPK5 {SPR_SSPK, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_SSPK5
// Flicky-sized bubble // Flicky-sized bubble
{SPR_FBUB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FLICKY_BUBBLE {SPR_FBUB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FLICKY_BUBBLE
@ -3913,6 +3917,9 @@ state_t states[NUMSTATES] =
{SPR_GFZD, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_GFZDEBRIS {SPR_GFZD, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_GFZDEBRIS
{SPR_BRIC, FF_ANIMATE, -1, {A_DebrisRandom}, 7, 2, S_NULL}, // S_BRICKDEBRIS {SPR_BRIC, FF_ANIMATE, -1, {A_DebrisRandom}, 7, 2, S_NULL}, // S_BRICKDEBRIS
{SPR_WDDB, FF_ANIMATE, -1, {A_DebrisRandom}, 7, 2, S_NULL}, // S_WOODDEBRIS {SPR_WDDB, FF_ANIMATE, -1, {A_DebrisRandom}, 7, 2, S_NULL}, // S_WOODDEBRIS
{SPR_BRIR, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_REDBRICKDEBRIS
{SPR_BRIB, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_BLUEBRICKDEBRIS
{SPR_BRIY, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 31, 1, S_NULL}, // S_YELLOWBRICKDEBRIS
#ifdef SEENAMES #ifdef SEENAMES
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
@ -4576,7 +4583,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_JETJAW_CHOMP1,// seestate S_JETJAW_CHOMP1,// seestate
sfx_None, // seesound sfx_None, // seesound
4*TICRATE, // reactiontime 4*TICRATE, // reactiontime
sfx_None, // attacksound sfx_s1ab, // attacksound
S_NULL, // painstate S_NULL, // painstate
0, // painchance 0, // painchance
sfx_None, // painsound sfx_None, // painsound
@ -5294,7 +5301,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass 100, // mass
0, // damage 0, // damage
sfx_None, // activesound sfx_None, // activesound
MF_SPECIAL|MF_SHOOTABLE|MF_ENEMY|MF_NOGRAVITY|MF_BOUNCE|MF_RUNSPAWNFUNC, // flags MF_SPECIAL|MF_SHOOTABLE|MF_ENEMY|MF_NOGRAVITY|MF_SLIDEME|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate S_NULL // raisestate
}, },
@ -21562,6 +21569,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate S_NULL // raisestate
}, },
{ // MT_REDBRICKDEBRIS
-1, // doomednum
S_REDBRICKDEBRIS, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // 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
32*FRACUNIT, // radius
64*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_BLUEBRICKDEBRIS
-1, // doomednum
S_BLUEBRICKDEBRIS, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // 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
32*FRACUNIT, // radius
64*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_YELLOWBRICKDEBRIS
-1, // doomednum
S_YELLOWBRICKDEBRIS, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // 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
32*FRACUNIT, // radius
64*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_crumbl, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},
#ifdef SEENAMES #ifdef SEENAMES
{ // MT_NAMECHECK { // MT_NAMECHECK
-1, // doomednum -1, // doomednum

View File

@ -774,6 +774,9 @@ typedef enum sprite
SPR_GFZD, // GFZ debris SPR_GFZD, // GFZ debris
SPR_BRIC, // Bricks SPR_BRIC, // Bricks
SPR_WDDB, // Wood Debris SPR_WDDB, // Wood Debris
SPR_BRIR, // CEZ3 colored bricks
SPR_BRIB,
SPR_BRIY,
// Gravity Well Objects // Gravity Well Objects
SPR_GWLG, SPR_GWLG,
@ -1186,6 +1189,7 @@ typedef enum state
S_JETJAW_CHOMP14, S_JETJAW_CHOMP14,
S_JETJAW_CHOMP15, S_JETJAW_CHOMP15,
S_JETJAW_CHOMP16, S_JETJAW_CHOMP16,
S_JETJAW_SOUND,
// Snailer // Snailer
S_SNAILER1, S_SNAILER1,
@ -4000,6 +4004,9 @@ typedef enum state
S_GFZDEBRIS, S_GFZDEBRIS,
S_BRICKDEBRIS, S_BRICKDEBRIS,
S_WOODDEBRIS, S_WOODDEBRIS,
S_REDBRICKDEBRIS, // for CEZ3
S_BLUEBRICKDEBRIS, // for CEZ3
S_YELLOWBRICKDEBRIS, // for CEZ3
#ifdef SEENAMES #ifdef SEENAMES
S_NAMECHECK, S_NAMECHECK,
@ -4799,6 +4806,9 @@ typedef enum mobj_type
MT_GFZDEBRIS, MT_GFZDEBRIS,
MT_BRICKDEBRIS, MT_BRICKDEBRIS,
MT_WOODDEBRIS, MT_WOODDEBRIS,
MT_REDBRICKDEBRIS, // for CEZ3
MT_BLUEBRICKDEBRIS, // for CEZ3
MT_YELLOWBRICKDEBRIS, // for CEZ3
#ifdef SEENAMES #ifdef SEENAMES
MT_NAMECHECK, MT_NAMECHECK,

View File

@ -2068,7 +2068,7 @@ msgstr ""
#: m_cheat.c:292 #: m_cheat.c:292
#, c-format #, c-format
msgid "Sissy Mode %s\n" msgid "Cheese Mode %s\n"
msgstr "" msgstr ""
#: m_cheat.c:315 m_cheat.c:349 m_cheat.c:514 m_cheat.c:538 m_cheat.c:557 #: m_cheat.c:315 m_cheat.c:349 m_cheat.c:514 m_cheat.c:538 m_cheat.c:557

View File

@ -2145,7 +2145,7 @@ msgstr ""
#: m_cheat.c:294 #: m_cheat.c:294
#, c-format #, c-format
msgid "Sissy Mode %s\n" msgid "Cheese Mode %s\n"
msgstr "" msgstr ""
#: m_cheat.c:314 #: m_cheat.c:314

View File

@ -1264,6 +1264,19 @@ static int lib_pElementalFire(lua_State *L)
return 0; return 0;
} }
static int lib_pSpawnSkidDust(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
fixed_t radius = luaL_checkfixed(L, 2);
boolean sound = lua_optboolean(L, 3);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_SpawnSkidDust(player, radius, sound);
return 0;
}
static int lib_pDoPlayerFinish(lua_State *L) static int lib_pDoPlayerFinish(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));
@ -1351,6 +1364,19 @@ static int lib_pNukeEnemies(lua_State *L)
return 0; return 0;
} }
static int lib_pEarthquake(lua_State *L)
{
mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t radius = luaL_checkfixed(L, 3);
NOHUD
INLEVEL
if (!inflictor || !source)
return LUA_ErrInvalid(L, "mobj_t");
P_Earthquake(inflictor, source, radius);
return 0;
}
static int lib_pHomingAttack(lua_State *L) 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));
@ -1559,11 +1585,12 @@ 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);
UINT8 damagetype = luaL_optinteger(L, 4, 0); UINT8 damagetype = luaL_optinteger(L, 4, 0);
boolean sightcheck = lua_opttrueboolean(L, 5);
NOHUD NOHUD
INLEVEL INLEVEL
if (!spot || !source) if (!spot || !source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_RadiusAttack(spot, source, damagedist, damagetype); P_RadiusAttack(spot, source, damagedist, damagetype, sightcheck);
return 0; return 0;
} }
@ -3267,6 +3294,7 @@ static luaL_Reg lib[] = {
{"P_DoBubbleBounce",lib_pDoBubbleBounce}, {"P_DoBubbleBounce",lib_pDoBubbleBounce},
{"P_BlackOw",lib_pBlackOw}, {"P_BlackOw",lib_pBlackOw},
{"P_ElementalFire",lib_pElementalFire}, {"P_ElementalFire",lib_pElementalFire},
{"P_SpawnSkidDust", lib_pSpawnSkidDust},
{"P_DoPlayerFinish",lib_pDoPlayerFinish}, {"P_DoPlayerFinish",lib_pDoPlayerFinish},
{"P_DoPlayerExit",lib_pDoPlayerExit}, {"P_DoPlayerExit",lib_pDoPlayerExit},
{"P_InstaThrust",lib_pInstaThrust}, {"P_InstaThrust",lib_pInstaThrust},
@ -3274,6 +3302,7 @@ static luaL_Reg lib[] = {
{"P_ReturnThrustY",lib_pReturnThrustY}, {"P_ReturnThrustY",lib_pReturnThrustY},
{"P_LookForEnemies",lib_pLookForEnemies}, {"P_LookForEnemies",lib_pLookForEnemies},
{"P_NukeEnemies",lib_pNukeEnemies}, {"P_NukeEnemies",lib_pNukeEnemies},
{"P_Earthquake",lib_pEarthquake},
{"P_HomingAttack",lib_pHomingAttack}, {"P_HomingAttack",lib_pHomingAttack},
{"P_SuperReady",lib_pSuperReady}, {"P_SuperReady",lib_pSuperReady},
{"P_DoJump",lib_pDoJump}, {"P_DoJump",lib_pDoJump},

View File

@ -88,6 +88,7 @@ enum mobj_e {
mobj_cvmem, mobj_cvmem,
mobj_standingslope, mobj_standingslope,
mobj_colorized, mobj_colorized,
mobj_mirrored,
mobj_shadowscale mobj_shadowscale
}; };
@ -156,6 +157,7 @@ static const char *const mobj_opt[] = {
"cvmem", "cvmem",
"standingslope", "standingslope",
"colorized", "colorized",
"mirrored",
"shadowscale", "shadowscale",
NULL}; NULL};
@ -395,6 +397,9 @@ static int mobj_get(lua_State *L)
case mobj_colorized: case mobj_colorized:
lua_pushboolean(L, mo->colorized); lua_pushboolean(L, mo->colorized);
break; break;
case mobj_mirrored:
lua_pushboolean(L, mo->mirrored);
break;
case mobj_shadowscale: case mobj_shadowscale:
lua_pushfixed(L, mo->shadowscale); lua_pushfixed(L, mo->shadowscale);
break; break;
@ -729,6 +734,9 @@ static int mobj_set(lua_State *L)
case mobj_colorized: case mobj_colorized:
mo->colorized = luaL_checkboolean(L, 3); mo->colorized = luaL_checkboolean(L, 3);
break; break;
case mobj_mirrored:
mo->mirrored = luaL_checkboolean(L, 3);
break;
case mobj_shadowscale: case mobj_shadowscale:
mo->shadowscale = luaL_checkfixed(L, 3); mo->shadowscale = luaL_checkfixed(L, 3);
break; break;

View File

@ -18,6 +18,7 @@
#include "z_zone.h" #include "z_zone.h"
#include "v_video.h" #include "v_video.h"
#include "i_video.h" #include "i_video.h"
#include "i_system.h" // I_GetTimeMicros
#include "m_misc.h" #include "m_misc.h"
#include "st_stuff.h" // st_palette #include "st_stuff.h" // st_palette
@ -30,11 +31,13 @@
consvar_t cv_gif_optimize = {"gif_optimize", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_gif_optimize = {"gif_optimize", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gif_downscale = {"gif_downscale", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_gif_downscale = {"gif_downscale", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gif_dynamicdelay = {"gif_dynamicdelay", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_gif_localcolortable = {"gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_gif_localcolortable = {"gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#ifdef HAVE_ANIGIF #ifdef HAVE_ANIGIF
static boolean gif_optimize = false; // So nobody can do something dumb static boolean gif_optimize = false; // So nobody can do something dumb
static boolean gif_downscale = false; // like changing cvars mid output static boolean gif_downscale = false; // like changing cvars mid output
static boolean gif_dynamicdelay = false; // and messing something up
// Palette handling // Palette handling
static boolean gif_localcolortable = false; static boolean gif_localcolortable = false;
@ -44,6 +47,7 @@ static RGBA_t *gif_framepalette = NULL;
static FILE *gif_out = NULL; static FILE *gif_out = NULL;
static INT32 gif_frames = 0; static INT32 gif_frames = 0;
static UINT32 gif_prevframems = 0;
static UINT8 gif_writeover = 0; static UINT8 gif_writeover = 0;
@ -588,11 +592,25 @@ static void GIF_framewrite(void)
// screen regions are handled in GIF_lzw // screen regions are handled in GIF_lzw
{ {
int d1 = (int)((100.0f/NEWTICRATE)*(gif_frames+1)); UINT16 delay;
int d2 = (int)((100.0f/NEWTICRATE)*(gif_frames));
UINT16 delay = d1-d2;
INT32 startline; INT32 startline;
if (gif_dynamicdelay) {
// golden's attempt at creating a "dynamic delay"
float delayf = ceil(100.0f/NEWTICRATE);
delay = (UINT16)((I_GetTimeMicros() - gif_prevframems)/10/1000);
if (delay < (int)(delayf))
delay = (int)(delayf);
}
else
{
// the original code
int d1 = (int)((100.0f/NEWTICRATE)*(gif_frames+1));
int d2 = (int)((100.0f/NEWTICRATE)*(gif_frames));
delay = d1-d2;
}
WRITEMEM(p, gifframe_gchead, 4); WRITEMEM(p, gifframe_gchead, 4);
WRITEUINT16(p, delay); WRITEUINT16(p, delay);
@ -670,6 +688,7 @@ static void GIF_framewrite(void)
} }
fwrite(gifframe_data, 1, (p - gifframe_data), gif_out); fwrite(gifframe_data, 1, (p - gifframe_data), gif_out);
++gif_frames; ++gif_frames;
gif_prevframems = I_GetTimeMicros();
} }
@ -690,12 +709,14 @@ INT32 GIF_open(const char *filename)
gif_optimize = (!!cv_gif_optimize.value); gif_optimize = (!!cv_gif_optimize.value);
gif_downscale = (!!cv_gif_downscale.value); gif_downscale = (!!cv_gif_downscale.value);
gif_dynamicdelay = (!!cv_gif_dynamicdelay.value);
gif_localcolortable = (!!cv_gif_localcolortable.value); gif_localcolortable = (!!cv_gif_localcolortable.value);
gif_colorprofile = (!!cv_screenshot_colorprofile.value); gif_colorprofile = (!!cv_screenshot_colorprofile.value);
gif_headerpalette = GIF_getpalette(0); gif_headerpalette = GIF_getpalette(0);
GIF_headwrite(); GIF_headwrite();
gif_frames = 0; gif_frames = 0;
gif_prevframems = I_GetTimeMicros();
return 1; return 1;
} }

View File

@ -27,6 +27,6 @@ void GIF_frame(void);
INT32 GIF_close(void); INT32 GIF_close(void);
#endif #endif
extern consvar_t cv_gif_optimize, cv_gif_downscale, cv_gif_localcolortable; extern consvar_t cv_gif_optimize, cv_gif_downscale, cv_gif_dynamicdelay, cv_gif_localcolortable;
#endif #endif

View File

@ -288,7 +288,7 @@ void Command_CheatGod_f(void)
plyr = &players[consoleplayer]; plyr = &players[consoleplayer];
plyr->pflags ^= PF_GODMODE; plyr->pflags ^= PF_GODMODE;
CONS_Printf(M_GetText("Sissy Mode %s\n"), plyr->pflags & PF_GODMODE ? M_GetText("On") : M_GetText("Off")); CONS_Printf(M_GetText("Cheese Mode %s\n"), plyr->pflags & PF_GODMODE ? M_GetText("On") : M_GetText("Off"));
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer);
} }

View File

@ -759,17 +759,18 @@ static menuitem_t SR_EmblemHintMenu[] =
// Single Player Main // Single Player Main
static menuitem_t SP_MainMenu[] = static menuitem_t SP_MainMenu[] =
{ {
// Note: If changing the positions here, also change them in M_SinglePlayerMenu()
{IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 76}, {IT_CALL | IT_STRING, NULL, "Start Game", M_LoadGame, 76},
{IT_SECRET, NULL, "Record Attack", M_TimeAttack, 84}, {IT_SECRET, NULL, "Record Attack", M_TimeAttack, 84},
{IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 92}, {IT_SECRET, NULL, "NiGHTS Mode", M_NightsAttack, 92},
{IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Marathon Run", M_Marathon, 100}, {IT_SECRET, NULL, "Marathon Run", M_Marathon, 100},
{IT_CALL | IT_STRING, NULL, "Tutorial", M_StartTutorial, 108}, {IT_CALL | IT_STRING, NULL, "Tutorial", M_StartTutorial, 108},
{IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 116} {IT_CALL | IT_STRING | IT_CALL_NOTMODIFIED, NULL, "Statistics", M_Statistics, 116}
}; };
enum enum
{ {
sploadgame, spstartgame,
sprecordattack, sprecordattack,
spnightsmode, spnightsmode,
spmarathon, spmarathon,
@ -2276,6 +2277,9 @@ void Nextmap_OnChange(void)
{ {
char *leveltitle; char *leveltitle;
char tabase[256]; char tabase[256];
#ifdef OLDNREPLAYNAME
char tabaseold[256];
#endif
short i; short i;
boolean active; boolean active;
@ -2300,11 +2304,17 @@ void Nextmap_OnChange(void)
SP_NightsAttackMenu[naghost].status = IT_DISABLED; SP_NightsAttackMenu[naghost].status = IT_DISABLED;
// Check if file exists, if not, disable REPLAY option // Check if file exists, if not, disable REPLAY option
sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)); sprintf(tabase,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name);
#ifdef OLDNREPLAYNAME
sprintf(tabaseold,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s",srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value));
#endif
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
SP_NightsReplayMenu[i].status = IT_DISABLED; SP_NightsReplayMenu[i].status = IT_DISABLED;
SP_NightsGuestReplayMenu[i].status = IT_DISABLED; SP_NightsGuestReplayMenu[i].status = IT_DISABLED;
} }
if (FIL_FileExists(va("%s-score-best.lmp", tabase))) { if (FIL_FileExists(va("%s-score-best.lmp", tabase))) {
SP_NightsReplayMenu[0].status = IT_WHITESTRING|IT_CALL; SP_NightsReplayMenu[0].status = IT_WHITESTRING|IT_CALL;
SP_NightsGuestReplayMenu[0].status = IT_WHITESTRING|IT_CALL; SP_NightsGuestReplayMenu[0].status = IT_WHITESTRING|IT_CALL;
@ -2320,16 +2330,37 @@ void Nextmap_OnChange(void)
SP_NightsGuestReplayMenu[2].status = IT_WHITESTRING|IT_CALL; SP_NightsGuestReplayMenu[2].status = IT_WHITESTRING|IT_CALL;
active = true; active = true;
} }
if (FIL_FileExists(va("%s-guest.lmp", tabase))) { if (FIL_FileExists(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)))) {
SP_NightsReplayMenu[3].status = IT_WHITESTRING|IT_CALL; SP_NightsReplayMenu[3].status = IT_WHITESTRING|IT_CALL;
SP_NightsGuestReplayMenu[3].status = IT_WHITESTRING|IT_CALL; SP_NightsGuestReplayMenu[3].status = IT_WHITESTRING|IT_CALL;
active = true; active = true;
} }
// Old style name compatibility
#ifdef OLDNREPLAYNAME
if (FIL_FileExists(va("%s-score-best.lmp", tabaseold))) {
SP_NightsReplayMenu[0].status = IT_WHITESTRING|IT_CALL;
SP_NightsGuestReplayMenu[0].status = IT_WHITESTRING|IT_CALL;
active = true;
}
if (FIL_FileExists(va("%s-time-best.lmp", tabaseold))) {
SP_NightsReplayMenu[1].status = IT_WHITESTRING|IT_CALL;
SP_NightsGuestReplayMenu[1].status = IT_WHITESTRING|IT_CALL;
active = true;
}
if (FIL_FileExists(va("%s-last.lmp", tabaseold))) {
SP_NightsReplayMenu[2].status = IT_WHITESTRING|IT_CALL;
SP_NightsGuestReplayMenu[2].status = IT_WHITESTRING|IT_CALL;
active = true;
}
#endif
if (active) { if (active) {
SP_NightsAttackMenu[naguest].status = IT_WHITESTRING|IT_SUBMENU; SP_NightsAttackMenu[naguest].status = IT_WHITESTRING|IT_SUBMENU;
SP_NightsAttackMenu[nareplay].status = IT_WHITESTRING|IT_SUBMENU; SP_NightsAttackMenu[nareplay].status = IT_WHITESTRING|IT_SUBMENU;
SP_NightsAttackMenu[naghost].status = IT_WHITESTRING|IT_SUBMENU; SP_NightsAttackMenu[naghost].status = IT_WHITESTRING|IT_SUBMENU;
} }
else if(itemOn == nareplay) // Reset lastOn so replay isn't still selected when not available. else if(itemOn == nareplay) // Reset lastOn so replay isn't still selected when not available.
{ {
currentMenu->lastOn = itemOn; currentMenu->lastOn = itemOn;
@ -4404,7 +4435,7 @@ static void M_DrawGenericMenu(void)
} }
} }
const char *PlaystyleNames[4] = {"Legacy", "Standard", "Simple", "Old Analog??"}; const char *PlaystyleNames[4] = {"Strafe", "Standard", "Simple", "Old Analog??"};
const char *PlaystyleDesc[4] = { const char *PlaystyleDesc[4] = {
// Legacy // Legacy
"The play style used for\n" "The play style used for\n"
@ -8043,29 +8074,67 @@ static void M_SinglePlayerMenu(INT32 choice)
{ {
(void)choice; (void)choice;
// Reset the item positions, to avoid them sinking farther down every time the menu is opened if one is unavailable
// Note that they're reset, not simply "not moved again", in case mid-game add-ons re-enable an option
SP_MainMenu[spstartgame] .alphaKey = 76;
SP_MainMenu[sprecordattack].alphaKey = 84;
SP_MainMenu[spnightsmode] .alphaKey = 92;
SP_MainMenu[spmarathon] .alphaKey = 100;
//SP_MainMenu[sptutorial] .alphaKey = 108; // Not needed
//SP_MainMenu[spstatistics].alphaKey = 116; // Not needed
levellistmode = LLM_RECORDATTACK; levellistmode = LLM_RECORDATTACK;
if (M_GametypeHasLevels(-1)) if (M_GametypeHasLevels(-1))
SP_MainMenu[sprecordattack].status = (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING : IT_SECRET; SP_MainMenu[sprecordattack].status = (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING : IT_SECRET;
else else // If Record Attack is nonexistent in the current add-on...
SP_MainMenu[sprecordattack].status = IT_NOTHING|IT_DISABLED; {
SP_MainMenu[sprecordattack].status = IT_NOTHING|IT_DISABLED; // ...hide and disable the Record Attack option...
SP_MainMenu[spstartgame].alphaKey += 8; // ...and lower Start Game by 8 pixels to close the gap
}
levellistmode = LLM_NIGHTSATTACK; levellistmode = LLM_NIGHTSATTACK;
if (M_GametypeHasLevels(-1)) if (M_GametypeHasLevels(-1))
SP_MainMenu[spnightsmode].status = (M_SecretUnlocked(SECRET_NIGHTSMODE)) ? IT_CALL|IT_STRING : IT_SECRET; SP_MainMenu[spnightsmode].status = (M_SecretUnlocked(SECRET_NIGHTSMODE)) ? IT_CALL|IT_STRING : IT_SECRET;
else else // If NiGHTS Mode is nonexistent in the current add-on...
SP_MainMenu[spnightsmode].status = IT_NOTHING|IT_DISABLED; {
SP_MainMenu[spnightsmode].status = IT_NOTHING|IT_DISABLED; // ...hide and disable the NiGHTS Mode option...
// ...and lower the above options' display positions by 8 pixels to close the gap
SP_MainMenu[spstartgame] .alphaKey += 8;
SP_MainMenu[sprecordattack].alphaKey += 8;
}
SP_MainMenu[sptutorial].status = tutorialmap ? IT_CALL|IT_STRING : IT_NOTHING|IT_DISABLED;
// If the FIRST stage immediately leads to the ending, or itself (which gets converted to the title screen in G_DoCompleted for marathonmode only), there's no point in having this option on the menu. You should use Record Attack in that circumstance, although if marathonnext is set this behaviour can be overridden if you make some weird mod that requires multiple playthroughs of the same map in sequence and has some in-level mechanism to break the cycle. // If the FIRST stage immediately leads to the ending, or itself (which gets converted to the title screen in G_DoCompleted for marathonmode only), there's no point in having this option on the menu. You should use Record Attack in that circumstance, although if marathonnext is set this behaviour can be overridden if you make some weird mod that requires multiple playthroughs of the same map in sequence and has some in-level mechanism to break the cycle.
if (!M_SecretUnlocked(SECRET_RECORDATTACK) // also if record attack is locked if (mapheaderinfo[spmarathon_start-1]
|| (mapheaderinfo[spmarathon_start-1]
&& !mapheaderinfo[spmarathon_start-1]->marathonnext && !mapheaderinfo[spmarathon_start-1]->marathonnext
&& (mapheaderinfo[spmarathon_start-1]->nextlevel == spmarathon_start && (mapheaderinfo[spmarathon_start-1]->nextlevel == spmarathon_start
|| mapheaderinfo[spmarathon_start-1]->nextlevel >= 1100))) || mapheaderinfo[spmarathon_start-1]->nextlevel >= 1100))
SP_MainMenu[spmarathon].status = IT_NOTHING|IT_DISABLED; {
else SP_MainMenu[spmarathon].status = IT_NOTHING|IT_DISABLED; // Hide and disable the Marathon Run option...
SP_MainMenu[spmarathon].status = IT_CALL|IT_STRING|IT_CALL_NOTMODIFIED; // ...and lower the above options' display positions by 8 pixels to close the gap
SP_MainMenu[spstartgame] .alphaKey += 8;
SP_MainMenu[sprecordattack].alphaKey += 8;
SP_MainMenu[spnightsmode] .alphaKey += 8;
}
else // Otherwise, if Marathon Run is allowed and Record Attack is unlocked, unlock Marathon Run!
SP_MainMenu[spmarathon].status = (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING|IT_CALL_NOTMODIFIED : IT_SECRET;
if (tutorialmap) // If there's a tutorial available in the current add-on...
SP_MainMenu[sptutorial].status = IT_CALL | IT_STRING; // ...always unlock Tutorial
else // But if there's no tutorial available in the current add-on...
{
SP_MainMenu[sptutorial].status = IT_NOTHING|IT_DISABLED; // ...hide and disable the Tutorial option...
// ...and lower the above options' display positions by 8 pixels to close the gap
SP_MainMenu[spstartgame] .alphaKey += 8;
SP_MainMenu[sprecordattack].alphaKey += 8;
SP_MainMenu[spnightsmode] .alphaKey += 8;
SP_MainMenu[spmarathon] .alphaKey += 8;
}
M_SetupNextMenu(&SP_MainDef); M_SetupNextMenu(&SP_MainDef);
} }
@ -10126,6 +10195,8 @@ static void M_NightsAttack(INT32 choice)
// Player has selected the "START" from the nights attack screen // Player has selected the "START" from the nights attack screen
static void M_ChooseNightsAttack(INT32 choice) static void M_ChooseNightsAttack(INT32 choice)
{ {
char *gpath;
const size_t glen = strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
char nameofdemo[256]; char nameofdemo[256];
(void)choice; (void)choice;
emeralds = 0; emeralds = 0;
@ -10136,14 +10207,18 @@ static void M_ChooseNightsAttack(INT32 choice)
I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755); I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755);
I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755); I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755);
snprintf(nameofdemo, sizeof nameofdemo, "replay"PATHSEP"%s"PATHSEP"%s-last", timeattackfolder, G_BuildMapName(cv_nextmap.value)); if ((gpath = malloc(glen)) == NULL)
I_Error("Out of memory for replay filepath\n");
sprintf(gpath,"replay"PATHSEP"%s"PATHSEP"%s", timeattackfolder, G_BuildMapName(cv_nextmap.value));
snprintf(nameofdemo, sizeof nameofdemo, "%s-%s-last", gpath, skins[cv_chooseskin.value-1].name);
if (!cv_autorecord.value) if (!cv_autorecord.value)
remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo)); remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo));
else else
G_RecordDemo(nameofdemo); G_RecordDemo(nameofdemo);
G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), 0, false, false); G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), (UINT8)(cv_chooseskin.value-1), false, false);
} }
// Player has selected the "START" from the time attack screen // Player has selected the "START" from the time attack screen
@ -10179,6 +10254,7 @@ static void M_ChooseTimeAttack(INT32 choice)
static void M_ReplayTimeAttack(INT32 choice) static void M_ReplayTimeAttack(INT32 choice)
{ {
const char *which; const char *which;
char *demoname;
M_ClearMenus(true); M_ClearMenus(true);
modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows modeattacking = ATTACKING_RECORD; // set modeattacking before G_DoPlayDemo so the map loader knows
@ -10220,11 +10296,18 @@ static void M_ReplayTimeAttack(INT32 choice)
which = "last"; which = "last";
break; break;
case 3: // guest case 3: // guest
which = "guest"; G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)));
break; return;
} }
// srb2/replay/main/map01-score-best.lmp
G_DoPlayDemo(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which)); demoname = va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which);
#ifdef OLDNREPLAYNAME // Check for old style named NiGHTS replay if a new style replay doesn't exist.
if (!FIL_FileExists(demoname))
demoname = va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which);
#endif
G_DoPlayDemo(demoname);
} }
} }
@ -10242,15 +10325,13 @@ static void M_EraseGuest(INT32 choice)
M_StartMessage(M_GetText("Guest replay data erased.\n"),NULL,MM_NOTHING); M_StartMessage(M_GetText("Guest replay data erased.\n"),NULL,MM_NOTHING);
} }
static void M_OverwriteGuest(const char *which, boolean nights) static void M_OverwriteGuest(const char *which)
{ {
char *rguest = Z_StrDup(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value))); char *rguest = Z_StrDup(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value)));
UINT8 *buf; UINT8 *buf;
size_t len; size_t len;
if (!nights) len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which), &buf);
len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), skins[cv_chooseskin.value-1].name, which), &buf);
else
len = FIL_ReadFile(va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-%s.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value), which), &buf);
if (!len) { if (!len) {
return; return;
} }
@ -10271,25 +10352,25 @@ static void M_OverwriteGuest(const char *which, boolean nights)
static void M_OverwriteGuest_Time(INT32 choice) static void M_OverwriteGuest_Time(INT32 choice)
{ {
(void)choice; (void)choice;
M_OverwriteGuest("time-best", currentMenu == &SP_NightsGuestReplayDef); M_OverwriteGuest("time-best");
} }
static void M_OverwriteGuest_Score(INT32 choice) static void M_OverwriteGuest_Score(INT32 choice)
{ {
(void)choice; (void)choice;
M_OverwriteGuest("score-best", currentMenu == &SP_NightsGuestReplayDef); M_OverwriteGuest("score-best");
} }
static void M_OverwriteGuest_Rings(INT32 choice) static void M_OverwriteGuest_Rings(INT32 choice)
{ {
(void)choice; (void)choice;
M_OverwriteGuest("rings-best", false); M_OverwriteGuest("rings-best");
} }
static void M_OverwriteGuest_Last(INT32 choice) static void M_OverwriteGuest_Last(INT32 choice)
{ {
(void)choice; (void)choice;
M_OverwriteGuest("last", currentMenu == &SP_NightsGuestReplayDef); M_OverwriteGuest("last");
} }
static void M_SetGuestReplay(INT32 choice) static void M_SetGuestReplay(INT32 choice)

View File

@ -21,6 +21,9 @@
#include "r_skins.h" // for SKINNAMESIZE #include "r_skins.h" // for SKINNAMESIZE
#include "f_finale.h" // for ttmode_enum #include "f_finale.h" // for ttmode_enum
// Compatibility with old-style named NiGHTS replay files.
#define OLDNREPLAYNAME
// //
// MENUS // MENUS
// //

View File

@ -3858,7 +3858,7 @@ void A_Explode(mobj_t *actor)
if (LUA_CallAction("A_Explode", actor)) if (LUA_CallAction("A_Explode", actor))
return; return;
P_RadiusAttack(actor, actor->target, actor->info->damage, locvar1); P_RadiusAttack(actor, actor->target, actor->info->damage, locvar1, true);
} }
// Function: A_BossDeath // Function: A_BossDeath
@ -5639,7 +5639,7 @@ void A_MinusPopup(mobj_t *actor)
P_SetObjectMomZ(rock, 3*FRACUNIT, false); P_SetObjectMomZ(rock, 3*FRACUNIT, false);
P_SetScale(rock, rock->scale/3); P_SetScale(rock, rock->scale/3);
} }
P_RadiusAttack(actor, actor, 2*actor->radius, 0); P_RadiusAttack(actor, actor, 2*actor->radius, 0, true);
if (actor->tracer) if (actor->tracer)
P_DamageMobj(actor->tracer, actor, actor, 1, 0); P_DamageMobj(actor->tracer, actor, actor, 1, 0);
@ -6945,7 +6945,9 @@ void A_RecyclePowers(mobj_t *actor)
for (j = 0; j < NUMPOWERS; j++) for (j = 0; j < NUMPOWERS; j++)
{ {
if (j == pw_flashing || j == pw_underwater || j == pw_spacetime || j == pw_carry if (j == pw_flashing || j == pw_underwater || j == pw_spacetime || j == pw_carry
|| j == pw_tailsfly || j == pw_extralife || j == pw_nocontrol || j == pw_super) || j == pw_tailsfly || j == pw_extralife || j == pw_nocontrol || j == pw_super
|| j == pw_pushing || j == pw_justsprung || j == pw_noautobrake || j == pw_justlaunched
|| j == pw_ignorelatch)
continue; continue;
players[recv_pl].powers[j] = powers[send_pl][j]; players[recv_pl].powers[j] = powers[send_pl][j];
} }
@ -11032,7 +11034,7 @@ void A_VileAttack(mobj_t *actor)
actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
fire->z); fire->z);
P_RadiusAttack(fire, actor, 70*FRACUNIT, 0); P_RadiusAttack(fire, actor, 70*FRACUNIT, 0, true);
} }
else else
{ {
@ -11077,7 +11079,7 @@ void A_VileAttack(mobj_t *actor)
actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)),
fire->z); fire->z);
P_RadiusAttack(fire, actor, 70*FRACUNIT, 0); P_RadiusAttack(fire, actor, 70*FRACUNIT, 0, true);
} }
} }
@ -12313,7 +12315,7 @@ void A_MineExplode(mobj_t *actor)
quake.intensity = 8*FRACUNIT; quake.intensity = 8*FRACUNIT;
quake.time = TICRATE/3; quake.time = TICRATE/3;
P_RadiusAttack(actor, actor->tracer, 192*FRACUNIT, DMG_CANHURTSELF); P_RadiusAttack(actor, actor->tracer, 192*FRACUNIT, DMG_CANHURTSELF, true);
P_MobjCheckWater(actor); P_MobjCheckWater(actor);
{ {
@ -13314,7 +13316,7 @@ void A_Boss5BombExplode(mobj_t *actor)
actor->flags2 = MF2_EXPLOSION; actor->flags2 = MF2_EXPLOSION;
if (actor->target) if (actor->target)
P_RadiusAttack(actor, actor->target, 7*actor->radius, 0); P_RadiusAttack(actor, actor->target, 7*actor->radius, 0, true);
P_DustRing(locvar1, 4, actor->x, actor->y, actor->z+actor->height, 2*actor->radius, 0, FRACUNIT, actor->scale); P_DustRing(locvar1, 4, actor->x, actor->y, actor->z+actor->height, 2*actor->radius, 0, FRACUNIT, actor->scale);
P_DustRing(locvar1, 6, actor->x, actor->y, actor->z+actor->height/2, 3*actor->radius, FRACUNIT, FRACUNIT, actor->scale); P_DustRing(locvar1, 6, actor->x, actor->y, actor->z+actor->height/2, 3*actor->radius, FRACUNIT, FRACUNIT, actor->scale);
@ -13339,6 +13341,9 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing)
if (!player) if (!player)
return true; return true;
if (player->powers[pw_carry] != CR_DUSTDEVIL && (player->powers[pw_ignorelatch] & (1<<15)))
return true;
if (abs(thing->x - dustdevil->x) > dustdevil->radius || abs(thing->y - dustdevil->y) > dustdevil->radius) if (abs(thing->x - dustdevil->x) > dustdevil->radius || abs(thing->y - dustdevil->y) > dustdevil->radius)
return true; return true;

View File

@ -1468,7 +1468,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return; return;
case MT_BLACKEGGMAN_GOOPFIRE: case MT_BLACKEGGMAN_GOOPFIRE:
if (!player->powers[pw_flashing]) if (!player->powers[pw_flashing] && !(player->powers[pw_ignorelatch] & (1<<15)))
{ {
toucher->momx = 0; toucher->momx = 0;
toucher->momy = 0; toucher->momy = 0;
@ -1584,44 +1584,53 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return; return;
case MT_SMALLGRABCHAIN: case MT_SMALLGRABCHAIN:
case MT_BIGGRABCHAIN: case MT_BIGGRABCHAIN:
if (P_MobjFlip(toucher)*toucher->momz > 0
|| (player->powers[pw_carry]))
return;
if (toucher->z > special->z + special->height/2)
return;
if (toucher->z + toucher->height/2 < special->z)
return;
if (player->powers[pw_flashing])
return;
if (special->movefactor && special->tracer && special->tracer->angle != ANGLE_90 && special->tracer->angle != ANGLE_270)
{ // I don't expect you to understand this, Mr Bond...
angle_t ang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->tracer->angle;
if ((special->movefactor > 0) == (special->tracer->angle > ANGLE_90 && special->tracer->angle < ANGLE_270))
ang += ANGLE_180;
if (ang < ANGLE_180)
return; // I expect you to die.
}
P_ResetPlayer(player);
P_SetTarget(&toucher->tracer, special);
if (special->tracer && !(special->tracer->flags2 & MF2_STRONGBOX))
{ {
player->powers[pw_carry] = CR_MACESPIN; boolean macespin = false;
S_StartSound(toucher, sfx_spin); if (P_MobjFlip(toucher)*toucher->momz > 0
P_SetPlayerMobjState(toucher, S_PLAY_ROLL); || (player->powers[pw_carry]))
return;
if (toucher->z > special->z + special->height/2)
return;
if (toucher->z + toucher->height/2 < special->z)
return;
if (player->powers[pw_flashing])
return;
if (special->tracer && !(special->tracer->flags2 & MF2_STRONGBOX))
macespin = true;
if (macespin ? (player->powers[pw_ignorelatch] & (1<<15)) : (player->powers[pw_ignorelatch]))
return;
if (special->movefactor && special->tracer && special->tracer->angle != ANGLE_90 && special->tracer->angle != ANGLE_270)
{ // I don't expect you to understand this, Mr Bond...
angle_t ang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->tracer->angle;
if ((special->movefactor > 0) == (special->tracer->angle > ANGLE_90 && special->tracer->angle < ANGLE_270))
ang += ANGLE_180;
if (ang < ANGLE_180)
return; // I expect you to die.
}
P_ResetPlayer(player);
P_SetTarget(&toucher->tracer, special);
if (macespin)
{
player->powers[pw_carry] = CR_MACESPIN;
S_StartSound(toucher, sfx_spin);
P_SetPlayerMobjState(toucher, S_PLAY_ROLL);
}
else
player->powers[pw_carry] = CR_GENERIC;
// Can't jump first frame
player->pflags |= PF_JUMPSTASIS;
return;
} }
else
player->powers[pw_carry] = CR_GENERIC;
// Can't jump first frame
player->pflags |= PF_JUMPSTASIS;
return;
case MT_EGGMOBILE2_POGO: case MT_EGGMOBILE2_POGO:
// sanity checks // sanity checks
if (!special->target || !special->target->health) if (!special->target || !special->target->health)
@ -1711,7 +1720,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return; return;
case MT_MINECARTSPAWNER: case MT_MINECARTSPAWNER:
if (!player->bot && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART) if (!player->bot && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART && !(player->powers[pw_ignorelatch] & (1<<15)))
{ {
mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART); mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART);
P_SetTarget(&mcart->target, toucher); P_SetTarget(&mcart->target, toucher);

View File

@ -175,6 +175,7 @@ void P_DoAbilityBounce(player_t *player, boolean changemomz);
void P_TwinSpinRejuvenate(player_t *player, mobjtype_t type); void P_TwinSpinRejuvenate(player_t *player, mobjtype_t type);
void P_BlackOw(player_t *player); void P_BlackOw(player_t *player);
void P_ElementalFire(player_t *player, boolean cropcircle); void P_ElementalFire(player_t *player, boolean cropcircle);
void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound);
void P_DoPityCheck(player_t *player); void P_DoPityCheck(player_t *player);
void P_PlayerThink(player_t *player); void P_PlayerThink(player_t *player);
@ -192,6 +193,7 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction,
mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet); mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet);
void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius);
void P_Earthquake(mobj_t *inflictor, mobj_t *source, fixed_t radius);
boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user
boolean P_SuperReady(player_t *player); boolean P_SuperReady(player_t *player);
void P_DoJump(player_t *player, boolean soundandstate); void P_DoJump(player_t *player, boolean soundandstate);
@ -419,7 +421,7 @@ void P_DelPrecipSeclist(mprecipsecnode_t *node);
void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y); void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y);
void P_Initsecnode(void); void P_Initsecnode(void);
void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype); void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype, boolean sightcheck);
fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height); fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height);
boolean PIT_PushableMoved(mobj_t *thing); boolean PIT_PushableMoved(mobj_t *thing);

View File

@ -527,6 +527,8 @@ static void P_DoPterabyteCarry(player_t *player, mobj_t *ptera)
{ {
if (player->powers[pw_carry] && player->powers[pw_carry] != CR_ROLLOUT) if (player->powers[pw_carry] && player->powers[pw_carry] != CR_ROLLOUT)
return; return;
if (player->powers[pw_ignorelatch] & (1<<15))
return;
if (ptera->extravalue1 != 1) if (ptera->extravalue1 != 1)
return; // Not swooping return; // Not swooping
if (ptera->target != player->mo) if (ptera->target != player->mo)
@ -611,7 +613,8 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails)
if (zdist <= sonic->mo->height + sonic->mo->scale // FixedMul(FRACUNIT, sonic->mo->scale), but scale == FRACUNIT by default if (zdist <= sonic->mo->height + sonic->mo->scale // FixedMul(FRACUNIT, sonic->mo->scale), but scale == FRACUNIT by default
&& zdist > sonic->mo->height*2/3 && zdist > sonic->mo->height*2/3
&& P_MobjFlip(tails->mo)*sonic->mo->momz <= 0) && P_MobjFlip(tails->mo)*sonic->mo->momz <= 0
&& !(sonic->powers[pw_ignorelatch] & (1<<15)))
{ {
if (sonic-players == consoleplayer && botingame) if (sonic-players == consoleplayer && botingame)
CV_SetValue(&cv_analog[1], false); CV_SetValue(&cv_analog[1], false);
@ -1002,6 +1005,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
} }
if ((thing->flags & MF_PUSHABLE) // not carrying a player if ((thing->flags & MF_PUSHABLE) // not carrying a player
&& (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something && (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something
&& !(tmthing->player->powers[pw_ignorelatch] & (1<<15))
&& ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP)) && ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP))
&& (P_MobjFlip(tmthing)*tmthing->momz <= 0) && (P_MobjFlip(tmthing)*tmthing->momz <= 0)
&& ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2)) && ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2))
@ -1291,6 +1295,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
else if (tmthing->type == MT_BLACKEGGMAN_MISSILE && thing->player else if (tmthing->type == MT_BLACKEGGMAN_MISSILE && thing->player
&& (thing->player->pflags & PF_JUMPED) && (thing->player->pflags & PF_JUMPED)
&& !thing->player->powers[pw_flashing] && !thing->player->powers[pw_flashing]
&& !thing->player->powers[pw_ignorelatch]
&& thing->tracer != tmthing && thing->tracer != tmthing
&& tmthing->target != thing) && tmthing->target != thing)
{ {
@ -2823,14 +2828,22 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
P_HandleSlopeLanding(thing, tmfloorslope); P_HandleSlopeLanding(thing, tmfloorslope);
if (thing->momz <= 0) if (thing->momz <= 0)
{
thing->standingslope = tmfloorslope; thing->standingslope = tmfloorslope;
if (thing->momz == 0 && thing->player && !startingonground)
P_PlayerHitFloor(thing->player, true);
}
} }
else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) { else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) {
if (!startingonground && tmceilingslope) if (!startingonground && tmceilingslope)
P_HandleSlopeLanding(thing, tmceilingslope); P_HandleSlopeLanding(thing, tmceilingslope);
if (thing->momz >= 0) if (thing->momz >= 0)
{
thing->standingslope = tmceilingslope; thing->standingslope = tmceilingslope;
if (thing->momz == 0 && thing->player && !startingonground)
P_PlayerHitFloor(thing->player, true);
}
} }
} }
else // don't set standingslope if you're not going to clip against it else // don't set standingslope if you're not going to clip against it
@ -2924,6 +2937,8 @@ static boolean P_ThingHeightClip(mobj_t *thing)
ffloor_t *oldceilingrover = thing->ceilingrover; ffloor_t *oldceilingrover = thing->ceilingrover;
boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz); boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz);
ffloor_t *rover = NULL; ffloor_t *rover = NULL;
boolean bouncing;
boolean hitfloor = false;
if (thing->flags & MF_NOCLIPHEIGHT) if (thing->flags & MF_NOCLIPHEIGHT)
return true; return true;
@ -2946,7 +2961,9 @@ static boolean P_ThingHeightClip(mobj_t *thing)
if (tmfloorz > oldfloorz+thing->height) if (tmfloorz > oldfloorz+thing->height)
return true; return true;
if (onfloor && !(thing->flags & MF_NOGRAVITY) && floormoved) bouncing = thing->player && thing->state-states == S_PLAY_BOUNCE_LANDING && P_IsObjectOnGround(thing);
if ((onfloor || bouncing) && !(thing->flags & MF_NOGRAVITY) && floormoved)
{ {
rover = (thing->eflags & MFE_VERTICALFLIP) ? oldceilingrover : oldfloorrover; rover = (thing->eflags & MFE_VERTICALFLIP) ? oldceilingrover : oldfloorrover;
@ -2954,6 +2971,7 @@ static boolean P_ThingHeightClip(mobj_t *thing)
// If ~FF_EXISTS, don't set mobj Z. // If ~FF_EXISTS, don't set mobj Z.
if (!rover || ((rover->flags & FF_EXISTS) && (rover->flags & FF_SOLID))) if (!rover || ((rover->flags & FF_EXISTS) && (rover->flags & FF_SOLID)))
{ {
hitfloor = bouncing;
if (thing->eflags & MFE_VERTICALFLIP) if (thing->eflags & MFE_VERTICALFLIP)
thing->pmomz = thing->ceilingz - (thing->z + thing->height); thing->pmomz = thing->ceilingz - (thing->z + thing->height);
else else
@ -2978,7 +2996,7 @@ static boolean P_ThingHeightClip(mobj_t *thing)
thing->z = thing->ceilingz - thing->height; thing->z = thing->ceilingz - thing->height;
} }
if (P_MobjFlip(thing)*(thing->z - oldz) > 0 && thing->player) if ((P_MobjFlip(thing)*(thing->z - oldz) > 0 || hitfloor) && thing->player)
P_PlayerHitFloor(thing->player, !onfloor); P_PlayerHitFloor(thing->player, !onfloor);
// debug: be sure it falls to the floor // debug: be sure it falls to the floor
@ -3373,8 +3391,13 @@ static void PTR_GlideClimbTraverse(line_t *li)
if (!slidemo->player->climbing) if (!slidemo->player->climbing)
{ {
S_StartSound(slidemo->player->mo, sfx_s3k4a); S_StartSound(slidemo, sfx_s3k4a);
slidemo->player->climbing = 5; slidemo->player->climbing = 5;
if (slidemo->player->powers[pw_super])
{
P_Earthquake(slidemo, slidemo, 256*FRACUNIT);
S_StartSound(slidemo, sfx_s3k49);
}
} }
slidemo->player->pflags &= ~(PF_GLIDING|PF_SPINNING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED); slidemo->player->pflags &= ~(PF_GLIDING|PF_SPINNING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED);
@ -4010,6 +4033,7 @@ static fixed_t bombdamage;
static mobj_t *bombsource; static mobj_t *bombsource;
static mobj_t *bombspot; static mobj_t *bombspot;
static UINT8 bombdamagetype; static UINT8 bombdamagetype;
static boolean bombsightcheck;
// //
// PIT_RadiusAttack // PIT_RadiusAttack
@ -4023,10 +4047,16 @@ static boolean PIT_RadiusAttack(mobj_t *thing)
if (thing == bombspot) // ignore the bomb itself (Deton fix) if (thing == bombspot) // ignore the bomb itself (Deton fix)
return true; return true;
if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) != MF_SHOOTABLE) if (bombsource && thing->type == bombsource->type && !(bombdamagetype & DMG_CANHURTSELF)) // ignore the type of guys who dropped the bomb (Jetty-Syn Bomber or Skim can bomb eachother, but not themselves.)
return true; return true;
if (bombsource && thing->type == bombsource->type && !(bombdamagetype & DMG_CANHURTSELF)) // ignore the type of guys who dropped the bomb (Jetty-Syn Bomber or Skim can bomb eachother, but not themselves.) if (thing->type == MT_MINUS && !(thing->flags & (MF_SPECIAL|MF_SHOOTABLE)) && !bombsightcheck)
thing->flags = (thing->flags & ~MF_NOCLIPTHING)|MF_SPECIAL|MF_SHOOTABLE;
if (thing->type == MT_EGGGUARD && thing->tracer) //nuke Egg Guard's shield!
P_KillMobj(thing->tracer, bombspot, bombsource, bombdamagetype);
if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) != MF_SHOOTABLE)
return true; return true;
dx = abs(thing->x - bombspot->x); dx = abs(thing->x - bombspot->x);
@ -4048,7 +4078,7 @@ static boolean PIT_RadiusAttack(mobj_t *thing)
if (thing->ceilingz < bombspot->z && bombspot->floorz > thing->z) if (thing->ceilingz < bombspot->z && bombspot->floorz > thing->z)
return true; return true;
if (P_CheckSight(thing, bombspot)) if (!bombsightcheck || P_CheckSight(thing, bombspot))
{ // must be in direct path { // must be in direct path
P_DamageMobj(thing, bombspot, bombsource, 1, bombdamagetype); // Tails 01-11-2001 P_DamageMobj(thing, bombspot, bombsource, 1, bombdamagetype); // Tails 01-11-2001
} }
@ -4060,7 +4090,7 @@ static boolean PIT_RadiusAttack(mobj_t *thing)
// P_RadiusAttack // P_RadiusAttack
// Source is the creature that caused the explosion at spot. // Source is the creature that caused the explosion at spot.
// //
void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype) void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype, boolean sightcheck)
{ {
INT32 x, y; INT32 x, y;
INT32 xl, xh, yl, yh; INT32 xl, xh, yl, yh;
@ -4078,6 +4108,7 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama
bombsource = source; bombsource = source;
bombdamage = FixedMul(damagedist, spot->scale); bombdamage = FixedMul(damagedist, spot->scale);
bombdamagetype = damagetype; bombdamagetype = damagetype;
bombsightcheck = sightcheck;
for (y = yl; y <= yh; y++) for (y = yl; y <= yh; y++)
for (x = xl; x <= xh; x++) for (x = xl; x <= xh; x++)

View File

@ -211,10 +211,16 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
return P_SetPlayerMobjState(mobj, S_PLAY_FALL); return P_SetPlayerMobjState(mobj, S_PLAY_FALL);
// Catch swimming versus flying // Catch swimming versus flying
if (state == S_PLAY_FLY && player->mo->eflags & MFE_UNDERWATER) if ((state == S_PLAY_FLY || (state == S_PLAY_GLIDE && skins[player->skin].sprites[SPR2_SWIM].numframes))
&& player->mo->eflags & MFE_UNDERWATER && !player->skidtime)
return P_SetPlayerMobjState(player->mo, S_PLAY_SWIM); return P_SetPlayerMobjState(player->mo, S_PLAY_SWIM);
else if (state == S_PLAY_SWIM && !(player->mo->eflags & MFE_UNDERWATER)) else if (state == S_PLAY_SWIM && !(player->mo->eflags & MFE_UNDERWATER))
return P_SetPlayerMobjState(player->mo, S_PLAY_FLY); {
if (player->charability == CA_GLIDEANDCLIMB)
return P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE);
else
return P_SetPlayerMobjState(player->mo, S_PLAY_FLY);
}
// Catch SF_NOSUPERSPIN jumps for Supers // Catch SF_NOSUPERSPIN jumps for Supers
if (player->powers[pw_super] && (player->charflags & SF_NOSUPERSPIN)) if (player->powers[pw_super] && (player->charflags & SF_NOSUPERSPIN))
@ -394,7 +400,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
if (skin) if (skin)
{ {
spr2 = P_GetSkinSprite2(skin, (((player->powers[pw_super]) ? FF_SPR2SUPER : 0)|st->frame) & FF_FRAMEMASK, mobj->player); spr2 = P_GetSkinSprite2(skin, (((player->powers[pw_super] && !(player->charflags & SF_NOSUPERSPRITES)) ? FF_SPR2SUPER : 0)|st->frame) & FF_FRAMEMASK, mobj->player);
numframes = skin->sprites[spr2].numframes; numframes = skin->sprites[spr2].numframes;
} }
else else
@ -874,7 +880,7 @@ void P_ExplodeMissile(mobj_t *mo)
if (mo->type == MT_DETON) if (mo->type == MT_DETON)
{ {
P_RadiusAttack(mo, mo, 96*FRACUNIT, 0); P_RadiusAttack(mo, mo, 96*FRACUNIT, 0, true);
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
P_SetScale(explodemo, mo->scale); P_SetScale(explodemo, mo->scale);
@ -9205,10 +9211,11 @@ static void P_DragonbomberThink(mobj_t *mobj)
mobj->angle += DRAGONTURNSPEED; mobj->angle += DRAGONTURNSPEED;
else else
{ {
boolean flip = mobj->spawnpoint->options & MTF_OBJECTFLIP;
fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale); fixed_t vspeed = FixedMul(mobj->info->speed >> 3, mobj->scale);
fixed_t x = mobj->spawnpoint->x << FRACBITS; fixed_t x = mobj->spawnpoint->x << FRACBITS;
fixed_t y = mobj->spawnpoint->y << FRACBITS; fixed_t y = mobj->spawnpoint->y << FRACBITS;
fixed_t z = mobj->spawnpoint->z << FRACBITS; fixed_t z = (flip ? P_GetSectorCeilingZAt : P_GetSectorFloorZAt)(R_PointInSubsector(x, y)->sector, x, y) + (flip ? -1 : 1)*(mobj->spawnpoint->z << FRACBITS);
angle_t diff = R_PointToAngle2(mobj->x, mobj->y, x, y) - mobj->angle; angle_t diff = R_PointToAngle2(mobj->x, mobj->y, x, y) - mobj->angle;
if (diff > ANGLE_180) if (diff > ANGLE_180)
mobj->angle -= DRAGONTURNSPEED; mobj->angle -= DRAGONTURNSPEED;

View File

@ -373,6 +373,7 @@ typedef struct mobj_s
struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?)
boolean colorized; // Whether the mobj uses the rainbow colormap boolean colorized; // Whether the mobj uses the rainbow colormap
boolean mirrored; // The object's rotations will be mirrored left to right, e.g., see frame AL from the right and AR from the left
fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius
// WARNING: New fields must be added separately to savegame and Lua. // WARNING: New fields must be added separately to savegame and Lua.

View File

@ -1152,7 +1152,8 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta,
if (turnthings == 2 || (turnthings == 1 && !mo->player)) { if (turnthings == 2 || (turnthings == 1 && !mo->player)) {
mo->angle += delta; mo->angle += delta;
P_SetPlayerAngle(mo->player, (angle_t)(mo->player->angleturn << 16) + delta); if (mo->player)
P_SetPlayerAngle(mo->player, (angle_t)(mo->player->angleturn << 16) + delta);
} }
} }
} }

View File

@ -64,8 +64,10 @@
#define FF_FULLBRIGHT 0x00100000 #define FF_FULLBRIGHT 0x00100000
/// \brief Frame flags: Flip sprite vertically (relative to what it should be for its gravity) /// \brief Frame flags: Flip sprite vertically (relative to what it should be for its gravity)
#define FF_VERTICALFLIP 0x00200000 #define FF_VERTICALFLIP 0x00200000
/// \brief Frame flags: Flip sprite horizontally
#define FF_HORIZONTALFLIP 0x00400000
/// \brief Frame flags: Thin, paper-like sprite (for collision equivalent, see MF_PAPERCOLLISION) /// \brief Frame flags: Thin, paper-like sprite (for collision equivalent, see MF_PAPERCOLLISION)
#define FF_PAPERSPRITE 0x00400000 #define FF_PAPERSPRITE 0x00800000
/// \brief Frame flags - Animate: Simple stateless animation /// \brief Frame flags - Animate: Simple stateless animation
#define FF_ANIMATE 0x01000000 #define FF_ANIMATE 0x01000000

View File

@ -1389,8 +1389,9 @@ typedef enum
MD2_CEILINGROVER = 1<<10, MD2_CEILINGROVER = 1<<10,
MD2_SLOPE = 1<<11, MD2_SLOPE = 1<<11,
MD2_COLORIZED = 1<<12, MD2_COLORIZED = 1<<12,
MD2_ROLLANGLE = 1<<13, MD2_MIRRORED = 1<<13,
MD2_SHADOWSCALE = 1<<14, MD2_ROLLANGLE = 1<<14,
MD2_SHADOWSCALE = 1<<15,
} mobj_diff2_t; } mobj_diff2_t;
typedef enum typedef enum
@ -1597,6 +1598,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_SLOPE; diff2 |= MD2_SLOPE;
if (mobj->colorized) if (mobj->colorized)
diff2 |= MD2_COLORIZED; diff2 |= MD2_COLORIZED;
if (mobj->mirrored)
diff2 |= MD2_MIRRORED;
if (mobj->rollangle) if (mobj->rollangle)
diff2 |= MD2_ROLLANGLE; diff2 |= MD2_ROLLANGLE;
if (mobj->shadowscale) if (mobj->shadowscale)
@ -1737,6 +1740,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
WRITEUINT16(save_p, mobj->standingslope->id); WRITEUINT16(save_p, mobj->standingslope->id);
if (diff2 & MD2_COLORIZED) if (diff2 & MD2_COLORIZED)
WRITEUINT8(save_p, mobj->colorized); WRITEUINT8(save_p, mobj->colorized);
if (diff2 & MD2_MIRRORED)
WRITEUINT8(save_p, mobj->mirrored);
if (diff2 & MD2_ROLLANGLE) if (diff2 & MD2_ROLLANGLE)
WRITEANGLE(save_p, mobj->rollangle); WRITEANGLE(save_p, mobj->rollangle);
if (diff2 & MD2_SHADOWSCALE) if (diff2 & MD2_SHADOWSCALE)
@ -2744,6 +2749,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->standingslope = P_SlopeById(READUINT16(save_p)); mobj->standingslope = P_SlopeById(READUINT16(save_p));
if (diff2 & MD2_COLORIZED) if (diff2 & MD2_COLORIZED)
mobj->colorized = READUINT8(save_p); mobj->colorized = READUINT8(save_p);
if (diff2 & MD2_MIRRORED)
mobj->mirrored = READUINT8(save_p);
if (diff2 & MD2_ROLLANGLE) if (diff2 & MD2_ROLLANGLE)
mobj->rollangle = READANGLE(save_p); mobj->rollangle = READANGLE(save_p);
if (diff2 & MD2_SHADOWSCALE) if (diff2 & MD2_SHADOWSCALE)

View File

@ -576,9 +576,9 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize)
strupr(levelflat->name); strupr(levelflat->name);
/* If we can't find a flat, try looking for a texture! */ /* If we can't find a flat, try looking for a texture! */
if (( flatnum = R_GetFlatNumForName(flatname) ) == LUMPERROR) if (( flatnum = R_GetFlatNumForName(levelflat->name) ) == LUMPERROR)
{ {
if (( texturenum = R_CheckTextureNumForName(flatname) ) == -1) if (( texturenum = R_CheckTextureNumForName(levelflat->name) ) == -1)
{ {
// check for REDWALL // check for REDWALL
if (( texturenum = R_CheckTextureNumForName("REDWALL") ) != -1) if (( texturenum = R_CheckTextureNumForName("REDWALL") ) != -1)
@ -3600,6 +3600,7 @@ static void P_LoadNightsGhosts(void)
{ {
const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1;
char *gpath = malloc(glen); char *gpath = malloc(glen);
INT32 i;
if (!gpath) if (!gpath)
return; return;
@ -3607,16 +3608,43 @@ static void P_LoadNightsGhosts(void)
sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap));
// Best Score ghost // Best Score ghost
if (cv_ghost_bestscore.value && FIL_FileExists(va("%s-score-best.lmp", gpath))) if (cv_ghost_bestscore.value)
G_AddGhost(va("%s-score-best.lmp", gpath)); {
for (i = 0; i < numskins; ++i)
{
if (cv_ghost_bestscore.value == 1 && players[consoleplayer].skin != i)
continue;
if (FIL_FileExists(va("%s-%s-score-best.lmp", gpath, skins[i].name)))
G_AddGhost(va("%s-%s-score-best.lmp", gpath, skins[i].name));
}
}
// Best Time ghost // Best Time ghost
if (cv_ghost_besttime.value && FIL_FileExists(va("%s-time-best.lmp", gpath))) if (cv_ghost_besttime.value)
G_AddGhost(va("%s-time-best.lmp", gpath)); {
for (i = 0; i < numskins; ++i)
{
if (cv_ghost_besttime.value == 1 && players[consoleplayer].skin != i)
continue;
if (FIL_FileExists(va("%s-%s-time-best.lmp", gpath, skins[i].name)))
G_AddGhost(va("%s-%s-time-best.lmp", gpath, skins[i].name));
}
}
// Last ghost // Last ghost
if (cv_ghost_last.value && FIL_FileExists(va("%s-last.lmp", gpath))) if (cv_ghost_last.value)
G_AddGhost(va("%s-last.lmp", gpath)); {
for (i = 0; i < numskins; ++i)
{
if (cv_ghost_last.value == 1 && players[consoleplayer].skin != i)
continue;
if (FIL_FileExists(va("%s-%s-last.lmp", gpath, skins[i].name)))
G_AddGhost(va("%s-%s-last.lmp", gpath, skins[i].name));
}
}
// Guest ghost // Guest ghost
if (cv_ghost_guest.value && FIL_FileExists(va("%s-guest.lmp", gpath))) if (cv_ghost_guest.value && FIL_FileExists(va("%s-guest.lmp", gpath)))

View File

@ -2935,30 +2935,35 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
// If titlemap, set the camera ref for title's thinker // If titlemap, set the camera ref for title's thinker
// This is not revoked until overwritten; awayviewtics is ignored // This is not revoked until overwritten; awayviewtics is ignored
if (titlemapinaction) if (titlemapinaction)
{
titlemapcameraref = altview; titlemapcameraref = altview;
return; else
{
P_SetTarget(&mo->player->awayviewmobj, altview);
mo->player->awayviewtics = P_AproxDistance(line->dx, line->dy)>>FRACBITS;
} }
P_SetTarget(&mo->player->awayviewmobj, altview);
mo->player->awayviewtics = P_AproxDistance(line->dx, line->dy)>>FRACBITS;
if (line->flags & ML_NOCLIMB) // lets you specify a vertical angle if (line->flags & ML_NOCLIMB) // lets you specify a vertical angle
{ {
INT32 aim; INT32 aim;
aim = sides[line->sidenum[0]].textureoffset>>FRACBITS; aim = sides[line->sidenum[0]].textureoffset>>FRACBITS;
while (aim < 0) aim = (aim + 360) % 360;
aim += 360;
while (aim >= 360)
aim -= 360;
aim *= (ANGLE_90>>8); aim *= (ANGLE_90>>8);
aim /= 90; aim /= 90;
aim <<= 8; aim <<= 8;
mo->player->awayviewaiming = (angle_t)aim; if (titlemapinaction)
titlemapcameraref->cusval = (angle_t)aim;
else
mo->player->awayviewaiming = (angle_t)aim;
} }
else else
mo->player->awayviewaiming = 0; // straight ahead {
// straight ahead
if (!titlemapinaction)
mo->player->awayviewaiming = 0;
// don't do cusval cause that's annoying
}
} }
break; break;
@ -4830,6 +4835,9 @@ DoneSection2:
if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE)
break; break;
if (player->powers[pw_ignorelatch] & (1<<15))
break;
// Find line #3 tagged to this sector // Find line #3 tagged to this sector
lineindex = P_FindSpecialLineFromTag(3, sector->tag, -1); lineindex = P_FindSpecialLineFromTag(3, sector->tag, -1);
@ -4892,6 +4900,9 @@ DoneSection2:
if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE)
break; break;
if (player->powers[pw_ignorelatch] & (1<<15))
break;
// Find line #3 tagged to this sector // Find line #3 tagged to this sector
lineindex = P_FindSpecialLineFromTag(3, sector->tag, -1); lineindex = P_FindSpecialLineFromTag(3, sector->tag, -1);
@ -5002,6 +5013,9 @@ DoneSection2:
if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG) if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG)
break; break;
if (player->powers[pw_ignorelatch] & (1<<15))
break;
if (player->mo->momz > 0) if (player->mo->momz > 0)
break; break;

View File

@ -2302,7 +2302,8 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
{ {
if (dorollstuff) if (dorollstuff)
{ {
if ((player->charability2 == CA2_SPINDASH) && !((player->pflags & (PF_SPINNING|PF_THOKKED)) == PF_THOKKED) && (player->cmd.buttons & BT_USE) && (FixedHypot(player->mo->momx, player->mo->momy) > (5*player->mo->scale))) if ((player->charability2 == CA2_SPINDASH) && !((player->pflags & (PF_SPINNING|PF_THOKKED)) == PF_THOKKED) && !(player->charability == CA_THOK && player->secondjump)
&& (player->cmd.buttons & BT_USE) && (FixedHypot(player->mo->momx, player->mo->momy) > (5*player->mo->scale)))
player->pflags = (player->pflags|PF_SPINNING) & ~PF_THOKKED; player->pflags = (player->pflags|PF_SPINNING) & ~PF_THOKKED;
else if (!(player->pflags & PF_STARTDASH)) else if (!(player->pflags & PF_STARTDASH))
player->pflags &= ~PF_SPINNING; player->pflags &= ~PF_SPINNING;
@ -2318,10 +2319,13 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
if (player->scoreadd) if (player->scoreadd)
player->scoreadd--; player->scoreadd--;
} }
else
player->mo->z += P_MobjFlip(player->mo);
clipmomz = false; clipmomz = false;
} }
else else
{ {
P_MobjCheckWater(player->mo);
if (player->pflags & PF_SPINNING) if (player->pflags & PF_SPINNING)
{ {
if (player->mo->state-states != S_PLAY_ROLL && !(player->pflags & PF_STARTDASH)) if (player->mo->state-states != S_PLAY_ROLL && !(player->pflags & PF_STARTDASH))
@ -2335,21 +2339,32 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
if (dorollstuff) if (dorollstuff)
{ {
player->skidtime = TICRATE; player->skidtime = TICRATE;
P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE);
P_SpawnSkidDust(player, player->mo->radius, true); // make sure the player knows they landed
player->mo->tics = -1; player->mo->tics = -1;
} }
else if (!player->skidtime) else if (!player->skidtime)
player->pflags &= ~PF_GLIDING; player->pflags &= ~PF_GLIDING;
} }
else if (player->charability == CA_GLIDEANDCLIMB && player->pflags & PF_THOKKED && !(player->pflags & (PF_JUMPED|PF_SHIELDABILITY)) && player->mo->state-states == S_PLAY_FALL) else if (player->charability == CA_GLIDEANDCLIMB && player->pflags & PF_THOKKED && !(player->pflags & (PF_JUMPED|PF_SHIELDABILITY))
&& (player->mo->floorz != player->mo->watertop) && player->mo->state-states == S_PLAY_FALL)
{ {
if (player->mo->state-states != S_PLAY_GLIDE_LANDING) if (player->mo->state-states != S_PLAY_GLIDE_LANDING)
{ {
P_ResetPlayer(player); P_ResetPlayer(player);
P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE_LANDING); P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE_LANDING);
S_StartSound(player->mo, sfx_s3k4c);
player->pflags |= PF_STASIS; player->pflags |= PF_STASIS;
player->mo->momx = ((player->mo->momx - player->cmomx)/3) + player->cmomx; if (player->speed > FixedMul(player->runspeed, player->mo->scale))
player->mo->momy = ((player->mo->momy - player->cmomy)/3) + player->cmomy; player->skidtime += player->mo->tics;
player->mo->momx = ((player->mo->momx - player->cmomx)/2) + player->cmomx;
player->mo->momy = ((player->mo->momy - player->cmomy)/2) + player->cmomy;
if (player->powers[pw_super])
{
P_Earthquake(player->mo, player->mo, 256*FRACUNIT);
S_StartSound(player->mo, sfx_s3k49);
}
else
S_StartSound(player->mo, sfx_s3k4c);
} }
} }
else if (player->charability2 == CA2_MELEE else if (player->charability2 == CA2_MELEE
@ -2403,7 +2418,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
; ;
else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2) else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2)
; ;
else if (player->panim != PA_IDLE && player->panim != PA_WALK && player->panim != PA_RUN && player->panim != PA_DASH) else if (dorollstuff && player->panim != PA_IDLE && player->panim != PA_WALK && player->panim != PA_RUN && player->panim != PA_DASH)
{ {
fixed_t runspd = FixedMul(player->runspeed, player->mo->scale); fixed_t runspd = FixedMul(player->runspeed, player->mo->scale);
@ -4407,7 +4422,8 @@ void P_DoJump(player_t *player, boolean soundandstate)
{ {
player->mo->momz = 9*FRACUNIT; player->mo->momz = 9*FRACUNIT;
player->powers[pw_carry] = CR_NONE; player->powers[pw_carry] = CR_NONE;
P_SetTarget(&player->mo->tracer->target, NULL); if (!(player->mo->tracer->flags & MF_MISSILE)) // Missiles remember their owner!
P_SetTarget(&player->mo->tracer->target, NULL);
P_SetTarget(&player->mo->tracer, NULL); P_SetTarget(&player->mo->tracer, NULL);
} }
else if (player->powers[pw_carry] == CR_ROPEHANG) else if (player->powers[pw_carry] == CR_ROPEHANG)
@ -4444,7 +4460,7 @@ void P_DoJump(player_t *player, boolean soundandstate)
} }
else if (maptol & TOL_NIGHTS) else if (maptol & TOL_NIGHTS)
player->mo->momz = 18*FRACUNIT; player->mo->momz = 18*FRACUNIT;
else if (player->powers[pw_super]) else if (player->powers[pw_super] && !(player->charflags & SF_NOSUPERJUMPBOOST))
{ {
player->mo->momz = 13*FRACUNIT; player->mo->momz = 13*FRACUNIT;
@ -5147,6 +5163,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
player->mo->momz = 0; player->mo->momz = 0;
player->pflags &= ~(PF_STARTJUMP|PF_SPINNING); player->pflags &= ~(PF_STARTJUMP|PF_SPINNING);
player->secondjump = 1;
} }
} }
break; break;
@ -5342,9 +5359,12 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
if (player->mo->eflags & MFE_UNDERWATER) if (player->mo->eflags & MFE_UNDERWATER)
{ {
glidespeed >>= 1; glidespeed >>= 1;
playerspeed >>= 1; playerspeed = 2*playerspeed/3;
player->mo->momx = ((player->mo->momx - player->cmomx) >> 1) + player->cmomx; if (!(player->powers[pw_super] || player->powers[pw_sneakers]))
player->mo->momy = ((player->mo->momy - player->cmomy) >> 1) + player->cmomy; {
player->mo->momx = (2*(player->mo->momx - player->cmomx)/3) + player->cmomx;
player->mo->momy = (2*(player->mo->momy - player->cmomy)/3) + player->cmomy;
}
} }
player->pflags |= PF_GLIDING|PF_THOKKED; player->pflags |= PF_GLIDING|PF_THOKKED;
@ -5520,7 +5540,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
else else
potentialmomz = ((player->speed < 10*player->mo->scale) potentialmomz = ((player->speed < 10*player->mo->scale)
? (player->speed - 10*player->mo->scale)/5 ? (player->speed - 10*player->mo->scale)/5
: -1); // Should be 0, but made negative to ensure P_PlayerHitFloor runs upon touching ground : 0);
if (P_MobjFlip(player->mo)*player->mo->momz < potentialmomz) if (P_MobjFlip(player->mo)*player->mo->momz < potentialmomz)
player->mo->momz = P_MobjFlip(player->mo)*potentialmomz; player->mo->momz = P_MobjFlip(player->mo)*potentialmomz;
player->pflags &= ~PF_SPINNING; player->pflags &= ~PF_SPINNING;
@ -5532,7 +5552,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
player->pflags &= ~PF_JUMPDOWN; player->pflags &= ~PF_JUMPDOWN;
// Repeat abilities, but not double jump! // Repeat abilities, but not double jump!
if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP && player->charability != CA_AIRDRILL) if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP && player->charability != CA_AIRDRILL && player->charability != CA_THOK)
{ {
if (player->charflags & SF_MULTIABILITY) if (player->charflags & SF_MULTIABILITY)
{ {
@ -5771,7 +5791,7 @@ static void P_2dMovement(player_t *player)
if (player->climbing) if (player->climbing)
{ {
if (cmd->forwardmove != 0) if (cmd->forwardmove != 0)
P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 15*FRACUNIT>>1), false); P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, player->powers[pw_super] ? 5*FRACUNIT : 15*FRACUNIT>>1), false); // 2/3 while super
player->mo->momx = 0; player->mo->momx = 0;
} }
@ -5986,9 +6006,9 @@ static void P_3dMovement(player_t *player)
if (cmd->forwardmove) if (cmd->forwardmove)
{ {
if (player->mo->eflags & MFE_UNDERWATER) if (player->mo->eflags & MFE_UNDERWATER)
P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 10*FRACUNIT), false); P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, player->powers[pw_super] ? 20*FRACUNIT/3 : 10*FRACUNIT), false); // 2/3 while super
else else
P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, 15*FRACUNIT>>1), false); P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT, player->powers[pw_super] ? 5*FRACUNIT : 15*FRACUNIT>>1), false); // 2/3 while super
} }
} }
else if (!(controlstyle == CS_LMAOGALOG) else if (!(controlstyle == CS_LMAOGALOG)
@ -6021,9 +6041,9 @@ static void P_3dMovement(player_t *player)
if (player->climbing) if (player->climbing)
{ {
if (player->mo->eflags & MFE_UNDERWATER) if (player->mo->eflags & MFE_UNDERWATER)
P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, 10*FRACUNIT)); P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, player->powers[pw_super] ? 20*FRACUNIT/3 : 10*FRACUNIT)); // 2/3 while super
else else
P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, 15*FRACUNIT>>1)); P_InstaThrust(player->mo, player->mo->angle-ANGLE_90, FixedDiv(cmd->sidemove*player->mo->scale, player->powers[pw_super] ? 5*FRACUNIT : 15*FRACUNIT>>1)); // 2/3 while super
} }
// Analog movement control // Analog movement control
else if (controlstyle == CS_LMAOGALOG) else if (controlstyle == CS_LMAOGALOG)
@ -7751,6 +7771,39 @@ void P_ElementalFire(player_t *player, boolean cropcircle)
} }
} }
//
// P_SpawnSkidDust
//
// Spawns spindash dust randomly around the player within a certain radius.
//
void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound)
{
mobj_t *mo = player->mo;
mobj_t *particle;
particle = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_SPINDUST);
if (radius >>= FRACBITS)
{
P_UnsetThingPosition(particle);
particle->x += P_RandomRange(-radius, radius) << FRACBITS;
particle->y += P_RandomRange(-radius, radius) << FRACBITS;
P_SetThingPosition(particle);
}
particle->tics = 10;
particle->destscale = (2*mo->scale)/3;
P_SetScale(particle, particle->destscale);
P_SetObjectMomZ(particle, FRACUNIT, false);
if (mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version
P_SetMobjState(particle, S_SPINDUST_BUBBLE1);
else if (player->powers[pw_shield] == SH_ELEMENTAL)
P_SetMobjState(particle, S_SPINDUST_FIRE1);
if (sound)
S_StartSound(mo, sfx_s3k7e); // the proper "Knuckles eats dirt" sfx.
}
static void P_SkidStuff(player_t *player) static void P_SkidStuff(player_t *player)
{ {
fixed_t pmx = player->rmomx + player->cmomx; fixed_t pmx = player->rmomx + player->cmomx;
@ -7764,7 +7817,7 @@ static void P_SkidStuff(player_t *player)
{ {
player->skidtime = 0; player->skidtime = 0;
player->pflags &= ~(PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE); player->pflags &= ~(PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE);
player->pflags |= PF_THOKKED; // nice try, speedrunners (but for real this is just behavior from S3K) player->pflags |= PF_THOKKED;
P_SetPlayerMobjState(player->mo, S_PLAY_FALL); P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
} }
// Get up and brush yourself off, idiot. // Get up and brush yourself off, idiot.
@ -7773,29 +7826,18 @@ static void P_SkidStuff(player_t *player)
P_ResetPlayer(player); P_ResetPlayer(player);
P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE_LANDING); P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE_LANDING);
player->pflags |= PF_STASIS; player->pflags |= PF_STASIS;
player->mo->momx = ((player->mo->momx - player->cmomx)/3) + player->cmomx; if (player->speed > FixedMul(player->runspeed, player->mo->scale))
player->mo->momy = ((player->mo->momy - player->cmomy)/3) + player->cmomy; player->skidtime += player->mo->tics;
player->mo->momx = ((player->mo->momx - player->cmomx)/2) + player->cmomx;
player->mo->momy = ((player->mo->momy - player->cmomy)/2) + player->cmomy;
} }
// Didn't stop yet? Skid FOREVER! // Didn't stop yet? Skid FOREVER!
else if (player->skidtime == 1) else if (player->skidtime == 1)
player->skidtime = 3*TICRATE+1; player->skidtime = 3*TICRATE+1;
// Spawn a particle every 3 tics. // Spawn a particle every 3 tics.
else if (!(player->skidtime % 3)) else if (!(player->skidtime % 3) && !(player->charflags & SF_NOSKID))
{ {
fixed_t radius = player->mo->radius >> FRACBITS; P_SpawnSkidDust(player, player->mo->radius, true);
mobj_t *particle = P_SpawnMobjFromMobj(player->mo, P_RandomRange(-radius, radius) << FRACBITS, P_RandomRange(-radius, radius) << FRACBITS, 0, MT_SPINDUST);
particle->tics = 10;
particle->destscale = (2*player->mo->scale)/3;
P_SetScale(particle, particle->destscale);
P_SetObjectMomZ(particle, FRACUNIT, false);
if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version
P_SetMobjState(particle, S_SPINDUST_BUBBLE1);
else if (player->powers[pw_shield] == SH_ELEMENTAL)
P_SetMobjState(particle, S_SPINDUST_FIRE1);
S_StartSound(player->mo, sfx_s3k7e); // the proper "Knuckles eats dirt" sfx.
} }
} }
// Skidding! // Skidding!
@ -7806,17 +7848,10 @@ static void P_SkidStuff(player_t *player)
// Spawn a particle every 3 tics. // Spawn a particle every 3 tics.
if (!(player->skidtime % 3)) if (!(player->skidtime % 3))
{ {
mobj_t *particle = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SPINDUST); if (player->mo->state-states == S_PLAY_GLIDE_LANDING)
particle->tics = 10; P_SpawnSkidDust(player, player->mo->radius, true);
else
particle->destscale = (2*player->mo->scale)/3; P_SpawnSkidDust(player, 0, false);
P_SetScale(particle, particle->destscale);
P_SetObjectMomZ(particle, FRACUNIT, false);
if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version
P_SetMobjState(particle, S_SPINDUST_BUBBLE1);
else if (player->powers[pw_shield] == SH_ELEMENTAL)
P_SetMobjState(particle, S_SPINDUST_FIRE1);
} }
} }
else if (P_AproxDistance(pmx, pmy) >= FixedMul(player->runspeed/2, player->mo->scale) // if you were moving faster than half your run speed last frame else if (P_AproxDistance(pmx, pmy) >= FixedMul(player->runspeed/2, player->mo->scale) // if you were moving faster than half your run speed last frame
@ -8177,10 +8212,11 @@ static void P_MovePlayer(player_t *player)
if (player->pflags & PF_GLIDING) if (player->pflags & PF_GLIDING)
{ {
mobj_t *mo = player->mo; // seriously why isn't this at the top of the function hngngngng mobj_t *mo = player->mo; // seriously why isn't this at the top of the function hngngngng
fixed_t leeway = (P_ControlStyle(player) != CS_LMAOGALOG) ? FixedAngle(cmd->sidemove*(FRACUNIT)) : 0;
fixed_t glidespeed = player->actionspd; fixed_t glidespeed = player->actionspd;
fixed_t momx = mo->momx - player->cmomx, momy = mo->momy - player->cmomy; fixed_t momx = mo->momx - player->cmomx, momy = mo->momy - player->cmomy;
angle_t angle, moveangle = R_PointToAngle2(0, 0, momx, momy); angle_t angle, moveangle = R_PointToAngle2(0, 0, momx, momy);
boolean swimming = mo->state - states == S_PLAY_SWIM;
boolean in2d = mo->flags2 & MF2_TWOD || twodlevel;
if (player->powers[pw_super] || player->powers[pw_sneakers]) if (player->powers[pw_super] || player->powers[pw_sneakers])
glidespeed *= 2; glidespeed *= 2;
@ -8197,42 +8233,82 @@ static void P_MovePlayer(player_t *player)
} }
// Strafing while gliding. // Strafing while gliding.
angle = mo->angle - leeway; if ((P_ControlStyle(player) & CS_LMAOGALOG) || in2d)
angle = mo->angle;
else if (swimming)
angle = mo->angle + R_PointToAngle2(0, 0, cmd->forwardmove<<FRACBITS, -cmd->sidemove<<FRACBITS);
else
angle = mo->angle - FixedAngle(cmd->sidemove * FRACUNIT);
if (!player->skidtime) // TODO: make sure this works in 2D! if (!player->skidtime) // TODO: make sure this works in 2D!
{ {
angle_t anglediff = angle - moveangle;
fixed_t accelfactor = 4*FRACUNIT - 3*FINECOSINE((anglediff >> ANGLETOFINESHIFT) & FINEMASK);
fixed_t speed, scale = mo->scale; fixed_t speed, scale = mo->scale;
fixed_t newMagnitude, oldMagnitude = R_PointToDist2(momx, momy, 0, 0);
fixed_t accelfactor = 4*FRACUNIT - 3*FINECOSINE(((angle-moveangle) >> ANGLETOFINESHIFT) & FINEMASK); // mamgic number BAD but this feels right
if (mo->eflags & MFE_UNDERWATER) if (in2d)
speed = FixedMul((glidespeed>>1) + player->glidetime*750, scale);
else
speed = FixedMul(glidespeed + player->glidetime*1500, scale);
P_Thrust(mo, angle, FixedMul(accelfactor, scale));
newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0);
if (newMagnitude > speed)
{ {
fixed_t tempmomx, tempmomy; if (mo->eflags & MFE_UNDERWATER)
if (oldMagnitude > speed) speed = FixedMul((glidespeed>>1) + player->glidetime*750, scale);
else
speed = FixedMul(glidespeed + player->glidetime*1500, scale);
P_InstaThrust(mo, angle, speed);
}
else if (swimming)
{
fixed_t minspeed;
if (anglediff > ANGLE_180)
anglediff = InvAngle(InvAngle(anglediff) >> 3);
else
anglediff = anglediff >> 3;
minspeed = FixedMul((glidespeed>>1) + player->glidetime*750, scale); // underwater-specific
speed = FixedHypot(momx, momy) - abs(P_ReturnThrustY(mo, anglediff, mo->scale));
if (speed < minspeed)
{ {
if (newMagnitude > oldMagnitude) momx += P_ReturnThrustX(mo, angle, FixedMul(accelfactor, scale));
momy += P_ReturnThrustY(mo, angle, FixedMul(accelfactor, scale));
speed = FixedHypot(momx, momy); // recalculate speed
}
mo->momx = P_ReturnThrustX(mo, moveangle + anglediff, speed) + player->cmomx;
mo->momy = P_ReturnThrustY(mo, moveangle + anglediff, speed) + player->cmomy;
}
else
{
fixed_t newMagnitude, oldMagnitude = R_PointToDist2(momx, momy, 0, 0);
if (mo->eflags & MFE_UNDERWATER)
speed = FixedMul((glidespeed>>1) + player->glidetime*750, scale);
else
speed = FixedMul(glidespeed + player->glidetime*1500, scale);
P_Thrust(mo, angle, FixedMul(accelfactor, scale));
newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0);
if (newMagnitude > speed)
{
fixed_t tempmomx, tempmomy;
if (oldMagnitude > speed)
{ {
tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), oldMagnitude); if (newMagnitude > oldMagnitude)
tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), oldMagnitude); {
tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), oldMagnitude);
tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), oldMagnitude);
player->mo->momx = tempmomx + player->cmomx;
player->mo->momy = tempmomy + player->cmomy;
}
// else do nothing
}
else
{
tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), speed);
tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), speed);
player->mo->momx = tempmomx + player->cmomx; player->mo->momx = tempmomx + player->cmomx;
player->mo->momy = tempmomy + player->cmomy; player->mo->momy = tempmomy + player->cmomy;
} }
// else do nothing
}
else
{
tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), speed);
tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), speed);
player->mo->momx = tempmomx + player->cmomx;
player->mo->momy = tempmomy + player->cmomy;
} }
} }
} }
@ -8548,6 +8624,7 @@ static void P_MovePlayer(player_t *player)
|| ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE)) || ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE))
|| (player->pflags & PF_SPINNING) || (player->pflags & PF_SPINNING)
|| player->powers[pw_tailsfly] || player->pflags & PF_GLIDING || player->powers[pw_tailsfly] || player->pflags & PF_GLIDING
|| (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING)
|| (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED))
player->mo->height = P_GetPlayerSpinHeight(player); player->mo->height = P_GetPlayerSpinHeight(player);
else else
@ -8613,74 +8690,6 @@ static void P_MovePlayer(player_t *player)
if (CheckForBustableBlocks) if (CheckForBustableBlocks)
P_CheckBustableBlocks(player); P_CheckBustableBlocks(player);
// Special handling for
// gliding in 2D mode
if ((twodlevel || player->mo->flags2 & MF2_TWOD) && player->pflags & PF_GLIDING && player->charability == CA_GLIDEANDCLIMB
&& !(player->mo->flags & MF_NOCLIP))
{
msecnode_t *node; // only place it's being used in P_MovePlayer now
fixed_t oldx;
fixed_t oldy;
fixed_t floorz, ceilingz;
oldx = player->mo->x;
oldy = player->mo->y;
P_UnsetThingPosition(player->mo);
player->mo->x += player->mo->momx;
player->mo->y += player->mo->momy;
P_SetThingPosition(player->mo);
for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
if (!node->m_sector)
break;
if (node->m_sector->ffloors)
{
ffloor_t *rover;
fixed_t topheight, bottomheight;
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER))
continue;
topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
if (topheight > player->mo->z && bottomheight < player->mo->z)
{
P_ResetPlayer(player);
S_StartSound(player->mo, sfx_s3k4a);
player->climbing = 5;
player->mo->momx = player->mo->momy = player->mo->momz = 0;
break;
}
}
}
floorz = P_GetFloorZ(player->mo, node->m_sector, player->mo->x, player->mo->y, NULL);
ceilingz = P_GetCeilingZ(player->mo, node->m_sector, player->mo->x, player->mo->y, NULL);
if (player->mo->z+player->mo->height > ceilingz
&& node->m_sector->ceilingpic == skyflatnum)
continue;
if (floorz > player->mo->z || ceilingz < player->mo->z)
{
P_ResetPlayer(player);
S_StartSound(player->mo, sfx_s3k4a);
player->climbing = 5;
player->mo->momx = player->mo->momy = player->mo->momz = 0;
break;
}
}
P_UnsetThingPosition(player->mo);
player->mo->x = oldx;
player->mo->y = oldy;
P_SetThingPosition(player->mo);
}
// Check for a BOUNCY sector! // Check for a BOUNCY sector!
if (CheckForBouncySector) if (CheckForBouncySector)
P_CheckBouncySectors(player); P_CheckBouncySectors(player);
@ -8986,6 +8995,49 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
} }
} }
//
// P_Earthquake
// Used for Super Knuckles' landing - damages enemies within the given radius
//
void P_Earthquake(mobj_t *inflictor, mobj_t *source, fixed_t radius)
{
const fixed_t scaledradius = FixedMul(radius, inflictor->scale);
const fixed_t ns = scaledradius/12;
mobj_t *mo;
angle_t fa;
INT32 i;
boolean grounded = P_IsObjectOnGround(inflictor);
for (i = 0; i < 16; i++)
{
fa = (i*(FINEANGLES/16));
mo = P_SpawnMobjFromMobj(inflictor, 0, 0, 0, MT_SUPERSPARK);
if (!P_MobjWasRemoved(mo))
{
if (grounded)
{
mo->momx = FixedMul(FINESINE(fa),ns);
mo->momy = FixedMul(FINECOSINE(fa),ns);
}
else
{
P_InstaThrust(mo, inflictor->angle + ANGLE_90, FixedMul(FINECOSINE(fa),ns));
mo->momz = FixedMul(FINESINE(fa),ns);
}
}
}
if (inflictor->player && P_IsLocalPlayer(inflictor->player))
{
quake.epicenter = NULL;
quake.intensity = 8*inflictor->scale;
quake.time = 8;
quake.radius = scaledradius;
}
P_RadiusAttack(inflictor, source, radius, 0, false);
}
// //
// P_LookForFocusTarget // P_LookForFocusTarget
// Looks for a target for a player to focus on, for Z-targeting etc. // Looks for a target for a player to focus on, for Z-targeting etc.
@ -12090,6 +12142,11 @@ void P_PlayerThink(player_t *player)
else else
player->powers[pw_nocontrol] = 0; player->powers[pw_nocontrol] = 0;
if (player->powers[pw_ignorelatch] & ((1<<15)-1) && player->powers[pw_ignorelatch] < UINT16_MAX)
player->powers[pw_ignorelatch]--;
else
player->powers[pw_ignorelatch] = 0;
//pw_super acts as a timer now //pw_super acts as a timer now
if (player->powers[pw_super] if (player->powers[pw_super]
&& (player->mo->state < &states[S_PLAY_SUPER_TRANS1] && (player->mo->state < &states[S_PLAY_SUPER_TRANS1]

View File

@ -1367,6 +1367,8 @@ static void R_ProjectSprite(mobj_t *thing)
size_t frame, rot; size_t frame, rot;
UINT16 flip; UINT16 flip;
boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP)); boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP));
boolean mirrored = thing->mirrored;
boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored);
INT32 lindex; INT32 lindex;
@ -1477,7 +1479,11 @@ static void R_ProjectSprite(mobj_t *thing)
#endif #endif
if (sprframe->rotate != SRF_SINGLE || papersprite) if (sprframe->rotate != SRF_SINGLE || papersprite)
{
ang = R_PointToAngle (thing->x, thing->y) - (thing->player ? thing->player->drawangle : thing->angle); ang = R_PointToAngle (thing->x, thing->y) - (thing->player ? thing->player->drawangle : thing->angle);
if (mirrored)
ang = InvAngle(ang);
}
if (sprframe->rotate == SRF_SINGLE) if (sprframe->rotate == SRF_SINGLE)
{ {
@ -1537,6 +1543,8 @@ static void R_ProjectSprite(mobj_t *thing)
} }
#endif #endif
flip = !flip != !hflip;
// calculate edges of the shape // calculate edges of the shape
if (flip) if (flip)
offset = spr_offset - spr_width; offset = spr_offset - spr_width;

View File

@ -330,7 +330,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s1a8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s1a8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s1a9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s1a9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s1aa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s1aa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s1ab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s1ab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Chomp"},
{"s1ac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s1ac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s1ad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s1ad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s1ae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s1ae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},

View File

@ -821,7 +821,7 @@ static void ST_drawLivesArea(void)
// skincolor face/super // skincolor face/super
UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->mo->color, GTC_CACHE); UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->mo->color, GTC_CACHE);
patch_t *face = faceprefix[stplyr->skin]; patch_t *face = faceprefix[stplyr->skin];
if (stplyr->powers[pw_super]) if (stplyr->powers[pw_super] && !(stplyr->charflags & SF_NOSUPERSPRITES))
face = superprefix[stplyr->skin]; face = superprefix[stplyr->skin];
V_DrawSmallMappedPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y, V_DrawSmallMappedPatch(hudinfo[HUD_LIVES].x, hudinfo[HUD_LIVES].y,
hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, face, colormap); hudinfo[HUD_LIVES].f|V_PERPLAYER|V_HUDTRANS, face, colormap);