Merge branch 'master' of https://git.magicalgirl.moe/STJr/SRB2Internal.git into nightsplus-laplogic

# Conflicts:
#	src/p_setup.c
This commit is contained in:
mazmazz 2018-08-10 13:35:59 -04:00
commit 487c62fe31
58 changed files with 19500 additions and 14330 deletions

View file

@ -1,3 +1,4 @@
*.exe
*.mo
r_opengl.dll
*.bat

View file

@ -1,3 +1,4 @@
# GNU Make makefile for SRB2
#############################################################################
# Copyright (C) 1998-2000 by DooM Legacy Team.
@ -357,7 +358,8 @@ endif
ifdef PROFILEMODE
# build with profiling information
CFLAGS:=-pg $(CFLAGS)
CFLAGS+=-pg
LDFLAGS+=-pg
endif
ifdef ZDEBUG

View file

@ -275,8 +275,7 @@ void B_RespawnBot(INT32 playernum)
player->accelstart = sonic->player->accelstart;
player->thrustfactor = sonic->player->thrustfactor;
player->normalspeed = sonic->player->normalspeed;
player->pflags |= PF_AUTOBRAKE;
player->pflags &= ~PF_DIRECTIONCHAR;
player->pflags |= PF_AUTOBRAKE|(sonic->player->pflags & PF_DIRECTIONCHAR);
P_TeleportMove(tails, x, y, z);
if (player->charability == CA_FLY)

View file

@ -16,7 +16,7 @@
#define ASSET_HASH_RINGS_DTA "${SRB2_ASSET_rings.dta_HASH}"
#define ASSET_HASH_ZONES_DTA "${SRB2_ASSET_zones.dta_HASH}"
#ifdef USE_PATCH_DTA
#define ASSET_HASH_PATCH_DTA "${SRB2_ASSET_patch.dta_HASH}"
#define ASSET_HASH_PATCH_PK3 "${SRB2_ASSET_patch.pk3_HASH}"
#endif
#define SRB2_COMP_REVISION "${SRB2_COMP_REVISION}"
@ -36,7 +36,7 @@
#define ASSET_HASH_PLAYER_DTA "cfca0f1c73023cbbd8f844f45480f799"
#define ASSET_HASH_RINGS_DTA "85901ad4bf94637e5753d2ac2c03ea26"
#ifdef USE_PATCH_DTA
#define ASSET_HASH_PATCH_DTA "dbbf8bc6121618ee3be2d5b14650429b"
#define ASSET_HASH_PATCH_PK3 "dbbf8bc6121618ee3be2d5b14650429b"
#endif
#endif

View file

@ -312,7 +312,7 @@ static void CON_SetupColormaps(void)
colset(lgreenmap, 97, 98, 106);
colset(bluemap, 146, 147, 155);
colset(redmap, 210, 32, 39);
colset(graymap, 8, 10, 15);
colset(graymap, 6, 8, 14);
colset(orangemap, 51, 52, 57);
colset(skymap, 129, 130, 133);
colset(purplemap, 160, 161, 163);

View file

@ -395,8 +395,7 @@ static void ExtraDataTicker(void)
DEBFILE(va("player %d kicked [gametic=%u] reason as follows:\n", i, gametic));
}
CONS_Alert(CONS_WARNING, M_GetText("Got unknown net command [%s]=%d (max %d)\n"), sizeu1(curpos - bufferstart), *curpos, bufferstart[0]);
D_FreeTextcmd(gametic);
return;
break;
}
}
}
@ -513,7 +512,8 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->powers[j] = (UINT16)SHORT(players[i].powers[j]);
// Score is resynched in the rspfirm resync packet
rsp->rings = LONG(players[i].rings);
rsp->rings = SHORT(players[i].rings);
rsp->spheres = SHORT(players[i].spheres);
rsp->lives = players[i].lives;
rsp->continues = players[i].continues;
rsp->scoreadd = players[i].scoreadd;
@ -643,7 +643,8 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].powers[j] = (UINT16)SHORT(rsp->powers[j]);
// Score is resynched in the rspfirm resync packet
players[i].rings = LONG(rsp->rings);
players[i].rings = SHORT(rsp->rings);
players[i].spheres = SHORT(rsp->spheres);
players[i].lives = rsp->lives;
players[i].continues = rsp->continues;
players[i].scoreadd = rsp->scoreadd;
@ -2254,7 +2255,7 @@ static void Command_connect(void)
// Assume we connect directly.
boolean viams = false;
if (COM_Argc() < 2)
if (COM_Argc() < 2 || *COM_Argv(1) == 0)
{
CONS_Printf(M_GetText(
"Connect <serveraddress> (port): connect to a server\n"
@ -2377,11 +2378,11 @@ static void CL_RemovePlayer(INT32 playernum)
if (gametype == GT_CTF)
P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you!
// If in a special stage, redistribute the player's rings across
// If in a special stage, redistribute the player's spheres across
// the remaining players.
if (G_IsSpecialStage(gamemap))
{
INT32 i, count, increment, rings;
INT32 i, count, increment, spheres;
for (i = 0, count = 0; i < MAXPLAYERS; i++)
{
@ -2390,19 +2391,19 @@ static void CL_RemovePlayer(INT32 playernum)
}
count--;
rings = players[playernum].rings;
increment = rings/count;
spheres = players[playernum].spheres;
increment = spheres/count;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && i != playernum)
{
if (rings < increment)
P_GivePlayerRings(&players[i], rings);
if (spheres < increment)
P_GivePlayerSpheres(&players[i], spheres);
else
P_GivePlayerRings(&players[i], increment);
P_GivePlayerSpheres(&players[i], increment);
rings -= increment;
spheres -= increment;
}
}
}
@ -3326,7 +3327,7 @@ void SV_StopServer(void)
localtextcmd[0] = 0;
localtextcmd2[0] = 0;
for (i = 0; i < BACKUPTICS; i++)
for (i = firstticstosend; i < firstticstosend + BACKUPTICS; i++)
D_Clearticcmd(i);
consoleplayer = 0;

View file

@ -164,7 +164,8 @@ typedef struct
UINT16 powers[NUMPOWERS];
// Score is resynched in the confirm resync packet
INT32 rings;
INT16 rings;
INT16 spheres;
SINT8 lives;
SINT8 continues;
UINT8 scoreadd;

View file

@ -734,11 +734,6 @@ void D_StartTitle(void)
CON_ToggleOff();
// Reset the palette
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_SetPaletteColor(0);
else
#endif
if (rendermode != render_none)
V_SetPaletteLump("PLAYPAL");
}
@ -843,7 +838,7 @@ static void IdentifyVersion(void)
#ifdef USE_PATCH_DTA
// Add our crappy patches to fix our bugs
D_AddFile(va(pandf,srb2waddir,"patch.dta"));
D_AddFile(va(pandf,srb2waddir,"patch.pk3"));
#endif
#if !defined (HAVE_SDL) || defined (HAVE_MIXER)
@ -1037,19 +1032,10 @@ void D_SRB2Main(void)
if (M_CheckParm("-password") && M_IsNextParm())
D_SetPassword(M_GetNextParm());
else
{
size_t z;
char junkpw[25];
for (z = 0; z < 24; z++)
junkpw[z] = (char)(rand() & 64)+32;
junkpw[24] = '\0';
D_SetPassword(junkpw);
}
// add any files specified on the command line with -file wadfile
// to the wad list
if (!(M_CheckParm("-connect")))
if (!(M_CheckParm("-connect") && !M_CheckParm("-server")))
{
if (M_CheckParm("-file"))
{
@ -1129,7 +1115,7 @@ void D_SRB2Main(void)
//W_VerifyFileMD5(1, ASSET_HASH_ZONES_DTA); // zones.dta
//W_VerifyFileMD5(2, ASSET_HASH_PLAYER_DTA); // player.dta
#ifdef USE_PATCH_DTA
W_VerifyFileMD5(3, ASSET_HASH_PATCH_DTA); // patch.dta
//W_VerifyFileMD5(3, ASSET_HASH_PATCH_PK3); // patch.pk3
#endif
// don't check music.dta because people like to modify it, and it doesn't matter if they do
@ -1138,7 +1124,7 @@ void D_SRB2Main(void)
mainwads = 3; // there are 3 wads not to unload
#ifdef USE_PATCH_DTA
++mainwads; // patch.dta adds one more
++mainwads; // patch.pk3 adds one more
#endif
#ifdef DEVELOP
++mainwads; // music_new, too
@ -1204,7 +1190,15 @@ void D_SRB2Main(void)
R_Init();
// setting up sound
CONS_Printf("S_Init(): Setting up sound.\n");
if (dedicated)
{
nosound = true;
nomidimusic = nodigimusic = true;
}
else
{
CONS_Printf("S_Init(): Setting up sound.\n");
}
if (M_CheckParm("-nosound"))
nosound = true;
if (M_CheckParm("-nomusic")) // combines -nomidimusic and -nodigmusic
@ -1316,7 +1310,7 @@ void D_SRB2Main(void)
}
}
if (autostart || netgame || M_CheckParm("+connect") || M_CheckParm("-connect"))
if (autostart || netgame)
{
gameaction = ga_nothing;
@ -1350,8 +1344,7 @@ void D_SRB2Main(void)
}
}
if (server && !M_CheckParm("+map") && !M_CheckParm("+connect")
&& !M_CheckParm("-connect"))
if (server && !M_CheckParm("+map"))
{
// Prevent warping to nonexistent levels
if (W_CheckNumForName(G_BuildMapName(pstartmap)) == LUMPERROR)

View file

@ -309,8 +309,8 @@ consvar_t cv_overtime = {"overtime", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL,
consvar_t cv_rollingdemos = {"rollingdemos", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t timetic_cons_t[] = {{0, "Normal"}, {1, "Centiseconds"}, {2, "Mania"}, {3, "Tics"}, {0, NULL}};
consvar_t cv_timetic = {"timerres", "Normal", CV_SAVE, timetic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display
static CV_PossibleValue_t timetic_cons_t[] = {{0, "Classic"}, {1, "Centiseconds"}, {2, "Mania"}, {3, "Tics"}, {0, NULL}};
consvar_t cv_timetic = {"timerres", "Classic", CV_SAVE, timetic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
static CV_PossibleValue_t powerupdisplay_cons_t[] = {{0, "Never"}, {1, "First-person only"}, {2, "Always"}, {0, NULL}};
consvar_t cv_powerupdisplay = {"powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -2682,8 +2682,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
// Clear player score and rings if a spectator.
if (players[playernum].spectator)
{
players[playernum].score = 0;
players[playernum].rings = 0;
players[playernum].score = players[playernum].rings = 0;
if (players[playernum].mo)
players[playernum].mo->health = 1;
}
@ -2725,10 +2724,12 @@ static void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt,
#define BASESALT "basepasswordstorage"
static UINT8 adminpassmd5[16];
static boolean adminpasswordset = false;
void D_SetPassword(const char *pw)
{
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &adminpassmd5);
adminpasswordset = true;
}
// Remote Administration
@ -2797,6 +2798,12 @@ static void Got_Login(UINT8 **cp, INT32 playernum)
READMEM(*cp, sentmd5, 16);
if (!adminpasswordset)
{
CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[playernum]);
return;
}
if (client)
return;
@ -3930,28 +3937,7 @@ static void Command_ExitLevel_f(void)
else if (gamestate != GS_LEVEL || demoplayback)
CONS_Printf(M_GetText("You must be in a level to use this.\n"));
else
{
if ((netgame || multiplayer)
&& ((mapheaderinfo[gamemap-1]->nextlevel <= 0)
|| (mapheaderinfo[gamemap-1]->nextlevel > NUMMAPS)
|| !(mapvisited[mapheaderinfo[gamemap-1]->nextlevel-1])))
{
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && players[i].exiting)
break;
}
if (i == MAXPLAYERS)
{
CONS_Printf(M_GetText("Someone must finish the level for you to use this.\n"));
return;
}
}
SendNetXCmd(XD_EXITLEVEL, NULL, 0);
}
}
static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum)
@ -4066,7 +4052,7 @@ static void Command_RestartAudio_f(void)
I_ShutdownSound();
I_StartupSound();
I_InitMusic();
// These must be called or no sound and music until manually set.
I_SetSfxVolume(cv_soundvolume.value);
@ -4074,7 +4060,7 @@ static void Command_RestartAudio_f(void)
I_SetMIDIMusicVolume(cv_midimusicvolume.value);
if (Playing()) // Gotta make sure the player is in a level
P_RestoreMusic(&players[consoleplayer]);
}
/** Quits a game and returns to the title screen.

View file

@ -950,15 +950,37 @@ filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum)
return FS_FOUND; // will never happen, but makes the compiler shut up
}
// Rewritten by Monster Iestyn to be less stupid
// Note: if completepath is true, "filename" is modified, but only if FS_FOUND is going to be returned
// (Don't worry about WinCE's version of filesearch, nobody cares about that OS anymore)
filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean completepath)
{
filestatus_t homecheck = filesearch(filename, srb2home, wantedmd5sum, false, 10);
if (homecheck == FS_FOUND)
return filesearch(filename, srb2home, wantedmd5sum, completepath, 10);
filestatus_t homecheck; // store result of last file search
boolean badmd5 = false; // store whether md5 was bad from either of the first two searches (if nothing was found in the third)
homecheck = filesearch(filename, srb2path, wantedmd5sum, false, 10);
if (homecheck == FS_FOUND)
return filesearch(filename, srb2path, wantedmd5sum, completepath, 10);
// first, check SRB2's "home" directory
homecheck = filesearch(filename, srb2home, wantedmd5sum, completepath, 10);
return filesearch(filename, ".", wantedmd5sum, completepath, 10);
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND;
else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5
badmd5 = true;
// if not found at all, just move on without doing anything
// next, check SRB2's "path" directory
homecheck = filesearch(filename, srb2path, wantedmd5sum, completepath, 10);
if (homecheck == FS_FOUND) // we found the file, so return that we have :)
return FS_FOUND;
else if (homecheck == FS_MD5SUMBAD) // file has a bad md5; move on and look for a file with the right md5
badmd5 = true;
// if not found at all, just move on without doing anything
// finally check "." directory
homecheck = filesearch(filename, ".", wantedmd5sum, completepath, 10);
if (homecheck != FS_NOTFOUND) // if not found this time, fall back on the below return statement
return homecheck; // otherwise return the result we got
return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found
}

View file

@ -324,7 +324,8 @@ typedef struct player_s
angle_t drawangle;
// player's ring count
INT32 rings;
INT16 rings;
INT16 spheres;
SINT8 pity; // i pity the fool.
INT32 currentweapon; // current weapon selected.
@ -462,7 +463,7 @@ typedef struct player_s
tic_t marebegunat; // Leveltime when mare begun
tic_t startedtime; // Time which you started this mare with.
tic_t finishedtime; // Time it took you to finish the mare (used for display)
INT16 finishedrings; // The rings you had left upon finishing the mare
INT16 finishedspheres; // The spheres you had left upon finishing the mare
UINT32 marescore; // score for this nights stage
UINT32 lastmarescore; // score for the last mare
UINT8 lastmare; // previous mare

File diff suppressed because it is too large Load diff

View file

@ -46,6 +46,9 @@ enum
ML_BLOCKMAP, // LUT, motion clipping, walls/grid element
};
// Extra flag for objects.
#define MTF_EXTRA 1
// Reverse gravity flag for objects.
#define MTF_OBJECTFLIP 2

View file

@ -569,6 +569,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
/// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink.
/// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
//#define SECTORSPECIALSAFTERTHINK
#define SECTORSPECIALSAFTERTHINK
#endif // __DOOMDEF__

View file

@ -126,15 +126,13 @@ extern INT32 secondarydisplayplayer; // for splitscreen
// Maps of special importance
extern INT16 spstage_start;
extern INT16 sstage_start;
extern INT16 sstage_end;
extern INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
extern INT16 titlemap;
extern boolean hidetitlepics;
extern INT16 bootmap; //bootmap for loading a map on startup
extern boolean looptitle;
extern boolean useNightsSS;
// CTF colors.
extern UINT8 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor_bluering;
@ -175,7 +173,7 @@ extern cutscene_t *cutscenes[128];
extern INT16 nextmapoverride;
extern boolean skipstats;
extern UINT32 totalrings; // Total # of rings in a level
extern UINT32 ssspheres; // Total # of spheres in a level
// Fun extra stuff
extern INT16 lastmap; // Last level you were at (returning from special stages).

View file

@ -987,7 +987,6 @@ static const char *credits[] = {
"\1Programming",
"Alam \"GBC\" Arias",
"Logan \"GBA\" Arias",
"Colette \"fickle\" Bordelon",
"Callum Dickinson",
"Scott \"Graue\" Feeney",
"Nathan \"Jazz\" Giroux",
@ -1345,7 +1344,7 @@ void F_GameEvaluationDrawer(void)
++timesBeatenUltimate;
if (M_UpdateUnlockablesAndExtraEmblems())
S_StartSound(NULL, sfx_ncitem);
S_StartSound(NULL, sfx_s3k68);
G_SaveGameData();
}

View file

@ -116,20 +116,18 @@ INT32 secondarydisplayplayer; // for splitscreen
tic_t gametic;
tic_t levelstarttic; // gametic at level start
UINT32 totalrings; // for intermission
UINT32 ssspheres; // old special stage
INT16 lastmap; // last level you were at (returning from special stages)
tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
INT16 spstage_start;
INT16 sstage_start;
INT16 sstage_end;
INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
INT16 titlemap = 0;
boolean hidetitlepics = false;
INT16 bootmap; //bootmap for loading a map on startup
boolean looptitle = false;
boolean useNightsSS = false;
UINT8 skincolor_redteam = SKINCOLOR_RED;
UINT8 skincolor_blueteam = SKINCOLOR_BLUE;
@ -2201,7 +2199,7 @@ void G_PlayerReborn(INT32 player)
p->pflags |= PF_JUMPDOWN;
p->playerstate = PST_LIVE;
p->rings = 0; // 0 rings
p->rings = p->spheres = 0; // 0 rings
p->panim = PA_IDLE; // standing animation
//if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there
@ -2798,7 +2796,11 @@ INT32 G_GetGametypeByName(const char *gametypestr)
//
boolean G_IsSpecialStage(INT32 mapnum)
{
if (gametype == GT_COOP && modeattacking != ATTACKING_RECORD && mapnum >= sstage_start && mapnum <= sstage_end)
if (gametype != GT_COOP || modeattacking == ATTACKING_RECORD)
return false;
if (mapnum >= sstage_start && mapnum <= sstage_end)
return true;
if (mapnum >= smpstage_start && mapnum <= smpstage_end)
return true;
return false;
@ -3023,21 +3025,14 @@ static void G_DoCompleted(void)
{
token--;
if (!(emeralds & EMERALD1))
nextmap = (INT16)(sstage_start - 1); // Special Stage 1
else if (!(emeralds & EMERALD2))
nextmap = (INT16)(sstage_start); // Special Stage 2
else if (!(emeralds & EMERALD3))
nextmap = (INT16)(sstage_start + 1); // Special Stage 3
else if (!(emeralds & EMERALD4))
nextmap = (INT16)(sstage_start + 2); // Special Stage 4
else if (!(emeralds & EMERALD5))
nextmap = (INT16)(sstage_start + 3); // Special Stage 5
else if (!(emeralds & EMERALD6))
nextmap = (INT16)(sstage_start + 4); // Special Stage 6
else if (!(emeralds & EMERALD7))
nextmap = (INT16)(sstage_start + 5); // Special Stage 7
else
for (i = 0; i < 7; i++)
if (!(emeralds & (1<<i)))
{
nextmap = ((netgame || multiplayer) ? smpstage_start : sstage_start) + i - 1; // to special stage!
break;
}
if (i == 7)
gottoken = false;
}
@ -3209,9 +3204,9 @@ void G_LoadGameSettings(void)
{
// defaults
spstage_start = 1;
sstage_start = 50;
sstage_end = 57; // 8 special stages in vanilla SRB2
useNightsSS = false; //true;
sstage_start = smpstage_start = 50;
sstage_end = smpstage_end = 56; // 7 special stages in vanilla SRB2
sstage_end++; // plus one weirdo
// initialize free sfx slots for skin sounds
S_InitRuntimeSounds();
@ -3817,7 +3812,8 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
unlocktriggers = 0;
// clear itemfinder, just in case
CV_StealthSetValue(&cv_itemfinder, 0);
if (!dedicated) // except in dedicated servers, where it is not registered and can actually I_Error debug builds
CV_StealthSetValue(&cv_itemfinder, 0);
}
// internal game map

View file

@ -68,7 +68,6 @@ typedef struct gr_vissprite_s
struct gr_vissprite_s *prev;
struct gr_vissprite_s *next;
float x1, x2;
float z1, z2;
float tz, ty;
lumpnum_t patchlumpnum;
boolean flip;
@ -79,6 +78,7 @@ typedef struct gr_vissprite_s
//Hurdler: 25/04/2000: now support colormap in hardware mode
UINT8 *colormap;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
float z1, z2;
} gr_vissprite_t;
// --------

View file

@ -62,7 +62,7 @@ static dynlights_t *dynlights = &view_dynlights[0];
light_t lspr[NUMLIGHTS] =
{
// type offset x, y coronas color, c_size,light color,l_radius, sqr radius computed at init
// UNDEFINED: 0
// NOLIGHT: 0
{ UNDEFINED_SPR, 0.0f, 0.0f, 0x00000000, 24.0f, 0x00000000, 0.0f, 0.0f},
// weapons
// RINGSPARK_L
@ -151,10 +151,9 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_POSS
&lspr[NOLIGHT], // SPR_SPOS
&lspr[NOLIGHT], // SPR_FISH
&lspr[NOLIGHT], // SPR_BUZZ Graue 03-10-2004
&lspr[NOLIGHT], // SPR_RBUZ Graue 03-10-2004
&lspr[NOLIGHT], // SPR_BUZZ
&lspr[NOLIGHT], // SPR_RBUZ
&lspr[NOLIGHT], // SPR_JETB
&lspr[NOLIGHT], // SPR_JETW
&lspr[NOLIGHT], // SPR_JETG
&lspr[NOLIGHT], // SPR_CCOM
&lspr[NOLIGHT], // SPR_DETN
@ -162,19 +161,20 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_TRET
&lspr[NOLIGHT], // SPR_TURR
&lspr[NOLIGHT], // SPR_SHRP
&lspr[NOLIGHT], // SPR_CRAB
&lspr[NOLIGHT], // SPR_JJAW
&lspr[NOLIGHT], // SPR_SNLR
&lspr[NOLIGHT], // SPR_VLTR
&lspr[NOLIGHT], // SPR_PNTY
&lspr[NOLIGHT], // SPR_ARCH
&lspr[NOLIGHT], // SPR_CBFS
&lspr[JETLIGHT_L], // SPR_STAB
&lspr[NOLIGHT], // SPR_SPSH
&lspr[NOLIGHT], // SPR_ESHI
&lspr[NOLIGHT], // SPR_GSNP
&lspr[NOLIGHT], // SPR_MNUS
&lspr[NOLIGHT], // SPR_SSHL
&lspr[NOLIGHT], // SPR_UNID
&lspr[NOLIGHT], // SPR_BBUZ
// Generic Boos Items
&lspr[JETLIGHT_L], // SPR_JETF // Boss jet fumes
@ -227,18 +227,18 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_RING
&lspr[NOLIGHT], // SPR_TRNG
&lspr[NOLIGHT], // SPR_TOKE
&lspr[REDBALL_L], // SPR_RFLG
&lspr[BLUEBALL_L], // SPR_BFLG
&lspr[NOLIGHT], // SPR_NWNG
&lspr[REDBALL_L], // SPR_RFLG
&lspr[BLUEBALL_L], // SPR_BFLG
&lspr[NOLIGHT], // SPR_SPHR
&lspr[NOLIGHT], // SPR_NCHP
&lspr[NOLIGHT], // SPR_NSTR
&lspr[NOLIGHT], // SPR_EMBM
&lspr[NOLIGHT], // SPR_CEMG
&lspr[NOLIGHT], // SPR_EMER
&lspr[NOLIGHT], // SPR_SHRD
// Interactive Objects
&lspr[NOLIGHT], // SPR_FANS
&lspr[NOLIGHT], // SPR_BBLS
&lspr[NOLIGHT], // SPR_SIGN
&lspr[NOLIGHT], // SPR_STEM
&lspr[NOLIGHT], // SPR_SPIK
&lspr[NOLIGHT], // SPR_SFLM
&lspr[NOLIGHT], // SPR_USPK
@ -294,17 +294,19 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_FWR4
&lspr[NOLIGHT], // SPR_BUS1
&lspr[NOLIGHT], // SPR_BUS2
&lspr[NOLIGHT], // SPR_BUS3
// Trees (both GFZ and misc)
&lspr[NOLIGHT], // SPR_TRE1
&lspr[NOLIGHT], // SPR_TRE2
&lspr[NOLIGHT], // SPR_TRE3
&lspr[NOLIGHT], // SPR_TRE4
&lspr[NOLIGHT], // SPR_TRE5
&lspr[NOLIGHT], // SPR_TRE6
// Techno Hill Scenery
&lspr[NOLIGHT], // SPR_THZP
&lspr[NOLIGHT], // SPR_FWR5
&lspr[REDBALL_L], // SPR_ALRM
&lspr[REDBALL_L], // SPR_ALRM
// Deep Sea Scenery
&lspr[NOLIGHT], // SPR_GARG
@ -327,6 +329,15 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_RSPB
&lspr[REDBALL_L], // SPR_SFBR
&lspr[REDBALL_L], // SPR_BFBR
&lspr[NOLIGHT], // SPR_BANR
&lspr[NOLIGHT], // SPR_PINE
&lspr[NOLIGHT], // SPR_CEZB
&lspr[REDBALL_L], // SPR_CNDL
&lspr[NOLIGHT], // SPR_FLMH
&lspr[REDBALL_L], // SPR_CTRC
&lspr[NOLIGHT], // SPR_CFLG
&lspr[NOLIGHT], // SPR_CSTA
&lspr[NOLIGHT], // SPR_CBBS
// Arid Canyon Scenery
&lspr[NOLIGHT], // SPR_BTBL
@ -347,12 +358,25 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_XMS3
&lspr[NOLIGHT], // SPR_XMS4
&lspr[NOLIGHT], // SPR_XMS5
&lspr[NOLIGHT], // SPR_FHZI
// Halloween Scenery
&lspr[RINGLIGHT_L], // SPR_PUMK
&lspr[NOLIGHT], // SPR_HHPL
&lspr[NOLIGHT], // SPR_SHRM
&lspr[NOLIGHT], // SPR_HHZM
// Botanic Serenity Scenery
&lspr[NOLIGHT], // SPR_BSZ1
&lspr[NOLIGHT], // SPR_BSZ2
&lspr[NOLIGHT], // SPR_BSZ3
&lspr[NOLIGHT], // SPR_BSZ4
//&lspr[NOLIGHT], -- SPR_BSZ4
&lspr[NOLIGHT], // SPR_BST1
&lspr[NOLIGHT], // SPR_BST2
&lspr[NOLIGHT], // SPR_BST3
&lspr[NOLIGHT], // SPR_BST4
&lspr[NOLIGHT], // SPR_BST5
&lspr[NOLIGHT], // SPR_BST6
&lspr[NOLIGHT], // SPR_BSZ5
&lspr[NOLIGHT], // SPR_BSZ6
&lspr[NOLIGHT], // SPR_BSZ7
@ -375,8 +399,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_FIRS
&lspr[NOLIGHT], // SPR_BUBS
&lspr[NOLIGHT], // SPR_ZAPS
&lspr[INVINCIBLE_L], // SPR_IVSP
&lspr[SUPERSPARK_L], // SPR_SSPK
&lspr[INVINCIBLE_L], // SPR_IVSP
&lspr[SUPERSPARK_L], // SPR_SSPK
&lspr[NOLIGHT], // SPR_GOAL
@ -398,13 +422,20 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_FL14
&lspr[NOLIGHT], // SPR_FL15
&lspr[NOLIGHT], // SPR_FL16
&lspr[NOLIGHT], // SPR_FS01
&lspr[NOLIGHT], // SPR_FS02
// Springs
&lspr[NOLIGHT], // SPR_FANS
&lspr[NOLIGHT], // SPR_STEM
&lspr[NOLIGHT], // SPR_BUMP
&lspr[NOLIGHT], // SPR_BLON
&lspr[NOLIGHT], // SPR_SPRY
&lspr[NOLIGHT], // SPR_SPRR
&lspr[NOLIGHT], // SPR_SPRB Graue
&lspr[NOLIGHT], // SPR_SPRB
&lspr[NOLIGHT], // SPR_YSPR
&lspr[NOLIGHT], // SPR_RSPR
&lspr[NOLIGHT], // SPR_BSPR
&lspr[NOLIGHT], // SPR_SSWY
&lspr[NOLIGHT], // SPR_SSWR
&lspr[NOLIGHT], // SPR_SSWB
@ -420,7 +451,7 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_DUST
&lspr[NOLIGHT], // SPR_FPRT
&lspr[SUPERSPARK_L], // SPR_TFOG
&lspr[NIGHTSLIGHT_L], // SPR_SEED // Sonic CD flower seed
&lspr[NIGHTSLIGHT_L], // SPR_SEED
&lspr[NOLIGHT], // SPR_PRTL
// Game Indicators
@ -459,25 +490,43 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_GOOM
&lspr[NOLIGHT], // SPR_BGOM
&lspr[REDBALL_L], // SPR_FFWR
&lspr[SMALLREDBALL_L], // SPR_FBLL
&lspr[SMALLREDBALL_L], // SPR_FBLL
&lspr[NOLIGHT], // SPR_SHLL
&lspr[REDBALL_L], // SPR_PUMA
&lspr[REDBALL_L], // SPR_PUMA
&lspr[NOLIGHT], // SPR_HAMM
&lspr[NOLIGHT], // SPR_KOOP
&lspr[REDBALL_L], // SPR_BFLM
&lspr[REDBALL_L], // SPR_BFLM
&lspr[NOLIGHT], // SPR_MAXE
&lspr[NOLIGHT], // SPR_MUS1
&lspr[NOLIGHT], // SPR_MUS2
&lspr[NOLIGHT], // SPR_TOAD
// NiGHTS Stuff
&lspr[SUPERSONIC_L], // SPR_NDRN // NiGHTS drone
&lspr[SUPERSONIC_L], // SPR_NDRN // NiGHTS drone
&lspr[NOLIGHT], // SPR_NSPK
&lspr[NOLIGHT], // SPR_NBMP
&lspr[NOLIGHT], // SPR_HOOP
&lspr[NOLIGHT], // SPR_HSCR
&lspr[NOLIGHT], // SPR_NPRU
&lspr[NOLIGHT], // SPR_CAPS
&lspr[INVINCIBLE_L], // SPR_IDYA
&lspr[NOLIGHT], // SPR_NTPN
&lspr[NOLIGHT], // SPR_SHLP
// Secret badniks and hazards, shhhh
&lspr[NOLIGHT], // SPR_PENG
&lspr[NOLIGHT], // SPR_POPH,
&lspr[NOLIGHT], // SPR_HIVE
&lspr[NOLIGHT], // SPR_BUMB,
&lspr[NOLIGHT], // SPR_BBUZ
&lspr[NOLIGHT], // SPR_FMCE,
&lspr[NOLIGHT], // SPR_HMCE,
&lspr[NOLIGHT], // SPR_CACO,
&lspr[BLUEBALL_L], // SPR_BAL2,
&lspr[NOLIGHT], // SPR_SBOB,
&lspr[BLUEBALL_L], // SPR_SBFL,
&lspr[BLUEBALL_L], // SPR_SBSK,
&lspr[NOLIGHT], // SPR_BATT,
// Debris
&lspr[RINGSPARK_L], // SPR_SPRK
@ -485,6 +534,7 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[SUPERSPARK_L], // SPR_BOM2
&lspr[SUPERSPARK_L], // SPR_BOM3
&lspr[NOLIGHT], // SPR_BOM4
&lspr[REDBALL_L], // SPR_BMNB
// Crumbly rocks
&lspr[NOLIGHT], // SPR_ROIA
@ -504,9 +554,6 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_ROIO
&lspr[NOLIGHT], // SPR_ROIP
// Blue Spheres
&lspr[NOLIGHT], // SPR_BBAL
// Gravity Well Objects
&lspr[NOLIGHT], // SPR_GWLG
&lspr[NOLIGHT], // SPR_GWLR

View file

@ -2115,27 +2115,34 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
}
else
{
#ifdef ESLOPE // P.S. this is better-organized than the old version
fixed_t offs = sides[(newline ? newline : rover->master)->sidenum[0]].rowoffset;
grTex = HWR_GetTexture(texnum);
wallVerts[3].t = (*rover->topheight - h + offs) * grTex->scaleY;
wallVerts[2].t = (*rover->topheight - hS + offs) * grTex->scaleY;
wallVerts[0].t = (*rover->topheight - l + offs) * grTex->scaleY;
wallVerts[1].t = (*rover->topheight - lS + offs) * grTex->scaleY;
#else
grTex = HWR_GetTexture(texnum);
fixed_t texturevpeg;
// Wow, how was this missing from OpenGL for so long?
// ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software
// -- Monster Iestyn 26/06/18
if (newline)
{
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset)) * grTex->scaleY;
texturevpeg = sides[newline->sidenum[0]].rowoffset;
if (newline->flags & ML_DONTPEGBOTTOM)
texturevpeg -= *rover->topheight - *rover->bottomheight;
}
else
{
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset)) * grTex->scaleY;
texturevpeg = sides[rover->master->sidenum[0]].rowoffset;
if (gr_linedef->flags & ML_DONTPEGBOTTOM)
texturevpeg -= *rover->topheight - *rover->bottomheight;
}
grTex = HWR_GetTexture(texnum);
#ifdef ESLOPE
wallVerts[3].t = (*rover->topheight - h + texturevpeg) * grTex->scaleY;
wallVerts[2].t = (*rover->topheight - hS + texturevpeg) * grTex->scaleY;
wallVerts[0].t = (*rover->topheight - l + texturevpeg) * grTex->scaleY;
wallVerts[1].t = (*rover->topheight - lS + texturevpeg) * grTex->scaleY;
#else
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + texturevpeg) * grTex->scaleY;
wallVerts[0].t = wallVerts[1].t = (*rover->topheight - l + texturevpeg) * grTex->scaleY;
#endif
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
@ -3032,8 +3039,8 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
return gld_clipper_SafeCheckRange(angle2, angle1);
#else
// check clip list for an open space
angle1 = R_PointToAngle(px1, py1) - dup_viewangle;
angle2 = R_PointToAngle(px2, py2) - dup_viewangle;
angle1 = R_PointToAngle2(dup_viewx>>1, dup_viewy>>1, px1>>1, py1>>1) - dup_viewangle;
angle2 = R_PointToAngle2(dup_viewx>>1, dup_viewy>>1, px2>>1, py2>>1) - dup_viewangle;
span = angle1 - angle2;
@ -4072,7 +4079,7 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
angle_t shadowdir;
// Set direction
if (splitscreen && stplyr != &players[displayplayer])
if (splitscreen && stplyr == &players[secondarydisplayplayer])
shadowdir = localangle2 + FixedAngle(cv_cam2_rotate.value);
else
shadowdir = localangle + FixedAngle(cv_cam_rotate.value);
@ -4359,6 +4366,9 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
i = 0;
temp = FLOAT_TO_FIXED(realtop);
if (spr->mobj->frame & FF_FULLBRIGHT)
lightlevel = 255;
#ifdef ESLOPE
for (i = 1; i < sector->numlights; i++)
{
@ -4366,14 +4376,16 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
: sector->lightlist[i].height;
if (h <= temp)
{
lightlevel = *list[i-1].lightlevel;
if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *list[i-1].lightlevel;
colormap = list[i-1].extra_colormap;
break;
}
}
#else
i = R_GetPlaneLight(sector, temp, false);
lightlevel = *list[i].lightlevel;
if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *list[i].lightlevel;
colormap = list[i].extra_colormap;
#endif
@ -4388,7 +4400,8 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
// even if we aren't changing colormap or lightlevel, we still need to continue drawing down the sprite
if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES))
{
lightlevel = *list[i].lightlevel;
if (!(spr->mobj->frame & FF_FULLBRIGHT))
lightlevel = *list[i].lightlevel;
colormap = list[i].extra_colormap;
}
@ -5305,7 +5318,6 @@ static void HWR_ProjectSprite(mobj_t *thing)
float tr_x, tr_y;
float tz;
float x1, x2;
float z1, z2;
float rightsin, rightcos;
float this_scale;
float gz, gzt;
@ -5320,9 +5332,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
INT32 heightsec, phs;
const boolean papersprite = (thing->frame & FF_PAPERSPRITE);
angle_t mobjangle = (thing->player ? thing->player->drawangle : thing->angle);
// float offset;
// float ang_scale = 1.0f, ang_scalez = 0.0f;
// float z1, z2;
float z1, z2;
if (!thing)
return;
@ -5377,28 +5387,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
I_Error("sprframes NULL for sprite %d\n", thing->sprite);
#endif
if (papersprite)
{
// Use the actual view angle, rather than the angle formed
// between the view point and the thing
// this makes sure paper sprites always appear at the right angle!
// Note: DO NOT do this in software mode version, it actually
// makes papersprites look WORSE there (I know, I've tried)
// Monster Iestyn - 13/05/17
ang = dup_viewangle - mobjangle;
/*
ang_scale = FIXED_TO_FLOAT(FINESINE(ang>>ANGLETOFINESHIFT));
ang_scalez = FIXED_TO_FLOAT(FINECOSINE(ang>>ANGLETOFINESHIFT));
if (ang_scale < 0)
{
ang_scale = -ang_scale;
ang_scalez = -ang_scalez;
}
*/
}
else if (sprframe->rotate != SRF_SINGLE)
ang = R_PointToAngle (thing->x, thing->y) - mobjangle;
ang = R_PointToAngle (thing->x, thing->y) - mobjangle;
if (sprframe->rotate == SRF_SINGLE)
{
@ -5406,6 +5395,14 @@ static void HWR_ProjectSprite(mobj_t *thing)
rot = 0; //Fab: for vis->patch below
lumpoff = sprframe->lumpid[0]; //Fab: see note above
flip = sprframe->flip; // Will only be 0x00 or 0xFF
if (papersprite && ang < ANGLE_180)
{
if (flip)
flip = 0;
else
flip = 255;
}
}
else
{
@ -5420,20 +5417,23 @@ static void HWR_ProjectSprite(mobj_t *thing)
//Fab: lumpid is the index for spritewidth,spriteoffset... tables
lumpoff = sprframe->lumpid[rot];
flip = sprframe->flip & (1<<rot);
if (papersprite && ang < ANGLE_180)
{
if (flip)
flip = 0;
else
flip = 1<<rot;
}
}
if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale);
if (papersprite) // replaces the ang_scale and scalez thing above
if (papersprite)
{
rightsin = FIXED_TO_FLOAT(FINESINE(mobjangle>>ANGLETOFINESHIFT));
rightcos = FIXED_TO_FLOAT(FINECOSINE(mobjangle>>ANGLETOFINESHIFT));
if (flip) // flip the signs of the above values so you don't end up displaying the sprite backwards
{
rightsin *= -1.0;
rightcos *= -1.0;
}
rightsin = FIXED_TO_FLOAT(FINESINE((mobjangle)>>ANGLETOFINESHIFT));
rightcos = FIXED_TO_FLOAT(FINECOSINE((mobjangle)>>ANGLETOFINESHIFT));
}
else
{
@ -5487,7 +5487,10 @@ static void HWR_ProjectSprite(mobj_t *thing)
}
heightsec = thing->subsector->sector->heightsec;
phs = players[displayplayer].mo->subsector->sector->heightsec;
if (viewplayer->mo && viewplayer->mo->subsector)
phs = viewplayer->mo->subsector->sector->heightsec;
else
phs = -1;
if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
{
@ -5505,13 +5508,13 @@ static void HWR_ProjectSprite(mobj_t *thing)
vis = HWR_NewVisSprite();
vis->x1 = x1;
vis->x2 = x2;
vis->z1 = z1;
vis->z2 = z2;
vis->tz = tz; // Keep tz for the simple sprite sorting that happens
vis->dispoffset = thing->info->dispoffset; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST
vis->patchlumpnum = sprframe->lumppat[rot];
vis->flip = flip;
vis->mobj = thing;
vis->z1 = z1;
vis->z2 = z2;
//Hurdler: 25/04/2000: now support colormap in hardware mode
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"

View file

@ -89,7 +89,7 @@ patch_t *tallinfin;
// coop hud
//-------------------------------------------
patch_t *emeraldpics[3][7]; // 0 = normal, 1 = tiny, 2 = coinbox
patch_t *emeraldpics[3][8]; // 0 = normal, 1 = tiny, 2 = coinbox
static patch_t *emblemicon;
patch_t *tokenicon;
static patch_t *exiticon;
@ -256,6 +256,7 @@ void HU_LoadGraphics(void)
emeraldpics[0][4] = W_CachePatchName("CHAOS5", PU_HUDGFX);
emeraldpics[0][5] = W_CachePatchName("CHAOS6", PU_HUDGFX);
emeraldpics[0][6] = W_CachePatchName("CHAOS7", PU_HUDGFX);
emeraldpics[0][7] = W_CachePatchName("CHAOS8", PU_HUDGFX);
emeraldpics[1][0] = W_CachePatchName("TEMER1", PU_HUDGFX);
emeraldpics[1][1] = W_CachePatchName("TEMER2", PU_HUDGFX);
@ -264,6 +265,7 @@ void HU_LoadGraphics(void)
emeraldpics[1][4] = W_CachePatchName("TEMER5", PU_HUDGFX);
emeraldpics[1][5] = W_CachePatchName("TEMER6", PU_HUDGFX);
emeraldpics[1][6] = W_CachePatchName("TEMER7", PU_HUDGFX);
//emeraldpics[1][7] = W_CachePatchName("TEMER8", PU_HUDGFX); -- unused
emeraldpics[2][0] = W_CachePatchName("EMBOX1", PU_HUDGFX);
emeraldpics[2][1] = W_CachePatchName("EMBOX2", PU_HUDGFX);
@ -272,6 +274,7 @@ void HU_LoadGraphics(void)
emeraldpics[2][4] = W_CachePatchName("EMBOX5", PU_HUDGFX);
emeraldpics[2][5] = W_CachePatchName("EMBOX6", PU_HUDGFX);
emeraldpics[2][6] = W_CachePatchName("EMBOX7", PU_HUDGFX);
//emeraldpics[2][7] = W_CachePatchName("EMBOX8", PU_HUDGFX); -- unused
}
// Initialise Heads up

View file

@ -63,7 +63,7 @@ extern patch_t *tallnum[10];
extern patch_t *nightsnum[10];
extern patch_t *lt_font[LT_FONTSIZE];
extern patch_t *cred_font[CRED_FONTSIZE];
extern patch_t *emeraldpics[3][7];
extern patch_t *emeraldpics[3][8];
extern patch_t *rflagico;
extern patch_t *bflagico;
extern patch_t *rmatcico;

3355
src/info.c

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -768,6 +768,19 @@ static int lib_pCanRunOnWater(lua_State *L)
return 1;
}
static int lib_pMaceRotate(lua_State *L)
{
mobj_t *center = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
INT32 baserot = luaL_checkinteger(L, 2);
INT32 baseprevrot = luaL_checkinteger(L, 3);
NOHUD
INLEVEL
if (!center)
return LUA_ErrInvalid(L, "mobj_t");
P_MaceRotate(center, baserot, baseprevrot);
return 0;
}
// P_USER
////////////
@ -1343,11 +1356,12 @@ static int lib_pRadiusAttack(lua_State *L)
mobj_t *spot = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t damagedist = luaL_checkfixed(L, 3);
UINT8 damagetype = luaL_optinteger(L, 4, 0);
NOHUD
INLEVEL
if (!spot || !source)
return LUA_ErrInvalid(L, "mobj_t");
P_RadiusAttack(spot, source, damagedist);
P_RadiusAttack(spot, source, damagedist, damagetype);
return 0;
}
@ -2517,6 +2531,7 @@ static luaL_Reg lib[] = {
{"P_CheckDeathPitCollide",lib_pCheckDeathPitCollide},
{"P_CheckSolidLava",lib_pCheckSolidLava},
{"P_CanRunOnWater",lib_pCanRunOnWater},
{"P_MaceRotate",lib_pMaceRotate},
// p_user
{"P_GetPlayerHeight",lib_pGetPlayerHeight},

View file

@ -85,7 +85,9 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
deny:
//must be hacked/buggy client
lua_settop(gL, 0); // clear stack
if (gL) // check if Lua is actually turned on first, you dummmy -- Monster Iestyn 04/07/18
lua_settop(gL, 0); // clear stack
CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]);
if (server)
{

View file

@ -24,7 +24,7 @@ enum hud {
// NiGHTS mode
hud_nightslink,
hud_nightsdrill,
hud_nightsrings,
hud_nightsspheres,
hud_nightsscore,
hud_nightstime,
hud_nightsrecords,

View file

@ -530,10 +530,22 @@ static int mobj_set(lua_State *L)
case mobj_bprev:
return UNIMPLEMENTED;
case mobj_hnext:
mo->hnext = luaL_checkudata(L, 3, META_MOBJ);
if (lua_isnil(L, 3))
P_SetTarget(&mo->hnext, NULL);
else
{
mobj_t *hnext = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&mo->hnext, hnext);
}
break;
case mobj_hprev:
mo->hprev = luaL_checkudata(L, 3, META_MOBJ);
if (lua_isnil(L, 3))
P_SetTarget(&mo->hprev, NULL);
else
{
mobj_t *hprev = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&mo->hprev, hprev);
}
break;
case mobj_type: // yeah sure, we'll let you change the mobj's type.
{

View file

@ -130,6 +130,8 @@ static int player_get(lua_State *L)
lua_pushangle(L, plr->drawangle);
else if (fastcmp(field,"rings"))
lua_pushinteger(L, plr->rings);
else if (fastcmp(field,"spheres"))
lua_pushinteger(L, plr->spheres);
else if (fastcmp(field,"pity"))
lua_pushinteger(L, plr->pity);
else if (fastcmp(field,"currentweapon"))
@ -298,8 +300,8 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->startedtime);
else if (fastcmp(field,"finishedtime"))
lua_pushinteger(L, plr->finishedtime);
else if (fastcmp(field,"finishedrings"))
lua_pushinteger(L, plr->finishedrings);
else if (fastcmp(field,"finishedspheres"))
lua_pushinteger(L, plr->finishedspheres);
else if (fastcmp(field,"marescore"))
lua_pushinteger(L, plr->marescore);
else if (fastcmp(field,"lastmarescore"))
@ -400,6 +402,8 @@ static int player_set(lua_State *L)
plr->drawangle = luaL_checkangle(L, 3);
else if (fastcmp(field,"rings"))
plr->rings = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"spheres"))
plr->spheres = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"pity"))
plr->pity = (SINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"currentweapon"))
@ -452,7 +456,7 @@ static int player_set(lua_State *L)
else if (fastcmp(field,"followitem"))
plr->followitem = luaL_checkinteger(L, 3);
else if (fastcmp(field,"followmobj"))
plr->followmobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_SetTarget(&plr->followmobj, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)));
else if (fastcmp(field,"actionspd"))
plr->actionspd = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"mindash"))
@ -578,8 +582,8 @@ static int player_set(lua_State *L)
plr->startedtime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"finishedtime"))
plr->finishedtime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"finishedrings"))
plr->finishedrings = (INT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"finishedspheres"))
plr->finishedspheres = (INT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"marescore"))
plr->marescore = (UINT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"lastmarescore"))

View file

@ -499,56 +499,211 @@ void Command_Teleport_f(void)
REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER;
if (COM_Argc() < 3 || COM_Argc() > 7)
if (COM_Argc() < 3 || COM_Argc() > 11)
{
CONS_Printf(M_GetText("teleport -x <value> -y <value> -z <value>: teleport to a location\n"));
CONS_Printf(M_GetText("teleport -x <value> -y <value> -z <value> -ang <value> -aim <value>: teleport to a location\nteleport -sp <sequence> <placement>: teleport to specified checkpoint\n"));
return;
}
if (!p->mo)
return;
i = COM_CheckParm("-x");
if (i)
intx = atoi(COM_Argv(i + 1));
else
{
CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified\n"), "X");
return;
}
i = COM_CheckParm("-y");
if (i)
inty = atoi(COM_Argv(i + 1));
else
{
CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified\n"), "Y");
return;
}
ss = R_PointInSubsector(intx*FRACUNIT, inty*FRACUNIT);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
return;
}
i = COM_CheckParm("-z");
i = COM_CheckParm("-sp");
if (i)
{
intz = atoi(COM_Argv(i + 1));
intz <<= FRACBITS;
if (intz < ss->sector->floorheight)
intz = ss->sector->floorheight;
if (intz > ss->sector->ceilingheight - p->mo->height)
intz = ss->sector->ceilingheight - p->mo->height;
INT32 starpostnum = atoi(COM_Argv(i + 1)); // starpost number
INT32 starpostpath = atoi(COM_Argv(i + 2)); // quick, dirty way to distinguish between paths
if (starpostnum < 0 || starpostpath < 0)
{
CONS_Alert(CONS_NOTICE, M_GetText("Negative starpost indexing is not valid.\n"));
return;
}
if (!starpostnum) // spawnpoints...
{
mapthing_t *mt;
if (starpostpath >= numcoopstarts)
{
CONS_Alert(CONS_NOTICE, M_GetText("Player %d spawnpoint not found (%d max).\n"), starpostpath+1, numcoopstarts-1);
return;
}
mt = playerstarts[starpostpath]; // Given above check, should never be NULL.
intx = mt->x<<FRACBITS;
inty = mt->y<<FRACBITS;
ss = R_IsPointInSubsector(intx, inty);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Spawnpoint not in a valid location.\n"));
return;
}
// Flagging a player's ambush will make them start on the ceiling
// Objectflip inverts
if (!!(mt->options & MTF_AMBUSH) ^ !!(mt->options & MTF_OBJECTFLIP))
{
intz = ss->sector->ceilingheight - p->mo->height;
if (mt->options >> ZSHIFT)
intz -= ((mt->options >> ZSHIFT) << FRACBITS);
}
else
{
intz = ss->sector->floorheight;
if (mt->options >> ZSHIFT)
intz += ((mt->options >> ZSHIFT) << FRACBITS);
}
if (mt->options & MTF_OBJECTFLIP) // flip the player!
{
p->mo->eflags |= MFE_VERTICALFLIP;
p->mo->flags2 |= MF2_OBJECTFLIP;
}
else
{
p->mo->eflags &= ~MFE_VERTICALFLIP;
p->mo->flags2 &= ~MF2_OBJECTFLIP;
}
localangle = p->mo->angle = p->drawangle = FixedAngle(mt->angle<<FRACBITS);
}
else // scan the thinkers to find starposts...
{
mobj_t *mo2;
thinker_t *th;
INT32 starpostmax = 0;
intz = starpostpath; // variable reuse - counting down for selection purposes
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_STARPOST)
continue;
if (mo2->health != starpostnum)
{
if (mo2->health > starpostmax)
starpostmax = mo2->health;
continue;
}
if (intz--)
continue;
break;
}
if (th == &thinkercap)
{
if (intz == starpostpath)
CONS_Alert(CONS_NOTICE, M_GetText("No starpost of position %d found (%d max).\n"), starpostnum, starpostmax);
else
CONS_Alert(CONS_NOTICE, M_GetText("Starpost of position %d, %d not found (%d, %d max).\n"), starpostnum, starpostpath, starpostmax, (starpostpath-intz)-1);
return;
}
ss = R_IsPointInSubsector(mo2->x, mo2->y);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Starpost not in a valid location.\n"));
return;
}
intx = mo2->x;
inty = mo2->y;
intz = mo2->z;
if (mo2->flags2 & MF2_OBJECTFLIP) // flip the player!
{
p->mo->eflags |= MFE_VERTICALFLIP;
p->mo->flags2 |= MF2_OBJECTFLIP;
}
else
{
p->mo->eflags &= ~MFE_VERTICALFLIP;
p->mo->flags2 &= ~MF2_OBJECTFLIP;
}
localangle = p->mo->angle = p->drawangle = mo2->angle;
}
CONS_Printf(M_GetText("Teleporting to checkpoint %d, %d...\n"), starpostnum, starpostpath);
}
else
intz = ss->sector->floorheight;
{
i = COM_CheckParm("-nop"); // undocumented stupid addition to allow pivoting on the spot with -ang and -aim
if (i)
{
intx = p->mo->x;
inty = p->mo->y;
}
else
{
i = COM_CheckParm("-x");
if (i)
intx = atoi(COM_Argv(i + 1))<<FRACBITS;
else
{
CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified.\n"), "X");
return;
}
CONS_Printf(M_GetText("Teleporting to %d, %d, %d...\n"), intx, inty, FixedInt(intz));
i = COM_CheckParm("-y");
if (i)
inty = atoi(COM_Argv(i + 1))<<FRACBITS;
else
{
CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified.\n"), "Y");
return;
}
}
ss = R_IsPointInSubsector(intx, inty);
if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height)
{
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n"));
return;
}
i = COM_CheckParm("-z");
if (i)
{
intz = atoi(COM_Argv(i + 1))<<FRACBITS;
if (intz < ss->sector->floorheight)
intz = ss->sector->floorheight;
if (intz > ss->sector->ceilingheight - p->mo->height)
intz = ss->sector->ceilingheight - p->mo->height;
}
else
intz = ((p->mo->eflags & MFE_VERTICALFLIP) ? ss->sector->ceilingheight : ss->sector->floorheight);
i = COM_CheckParm("-ang");
if (i)
localangle = p->drawangle = p->mo->angle = FixedAngle(atoi(COM_Argv(i + 1))<<FRACBITS);
i = COM_CheckParm("-aim");
if (i)
{
angle_t aim = FixedAngle(atoi(COM_Argv(i + 1))<<FRACBITS);
if (aim >= ANGLE_90 && aim <= ANGLE_270)
{
CONS_Alert(CONS_NOTICE, M_GetText("Not a valid aiming angle (between +/-90).\n"));
return;
}
localaiming = p->aiming = aim;
}
CONS_Printf(M_GetText("Teleporting to %d, %d, %d...\n"), FixedInt(intx), FixedInt(inty), FixedInt(intz));
}
P_MapStart();
if (!P_TeleportMove(p->mo, intx*FRACUNIT, inty*FRACUNIT, intz))
if (!P_TeleportMove(p->mo, intx, inty, intz))
CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n"));
else
S_StartSound(p->mo, sfx_mixup);
@ -728,7 +883,7 @@ void Command_Setrings_f(void)
// P_GivePlayerRings does value clamping
players[consoleplayer].rings = 0;
P_GivePlayerRings(&players[consoleplayer], atoi(COM_Argv(1)));
if (!G_IsSpecialStage(gamemap) || !useNightsSS)
if (!G_IsSpecialStage(gamemap) || !(maptol & TOL_NIGHTS))
players[consoleplayer].totalring -= atoi(COM_Argv(1)); //undo totalring addition done in P_GivePlayerRings
G_SetGameModified(multiplayer);
@ -744,9 +899,15 @@ void Command_Setlives_f(void)
if (COM_Argc() > 1)
{
// P_GivePlayerLives does value clamping
players[consoleplayer].lives = 0;
P_GivePlayerLives(&players[consoleplayer], atoi(COM_Argv(1)));
SINT8 lives = atoi(COM_Argv(1));
if (lives == -1)
players[consoleplayer].lives = 0x7f; // infinity!
else
{
// P_GivePlayerLives does value clamping
players[consoleplayer].lives = 0;
P_GivePlayerLives(&players[consoleplayer], atoi(COM_Argv(1)));
}
G_SetGameModified(multiplayer);
}
@ -1010,7 +1171,7 @@ void OP_NightsObjectplace(player_t *player)
mt->options = (UINT16)((player->mo->z - fheight)>>FRACBITS);
mt->angle = (INT16)(mt->angle+(INT16)((FixedInt(FixedDiv(temp*FRACUNIT, 360*(FRACUNIT/256))))<<8));
P_SpawnHoopsAndRings(mt);
P_SpawnHoopsAndRings(mt, false);
}
// This places a bumper!
@ -1024,26 +1185,26 @@ void OP_NightsObjectplace(player_t *player)
P_SpawnMapThing(mt);
}
// This places a ring!
// This places a sphere!
if (cmd->buttons & BT_WEAPONNEXT)
{
player->pflags |= PF_ATTACKDOWN;
if (!OP_HeightOkay(player, false))
return;
mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_RING].doomednum, false);
P_SpawnHoopsAndRings(mt);
mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_BLUESPHERE].doomednum, false);
P_SpawnHoopsAndRings(mt, false);
}
// This places a wing item!
// This places a ring!
if (cmd->buttons & BT_WEAPONPREV)
{
player->pflags |= PF_ATTACKDOWN;
if (!OP_HeightOkay(player, false))
return;
mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_NIGHTSWING].doomednum, false);
P_SpawnHoopsAndRings(mt);
mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_RING].doomednum, false);
P_SpawnHoopsAndRings(mt, false);
}
// This places a custom object as defined in the console cv_mapthingnum.
@ -1077,12 +1238,12 @@ void OP_NightsObjectplace(player_t *player)
if (mt->type == 300 // Ring
|| mt->type == 308 || mt->type == 309 // Team Rings
|| mt->type == 1706 // Nights Wing
|| mt->type == 1706 // Sphere
|| (mt->type >= 600 && mt->type <= 609) // Placement patterns
|| mt->type == 1705 || mt->type == 1713 // NiGHTS Hoops
|| mt->type == 1800) // Mario Coin
{
P_SpawnHoopsAndRings(mt);
P_SpawnHoopsAndRings(mt, false);
}
else
P_SpawnMapThing(mt);
@ -1227,7 +1388,7 @@ void OP_ObjectplaceMovement(player_t *player)
|| mt->type == 1705 || mt->type == 1713 // NiGHTS Hoops
|| mt->type == 1800) // Mario Coin
{
P_SpawnHoopsAndRings(mt);
P_SpawnHoopsAndRings(mt, false);
}
else
P_SpawnMapThing(mt);

View file

@ -33,7 +33,9 @@
*/
fixed_t FixedMul(fixed_t a, fixed_t b)
{
return (fixed_t)((((INT64)a * b) ) / FRACUNIT);
// Need to cast to unsigned before shifting to avoid undefined behaviour
// for negative integers
return (fixed_t)(((UINT64)((INT64)a * b)) >> FRACBITS);
}
#endif //__USE_C_FIXEDMUL__

View file

@ -458,7 +458,7 @@ consvar_t cv_ghost_guest = {"ghost_guest", "Show", CV_SAVE, ghost2_cons_
static CV_PossibleValue_t dummyteam_cons_t[] = {{0, "Spectator"}, {1, "Red"}, {2, "Blue"}, {0, NULL}};
static CV_PossibleValue_t dummyscramble_cons_t[] = {{0, "Random"}, {1, "Points"}, {0, NULL}};
static CV_PossibleValue_t ringlimit_cons_t[] = {{0, "MIN"}, {9999, "MAX"}, {0, NULL}};
static CV_PossibleValue_t liveslimit_cons_t[] = {{0, "MIN"}, {99, "MAX"}, {0, NULL}};
static CV_PossibleValue_t liveslimit_cons_t[] = {{-1, "MIN"}, {99, "MAX"}, {0, NULL}};
static CV_PossibleValue_t dummymares_cons_t[] = {
{-1, "END"}, {0,"Overall"}, {1,"Mare 1"}, {2,"Mare 2"}, {3,"Mare 3"}, {4,"Mare 4"}, {5,"Mare 5"}, {6,"Mare 6"}, {7,"Mare 7"}, {8,"Mare 8"}, {0,NULL}
};
@ -4938,6 +4938,7 @@ static void M_DrawAddons(void)
{
INT32 x, y;
ssize_t i, max;
const char* topstr;
// hack - need to refresh at end of frame to handle addfile...
if (refreshdirmenu & M_AddonsRefresh())
@ -4949,9 +4950,16 @@ static void M_DrawAddons(void)
if (addonsresponselimit)
addonsresponselimit--;
V_DrawCenteredString(BASEVIDWIDTH/2, 4+offs, 0, (Playing()
? "\x85""Adding files mid-game may cause problems."
: LOCATIONSTRING));
if (Playing())
topstr = "\x85""Adding files mid-game may cause problems.";
else if (savemoddata)
topstr = "\x83""Add-on has its own data, saving enabled.";
else if (modifiedgame)
topstr = "\x87""Game is modified, saving is disabled.";
else
topstr = LOCATIONSTRING;
V_DrawCenteredString(BASEVIDWIDTH/2, 4+offs, 0, topstr);
if (numwadfiles <= mainwads+1)
y = 0;
@ -5222,7 +5230,7 @@ static void M_HandleAddons(INT32 choice)
case EXT_SOC:
case EXT_WAD:
case EXT_PK3:
COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
COM_BufAddText(va("addfile \"%s%s\"", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
addonsresponselimit = 5;
break;
default:
@ -5266,7 +5274,10 @@ static void M_PandorasBox(INT32 choice)
{
(void)choice;
CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].rings, 0));
CV_StealthSetValue(&cv_dummylives, players[consoleplayer].lives);
if (players[consoleplayer].lives == 0x7f)
CV_StealthSetValue(&cv_dummylives, -1);
else
CV_StealthSetValue(&cv_dummylives, players[consoleplayer].lives);
CV_StealthSetValue(&cv_dummycontinues, players[consoleplayer].continues);
SR_PandorasBox[6].status = ((players[consoleplayer].charflags & SF_SUPER)
#ifndef DEVELOP
@ -8441,6 +8452,13 @@ Update the maxplayers label...
static void M_ConnectIP(INT32 choice)
{
(void)choice;
if (*setupm_ip == 0)
{
M_StartMessage("You must specify an IP address.\n", NULL, MM_NOTHING);
return;
}
COM_BufAddText(va("connect \"%s\"\n", setupm_ip));
// A little "please wait" message.
@ -8822,7 +8840,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
break;
S_StartSound(NULL,sfx_menu1); // Tails
l = strlen(setupm_name);
if (l < MAXPLAYERNAME-1)
if (l < MAXPLAYERNAME)
{
setupm_name[l] = (char)choice;
setupm_name[l+1] = 0;

View file

@ -56,7 +56,9 @@ typedef off_t off64_t;
#endif
#endif
#if defined (_WIN32)
#if defined(__MINGW32__) && ((__GNUC__ > 7) || (__GNUC__ == 6 && __GNUC_MINOR__ >= 3))
#define PRIdS "u"
#elif defined (_WIN32)
#define PRIdS "Iu"
#elif defined (DJGPP)
#define PRIdS "u"

File diff suppressed because it is too large Load diff

View file

@ -2144,6 +2144,7 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
boolean floortouch = false;
fixed_t bottomheight, topheight;
msecnode_t *node;
ffloor_t *rover;
for (i = 0; i < MAXPLAYERS; i++)
{
@ -2191,6 +2192,19 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
{
targetsec = &sectors[targetsecnum];
// Find the FOF corresponding to the control linedef
for (rover = targetsec->ffloors; rover; rover = rover->next)
{
if (rover->master == sec->lines[i])
break;
}
if (!rover) // This should be impossible, but don't complain if it is the case somehow
continue;
if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there
continue;
for (j = 0; j < MAXPLAYERS; j++)
{
if (!playeringame[j])
@ -3304,7 +3318,7 @@ INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
P_SetThingPosition(thing);
if (thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, puncher, puncher, 1, 0);
else if (thing->type == MT_RING || thing->type == MT_COIN)
else if (thing->type == MT_RING || thing->type == MT_COIN || thing->type == MT_TOKEN)
{
thing->momz = FixedMul(3*FRACUNIT, thing->scale);
P_TouchSpecialThing(thing, puncher, false);

File diff suppressed because it is too large Load diff

View file

@ -146,6 +146,7 @@ void P_SpawnShieldOrb(player_t *player);
void P_SwitchShield(player_t *player, UINT16 shieldtype);
mobj_t *P_SpawnGhostMobj(mobj_t *mobj);
void P_GivePlayerRings(player_t *player, INT32 num_rings);
void P_GivePlayerSpheres(player_t *player, INT32 num_spheres);
void P_GivePlayerLives(player_t *player, INT32 numlives);
void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound);
UINT8 P_GetNextEmerald(void);
@ -256,6 +257,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover);
boolean P_CheckDeathPitCollide(mobj_t *mo);
boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover);
void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype);
mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type);
@ -280,6 +282,8 @@ mobj_t *P_GetClosestAxis(mobj_t *source);
boolean P_CanRunOnWater(player_t *player, ffloor_t *rover);
void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot);
void P_FlashPal(player_t *pl, UINT16 type, UINT16 duration);
#define PAL_WHITE 1
#define PAL_MIXUP 2
@ -360,7 +364,7 @@ void P_DelPrecipSeclist(mprecipsecnode_t *node);
void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y);
void P_Initsecnode(void);
void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist);
void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype);
fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height);
boolean PIT_PushableMoved(mobj_t *thing);
@ -410,6 +414,8 @@ typedef struct BasicFF_s
#define DMG_DEATHPIT 0x80+3
#define DMG_CRUSHED 0x80+4
#define DMG_SPECTATOR 0x80+5
// Masks
#define DMG_CANHURTSELF 0x40 // Flag - can hurt self/team indirectly, such as through mines
#define DMG_DEATHMASK DMG_INSTAKILL // if bit 7 is set, this is a death type instead of a damage type
void P_ForceFeed(const player_t *player, INT32 attack, INT32 fade, tic_t duration, INT32 period);

View file

@ -109,21 +109,148 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
// MOVEMENT ITERATOR FUNCTIONS
// =========================================================================
// P_DoSpring
//
// MF_SPRING does some weird, mildly hacky stuff sometimes.
// mass = vertical speed
// damage = horizontal speed
// raisestate = state to change spring to on collision
// reactiontime = number of times it can give 10 points (0 is standard)
// painchance = spring mode:
// 0 = standard vanilla spring behaviour
// Positive spring modes are minor variants of vanilla spring behaviour.
// 1 = launch players in jump
// 2 = don't modify player at all, just add momentum
// Negative spring modes are mildly-related gimmicks with customisation.
// -1 = pinball bumper
// Any other spring mode defaults to standard vanilla spring behaviour,
// ****** but forward compatibility is not guaranteed for these. ******
//
boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{
INT32 pflags;
fixed_t offx, offy;
fixed_t vertispeed = spring->info->mass;
fixed_t horizspeed = spring->info->damage;
UINT8 secondjump;
boolean final;
if (object->eflags & MFE_SPRUNG) // Object was already sprung this tic
// Object was already sprung this tic
if (object->eflags & MFE_SPRUNG)
return false;
// Spectators don't trigger springs.
if (object->player && object->player->spectator)
return false;
// "Even in Death" is a song from Volume 8, not a command.
if (!spring->health || !object->health)
return false;
if (spring->info->painchance == -1) // Pinball bumper mode.
{
// The first of the entirely different spring modes!
// Some of the attributes mean different things here.
// mass = default strength (can be controlled by mapthing's spawnangle)
// damage = unused
angle_t horizangle, vertiangle;
if (!vertispeed)
return false;
if (object->player && object->player->homing) // Sonic Heroes and Shadow the Hedgehog are the only games to contain homing-attackable bumpers!
{
horizangle = 0;
vertiangle = ((object->eflags & MFE_VERTICALFLIP) ? ANGLE_270 : ANGLE_90) >> ANGLETOFINESHIFT;
object->player->pflags &= ~PF_THOKKED;
if (spring->eflags & MFE_VERTICALFLIP)
object->z = spring->z - object->height - 1;
else
object->z = spring->z + spring->height + 1;
}
else
{
horizangle = R_PointToAngle2(spring->x, spring->y, object->x, object->y);
vertiangle = (R_PointToAngle2(
0,
spring->z + spring->height/2,
FixedHypot(object->x - spring->x, object->y - spring->y),
object->z + object->height/2)
>> ANGLETOFINESHIFT) & FINEMASK;
}
if (spring->spawnpoint && spring->spawnpoint->angle > 0)
vertispeed = (spring->spawnpoint->angle<<(FRACBITS-1))/5;
vertispeed = FixedMul(vertispeed, FixedMul(object->scale, spring->scale));
if (object->player)
{
fixed_t playervelocity;
if (!(object->player->pflags & PF_THOKKED) && !(object->player->homing)
&& ((playervelocity = FixedDiv(9*FixedHypot(object->player->speed, object->momz), 10<<FRACBITS)) > vertispeed))
vertispeed = playervelocity;
if (object->player->powers[pw_carry] == CR_NIGHTSMODE) // THIS has NiGHTS support, at least...
{
angle_t nightsangle = 0;
if (object->player->bumpertime >= TICRATE/4)
return false;
if ((object->player->pflags & PF_TRANSFERTOCLOSEST) && object->player->axis1 && object->player->axis2)
{
nightsangle = R_PointToAngle2(object->player->axis1->x, object->player->axis1->y, object->player->axis2->x, object->player->axis2->y);
nightsangle += ANGLE_90;
}
else if (object->target)
{
if (object->target->flags2 & MF2_AMBUSH)
nightsangle = R_PointToAngle2(object->target->x, object->target->y, object->x, object->y);
else
nightsangle = R_PointToAngle2(object->x, object->y, object->target->x, object->target->y);
}
object->player->flyangle = AngleFixed(R_PointToAngle2(
0,
spring->z + spring->height/2,
FixedMul(
FINESINE(((nightsangle - horizangle) >> ANGLETOFINESHIFT) & FINEMASK),
FixedHypot(object->x - spring->x, object->y - spring->y)),
object->z + object->height/2))>>FRACBITS;
object->player->bumpertime = TICRATE/2;
}
else
{
INT32 pflags = object->player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING); // Not identical to below...
UINT8 secondjump = object->player->secondjump;
if (object->player->pflags & PF_GLIDING)
P_SetPlayerMobjState(object, S_PLAY_FALL);
P_ResetPlayer(object->player);
object->player->pflags |= pflags;
object->player->secondjump = secondjump;
}
}
if (!P_IsObjectOnGround(object)) // prevents uncurling when spinning due to "landing"
object->momz = FixedMul(vertispeed, FINESINE(vertiangle));
P_InstaThrust(object, horizangle, FixedMul(vertispeed, FINECOSINE(vertiangle)));
object->eflags |= MFE_SPRUNG; // apply this flag asap!
goto springstate;
}
// Does nothing?
if (!vertispeed && !horizspeed)
return false;
#ifdef ESLOPE
object->standingslope = NULL; // Okay, now we know it's not going to be relevant - no launching off at silly angles for you.
#endif
if (spring->eflags & MFE_VERTICALFLIP)
vertispeed *= -1;
if (object->player && (object->player->powers[pw_carry] == CR_NIGHTSMODE))
{
/*Someone want to make these work like bumpers?*/
@ -135,48 +262,51 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|| (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2)))
{
S_StartSound(object, sfx_s3k8b);
horizspeed = FixedMul(horizspeed, (4*FRACUNIT)/3);
vertispeed = FixedMul(vertispeed, (6*FRACUNIT)/5); // aprox square root of above
if (horizspeed)
horizspeed = FixedMul(horizspeed, (4*FRACUNIT)/3);
if (vertispeed)
vertispeed = FixedMul(vertispeed, (6*FRACUNIT)/5); // aprox square root of above
}
object->eflags |= MFE_SPRUNG; // apply this flag asap!
spring->flags &= ~(MF_SOLID|MF_SPECIAL); // De-solidify
spring->flags &= ~(MF_SPRING|MF_SPECIAL); // De-solidify
if ((horizspeed && vertispeed) || (object->player && object->player->homing)) // Mimic SA
if (spring->info->painchance != 2)
{
object->momx = object->momy = 0;
P_TryMove(object, spring->x, spring->y, true);
}
if ((horizspeed && vertispeed) || (object->player && object->player->homing)) // Mimic SA
{
object->momx = object->momy = 0;
P_TryMove(object, spring->x, spring->y, true);
}
if (spring->eflags & MFE_VERTICALFLIP)
vertispeed *= -1;
if (vertispeed > 0)
object->z = spring->z + spring->height + 1;
else if (vertispeed < 0)
object->z = spring->z - object->height - 1;
else
{
fixed_t offx, offy;
// Horizontal springs teleport you in FRONT of them.
object->momx = object->momy = 0;
if (vertispeed > 0)
object->z = spring->z + spring->height + 1;
else if (vertispeed < 0)
object->z = spring->z - object->height - 1;
else
{
// Horizontal springs teleport you in FRONT of them.
object->momx = object->momy = 0;
// Overestimate the distance to position you at
offx = P_ReturnThrustX(spring, spring->angle, (spring->radius + object->radius + 1) * 2);
offy = P_ReturnThrustY(spring, spring->angle, (spring->radius + object->radius + 1) * 2);
// Overestimate the distance to position you at
offx = P_ReturnThrustX(spring, spring->angle, (spring->radius + object->radius + 1) * 2);
offy = P_ReturnThrustY(spring, spring->angle, (spring->radius + object->radius + 1) * 2);
// Make it square by clipping
if (offx > (spring->radius + object->radius + 1))
offx = spring->radius + object->radius + 1;
else if (offx < -(spring->radius + object->radius + 1))
offx = -(spring->radius + object->radius + 1);
// Make it square by clipping
if (offx > (spring->radius + object->radius + 1))
offx = spring->radius + object->radius + 1;
else if (offx < -(spring->radius + object->radius + 1))
offx = -(spring->radius + object->radius + 1);
if (offy > (spring->radius + object->radius + 1))
offy = spring->radius + object->radius + 1;
else if (offy < -(spring->radius + object->radius + 1))
offy = -(spring->radius + object->radius + 1);
if (offy > (spring->radius + object->radius + 1))
offy = spring->radius + object->radius + 1;
else if (offy < -(spring->radius + object->radius + 1))
offy = -(spring->radius + object->radius + 1);
// Set position!
P_TryMove(object, spring->x + offx, spring->y + offy, true);
// Set position!
P_TryMove(object, spring->x + offx, spring->y + offy, true);
}
}
if (vertispeed)
@ -186,12 +316,14 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
P_InstaThrustEvenIn2D(object, spring->angle, FixedMul(horizspeed,FixedSqrt(FixedMul(object->scale, spring->scale))));
// Re-solidify
spring->flags |= (spring->info->flags & (MF_SPECIAL|MF_SOLID));
P_SetMobjState(spring, spring->info->raisestate);
spring->flags |= (spring->info->flags & (MF_SPRING|MF_SPECIAL));
if (object->player)
{
INT32 pflags;
UINT8 secondjump;
boolean washoming;
if (spring->flags & MF_ENEMY) // Spring shells
P_SetTarget(&spring->target, object);
@ -212,19 +344,28 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
}
}
pflags = object->player->pflags & (PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_SHIELDABILITY|PF_BOUNCING); // I still need these.
pflags = object->player->pflags & (PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_BOUNCING); // I still need these.
secondjump = object->player->secondjump;
washoming = object->player->homing;
if (object->player->pflags & PF_GLIDING)
P_SetPlayerMobjState(object, S_PLAY_FALL);
P_ResetPlayer(object->player);
if (spring->info->painchance)
if (spring->info->painchance == 1) // For all those ancient, SOC'd abilities.
{
object->player->pflags |= P_GetJumpFlags(object->player);
P_SetPlayerMobjState(object, S_PLAY_JUMP);
}
else if (!vertispeed || (pflags & PF_BOUNCING)) // horizontal spring or bouncing
else if ((spring->info->painchance == 2) || (pflags & PF_BOUNCING)) // Adding momentum only.
{
if ((pflags & PF_BOUNCING)
|| (pflags & (PF_JUMPED|PF_SPINNING) && (object->player->panim == PA_ROLL || object->player->panim == PA_JUMP || object->player->panim == PA_FALL)))
object->player->pflags |= (pflags &~ PF_STARTJUMP);
object->player->secondjump = secondjump;
if (washoming)
object->player->pflags &= ~PF_THOKKED;
}
else if (!vertispeed)
{
if (pflags & (PF_JUMPED|PF_SPINNING))
{
object->player->pflags |= pflags;
object->player->secondjump = secondjump;
@ -239,10 +380,25 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
}
#ifdef ESLOPE
object->standingslope = NULL; // Okay, now we know it's not going to be relevant - no launching off at silly angles for you.
object->standingslope = NULL; // And again.
#endif
return true;
final = true;
springstate:
if ((statenum_t)(spring->state-states) < spring->info->raisestate)
{
P_SetMobjState(spring, spring->info->raisestate);
if (object->player && spring->reactiontime && !(spring->info->flags & MF_ENEMY))
{
if (object->player->powers[pw_carry] != CR_NIGHTSMODE) // don't make graphic in NiGHTS
P_SetMobjState(P_SpawnMobj(spring->x, spring->y, spring->z + (spring->height/2), MT_SCORE), mobjinfo[MT_SCORE].spawnstate+11);
P_AddPlayerScore(object->player, 10);
spring->reactiontime--;
}
}
return final;
}
static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
@ -398,7 +554,6 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails)
static boolean PIT_CheckThing(mobj_t *thing)
{
fixed_t blockdist;
boolean iwassprung = false;
// don't clip against self
if (thing == tmthing)
@ -514,7 +669,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true;
}
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE)))
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING)))
return true;
// Don't collide with your buddies while NiGHTS-flying.
@ -622,6 +777,54 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
#endif
// Billiards mines!
if (thing->type == MT_BIGMINE)
{
if (tmthing->type == MT_BIGMINE)
{
if (!tmthing->momx && !tmthing->momy)
return true;
if ((statenum_t)(thing->state-states) >= thing->info->meleestate)
return true;
if (thing->z > tmthing->z + tmthing->height)
return true; // overhead
if (thing->z + thing->height < tmthing->z)
return true; // underneath
thing->momx = tmthing->momx/3;
thing->momy = tmthing->momy/3;
thing->momz = tmthing->momz/3;
tmthing->momx /= -8;
tmthing->momy /= -8;
tmthing->momz /= -8;
if (thing->info->activesound)
S_StartSound(thing, thing->info->activesound);
P_SetMobjState(thing, thing->info->meleestate);
P_SetTarget(&thing->tracer, tmthing->tracer);
return true;
}
else if (tmthing->type == MT_CRUSHCLAW)
{
if (tmthing->extravalue1 <= 0)
return true;
if ((statenum_t)(thing->state-states) >= thing->info->meleestate)
return true;
if (thing->z > tmthing->z + tmthing->height)
return true; // overhead
if (thing->z + thing->height < tmthing->z)
return true; // underneath
thing->momx = P_ReturnThrustX(tmthing, tmthing->angle, 2*tmthing->extravalue1*tmthing->scale/3);
thing->momy = P_ReturnThrustY(tmthing, tmthing->angle, 2*tmthing->extravalue1*tmthing->scale/3);
if (thing->info->activesound)
S_StartSound(thing, thing->info->activesound);
P_SetMobjState(thing, thing->info->meleestate);
if (tmthing->tracer)
P_SetTarget(&thing->tracer, tmthing->tracer->target);
return false;
}
}
// When solid spikes move, assume they just popped up and teleport things on top of them to hurt.
if (tmthing->type == MT_SPIKE && tmthing->flags & MF_SOLID)
{
@ -639,35 +842,37 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true;
}
if (thing->flags & MF_PAIN)
if (thing->flags & MF_PAIN && tmthing->player)
{ // Player touches painful thing sitting on the floor
// see if it went over / under
if (thing->z > tmthing->z + tmthing->height)
return true; // overhead
if (thing->z + thing->height < tmthing->z)
return true; // underneath
if (tmthing->player && tmthing->flags & MF_SHOOTABLE && thing->health > 0)
if (tmthing->flags & MF_SHOOTABLE && thing->health > 0)
{
UINT8 damagetype = 0;
if (thing->flags & MF_FIRE) // BURN!
UINT8 damagetype = (thing->info->mass & 0xFF);
if (!damagetype && thing->flags & MF_FIRE) // BURN!
damagetype = DMG_FIRE;
P_DamageMobj(tmthing, thing, thing, 1, damagetype);
if (P_DamageMobj(tmthing, thing, thing, 1, damagetype) && (damagetype = (thing->info->mass>>8)))
S_StartSound(thing, damagetype);
}
return true;
}
else if (tmthing->flags & MF_PAIN)
else if (tmthing->flags & MF_PAIN && thing->player)
{ // Painful thing splats player in the face
// see if it went over / under
if (tmthing->z > thing->z + thing->height)
return true; // overhead
if (tmthing->z + tmthing->height < thing->z)
return true; // underneath
if (thing->player && thing->flags & MF_SHOOTABLE && tmthing->health > 0)
if (thing->flags & MF_SHOOTABLE && tmthing->health > 0)
{
UINT8 damagetype = 0;
if (tmthing->flags & MF_FIRE) // BURN!
UINT8 damagetype = (tmthing->info->mass & 0xFF);
if (!damagetype && tmthing->flags & MF_FIRE) // BURN!
damagetype = DMG_FIRE;
P_DamageMobj(thing, tmthing, tmthing, 1, damagetype);
if (P_DamageMobj(thing, tmthing, tmthing, 1, damagetype) && (damagetype = (tmthing->info->mass>>8)))
S_StartSound(tmthing, damagetype);
}
return true;
}
@ -714,6 +919,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
else if (tmz > thzh - sprarea && tmz < thzh) // Don't damage people springing up / down
return true;
}
// missiles can hit other things
if (tmthing->flags & MF_MISSILE || tmthing->type == MT_SHELL)
{
@ -768,30 +974,11 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_EGGSHIELD)
{
fixed_t touchx, touchy;
angle_t angle;
angle_t angle = (R_PointToAngle2(thing->x, thing->y, tmthing->x - tmthing->momx, tmthing->y - tmthing->momy) - thing->angle) - ANGLE_90;
if (P_AproxDistance(tmthing->x-thing->x, tmthing->y-thing->y) >
P_AproxDistance((tmthing->x-tmthing->momx)-thing->x, (tmthing->y-tmthing->momy)-thing->y))
{
touchx = tmthing->x + tmthing->momx;
touchy = tmthing->y + tmthing->momy;
}
else
{
touchx = tmthing->x;
touchy = tmthing->y;
}
angle = R_PointToAngle2(thing->x, thing->y, touchx, touchy) - thing->angle;
if (!(angle > ANGLE_90 && angle < ANGLE_270)) // hit front of shield, didn't destroy it
return false;
else // hit shield from behind, shield is destroyed!
{
if (angle < ANGLE_180) // hit shield from behind, shield is destroyed!
P_KillMobj(thing, tmthing, tmthing, 0);
return false;
}
return false;
}
// damage / explode
@ -835,7 +1022,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
P_SetThingPosition(tmthing);
}
else if (!(tmthing->type == MT_SHELL && thing->player)) // player collision handled in touchspecial
P_DamageMobj(thing, tmthing, tmthing->target, 1, 0);
{
UINT8 damagetype = tmthing->info->mass;
if (!damagetype && tmthing->flags & MF_FIRE) // BURN!
damagetype = DMG_FIRE;
P_DamageMobj(thing, tmthing, tmthing->target, 1, damagetype);
}
// don't traverse any more
@ -1037,15 +1229,28 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (tmthing->flags & MF_PUSHABLE)
{
if (thing->type == MT_FAN || thing->type == MT_STEAM)
{
P_DoFanAndGasJet(thing, tmthing);
return true;
}
else if (thing->flags & MF_SPRING)
{
if ( thing->z <= tmthing->z + tmthing->height
&& tmthing->z <= thing->z + thing->height)
iwassprung = P_DoSpring(thing, tmthing);
if (P_DoSpring(thing, tmthing))
return false;
return true;
}
}
// thanks to sal for solidenemies dot lua
if (thing->flags & (MF_ENEMY|MF_BOSS) && tmthing->flags & (MF_ENEMY|MF_BOSS))
{
if ((thing->z + thing->height >= tmthing->z)
&& (tmthing->z + tmthing->height >= thing->z))
return false;
}
// Damage other players when invincible
if (tmthing->player && thing->player
// Make sure they aren't able to damage you ANYWHERE along the Z axis, you have to be TOUCHING the person.
@ -1110,7 +1315,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
{
// Objects kill you if it falls from above.
if (thing != tmthing->target)
P_DamageMobj(thing, tmthing, tmthing->target, 1, DMG_INSTAKILL);
P_DamageMobj(thing, tmthing, tmthing->target, 1, DMG_CRUSHED);
tmthing->momz = -tmthing->momz/2; // Bounce, just for fun!
// The tmthing->target allows the pusher of the object
@ -1133,75 +1338,62 @@ static boolean PIT_CheckThing(mobj_t *thing)
{
if ( thing->z <= tmthing->z + tmthing->height
&& tmthing->z <= thing->z + thing->height)
iwassprung = P_DoSpring(thing, tmthing);
if (P_DoSpring(thing, tmthing))
return false;
return true;
}
// Are you touching the side of the object you're interacting with?
else if (thing->z - FixedMul(FRACUNIT, thing->scale) <= tmthing->z + tmthing->height
&& thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) >= tmthing->z)
// Monitor?
else if (thing->flags & MF_MONITOR
&& !((thing->type == MT_RING_REDBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_RING_BLUEBOX && tmthing->player->ctfteam != 2)))
{
// 0 = none, 1 = elemental pierce, 2 = bubble bounce
UINT8 elementalpierce = (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY)
? (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2)
: 0);
if (thing->flags & MF_MONITOR
&& (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING)
|| ((tmthing->player->pflags & PF_JUMPED)
&& (!(tmthing->player->pflags & PF_NOJUMPDAMAGE)
|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
|| ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING)
&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))
|| elementalpierce))
if (!(thing->flags & MF_SOLID)
|| tmthing->player->pflags & (PF_SPINNING|PF_GLIDING)
|| ((tmthing->player->pflags & PF_JUMPED)
&& (!(tmthing->player->pflags & PF_NOJUMPDAMAGE)
|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
|| ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING)
&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))
|| elementalpierce)
{
player_t *player = tmthing->player;
SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed.
fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;;
fixed_t *z = &tmthing->z; // aau.
P_DamageMobj(thing, tmthing, tmthing, 1, 0); // break the monitor
// Going down? Then bounce back up.
if ((P_MobjWasRemoved(thing) // Monitor was removed
|| !thing->health) // or otherwise popped
&& (flipval*(*momz) < 0) // monitor is on the floor and you're going down, or on the ceiling and you're going up
&& (elementalpierce != 1)) // you're not piercing through the monitor...
if (thing->z - thing->scale <= tmthing->z + tmthing->height
&& thing->z + thing->height + thing->scale >= tmthing->z)
{
if (elementalpierce == 2)
P_DoBubbleBounce(player);
else if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))
*momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically.
player_t *player = tmthing->player;
SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed.
fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;;
fixed_t *z = &tmthing->z; // aau.
// Going down? Then bounce back up.
if (P_DamageMobj(thing, tmthing, tmthing, 1, 0) // break the monitor
&& (flipval*(*momz) < 0) // monitor is on the floor and you're going down, or on the ceiling and you're going up
&& (elementalpierce != 1)) // you're not piercing through the monitor...
{
if (elementalpierce == 2)
P_DoBubbleBounce(player);
else if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))
*momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically.
}
if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough.
{
if (player->pflags & PF_BOUNCING)
P_DoAbilityBounce(player, false);
return false;
}
else
*z -= *momz; // to ensure proper collision.
}
if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough.
{
if (player->pflags & PF_BOUNCING)
P_DoAbilityBounce(player, false);
return false;
}
else
*z -= *momz; // to ensure proper collision.
return true;
}
}
}
if (!(tmthing->player) && (thing->player))
if ((!tmthing->player) && (thing->player))
; // no solid thing should ever be able to step up onto a player
else if (thing->flags & MF_SPRING && (tmthing->player || tmthing->flags & MF_PUSHABLE))
{
if (iwassprung) // this spring caused you to gain MFE_SPRUNG just now...
return false; // "cancel" P_TryMove via blocking so you keep your current position
}
else if (tmthing->flags & MF_SPRING && (thing->flags & MF_PUSHABLE))
; // Fix a few nasty spring-jumping bugs that happen sometimes.
// Monitors are not treated as solid to players who are jumping, spinning or gliding,
// unless it's a CTF team monitor and you're on the wrong team
else if (thing->flags & MF_MONITOR && tmthing->player
&& (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING)
|| ((tmthing->player->pflags & PF_JUMPED)
&& (!(tmthing->player->pflags & PF_NOJUMPDAMAGE)
|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
|| ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING)
&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0)))
&& !((thing->type == MT_RING_REDBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_RING_BLUEBOX && tmthing->player->ctfteam != 2)))
;
// z checking at last
// Treat noclip things as non-solid!
else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID
@ -1228,16 +1420,14 @@ static boolean PIT_CheckThing(mobj_t *thing)
topz = thing->z - thing->scale; // FixedMul(FRACUNIT, thing->scale), but thing->scale == FRACUNIT in base scale anyways
if (thing->flags & MF_SPRING)
;
// block only when jumping not high enough,
// (dont climb max. 24units while already in air)
// since return false doesn't handle momentum properly,
// we lie to P_TryMove() so it's always too high
else if (tmthing->player && tmthing->z + tmthing->height > topz
if (tmthing->player && tmthing->z + tmthing->height > topz
&& tmthing->z + tmthing->height < tmthing->ceilingz)
{
if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->flags2 & MF2_STANDONME)) // Gold monitor hack...
if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->info->flags & MF_MONITOR)) // Gold monitor hack...
return false;
tmfloorz = tmceilingz = topz; // block while in air
@ -1274,16 +1464,14 @@ static boolean PIT_CheckThing(mobj_t *thing)
topz = thing->z + thing->height + thing->scale; // FixedMul(FRACUNIT, thing->scale), but thing->scale == FRACUNIT in base scale anyways
if (thing->flags & MF_SPRING)
;
// block only when jumping not high enough,
// (dont climb max. 24units while already in air)
// since return false doesn't handle momentum properly,
// we lie to P_TryMove() so it's always too high
else if (tmthing->player && tmthing->z < topz
if (tmthing->player && tmthing->z < topz
&& tmthing->z > tmthing->floorz)
{
if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->flags2 & MF2_STANDONME)) // Gold monitor hack...
if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->info->flags & MF_MONITOR)) // Gold monitor hack...
return false;
tmfloorz = tmceilingz = topz; // block while in air
@ -3505,6 +3693,7 @@ bounceback:
static fixed_t bombdamage;
static mobj_t *bombsource;
static mobj_t *bombspot;
static UINT8 bombdamagetype;
//
// PIT_RadiusAttack
@ -3515,17 +3704,13 @@ static boolean PIT_RadiusAttack(mobj_t *thing)
{
fixed_t dx, dy, dz, dist;
if (thing == bombspot // ignore the bomb itself (Deton fix)
|| (bombsource && thing->type == bombsource->type)) // ignore the type of guys who dropped the bomb (Jetty-Syn Bomber or Skim can bomb eachother, but not themselves.)
if (thing == bombspot) // ignore the bomb itself (Deton fix)
return true;
if (!(thing->flags & MF_SHOOTABLE))
if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) != MF_SHOOTABLE)
return true;
if (thing->flags & MF_BOSS)
return true;
if (thing->flags & MF_MONITOR)
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;
dx = abs(thing->x - bombspot->x);
@ -3549,7 +3734,7 @@ static boolean PIT_RadiusAttack(mobj_t *thing)
if (P_CheckSight(thing, bombspot))
{ // must be in direct path
P_DamageMobj(thing, bombspot, bombsource, 1, 0); // Tails 01-11-2001
P_DamageMobj(thing, bombspot, bombsource, 1, bombdamagetype); // Tails 01-11-2001
}
return true;
@ -3559,7 +3744,7 @@ static boolean PIT_RadiusAttack(mobj_t *thing)
// P_RadiusAttack
// Source is the creature that caused the explosion at spot.
//
void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist)
void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype)
{
INT32 x, y;
INT32 xl, xh, yl, yh;
@ -3576,6 +3761,7 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist)
bombspot = spot;
bombsource = source;
bombdamage = FixedMul(damagedist, spot->scale);
bombdamagetype = damagetype;
for (y = yl; y <= yh; y++)
for (x = xl; x <= xh; x++)

File diff suppressed because it is too large Load diff

View file

@ -175,8 +175,8 @@ typedef enum
MF2_SCATTER = 1<<8, // Thrown ring has scatter properties
MF2_BEYONDTHEGRAVE = 1<<9, // Source of this missile has died and has since respawned.
MF2_SLIDEPUSH = 1<<10, // MF_PUSHABLE that pushes continuously.
MF2_CLASSICPUSH = 1<<11, // Drops straight down when object has negative Z.
MF2_STANDONME = 1<<12, // While not pushable, stand on me anyway.
MF2_CLASSICPUSH = 1<<11, // Drops straight down when object has negative momz.
MF2_INVERTAIMABLE = 1<<12, // Flips whether it's targetable by A_LookForEnemies (enemies no, decoys yes)
MF2_INFLOAT = 1<<13, // Floating to a height for a move, don't auto float to target's height.
MF2_DEBRIS = 1<<14, // Splash ring from explosion ring
MF2_NIGHTSPULL = 1<<15, // Attracted from a paraloop
@ -194,7 +194,6 @@ typedef enum
MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH
MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
MF2_MACEROTATE = 1<<30, // Thinker calls P_MaceRotate around tracer
// free: to and including 1<<31
} mobjflag2_t;
@ -315,7 +314,7 @@ typedef struct mobj_s
mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->type]
INT32 health; // for player this is rings + 1
INT32 health; // for player this is rings + 1 -- no it isn't, not any more!!
// Movement direction, movement generation (zig-zagging).
angle_t movedir; // dirtype_t 0-7; also used by Deton for up/down angle
@ -389,6 +388,7 @@ typedef struct precipmobj_s
angle_t angle; // orientation
spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h
UINT8 sprite2; // player sprites
UINT16 anim_duration; // for FF_ANIMATE states
struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
@ -436,7 +436,7 @@ void P_MovePlayerToStarpost(INT32 playernum);
void P_AfterPlayerSpawn(INT32 playernum);
void P_SpawnMapThing(mapthing_t *mthing);
void P_SpawnHoopsAndRings(mapthing_t *mthing);
void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime);
void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle);
void P_SpawnPrecipitation(void);
void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, statenum_t nstate, angle_t rotangle, boolean spawncenter);

View file

@ -116,7 +116,8 @@ static void P_NetArchivePlayers(void)
WRITEANGLE(save_p, players[i].drawangle);
WRITEANGLE(save_p, players[i].awayviewaiming);
WRITEINT32(save_p, players[i].awayviewtics);
WRITEINT32(save_p, players[i].rings);
WRITEINT16(save_p, players[i].rings);
WRITEINT16(save_p, players[i].spheres);
WRITESINT8(save_p, players[i].pity);
WRITEINT32(save_p, players[i].currentweapon);
@ -203,7 +204,7 @@ static void P_NetArchivePlayers(void)
WRITEUINT32(save_p, players[i].marebegunat);
WRITEUINT32(save_p, players[i].startedtime);
WRITEUINT32(save_p, players[i].finishedtime);
WRITEINT16(save_p, players[i].finishedrings);
WRITEINT16(save_p, players[i].finishedspheres);
WRITEUINT32(save_p, players[i].marescore);
WRITEUINT32(save_p, players[i].lastmarescore);
WRITEUINT8(save_p, players[i].lastmare);
@ -305,7 +306,8 @@ static void P_NetUnArchivePlayers(void)
players[i].drawangle = READANGLE(save_p);
players[i].awayviewaiming = READANGLE(save_p);
players[i].awayviewtics = READINT32(save_p);
players[i].rings = READINT32(save_p);
players[i].rings = READINT16(save_p);
players[i].spheres = READINT16(save_p);
players[i].pity = READSINT8(save_p);
players[i].currentweapon = READINT32(save_p);
@ -392,7 +394,7 @@ static void P_NetUnArchivePlayers(void)
players[i].marebegunat = READUINT32(save_p);
players[i].startedtime = READUINT32(save_p);
players[i].finishedtime = READUINT32(save_p);
players[i].finishedrings = READINT16(save_p);
players[i].finishedspheres = READINT16(save_p);
players[i].marescore = READUINT32(save_p);
players[i].lastmarescore = READUINT32(save_p);
players[i].lastmare = READUINT8(save_p);
@ -1990,7 +1992,7 @@ static void LoadMobjThinker(actionf_p1 thinker)
if (mapthings[spawnpointnum].type == 1705 || mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case
{
P_SpawnHoopsAndRings(&mapthings[spawnpointnum]);
P_SpawnHoopsAndRings(&mapthings[spawnpointnum], false);
return;
}
@ -3265,7 +3267,7 @@ static void P_NetArchiveMisc(void)
WRITEUINT32(save_p, tokenlist);
WRITEUINT32(save_p, leveltime);
WRITEUINT32(save_p, totalrings);
WRITEUINT32(save_p, ssspheres);
WRITEINT16(save_p, lastmap);
WRITEUINT16(save_p, emeralds);
@ -3342,7 +3344,7 @@ static inline boolean P_NetUnArchiveMisc(void)
// get the time
leveltime = READUINT32(save_p);
totalrings = READUINT32(save_p);
ssspheres = READUINT32(save_p);
lastmap = READINT16(save_p);
emeralds = READUINT16(save_p);

View file

@ -808,7 +808,7 @@ void P_ReloadRings(void)
mapthing_t *hoopsToRespawn[4096];
mapthing_t *mt = mapthings;
// scan the thinkers to find rings/wings/hoops to unset
// scan the thinkers to find rings/spheres/hoops to unset
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
@ -826,7 +826,9 @@ void P_ReloadRings(void)
}
continue;
}
if (!(mo->type == MT_RING || mo->type == MT_NIGHTSWING || mo->type == MT_COIN || mo->type == MT_BLUEBALL))
if (!(mo->type == MT_RING || mo->type == MT_COIN
|| mo->type == MT_BLUESPHERE || mo->type == MT_BOMBSPHERE
|| mo->type == MT_NIGHTSCHIP || mo->type == MT_NIGHTSSTAR))
continue;
// Don't auto-disintegrate things being pulled to us
@ -840,9 +842,10 @@ void P_ReloadRings(void)
for (i = 0; i < nummapthings; i++, mt++)
{
// Notice an omission? We handle hoops differently.
if (mt->type == 300 || mt->type == 308 || mt->type == 309
|| mt->type == 1706 || (mt->type >= 600 && mt->type <= 609)
|| mt->type == 1800)
if (mt->type == mobjinfo[MT_RING].doomednum || mt->type == mobjinfo[MT_COIN].doomednum
|| mt->type == mobjinfo[MT_REDTEAMRING].doomednum || mt->type == mobjinfo[MT_BLUETEAMRING].doomednum
|| mt->type == mobjinfo[MT_BLUESPHERE].doomednum || mt->type == mobjinfo[MT_BOMBSPHERE].doomednum
|| (mt->type >= 600 && mt->type <= 609)) // circles and diagonals
{
mt->mobj = NULL;
@ -850,12 +853,45 @@ void P_ReloadRings(void)
mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)
->sector->floorheight>>FRACBITS);
P_SpawnHoopsAndRings (mt);
P_SpawnHoopsAndRings(mt,
#ifdef MANIASPHERES
true);
#else
!G_IsSpecialStage(gamemap)); // prevent flashing spheres in special stages
#endif
}
}
for (i = 0; i < numHoops; i++)
{
P_SpawnHoopsAndRings(hoopsToRespawn[i]);
P_SpawnHoopsAndRings(hoopsToRespawn[i], false);
}
}
void P_SwitchSpheresBonusMode(boolean bonustime)
{
mobj_t *mo;
thinker_t *th;
#ifndef MANIASPHERES
if (G_IsSpecialStage(gamemap)) // prevent flashing spheres in special stages
return;
#endif
// scan the thinkers to find spheres to switch
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo = (mobj_t *)th;
if (mo->type != MT_BLUESPHERE && mo->type != MT_NIGHTSCHIP)
continue;
if (!mo->health)
continue;
P_SetMobjState(mo, ((bonustime) ? mo->info->raisestate : mo->info->spawnstate));
}
}
@ -1025,20 +1061,22 @@ static void P_LoadThings(void)
}
//decrement spawn values to the actual number because zero is valid.
if (emer1)
P_SpawnMobj(huntemeralds[emer1 - 1]->x<<FRACBITS,
huntemeralds[emer1 - 1]->y<<FRACBITS,
huntemeralds[emer1 - 1]->z<<FRACBITS, MT_EMERHUNT);
if (emer1--)
P_SpawnMobj(huntemeralds[emer1]->x<<FRACBITS,
huntemeralds[emer1]->y<<FRACBITS,
huntemeralds[emer1]->z<<FRACBITS, MT_EMERHUNT);
if (emer2)
P_SpawnMobj(huntemeralds[emer2 - 1]->x<<FRACBITS,
huntemeralds[emer2 - 1]->y<<FRACBITS,
huntemeralds[emer2 - 1]->z<<FRACBITS, MT_EMERHUNT);
if (emer2--)
P_SetMobjStateNF(P_SpawnMobj(huntemeralds[emer2]->x<<FRACBITS,
huntemeralds[emer2]->y<<FRACBITS,
huntemeralds[emer2]->z<<FRACBITS, MT_EMERHUNT),
mobjinfo[MT_EMERHUNT].spawnstate+1);
if (emer3)
P_SpawnMobj(huntemeralds[emer3 - 1]->x<<FRACBITS,
huntemeralds[emer3 - 1]->y<<FRACBITS,
huntemeralds[emer3 - 1]->z<<FRACBITS, MT_EMERHUNT);
if (emer3--)
P_SetMobjStateNF(P_SpawnMobj(huntemeralds[emer3]->x<<FRACBITS,
huntemeralds[emer3]->y<<FRACBITS,
huntemeralds[emer3]->z<<FRACBITS, MT_EMERHUNT),
mobjinfo[MT_EMERHUNT].spawnstate+2);
}
if (metalrecording) // Metal Sonic gets no rings to distract him.
@ -1048,9 +1086,11 @@ static void P_LoadThings(void)
mt = mapthings;
for (i = 0; i < nummapthings; i++, mt++)
{
if (mt->type == 300 || mt->type == 308 || mt->type == 309
|| mt->type == 1706 || (mt->type >= 600 && mt->type <= 609)
|| mt->type == 1705 || mt->type == 1713 || mt->type == 1800)
if (mt->type == mobjinfo[MT_RING].doomednum || mt->type == mobjinfo[MT_COIN].doomednum
|| mt->type == mobjinfo[MT_REDTEAMRING].doomednum || mt->type == mobjinfo[MT_BLUETEAMRING].doomednum
|| mt->type == mobjinfo[MT_BLUESPHERE].doomednum || mt->type == mobjinfo[MT_BOMBSPHERE].doomednum
|| (mt->type >= 600 && mt->type <= 609) // circles and diagonals
|| mt->type == 1705 || mt->type == 1713 || mt->type == 1800) // hoops
{
mt->mobj = NULL;
@ -1058,7 +1098,7 @@ static void P_LoadThings(void)
mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)
->sector->floorheight>>FRACBITS);
P_SpawnHoopsAndRings (mt);
P_SpawnHoopsAndRings(mt, false);
}
}
}
@ -2298,7 +2338,7 @@ static void P_LevelInitStuff(void)
// circuit, race and competition stuff
circuitmap = false;
numstarposts = 0;
totalrings = timeinmap = 0;
ssspheres = timeinmap = 0;
// special stage
stagefailed = false;
@ -2320,6 +2360,8 @@ static void P_LevelInitStuff(void)
}
}
countdown = countdown2 = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0))
@ -2328,42 +2370,37 @@ static void P_LevelInitStuff(void)
players[i].lives = cv_startinglives.value;
}
players[i].realtime = countdown = countdown2 = 0;
// obliteration station...
players[i].rings = players[i].spheres =\
players[i].xtralife = players[i].deadtimer =\
players[i].numboxes = players[i].totalring =\
players[i].laps = players[i].aiming =\
players[i].losstime = players[i].timeshit =\
players[i].marescore = players[i].lastmarescore =\
players[i].maxlink = players[i].startedtime =\
players[i].finishedtime = players[i].finishedspheres =\
players[i].lastmare = players[i].marebegunat =\
players[i].textvar = players[i].texttimer =\
players[i].linkcount = players[i].linktimer =\
players[i].flyangle = players[i].anotherflyangle =\
players[i].nightstime = players[i].mare =\
players[i].marelap = players[i].marebonuslap =\
players[i].realtime = players[i].exiting = 0;
// i guess this could be part of the above but i feel mildly uncomfortable implicitly casting
players[i].gotcontinue = false;
players[i].xtralife = players[i].deadtimer = players[i].numboxes = players[i].totalring = players[i].laps = 0;
players[i].rings = 0;
players[i].aiming = 0;
players[i].pflags &= ~PF_GAMETYPEOVER;
players[i].losstime = 0;
players[i].timeshit = 0;
players[i].marescore = players[i].lastmarescore = players[i].maxlink = 0;
players[i].startedtime = players[i].finishedtime = players[i].finishedrings = 0;
players[i].lastmare = players[i].marebegunat = 0;
// Don't show anything
players[i].textvar = players[i].texttimer = 0;
players[i].linkcount = players[i].linktimer = 0;
players[i].flyangle = players[i].anotherflyangle = 0;
players[i].nightstime = players[i].mare = 0;
players[i].marelap = 0; players[i].marebonuslap = 0;
P_SetTarget(&players[i].capsule, NULL);
// aha, the first evidence this shouldn't be a memset!
players[i].drillmeter = 40*20;
players[i].exiting = 0;
P_ResetPlayer(&players[i]);
// hit these too
players[i].pflags &= ~(PF_GAMETYPEOVER|PF_TRANSFERTOCLOSEST);
players[i].mo = NULL;
// we must unset axis details too
players[i].axis1 = players[i].axis2 = NULL;
// and this stupid flag as a result
players[i].pflags &= ~PF_TRANSFERTOCLOSEST;
// unset ALL the pointers. P_SetTarget isn't needed here because if this
// function is being called we're just going to clobber the data anyways
players[i].mo = players[i].followmobj = players[i].awayviewmobj =\
players[i].capsule = players[i].axis1 = players[i].axis2 = NULL;
}
}
@ -2403,7 +2440,17 @@ void P_LoadThingsOnly(void)
P_LevelInitStuff();
P_PrepareThings(lastloadedmaplumpnum + ML_THINGS);
if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3
{ // HACK: Open wad file rather quickly so we can use the things lump
UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC);
filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs);
fileinfo += ML_THINGS; // we only need the THINGS lump
P_PrepareRawThings(wadData + fileinfo->filepos, fileinfo->size);
Z_Free(wadData); // we're done with this now
}
else // phew it's just a WAD
P_PrepareThings(lastloadedmaplumpnum + ML_THINGS);
P_LoadThings();
@ -2676,11 +2723,6 @@ boolean P_SetupLevel(boolean skipprecip)
// Reset the palette
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_SetPaletteColor(0);
else
#endif
if (rendermode != render_none)
V_SetPaletteLump("PLAYPAL");
@ -2738,6 +2780,7 @@ boolean P_SetupLevel(boolean skipprecip)
{
tic_t starttime = I_GetTime();
tic_t endtime = starttime + (3*TICRATE)/2;
tic_t nowtime;
S_StartSound(NULL, sfx_s3kaf);
@ -2747,9 +2790,17 @@ boolean P_SetupLevel(boolean skipprecip)
F_WipeEndScreen();
F_RunWipe(wipedefs[wipe_speclevel_towhite], false);
nowtime = lastwipetic;
// Hold on white for extra effect.
while (I_GetTime() < endtime)
I_Sleep();
while (nowtime < endtime)
{
// wait loop
while (!((nowtime = I_GetTime()) - lastwipetic))
I_Sleep();
lastwipetic = nowtime;
if (moviemode) // make sure we save frames for the white hold too
M_SaveFrame();
}
ranspecialwipe = 1;
}
@ -3337,7 +3388,7 @@ boolean P_AddWadFile(const char *wadfilename)
if ((numlumps = W_InitFile(wadfilename)) == INT16_MAX)
{
refreshdirmenu |= REFRESHDIR_NOTLOADED;
CONS_Printf(M_GetText("Errors occured while loading %s; not added.\n"), wadfilename);
CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename);
return false;
}
else
@ -3351,7 +3402,7 @@ boolean P_AddWadFile(const char *wadfilename)
for (i = 0; i < numlumps; i++, lumpinfo++)
{
// lumpinfo = FindFolder("Lua/", &luaPos, &luaNum, lumpinfo, &numlumps, &i);
// lumpinfo = FindFolder("SOCs/", &socPos, &socNum, lumpinfo, &numlumps, &i);
// lumpinfo = FindFolder("SOC/", &socPos, &socNum, lumpinfo, &numlumps, &i);
lumpinfo = FindFolder("Sounds/", &sfxPos, &sfxNum, lumpinfo, &numlumps, &i);
lumpinfo = FindFolder("Music/", &musPos, &musNum, lumpinfo, &numlumps, &i);
// lumpinfo = FindFolder("Sprites/", &sprPos, &sprNum, lumpinfo, &numlumps, &i);

View file

@ -72,6 +72,7 @@ void P_DeleteFlickies(INT16 i);
// Needed for NiGHTS
void P_ReloadRings(void);
void P_SwitchSpheresBonusMode(boolean bonustime);
void P_DeleteGrades(INT16 i);
void P_AddGradesForMare(INT16 i, UINT8 mare, char *gtext);
UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare);

View file

@ -2868,7 +2868,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
// Unlocked something?
if (M_UpdateUnlockablesAndExtraEmblems())
{
S_StartSound(NULL, sfx_ncitem);
S_StartSound(NULL, sfx_s3k68);
G_SaveGameData(); // only save if unlocked something
}
}
@ -3527,7 +3527,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
if (player->exiting || player->bot) // Don't do anything for bots or players who have just finished
break;
if (!(player->powers[pw_shield] || player->rings > 0)) // Don't do anything if no shield or rings anyway
if (!(player->powers[pw_shield] || player->spheres > 0)) // Don't do anything if no shield or spheres anyway
break;
P_SpecialStageDamage(player, NULL, NULL);
@ -3775,8 +3775,8 @@ DoneSection2:
case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return
if (player->bot)
break;
if (!useNightsSS && G_IsSpecialStage(gamemap) && sstimer > 6)
sstimer = 6; // Just let P_Ticker take care of the rest.
if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6)
player->nightstime = 6; // Just let P_Ticker take care of the rest.
// Exit (for FOF exits; others are handled in P_PlayerThink in p_user.c)
{
@ -4643,7 +4643,7 @@ static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector)
switch(GETSECSPECIAL(sector->special, 4))
{
case 2: // Level Exit / GOAL Sector / Flag Return
if (!useNightsSS && G_IsSpecialStage(gamemap))
if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))
{
// Special stage GOAL sector
// requires touching floor.
@ -5502,7 +5502,7 @@ void P_InitSpecials(void)
// Defaults in case levels don't have them set.
sstimer = 90*TICRATE + 6;
totalrings = 1;
ssspheres = 1;
CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false;
@ -5527,6 +5527,30 @@ void P_InitSpecials(void)
P_InitTagLists(); // Create xref tables for tags
}
static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs)
{
if (!(master->flags & ML_NOSONIC)) // Modify floor flat alignment unless NOSONIC flag is set
{
sector->spawn_flrpic_angle = sector->floorpic_angle = flatangle;
sector->floor_xoffs += xoffs;
sector->floor_yoffs += yoffs;
// saved for netgames
sector->spawn_flr_xoffs = sector->floor_xoffs;
sector->spawn_flr_yoffs = sector->floor_yoffs;
}
if (!(master->flags & ML_NOTAILS)) // Modify ceiling flat alignment unless NOTAILS flag is set
{
sector->spawn_ceilpic_angle = sector->ceilingpic_angle = flatangle;
sector->ceiling_xoffs += xoffs;
sector->ceiling_yoffs += yoffs;
// saved for netgames
sector->spawn_ceil_xoffs = sector->ceiling_xoffs;
sector->spawn_ceil_yoffs = sector->ceiling_yoffs;
}
}
/** After the map has loaded, scans for specials that spawn 3Dfloors and
* thinkers.
*
@ -5572,7 +5596,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
{
case 10: // Time for special stage
sstimer = (sector->floorheight>>FRACBITS) * TICRATE + 6; // Time to finish
totalrings = sector->ceilingheight>>FRACBITS; // Ring count for special stage
ssspheres = sector->ceilingheight>>FRACBITS; // Ring count for special stage
break;
case 11: // Custom global gravity!
@ -5730,27 +5754,13 @@ void P_SpawnSpecials(INT32 fromnetsave)
yoffs = lines[i].v1->y;
}
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
//If no tag is given, apply to front sector
if (lines[i].tag == 0)
P_ApplyFlatAlignment(lines + i, lines[i].frontsector, flatangle, xoffs, yoffs);
else
{
if (!(lines[i].flags & ML_NOSONIC)) // Modify floor flat alignment unless NOSONIC flag is set
{
sectors[s].spawn_flrpic_angle = sectors[s].floorpic_angle = flatangle;
sectors[s].floor_xoffs += xoffs;
sectors[s].floor_yoffs += yoffs;
// saved for netgames
sectors[s].spawn_flr_xoffs = sectors[s].floor_xoffs;
sectors[s].spawn_flr_yoffs = sectors[s].floor_yoffs;
}
if (!(lines[i].flags & ML_NOTAILS)) // Modify ceiling flat alignment unless NOTAILS flag is set
{
sectors[s].spawn_ceilpic_angle = sectors[s].ceilingpic_angle = flatangle;
sectors[s].ceiling_xoffs += xoffs;
sectors[s].ceiling_yoffs += yoffs;
// saved for netgames
sectors[s].spawn_ceil_xoffs = sectors[s].ceiling_xoffs;
sectors[s].spawn_ceil_yoffs = sectors[s].ceiling_yoffs;
}
for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0;)
P_ApplyFlatAlignment(lines + i, sectors + s, flatangle, xoffs, yoffs);
}
}
else // Otherwise, print a helpful warning. Can I do no less?
@ -6689,6 +6699,7 @@ void T_Scroll(scroll_t *s)
line_t *line;
size_t i;
INT32 sect;
ffloor_t *rover;
case sc_side: // scroll wall texture
side = sides + s->affectee;
@ -6730,6 +6741,19 @@ void T_Scroll(scroll_t *s)
sector_t *psec;
psec = sectors + sect;
// Find the FOF corresponding to the control linedef
for (rover = psec->ffloors; rover; rover = rover->next)
{
if (rover->master == sec->lines[i])
break;
}
if (!rover) // This should be impossible, but don't complain if it is the case somehow
continue;
if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there
continue;
for (node = psec->touching_thinglist; node; node = node->m_thinglist_next)
{
thing = node->m_thing;
@ -6793,6 +6817,19 @@ void T_Scroll(scroll_t *s)
sector_t *psec;
psec = sectors + sect;
// Find the FOF corresponding to the control linedef
for (rover = psec->ffloors; rover; rover = rover->next)
{
if (rover->master == sec->lines[i])
break;
}
if (!rover) // This should be impossible, but don't complain if it is the case somehow
continue;
if (!(rover->flags & FF_EXISTS)) // If the FOF does not "exist", we pretend that nobody's there
continue;
for (node = psec->touching_thinglist; node; node = node->m_thinglist_next)
{
thing = node->m_thing;
@ -7646,7 +7683,6 @@ void T_Pusher(pusher_t *p)
thing->player->pflags |= jumped;
thing->player->pflags |= PF_SLIDING;
P_SetPlayerMobjState (thing, thing->info->painstate); // Whee!
thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR));
if (!demoplayback || P_AnalogMove(thing->player))

View file

@ -424,7 +424,7 @@ void P_DoTeamscrambling(void)
static inline void P_DoSpecialStageStuff(void)
{
boolean inwater = false;
boolean stillalive = false;
INT32 i;
// Can't drown in a special stage
@ -436,68 +436,60 @@ static inline void P_DoSpecialStageStuff(void)
players[i].powers[pw_underwater] = players[i].powers[pw_spacetime] = 0;
}
if (sstimer < 15*TICRATE+6 && sstimer > 7 && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC))
S_SpeedMusic(1.4f);
//if (sstimer < 15*TICRATE+6 && sstimer > 7 && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC))
//S_SpeedMusic(1.4f);
if (sstimer < 7 && sstimer > 0) // The special stage time is up!
if (sstimer && !objectplacing)
{
sstimer = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
{
players[i].exiting = (14*TICRATE)/5 + 1;
players[i].pflags &= ~PF_GLIDING;
}
if (i == consoleplayer)
S_StartSound(NULL, sfx_lose);
}
if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)
S_SpeedMusic(1.0f);
stagefailed = true;
}
if (sstimer > 1) // As long as time isn't up...
{
UINT32 ssrings = 0;
UINT16 countspheres = 0;
// Count up the rings of all the players and see if
// they've collected the required amount.
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
{
ssrings += players[i].rings;
tic_t oldnightstime = players[i].nightstime;
countspheres += players[i].spheres;
// If in water, deplete timer 6x as fast.
if ((players[i].mo->eflags & MFE_TOUCHWATER)
|| (players[i].mo->eflags & MFE_UNDERWATER))
inwater = true;
if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))
players[i].nightstime -= 5;
if (--players[i].nightstime > 6)
{
if (P_IsLocalPlayer(&players[i]) && oldnightstime > 10*TICRATE && players[i].nightstime <= 10*TICRATE)
S_ChangeMusicInternal("_drown", false);
stillalive = true;
}
else if (!players[i].exiting)
{
players[i].exiting = (14*TICRATE)/5 + 1;
players[i].pflags &= ~(PF_GLIDING|PF_BOUNCING);
players[i].nightstime = 0;
if (P_IsLocalPlayer(&players[i]))
S_StartSound(NULL, sfx_s3k66);
}
}
if (ssrings >= totalrings && totalrings > 0)
if (stillalive)
{
// Halt all the players
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
{
players[i].mo->momx = players[i].mo->momy = 0;
players[i].exiting = (14*TICRATE)/5 + 1;
}
if (countspheres >= ssspheres)
{
// Halt all the players
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
{
players[i].mo->momx = players[i].mo->momy = 0;
players[i].exiting = (14*TICRATE)/5 + 1;
}
sstimer = 0;
P_GiveEmerald(true);
sstimer = 0;
P_GiveEmerald(true);
P_RestoreMusic(&players[consoleplayer]);
}
}
// Decrement the timer
if (!objectplacing)
else
{
if (inwater)
sstimer -= 6;
else
sstimer--;
sstimer = 0;
stagefailed = true;
}
}
}
@ -606,9 +598,10 @@ void P_Ticker(boolean run)
}
// Keep track of how long they've been playing!
totalplaytime++;
if (!demoplayback) // Don't increment if a demo is playing.
totalplaytime++;
if (!useNightsSS && G_IsSpecialStage(gamemap))
if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))
P_DoSpecialStageStuff();
if (runemeraldmanager)

View file

@ -283,22 +283,11 @@ boolean P_PlayerMoving(INT32 pnum)
//
UINT8 P_GetNextEmerald(void)
{
if (!useNightsSS) // In order
{
if (!(emeralds & EMERALD1)) return 0;
if (!(emeralds & EMERALD2)) return 1;
if (!(emeralds & EMERALD3)) return 2;
if (!(emeralds & EMERALD4)) return 3;
if (!(emeralds & EMERALD5)) return 4;
if (!(emeralds & EMERALD6)) return 5;
return 6;
}
else // Depends on stage
{
if (gamemap < sstage_start || gamemap > sstage_end)
return 0;
if (gamemap >= sstage_start && gamemap <= sstage_end)
return (UINT8)(gamemap - sstage_start);
}
if (gamemap >= smpstage_start || gamemap <= smpstage_end)
return (UINT8)(gamemap - smpstage_start);
return 0;
}
//
@ -309,20 +298,19 @@ UINT8 P_GetNextEmerald(void)
//
void P_GiveEmerald(boolean spawnObj)
{
INT32 i;
UINT8 em;
UINT8 em = P_GetNextEmerald();
S_StartSound(NULL, sfx_cgot); // Got the emerald!
em = P_GetNextEmerald();
emeralds |= (1 << em);
if (spawnObj)
if (spawnObj && playeringame[consoleplayer])
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
P_SetMobjState(P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z + players[i].mo->info->height, MT_GOTEMERALD),
mobjinfo[MT_GOTEMERALD].spawnstate + em);
// The Chaos Emerald begins to orbit us!
// Only give it to ONE person!
mobj_t *emmo = P_SpawnMobjFromMobj(players[consoleplayer].mo, 0, 0, players[consoleplayer].mo->height, MT_GOTEMERALD);
P_SetTarget(&emmo->target, players[consoleplayer].mo);
P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em);
P_SetTarget(&players[consoleplayer].mo->tracer, emmo);
}
}
@ -696,10 +684,10 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
oldmare = player->mare;
if (P_TransferToNextMare(player) == false)
if (!P_TransferToNextMare(player))
{
INT32 i;
INT32 total_rings = 0;
INT32 total_spheres = 0;
P_SetTarget(&player->mo->target, NULL);
@ -707,7 +695,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i]/* && players[i].powers[pw_carry] == CR_NIGHTSMODE*/)
total_rings += players[i].rings;
total_spheres += players[i].spheres;
}
for (i = 0; i < MAXPLAYERS; i++)
@ -720,13 +708,13 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
players[i].lastmare = players[i].mare;
if (G_IsSpecialStage(gamemap))
{
players[i].finishedrings = (INT16)total_rings;
P_AddPlayerScore(player, total_rings * 50);
players[i].finishedspheres = (INT16)total_spheres;
P_AddPlayerScore(player, total_spheres * 50);
}
else
{
players[i].finishedrings = (INT16)(players[i].rings);
P_AddPlayerScore(&players[i], (players[i].rings) * 50);
players[i].finishedspheres = (INT16)(players[i].spheres);
P_AddPlayerScore(&players[i], (players[i].spheres) * 50);
}
// Add score to leaderboards now
@ -737,20 +725,20 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
players[i].lastmarescore = players[i].marescore;
players[i].marescore = 0;
players[i].rings = 0;
players[i].spheres = 0;
P_DoPlayerExit(&players[i]);
}
}
else if (oldmare != player->mare)
{
/// \todo Handle multi-mare special stages.
// Ring bonus
P_AddPlayerScore(player, (player->rings) * 50);
// Spheres bonus
P_AddPlayerScore(player, (player->spheres) * 50);
player->lastmare = (UINT8)oldmare;
player->texttimer = 4*TICRATE;
player->textvar = 4; // Score and grades
player->finishedrings = (INT16)(player->rings);
player->finishedspheres = (INT16)(player->spheres);
// Add score to temp leaderboards
if (!(netgame||multiplayer) && P_IsLocalPlayer(player))
@ -761,7 +749,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
player->marescore = 0;
player->marebegunat = leveltime;
player->rings = 0;
player->spheres = 0;
}
else
{
@ -861,7 +849,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
}
else
{
ang = R_PointToAngle2(player->mo->momx, player->mo->momy, 0, 0);
ang = ((player->mo->momx || player->mo->momy) ? R_PointToAngle2(player->mo->momx, player->mo->momy, 0, 0) : player->drawangle);
fallbackspeed = FixedMul(4*FRACUNIT, player->mo->scale);
}
@ -927,8 +915,7 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings)
player->rings += num_rings;
if (!G_IsSpecialStage(gamemap) || !useNightsSS)
player->totalring += num_rings;
player->totalring += num_rings;
// Can only get up to 9999 rings, sorry!
if (player->rings > 9999)
@ -960,6 +947,26 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings)
}
}
void P_GivePlayerSpheres(player_t *player, INT32 num_spheres)
{
if (!player)
return;
if (player->bot)
player = &players[consoleplayer];
if (!player->mo)
return;
player->spheres += num_spheres;
// Can only get up to 9999 spheres, sorry!
if (player->spheres > 9999)
player->spheres = 9999;
else if (player->spheres < 0)
player->spheres = 0;
}
//
// P_GivePlayerLives
//
@ -1039,12 +1046,11 @@ void P_DoSuperTransformation(player_t *player, boolean giverings)
S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi
player->mo->momx = player->mo->momy = player->mo->momz = player->cmomx = player->cmomy = player->rmomx = player->rmomy = 0;
// Transformation animation
P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_TRANS1);
player->mo->momx = player->mo->momy = player->mo->momz = 0;
player->pflags |= PF_NOJUMPDAMAGE; // just to avoid recurling but still allow thok
if (giverings)
player->rings = 50;
@ -1800,6 +1806,9 @@ boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space
for (rover = sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != SPACESPECIAL)
continue;
#ifdef ESLOPE
@ -2160,6 +2169,12 @@ static void P_CheckBouncySectors(player_t *player)
for (rover = node->m_sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue; // FOFs should not be bouncy if they don't even "exist"
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 15)
continue; // this sector type is required for FOFs to be bouncy
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);
@ -2173,7 +2188,6 @@ static void P_CheckBouncySectors(player_t *player)
&& oldz + player->mo->height > P_GetFOFBottomZ(player->mo, node->m_sector, rover, oldx, oldy, NULL))
top = false;
if (GETSECSPECIAL(rover->master->frontsector->special, 1) == 15)
{
fixed_t linedist;
@ -3488,194 +3502,198 @@ static void P_SetWeaponDelay(player_t *player, INT32 delay)
static void P_DoFiring(player_t *player, ticcmd_t *cmd)
{
INT32 i;
mobj_t *mo = NULL;
I_Assert(player != NULL);
I_Assert(!P_MobjWasRemoved(player->mo));
if (cmd->buttons & BT_ATTACK || cmd->buttons & BT_FIRENORMAL)
if (!(cmd->buttons & (BT_ATTACK|BT_FIRENORMAL)))
{
if (!(player->pflags & PF_ATTACKDOWN) && (player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER && !player->climbing)
{
player->pflags |= PF_ATTACKDOWN;
P_SpawnPlayerMissile(player->mo, MT_FIREBALL, 0);
S_StartSound(player->mo, sfx_mario7);
}
else if (G_RingSlingerGametype() && (!G_TagGametype() || player->pflags & PF_TAGIT)
&& !player->weapondelay && !player->climbing
&& !(player->pflags & PF_ATTACKDOWN))
{
mobj_t *mo = NULL;
player->pflags |= PF_ATTACKDOWN;
#define TAKE_AMMO(player, power) \
player->powers[power]--; \
if (player->rings < 1) \
{ \
if (player->powers[power] > 0) \
player->powers[power]--; \
} \
else \
player->rings--;
if (cmd->buttons & BT_FIRENORMAL) // No powers, just a regular ring.
goto firenormal; //code repetition sucks.
// Bounce ring
else if (player->currentweapon == WEP_BOUNCE && player->powers[pw_bouncering])
{
TAKE_AMMO(player, pw_bouncering);
P_SetWeaponDelay(player, TICRATE/4);
mo = P_SpawnPlayerMissile(player->mo, MT_THROWNBOUNCE, MF2_BOUNCERING);
if (mo)
mo->fuse = 3*TICRATE; // Bounce Ring time
}
// Rail ring
else if (player->currentweapon == WEP_RAIL && player->powers[pw_railring])
{
TAKE_AMMO(player, pw_railring);
P_SetWeaponDelay(player, (3*TICRATE)/2);
mo = P_SpawnPlayerMissile(player->mo, MT_REDRING, MF2_RAILRING|MF2_DONTDRAW);
// Rail has no unique thrown object, therefore its sound plays here.
S_StartSound(player->mo, sfx_rail1);
}
// Automatic
else if (player->currentweapon == WEP_AUTO && player->powers[pw_automaticring])
{
TAKE_AMMO(player, pw_automaticring);
player->pflags &= ~PF_ATTACKDOWN;
P_SetWeaponDelay(player, 2);
mo = P_SpawnPlayerMissile(player->mo, MT_THROWNAUTOMATIC, MF2_AUTOMATIC);
}
// Explosion
else if (player->currentweapon == WEP_EXPLODE && player->powers[pw_explosionring])
{
TAKE_AMMO(player, pw_explosionring);
P_SetWeaponDelay(player, (3*TICRATE)/2);
mo = P_SpawnPlayerMissile(player->mo, MT_THROWNEXPLOSION, MF2_EXPLOSION);
}
// Grenade
else if (player->currentweapon == WEP_GRENADE && player->powers[pw_grenadering])
{
TAKE_AMMO(player, pw_grenadering);
P_SetWeaponDelay(player, TICRATE/3);
mo = P_SpawnPlayerMissile(player->mo, MT_THROWNGRENADE, MF2_EXPLOSION);
if (mo)
{
//P_InstaThrust(mo, player->mo->angle, FixedMul(mo->info->speed, player->mo->scale));
mo->fuse = mo->info->mass;
}
}
// Scatter
// Note: Ignores MF2_RAILRING
else if (player->currentweapon == WEP_SCATTER && player->powers[pw_scatterring])
{
fixed_t oldz = player->mo->z;
angle_t shotangle = player->mo->angle;
angle_t oldaiming = player->aiming;
TAKE_AMMO(player, pw_scatterring);
P_SetWeaponDelay(player, (2*TICRATE)/3);
// Center
mo = P_SpawnPlayerMissile(player->mo, MT_THROWNSCATTER, MF2_SCATTER);
if (mo)
shotangle = R_PointToAngle2(player->mo->x, player->mo->y, mo->x, mo->y);
// Left
mo = P_SPMAngle(player->mo, MT_THROWNSCATTER, shotangle-ANG2, true, MF2_SCATTER);
// Right
mo = P_SPMAngle(player->mo, MT_THROWNSCATTER, shotangle+ANG2, true, MF2_SCATTER);
// Down
player->mo->z += FixedMul(12*FRACUNIT, player->mo->scale);
player->aiming += ANG1;
mo = P_SPMAngle(player->mo, MT_THROWNSCATTER, shotangle, true, MF2_SCATTER);
// Up
player->mo->z -= FixedMul(24*FRACUNIT, player->mo->scale);
player->aiming -= ANG2;
mo = P_SPMAngle(player->mo, MT_THROWNSCATTER, shotangle, true, MF2_SCATTER);
player->mo->z = oldz;
player->aiming = oldaiming;
return;
}
// No powers, just a regular ring.
else
{
firenormal:
// Infinity ring was selected.
// Mystic wants this ONLY to happen specifically if it's selected,
// and to not be able to get around it EITHER WAY with firenormal.
// Infinity Ring
if (player->currentweapon == 0
&& player->powers[pw_infinityring])
{
P_SetWeaponDelay(player, TICRATE/4);
mo = P_SpawnPlayerMissile(player->mo, MT_THROWNINFINITY, 0);
player->powers[pw_infinityring]--;
}
// Red Ring
else
{
if (player->rings <= 0)
return;
P_SetWeaponDelay(player, TICRATE/4);
mo = P_SpawnPlayerMissile(player->mo, MT_REDRING, 0);
if (mo)
P_ColorTeamMissile(mo, player);
player->rings--;
}
}
#undef TAKE_AMMO
if (mo)
{
if (mo->flags & MF_MISSILE && mo->flags2 & MF2_RAILRING)
{
const boolean nblockmap = !(mo->flags & MF_NOBLOCKMAP);
for (i = 0; i < 256; i++)
{
if (nblockmap)
{
P_UnsetThingPosition(mo);
mo->flags |= MF_NOBLOCKMAP;
P_SetThingPosition(mo);
}
if (i&1)
P_SpawnMobj(mo->x, mo->y, mo->z, MT_SPARK);
if (P_RailThinker(mo))
break; // mobj was removed (missile hit a wall) or couldn't move
}
// Other rail sound plays at contact point.
S_StartSound(mo, sfx_rail2);
}
}
}
// Not holding any firing buttons anymore.
// Release the grenade / whatever.
player->pflags &= ~PF_ATTACKDOWN;
return;
}
// Not holding any firing buttons anymore.
// Release the grenade / whatever.
player->pflags &= ~PF_ATTACKDOWN;
if (player->pflags & PF_ATTACKDOWN || player->climbing || (G_TagGametype() && !(player->pflags & PF_TAGIT)))
return;
if ((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER)
{
player->pflags |= PF_ATTACKDOWN;
mo = P_SpawnPlayerMissile(player->mo, MT_FIREBALL, 0);
P_InstaThrust(mo, player->mo->angle, ((mo->info->speed>>FRACBITS)*player->mo->scale) + player->speed);
S_StartSound(player->mo, sfx_mario7);
return;
}
if (!G_RingSlingerGametype() || player->weapondelay)
return;
player->pflags |= PF_ATTACKDOWN;
#define TAKE_AMMO(player, power) \
player->powers[power]--; \
if (player->rings < 1) \
{ \
if (player->powers[power] > 0) \
player->powers[power]--; \
} \
else \
player->rings--;
if (cmd->buttons & BT_FIRENORMAL) // No powers, just a regular ring.
goto firenormal; //code repetition sucks.
// Bounce ring
else if (player->currentweapon == WEP_BOUNCE && player->powers[pw_bouncering])
{
TAKE_AMMO(player, pw_bouncering);
P_SetWeaponDelay(player, TICRATE/4);
mo = P_SpawnPlayerMissile(player->mo, MT_THROWNBOUNCE, MF2_BOUNCERING);
if (mo)
mo->fuse = 3*TICRATE; // Bounce Ring time
}
// Rail ring
else if (player->currentweapon == WEP_RAIL && player->powers[pw_railring])
{
TAKE_AMMO(player, pw_railring);
P_SetWeaponDelay(player, (3*TICRATE)/2);
mo = P_SpawnPlayerMissile(player->mo, MT_REDRING, MF2_RAILRING|MF2_DONTDRAW);
// Rail has no unique thrown object, therefore its sound plays here.
S_StartSound(player->mo, sfx_rail1);
}
// Automatic
else if (player->currentweapon == WEP_AUTO && player->powers[pw_automaticring])
{
TAKE_AMMO(player, pw_automaticring);
player->pflags &= ~PF_ATTACKDOWN;
P_SetWeaponDelay(player, 2);
mo = P_SpawnPlayerMissile(player->mo, MT_THROWNAUTOMATIC, MF2_AUTOMATIC);
}
// Explosion
else if (player->currentweapon == WEP_EXPLODE && player->powers[pw_explosionring])
{
TAKE_AMMO(player, pw_explosionring);
P_SetWeaponDelay(player, (3*TICRATE)/2);
mo = P_SpawnPlayerMissile(player->mo, MT_THROWNEXPLOSION, MF2_EXPLOSION);
}
// Grenade
else if (player->currentweapon == WEP_GRENADE && player->powers[pw_grenadering])
{
TAKE_AMMO(player, pw_grenadering);
P_SetWeaponDelay(player, TICRATE/3);
mo = P_SpawnPlayerMissile(player->mo, MT_THROWNGRENADE, MF2_EXPLOSION);
if (mo)
{
//P_InstaThrust(mo, player->mo->angle, FixedMul(mo->info->speed, player->mo->scale));
mo->fuse = mo->info->reactiontime;
}
}
// Scatter
// Note: Ignores MF2_RAILRING
else if (player->currentweapon == WEP_SCATTER && player->powers[pw_scatterring])
{
fixed_t oldz = player->mo->z;
angle_t shotangle = player->mo->angle;
angle_t oldaiming = player->aiming;
TAKE_AMMO(player, pw_scatterring);
P_SetWeaponDelay(player, (2*TICRATE)/3);
// Center
mo = P_SpawnPlayerMissile(player->mo, MT_THROWNSCATTER, MF2_SCATTER);
if (mo)
shotangle = R_PointToAngle2(player->mo->x, player->mo->y, mo->x, mo->y);
// Left
mo = P_SPMAngle(player->mo, MT_THROWNSCATTER, shotangle-ANG2, true, MF2_SCATTER);
// Right
mo = P_SPMAngle(player->mo, MT_THROWNSCATTER, shotangle+ANG2, true, MF2_SCATTER);
// Down
player->mo->z += FixedMul(12*FRACUNIT, player->mo->scale);
player->aiming += ANG1;
mo = P_SPMAngle(player->mo, MT_THROWNSCATTER, shotangle, true, MF2_SCATTER);
// Up
player->mo->z -= FixedMul(24*FRACUNIT, player->mo->scale);
player->aiming -= ANG2;
mo = P_SPMAngle(player->mo, MT_THROWNSCATTER, shotangle, true, MF2_SCATTER);
player->mo->z = oldz;
player->aiming = oldaiming;
return;
}
// No powers, just a regular ring.
else
{
firenormal:
// Infinity ring was selected.
// Mystic wants this ONLY to happen specifically if it's selected,
// and to not be able to get around it EITHER WAY with firenormal.
// Infinity Ring
if (player->currentweapon == 0
&& player->powers[pw_infinityring])
{
P_SetWeaponDelay(player, TICRATE/4);
mo = P_SpawnPlayerMissile(player->mo, MT_THROWNINFINITY, 0);
player->powers[pw_infinityring]--;
}
// Red Ring
else
{
if (player->rings <= 0)
return;
P_SetWeaponDelay(player, TICRATE/4);
mo = P_SpawnPlayerMissile(player->mo, MT_REDRING, 0);
if (mo)
P_ColorTeamMissile(mo, player);
player->rings--;
}
}
#undef TAKE_AMMO
if (mo)
{
if (mo->flags & MF_MISSILE && mo->flags2 & MF2_RAILRING)
{
const boolean nblockmap = !(mo->flags & MF_NOBLOCKMAP);
for (i = 0; i < 256; i++)
{
if (nblockmap)
{
P_UnsetThingPosition(mo);
mo->flags |= MF_NOBLOCKMAP;
P_SetThingPosition(mo);
}
if (i&1)
P_SpawnMobj(mo->x, mo->y, mo->z, MT_SPARK);
if (P_RailThinker(mo))
break; // mobj was removed (missile hit a wall) or couldn't move
}
// Other rail sound plays at contact point.
S_StartSound(mo, sfx_rail2);
}
}
}
//
@ -3797,12 +3815,15 @@ static void P_DoSuperStuff(player_t *player)
//
boolean P_SuperReady(player_t *player)
{
if ((ALL7EMERALDS(emeralds) && player->rings >= 50) && !player->powers[pw_super] && !player->powers[pw_tailsfly]
&& !(player->powers[pw_shield] & SH_NOSTACK)
if (!player->powers[pw_super]
&& !player->powers[pw_invulnerability]
&& !(maptol & TOL_NIGHTS || (player->powers[pw_carry] == CR_NIGHTSMODE)) // don't turn 'regular super' in nights levels
&& player->pflags & PF_JUMPED
&& player->charflags & SF_SUPER)
&& !player->powers[pw_tailsfly]
&& (player->charflags & SF_SUPER)
&& (player->pflags & PF_JUMPED)
&& !(player->powers[pw_shield] & SH_NOSTACK)
&& !(maptol & TOL_NIGHTS)
&& ALL7EMERALDS(emeralds)
&& (player->rings >= 50))
return true;
return false;
@ -4488,12 +4509,12 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
}
else if (player->pflags & PF_SLIDING || (gametype == GT_CTF && player->gotflag))
;
else if (P_SuperReady(player))
/*else if (P_SuperReady(player))
{
// If you can turn super and aren't already,
// and you don't have a shield, do it!
P_DoSuperTransformation(player, false);
}
}*/
else if (player->pflags & PF_JUMPED)
{
#ifdef HAVE_BLUA
@ -5957,10 +5978,10 @@ static void P_DoNiGHTSCapsule(player_t *player)
if (G_IsSpecialStage(gamemap))
{ // In special stages, share rings. Everyone gives up theirs to the capsule player always, because we can't have any individualism here!
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && (&players[i] != player) && players[i].rings > 0)
if (playeringame[i] && (&players[i] != player) && players[i].spheres > 0)
{
player->rings += players[i].rings;
players[i].rings = 0;
player->spheres += players[i].spheres;
players[i].spheres = 0;
}
}
@ -5969,9 +5990,9 @@ static void P_DoNiGHTSCapsule(player_t *player)
&& player->mo->y == player->capsule->y
&& player->mo->z == player->capsule->z+(player->capsule->height/3))
{
if (player->rings > 0)
if (player->spheres > 0)
{
player->rings--;
player->spheres--;
player->capsule->health--;
player->capsule->extravalue1++;
@ -6003,9 +6024,6 @@ static void P_DoNiGHTSCapsule(player_t *player)
if (G_IsSpecialStage(gamemap))
{
// The Chaos Emerald begins to orbit us!
mobj_t *emmo;
UINT8 em = P_GetNextEmerald();
tic_t lowest_time;
/*for (i = 0; i < MAXPLAYERS; i++)
@ -6020,8 +6038,10 @@ static void P_DoNiGHTSCapsule(player_t *player)
if (player->powers[pw_carry] == CR_NIGHTSMODE)
{
// The Chaos Emerald begins to orbit us!
UINT8 em = P_GetNextEmerald();
// Only give it to ONE person, and THAT player has to get to the goal!
emmo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->info->height, MT_GOTEMERALD);
mobj_t *emmo = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height, MT_GOTEMERALD);
P_SetTarget(&emmo->target, player->mo);
P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em);
P_SetTarget(&player->mo->tracer, emmo);
@ -6039,18 +6059,24 @@ static void P_DoNiGHTSCapsule(player_t *player)
}
else
{
for (i = 0; i < 16; i++)
/*for (i = 0; i < 16; i++)
{
mobj_t *flicky = P_InternalFlickySpawn(player->capsule, 0, ((i%4) + 1)*2*FRACUNIT, true);
flicky->z += player->capsule->height/2;
flicky->angle = (i*(ANGLE_MAX/16));
P_InstaThrust(flicky, flicky->angle, 8*FRACUNIT);
}
}*/
mobj_t *idya = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height, MT_GOTEMERALD);
idya->extravalue2 = player->mare/5;
P_SetTarget(&idya->target, player->mo);
P_SetMobjState(idya, mobjinfo[MT_GOTEMERALD].missilestate + ((player->mare + 1) % 5));
P_SetTarget(&player->mo->tracer, idya);
}
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mare == player->mare)
P_SetTarget(&players[i].capsule, NULL); // Remove capsule from everyone now that it is dead!
S_StartScreamSound(player->mo, sfx_ngdone);
P_SwitchSpheresBonusMode(true);
}
}
else
@ -6143,7 +6169,7 @@ static void P_NiGHTSMovement(player_t *player)
}
else if (P_IsLocalPlayer(player) && player->nightstime == 10*TICRATE)
// S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH
S_ChangeMusicInternal("_drown",false);
S_ChangeMusicInternal((((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? "_ntime" : "_drown"), false);
if (player->mo->z < player->mo->floorz)
@ -6942,12 +6968,17 @@ static void P_MovePlayer(player_t *player)
if ((player->powers[pw_carry] == CR_NIGHTSMODE)
&& (player->exiting
|| !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1]
&& player->mo->state < &states[S_PLAY_NIGHTS_TRANS6])))
&& player->mo->state < &states[S_PLAY_NIGHTS_TRANS6]))) // Note the < instead of <=
{
skin_t *skin = ((skin_t *)(player->mo->skin));
if (skin->flags & SF_SUPER && player->mo->color < MAXSKINCOLORS)
if (skin->flags & SF_SUPER)
{
player->mo->color = skin->supercolor
+ ((player->nightstime == player->startedtime)
? 4
: abs((((signed)leveltime >> 1) % 9) - 4)); // This is where super flashing is handled.
G_GhostAddColor(GHC_SUPER);
player->mo->color = (skin->flags & SF_SUPER) ? skin->supercolor + abs((((signed)(player->startedtime - player->nightstime) >> 1) % 9) - 4) : player->mo->color; // This is where super flashing is handled.
}
}
if (!player->capsule && !player->bonustime)
@ -7481,7 +7512,7 @@ static void P_MovePlayer(player_t *player)
#endif
{
if (!(player->pflags & (PF_USEDOWN|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player is not holding down BT_USE, or having used an ability previously
&& (!(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX))) // thokked is optional if you're bubblewrapped
&& (!(player->powers[pw_shield] & SH_NOSTACK) || !(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX))) // thokked is optional if you're bubblewrapped/turning super
{
// Force shield activation
if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE)
@ -7494,6 +7525,11 @@ static void P_MovePlayer(player_t *player)
{
switch (player->powers[pw_shield] & SH_NOSTACK)
{
// Super!
case SH_NONE:
if (P_SuperReady(player))
P_DoSuperTransformation(player, false);
break;
// Whirlwind/Thundercoin shield activation
case SH_WHIRLWIND:
case SH_THUNDERCOIN:
@ -7945,17 +7981,18 @@ static void P_DoRopeHang(player_t *player)
if (player->cmd.buttons & BT_USE && !(player->pflags & PF_STASIS)) // Drop off of the rope
{
P_SetTarget(&player->mo->tracer, NULL);
player->pflags |= P_GetJumpFlags(player);
P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
P_SetTarget(&player->mo->tracer, NULL);
player->powers[pw_carry] = CR_NONE;
if (!(player->pflags & PF_SLIDING) && (player->pflags & PF_JUMPED)
&& !(player->panim == PA_JUMP))
P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
return;
}
if (player->mo->state-states != S_PLAY_RIDE)
P_SetPlayerMobjState(player->mo, S_PLAY_RIDE);
// If not allowed to move, we're done here.
if (!speed)
return;
@ -8046,10 +8083,7 @@ static void P_DoRopeHang(player_t *player)
if (player->mo->tracer->flags & MF_SLIDEME)
{
player->pflags |= P_GetJumpFlags(player);
if (!(player->pflags & PF_SLIDING) && (player->pflags & PF_JUMPED)
&& !(player->panim == PA_JUMP))
P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
}
P_SetTarget(&player->mo->tracer, NULL);
@ -8167,7 +8201,6 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
mobj_t *mo;
thinker_t *think;
mobj_t *closestmo = NULL;
const UINT32 targetmask = (MF_ENEMY|MF_BOSS|(nonenemies ? (MF_MONITOR|MF_SPRING) : 0));
const fixed_t maxdist = FixedMul((bullet ? RING_DIST*2 : RING_DIST), player->mo->scale);
const angle_t span = (bullet ? ANG30 : ANGLE_90);
fixed_t dist, closestdist = 0;
@ -8178,9 +8211,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
continue; // not a mobj thinker
mo = (mobj_t *)think;
if (!(mo->flags & targetmask
|| mo->type == MT_FAKEMOBILE // hehehehe
|| mo->type == MT_EGGSHIELD))
if (!(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag
continue; // not a valid target
if (mo->health <= 0) // dead
@ -8195,6 +8226,9 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
if ((mo->flags & (MF_ENEMY|MF_BOSS)) && !(mo->flags & MF_SHOOTABLE)) // don't aim at something you can't shoot at anyway (see Egg Guard or Minus)
continue;
if (!nonenemies && mo->flags & (MF_MONITOR|MF_SPRING))
continue;
if (!bullet && mo->type == MT_DETON) // Don't be STUPID, Sonic!
continue;
@ -8232,7 +8266,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
if (closestmo && dist > closestdist)
continue;
if ((R_PointToAngle2(player->mo->x, player->mo->y, mo->x, mo->y) - player->mo->angle + span) > span*2)
if ((R_PointToAngle2(player->mo->x + P_ReturnThrustX(player->mo, player->mo->angle, player->mo->radius), player->mo->y + P_ReturnThrustY(player->mo, player->mo->angle, player->mo->radius), mo->x, mo->y) - player->mo->angle + span) > span*2)
continue; // behind back
if (!P_CheckSight(player->mo, mo))
@ -9567,11 +9601,8 @@ void P_PlayerThink(player_t *player)
// If 11 seconds are left on the timer,
// begin the drown music for countdown!
if (countdown == 11*TICRATE - 1)
{
if (P_IsLocalPlayer(player))
S_ChangeMusicInternal("_drown", false);
}
if (countdown == 11*TICRATE - 1 && P_IsLocalPlayer(player))
S_ChangeMusicInternal("_drown", false);
// If you've hit the countdown and you haven't made
// it to the exit, you're a goner!
@ -9671,7 +9702,7 @@ void P_PlayerThink(player_t *player)
if (gametype != GT_COOP)
player->score = 0;
player->mo->health = 1;
player->rings = 0;
player->rings = player->spheres = 0;
}
else if ((netgame || multiplayer) && player->lives <= 0 && gametype != GT_COOP)
{
@ -9724,8 +9755,9 @@ void P_PlayerThink(player_t *player)
mo2 = (mobj_t *)th;
if (!(mo2->type == MT_NIGHTSWING || mo2->type == MT_RING || mo2->type == MT_COIN
|| mo2->type == MT_BLUEBALL))
if (!(mo2->type == MT_RING || mo2->type == MT_COIN
|| mo2->type == MT_BLUESPHERE || mo2->type == MT_BOMBSPHERE
|| mo2->type == MT_NIGHTSCHIP || mo2->type == MT_NIGHTSSTAR))
continue;
if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > FixedMul(128*FRACUNIT, player->mo->scale))
@ -9761,8 +9793,6 @@ void P_PlayerThink(player_t *player)
ticmiss++;
P_DoRopeHang(player);
if (player->mo->state-states != S_PLAY_RIDE)
P_SetPlayerMobjState(player->mo, S_PLAY_RIDE);
P_DoJumpStuff(player, &player->cmd);
}
else //if (player->powers[pw_carry] == CR_ZOOMTUBE)
@ -9878,7 +9908,8 @@ void P_PlayerThink(player_t *player)
if (!player->powers[pw_carry]
&& ((player->pflags & (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) == (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE))
&& !(cmd->forwardmove || cmd->sidemove)
&& (player->rmomx || player->rmomy))
&& (player->rmomx || player->rmomy)
&& (!player->capsule || (player->capsule->reactiontime != (player-players)+1)))
{
fixed_t acceleration = (player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration) * player->thrustfactor * 20;
angle_t moveAngle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
@ -9900,7 +9931,7 @@ void P_PlayerThink(player_t *player)
|| player->climbing
|| player->pflags & (PF_SPINNING|PF_SLIDING))
player->pflags &= ~PF_APPLYAUTOBRAKE;
else if (currentlyonground)
else if (currentlyonground || player->powers[pw_tailsfly])
player->pflags |= PF_APPLYAUTOBRAKE;
}
}
@ -10214,7 +10245,7 @@ void P_PlayerAfterThink(player_t *player)
if (player->followmobj)
{
P_RemoveMobj(player->followmobj);
player->followmobj = NULL;
P_SetTarget(&player->followmobj, NULL);
}
return;
}
@ -10332,7 +10363,7 @@ void P_PlayerAfterThink(player_t *player)
if (P_IsLocalPlayer(player) && (player->pflags & PF_WPNDOWN) && player->currentweapon != oldweapon)
S_StartSound(NULL, sfx_wepchg);
if (player->pflags & PF_SLIDING)
if ((player->pflags & PF_SLIDING) && ((player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE)) != PF_JUMPED))
P_SetPlayerMobjState(player->mo, player->mo->info->painstate);
/* if (player->powers[pw_carry] == CR_NONE && player->mo->tracer && !player->homing)
@ -10448,21 +10479,10 @@ void P_PlayerAfterThink(player_t *player)
player->secondjump = 0;
player->pflags &= ~PF_THOKKED;
if (cmd->forwardmove > 0)
{
if ((player->mo->tracer->tracer->lastlook += 2) > player->mo->tracer->tracer->friction)
player->mo->tracer->tracer->lastlook = player->mo->tracer->tracer->friction;
}
else if (cmd->forwardmove < 0)
{
if ((player->mo->tracer->tracer->lastlook -= 2) < player->mo->tracer->tracer->movecount)
player->mo->tracer->tracer->lastlook = player->mo->tracer->tracer->movecount;
}
if ((player->mo->tracer->tracer->flags & MF_SLIDEME) // Noclimb on chain parameters gives this
&& !(twodlevel || player->mo->flags2 & MF2_TWOD)) // why on earth would you want to turn them in 2D mode?
{
player->mo->tracer->tracer->health += cmd->sidemove;
player->mo->tracer->tracer->angle += cmd->sidemove<<ANGLETOFINESHIFT;
player->mo->angle += cmd->sidemove<<ANGLETOFINESHIFT; // 2048 --> ANGLE_MAX
if (!demoplayback || P_AnalogMove(player))
@ -10510,14 +10530,14 @@ void P_PlayerAfterThink(player_t *player)
if (player->followmobj && (player->spectator || player->mo->health <= 0 || player->followmobj->type != player->followitem))
{
P_RemoveMobj(player->followmobj);
player->followmobj = NULL;
P_SetTarget(&player->followmobj, NULL);
}
if (!player->spectator && player->mo->health && player->followitem)
{
if (!player->followmobj || P_MobjWasRemoved(player->followmobj))
{
player->followmobj = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, player->followitem);
P_SetTarget(&player->followmobj, P_SpawnMobjFromMobj(player->mo, 0, 0, 0, player->followitem));
P_SetTarget(&player->followmobj->tracer, player->mo);
player->followmobj->flags2 |= MF2_LINKDRAW;
}

View file

@ -257,7 +257,7 @@ const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = {
{0x00, 0x50, 0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5}, // SKINCOLOR_SUPERTAN2
{0x50, 0x51, 0x51, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9}, // SKINCOLOR_SUPERTAN3
{0x51, 0x52, 0x52, 0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed}, // SKINCOLOR_SUPERTAN4
{0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed, 0xee, 0xef, 0xef} // SKINCOLOR_SUPERTAN5
{0x52, 0x52, 0x54, 0x54, 0x54, 0x55, 0x56, 0x57, 0xf5, 0xf7, 0xf9, 0xfb, 0xed, 0xee, 0xef, 0xef} // SKINCOLOR_SUPERTAN5
};
// See also the enum skincolors_t

View file

@ -717,7 +717,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
colfunc = basecolfunc; // hack: this isn't resetting properly somewhere.
dc_colormap = vis->colormap;
if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
{
// translate certain pixels to white
colfunc = transcolfunc;
@ -2673,7 +2673,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
if (player->followmobj)
{
P_RemoveMobj(player->followmobj);
player->followmobj = NULL;
P_SetTarget(&player->followmobj, NULL);
}
if (player->mo)

View file

@ -446,10 +446,11 @@ void SCR_ClosedCaptions(void)
{
if (splitscreen)
basey -= 8;
else if (((maptol & TOL_NIGHTS) && (modeattacking == ATTACKING_NIGHTS))
|| (cv_powerupdisplay.value == 2)
else if ((modeattacking == ATTACKING_NIGHTS)
|| (!(maptol & TOL_NIGHTS)
&& ((cv_powerupdisplay.value == 2)
|| (cv_powerupdisplay.value == 1 && ((stplyr == &players[displayplayer] && !camera.chase)
|| ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase))))
|| ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase))))))
basey -= 16;
}

View file

@ -658,6 +658,14 @@ static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type)
SDL_memset(&event, 0, sizeof(event_t));
// Ignore the event if the mouse is not actually focused on the window.
// This can happen if you used the mouse to restore keyboard focus;
// this apparently makes a mouse button down event but not a mouse button up event,
// resulting in whatever key was pressed down getting "stuck" if we don't ignore it.
// -- Monster Iestyn (28/05/18)
if (SDL_GetMouseFocus() != window)
return;
/// \todo inputEvent.button.which
if (USE_MOUSEINPUT)
{

View file

@ -66,6 +66,7 @@ static boolean midimode;
static Mix_Music *music;
static UINT8 music_volume, midi_volume, sfx_volume;
static float loop_point;
static boolean songpaused;
#ifdef HAVE_LIBGME
static Music_Emu *gme;
@ -102,6 +103,7 @@ void I_StartupSound(void)
}
sound_started = true;
songpaused = false;
Mix_AllocateChannels(256);
}
@ -450,7 +452,7 @@ static void mix_gme(void *udata, Uint8 *stream, int len)
(void)udata;
// no gme? no music.
if (!gme || gme_track_ended(gme))
if (!gme || gme_track_ended(gme) || songpaused)
return;
// play gme into stream
@ -458,7 +460,7 @@ static void mix_gme(void *udata, Uint8 *stream, int len)
// apply volume to stream
for (i = 0, p = (short *)stream; i < len/2; i++, p++)
*p = ((INT32)*p) * music_volume / 31;
*p = ((INT32)*p) * music_volume*2 / 42;
}
#endif
@ -476,12 +478,14 @@ void I_PauseSong(INT32 handle)
{
(void)handle;
Mix_PauseMusic();
songpaused = true;
}
void I_ResumeSong(INT32 handle)
{
(void)handle;
Mix_ResumeMusic();
songpaused = false;
}
//

View file

@ -1180,12 +1180,6 @@ void I_StartupSound(void)
audio.callback = I_UpdateStream;
audio.userdata = &localdata;
if (dedicated)
{
nosound = nomidimusic = nodigimusic = true;
return;
}
// Configure sound device
CONS_Printf("I_StartupSound:\n");
@ -1481,9 +1475,6 @@ void I_InitMusic(void)
I_AddExitFunc(I_ShutdownGMEMusic);
#endif
if ((nomidimusic && nodigimusic) || dedicated)
return;
#ifdef HAVE_MIXER
MIX_VERSION(&MIXcompiled)
MIXlinked = Mix_Linked_Version();

View file

@ -65,7 +65,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"buzz1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Electric zap"},
{"buzz2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Electric zap"},
{"buzz3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wacky worksurface"},
{"buzz4", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Buzz"},
{"buzz4", true, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Buzz"},
{"crumbl", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crumbling"}, // Platform Crumble Tails 03-16-2001
{"fire", false, 8, 32, -1, NULL, 0, -1, -1, LUMPERROR, "Flamethrower"},
{"grind", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Metallic grinding"},
@ -76,6 +76,8 @@ sfxinfo_t S_sfx[NUMSFX] =
{"steam1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Steam jet"}, // Tails 06-19-2001
{"steam2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Steam jet"}, // Tails 06-19-2001
{"wbreak", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wood breaking"},
{"ambmac", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Machinery"},
{"spsmsh", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy impact"},
{"rainin", true, 24, 4, -1, NULL, 0, -1, -1, LUMPERROR, "Rain"},
{"litng1", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning"},
@ -139,14 +141,14 @@ sfxinfo_t S_sfx[NUMSFX] =
{"bnce1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"}, // Boing!
{"bnce2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Scatter"}, // Boing!
{"cannon", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful shot"},
{"cgot" , true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Chaos Emerald"}, // Got Emerald! Tails 09-02-2001
{"cgot" , true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Emerald"}, // Got Emerald! Tails 09-02-2001
{"cybdth", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Explosion"},
{"deton", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous beeping"},
{"deton", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Threatening beeping"},
{"ding", false, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Ding"},
{"dmpain", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Machine damage"},
{"drown", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drowning"},
{"fizzle", false, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Electric fizzle"},
{"gbeep", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous beeping"}, // Grenade beep
{"gbeep", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Threatening beeping"}, // Grenade beep
{"wepfir", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing weapon"}, // defaults to thok
{"ghit" , false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Goop splash"},
{"gloop", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Splash"},
@ -177,15 +179,17 @@ sfxinfo_t S_sfx[NUMSFX] =
{"spring", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spring"},
{"statu1", true, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Pushing a statue"},
{"statu2", true, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Pushing a statue"},
{"strpst", true, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"}, // Starpost Sound Tails 07-04-2002
{"strpst", true, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"},
{"supert", true, 127, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Transformation"},
{"telept", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Dash"},
{"tink" , false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Tink"},
{"token" , true, 224, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Token"}, // SS token
{"token" , true, 224, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Token"},
{"trfire", true, 60, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Laser fired"},
{"trpowr", true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"},
{"turhit", false, 40, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Laser hit"},
{"wdjump", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Whirlwind jump"},
{"shrpsp", true, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spincushion"},
{"shrpgo", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Launch"},
{"mswarp", false, 60, 16, -1, NULL, 0, -1, -1, LUMPERROR, "Spinning out"},
{"mspogo", false, 60, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Breaking through"},
{"boingf", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bouncing"},
@ -210,11 +214,12 @@ sfxinfo_t S_sfx[NUMSFX] =
{"xideya", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Success"}, // Xmas
{"nbmper", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"},
{"nxbump", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, // Xmas
{"ncchip", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got chip"},
{"ncitem", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got special"},
{"nxitem", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got special"}, // Xmas
{"ngdone", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bonus time start"},
{"nxdone", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bonus time start"}, // Xmas
{"drill1", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drill start"},
{"drill1", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drill"},
{"drill2", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drill"},
{"ncspec", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power-up"}, // Tails 12-15-2003
{"nghurt", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hurt"},
@ -224,19 +229,26 @@ sfxinfo_t S_sfx[NUMSFX] =
{"hoop3", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hoop++"},
{"hidden", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"},
{"prloop", false, 104, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Gust of wind"},
{"timeup", true, 256, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous Countdown"},
{"ngjump", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"},
{"peww", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pew"},
// Halloween
{"lntsit", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cacolantern awake"},
{"lntdie", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cacolantern death"},
{"pumpkn", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pumpkin smash"}, // idspispopd
{"ghosty", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Laughter"},
// Mario
{"koopfr" , true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Fire"},
{"mario1", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hitting a ceiling"},
{"mario2", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Koopa shell"},
{"mario1", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hit"},
{"mario2", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bonk"},
{"mario3", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power-up"},
{"mario4", true, 78, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got coin"},
{"mario5", false, 78, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Boot"},
{"mario5", false, 78, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Boot-stomp"},
{"mario6", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"},
{"mario7", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Fire"},
{"mario8", false, 48, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Hurt"},
{"mario9", true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Emerging"},
{"mario9", true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Emerging power-up"},
{"marioa", true, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "One-up"},
{"thwomp", true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Thwomp"},
@ -287,7 +299,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3k3d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pop"},
{"s3k3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame Shield"},
{"s3k3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble Shield"},
{"s3k40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction shot"},
{"s3k40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction blast"},
{"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning Shield"},
{"s3k42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Twinspin"},
{"s3k43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame burst"},
@ -295,22 +307,22 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3k45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning zap"},
{"s3k46", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Transformation"},
{"s3k47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising dust"},
{"s3k48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Metallic clink"},
{"s3k49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling rock"},
{"s3k48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pulse"},
{"s3k49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Impact"},
{"s3k4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Grab"},
{"s3k4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Water splash"},
{"s3k4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy hit"},
{"s3k4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing bullet"},
{"s3k4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bomb explosion"},
{"s3k4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Big explosion"},
{"s3k4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flamethrower"},
{"s3k50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Siren"},
{"s3k51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling bomb"},
{"s3k51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling hazard"},
{"s3k52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spike"},
{"s3k53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"},
{"s3k54", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Firing"}, // MetalSonic shot fire
{"s3k55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical movement"},
{"s3k56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy landing"},
{"s3k57", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Splash"},
{"s3k57", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"},
{"s3k58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical movement"},
{"s3k59", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crumbling"},
{"s3k5a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"},
@ -324,13 +336,13 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3k62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"},
{"s3k63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"},
{"s3k64", false, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Clatter"},
{"s3k65", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got blue sphere"}, // Blue Spheres
{"s3k66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Special stage clear"},
{"s3k65", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got sphere"}, // Blue Spheres
{"s3k66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Special stage end"},
{"s3k67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing missile"},
{"s3k68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Unknown possibilities"},
{"s3k68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"},
{"s3k69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Switch click"},
{"s3k6a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Special stage clear"},
{"s3k6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3k6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Punch"},
{"s3k6c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"},
{"s3k6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3k6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical damage"},
@ -363,16 +375,16 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3k89", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Advanced technology"},
{"s3k8a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Boing"},
{"s3k8b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful hit"},
{"s3k8c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3k8c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Humming power"},
{"s3k8d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3k8e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3k8e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Accelerating"},
{"s3k8f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Opening"},
{"s3k90", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Impact"},
{"s3k91", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Closed"},
{"s3k92", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ghost"},
{"s3k93", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rebuilding"},
{"s3k94", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spike"},
{"s3k95", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising from lava"},
{"s3k95", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lava burst"},
{"s3k96", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling object"},
{"s3k97", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wind"},
{"s3k98", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling spike"},
@ -429,8 +441,8 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3kc3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Levitation"}, // ditto
{"s3kc4s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing laser"},
{"s3kc4l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing laser"}, // ditto
{"s3kc5s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3kc5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto
{"s3kc5s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Revving up"},
{"s3kc5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Revving up"}, // ditto
{"s3kc6s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"},
{"s3kc6l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"}, // ditto
{"s3kc7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"},
@ -455,7 +467,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3kd1s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3kd1l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto
{"s3kd2s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turning"},
{"s3kd2l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turning"}, // ditto
{"s3kd2l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Moving chain"}, // ditto
{"s3kd3s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3kd3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto
{"s3kd4s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Engine"},

View file

@ -142,6 +142,8 @@ typedef enum
sfx_steam1,
sfx_steam2,
sfx_wbreak,
sfx_ambmac,
sfx_spsmsh,
sfx_rainin,
sfx_litng1,
@ -252,6 +254,8 @@ typedef enum
sfx_trpowr,
sfx_turhit,
sfx_wdjump,
sfx_shrpsp,
sfx_shrpgo,
sfx_mswarp,
sfx_mspogo,
sfx_boingf,
@ -276,6 +280,7 @@ typedef enum
sfx_xideya, // Xmas
sfx_nbmper,
sfx_nxbump, // Xmas
sfx_ncchip,
sfx_ncitem,
sfx_nxitem, // Xmas
sfx_ngdone,
@ -290,7 +295,14 @@ typedef enum
sfx_hoop3,
sfx_hidden,
sfx_prloop,
sfx_timeup, // Was gonna be played when less than ten seconds are on the clock; uncomment uses of this to see it in-context
sfx_ngjump,
sfx_peww,
// Halloween
sfx_lntsit,
sfx_lntdie,
sfx_pumpkn,
sfx_ghosty,
// Mario
sfx_koopfr,

View file

@ -27,6 +27,8 @@
#include "i_system.h"
#include "m_menu.h"
#include "m_cheat.h"
#include "m_misc.h" // moviemode
#include "m_anigif.h" // cv_gif_downscale
#include "p_setup.h" // NiGHTS grading
//random index
@ -110,6 +112,8 @@ static patch_t *yelstat;
static patch_t *nbracket;
static patch_t *nhud[12];
static patch_t *nsshud;
static patch_t *nbon[12];
static patch_t *nssbon;
static patch_t *narrow[9];
static patch_t *nredar[8]; // Red arrow
static patch_t *drillbar;
@ -200,17 +204,17 @@ void ST_doPaletteStuff(void)
else
palette = 0;
#ifdef HWRENDER
if (rendermode == render_opengl)
palette = 0; // No flashpals here in OpenGL
#endif
palette = min(max(palette, 0), 13);
if (palette != st_palette)
{
st_palette = palette;
#ifdef HWRENDER
if (rendermode == render_opengl)
HWR_SetPaletteColor(0);
else
#endif
if (rendermode != render_none)
{
V_SetPaletteLump(GetPalette()); // Reset the palette
@ -307,8 +311,12 @@ void ST_LoadGraphics(void)
yelstat = W_CachePatchName("YELSTAT", PU_HUDGFX);
nbracket = W_CachePatchName("NBRACKET", PU_HUDGFX);
for (i = 0; i < 12; ++i)
{
nhud[i] = W_CachePatchName(va("NHUD%d", i+1), PU_HUDGFX);
nbon[i] = W_CachePatchName(va("NBON%d", i+1), PU_HUDGFX);
}
nsshud = W_CachePatchName("NSSHUD", PU_HUDGFX);
nssbon = W_CachePatchName("NSSBON", PU_HUDGFX);
minicaps = W_CachePatchName("MINICAPS", PU_HUDGFX);
for (i = 0; i < 8; ++i)
@ -460,7 +468,7 @@ static void ST_drawDebugInfo(void)
#define VFLAGS V_MONOSPACE|V_SNAPTOTOP|V_SNAPTORIGHT
if (vid.dupx == 1)
if ((moviemode == MM_GIF && cv_gif_downscale.value) || vid.dupx == 1)
{
if (cv_debug & DBG_BASIC)
{
@ -657,9 +665,9 @@ static void ST_drawTime(void)
else
{
// Counting down the hidetime?
if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (leveltime <= (hidetime*TICRATE)))
if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (stplyr->realtime <= (hidetime*TICRATE)))
{
tics = (hidetime*TICRATE - leveltime);
tics = (hidetime*TICRATE - stplyr->realtime);
if (tics < 3*TICRATE)
ST_drawRaceNum(tics);
downwards = true;
@ -667,15 +675,15 @@ static void ST_drawTime(void)
else
{
// Hidetime finish!
if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (leveltime < ((hidetime+1)*TICRATE)))
ST_drawRaceNum(hidetime*TICRATE - leveltime);
if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (stplyr->realtime < ((hidetime+1)*TICRATE)))
ST_drawRaceNum(hidetime*TICRATE - stplyr->realtime);
// Time limit?
if (gametype != GT_RACE && gametype != GT_COMPETITION && gametype != GT_COOP && cv_timelimit.value && timelimitintics > 0)
if (gametype != GT_COOP && gametype != GT_RACE && gametype != GT_COMPETITION && cv_timelimit.value && timelimitintics > 0)
{
if (timelimitintics >= leveltime)
if (timelimitintics >= stplyr->realtime)
{
tics = (timelimitintics - leveltime);
tics = (timelimitintics - stplyr->realtime);
if (tics < 3*TICRATE)
ST_drawRaceNum(tics);
}
@ -733,18 +741,7 @@ static inline void ST_drawRings(void)
ST_DrawPatchFromHud(HUD_RINGS, ((!stplyr->spectator && stplyr->rings <= 0 && leveltime/5 & 1) ? sboredrings : sborings), ((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS));
if (objectplacing)
ringnum = op_currentdoomednum;
else if (!useNightsSS && G_IsSpecialStage(gamemap))
{
INT32 i;
ringnum = 0;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && players[i].rings > 0)
ringnum += players[i].rings;
}
else
ringnum = max(stplyr->rings, 0);
ringnum = ((objectplacing) ? op_currentdoomednum : max(stplyr->rings, 0));
if (cv_timetic.value == 2) // Yes, even in modeattacking
ST_DrawNumFromHud(HUD_RINGSNUMTICS, ringnum, V_PERPLAYER|((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS));
@ -1096,7 +1093,8 @@ static void ST_drawInput(void)
((!stplyr->powers[pw_carry]
&& (stplyr->pflags & PF_APPLYAUTOBRAKE)
&& !(stplyr->cmd.sidemove || stplyr->cmd.forwardmove)
&& (stplyr->rmomx || stplyr->rmomy))
&& (stplyr->rmomx || stplyr->rmomy)
&& (!stplyr->capsule || (stplyr->capsule->reactiontime != (stplyr-players)+1)))
? 0 : V_GRAYMAP),
"AUTOBRAKE");
y -= 8;
@ -1392,17 +1390,17 @@ static void ST_drawNightsRecords(void)
V_DrawCenteredString(BASEVIDWIDTH/2, 60, aflag,
va(M_GetText("\x80GET\x82 %d\x80 %s%s%s!"), stplyr->capsule->health,
(stplyr->textvar == 3) ? M_GetText("MORE ") : "",
(G_IsSpecialStage(gamemap)) ? "SPHERE" : "RING",
(G_IsSpecialStage(gamemap)) ? "SPHERE" : "CHIP",
(stplyr->capsule->health > 1) ? "S" : ""));
}
// End Bonus
else if (stplyr->textvar == 4)
{
V_DrawString(BASEVIDWIDTH/2 - 56, 140, aflag, (G_IsSpecialStage(gamemap)) ? "SPHERES:" : "RINGS:");
V_DrawString(BASEVIDWIDTH/2 - 56, 140, aflag, (G_IsSpecialStage(gamemap)) ? "SPHERES:" : "CHIPS:");
V_DrawString(BASEVIDWIDTH/2 - 56, 148, aflag, "BONUS:");
V_DrawRightAlignedString(BASEVIDWIDTH/2 + 56, 140, V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings));
V_DrawRightAlignedString(BASEVIDWIDTH/2 + 56, 140, V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings * 50));
V_DrawRightAlignedString(BASEVIDWIDTH/2 + 56, 140, V_ORANGEMAP|aflag, va("%d", stplyr->finishedspheres));
V_DrawRightAlignedString(BASEVIDWIDTH/2 + 56, 148, V_ORANGEMAP|aflag, va("%d", stplyr->finishedspheres * 50));
ST_DrawNightsOverlayNum((BASEVIDWIDTH/2 + 56)<<FRACBITS, 160<<FRACBITS, FRACUNIT, aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_AZURE);
// If new record, say so!
@ -1460,15 +1458,15 @@ static void ST_drawNiGHTSHUD(void)
{
INT32 origamount;
INT32 minlink = 1;
INT32 total_ringcount;
// When debugging, show "0 Link".
if (cv_debug & DBG_NIGHTSBASIC)
minlink = 0;
INT32 total_spherecount;
const boolean oldspecialstage = (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS));
// Cheap hack: don't display when the score is showing (it popping up for a split second when exiting a map is intentional)
if (stplyr->texttimer && stplyr->textvar == 4)
if (oldspecialstage || (stplyr->texttimer && stplyr->textvar == 4))
minlink = INT32_MAX;
// When debugging, show "0 Link".
else if (cv_debug & DBG_NIGHTSBASIC)
minlink = 0;
// Drill meter
if (
@ -1574,25 +1572,37 @@ static void ST_drawNiGHTSHUD(void)
// Begin drawing brackets/chip display
#ifdef HAVE_BLUA
if (LUA_HudEnabled(hud_nightsrings))
if (LUA_HudEnabled(hud_nightsspheres))
{
#endif
ST_DrawTopLeftOverlayPatch(16, 8, nbracket);
if (G_IsSpecialStage(gamemap))
ST_DrawTopLeftOverlayPatch(24, 16, nsshud);
ST_DrawTopLeftOverlayPatch(24, 16, (
#ifdef MANIASPHERES
(stplyr->bonustime && (leveltime & 4)) ? nssbon :
#endif
nsshud));
else
ST_DrawTopLeftOverlayPatch(24, 16, nhud[(leveltime/2)%12]);
ST_DrawTopLeftOverlayPatch(24, 16, *(((stplyr->bonustime) ? nbon : nhud)+((leveltime/2)%12)));
if (G_IsSpecialStage(gamemap))
{
INT32 i;
total_ringcount = 0;
total_spherecount = 0;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/ && players[i].rings)
total_ringcount += players[i].rings;
if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/ && players[i].spheres)
total_spherecount += players[i].spheres;
}
else
total_ringcount = stplyr->rings;
total_spherecount = stplyr->spheres;
/*if (oldspecialstage)
{
if (total_spherecount < ssspheres)
total_spherecount = ssspheres - total_spherecount;
else
total_spherecount = 0;
}*/
if (stplyr->capsule)
{
@ -1648,28 +1658,48 @@ static void ST_drawNiGHTSHUD(void)
amount = (origamount - stplyr->capsule->health);
amount = (amount * length)/origamount;
for (cfill = 0; cfill < amount && cfill < 88; ++cfill)
for (cfill = 0; cfill < amount && cfill < length; ++cfill)
V_DrawScaledPatch(15 + cfill + 1, 8 + 35, V_PERPLAYER|V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulefill);
}
if (total_ringcount >= stplyr->capsule->health)
ST_DrawTopLeftOverlayPatch(40, 8 + 5, nredar[leveltime%8]);
if (total_spherecount >= stplyr->capsule->health)
ST_DrawTopLeftOverlayPatch(40, 8 + 5, nredar[leveltime&7]);
else
ST_DrawTopLeftOverlayPatch(40, 8 + 5, narrow[(leveltime/2)%8]);
ST_DrawTopLeftOverlayPatch(40, 8 + 5, narrow[(leveltime/2)&7]);
}
else if (oldspecialstage && total_spherecount < (INT32)ssspheres)
{
INT32 cfill, amount;
const INT32 length = 88;
UINT8 em = P_GetNextEmerald();
ST_DrawTopLeftOverlayPatch(72, 8, nbracket);
if (em <= 7)
ST_DrawTopLeftOverlayPatch(80, 8 + 8, emeraldpics[0][em]);
ST_DrawTopLeftOverlayPatch(40, 8 + 5, narrow[(leveltime/2)&7]);
// Lil' white box!
V_DrawScaledPatch(15, 8 + 34, V_PERPLAYER|V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulebar);
amount = (total_spherecount * length)/ssspheres;
for (cfill = 0; cfill < amount && cfill < length; ++cfill)
V_DrawScaledPatch(15 + cfill + 1, 8 + 35, V_PERPLAYER|V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulefill);
}
else
ST_DrawTopLeftOverlayPatch(40, 8 + 5, narrow[8]);
if (total_ringcount >= 100)
V_DrawTallNum((total_ringcount >= 1000) ? 76 : 72, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_ringcount);
if (total_spherecount >= 100)
V_DrawTallNum((total_spherecount >= 1000) ? 76 : 72, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_spherecount);
else
V_DrawTallNum(68, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_ringcount);
V_DrawTallNum(68, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_spherecount);
#ifdef HAVE_BLUA
}
#endif
// Score
if (!stplyr->exiting
if (!stplyr->exiting && !oldspecialstage
#ifdef HAVE_BLUA
&& LUA_HudEnabled(hud_nightsscore)
#endif
@ -1712,6 +1742,7 @@ static void ST_drawNiGHTSHUD(void)
{
INT32 realnightstime = stplyr->nightstime/TICRATE;
INT32 numbersize;
UINT8 col = ((realnightstime < 10) ? SKINCOLOR_RED : SKINCOLOR_SUPERGOLD4);
if (G_IsSpecialStage(gamemap))
{
@ -1742,46 +1773,66 @@ static void ST_drawNiGHTSHUD(void)
else
numbersize = 48/2;
ST_DrawNightsOverlayNum((160 + numbersize)<<FRACBITS, 14<<FRACBITS, FRACUNIT, V_PERPLAYER|V_SNAPTOTOP, realnightstime, nightsnum,
((realnightstime < 10) ? SKINCOLOR_RED : SKINCOLOR_SUPERGOLD4));
if ((oldspecialstage && leveltime & 2)
&& (stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)))
col = SKINCOLOR_ORANGE;
ST_DrawNightsOverlayNum((160 + numbersize)<<FRACBITS, 14<<FRACBITS, FRACUNIT, V_PERPLAYER|V_SNAPTOTOP, realnightstime, nightsnum, col);
// Show exact time in debug
if (cv_debug & DBG_NIGHTSBASIC)
V_DrawString(160 + numbersize + 8, 24, V_SNAPTOTOP|((realnightstime < 10) ? V_REDMAP : V_YELLOWMAP), va("%02d", G_TicsToCentiseconds(stplyr->nightstime)));
}
// Show pickup durations
if (cv_debug & DBG_NIGHTSBASIC)
if (oldspecialstage)
{
UINT16 pwr;
if (stplyr->powers[pw_nights_superloop])
if (leveltime < 5*TICRATE)
{
pwr = stplyr->powers[pw_nights_superloop];
V_DrawSmallScaledPatch(110, 44, 0, W_CachePatchName("NPRUA0",PU_CACHE));
V_DrawThinString(106, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr)));
}
if (stplyr->powers[pw_nights_helper])
{
pwr = stplyr->powers[pw_nights_helper];
V_DrawSmallScaledPatch(150, 44, 0, W_CachePatchName("NPRUC0",PU_CACHE));
V_DrawThinString(146, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr)));
}
if (stplyr->powers[pw_nights_linkfreeze])
{
pwr = stplyr->powers[pw_nights_linkfreeze];
V_DrawSmallScaledPatch(190, 44, 0, W_CachePatchName("NPRUE0",PU_CACHE));
V_DrawThinString(186, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr)));
INT32 aflag = V_PERPLAYER;
tic_t drawtime = (5*TICRATE) - leveltime;
if (drawtime < TICRATE/2)
aflag |= (9 - 9*drawtime/(TICRATE/2)) << V_ALPHASHIFT;
// This one, not quite as much so.
V_DrawCenteredString(BASEVIDWIDTH/2, 60, aflag,
va(M_GetText("\x80GET\x82 %d\x80 SPHERE%s!"), ssspheres,
(ssspheres > 1) ? "S" : ""));
}
}
else
{
// Show pickup durations
if (cv_debug & DBG_NIGHTSBASIC)
{
UINT16 pwr;
// Records/extra text
if (stplyr->powers[pw_nights_superloop])
{
pwr = stplyr->powers[pw_nights_superloop];
V_DrawSmallScaledPatch(110, 44, 0, W_CachePatchName("NPRUA0",PU_CACHE));
V_DrawThinString(106, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr)));
}
if (stplyr->powers[pw_nights_helper])
{
pwr = stplyr->powers[pw_nights_helper];
V_DrawSmallScaledPatch(150, 44, 0, W_CachePatchName("NPRUC0",PU_CACHE));
V_DrawThinString(146, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr)));
}
if (stplyr->powers[pw_nights_linkfreeze])
{
pwr = stplyr->powers[pw_nights_linkfreeze];
V_DrawSmallScaledPatch(190, 44, 0, W_CachePatchName("NPRUE0",PU_CACHE));
V_DrawThinString(186, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr)));
}
}
// Records/extra text
#ifdef HAVE_BLUA
if (LUA_HudEnabled(hud_nightsrecords))
if (LUA_HudEnabled(hud_nightsrecords))
#endif
ST_drawNightsRecords();
ST_drawNightsRecords();
}
}
static inline void ST_drawWeaponSelect(INT32 xoffs, INT32 y)
@ -1950,7 +2001,7 @@ static void ST_drawTextHUD(void)
}
else if (stplyr->spectator && (gametype != GT_COOP || stplyr->playerstate == PST_LIVE))
{
if (G_IsSpecialStage(gamemap) && useNightsSS)
if (G_IsSpecialStage(gamemap) && (maptol & TOL_NIGHTS))
textHUDdraw(M_GetText("\x82""Wait for the stage to end..."))
else if (gametype == GT_COOP)
{
@ -2068,22 +2119,22 @@ num:
#undef SEP
}
static void ST_drawSpecialStageHUD(void)
/*static void ST_drawSpecialStageHUD(void)
{
if (totalrings > 0)
if (ssspheres > 0)
{
if (hudinfo[HUD_SS_TOTALRINGS].x)
ST_DrawNumFromHud(HUD_SS_TOTALRINGS, totalrings, V_HUDTRANS);
ST_DrawNumFromHud(HUD_SS_TOTALRINGS, ssspheres, V_HUDTRANS);
else if (cv_timetic.value == 2)
V_DrawTallNum(hudinfo[HUD_RINGSNUMTICS].x, hudinfo[HUD_SS_TOTALRINGS].y, hudinfo[HUD_RINGSNUMTICS].f|V_PERPLAYER|V_HUDTRANS, totalrings);
V_DrawTallNum(hudinfo[HUD_RINGSNUMTICS].x, hudinfo[HUD_SS_TOTALRINGS].y, hudinfo[HUD_RINGSNUMTICS].f|V_PERPLAYER|V_HUDTRANS, ssspheres);
else
V_DrawTallNum(hudinfo[HUD_RINGSNUM].x, hudinfo[HUD_SS_TOTALRINGS].y, hudinfo[HUD_RINGSNUM].f|V_PERPLAYER|V_HUDTRANS, totalrings);
V_DrawTallNum(hudinfo[HUD_RINGSNUM].x, hudinfo[HUD_SS_TOTALRINGS].y, hudinfo[HUD_RINGSNUM].f|V_PERPLAYER|V_HUDTRANS, ssspheres);
}
if (leveltime < 5*TICRATE && totalrings > 0)
if (leveltime < 5*TICRATE && ssspheres > 0)
{
ST_DrawPatchFromHud(HUD_GETRINGS, getall, V_HUDTRANS);
ST_DrawNumFromHud(HUD_GETRINGSNUM, totalrings, V_HUDTRANS);
ST_DrawNumFromHud(HUD_GETRINGSNUM, ssspheres, V_HUDTRANS);
}
if (sstimer)
@ -2093,7 +2144,7 @@ static void ST_drawSpecialStageHUD(void)
}
else
ST_DrawPatchFromHud(HUD_TIMEUP, timeup, V_HUDTRANS);
}
}*/
static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offset)
{
@ -2229,7 +2280,7 @@ static void ST_overlayDrawer(void)
//hu_showscores = auto hide score/time/rings when tab rankings are shown
if (!(hu_showscores && (netgame || multiplayer)))
{
if (maptol & TOL_NIGHTS)
if (maptol & TOL_NIGHTS || G_IsSpecialStage(gamemap))
ST_drawNiGHTSHUD();
else
{
@ -2338,10 +2389,6 @@ static void ST_overlayDrawer(void)
if (gametype == GT_RACE || gametype == GT_COMPETITION)
ST_drawRaceHUD();
// Special Stage HUD
if (!useNightsSS && G_IsSpecialStage(gamemap) && stplyr == &players[displayplayer])
ST_drawSpecialStageHUD();
// Emerald Hunt Indicators
if (cv_itemfinder.value && M_SecretUnlocked(SECRET_ITEMFINDER))
ST_doItemFinderIconsAndSound();
@ -2360,15 +2407,18 @@ static void ST_overlayDrawer(void)
}
// This is where we draw all the fun cheese if you have the chasecam off!
if ((stplyr == &players[displayplayer] && !camera.chase)
|| ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase))
if (!(maptol & TOL_NIGHTS))
{
ST_drawFirstPersonHUD();
if (cv_powerupdisplay.value)
if ((stplyr == &players[displayplayer] && !camera.chase)
|| ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase))
{
ST_drawFirstPersonHUD();
if (cv_powerupdisplay.value)
ST_drawPowerupHUD();
}
else if (cv_powerupdisplay.value == 2)
ST_drawPowerupHUD();
}
else if (cv_powerupdisplay.value == 2)
ST_drawPowerupHUD();
}
#ifdef HAVE_BLUA

View file

@ -1624,7 +1624,7 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string)
{
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, center = 0, left = 0;
const char *ch = string;
INT32 charflags = 0;
INT32 charflags = (option & V_CHARCOLORMASK);
const UINT8 *colormap = NULL;
INT32 spacewidth = 4, charwidth = 0;
@ -1644,8 +1644,6 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string)
left = (scrwidth - BASEVIDWIDTH)/2;
}
charflags = (option & V_CHARCOLORMASK);
switch (option & V_SPACINGMASK)
{
case V_MONOSPACE:
@ -2154,8 +2152,10 @@ INT32 V_CreditStringWidth(const char *string)
//
void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string)
{
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth = BASEVIDWIDTH;
INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, left = 0;
const char *ch = string;
INT32 charflags = (option & V_CHARCOLORMASK);
const UINT8 *colormap = NULL;
if (option & V_NOSCALESTART)
{
@ -2164,21 +2164,31 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string)
scrwidth = vid.width;
}
else
dupx = dupy = 1;
for (;;)
{
c = *ch++;
if (!c)
dupx = dupy = 1;
scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2;
}
for (;;ch++)
{
if (!*ch)
break;
if (c == '\n')
if (*ch & 0x80) //color parsing -x 2.16.09
{
// manually set flags override color codes
if (!(option & V_CHARCOLORMASK))
charflags = ((*ch & 0x7f) << V_CHARCOLORSHIFT) & V_CHARCOLORMASK;
continue;
}
if (*ch == '\n')
{
cx = x;
cy += 12*dupy;
continue;
}
c = toupper(c) - LT_FONTSTART;
c = toupper(*ch) - LT_FONTSTART;
if (c < 0 || c >= LT_FONTSIZE || !lt_font[c])
{
cx += 16*dupx;
@ -2186,17 +2196,19 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string)
}
w = SHORT(lt_font[c]->width) * dupx;
if (cx + w > scrwidth)
break;
if (cx+left > scrwidth)
break;
//left boundary check
if (cx < 0)
if (cx+left + w < 0)
{
cx += w;
continue;
}
V_DrawScaledPatch(cx, cy, option, lt_font[c]);
colormap = V_GetStringColormap(charflags);
V_DrawFixedPatch(cx<<FRACBITS, cy<<FRACBITS, FRACUNIT, option, lt_font[c], colormap);
cx += w;
}
}
@ -2210,6 +2222,8 @@ INT32 V_LevelNameWidth(const char *string)
for (i = 0; i < strlen(string); i++)
{
if (string[i] & 0x80)
continue;
c = toupper(string[i]) - LT_FONTSTART;
if (c < 0 || c >= LT_FONTSIZE || !lt_font[c])
w += 16;
@ -2265,11 +2279,9 @@ INT32 V_StringWidth(const char *string, INT32 option)
for (i = 0; i < strlen(string); i++)
{
c = string[i];
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09
if (string[i] & 0x80)
continue;
c = toupper(c) - HU_FONTSTART;
c = toupper(string[i]) - HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
w += spacewidth;
else
@ -2307,11 +2319,9 @@ INT32 V_SmallStringWidth(const char *string, INT32 option)
for (i = 0; i < strlen(string); i++)
{
c = string[i];
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09
if (string[i] & 0x80)
continue;
c = toupper(c) - HU_FONTSTART;
c = toupper(string[i]) - HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
w += spacewidth;
else
@ -2346,11 +2356,9 @@ INT32 V_ThinStringWidth(const char *string, INT32 option)
for (i = 0; i < strlen(string); i++)
{
c = string[i];
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09
if (string[i] & 0x80)
continue;
c = toupper(c) - HU_FONTSTART;
c = toupper(string[i]) - HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE || !tny_font[c])
w += spacewidth;
else

View file

@ -194,11 +194,11 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum)
for (; posStart < posEnd; posStart++)
LUA_LoadLump(wadnum, posStart);
}
posStart = W_CheckNumForFolderStartPK3("SOCs/", wadnum, 0);
posStart = W_CheckNumForFolderStartPK3("SOC/", wadnum, 0);
if (posStart != INT16_MAX)
{
posEnd = W_CheckNumForFolderEndPK3("SOCs/", wadnum, posStart);
posStart++; // first "lump" will be "SOCs/" folder itself, so ignore it
posEnd = W_CheckNumForFolderEndPK3("SOC/", wadnum, posStart);
posStart++; // first "lump" will be "SOC/" folder itself, so ignore it
for(; posStart < posEnd; posStart++)
{
lumpinfo_t *lump_p = &wadfiles[wadnum]->lumpinfo[posStart];

View file

@ -77,8 +77,8 @@ typedef union
struct
{
char passed1[29]; // KNUCKLES GOT / CRAWLA HONCHO
char passed2[17]; // A CHAOS EMERALD / GOT THEM ALL!
char passed1[29]; // KNUCKLES GOT / CRAWLA HONCHO
char passed2[17]; // A CHAOS EMERALD? / GOT THEM ALL!
char passed3[15]; // CAN NOW BECOME
char passed4[SKINNAMESIZE+7]; // SUPER CRAWLA HONCHO
INT32 passedx1;
@ -315,6 +315,9 @@ void Y_IntermissionDrawer(void)
INT32 xoffset1 = 0; // Line 1 x offset
INT32 xoffset2 = 0; // Line 2 x offset
INT32 xoffset3 = 0; // Line 3 x offset
INT32 xoffset4 = 0; // Line 4 x offset
INT32 xoffset5 = 0; // Line 5 x offset
INT32 xoffset6 = 0; // Line 6 x offset
UINT8 drawsection = 0;
if (gottoken) // first to be behind everything else
@ -324,71 +327,130 @@ void Y_IntermissionDrawer(void)
if (intertic <= 2*TICRATE)
animatetic = 0;
else if (!animatetic && data.spec.bonus.points == 0 && data.spec.passed3[0] != '\0')
animatetic = intertic;
animatetic = intertic + TICRATE;
if (animatetic)
if (animatetic && (tic_t)intertic >= animatetic)
{
const INT32 scradjust = (vid.width/vid.dupx)>>3; // 40 for BASEVIDWIDTH
INT32 animatetimer = (intertic - animatetic);
if (animatetimer <= 8)
if (animatetimer <= 14)
{
xoffset1 = -(animatetimer * 40);
xoffset2 = -((animatetimer-2) * 40);
xoffset1 = -(animatetimer * scradjust);
xoffset2 = -((animatetimer-2) * scradjust);
xoffset3 = -((animatetimer-4) * scradjust);
xoffset4 = -((animatetimer-6) * scradjust);
xoffset5 = -((animatetimer-8) * scradjust);
if (xoffset2 > 0) xoffset2 = 0;
if (xoffset3 > 0) xoffset3 = 0;
if (xoffset4 > 0) xoffset4 = 0;
if (xoffset5 > 0) xoffset5 = 0;
}
else if (animatetimer <= 19)
else if (animatetimer < 32)
{
drawsection = 1;
xoffset1 = (16-animatetimer) * 40;
xoffset2 = (18-animatetimer) * 40;
xoffset3 = (20-animatetimer) * 40;
xoffset1 = (22-animatetimer) * scradjust;
xoffset2 = (24-animatetimer) * scradjust;
xoffset3 = (26-animatetimer) * scradjust;
xoffset4 = (28-animatetimer) * scradjust;
xoffset5 = (30-animatetimer) * scradjust;
xoffset6 = (32-animatetimer) * scradjust;
if (xoffset1 < 0) xoffset1 = 0;
if (xoffset2 < 0) xoffset2 = 0;
if (xoffset3 < 0) xoffset3 = 0;
if (xoffset4 < 0) xoffset4 = 0;
if (xoffset5 < 0) xoffset5 = 0;
}
else
{
drawsection = 1;
if (animatetimer == 32)
S_StartSound(NULL, sfx_s3k68);
}
}
if (drawsection == 1)
{
const char *ringtext = "\x86" "50 RINGS, NO SHIELD";
const char *tut1text = "\x86" "PRESS " "\x82" "SPIN";
const char *tut2text = "\x86" "MID-" "\x82" "JUMP";
ttheight = 16;
V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1);
ttheight += V_LevelNameHeight(data.spec.passed3) + 2;
V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3);
ttheight += V_LevelNameHeight(data.spec.passed4) + 2;
V_DrawLevelTitle(data.spec.passedx4 + xoffset3, ttheight, 0, data.spec.passed4);
}
else if (data.spec.passed1[0] != '\0')
{
ttheight = 24;
V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1);
ttheight += V_LevelNameHeight(data.spec.passed2) + 2;
V_DrawLevelTitle(data.spec.passedx2 + xoffset2, ttheight, 0, data.spec.passed2);
ttheight = 108;
V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset4 - (V_LevelNameWidth(ringtext)/2), ttheight, 0, ringtext);
ttheight += V_LevelNameHeight(ringtext) + 2;
V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset5 - (V_LevelNameWidth(tut1text)/2), ttheight, 0, tut1text);
ttheight += V_LevelNameHeight(tut1text) + 2;
V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset6 - (V_LevelNameWidth(tut2text)/2), ttheight, 0, tut2text);
}
else
{
ttheight = 24 + (V_LevelNameHeight(data.spec.passed2)/2) + 2;
V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2);
if (data.spec.passed1[0] != '\0')
{
ttheight = 24;
V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1);
ttheight += V_LevelNameHeight(data.spec.passed2) + 2;
V_DrawLevelTitle(data.spec.passedx2 + xoffset2, ttheight, 0, data.spec.passed2);
}
else
{
ttheight = 24 + (V_LevelNameHeight(data.spec.passed2)/2) + 2;
V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2);
}
V_DrawScaledPatch(152 + xoffset3, 108, 0, data.spec.bonuspatch);
V_DrawTallNum(BASEVIDWIDTH + xoffset3 - 68, 109, 0, data.spec.bonus.points);
V_DrawScaledPatch(152 + xoffset4, 124, 0, data.spec.pscore);
V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125, 0, data.spec.score);
// Draw continues!
if (!multiplayer /* && (data.spec.continues & 0x80) */) // Always draw outside of netplay
{
UINT8 continues = data.spec.continues & 0x7F;
V_DrawScaledPatch(152 + xoffset5, 150, 0, data.spec.pcontinues);
for (i = 0; i < continues; ++i)
{
if ((data.spec.continues & 0x80) && i == continues-1 && (endtic < 0 || intertic%20 < 10))
break;
V_DrawContinueIcon(246 + xoffset5 - (i*12), 162, 0, *data.spec.playerchar, *data.spec.playercolor);
}
}
}
// draw the emeralds
//if (intertic & 1)
{
boolean drawthistic = !(ALL7EMERALDS(emeralds) && (intertic & 1));
INT32 emeraldx = 152 - 3*28;
INT32 em = (gamemap - sstage_start);
INT32 em = P_GetNextEmerald();
for (i = 0; i < 7; ++i)
if (em == 7)
{
if ((i != em) && !(intertic & 1) && (emeralds & (1 << i)))
V_DrawScaledPatch(emeraldx, 74, 0, emeraldpics[0][i]);
emeraldx += 28;
if (!stagefailed)
{
fixed_t adjust = 2*(FINESINE(FixedAngle((intertic + 1)<<(FRACBITS-4)) & FINEMASK));
V_DrawFixedPatch(152<<FRACBITS, (74<<FRACBITS) - adjust, FRACUNIT, 0, emeraldpics[0][em], NULL);
}
}
if (em < 7)
else if (em < 7)
{
static UINT8 emeraldbounces = 0;
static INT32 emeraldmomy = 20;
static INT32 emeraldy = -40;
if (drawthistic)
for (i = 0; i < 7; ++i)
{
if ((i != em) && (emeralds & (1 << i)))
V_DrawScaledPatch(emeraldx, 74, 0, emeraldpics[0][i]);
emeraldx += 28;
}
emeraldx = 152 + (em-3)*28;
if (intertic <= 1)
@ -399,7 +461,7 @@ void Y_IntermissionDrawer(void)
}
else
{
if (emeralds & (1 << em))
if (!stagefailed)
{
if (emeraldbounces < 3)
{
@ -427,29 +489,11 @@ void Y_IntermissionDrawer(void)
emeraldy = 74;
}
}
V_DrawScaledPatch(emeraldx, emeraldy, 0, emeraldpics[0][em]);
if (drawthistic)
V_DrawScaledPatch(emeraldx, emeraldy, 0, emeraldpics[0][em]);
}
}
}
V_DrawScaledPatch(152, 108, 0, data.spec.bonuspatch);
V_DrawTallNum(BASEVIDWIDTH - 68, 109, 0, data.spec.bonus.points);
V_DrawScaledPatch(152, 124, 0, data.spec.pscore);
V_DrawTallNum(BASEVIDWIDTH - 68, 125, 0, data.spec.score);
// Draw continues!
if (!multiplayer /* && (data.spec.continues & 0x80) */) // Always draw outside of netplay
{
UINT8 continues = data.spec.continues & 0x7F;
V_DrawScaledPatch(152, 150, 0, data.spec.pcontinues);
for (i = 0; i < continues; ++i)
{
if ((data.spec.continues & 0x80) && i == continues-1 && (endtic < 0 || intertic%20 < 10))
break;
V_DrawContinueIcon(246 - (i*12), 162, 0, *data.spec.playerchar, *data.spec.playercolor);
}
}
}
else if (intertype == int_match || intertype == int_race)
{
@ -831,7 +875,7 @@ void Y_Ticker(void)
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback)
{
if (M_UpdateUnlockablesAndExtraEmblems())
S_StartSound(NULL, sfx_ncitem);
S_StartSound(NULL, sfx_s3k68);
G_SaveGameData();
}
@ -850,7 +894,7 @@ void Y_Ticker(void)
{
INT32 i;
UINT32 oldscore = data.spec.score;
boolean skip = false;
boolean skip = false, super = false;
if (!intertic) // first time only
{
@ -862,15 +906,22 @@ void Y_Ticker(void)
return;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && (players[i].cmd.buttons & BT_USE))
skip = true;
if (playeringame[i])
{
if (players[i].cmd.buttons & BT_USE)
skip = true;
if (players[i].charflags & SF_SUPER)
super = true;
}
if ((data.spec.continues & 0x80) && tallydonetic != -1)
if (tallydonetic != -1 && ((data.spec.continues & 0x80) || (super && ALL7EMERALDS(emeralds))))
{
if ((intertic - tallydonetic) > (3*TICRATE)/2)
{
endtic = intertic + 4*TICRATE; // 4 second pause after end of tally
S_StartSound(NULL, sfx_s3kac); // bingly-bingly-bing!
if (data.spec.continues & 0x80)
S_StartSound(NULL, sfx_s3kac); // bingly-bingly-bing!
}
return;
}
@ -887,7 +938,7 @@ void Y_Ticker(void)
if (!data.spec.bonus.points)
{
tallydonetic = intertic;
if (!(data.spec.continues & 0x80)) // don't set endtic yet!
if (!((data.spec.continues & 0x80) || (super && ALL7EMERALDS(emeralds)))) // don't set endtic yet!
endtic = intertic + 4*TICRATE; // 4 second pause after end of tally
S_StartSound(NULL, (gottoken ? sfx_token : sfx_chchng)); // cha-ching!
@ -896,7 +947,7 @@ void Y_Ticker(void)
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback)
{
if (M_UpdateUnlockablesAndExtraEmblems())
S_StartSound(NULL, sfx_ncitem);
S_StartSound(NULL, sfx_s3k68);
G_SaveGameData();
}
@ -1286,7 +1337,7 @@ void Y_StartIntermission(void)
data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0';
strcpy(data.spec.passed2, "GOT THEM ALL!");
if (skins[players[consoleplayer].skin].flags & SF_SUPER)
if (players[consoleplayer].charflags & SF_SUPER)
{
strcpy(data.spec.passed3, "CAN NOW BECOME");
snprintf(data.spec.passed4,
@ -1307,6 +1358,11 @@ void Y_StartIntermission(void)
else
strcpy(data.spec.passed1, "YOU GOT");
strcpy(data.spec.passed2, "A CHAOS EMERALD");
if (P_GetNextEmerald() > 6)
{
data.spec.passed2[15] = '?';
data.spec.passed2[16] = '\0';
}
}
data.spec.passedx1 = (BASEVIDWIDTH - V_LevelNameWidth(data.spec.passed1))/2;
data.spec.passedx2 = (BASEVIDWIDTH - V_LevelNameWidth(data.spec.passed2))/2;
@ -1745,7 +1801,7 @@ static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct)
if (!playeringame[i]) continue;
sharedringtotal += players[i].rings;
}
if (!sharedringtotal || sharedringtotal < nummaprings)
if (!sharedringtotal || nummaprings == -1 || sharedringtotal < nummaprings)
data.coop.gotperfbonus = 0;
else
data.coop.gotperfbonus = 1;
@ -1857,7 +1913,7 @@ static void Y_AwardSpecialStageBonus(void)
if (!playeringame[i] || players[i].lives < 1) // not active or game over
Y_SetNullBonus(&players[i], &localbonus);
else if (useNightsSS) // Link instead of Score
else if (maptol & TOL_NIGHTS) // Link instead of Rings
Y_SetLinkBonus(&players[i], &localbonus);
else
Y_SetRingBonus(&players[i], &localbonus);