Merge branch 'master' into hud-n-menu-tidbits

# Conflicts:
#	src/m_menu.c
#	src/screen.c
#	src/st_stuff.c
This commit is contained in:
Monster Iestyn 2018-08-28 20:51:46 +01:00
commit 1af8d3ac02
68 changed files with 20601 additions and 14972 deletions

View file

@ -57,49 +57,6 @@ matrix:
- gcc-4.8 - gcc-4.8
compiler: gcc-4.8 compiler: gcc-4.8
#gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5 #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5
- os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- libsdl2-mixer-dev
- libpng-dev
- libgl1-mesa-dev
- libgme-dev
- p7zip-full
- gcc-4.9
compiler: gcc-4.9
#gcc-4.9 (Ubuntu 4.9.3-8ubuntu2~14.04) 4.9.3
- os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- libsdl2-mixer-dev
- libpng-dev
- libgl1-mesa-dev
- libgme-dev
- p7zip-full
- gcc-5
compiler: gcc-5
#gcc-5 (Ubuntu 5.3.0-3ubuntu1~14.04) 5.3.0 20151204
- os: linux
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- libsdl2-mixer-dev
- libpng-dev
- libgl1-mesa-dev
- libgme-dev
- p7zip-full
- gcc-6
compiler: gcc-6
env: WFLAGS="-Wno-tautological-compare"
#gcc-6 (Ubuntu 6.1.1-3ubuntu11~14.04.1) 6.1.1 20160511
- os: linux - os: linux
addons: addons:
apt: apt:

View file

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

View file

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

View file

@ -8,7 +8,7 @@
UINT8 cdaudio_started = 0; UINT8 cdaudio_started = 0;
consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};

View file

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

View file

@ -16,7 +16,7 @@
#define ASSET_HASH_RINGS_DTA "${SRB2_ASSET_rings.dta_HASH}" #define ASSET_HASH_RINGS_DTA "${SRB2_ASSET_rings.dta_HASH}"
#define ASSET_HASH_ZONES_DTA "${SRB2_ASSET_zones.dta_HASH}" #define ASSET_HASH_ZONES_DTA "${SRB2_ASSET_zones.dta_HASH}"
#ifdef USE_PATCH_DTA #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 #endif
#define SRB2_COMP_REVISION "${SRB2_COMP_REVISION}" #define SRB2_COMP_REVISION "${SRB2_COMP_REVISION}"
@ -36,7 +36,7 @@
#define ASSET_HASH_PLAYER_DTA "cfca0f1c73023cbbd8f844f45480f799" #define ASSET_HASH_PLAYER_DTA "cfca0f1c73023cbbd8f844f45480f799"
#define ASSET_HASH_RINGS_DTA "85901ad4bf94637e5753d2ac2c03ea26" #define ASSET_HASH_RINGS_DTA "85901ad4bf94637e5753d2ac2c03ea26"
#ifdef USE_PATCH_DTA #ifdef USE_PATCH_DTA
#define ASSET_HASH_PATCH_DTA "dbbf8bc6121618ee3be2d5b14650429b" #define ASSET_HASH_PATCH_PK3 "dbbf8bc6121618ee3be2d5b14650429b"
#endif #endif
#endif #endif

View file

@ -312,7 +312,7 @@ static void CON_SetupColormaps(void)
colset(lgreenmap, 97, 98, 106); colset(lgreenmap, 97, 98, 106);
colset(bluemap, 146, 147, 155); colset(bluemap, 146, 147, 155);
colset(redmap, 210, 32, 39); colset(redmap, 210, 32, 39);
colset(graymap, 8, 10, 15); colset(graymap, 6, 8, 14);
colset(orangemap, 51, 52, 57); colset(orangemap, 51, 52, 57);
colset(skymap, 129, 130, 133); colset(skymap, 129, 130, 133);
colset(purplemap, 160, 161, 163); 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)); 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]); CONS_Alert(CONS_WARNING, M_GetText("Got unknown net command [%s]=%d (max %d)\n"), sizeu1(curpos - bufferstart), *curpos, bufferstart[0]);
D_FreeTextcmd(gametic); break;
return;
} }
} }
} }
@ -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]); rsp->powers[j] = (UINT16)SHORT(players[i].powers[j]);
// Score is resynched in the rspfirm resync packet // 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->lives = players[i].lives;
rsp->continues = players[i].continues; rsp->continues = players[i].continues;
rsp->scoreadd = players[i].scoreadd; 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]); players[i].powers[j] = (UINT16)SHORT(rsp->powers[j]);
// Score is resynched in the rspfirm resync packet // 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].lives = rsp->lives;
players[i].continues = rsp->continues; players[i].continues = rsp->continues;
players[i].scoreadd = rsp->scoreadd; players[i].scoreadd = rsp->scoreadd;
@ -2377,11 +2378,11 @@ static void CL_RemovePlayer(INT32 playernum)
if (gametype == GT_CTF) if (gametype == GT_CTF)
P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you! 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. // the remaining players.
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
{ {
INT32 i, count, increment, rings; INT32 i, count, increment, spheres;
for (i = 0, count = 0; i < MAXPLAYERS; i++) for (i = 0, count = 0; i < MAXPLAYERS; i++)
{ {
@ -2390,19 +2391,19 @@ static void CL_RemovePlayer(INT32 playernum)
} }
count--; count--;
rings = players[playernum].rings; spheres = players[playernum].spheres;
increment = rings/count; increment = spheres/count;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] && i != playernum) if (playeringame[i] && i != playernum)
{ {
if (rings < increment) if (spheres < increment)
P_GivePlayerRings(&players[i], rings); P_GivePlayerSpheres(&players[i], spheres);
else 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; localtextcmd[0] = 0;
localtextcmd2[0] = 0; localtextcmd2[0] = 0;
for (i = 0; i < BACKUPTICS; i++) for (i = firstticstosend; i < firstticstosend + BACKUPTICS; i++)
D_Clearticcmd(i); D_Clearticcmd(i);
consoleplayer = 0; consoleplayer = 0;

View file

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

View file

@ -850,7 +850,7 @@ static void IdentifyVersion(void)
#ifdef USE_PATCH_DTA #ifdef USE_PATCH_DTA
// Add our crappy patches to fix our bugs // Add our crappy patches to fix our bugs
D_AddFile(va(pandf,srb2waddir,"patch.dta")); D_AddFile(va(pandf,srb2waddir,"patch.pk3"));
#endif #endif
#if !defined (HAVE_SDL) || defined (HAVE_MIXER) #if !defined (HAVE_SDL) || defined (HAVE_MIXER)
@ -1044,15 +1044,6 @@ void D_SRB2Main(void)
if (M_CheckParm("-password") && M_IsNextParm()) if (M_CheckParm("-password") && M_IsNextParm())
D_SetPassword(M_GetNextParm()); 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 // add any files specified on the command line with -file wadfile
// to the wad list // to the wad list
@ -1136,7 +1127,7 @@ void D_SRB2Main(void)
//W_VerifyFileMD5(1, ASSET_HASH_ZONES_DTA); // zones.dta //W_VerifyFileMD5(1, ASSET_HASH_ZONES_DTA); // zones.dta
//W_VerifyFileMD5(2, ASSET_HASH_PLAYER_DTA); // player.dta //W_VerifyFileMD5(2, ASSET_HASH_PLAYER_DTA); // player.dta
#ifdef USE_PATCH_DTA #ifdef USE_PATCH_DTA
W_VerifyFileMD5(3, ASSET_HASH_PATCH_DTA); // patch.dta //W_VerifyFileMD5(3, ASSET_HASH_PATCH_PK3); // patch.pk3
#endif #endif
// don't check music.dta because people like to modify it, and it doesn't matter if they do // don't check music.dta because people like to modify it, and it doesn't matter if they do
@ -1145,7 +1136,7 @@ void D_SRB2Main(void)
mainwads = 3; // there are 3 wads not to unload mainwads = 3; // there are 3 wads not to unload
#ifdef USE_PATCH_DTA #ifdef USE_PATCH_DTA
++mainwads; // patch.dta adds one more ++mainwads; // patch.pk3 adds one more
#endif #endif
#ifdef DEVELOP #ifdef DEVELOP
++mainwads; // music_new, too ++mainwads; // music_new, too

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}; 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}}; static CV_PossibleValue_t timetic_cons_t[] = {{0, "Classic"}, {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 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}}; 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}; consvar_t cv_powerupdisplay = {"powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@ -811,6 +811,7 @@ void D_RegisterClientCommands(void)
COM_AddCommand("writethings", Command_Writethings_f); COM_AddCommand("writethings", Command_Writethings_f);
CV_RegisterVar(&cv_speed); CV_RegisterVar(&cv_speed);
CV_RegisterVar(&cv_opflags); CV_RegisterVar(&cv_opflags);
CV_RegisterVar(&cv_ophoopflags);
CV_RegisterVar(&cv_mapthingnum); CV_RegisterVar(&cv_mapthingnum);
// CV_RegisterVar(&cv_grid); // CV_RegisterVar(&cv_grid);
// CV_RegisterVar(&cv_snapto); // CV_RegisterVar(&cv_snapto);
@ -822,6 +823,7 @@ void D_RegisterClientCommands(void)
COM_AddCommand("getallemeralds", Command_Getallemeralds_f); COM_AddCommand("getallemeralds", Command_Getallemeralds_f);
COM_AddCommand("resetemeralds", Command_Resetemeralds_f); COM_AddCommand("resetemeralds", Command_Resetemeralds_f);
COM_AddCommand("setrings", Command_Setrings_f); COM_AddCommand("setrings", Command_Setrings_f);
COM_AddCommand("setspheres", Command_Setspheres_f);
COM_AddCommand("setlives", Command_Setlives_f); COM_AddCommand("setlives", Command_Setlives_f);
COM_AddCommand("setcontinues", Command_Setcontinues_f); COM_AddCommand("setcontinues", Command_Setcontinues_f);
COM_AddCommand("devmode", Command_Devmode_f); COM_AddCommand("devmode", Command_Devmode_f);
@ -2682,8 +2684,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
// Clear player score and rings if a spectator. // Clear player score and rings if a spectator.
if (players[playernum].spectator) if (players[playernum].spectator)
{ {
players[playernum].score = 0; players[playernum].score = players[playernum].rings = 0;
players[playernum].rings = 0;
if (players[playernum].mo) if (players[playernum].mo)
players[playernum].mo->health = 1; players[playernum].mo->health = 1;
} }
@ -2725,10 +2726,12 @@ static void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt,
#define BASESALT "basepasswordstorage" #define BASESALT "basepasswordstorage"
static UINT8 adminpassmd5[16]; static UINT8 adminpassmd5[16];
static boolean adminpasswordset = false;
void D_SetPassword(const char *pw) void D_SetPassword(const char *pw)
{ {
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &adminpassmd5); D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &adminpassmd5);
adminpasswordset = true;
} }
// Remote Administration // Remote Administration
@ -2800,6 +2803,12 @@ static void Got_Login(UINT8 **cp, INT32 playernum)
if (client) if (client)
return; return;
if (!adminpasswordset)
{
CONS_Printf(M_GetText("Password from %s failed (no password set).\n"), player_names[playernum]);
return;
}
// Do the final pass to compare with the sent md5 // Do the final pass to compare with the sent md5
D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", playernum), &finalmd5); D_MD5PasswordPass(adminpassmd5, 16, va("PNUM%02d", playernum), &finalmd5);
@ -3911,28 +3920,7 @@ static void Command_ExitLevel_f(void)
else if (gamestate != GS_LEVEL || demoplayback) else if (gamestate != GS_LEVEL || demoplayback)
CONS_Printf(M_GetText("You must be in a level to use this.\n")); CONS_Printf(M_GetText("You must be in a level to use this.\n"));
else 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); SendNetXCmd(XD_EXITLEVEL, NULL, 0);
}
} }
static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum) static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum)
@ -4047,7 +4035,7 @@ static void Command_RestartAudio_f(void)
I_ShutdownSound(); I_ShutdownSound();
I_StartupSound(); I_StartupSound();
I_InitMusic(); I_InitMusic();
// These must be called or no sound and music until manually set. // These must be called or no sound and music until manually set.
I_SetSfxVolume(cv_soundvolume.value); I_SetSfxVolume(cv_soundvolume.value);
@ -4055,7 +4043,7 @@ static void Command_RestartAudio_f(void)
I_SetMIDIMusicVolume(cv_midimusicvolume.value); I_SetMIDIMusicVolume(cv_midimusicvolume.value);
if (Playing()) // Gotta make sure the player is in a level if (Playing()) // Gotta make sure the player is in a level
P_RestoreMusic(&players[consoleplayer]); P_RestoreMusic(&players[consoleplayer]);
} }
/** Quits a game and returns to the title screen. /** Quits a game and returns to the title screen.

View file

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

File diff suppressed because it is too large Load diff

View file

@ -50,7 +50,7 @@ static boolean wasPlaying;
static int cdVolume=0; // current cd volume (0-31) static int cdVolume=0; // current cd volume (0-31)
// 0-31 like Music & Sfx, though CD hardware volume is 0-255. // 0-31 like Music & Sfx, though CD hardware volume is 0-255.
consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// allow Update for next/loop track // allow Update for next/loop track
// some crap cd drivers take up to // some crap cd drivers take up to

View file

@ -46,6 +46,9 @@ enum
ML_BLOCKMAP, // LUT, motion clipping, walls/grid element ML_BLOCKMAP, // LUT, motion clipping, walls/grid element
}; };
// Extra flag for objects.
#define MTF_EXTRA 1
// Reverse gravity flag for objects. // Reverse gravity flag for objects.
#define MTF_OBJECTFLIP 2 #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. /// 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. /// \note Required for proper collision with moving sloped surfaces that have sector specials on them.
//#define SECTORSPECIALSAFTERTHINK #define SECTORSPECIALSAFTERTHINK
#endif // __DOOMDEF__ #endif // __DOOMDEF__

View file

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

View file

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

View file

@ -116,20 +116,18 @@ INT32 secondarydisplayplayer; // for splitscreen
tic_t gametic; tic_t gametic;
tic_t levelstarttic; // gametic at level start 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) INT16 lastmap; // last level you were at (returning from special stages)
tic_t timeinmap; // Ticker for time spent in level (used for levelcard display) tic_t timeinmap; // Ticker for time spent in level (used for levelcard display)
INT16 spstage_start; INT16 spstage_start;
INT16 sstage_start; INT16 sstage_start, sstage_end, smpstage_start, smpstage_end;
INT16 sstage_end;
INT16 titlemap = 0; INT16 titlemap = 0;
boolean hidetitlepics = false; boolean hidetitlepics = false;
INT16 bootmap; //bootmap for loading a map on startup INT16 bootmap; //bootmap for loading a map on startup
boolean looptitle = false; boolean looptitle = false;
boolean useNightsSS = false;
UINT8 skincolor_redteam = SKINCOLOR_RED; UINT8 skincolor_redteam = SKINCOLOR_RED;
UINT8 skincolor_blueteam = SKINCOLOR_BLUE; UINT8 skincolor_blueteam = SKINCOLOR_BLUE;
@ -2230,7 +2228,7 @@ void G_PlayerReborn(INT32 player)
p->pflags |= PF_JUMPDOWN; p->pflags |= PF_JUMPDOWN;
p->playerstate = PST_LIVE; p->playerstate = PST_LIVE;
p->rings = 0; // 0 rings p->rings = p->spheres = 0; // 0 rings
p->panim = PA_IDLE; // standing animation p->panim = PA_IDLE; // standing animation
//if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there //if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there
@ -2825,7 +2823,11 @@ INT32 G_GetGametypeByName(const char *gametypestr)
// //
boolean G_IsSpecialStage(INT32 mapnum) 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 true;
return false; return false;
@ -3053,21 +3055,14 @@ static void G_DoCompleted(void)
{ {
token--; token--;
if (!(emeralds & EMERALD1)) for (i = 0; i < 7; i++)
nextmap = (INT16)(sstage_start - 1); // Special Stage 1 if (!(emeralds & (1<<i)))
else if (!(emeralds & EMERALD2)) {
nextmap = (INT16)(sstage_start); // Special Stage 2 nextmap = ((netgame || multiplayer) ? smpstage_start : sstage_start) + i - 1; // to special stage!
else if (!(emeralds & EMERALD3)) break;
nextmap = (INT16)(sstage_start + 1); // Special Stage 3 }
else if (!(emeralds & EMERALD4))
nextmap = (INT16)(sstage_start + 2); // Special Stage 4 if (i == 7)
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
gottoken = false; gottoken = false;
} }
@ -3239,9 +3234,9 @@ void G_LoadGameSettings(void)
{ {
// defaults // defaults
spstage_start = 1; spstage_start = 1;
sstage_start = 50; sstage_start = smpstage_start = 50;
sstage_end = 57; // 8 special stages in vanilla SRB2 sstage_end = smpstage_end = 56; // 7 special stages in vanilla SRB2
useNightsSS = false; //true; sstage_end++; // plus one weirdo
// initialize free sfx slots for skin sounds // initialize free sfx slots for skin sounds
S_InitRuntimeSounds(); S_InitRuntimeSounds();
@ -4701,6 +4696,7 @@ void G_GhostTicker(void)
p->next = g->next; p->next = g->next;
else else
ghosts = g->next; ghosts = g->next;
Z_Free(g);
continue; continue;
} }
p = g; p = g;
@ -5701,29 +5697,28 @@ void G_AddGhost(char *defdemoname)
mthing = playerstarts[0]; mthing = playerstarts[0];
I_Assert(mthing); I_Assert(mthing);
{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling. { // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
fixed_t x,y,z; fixed_t z,f,c;
sector_t *sector; gh->mo = P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST);
x = mthing->x << FRACBITS; gh->mo->angle = FixedAngle(mthing->angle*FRACUNIT);
y = mthing->y << FRACBITS; f = gh->mo->floorz;
sector = R_PointInSubsector(x, y)->sector; c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height;
if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP)) if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP))
{ {
z = sector->ceilingheight - mobjinfo[MT_PLAYER].height; z = c;
if (mthing->options >> ZSHIFT) if (mthing->options >> ZSHIFT)
z -= ((mthing->options >> ZSHIFT) << FRACBITS); z -= ((mthing->options >> ZSHIFT) << FRACBITS);
if (z < sector->floorheight) if (z < f)
z = sector->floorheight; z = f;
} }
else else
{ {
z = sector->floorheight; z = f;
if (mthing->options >> ZSHIFT) if (mthing->options >> ZSHIFT)
z += ((mthing->options >> ZSHIFT) << FRACBITS); z += ((mthing->options >> ZSHIFT) << FRACBITS);
if (z > sector->ceilingheight - mobjinfo[MT_PLAYER].height) if (z > c)
z = sector->ceilingheight - mobjinfo[MT_PLAYER].height; z = c;
} }
gh->mo = P_SpawnMobj(x, y, z, MT_GHOST); gh->mo->z = z;
gh->mo->angle = FixedAngle(mthing->angle*FRACUNIT);
} }
gh->oldmo.x = gh->mo->x; gh->oldmo.x = gh->mo->x;
@ -5922,8 +5917,14 @@ boolean G_CheckDemoStatus(void)
{ {
boolean saved; boolean saved;
if(ghosts) // ... ... ... while (ghosts)
ghosts = NULL; // :) {
demoghost *next = ghosts->next;
Z_Free(ghosts);
ghosts = next;
}
ghosts = NULL;
// DO NOT end metal sonic demos here // DO NOT end metal sonic demos here

View file

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

View file

@ -2115,27 +2115,34 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
} }
else else
{ {
#ifdef ESLOPE // P.S. this is better-organized than the old version fixed_t texturevpeg;
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);
// 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) if (newline)
{ {
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset) * grTex->scaleY; texturevpeg = sides[newline->sidenum[0]].rowoffset;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[newline->sidenum[0]].rowoffset)) * grTex->scaleY; if (newline->flags & ML_DONTPEGBOTTOM)
texturevpeg -= *rover->topheight - *rover->bottomheight;
} }
else else
{ {
wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset) * grTex->scaleY; texturevpeg = sides[rover->master->sidenum[0]].rowoffset;
wallVerts[0].t = wallVerts[1].t = (h - l + (*rover->topheight - h + sides[rover->master->sidenum[0]].rowoffset)) * grTex->scaleY; 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 #endif
wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
@ -4072,7 +4079,7 @@ static void HWR_DrawSpriteShadow(gr_vissprite_t *spr, GLPatch_t *gpatch, float t
angle_t shadowdir; angle_t shadowdir;
// Set direction // Set direction
if (splitscreen && stplyr != &players[displayplayer]) if (splitscreen && stplyr == &players[secondarydisplayplayer])
shadowdir = localangle2 + FixedAngle(cv_cam2_rotate.value); shadowdir = localangle2 + FixedAngle(cv_cam2_rotate.value);
else else
shadowdir = localangle + FixedAngle(cv_cam_rotate.value); shadowdir = localangle + FixedAngle(cv_cam_rotate.value);
@ -5480,7 +5487,10 @@ static void HWR_ProjectSprite(mobj_t *thing)
} }
heightsec = thing->subsector->sector->heightsec; 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 if (heightsec != -1 && phs != -1) // only clip things which are in special sectors
{ {

View file

@ -69,6 +69,7 @@ patch_t *nightsnum[10]; // 0-9
// Level title and credits fonts // Level title and credits fonts
patch_t *lt_font[LT_FONTSIZE]; patch_t *lt_font[LT_FONTSIZE];
patch_t *cred_font[CRED_FONTSIZE]; patch_t *cred_font[CRED_FONTSIZE];
patch_t *ttlnum[20]; // act numbers (0-19)
static player_t *plr; static player_t *plr;
boolean chat_on; // entering a chat message? boolean chat_on; // entering a chat message?
@ -89,7 +90,7 @@ patch_t *tallinfin;
// coop hud // 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; static patch_t *emblemicon;
patch_t *tokenicon; patch_t *tokenicon;
static patch_t *exiticon; static patch_t *exiticon;
@ -237,6 +238,13 @@ void HU_LoadGraphics(void)
tallminus = (patch_t *)W_CachePatchName("STTMINUS", PU_HUDGFX); tallminus = (patch_t *)W_CachePatchName("STTMINUS", PU_HUDGFX);
tallinfin = (patch_t *)W_CachePatchName("STTINFIN", PU_HUDGFX); tallinfin = (patch_t *)W_CachePatchName("STTINFIN", PU_HUDGFX);
// cache act numbers for level titles
for (i = 0; i < 20; i++)
{
sprintf(buffer, "TTL%.2d", i);
ttlnum[i] = (patch_t *)W_CachePatchName(buffer, PU_HUDGFX);
}
// cache the crosshairs, don't bother to know which one is being used, // cache the crosshairs, don't bother to know which one is being used,
// just cache all 3, they're so small anyway. // just cache all 3, they're so small anyway.
for (i = 0; i < HU_CROSSHAIRS; i++) for (i = 0; i < HU_CROSSHAIRS; i++)
@ -256,6 +264,7 @@ void HU_LoadGraphics(void)
emeraldpics[0][4] = W_CachePatchName("CHAOS5", PU_HUDGFX); emeraldpics[0][4] = W_CachePatchName("CHAOS5", PU_HUDGFX);
emeraldpics[0][5] = W_CachePatchName("CHAOS6", PU_HUDGFX); emeraldpics[0][5] = W_CachePatchName("CHAOS6", PU_HUDGFX);
emeraldpics[0][6] = W_CachePatchName("CHAOS7", 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][0] = W_CachePatchName("TEMER1", PU_HUDGFX);
emeraldpics[1][1] = W_CachePatchName("TEMER2", PU_HUDGFX); emeraldpics[1][1] = W_CachePatchName("TEMER2", PU_HUDGFX);
@ -264,6 +273,7 @@ void HU_LoadGraphics(void)
emeraldpics[1][4] = W_CachePatchName("TEMER5", PU_HUDGFX); emeraldpics[1][4] = W_CachePatchName("TEMER5", PU_HUDGFX);
emeraldpics[1][5] = W_CachePatchName("TEMER6", PU_HUDGFX); emeraldpics[1][5] = W_CachePatchName("TEMER6", PU_HUDGFX);
emeraldpics[1][6] = W_CachePatchName("TEMER7", 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][0] = W_CachePatchName("EMBOX1", PU_HUDGFX);
emeraldpics[2][1] = W_CachePatchName("EMBOX2", PU_HUDGFX); emeraldpics[2][1] = W_CachePatchName("EMBOX2", PU_HUDGFX);
@ -272,6 +282,7 @@ void HU_LoadGraphics(void)
emeraldpics[2][4] = W_CachePatchName("EMBOX5", PU_HUDGFX); emeraldpics[2][4] = W_CachePatchName("EMBOX5", PU_HUDGFX);
emeraldpics[2][5] = W_CachePatchName("EMBOX6", PU_HUDGFX); emeraldpics[2][5] = W_CachePatchName("EMBOX6", PU_HUDGFX);
emeraldpics[2][6] = W_CachePatchName("EMBOX7", PU_HUDGFX); emeraldpics[2][6] = W_CachePatchName("EMBOX7", PU_HUDGFX);
//emeraldpics[2][7] = W_CachePatchName("EMBOX8", PU_HUDGFX); -- unused
} }
// Initialise Heads up // Initialise Heads up

View file

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

3425
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

@ -1356,11 +1356,12 @@ static int lib_pRadiusAttack(lua_State *L)
mobj_t *spot = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *spot = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t damagedist = luaL_checkfixed(L, 3); fixed_t damagedist = luaL_checkfixed(L, 3);
UINT8 damagetype = luaL_optinteger(L, 4, 0);
NOHUD NOHUD
INLEVEL INLEVEL
if (!spot || !source) if (!spot || !source)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
P_RadiusAttack(spot, source, damagedist); P_RadiusAttack(spot, source, damagedist, damagetype);
return 0; return 0;
} }

View file

@ -85,7 +85,9 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum)
deny: deny:
//must be hacked/buggy client //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]); CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]);
if (server) if (server)
{ {

View file

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

View file

@ -421,6 +421,7 @@ static int sector_get(lua_State *L)
{ {
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt); enum sector_e field = luaL_checkoption(L, 2, sector_opt[0], sector_opt);
INT16 i;
if (!sector) if (!sector)
{ {
@ -443,11 +444,23 @@ static int sector_get(lua_State *L)
lua_pushfixed(L, sector->ceilingheight); lua_pushfixed(L, sector->ceilingheight);
return 1; return 1;
case sector_floorpic: // floorpic case sector_floorpic: // floorpic
lua_pushlstring(L, levelflats[sector->floorpic].name, 8); {
levelflat_t *levelflat = &levelflats[sector->floorpic];
for (i = 0; i < 8; i++)
if (!levelflat->name[i])
break;
lua_pushlstring(L, levelflat->name, i);
return 1; return 1;
}
case sector_ceilingpic: // ceilingpic case sector_ceilingpic: // ceilingpic
lua_pushlstring(L, levelflats[sector->ceilingpic].name, 8); {
levelflat_t *levelflat = &levelflats[sector->ceilingpic];
for (i = 0; i < 8; i++)
if (!levelflat->name[i])
break;
lua_pushlstring(L, levelflat->name, i);
return 1; return 1;
}
case sector_lightlevel: case sector_lightlevel:
lua_pushinteger(L, sector->lightlevel); lua_pushinteger(L, sector->lightlevel);
return 1; return 1;

View file

@ -130,6 +130,8 @@ static int player_get(lua_State *L)
lua_pushangle(L, plr->drawangle); lua_pushangle(L, plr->drawangle);
else if (fastcmp(field,"rings")) else if (fastcmp(field,"rings"))
lua_pushinteger(L, plr->rings); lua_pushinteger(L, plr->rings);
else if (fastcmp(field,"spheres"))
lua_pushinteger(L, plr->spheres);
else if (fastcmp(field,"pity")) else if (fastcmp(field,"pity"))
lua_pushinteger(L, plr->pity); lua_pushinteger(L, plr->pity);
else if (fastcmp(field,"currentweapon")) else if (fastcmp(field,"currentweapon"))
@ -294,6 +296,8 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->startedtime); lua_pushinteger(L, plr->startedtime);
else if (fastcmp(field,"finishedtime")) else if (fastcmp(field,"finishedtime"))
lua_pushinteger(L, plr->finishedtime); lua_pushinteger(L, plr->finishedtime);
else if (fastcmp(field,"finishedspheres"))
lua_pushinteger(L, plr->finishedspheres);
else if (fastcmp(field,"finishedrings")) else if (fastcmp(field,"finishedrings"))
lua_pushinteger(L, plr->finishedrings); lua_pushinteger(L, plr->finishedrings);
else if (fastcmp(field,"marescore")) else if (fastcmp(field,"marescore"))
@ -396,6 +400,8 @@ static int player_set(lua_State *L)
plr->drawangle = luaL_checkangle(L, 3); plr->drawangle = luaL_checkangle(L, 3);
else if (fastcmp(field,"rings")) else if (fastcmp(field,"rings"))
plr->rings = (INT32)luaL_checkinteger(L, 3); plr->rings = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"spheres"))
plr->spheres = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"pity")) else if (fastcmp(field,"pity"))
plr->pity = (SINT8)luaL_checkinteger(L, 3); plr->pity = (SINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"currentweapon")) else if (fastcmp(field,"currentweapon"))
@ -448,7 +454,7 @@ static int player_set(lua_State *L)
else if (fastcmp(field,"followitem")) else if (fastcmp(field,"followitem"))
plr->followitem = luaL_checkinteger(L, 3); plr->followitem = luaL_checkinteger(L, 3);
else if (fastcmp(field,"followmobj")) 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")) else if (fastcmp(field,"actionspd"))
plr->actionspd = (INT32)luaL_checkinteger(L, 3); plr->actionspd = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"mindash")) else if (fastcmp(field,"mindash"))
@ -570,6 +576,8 @@ static int player_set(lua_State *L)
plr->startedtime = (tic_t)luaL_checkinteger(L, 3); plr->startedtime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"finishedtime")) else if (fastcmp(field,"finishedtime"))
plr->finishedtime = (tic_t)luaL_checkinteger(L, 3); plr->finishedtime = (tic_t)luaL_checkinteger(L, 3);
else if (fastcmp(field,"finishedspheres"))
plr->finishedspheres = (INT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"finishedrings")) else if (fastcmp(field,"finishedrings"))
plr->finishedrings = (INT16)luaL_checkinteger(L, 3); plr->finishedrings = (INT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"marescore")) else if (fastcmp(field,"marescore"))

View file

@ -572,9 +572,23 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
break; break;
} }
case LUA_TSTRING: case LUA_TSTRING:
{
UINT16 len = (UINT16)lua_objlen(gL, myindex); // get length of string, including embedded zeros
const char *s = lua_tostring(gL, myindex);
UINT16 i = 0;
WRITEUINT8(save_p, ARCH_STRING); WRITEUINT8(save_p, ARCH_STRING);
WRITESTRING(save_p, lua_tostring(gL, myindex)); // if you're wondering why we're writing a string to save_p this way,
// it turns out that Lua can have embedded zeros ('\0') in the strings,
// so we can't use WRITESTRING as that cuts off when it finds a '\0'.
// Saving the size of the string also allows us to get the size of the string on the other end,
// fixing the awful crashes previously encountered for reading strings longer than 1024
// (yes I know that's kind of a stupid thing to care about, but it'd be evil to trim or ignore them?)
// -- Monster Iestyn 05/08/18
WRITEUINT16(save_p, len); // save size of string
while (i < len)
WRITECHAR(save_p, s[i++]); // write chars individually, including the embedded zeros
break; break;
}
case LUA_TTABLE: case LUA_TTABLE:
{ {
boolean found = false; boolean found = false;
@ -905,9 +919,19 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
break; break;
case ARCH_STRING: case ARCH_STRING:
{ {
char value[1024]; UINT16 len = READUINT16(save_p); // length of string, including embedded zeros
READSTRING(save_p, value); char *value;
lua_pushstring(gL, value); UINT16 i = 0;
// See my comments in the ArchiveValue function;
// it's much the same for reading strings as writing them!
// (i.e. we can't use READSTRING either)
// -- Monster Iestyn 05/08/18
value = malloc(len); // make temp buffer of size len
// now read the actual string
while (i < len)
value[i++] = READCHAR(save_p); // read chars individually, including the embedded zeros
lua_pushlstring(gL, value, len); // push the string (note: this function supports embedded zeros)
free(value); // free the buffer
break; break;
} }
case ARCH_TABLE: case ARCH_TABLE:

View file

@ -499,56 +499,211 @@ void Command_Teleport_f(void)
REQUIRE_INLEVEL; REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER; 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; return;
} }
if (!p->mo) if (!p->mo)
return; return;
i = COM_CheckParm("-x"); i = COM_CheckParm("-sp");
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");
if (i) if (i)
{ {
intz = atoi(COM_Argv(i + 1)); INT32 starpostnum = atoi(COM_Argv(i + 1)); // starpost number
intz <<= FRACBITS; INT32 starpostpath = atoi(COM_Argv(i + 2)); // quick, dirty way to distinguish between paths
if (intz < ss->sector->floorheight)
intz = ss->sector->floorheight; if (starpostnum < 0 || starpostpath < 0)
if (intz > ss->sector->ceilingheight - p->mo->height) {
intz = ss->sector->ceilingheight - p->mo->height; 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 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(); 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")); CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n"));
else else
S_StartSound(p->mo, sfx_mixup); S_StartSound(p->mo, sfx_mixup);
@ -728,13 +883,30 @@ void Command_Setrings_f(void)
// P_GivePlayerRings does value clamping // P_GivePlayerRings does value clamping
players[consoleplayer].rings = 0; players[consoleplayer].rings = 0;
P_GivePlayerRings(&players[consoleplayer], atoi(COM_Argv(1))); 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 players[consoleplayer].totalring -= atoi(COM_Argv(1)); //undo totalring addition done in P_GivePlayerRings
G_SetGameModified(multiplayer); G_SetGameModified(multiplayer);
} }
} }
void Command_Setspheres_f(void)
{
REQUIRE_INLEVEL;
REQUIRE_SINGLEPLAYER;
REQUIRE_NOULTIMATE;
REQUIRE_PANDORA;
if (COM_Argc() > 1)
{
// P_GivePlayerRings does value clamping
players[consoleplayer].spheres = 0;
P_GivePlayerSpheres(&players[consoleplayer], atoi(COM_Argv(1)));
G_SetGameModified(multiplayer);
}
}
void Command_Setlives_f(void) void Command_Setlives_f(void)
{ {
REQUIRE_INLEVEL; REQUIRE_INLEVEL;
@ -744,9 +916,15 @@ void Command_Setlives_f(void)
if (COM_Argc() > 1) if (COM_Argc() > 1)
{ {
// P_GivePlayerLives does value clamping SINT8 lives = atoi(COM_Argv(1));
players[consoleplayer].lives = 0; if (lives == -1)
P_GivePlayerLives(&players[consoleplayer], atoi(COM_Argv(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); G_SetGameModified(multiplayer);
} }
@ -779,10 +957,12 @@ void Command_Setcontinues_f(void)
static CV_PossibleValue_t op_mapthing_t[] = {{0, "MIN"}, {4095, "MAX"}, {0, NULL}}; static CV_PossibleValue_t op_mapthing_t[] = {{0, "MIN"}, {4095, "MAX"}, {0, NULL}};
static CV_PossibleValue_t op_speed_t[] = {{1, "MIN"}, {128, "MAX"}, {0, NULL}}; static CV_PossibleValue_t op_speed_t[] = {{1, "MIN"}, {128, "MAX"}, {0, NULL}};
static CV_PossibleValue_t op_flags_t[] = {{0, "MIN"}, {15, "MAX"}, {0, NULL}}; static CV_PossibleValue_t op_flags_t[] = {{0, "MIN"}, {15, "MAX"}, {0, NULL}};
static CV_PossibleValue_t op_hoopflags_t[] = {{0, "MIN"}, {15, "MAX"}, {0, NULL}};
consvar_t cv_mapthingnum = {"op_mapthingnum", "0", CV_NOTINNET, op_mapthing_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_mapthingnum = {"op_mapthingnum", "0", CV_NOTINNET, op_mapthing_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_speed = {"op_speed", "16", CV_NOTINNET, op_speed_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_speed = {"op_speed", "16", CV_NOTINNET, op_speed_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_opflags = {"op_flags", "0", CV_NOTINNET, op_flags_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_opflags = {"op_flags", "0", CV_NOTINNET, op_flags_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_ophoopflags = {"op_hoopflags", "4", CV_NOTINNET, op_hoopflags_t, NULL, 0, NULL, NULL, 0, 0, NULL};
boolean objectplacing = false; boolean objectplacing = false;
mobjtype_t op_currentthing = 0; // For the object placement mode mobjtype_t op_currentthing = 0; // For the object placement mode
@ -986,17 +1166,10 @@ void OP_NightsObjectplace(player_t *player)
{ {
UINT16 angle = (UINT16)(player->anotherflyangle % 360); UINT16 angle = (UINT16)(player->anotherflyangle % 360);
INT16 temp = (INT16)FixedInt(AngleFixed(player->mo->angle)); // Traditional 2D Angle INT16 temp = (INT16)FixedInt(AngleFixed(player->mo->angle)); // Traditional 2D Angle
sector_t *sec = player->mo->subsector->sector;
#ifdef ESLOPE
fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight;
#else
fixed_t fheight = sec->floorheight;
#endif
player->pflags |= PF_ATTACKDOWN; player->pflags |= PF_ATTACKDOWN;
mt = OP_CreateNewMapThing(player, 1705, false); mt = OP_CreateNewMapThing(player, 1713, false);
// Tilt // Tilt
mt->angle = (INT16)FixedInt(FixedDiv(angle*FRACUNIT, 360*(FRACUNIT/256))); mt->angle = (INT16)FixedInt(FixedDiv(angle*FRACUNIT, 360*(FRACUNIT/256)));
@ -1007,10 +1180,10 @@ void OP_NightsObjectplace(player_t *player)
temp += 90; temp += 90;
temp %= 360; temp %= 360;
mt->options = (UINT16)((player->mo->z - fheight)>>FRACBITS); mt->options = (mt->options & ~(UINT16)cv_opflags.value) | (UINT16)cv_ophoopflags.value;
mt->angle = (INT16)(mt->angle+(INT16)((FixedInt(FixedDiv(temp*FRACUNIT, 360*(FRACUNIT/256))))<<8)); 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! // This places a bumper!
@ -1024,26 +1197,26 @@ void OP_NightsObjectplace(player_t *player)
P_SpawnMapThing(mt); P_SpawnMapThing(mt);
} }
// This places a ring! // This places a sphere!
if (cmd->buttons & BT_WEAPONNEXT) if (cmd->buttons & BT_WEAPONNEXT)
{ {
player->pflags |= PF_ATTACKDOWN; player->pflags |= PF_ATTACKDOWN;
if (!OP_HeightOkay(player, false)) if (!OP_HeightOkay(player, false))
return; return;
mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_RING].doomednum, false); mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_BLUESPHERE].doomednum, false);
P_SpawnHoopsAndRings(mt); P_SpawnHoopsAndRings(mt, false);
} }
// This places a wing item! // This places a ring!
if (cmd->buttons & BT_WEAPONPREV) if (cmd->buttons & BT_WEAPONPREV)
{ {
player->pflags |= PF_ATTACKDOWN; player->pflags |= PF_ATTACKDOWN;
if (!OP_HeightOkay(player, false)) if (!OP_HeightOkay(player, false))
return; return;
mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_NIGHTSWING].doomednum, false); mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_RING].doomednum, false);
P_SpawnHoopsAndRings(mt); P_SpawnHoopsAndRings(mt, false);
} }
// This places a custom object as defined in the console cv_mapthingnum. // This places a custom object as defined in the console cv_mapthingnum.
@ -1077,12 +1250,12 @@ void OP_NightsObjectplace(player_t *player)
if (mt->type == 300 // Ring if (mt->type == 300 // Ring
|| mt->type == 308 || mt->type == 309 // Team Rings || 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 >= 600 && mt->type <= 609) // Placement patterns
|| mt->type == 1705 || mt->type == 1713 // NiGHTS Hoops || mt->type == 1705 || mt->type == 1713 // NiGHTS Hoops
|| mt->type == 1800) // Mario Coin || mt->type == 1800) // Mario Coin
{ {
P_SpawnHoopsAndRings(mt); P_SpawnHoopsAndRings(mt, false);
} }
else else
P_SpawnMapThing(mt); P_SpawnMapThing(mt);
@ -1227,7 +1400,7 @@ void OP_ObjectplaceMovement(player_t *player)
|| mt->type == 1705 || mt->type == 1713 // NiGHTS Hoops || mt->type == 1705 || mt->type == 1713 // NiGHTS Hoops
|| mt->type == 1800) // Mario Coin || mt->type == 1800) // Mario Coin
{ {
P_SpawnHoopsAndRings(mt); P_SpawnHoopsAndRings(mt, false);
} }
else else
P_SpawnMapThing(mt); P_SpawnMapThing(mt);

View file

@ -28,7 +28,7 @@ void cht_Init(void);
void Command_ObjectPlace_f(void); void Command_ObjectPlace_f(void);
void Command_Writethings_f(void); void Command_Writethings_f(void);
extern consvar_t cv_opflags, cv_mapthingnum, cv_speed; extern consvar_t cv_opflags, cv_ophoopflags, cv_mapthingnum, cv_speed;
//extern consvar_t cv_snapto, cv_grid; //extern consvar_t cv_snapto, cv_grid;
extern boolean objectplacing; extern boolean objectplacing;
@ -51,6 +51,7 @@ void Command_Savecheckpoint_f(void);
void Command_Getallemeralds_f(void); void Command_Getallemeralds_f(void);
void Command_Resetemeralds_f(void); void Command_Resetemeralds_f(void);
void Command_Setrings_f(void); void Command_Setrings_f(void);
void Command_Setspheres_f(void);
void Command_Setlives_f(void); void Command_Setlives_f(void);
void Command_Setcontinues_f(void); void Command_Setcontinues_f(void);
void Command_Devmode_f(void); void Command_Devmode_f(void);

View file

@ -456,7 +456,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 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 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 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[] = { 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} {-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}
}; };
@ -4947,6 +4947,7 @@ static void M_DrawAddons(void)
{ {
INT32 x, y; INT32 x, y;
ssize_t i, max; ssize_t i, max;
const char* topstr;
// hack - need to refresh at end of frame to handle addfile... // hack - need to refresh at end of frame to handle addfile...
if (refreshdirmenu & M_AddonsRefresh()) if (refreshdirmenu & M_AddonsRefresh())
@ -4955,9 +4956,19 @@ static void M_DrawAddons(void)
return; return;
} }
V_DrawCenteredString(BASEVIDWIDTH/2, 5, 0, (Playing() if (addonsresponselimit)
? "\x85""Adding files mid-game may cause problems." addonsresponselimit--;
: 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, 5, 0, topstr);
if (numwadfiles <= mainwads+1) if (numwadfiles <= mainwads+1)
y = 0; y = 0;
@ -5225,7 +5236,7 @@ static void M_HandleAddons(INT32 choice)
case EXT_SOC: case EXT_SOC:
case EXT_WAD: case EXT_WAD:
case EXT_PK3: 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));
break; break;
default: default:
S_StartSound(NULL, sfx_lose); S_StartSound(NULL, sfx_lose);
@ -5260,8 +5271,14 @@ static void M_HandleAddons(INT32 choice)
static void M_PandorasBox(INT32 choice) static void M_PandorasBox(INT32 choice)
{ {
(void)choice; (void)choice;
CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].rings, 0)); if (maptol & TOL_NIGHTS)
CV_StealthSetValue(&cv_dummylives, players[consoleplayer].lives); CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].spheres, 0));
else
CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].rings, 0));
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); CV_StealthSetValue(&cv_dummycontinues, players[consoleplayer].continues);
SR_PandorasBox[6].status = ((players[consoleplayer].charflags & SF_SUPER) SR_PandorasBox[6].status = ((players[consoleplayer].charflags & SF_SUPER)
#ifndef DEVELOP #ifndef DEVELOP
@ -5275,7 +5292,12 @@ static void M_PandorasBox(INT32 choice)
static boolean M_ExitPandorasBox(void) static boolean M_ExitPandorasBox(void)
{ {
if (cv_dummyrings.value != max(players[consoleplayer].rings, 0)) if (cv_dummyrings.value != max(players[consoleplayer].rings, 0))
COM_ImmedExecute(va("setrings %d", cv_dummyrings.value)); {
if (maptol & TOL_NIGHTS)
COM_ImmedExecute(va("setspheres %d", cv_dummyrings.value));
else
COM_ImmedExecute(va("setrings %d", cv_dummyrings.value));
}
if (cv_dummylives.value != players[consoleplayer].lives) if (cv_dummylives.value != players[consoleplayer].lives)
COM_ImmedExecute(va("setlives %d", cv_dummylives.value)); COM_ImmedExecute(va("setlives %d", cv_dummylives.value));
if (cv_dummycontinues.value != players[consoleplayer].continues) if (cv_dummycontinues.value != players[consoleplayer].continues)
@ -8825,7 +8847,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice)
break; break;
S_StartSound(NULL,sfx_menu1); // Tails S_StartSound(NULL,sfx_menu1); // Tails
l = strlen(setupm_name); l = strlen(setupm_name);
if (l < MAXPLAYERNAME-1) if (l < MAXPLAYERNAME)
{ {
setupm_name[l] = (char)choice; setupm_name[l] = (char)choice;
setupm_name[l+1] = 0; setupm_name[l+1] = 0;

View file

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

File diff suppressed because it is too large Load diff

View file

@ -3318,7 +3318,7 @@ INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
P_SetThingPosition(thing); P_SetThingPosition(thing);
if (thing->flags & MF_SHOOTABLE) if (thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, puncher, puncher, 1, 0); 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); thing->momz = FixedMul(3*FRACUNIT, thing->scale);
P_TouchSpecialThing(thing, puncher, false); 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); void P_SwitchShield(player_t *player, UINT16 shieldtype);
mobj_t *P_SpawnGhostMobj(mobj_t *mobj); mobj_t *P_SpawnGhostMobj(mobj_t *mobj);
void P_GivePlayerRings(player_t *player, INT32 num_rings); 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_GivePlayerLives(player_t *player, INT32 numlives);
void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound); void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound);
UINT8 P_GetNextEmerald(void); 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_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover);
boolean P_CheckDeathPitCollide(mobj_t *mo); boolean P_CheckDeathPitCollide(mobj_t *mo);
boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover); 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); mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type);
@ -362,7 +364,7 @@ void P_DelPrecipSeclist(mprecipsecnode_t *node);
void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y); void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y);
void P_Initsecnode(void); void P_Initsecnode(void);
void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist); 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); fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height);
boolean PIT_PushableMoved(mobj_t *thing); boolean PIT_PushableMoved(mobj_t *thing);
@ -412,6 +414,8 @@ typedef struct BasicFF_s
#define DMG_DEATHPIT 0x80+3 #define DMG_DEATHPIT 0x80+3
#define DMG_CRUSHED 0x80+4 #define DMG_CRUSHED 0x80+4
#define DMG_SPECTATOR 0x80+5 #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 #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); 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 // 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) boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{ {
INT32 pflags;
fixed_t offx, offy;
fixed_t vertispeed = spring->info->mass; fixed_t vertispeed = spring->info->mass;
fixed_t horizspeed = spring->info->damage; 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; return false;
// Spectators don't trigger springs. // Spectators don't trigger springs.
if (object->player && object->player->spectator) if (object->player && object->player->spectator)
return false; 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)) if (object->player && (object->player->powers[pw_carry] == CR_NIGHTSMODE))
{ {
/*Someone want to make these work like bumpers?*/ /*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))) || (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2)))
{ {
S_StartSound(object, sfx_s3k8b); S_StartSound(object, sfx_s3k8b);
horizspeed = FixedMul(horizspeed, (4*FRACUNIT)/3); if (horizspeed)
vertispeed = FixedMul(vertispeed, (6*FRACUNIT)/5); // aprox square root of above 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! 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; if ((horizspeed && vertispeed) || (object->player && object->player->homing)) // Mimic SA
P_TryMove(object, spring->x, spring->y, true); {
} object->momx = object->momy = 0;
P_TryMove(object, spring->x, spring->y, true);
}
if (spring->eflags & MFE_VERTICALFLIP) if (vertispeed > 0)
vertispeed *= -1; 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) // Overestimate the distance to position you at
object->z = spring->z + spring->height + 1; offx = P_ReturnThrustX(spring, spring->angle, (spring->radius + object->radius + 1) * 2);
else if (vertispeed < 0) offy = P_ReturnThrustY(spring, spring->angle, (spring->radius + object->radius + 1) * 2);
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 // Make it square by clipping
offx = P_ReturnThrustX(spring, spring->angle, (spring->radius + object->radius + 1) * 2); if (offx > (spring->radius + object->radius + 1))
offy = P_ReturnThrustY(spring, spring->angle, (spring->radius + object->radius + 1) * 2); 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 (offy > (spring->radius + object->radius + 1))
if (offx > (spring->radius + object->radius + 1)) offy = spring->radius + object->radius + 1;
offx = spring->radius + object->radius + 1; else if (offy < -(spring->radius + object->radius + 1))
else if (offx < -(spring->radius + object->radius + 1)) offy = -(spring->radius + object->radius + 1);
offx = -(spring->radius + object->radius + 1);
if (offy > (spring->radius + object->radius + 1)) // Set position!
offy = spring->radius + object->radius + 1; P_TryMove(object, spring->x + offx, spring->y + offy, true);
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);
} }
if (vertispeed) 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)))); P_InstaThrustEvenIn2D(object, spring->angle, FixedMul(horizspeed,FixedSqrt(FixedMul(object->scale, spring->scale))));
// Re-solidify // Re-solidify
spring->flags |= (spring->info->flags & (MF_SPECIAL|MF_SOLID)); spring->flags |= (spring->info->flags & (MF_SPRING|MF_SPECIAL));
P_SetMobjState(spring, spring->info->raisestate);
if (object->player) if (object->player)
{ {
INT32 pflags;
UINT8 secondjump;
boolean washoming;
if (spring->flags & MF_ENEMY) // Spring shells if (spring->flags & MF_ENEMY) // Spring shells
P_SetTarget(&spring->target, object); 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; secondjump = object->player->secondjump;
washoming = object->player->homing;
if (object->player->pflags & PF_GLIDING)
P_SetPlayerMobjState(object, S_PLAY_FALL);
P_ResetPlayer(object->player); 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); object->player->pflags |= P_GetJumpFlags(object->player);
P_SetPlayerMobjState(object, S_PLAY_JUMP); 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) object->player->pflags |= (pflags &~ PF_STARTJUMP);
|| (pflags & (PF_JUMPED|PF_SPINNING) && (object->player->panim == PA_ROLL || object->player->panim == PA_JUMP || object->player->panim == PA_FALL))) 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->pflags |= pflags;
object->player->secondjump = secondjump; object->player->secondjump = secondjump;
@ -239,10 +380,25 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
} }
#ifdef ESLOPE #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 #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) 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) static boolean PIT_CheckThing(mobj_t *thing)
{ {
fixed_t blockdist; fixed_t blockdist;
boolean iwassprung = false;
// don't clip against self // don't clip against self
if (thing == tmthing) if (thing == tmthing)
@ -514,7 +669,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true; 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; return true;
// Don't collide with your buddies while NiGHTS-flying. // Don't collide with your buddies while NiGHTS-flying.
@ -622,6 +777,54 @@ static boolean PIT_CheckThing(mobj_t *thing)
} }
#endif #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. // 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) if (tmthing->type == MT_SPIKE && tmthing->flags & MF_SOLID)
{ {
@ -639,35 +842,37 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true; return true;
} }
if (thing->flags & MF_PAIN) if (thing->flags & MF_PAIN && tmthing->player)
{ // Player touches painful thing sitting on the floor { // Player touches painful thing sitting on the floor
// see if it went over / under // see if it went over / under
if (thing->z > tmthing->z + tmthing->height) if (thing->z > tmthing->z + tmthing->height)
return true; // overhead return true; // overhead
if (thing->z + thing->height < tmthing->z) if (thing->z + thing->height < tmthing->z)
return true; // underneath return true; // underneath
if (tmthing->player && tmthing->flags & MF_SHOOTABLE && thing->health > 0) if (tmthing->flags & MF_SHOOTABLE && thing->health > 0)
{ {
UINT8 damagetype = 0; UINT8 damagetype = (thing->info->mass & 0xFF);
if (thing->flags & MF_FIRE) // BURN! if (!damagetype && thing->flags & MF_FIRE) // BURN!
damagetype = DMG_FIRE; 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; return true;
} }
else if (tmthing->flags & MF_PAIN) else if (tmthing->flags & MF_PAIN && thing->player)
{ // Painful thing splats player in the face { // Painful thing splats player in the face
// see if it went over / under // see if it went over / under
if (tmthing->z > thing->z + thing->height) if (tmthing->z > thing->z + thing->height)
return true; // overhead return true; // overhead
if (tmthing->z + tmthing->height < thing->z) if (tmthing->z + tmthing->height < thing->z)
return true; // underneath return true; // underneath
if (thing->player && thing->flags & MF_SHOOTABLE && tmthing->health > 0) if (thing->flags & MF_SHOOTABLE && tmthing->health > 0)
{ {
UINT8 damagetype = 0; UINT8 damagetype = (tmthing->info->mass & 0xFF);
if (tmthing->flags & MF_FIRE) // BURN! if (!damagetype && tmthing->flags & MF_FIRE) // BURN!
damagetype = DMG_FIRE; 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; 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 else if (tmz > thzh - sprarea && tmz < thzh) // Don't damage people springing up / down
return true; return true;
} }
// missiles can hit other things // missiles can hit other things
if (tmthing->flags & MF_MISSILE || tmthing->type == MT_SHELL) 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) if (thing->type == MT_EGGSHIELD)
{ {
fixed_t touchx, touchy; angle_t angle = (R_PointToAngle2(thing->x, thing->y, tmthing->x - tmthing->momx, tmthing->y - tmthing->momy) - thing->angle) - ANGLE_90;
angle_t angle;
if (P_AproxDistance(tmthing->x-thing->x, tmthing->y-thing->y) > if (angle < ANGLE_180) // hit shield from behind, shield is destroyed!
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!
{
P_KillMobj(thing, tmthing, tmthing, 0); P_KillMobj(thing, tmthing, tmthing, 0);
return false; return false;
}
} }
// damage / explode // damage / explode
@ -835,7 +1022,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
P_SetThingPosition(tmthing); P_SetThingPosition(tmthing);
} }
else if (!(tmthing->type == MT_SHELL && thing->player)) // player collision handled in touchspecial 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 // don't traverse any more
@ -917,14 +1109,14 @@ static boolean PIT_CheckThing(mobj_t *thing)
// not (your direction) xor (stored direction) // not (your direction) xor (stored direction)
// In other words, you can't u-turn and respawn rings near the drone. // In other words, you can't u-turn and respawn rings near the drone.
if (pl->bonustime && (pl->powers[pw_carry] == CR_NIGHTSMODE) && (INT32)leveltime > droneobj->extravalue2 && ( if (pl->bonustime && (pl->powers[pw_carry] == CR_NIGHTSMODE) && (INT32)leveltime > droneobj->extravalue2 && (
!(pl->anotherflyangle >= 90 && pl->anotherflyangle <= 270) !(pl->flyangle > 90 && pl->flyangle < 270)
^ (droneobj->extravalue1 >= 90 && droneobj->extravalue1 <= 270) ^ (droneobj->extravalue1 > 90 && droneobj->extravalue1 < 270)
)) ))
{ {
// Reload all the fancy ring stuff! // Reload all the fancy ring stuff!
P_ReloadRings(); P_ReloadRings();
} }
droneobj->extravalue1 = pl->anotherflyangle; droneobj->extravalue1 = pl->flyangle;
droneobj->extravalue2 = (INT32)leveltime + TICRATE; droneobj->extravalue2 = (INT32)leveltime + TICRATE;
} }
@ -1030,15 +1222,28 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (tmthing->flags & MF_PUSHABLE) if (tmthing->flags & MF_PUSHABLE)
{ {
if (thing->type == MT_FAN || thing->type == MT_STEAM) if (thing->type == MT_FAN || thing->type == MT_STEAM)
{
P_DoFanAndGasJet(thing, tmthing); P_DoFanAndGasJet(thing, tmthing);
return true;
}
else if (thing->flags & MF_SPRING) else if (thing->flags & MF_SPRING)
{ {
if ( thing->z <= tmthing->z + tmthing->height if ( thing->z <= tmthing->z + tmthing->height
&& tmthing->z <= thing->z + thing->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 // Damage other players when invincible
if (tmthing->player && thing->player 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. // Make sure they aren't able to damage you ANYWHERE along the Z axis, you have to be TOUCHING the person.
@ -1103,7 +1308,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
{ {
// Objects kill you if it falls from above. // Objects kill you if it falls from above.
if (thing != tmthing->target) 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! tmthing->momz = -tmthing->momz/2; // Bounce, just for fun!
// The tmthing->target allows the pusher of the object // The tmthing->target allows the pusher of the object
@ -1126,75 +1331,62 @@ static boolean PIT_CheckThing(mobj_t *thing)
{ {
if ( thing->z <= tmthing->z + tmthing->height if ( thing->z <= tmthing->z + tmthing->height
&& tmthing->z <= thing->z + thing->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? // Monitor?
else if (thing->z - FixedMul(FRACUNIT, thing->scale) <= tmthing->z + tmthing->height else if (thing->flags & MF_MONITOR
&& thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) >= tmthing->z) && !((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 // 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) 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) ? (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2)
: 0); : 0);
if (thing->flags & MF_MONITOR if (!(thing->flags & MF_SOLID)
&& (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING) || tmthing->player->pflags & (PF_SPINNING|PF_GLIDING)
|| ((tmthing->player->pflags & PF_JUMPED) || ((tmthing->player->pflags & PF_JUMPED)
&& (!(tmthing->player->pflags & PF_NOJUMPDAMAGE) && (!(tmthing->player->pflags & PF_NOJUMPDAMAGE)
|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) || (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2) || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
|| ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING) || ((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)) && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))
|| elementalpierce)) || elementalpierce)
{ {
player_t *player = tmthing->player; if (thing->z - thing->scale <= tmthing->z + tmthing->height
SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed. && thing->z + thing->height + thing->scale >= tmthing->z)
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 (elementalpierce == 2) player_t *player = tmthing->player;
P_DoBubbleBounce(player); SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed.
else if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;;
*momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically. 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.
{ return true;
if (player->pflags & PF_BOUNCING)
P_DoAbilityBounce(player, false);
return false;
}
else
*z -= *momz; // to ensure proper collision.
} }
} }
} }
if (!(tmthing->player) && (thing->player)) if ((!tmthing->player) && (thing->player))
; // no solid thing should ever be able to step up onto a 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 // z checking at last
// Treat noclip things as non-solid! // Treat noclip things as non-solid!
else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID
@ -1221,16 +1413,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 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, // block only when jumping not high enough,
// (dont climb max. 24units while already in air) // (dont climb max. 24units while already in air)
// since return false doesn't handle momentum properly, // since return false doesn't handle momentum properly,
// we lie to P_TryMove() so it's always too high // 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) && 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; return false;
tmfloorz = tmceilingz = topz; // block while in air tmfloorz = tmceilingz = topz; // block while in air
@ -1267,16 +1457,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 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, // block only when jumping not high enough,
// (dont climb max. 24units while already in air) // (dont climb max. 24units while already in air)
// since return false doesn't handle momentum properly, // since return false doesn't handle momentum properly,
// we lie to P_TryMove() so it's always too high // 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) && 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; return false;
tmfloorz = tmceilingz = topz; // block while in air tmfloorz = tmceilingz = topz; // block while in air
@ -3498,6 +3686,7 @@ bounceback:
static fixed_t bombdamage; static fixed_t bombdamage;
static mobj_t *bombsource; static mobj_t *bombsource;
static mobj_t *bombspot; static mobj_t *bombspot;
static UINT8 bombdamagetype;
// //
// PIT_RadiusAttack // PIT_RadiusAttack
@ -3508,17 +3697,13 @@ static boolean PIT_RadiusAttack(mobj_t *thing)
{ {
fixed_t dx, dy, dz, dist; fixed_t dx, dy, dz, dist;
if (thing == bombspot // ignore the bomb itself (Deton fix) 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.)
return true; return true;
if (!(thing->flags & MF_SHOOTABLE)) if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) != MF_SHOOTABLE)
return true; return true;
if (thing->flags & MF_BOSS) 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;
if (thing->flags & MF_MONITOR)
return true; return true;
dx = abs(thing->x - bombspot->x); dx = abs(thing->x - bombspot->x);
@ -3542,7 +3727,7 @@ static boolean PIT_RadiusAttack(mobj_t *thing)
if (P_CheckSight(thing, bombspot)) if (P_CheckSight(thing, bombspot))
{ // must be in direct path { // 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; return true;
@ -3552,7 +3737,7 @@ static boolean PIT_RadiusAttack(mobj_t *thing)
// P_RadiusAttack // P_RadiusAttack
// Source is the creature that caused the explosion at spot. // Source is the creature that caused the explosion at spot.
// //
void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist) void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype)
{ {
INT32 x, y; INT32 x, y;
INT32 xl, xh, yl, yh; INT32 xl, xh, yl, yh;
@ -3569,6 +3754,7 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist)
bombspot = spot; bombspot = spot;
bombsource = source; bombsource = source;
bombdamage = FixedMul(damagedist, spot->scale); bombdamage = FixedMul(damagedist, spot->scale);
bombdamagetype = damagetype;
for (y = yl; y <= yh; y++) for (y = yl; y <= yh; y++)
for (x = xl; x <= xh; x++) 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_SCATTER = 1<<8, // Thrown ring has scatter properties
MF2_BEYONDTHEGRAVE = 1<<9, // Source of this missile has died and has since respawned. MF2_BEYONDTHEGRAVE = 1<<9, // Source of this missile has died and has since respawned.
MF2_SLIDEPUSH = 1<<10, // MF_PUSHABLE that pushes continuously. MF2_SLIDEPUSH = 1<<10, // MF_PUSHABLE that pushes continuously.
MF2_CLASSICPUSH = 1<<11, // Drops straight down when object has negative Z. MF2_CLASSICPUSH = 1<<11, // Drops straight down when object has negative momz.
MF2_STANDONME = 1<<12, // While not pushable, stand on me anyway. 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_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_DEBRIS = 1<<14, // Splash ring from explosion ring
MF2_NIGHTSPULL = 1<<15, // Attracted from a paraloop MF2_NIGHTSPULL = 1<<15, // Attracted from a paraloop
@ -314,7 +314,7 @@ typedef struct mobj_s
mobjtype_t type; mobjtype_t type;
const mobjinfo_t *info; // &mobjinfo[mobj->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). // Movement direction, movement generation (zig-zagging).
angle_t movedir; // dirtype_t 0-7; also used by Deton for up/down angle angle_t movedir; // dirtype_t 0-7; also used by Deton for up/down angle
@ -388,6 +388,7 @@ typedef struct precipmobj_s
angle_t angle; // orientation angle_t angle; // orientation
spritenum_t sprite; // used to find patch_t and flip value spritenum_t sprite; // used to find patch_t and flip value
UINT32 frame; // frame number, plus bits see p_pspr.h UINT32 frame; // frame number, plus bits see p_pspr.h
UINT8 sprite2; // player sprites
UINT16 anim_duration; // for FF_ANIMATE states UINT16 anim_duration; // for FF_ANIMATE states
struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
@ -435,7 +436,7 @@ void P_MovePlayerToStarpost(INT32 playernum);
void P_AfterPlayerSpawn(INT32 playernum); void P_AfterPlayerSpawn(INT32 playernum);
void P_SpawnMapThing(mapthing_t *mthing); 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_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_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); 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].drawangle);
WRITEANGLE(save_p, players[i].awayviewaiming); WRITEANGLE(save_p, players[i].awayviewaiming);
WRITEINT32(save_p, players[i].awayviewtics); 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); WRITESINT8(save_p, players[i].pity);
WRITEINT32(save_p, players[i].currentweapon); WRITEINT32(save_p, players[i].currentweapon);
@ -201,6 +202,7 @@ static void P_NetArchivePlayers(void)
WRITEUINT32(save_p, players[i].marebegunat); WRITEUINT32(save_p, players[i].marebegunat);
WRITEUINT32(save_p, players[i].startedtime); WRITEUINT32(save_p, players[i].startedtime);
WRITEUINT32(save_p, players[i].finishedtime); WRITEUINT32(save_p, players[i].finishedtime);
WRITEINT16(save_p, players[i].finishedspheres);
WRITEINT16(save_p, players[i].finishedrings); WRITEINT16(save_p, players[i].finishedrings);
WRITEUINT32(save_p, players[i].marescore); WRITEUINT32(save_p, players[i].marescore);
WRITEUINT32(save_p, players[i].lastmarescore); WRITEUINT32(save_p, players[i].lastmarescore);
@ -303,7 +305,8 @@ static void P_NetUnArchivePlayers(void)
players[i].drawangle = READANGLE(save_p); players[i].drawangle = READANGLE(save_p);
players[i].awayviewaiming = READANGLE(save_p); players[i].awayviewaiming = READANGLE(save_p);
players[i].awayviewtics = READINT32(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].pity = READSINT8(save_p);
players[i].currentweapon = READINT32(save_p); players[i].currentweapon = READINT32(save_p);
@ -388,6 +391,7 @@ static void P_NetUnArchivePlayers(void)
players[i].marebegunat = READUINT32(save_p); players[i].marebegunat = READUINT32(save_p);
players[i].startedtime = READUINT32(save_p); players[i].startedtime = READUINT32(save_p);
players[i].finishedtime = READUINT32(save_p); players[i].finishedtime = READUINT32(save_p);
players[i].finishedspheres = READINT16(save_p);
players[i].finishedrings = READINT16(save_p); players[i].finishedrings = READINT16(save_p);
players[i].marescore = READUINT32(save_p); players[i].marescore = READUINT32(save_p);
players[i].lastmarescore = READUINT32(save_p); players[i].lastmarescore = READUINT32(save_p);
@ -1986,7 +1990,7 @@ static void LoadMobjThinker(actionf_p1 thinker)
if (mapthings[spawnpointnum].type == 1705 || mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case if (mapthings[spawnpointnum].type == 1705 || mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case
{ {
P_SpawnHoopsAndRings(&mapthings[spawnpointnum]); P_SpawnHoopsAndRings(&mapthings[spawnpointnum], false);
return; return;
} }
@ -3261,7 +3265,7 @@ static void P_NetArchiveMisc(void)
WRITEUINT32(save_p, tokenlist); WRITEUINT32(save_p, tokenlist);
WRITEUINT32(save_p, leveltime); WRITEUINT32(save_p, leveltime);
WRITEUINT32(save_p, totalrings); WRITEUINT32(save_p, ssspheres);
WRITEINT16(save_p, lastmap); WRITEINT16(save_p, lastmap);
WRITEUINT16(save_p, emeralds); WRITEUINT16(save_p, emeralds);
@ -3338,7 +3342,7 @@ static inline boolean P_NetUnArchiveMisc(void)
// get the time // get the time
leveltime = READUINT32(save_p); leveltime = READUINT32(save_p);
totalrings = READUINT32(save_p); ssspheres = READUINT32(save_p);
lastmap = READINT16(save_p); lastmap = READINT16(save_p);
emeralds = READUINT16(save_p); emeralds = READUINT16(save_p);

View file

@ -812,7 +812,7 @@ void P_ReloadRings(void)
mapthing_t *hoopsToRespawn[4096]; mapthing_t *hoopsToRespawn[4096];
mapthing_t *mt = mapthings; 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) for (th = thinkercap.next; th != &thinkercap; th = th->next)
{ {
if (th->function.acp1 != (actionf_p1)P_MobjThinker) if (th->function.acp1 != (actionf_p1)P_MobjThinker)
@ -830,7 +830,9 @@ void P_ReloadRings(void)
} }
continue; 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; continue;
// Don't auto-disintegrate things being pulled to us // Don't auto-disintegrate things being pulled to us
@ -844,9 +846,10 @@ void P_ReloadRings(void)
for (i = 0; i < nummapthings; i++, mt++) for (i = 0; i < nummapthings; i++, mt++)
{ {
// Notice an omission? We handle hoops differently. // Notice an omission? We handle hoops differently.
if (mt->type == 300 || mt->type == 308 || mt->type == 309 if (mt->type == mobjinfo[MT_RING].doomednum || mt->type == mobjinfo[MT_COIN].doomednum
|| mt->type == 1706 || (mt->type >= 600 && mt->type <= 609) || mt->type == mobjinfo[MT_REDTEAMRING].doomednum || mt->type == mobjinfo[MT_BLUETEAMRING].doomednum
|| mt->type == 1800) || mt->type == mobjinfo[MT_BLUESPHERE].doomednum || mt->type == mobjinfo[MT_BOMBSPHERE].doomednum
|| (mt->type >= 600 && mt->type <= 609)) // circles and diagonals
{ {
mt->mobj = NULL; mt->mobj = NULL;
@ -854,12 +857,46 @@ void P_ReloadRings(void)
mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS) mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)
->sector->floorheight>>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++) 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
&& mo->type != MT_FLINGBLUESPHERE && mo->type != MT_FLINGNIGHTSCHIP)
continue;
if (!mo->health)
continue;
P_SetMobjState(mo, ((bonustime) ? mo->info->raisestate : mo->info->spawnstate));
} }
} }
@ -1029,20 +1066,22 @@ static void P_LoadThings(void)
} }
//decrement spawn values to the actual number because zero is valid. //decrement spawn values to the actual number because zero is valid.
if (emer1) if (emer1--)
P_SpawnMobj(huntemeralds[emer1 - 1]->x<<FRACBITS, P_SpawnMobj(huntemeralds[emer1]->x<<FRACBITS,
huntemeralds[emer1 - 1]->y<<FRACBITS, huntemeralds[emer1]->y<<FRACBITS,
huntemeralds[emer1 - 1]->z<<FRACBITS, MT_EMERHUNT); huntemeralds[emer1]->z<<FRACBITS, MT_EMERHUNT);
if (emer2) if (emer2--)
P_SpawnMobj(huntemeralds[emer2 - 1]->x<<FRACBITS, P_SetMobjStateNF(P_SpawnMobj(huntemeralds[emer2]->x<<FRACBITS,
huntemeralds[emer2 - 1]->y<<FRACBITS, huntemeralds[emer2]->y<<FRACBITS,
huntemeralds[emer2 - 1]->z<<FRACBITS, MT_EMERHUNT); huntemeralds[emer2]->z<<FRACBITS, MT_EMERHUNT),
mobjinfo[MT_EMERHUNT].spawnstate+1);
if (emer3) if (emer3--)
P_SpawnMobj(huntemeralds[emer3 - 1]->x<<FRACBITS, P_SetMobjStateNF(P_SpawnMobj(huntemeralds[emer3]->x<<FRACBITS,
huntemeralds[emer3 - 1]->y<<FRACBITS, huntemeralds[emer3]->y<<FRACBITS,
huntemeralds[emer3 - 1]->z<<FRACBITS, MT_EMERHUNT); huntemeralds[emer3]->z<<FRACBITS, MT_EMERHUNT),
mobjinfo[MT_EMERHUNT].spawnstate+2);
} }
if (metalrecording) // Metal Sonic gets no rings to distract him. if (metalrecording) // Metal Sonic gets no rings to distract him.
@ -1052,9 +1091,11 @@ static void P_LoadThings(void)
mt = mapthings; mt = mapthings;
for (i = 0; i < nummapthings; i++, mt++) for (i = 0; i < nummapthings; i++, mt++)
{ {
if (mt->type == 300 || mt->type == 308 || mt->type == 309 if (mt->type == mobjinfo[MT_RING].doomednum || mt->type == mobjinfo[MT_COIN].doomednum
|| mt->type == 1706 || (mt->type >= 600 && mt->type <= 609) || mt->type == mobjinfo[MT_REDTEAMRING].doomednum || mt->type == mobjinfo[MT_BLUETEAMRING].doomednum
|| mt->type == 1705 || mt->type == 1713 || mt->type == 1800) || 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; mt->mobj = NULL;
@ -1062,7 +1103,7 @@ static void P_LoadThings(void)
mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS) mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)
->sector->floorheight>>FRACBITS); ->sector->floorheight>>FRACBITS);
P_SpawnHoopsAndRings (mt); P_SpawnHoopsAndRings(mt, false);
} }
} }
} }
@ -2302,7 +2343,7 @@ static void P_LevelInitStuff(void)
// circuit, race and competition stuff // circuit, race and competition stuff
circuitmap = false; circuitmap = false;
numstarposts = 0; numstarposts = 0;
totalrings = timeinmap = 0; ssspheres = timeinmap = 0;
// special stage // special stage
stagefailed = false; stagefailed = false;
@ -2324,6 +2365,8 @@ static void P_LevelInitStuff(void)
} }
} }
countdown = countdown2 = 0;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0)) if (canresetlives && (netgame || multiplayer) && playeringame[i] && (gametype == GT_COMPETITION || players[i].lives <= 0))
@ -2332,41 +2375,37 @@ static void P_LevelInitStuff(void)
players[i].lives = cv_startinglives.value; 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].finishedrings = 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].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].gotcontinue = false;
players[i].xtralife = players[i].deadtimer = players[i].numboxes = players[i].totalring = players[i].laps = 0; // aha, the first evidence this shouldn't be a memset!
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;
P_SetTarget(&players[i].capsule, NULL);
players[i].drillmeter = 40*20; players[i].drillmeter = 40*20;
players[i].exiting = 0;
P_ResetPlayer(&players[i]); P_ResetPlayer(&players[i]);
// hit these too
players[i].pflags &= ~(PF_GAMETYPEOVER|PF_TRANSFERTOCLOSEST);
players[i].mo = NULL; // 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
// we must unset axis details too players[i].mo = players[i].followmobj = players[i].awayviewmobj =\
players[i].axis1 = players[i].axis2 = NULL; players[i].capsule = players[i].axis1 = players[i].axis2 = NULL;
// and this stupid flag as a result
players[i].pflags &= ~PF_TRANSFERTOCLOSEST;
} }
} }
@ -2406,7 +2445,17 @@ void P_LoadThingsOnly(void)
P_LevelInitStuff(); 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(); P_LoadThings();
@ -3410,7 +3459,7 @@ boolean P_AddWadFile(const char *wadfilename)
for (i = 0; i < numlumps; i++, lumpinfo++) for (i = 0; i < numlumps; i++, lumpinfo++)
{ {
// lumpinfo = FindFolder("Lua/", &luaPos, &luaNum, lumpinfo, &numlumps, &i); // 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("Sounds/", &sfxPos, &sfxNum, lumpinfo, &numlumps, &i);
lumpinfo = FindFolder("Music/", &musPos, &musNum, lumpinfo, &numlumps, &i); lumpinfo = FindFolder("Music/", &musPos, &musNum, lumpinfo, &numlumps, &i);
// lumpinfo = FindFolder("Sprites/", &sprPos, &sprNum, lumpinfo, &numlumps, &i); // lumpinfo = FindFolder("Sprites/", &sprPos, &sprNum, lumpinfo, &numlumps, &i);

View file

@ -73,6 +73,7 @@ void P_DeleteFlickies(INT16 i);
// Needed for NiGHTS // Needed for NiGHTS
void P_ReloadRings(void); void P_ReloadRings(void);
void P_SwitchSpheresBonusMode(boolean bonustime);
void P_DeleteGrades(INT16 i); void P_DeleteGrades(INT16 i);
void P_AddGradesForMare(INT16 i, UINT8 mare, char *gtext); void P_AddGradesForMare(INT16 i, UINT8 mare, char *gtext);
UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare); 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? // Unlocked something?
if (M_UpdateUnlockablesAndExtraEmblems()) if (M_UpdateUnlockablesAndExtraEmblems())
{ {
S_StartSound(NULL, sfx_ncitem); S_StartSound(NULL, sfx_s3k68);
G_SaveGameData(); // only save if unlocked something 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 if (player->exiting || player->bot) // Don't do anything for bots or players who have just finished
break; 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; break;
P_SpecialStageDamage(player, NULL, NULL); P_SpecialStageDamage(player, NULL, NULL);
@ -3775,8 +3775,8 @@ DoneSection2:
case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return
if (player->bot) if (player->bot)
break; break;
if (!useNightsSS && G_IsSpecialStage(gamemap) && sstimer > 6) if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6)
sstimer = 6; // Just let P_Ticker take care of the rest. 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) // 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)) switch(GETSECSPECIAL(sector->special, 4))
{ {
case 2: // Level Exit / GOAL Sector / Flag Return case 2: // Level Exit / GOAL Sector / Flag Return
if (!useNightsSS && G_IsSpecialStage(gamemap)) if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))
{ {
// Special stage GOAL sector // Special stage GOAL sector
// requires touching floor. // requires touching floor.
@ -5502,7 +5502,7 @@ void P_InitSpecials(void)
// Defaults in case levels don't have them set. // Defaults in case levels don't have them set.
sstimer = 90*TICRATE + 6; sstimer = 90*TICRATE + 6;
totalrings = 1; ssspheres = 1;
CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false; CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false;
@ -5596,7 +5596,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
{ {
case 10: // Time for special stage case 10: // Time for special stage
sstimer = (sector->floorheight>>FRACBITS) * TICRATE + 6; // Time to finish 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; break;
case 11: // Custom global gravity! case 11: // Custom global gravity!
@ -7683,7 +7683,6 @@ void T_Pusher(pusher_t *p)
thing->player->pflags |= jumped; thing->player->pflags |= jumped;
thing->player->pflags |= PF_SLIDING; 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)); thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR));
if (!demoplayback || P_AnalogMove(thing->player)) if (!demoplayback || P_AnalogMove(thing->player))

View file

@ -424,7 +424,7 @@ void P_DoTeamscrambling(void)
static inline void P_DoSpecialStageStuff(void) static inline void P_DoSpecialStageStuff(void)
{ {
boolean inwater = false; boolean stillalive = false;
INT32 i; INT32 i;
// Can't drown in a special stage // 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; players[i].powers[pw_underwater] = players[i].powers[pw_spacetime] = 0;
} }
if (sstimer < 15*TICRATE+6 && sstimer > 7 && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)) //if (sstimer < 15*TICRATE+6 && sstimer > 7 && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC))
S_SpeedMusic(1.4f); //S_SpeedMusic(1.4f);
if (sstimer < 7 && sstimer > 0) // The special stage time is up! if (sstimer && !objectplacing)
{ {
sstimer = 0; UINT16 countspheres = 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;
// Count up the rings of all the players and see if // Count up the rings of all the players and see if
// they've collected the required amount. // they've collected the required amount.
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[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 in water, deplete timer 6x as fast.
if ((players[i].mo->eflags & MFE_TOUCHWATER) if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))
|| (players[i].mo->eflags & MFE_UNDERWATER)) players[i].nightstime -= 5;
inwater = true; 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 if (countspheres >= ssspheres)
for (i = 0; i < MAXPLAYERS; i++) {
if (playeringame[i]) // Halt all the players
{ for (i = 0; i < MAXPLAYERS; i++)
players[i].mo->momx = players[i].mo->momy = 0; if (playeringame[i])
players[i].exiting = (14*TICRATE)/5 + 1; {
} players[i].mo->momx = players[i].mo->momy = 0;
players[i].exiting = (14*TICRATE)/5 + 1;
}
sstimer = 0; sstimer = 0;
P_GiveEmerald(true);
P_GiveEmerald(true); P_RestoreMusic(&players[consoleplayer]);
}
} }
else
// Decrement the timer
if (!objectplacing)
{ {
if (inwater) sstimer = 0;
sstimer -= 6; stagefailed = true;
else
sstimer--;
} }
} }
} }
@ -609,7 +601,7 @@ void P_Ticker(boolean run)
if (!demoplayback) // Don't increment if a demo is playing. if (!demoplayback) // Don't increment if a demo is playing.
totalplaytime++; totalplaytime++;
if (!useNightsSS && G_IsSpecialStage(gamemap)) if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap))
P_DoSpecialStageStuff(); P_DoSpecialStageStuff();
if (runemeraldmanager) if (runemeraldmanager)

View file

@ -283,22 +283,11 @@ boolean P_PlayerMoving(INT32 pnum)
// //
UINT8 P_GetNextEmerald(void) UINT8 P_GetNextEmerald(void)
{ {
if (!useNightsSS) // In order if (gamemap >= sstage_start && gamemap <= sstage_end)
{
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;
return (UINT8)(gamemap - sstage_start); 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) void P_GiveEmerald(boolean spawnObj)
{ {
INT32 i; UINT8 em = P_GetNextEmerald();
UINT8 em;
S_StartSound(NULL, sfx_cgot); // Got the emerald! S_StartSound(NULL, sfx_cgot); // Got the emerald!
em = P_GetNextEmerald();
emeralds |= (1 << em); emeralds |= (1 << em);
if (spawnObj) if (spawnObj && playeringame[consoleplayer])
{ {
for (i = 0; i < MAXPLAYERS; i++) // The Chaos Emerald begins to orbit us!
if (playeringame[i]) // Only give it to ONE person!
P_SetMobjState(P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z + players[i].mo->info->height, MT_GOTEMERALD), mobj_t *emmo = P_SpawnMobjFromMobj(players[consoleplayer].mo, 0, 0, players[consoleplayer].mo->height, MT_GOTEMERALD);
mobjinfo[MT_GOTEMERALD].spawnstate + em); P_SetTarget(&emmo->target, players[consoleplayer].mo);
P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em);
P_SetTarget(&players[consoleplayer].mo->tracer, emmo);
} }
} }
@ -602,8 +590,9 @@ static void P_DeNightserizePlayer(player_t *player)
else if (player == &players[secondarydisplayplayer]) else if (player == &players[secondarydisplayplayer])
localaiming2 = 0; localaiming2 = 0;
// If you screwed up, kiss your score goodbye. // If you screwed up, kiss your score and ring bonus goodbye.
player->marescore = 0; player->marescore = 0;
player->rings = 0;
P_SetPlayerMobjState(player->mo, S_PLAY_FALL); P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
@ -692,9 +681,10 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
oldmare = player->mare; oldmare = player->mare;
if (P_TransferToNextMare(player) == false) if (!P_TransferToNextMare(player))
{ {
INT32 i; INT32 i;
INT32 total_spheres = 0;
INT32 total_rings = 0; INT32 total_rings = 0;
P_SetTarget(&player->mo->target, NULL); P_SetTarget(&player->mo->target, NULL);
@ -703,7 +693,10 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
{ {
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i]/* && players[i].powers[pw_carry] == CR_NIGHTSMODE*/) if (playeringame[i]/* && players[i].powers[pw_carry] == CR_NIGHTSMODE*/)
{
total_spheres += players[i].spheres;
total_rings += players[i].rings; total_rings += players[i].rings;
}
} }
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
@ -716,13 +709,15 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
players[i].lastmare = players[i].mare; players[i].lastmare = players[i].mare;
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
{ {
players[i].finishedspheres = (INT16)total_spheres;
players[i].finishedrings = (INT16)total_rings; players[i].finishedrings = (INT16)total_rings;
P_AddPlayerScore(player, total_rings * 50); P_AddPlayerScore(player, total_spheres * 50);
} }
else else
{ {
players[i].finishedspheres = (INT16)(players[i].spheres);
players[i].finishedrings = (INT16)(players[i].rings); players[i].finishedrings = (INT16)(players[i].rings);
P_AddPlayerScore(&players[i], (players[i].rings) * 50); P_AddPlayerScore(&players[i], (players[i].spheres) * 50);
} }
// Add score to leaderboards now // Add score to leaderboards now
@ -733,20 +728,20 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
players[i].lastmarescore = players[i].marescore; players[i].lastmarescore = players[i].marescore;
players[i].marescore = 0; players[i].marescore = 0;
players[i].rings = 0; players[i].spheres = players[i].rings = 0;
P_DoPlayerExit(&players[i]); P_DoPlayerExit(&players[i]);
} }
} }
else if (oldmare != player->mare) else if (oldmare != player->mare)
{ {
/// \todo Handle multi-mare special stages. /// \todo Handle multi-mare special stages.
// Ring bonus // Spheres bonus
P_AddPlayerScore(player, (player->rings) * 50); P_AddPlayerScore(player, (player->spheres) * 50);
player->lastmare = (UINT8)oldmare; player->lastmare = (UINT8)oldmare;
player->texttimer = 4*TICRATE; player->texttimer = 4*TICRATE;
player->textvar = 4; // Score and grades player->textvar = 4; // Score and grades
player->finishedrings = (INT16)(player->rings); player->finishedspheres = (INT16)(player->spheres);
// Add score to temp leaderboards // Add score to temp leaderboards
if (!(netgame||multiplayer) && P_IsLocalPlayer(player)) if (!(netgame||multiplayer) && P_IsLocalPlayer(player))
@ -757,7 +752,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
player->marescore = 0; player->marescore = 0;
player->marebegunat = leveltime; player->marebegunat = leveltime;
player->rings = 0; player->spheres = player->rings = 0;
} }
else else
{ {
@ -857,7 +852,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
} }
else 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); fallbackspeed = FixedMul(4*FRACUNIT, player->mo->scale);
} }
@ -923,8 +918,7 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings)
player->rings += 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! // Can only get up to 9999 rings, sorry!
if (player->rings > 9999) if (player->rings > 9999)
@ -956,6 +950,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 // P_GivePlayerLives
// //
@ -1035,12 +1049,11 @@ void P_DoSuperTransformation(player_t *player, boolean giverings)
S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi 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 // Transformation animation
P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_TRANS1); 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) if (giverings)
player->rings = 50; player->rings = 50;
@ -3492,194 +3505,198 @@ static void P_SetWeaponDelay(player_t *player, INT32 delay)
static void P_DoFiring(player_t *player, ticcmd_t *cmd) static void P_DoFiring(player_t *player, ticcmd_t *cmd)
{ {
INT32 i; INT32 i;
mobj_t *mo = NULL;
I_Assert(player != NULL); I_Assert(player != NULL);
I_Assert(!P_MobjWasRemoved(player->mo)); 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) // Not holding any firing buttons anymore.
{ // Release the grenade / whatever.
player->pflags |= PF_ATTACKDOWN; 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);
}
}
}
return; return;
} }
// Not holding any firing buttons anymore. if (player->pflags & PF_ATTACKDOWN || player->climbing || (G_TagGametype() && !(player->pflags & PF_TAGIT)))
// Release the grenade / whatever. return;
player->pflags &= ~PF_ATTACKDOWN;
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);
}
}
} }
// //
@ -3801,12 +3818,15 @@ static void P_DoSuperStuff(player_t *player)
// //
boolean P_SuperReady(player_t *player) boolean P_SuperReady(player_t *player)
{ {
if ((ALL7EMERALDS(emeralds) && player->rings >= 50) && !player->powers[pw_super] && !player->powers[pw_tailsfly] if (!player->powers[pw_super]
&& !(player->powers[pw_shield] & SH_NOSTACK)
&& !player->powers[pw_invulnerability] && !player->powers[pw_invulnerability]
&& !(maptol & TOL_NIGHTS || (player->powers[pw_carry] == CR_NIGHTSMODE)) // don't turn 'regular super' in nights levels && !player->powers[pw_tailsfly]
&& player->pflags & PF_JUMPED && (player->charflags & SF_SUPER)
&& 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 true;
return false; return false;
@ -4492,12 +4512,12 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
} }
else if (player->pflags & PF_SLIDING || (gametype == GT_CTF && player->gotflag)) 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, // If you can turn super and aren't already,
// and you don't have a shield, do it! // and you don't have a shield, do it!
P_DoSuperTransformation(player, false); P_DoSuperTransformation(player, false);
} }*/
else if (player->pflags & PF_JUMPED) else if (player->pflags & PF_JUMPED)
{ {
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
@ -5961,10 +5981,10 @@ static void P_DoNiGHTSCapsule(player_t *player)
if (G_IsSpecialStage(gamemap)) 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! { // 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++) 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; player->spheres += players[i].spheres;
players[i].rings = 0; players[i].spheres = 0;
} }
} }
@ -5973,9 +5993,9 @@ static void P_DoNiGHTSCapsule(player_t *player)
&& player->mo->y == player->capsule->y && player->mo->y == player->capsule->y
&& player->mo->z == player->capsule->z+(player->capsule->height/3)) && 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->health--;
player->capsule->extravalue1++; player->capsule->extravalue1++;
@ -6007,9 +6027,6 @@ static void P_DoNiGHTSCapsule(player_t *player)
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
{ {
// The Chaos Emerald begins to orbit us!
mobj_t *emmo;
UINT8 em = P_GetNextEmerald();
tic_t lowest_time; tic_t lowest_time;
/*for (i = 0; i < MAXPLAYERS; i++) /*for (i = 0; i < MAXPLAYERS; i++)
@ -6024,8 +6041,10 @@ static void P_DoNiGHTSCapsule(player_t *player)
if (player->powers[pw_carry] == CR_NIGHTSMODE) 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! // 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_SetTarget(&emmo->target, player->mo);
P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em);
P_SetTarget(&player->mo->tracer, emmo); P_SetTarget(&player->mo->tracer, emmo);
@ -6043,18 +6062,24 @@ static void P_DoNiGHTSCapsule(player_t *player)
} }
else 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); mobj_t *flicky = P_InternalFlickySpawn(player->capsule, 0, ((i%4) + 1)*2*FRACUNIT, true);
flicky->z += player->capsule->height/2; flicky->z += player->capsule->height/2;
flicky->angle = (i*(ANGLE_MAX/16)); flicky->angle = (i*(ANGLE_MAX/16));
P_InstaThrust(flicky, flicky->angle, 8*FRACUNIT); 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++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mare == player->mare) if (playeringame[i] && players[i].mare == player->mare)
P_SetTarget(&players[i].capsule, NULL); // Remove capsule from everyone now that it is dead! P_SetTarget(&players[i].capsule, NULL); // Remove capsule from everyone now that it is dead!
S_StartScreamSound(player->mo, sfx_ngdone); S_StartScreamSound(player->mo, sfx_ngdone);
P_SwitchSpheresBonusMode(true);
} }
} }
else else
@ -6147,7 +6172,7 @@ static void P_NiGHTSMovement(player_t *player)
} }
else if (P_IsLocalPlayer(player) && player->nightstime == 10*TICRATE) 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_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) if (player->mo->z < player->mo->floorz)
@ -6946,12 +6971,17 @@ static void P_MovePlayer(player_t *player)
if ((player->powers[pw_carry] == CR_NIGHTSMODE) if ((player->powers[pw_carry] == CR_NIGHTSMODE)
&& (player->exiting && (player->exiting
|| !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] || !(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)); 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); 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) if (!player->capsule && !player->bonustime)
@ -7000,7 +7030,7 @@ static void P_MovePlayer(player_t *player)
if (playeringame[i]) if (playeringame[i])
players[i].exiting = (14*TICRATE)/5 + 1; players[i].exiting = (14*TICRATE)/5 + 1;
} }
else if (player->rings > 0) else if (player->spheres > 0)
P_DamageMobj(player->mo, NULL, NULL, 1, 0); P_DamageMobj(player->mo, NULL, NULL, 1, 0);
player->powers[pw_carry] = CR_NONE; player->powers[pw_carry] = CR_NONE;
} }
@ -7485,7 +7515,7 @@ static void P_MovePlayer(player_t *player)
#endif #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 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 // Force shield activation
if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE)
@ -7498,6 +7528,11 @@ static void P_MovePlayer(player_t *player)
{ {
switch (player->powers[pw_shield] & SH_NOSTACK) switch (player->powers[pw_shield] & SH_NOSTACK)
{ {
// Super!
case SH_NONE:
if (P_SuperReady(player))
P_DoSuperTransformation(player, false);
break;
// Whirlwind/Thundercoin shield activation // Whirlwind/Thundercoin shield activation
case SH_WHIRLWIND: case SH_WHIRLWIND:
case SH_THUNDERCOIN: case SH_THUNDERCOIN:
@ -7949,17 +7984,18 @@ static void P_DoRopeHang(player_t *player)
if (player->cmd.buttons & BT_USE && !(player->pflags & PF_STASIS)) // Drop off of the rope 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); player->pflags |= P_GetJumpFlags(player);
P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
P_SetTarget(&player->mo->tracer, NULL);
player->powers[pw_carry] = CR_NONE; 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; 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 not allowed to move, we're done here.
if (!speed) if (!speed)
return; return;
@ -8050,10 +8086,7 @@ static void P_DoRopeHang(player_t *player)
if (player->mo->tracer->flags & MF_SLIDEME) if (player->mo->tracer->flags & MF_SLIDEME)
{ {
player->pflags |= P_GetJumpFlags(player); player->pflags |= P_GetJumpFlags(player);
P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
if (!(player->pflags & PF_SLIDING) && (player->pflags & PF_JUMPED)
&& !(player->panim == PA_JUMP))
P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
} }
P_SetTarget(&player->mo->tracer, NULL); P_SetTarget(&player->mo->tracer, NULL);
@ -8171,7 +8204,6 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
mobj_t *mo; mobj_t *mo;
thinker_t *think; thinker_t *think;
mobj_t *closestmo = NULL; 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 fixed_t maxdist = FixedMul((bullet ? RING_DIST*2 : RING_DIST), player->mo->scale);
const angle_t span = (bullet ? ANG30 : ANGLE_90); const angle_t span = (bullet ? ANG30 : ANGLE_90);
fixed_t dist, closestdist = 0; fixed_t dist, closestdist = 0;
@ -8182,9 +8214,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
continue; // not a mobj thinker continue; // not a mobj thinker
mo = (mobj_t *)think; mo = (mobj_t *)think;
if (!(mo->flags & targetmask 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
|| mo->type == MT_FAKEMOBILE // hehehehe
|| mo->type == MT_EGGSHIELD))
continue; // not a valid target continue; // not a valid target
if (mo->health <= 0) // dead if (mo->health <= 0) // dead
@ -8199,6 +8229,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) 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; continue;
if (!nonenemies && mo->flags & (MF_MONITOR|MF_SPRING))
continue;
if (!bullet && mo->type == MT_DETON) // Don't be STUPID, Sonic! if (!bullet && mo->type == MT_DETON) // Don't be STUPID, Sonic!
continue; continue;
@ -8236,7 +8269,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
if (closestmo && dist > closestdist) if (closestmo && dist > closestdist)
continue; 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 continue; // behind back
if (!P_CheckSight(player->mo, mo)) if (!P_CheckSight(player->mo, mo))
@ -9571,11 +9604,8 @@ void P_PlayerThink(player_t *player)
// If 11 seconds are left on the timer, // If 11 seconds are left on the timer,
// begin the drown music for countdown! // begin the drown music for countdown!
if (countdown == 11*TICRATE - 1) if (countdown == 11*TICRATE - 1 && P_IsLocalPlayer(player))
{ S_ChangeMusicInternal("_drown", false);
if (P_IsLocalPlayer(player))
S_ChangeMusicInternal("_drown", false);
}
// If you've hit the countdown and you haven't made // If you've hit the countdown and you haven't made
// it to the exit, you're a goner! // it to the exit, you're a goner!
@ -9675,7 +9705,7 @@ void P_PlayerThink(player_t *player)
if (gametype != GT_COOP) if (gametype != GT_COOP)
player->score = 0; player->score = 0;
player->mo->health = 1; player->mo->health = 1;
player->rings = 0; player->rings = player->spheres = 0;
} }
else if ((netgame || multiplayer) && player->lives <= 0 && gametype != GT_COOP) else if ((netgame || multiplayer) && player->lives <= 0 && gametype != GT_COOP)
{ {
@ -9728,8 +9758,9 @@ void P_PlayerThink(player_t *player)
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (!(mo2->type == MT_NIGHTSWING || mo2->type == MT_RING || mo2->type == MT_COIN if (!(mo2->type == MT_RING || mo2->type == MT_COIN
|| mo2->type == MT_BLUEBALL)) || mo2->type == MT_BLUESPHERE || mo2->type == MT_BOMBSPHERE
|| mo2->type == MT_NIGHTSCHIP || mo2->type == MT_NIGHTSSTAR))
continue; continue;
if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > FixedMul(128*FRACUNIT, player->mo->scale)) if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > FixedMul(128*FRACUNIT, player->mo->scale))
@ -9765,8 +9796,6 @@ void P_PlayerThink(player_t *player)
ticmiss++; ticmiss++;
P_DoRopeHang(player); P_DoRopeHang(player);
if (player->mo->state-states != S_PLAY_RIDE)
P_SetPlayerMobjState(player->mo, S_PLAY_RIDE);
P_DoJumpStuff(player, &player->cmd); P_DoJumpStuff(player, &player->cmd);
} }
else //if (player->powers[pw_carry] == CR_ZOOMTUBE) else //if (player->powers[pw_carry] == CR_ZOOMTUBE)
@ -9882,7 +9911,8 @@ void P_PlayerThink(player_t *player)
if (!player->powers[pw_carry] if (!player->powers[pw_carry]
&& ((player->pflags & (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) == (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) && ((player->pflags & (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) == (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE))
&& !(cmd->forwardmove || cmd->sidemove) && !(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; 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); angle_t moveAngle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
@ -9904,7 +9934,7 @@ void P_PlayerThink(player_t *player)
|| player->climbing || player->climbing
|| player->pflags & (PF_SPINNING|PF_SLIDING)) || player->pflags & (PF_SPINNING|PF_SLIDING))
player->pflags &= ~PF_APPLYAUTOBRAKE; player->pflags &= ~PF_APPLYAUTOBRAKE;
else if (currentlyonground) else if (currentlyonground || player->powers[pw_tailsfly])
player->pflags |= PF_APPLYAUTOBRAKE; player->pflags |= PF_APPLYAUTOBRAKE;
} }
} }
@ -10218,7 +10248,7 @@ void P_PlayerAfterThink(player_t *player)
if (player->followmobj) if (player->followmobj)
{ {
P_RemoveMobj(player->followmobj); P_RemoveMobj(player->followmobj);
player->followmobj = NULL; P_SetTarget(&player->followmobj, NULL);
} }
return; return;
} }
@ -10336,7 +10366,7 @@ void P_PlayerAfterThink(player_t *player)
if (P_IsLocalPlayer(player) && (player->pflags & PF_WPNDOWN) && player->currentweapon != oldweapon) if (P_IsLocalPlayer(player) && (player->pflags & PF_WPNDOWN) && player->currentweapon != oldweapon)
S_StartSound(NULL, sfx_wepchg); 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); P_SetPlayerMobjState(player->mo, player->mo->info->painstate);
/* if (player->powers[pw_carry] == CR_NONE && player->mo->tracer && !player->homing) /* if (player->powers[pw_carry] == CR_NONE && player->mo->tracer && !player->homing)
@ -10503,14 +10533,14 @@ void P_PlayerAfterThink(player_t *player)
if (player->followmobj && (player->spectator || player->mo->health <= 0 || player->followmobj->type != player->followitem)) if (player->followmobj && (player->spectator || player->mo->health <= 0 || player->followmobj->type != player->followitem))
{ {
P_RemoveMobj(player->followmobj); P_RemoveMobj(player->followmobj);
player->followmobj = NULL; P_SetTarget(&player->followmobj, NULL);
} }
if (!player->spectator && player->mo->health && player->followitem) if (!player->spectator && player->mo->health && player->followitem)
{ {
if (!player->followmobj || P_MobjWasRemoved(player->followmobj)) 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); P_SetTarget(&player->followmobj->tracer, player->mo);
player->followmobj->flags2 |= MF2_LINKDRAW; player->followmobj->flags2 |= MF2_LINKDRAW;
} }

View file

@ -1362,7 +1362,7 @@ INT32 R_ColormapNumForName(char *name)
extra_colormaps[num_extra_colormaps].fadecolor = 0x0; extra_colormaps[num_extra_colormaps].fadecolor = 0x0;
extra_colormaps[num_extra_colormaps].maskamt = 0x0; extra_colormaps[num_extra_colormaps].maskamt = 0x0;
extra_colormaps[num_extra_colormaps].fadestart = 0; extra_colormaps[num_extra_colormaps].fadestart = 0;
extra_colormaps[num_extra_colormaps].fadeend = 33; extra_colormaps[num_extra_colormaps].fadeend = 31;
extra_colormaps[num_extra_colormaps].fog = 0; extra_colormaps[num_extra_colormaps].fog = 0;
num_extra_colormaps++; num_extra_colormaps++;
@ -1390,7 +1390,7 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
size_t mapnum = num_extra_colormaps; size_t mapnum = num_extra_colormaps;
size_t i; size_t i;
UINT32 cr, cg, cb, maskcolor, fadecolor; UINT32 cr, cg, cb, maskcolor, fadecolor;
UINT32 fadestart = 0, fadeend = 33, fadedist = 33; UINT32 fadestart = 0, fadeend = 31, fadedist = 31;
#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
if (p1[0] == '#') if (p1[0] == '#')
@ -1431,12 +1431,12 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3)
// Get parameters like fadestart, fadeend, and the fogflag // Get parameters like fadestart, fadeend, and the fogflag
fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);
fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10);
if (fadestart > 32) if (fadestart > 30)
fadestart = 0; fadestart = 0;
if (fadeend > 33 || fadeend < 1) if (fadeend > 31 || fadeend < 1)
fadeend = 33; fadeend = 31;
fadedist = fadeend - fadestart; fadedist = fadeend - fadestart;
fog = NUMFROMCHAR(p2[1]) ? 1 : 0; fog = NUMFROMCHAR(p2[1]);
} }
#undef getnum #undef getnum
@ -1537,7 +1537,7 @@ void R_CreateColormap2(char *p1, char *p2, char *p3)
size_t i; size_t i;
char *colormap_p; char *colormap_p;
UINT32 cr, cg, cb, maskcolor, fadecolor; UINT32 cr, cg, cb, maskcolor, fadecolor;
UINT32 fadestart = 0, fadeend = 33, fadedist = 33; UINT32 fadestart = 0, fadeend = 31, fadedist = 31;
#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) #define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0)
if (p1[0] == '#') if (p1[0] == '#')
@ -1578,12 +1578,12 @@ void R_CreateColormap2(char *p1, char *p2, char *p3)
// Get parameters like fadestart, fadeend, and the fogflag // Get parameters like fadestart, fadeend, and the fogflag
fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10);
fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10);
if (fadestart > 32) if (fadestart > 30)
fadestart = 0; fadestart = 0;
if (fadeend > 33 || fadeend < 1) if (fadeend > 31 || fadeend < 1)
fadeend = 33; fadeend = 31;
fadedist = fadeend - fadestart; fadedist = fadeend - fadestart;
fog = NUMFROMCHAR(p2[1]) ? 1 : 0; fog = NUMFROMCHAR(p2[1]);
} }
#undef getnum #undef getnum

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 {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 {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 {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 // See also the enum skincolors_t

View file

@ -394,7 +394,7 @@ void R_DrawTranslucentColumn_8(void)
// Re-map color indices from wall texture column // Re-map color indices from wall texture column
// using a lighting/special effects LUT. // using a lighting/special effects LUT.
// heightmask is the Tutti-Frutti fix // heightmask is the Tutti-Frutti fix
*dest = colormap[*(transmap + (source[frac>>FRACBITS]<<8) + (*dest))]; *dest = *(transmap + (colormap[source[frac>>FRACBITS]]<<8) + (*dest));
dest += vid.width; dest += vid.width;
if ((frac += fracstep) >= heightmask) if ((frac += fracstep) >= heightmask)
frac -= heightmask; frac -= heightmask;
@ -405,15 +405,15 @@ void R_DrawTranslucentColumn_8(void)
{ {
while ((count -= 2) >= 0) // texture height is a power of 2 while ((count -= 2) >= 0) // texture height is a power of 2
{ {
*dest = colormap[*(transmap + ((source[(frac>>FRACBITS)&heightmask]<<8)) + (*dest))]; *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest));
dest += vid.width; dest += vid.width;
frac += fracstep; frac += fracstep;
*dest = colormap[*(transmap + ((source[(frac>>FRACBITS)&heightmask]<<8)) + (*dest))]; *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest));
dest += vid.width; dest += vid.width;
frac += fracstep; frac += fracstep;
} }
if (count & 1) if (count & 1)
*dest = colormap[*(transmap + ((source[(frac>>FRACBITS)&heightmask]<<8)) + (*dest))]; *dest = *(transmap + (colormap[source[(frac>>FRACBITS)&heightmask]]<<8) + (*dest));
} }
} }
} }
@ -464,8 +464,7 @@ void R_DrawTranslatedTranslucentColumn_8(void)
// using a lighting/special effects LUT. // using a lighting/special effects LUT.
// heightmask is the Tutti-Frutti fix // heightmask is the Tutti-Frutti fix
*dest = dc_colormap[*(dc_transmap *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest));
+ (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest))];
dest += vid.width; dest += vid.width;
if ((frac += fracstep) >= heightmask) if ((frac += fracstep) >= heightmask)
@ -477,17 +476,15 @@ void R_DrawTranslatedTranslucentColumn_8(void)
{ {
while ((count -= 2) >= 0) // texture height is a power of 2 while ((count -= 2) >= 0) // texture height is a power of 2
{ {
*dest = dc_colormap[*(dc_transmap *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest));
+ (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest))];
dest += vid.width; dest += vid.width;
frac += fracstep; frac += fracstep;
*dest = dc_colormap[*(dc_transmap *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest));
+ (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]]<<8) + (*dest))];
dest += vid.width; dest += vid.width;
frac += fracstep; frac += fracstep;
} }
if (count & 1) if (count & 1)
*dest = dc_colormap[*(dc_transmap + (dc_colormap[dc_translation[dc_source[frac>>FRACBITS]]] <<8) + (*dest))]; *dest = *(dc_transmap + (dc_colormap[dc_translation[dc_source[(frac>>FRACBITS)&heightmask]]]<<8) + (*dest));
} }
} }
} }
@ -835,8 +832,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
v = (INT64)(vz*z) + viewy; v = (INT64)(vz*z) + viewy;
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
*dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest);
*dest = colormap[*(ds_transmap + (source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)] << 8) + dest[0])];
dest++; dest++;
iz += ds_sz.x; iz += ds_sz.x;
uz += ds_su.x; uz += ds_su.x;
@ -873,7 +869,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
for (i = SPANSIZE-1; i >= 0; i--) for (i = SPANSIZE-1; i >= 0; i--)
{ {
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
*dest = colormap[*(ds_transmap + (source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)] << 8) + dest[0])]; *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest);
dest++; dest++;
u += stepu; u += stepu;
v += stepv; v += stepv;
@ -889,7 +885,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
u = (INT64)(startu); u = (INT64)(startu);
v = (INT64)(startv); v = (INT64)(startv);
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
*dest = colormap[*(ds_transmap + (source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)] << 8) + dest[0])]; *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest);
} }
else else
{ {
@ -910,7 +906,7 @@ void R_DrawTiltedTranslucentSpan_8(void)
for (; width != 0; width--) for (; width != 0; width--)
{ {
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
*dest = colormap[*(ds_transmap + (source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)] << 8) + dest[0])]; *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest);
dest++; dest++;
u += stepu; u += stepu;
v += stepv; v += stepv;
@ -1221,49 +1217,49 @@ void R_DrawTranslucentSplat_8 (void)
// need! // need!
val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)];
if (val != TRANSPARENTPIXEL) if (val != TRANSPARENTPIXEL)
dest[0] = colormap[*(ds_transmap + (val << 8) + dest[0])]; dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)];
if (val != TRANSPARENTPIXEL) if (val != TRANSPARENTPIXEL)
dest[1] = colormap[*(ds_transmap + (val << 8) + dest[1])]; dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)];
if (val != TRANSPARENTPIXEL) if (val != TRANSPARENTPIXEL)
dest[2] = colormap[*(ds_transmap + (val << 8) + dest[2])]; dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)];
if (val != TRANSPARENTPIXEL) if (val != TRANSPARENTPIXEL)
dest[3] = colormap[*(ds_transmap + (val << 8) + dest[3])]; dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)];
if (val != TRANSPARENTPIXEL) if (val != TRANSPARENTPIXEL)
dest[4] = colormap[*(ds_transmap + (val << 8) + dest[4])]; dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)];
if (val != TRANSPARENTPIXEL) if (val != TRANSPARENTPIXEL)
dest[5] = colormap[*(ds_transmap + (val << 8) + dest[5])]; dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)];
if (val != TRANSPARENTPIXEL) if (val != TRANSPARENTPIXEL)
dest[6] = colormap[*(ds_transmap + (val << 8) + dest[6])]; dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)];
if (val != TRANSPARENTPIXEL) if (val != TRANSPARENTPIXEL)
dest[7] = colormap[*(ds_transmap + (val << 8) + dest[7])]; dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
@ -1274,7 +1270,7 @@ void R_DrawTranslucentSplat_8 (void)
{ {
val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)];
if (val != TRANSPARENTPIXEL) if (val != TRANSPARENTPIXEL)
*dest = colormap[*(ds_transmap + (val << 8) + *dest)]; *dest = *(ds_transmap + (colormap[val] << 8) + *dest);
dest++; dest++;
xposition += xstep; xposition += xstep;
@ -1317,35 +1313,35 @@ void R_DrawTranslucentSpan_8 (void)
// SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't
// have the uber complicated math to calculate it now, so that was a memory write we didn't // have the uber complicated math to calculate it now, so that was a memory write we didn't
// need! // need!
dest[0] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[0])]; dest[0] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[0]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
dest[1] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[1])]; dest[1] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[1]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
dest[2] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[2])]; dest[2] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[2]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
dest[3] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[3])]; dest[3] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[3]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
dest[4] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[4])]; dest[4] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[4]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
dest[5] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[5])]; dest[5] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[5]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
dest[6] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[6])]; dest[6] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[6]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
dest[7] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + dest[7])]; dest[7] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[7]);
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;
@ -1354,7 +1350,7 @@ void R_DrawTranslucentSpan_8 (void)
} }
while (count--) while (count--)
{ {
*dest = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dest)]; *dest = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + *dest);
dest++; dest++;
xposition += xstep; xposition += xstep;
yposition += ystep; yposition += ystep;

View file

@ -37,6 +37,9 @@
// Quincunx antialiasing of flats! // Quincunx antialiasing of flats!
//#define QUINCUNX //#define QUINCUNX
// good night sweet prince
#define SHITPLANESPARENCY
//SoM: 3/23/2000: Use Boom visplane hashing. //SoM: 3/23/2000: Use Boom visplane hashing.
#define MAXVISPLANES 512 #define MAXVISPLANES 512
@ -813,7 +816,11 @@ void R_DrawSinglePlane(visplane_t *pl)
else // Opaque, but allow transparent flat pixels else // Opaque, but allow transparent flat pixels
spanfunc = splatfunc; spanfunc = splatfunc;
if (pl->extra_colormap && pl->extra_colormap->fog) #ifdef SHITPLANESPARENCY
if (spanfunc == splatfunc || (pl->extra_colormap && pl->extra_colormap->fog))
#else
if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2))
#endif
light = (pl->lightlevel >> LIGHTSEGSHIFT); light = (pl->lightlevel >> LIGHTSEGSHIFT);
else else
light = LIGHTLEVELS-1; light = LIGHTLEVELS-1;
@ -867,7 +874,11 @@ void R_DrawSinglePlane(visplane_t *pl)
else // Opaque, but allow transparent flat pixels else // Opaque, but allow transparent flat pixels
spanfunc = splatfunc; spanfunc = splatfunc;
if (pl->extra_colormap && pl->extra_colormap->fog) #ifdef SHITPLANESPARENCY
if (spanfunc == splatfunc || (pl->extra_colormap && pl->extra_colormap->fog))
#else
if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2))
#endif
light = (pl->lightlevel >> LIGHTSEGSHIFT); light = (pl->lightlevel >> LIGHTSEGSHIFT);
else else
light = LIGHTLEVELS-1; light = LIGHTLEVELS-1;

View file

@ -1443,7 +1443,8 @@ static void R_RenderSegLoop (void)
#ifdef POLYOBJECTS_PLANES #ifdef POLYOBJECTS_PLANES
// Polyobject-specific hack to fix plane leaking -Red // Polyobject-specific hack to fix plane leaking -Red
if (ffloor[i].polyobj && top_w >= bottom_w) { if (ffloor[i].polyobj && top_w >= bottom_w) {
ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF; ffloor[i].plane->top[rw_x] = 0xFFFF;
ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18
} else } else
#endif #endif
@ -1467,7 +1468,8 @@ static void R_RenderSegLoop (void)
#ifdef POLYOBJECTS_PLANES #ifdef POLYOBJECTS_PLANES
// Polyobject-specific hack to fix plane leaking -Red // Polyobject-specific hack to fix plane leaking -Red
if (ffloor[i].polyobj && top_w >= bottom_w) { if (ffloor[i].polyobj && top_w >= bottom_w) {
ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF; ffloor[i].plane->top[rw_x] = 0xFFFF;
ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18
} else } else
#endif #endif
@ -2693,6 +2695,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
if (linedef->special == 41) { // HORIZON LINES if (linedef->special == 41) { // HORIZON LINES
topstep = bottomstep = 0; topstep = bottomstep = 0;
topfrac = bottomfrac = (centeryfrac>>4); topfrac = bottomfrac = (centeryfrac>>4);
topfrac++; // Prevent 1px HOM
} else { } else {
topstep = -FixedMul (rw_scalestep, worldtop); topstep = -FixedMul (rw_scalestep, worldtop);
topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale); topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);

View file

@ -717,7 +717,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
colfunc = basecolfunc; // hack: this isn't resetting properly somewhere. colfunc = basecolfunc; // hack: this isn't resetting properly somewhere.
dc_colormap = vis->colormap; 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 // translate certain pixels to white
colfunc = transcolfunc; colfunc = transcolfunc;
@ -983,7 +983,8 @@ static void R_SplitSprite(vissprite_t *sprite)
newsprite->extra_colormap = sector->lightlist[i].extra_colormap; newsprite->extra_colormap = sector->lightlist[i].extra_colormap;
if (!((newsprite->cut & SC_FULLBRIGHT) && (!newsprite->extra_colormap || !newsprite->extra_colormap->fog))) if (!((newsprite->cut & SC_FULLBRIGHT)
&& (!newsprite->extra_colormap || !(newsprite->extra_colormap->fog & 1))))
{ {
lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT); lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT);
@ -1403,7 +1404,7 @@ static void R_ProjectSprite(mobj_t *thing)
vis->cut |= SC_FULLBRIGHT; vis->cut |= SC_FULLBRIGHT;
if (vis->cut & SC_FULLBRIGHT if (vis->cut & SC_FULLBRIGHT
&& (!vis->extra_colormap || !vis->extra_colormap->fog)) && (!vis->extra_colormap || !(vis->extra_colormap->fog & 1)))
{ {
// full bright: goggles // full bright: goggles
vis->colormap = colormaps; vis->colormap = colormaps;
@ -2673,7 +2674,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
if (player->followmobj) if (player->followmobj)
{ {
P_RemoveMobj(player->followmobj); P_RemoveMobj(player->followmobj);
player->followmobj = NULL; P_SetTarget(&player->followmobj, NULL);
} }
if (player->mo) if (player->mo)

View file

@ -75,7 +75,7 @@ consvar_t stereoreverse = {"stereoreverse", "Off", CV_SAVE, CV_OnOff, NULL, 0, N
static consvar_t precachesound = {"precachesound", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; static consvar_t precachesound = {"precachesound", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
// actual general (maximum) sound & music volume, saved into the config // actual general (maximum) sound & music volume, saved into the config
consvar_t cv_soundvolume = {"soundvolume", "31", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_soundvolume = {"soundvolume", "18", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_digmusicvolume = {"digmusicvolume", "18", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_digmusicvolume = {"digmusicvolume", "18", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_midimusicvolume = {"midimusicvolume", "18", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_midimusicvolume = {"midimusicvolume", "18", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};

View file

@ -450,8 +450,9 @@ void SCR_ClosedCaptions(void)
if (splitscreen) if (splitscreen)
basey -= 8; basey -= 8;
else if ((modeattacking == ATTACKING_NIGHTS) else if ((modeattacking == ATTACKING_NIGHTS)
|| (cv_powerupdisplay.value == 2) || (!(maptol & TOL_NIGHTS)
|| (cv_powerupdisplay.value == 1 && !splitscreen && !camera.chase)) && ((cv_powerupdisplay.value == 2)
|| (cv_powerupdisplay.value == 1 && !splitscreen && !camera.chase))))
basey -= 16; basey -= 16;
} }

File diff suppressed because it is too large Load diff

View file

@ -1,425 +1,213 @@
/* XPM */ /* XPM */
static char * C:\Repo\srb2\src\sdl\SDL_icon_xpm[] = { static const char *SDL_icon_xpm[] = {
"32 32 390 2", /* columns rows colors chars-per-pixel */
" c None", "32 32 175 2 ",
". c #4F4F70", " c None",
"+ c #4D4D87", ". c #2E2E2E",
"@ c #4D4D84", "X c #3C3C3C",
"# c #4E4E6C", "o c #493939",
"$ c #6C6C95", "O c #4E473F",
"% c #5E5EB2", "+ c #161658",
"& c #6B6BE7", "@ c #131369",
"* c #7373F9", "# c #06067B",
"= c #7C7CFF", "$ c #111173",
"- c #6F70E7", "% c #16167F",
"; c #494BB2", "& c #252567",
"> c #4F4FA3", "* c #372B7C",
", c #6464D4", "= c #3D3679",
"' c #7979F5", "- c #41414A",
") c #5F5FCA", "; c #575655",
"! c #5D5D93", ": c #6A5841",
"~ c #3A3A9F", "> c #5B4B72",
"{ c #6060AC", ", c #616160",
"] c #777793", "< c #7B7B7B",
"^ c #5C5CB3", "1 c #906E49",
"/ c #7373EA", "2 c #89685D",
"( c #7A7AFF", "3 c #A67B4A",
"_ c #7575FF", "4 c #AA7F50",
": c #7979FF", "5 c #9B7560",
"< c #6264DD", "6 c #856C78",
"[ c #47478C", "7 c #997B7D",
"} c #564567", "8 c #B48552",
"| c #4647D0", "9 c #BA8A55",
"1 c #5C5CAE", "0 c #A48665",
"2 c #5E5EFF", "q c #B98F67",
"3 c #2929FF", "w c #B9946A",
"4 c #1D1DFF", "e c #B7937A",
"5 c #1919D1", "r c #C8955C",
"6 c #4F4F90", "t c #CA9966",
"7 c #1E1ECE", "y c #DAA469",
"8 c #5858FF", "u c #C9A37B",
"9 c #6767A8", "i c #D7AB7B",
"0 c #4949A0", "p c #DFB07D",
"a c #7070FB", "a c #EBAE6A",
"b c #7D7DFF", "s c #E5B27A",
"c c #7777FF", "d c #F1B779",
"d c #7373FF", "f c #0A0A83",
"e c #7272FF", "g c #05058B",
"f c #7878FF", "h c #060687",
"g c #6465D8", "j c #101089",
"h c #363886", "k c #131382",
"i c #9F7655", "l c #040494",
"j c #C89B5C", "z c #02029D",
"k c #1D1CB7", "x c #0C0B9C",
"l c #3031B1", "c c #120F9E",
"m c #1919F4", "v c #19199B",
"n c #1111FF", "b c #382D84",
"o c #1818FF", "n c #39398D",
"p c #1B1BFF", "m c #222296",
"q c #1C1CFF", "M c #0101A6",
"r c #2626B3", "N c #0A0AA2",
"s c #1E1EC8", "B c #0202AC",
"t c #1A1AE8", "V c #1919A2",
"u c #24249F", "C c #1616AD",
"v c #2F2FD2", "Z c #0000B5",
"w c #7676FF", "A c #0202BC",
"x c #6869E2", "S c #0C0CB6",
"y c #414290", "D c #1313B3",
"z c #8C6751", "F c #1011BD",
"A c #FCBA68", "G c #1B1BBE",
"B c #E9BD7D", "H c #2B2BAC",
"C c #201EB8", "J c #3737A1",
"D c #090AB8", "K c #2A26BE",
"E c #1616EB", "L c #2A29B4",
"F c #1818FD", "P c #3B3BB8",
"G c #1414EE", "I c #48478B",
"H c #1010E1", "U c #57578A",
"I c #0E0EE2", "Y c #4A499A",
"J c #0E0EF4", "T c #524F95",
"K c #0606B2", "R c #565399",
"L c #7A7A89", "E c #4C4CA8",
"M c #0C0C9A", "W c #524DA7",
"N c #0A0AA7", "Q c #5353A4",
"O c #2424E4", "! c #5555A9",
"P c #6669E6", "~ c #5555B4",
"Q c #4F4A8F", "^ c #5656B7",
"R c #BF853B", "/ c #6464A6",
"S c #FFD98D", "( c #6F67B5",
"T c #CDAB76", ") c #0404C3",
"U c #1717C4", "_ c #0707CA",
"V c #0F10BA", "` c #1414CB",
"W c #0909B6", "' c #1A1AC6",
"X c #0505C3", "] c #0A0AD3",
"Y c #0000B6", "[ c #0D0DDC",
"Z c #0000BE", "{ c #1A1AD4",
"` c #0000AD", "} c #1010DF",
" . c #1D1D83", "| c #1E1EDE",
".. c #63638E", " . c #1817DE",
"+. c #090975", ".. c #221FCA",
"@. c #1414F3", "X. c #2B2BCC",
"#. c #5B5BFF", "o. c #2727C9",
"$. c #7B7BFF", "O. c #3434C3",
"%. c #7070FF", "+. c #3434D4",
"&. c #6E6EFF", "@. c #0F0FE2",
"*. c #7172F6", "#. c #1313E5",
"=. c #625DAF", "$. c #1515ED",
"-. c #BA9E6C", "%. c #1B1BEA",
";. c #887167", "&. c #1C1CE4",
">. c #090DF2", "*. c #1515F4",
",. c #1313BE", "=. c #1818F3",
"'. c #000085", "-. c #1717FD",
"). c #0000AC", ";. c #1818FF",
"!. c #0202AA", ":. c #2B2BE9",
"~. c #242488", ">. c #2424FF",
"{. c #1414C7", ",. c #2A2AFF",
"]. c #1717FF", "<. c #2222F1",
"^. c #5959FF", "1. c #3737FF",
"/. c #7F7FFF", "2. c #5D5DC3",
"(. c #7474FF", "3. c #5F5FC9",
"_. c #7171FF", "4. c #5655C2",
":. c #8686FF", "5. c #4747D1",
"<. c #7574FF", "6. c #5B5BD4",
"[. c #797CFF", "7. c #6565C8",
"}. c #5756B8", "8. c #6363DA",
"|. c #1C19A4", "9. c #4545FF",
"1. c #1617FF", "0. c #4D4DFC",
"2. c #1212BD", "q. c #5454FF",
"3. c #040485", "w. c #5959FF",
"4. c #0707A4", "e. c #6969E5",
"5. c #1B1B71", "r. c #6B6CEA",
"6. c #373797", "t. c #6666E7",
"7. c #1616FF", "y. c #6B6BFE",
"8. c #5050FF", "u. c #6767F8",
"9. c #8080FF", "i. c #7070F6",
"0. c #AAAAFF", "p. c #7373FF",
"a. c #AEAEF6", "a. c #7C7CFF",
"b. c #8A8AEF", "s. c #91918F",
"c. c #6969FB", "d. c #8F9090",
"d. c #2728FF", "f. c #979797",
"e. c #1314FF", "g. c #9C9C9C",
"f. c #1919FF", "h. c #8585A1",
"g. c #1313E8", "j. c #9C9CA7",
"h. c #1F1FF4", "k. c #9292B6",
"i. c #5454FF", "l. c #A4A4A4",
"j. c #6D6DF0", "z. c #BDB2A4",
"k. c #6868B5", "x. c #A4A4B1",
"l. c #0B0BB8", "c. c #BFBFBD",
"m. c #1212C5", "v. c #BABAB7",
"n. c #1616FC", "b. c #C8AA87",
"o. c #1515FF", "n. c #DAAE82",
"p. c #1212FF", "m. c #DBB081",
"q. c #2323FF", "M. c #EBBA85",
"r. c #3636FF", "N. c #F3BF84",
"s. c #4040FF", "B. c #F2BE88",
"t. c #4343F9", "V. c #C2B3A3",
"u. c #5D5DB8", "C. c #FBC386",
"v. c #7F7F92", "Z. c #FCC68C",
"w. c #878793", "A. c #FFC88F",
"x. c #4B4B94", "S. c #F4C387",
"y. c #0B0CE2", "D. c #FFC990",
"z. c #1313FF", "F. c #C3C1BF",
"A. c #4C4CFF", "G. c #8F8FCB",
"B. c #8282FF", "H. c #BDBDC2",
"C. c #7171ED", "J. c #BDBDD1",
"D. c #636394", "K. c #8888F9",
"E. c #575785", "L. c #A4A4FB",
"F. c #A9A99C", "P. c #CDCDCC",
"G. c #1414BC", "I. c #CECAC6",
"H. c #1414FF", "U. c #D3CFCA",
"I. c #0707FD", "Y. c #D3D0CC",
"J. c #2525AA", "T. c #C0C0D5",
"K. c #A8A8A4", "R. c #D6D5D4",
"L. c #EBEBE2", "E. c #D7D7DD",
"M. c #F9F9F2", "W. c #E1E1DF",
"N. c #E1E1CC", "Q. c #DEDEE1",
"O. c #4D4D9F", "!. c #E4E4E4",
"P. c #0B0BF7", "~. c #E8E8E8",
"Q. c #2121FF", "^. c #F0F0EE",
"R. c #3232FF", "/. c #F5F5F2",
"S. c #5555FF", "(. c #FFFFFF",
"T. c #6161B4", /* pixels */
"U. c #B5B5B2",
"V. c #FFFFF8",
"W. c #4F4F9A",
"X. c #0B0BF5",
"Y. c #1616C5",
"Z. c #A8A8A1",
"`. c #FFFFFC",
" + c #FFFFFF",
".+ c #C0C0C4",
"++ c #1212D4",
"@+ c #4444FF",
"#+ c #6464FF",
"$+ c #8383FF",
"%+ c #6767C3",
"&+ c #E4E4E4",
"*+ c #9494AE",
"=+ c #0808DF",
"-+ c #0D0DF2",
";+ c #61619A",
">+ c #F1F1E0",
",+ c #E8E8DD",
"'+ c #2424BB",
")+ c #1010FF",
"!+ c #3434FF",
"~+ c #6161FF",
"{+ c #6969D2",
"]+ c #EFEFF0",
"^+ c #C2C2BA",
"/+ c #1010B6",
"(+ c #0909AC",
"_+ c #A4A49A",
":+ c #EAEADE",
"<+ c #2525B8",
"[+ c #2F2FFF",
"}+ c #3C3CB5",
"|+ c #EEEEEE",
"1+ c #BBBBAD",
"2+ c #0B0B56",
"3+ c #0B0BFC",
"4+ c #1212EF",
"5+ c #0C0C3E",
"6+ c #919187",
"7+ c #DEDED6",
"8+ c #1F1FC0",
"9+ c #1A1AFF",
"0+ c #1717FA",
"a+ c #1515F8",
"b+ c #1111FC",
"c+ c #494992",
"d+ c #999998",
"e+ c #3E3E3B",
"f+ c #3C3C99",
"g+ c #535397",
"h+ c #5A5A4D",
"i+ c #6F6F70",
"j+ c #BFBFC9",
"k+ c #1111D6",
"l+ c #1515F1",
"m+ c #0F0FE2",
"n+ c #0D0DD9",
"o+ c #0909CD",
"p+ c #0808C7",
"q+ c #0505C7",
"r+ c #0303CB",
"s+ c #0101C0",
"t+ c #0202AF",
"u+ c #0606AC",
"v+ c #121283",
"w+ c #BBBBBB",
"x+ c #BEBEBE",
"y+ c #2F2F2E",
"z+ c #C7C8BB",
"A+ c #D8DAD1",
"B+ c #272828",
"C+ c #929292",
"D+ c #8688C7",
"E+ c #0506F6",
"F+ c #1616F5",
"G+ c #0B0BD3",
"H+ c #0202B6",
"I+ c #0000AF",
"J+ c #0000B4",
"K+ c #0000BD",
"L+ c #0000BB",
"M+ c #00009E",
"N+ c #2C2C7E",
"O+ c #6A6A8B",
"P+ c #959595",
"Q+ c #F0F0F1",
"R+ c #E1E1E1",
"S+ c #8C8E90",
"T+ c #BEBEBF",
"U+ c #C9C7C5",
"V+ c #939699",
"W+ c #E7EAED",
"X+ c #CBCBC7",
"Y+ c #413B9B",
"Z+ c #0607DD",
"`+ c #0C0CE2",
" @ c #0303B9",
".@ c #0000A8",
"+@ c #181888",
"@@ c #6A6A6A",
"#@ c #626263",
"$@ c #4B4B4C",
"%@ c #3E3B36",
"&@ c #9B805C",
"*@ c #D9B07D",
"=@ c #C9AE89",
"-@ c #B9AF9E",
";@ c #C7C5C4",
">@ c #CBCCCF",
",@ c #C7C6C6",
"'@ c #AEA59A",
")@ c #B69974",
"!@ c #D8B87F",
"~@ c #9B8272",
"{@ c #0E0B9B",
"]@ c #0000B7",
"^@ c #0000B8",
"/@ c #000082",
"(@ c #00007A",
"_@ c #636379",
":@ c #62533E",
"<@ c #B59B6C",
"[@ c #DEB07B",
"}@ c #FECC90",
"|@ c #FFCE92",
"1@ c #FEC98C",
"2@ c #F1BD82",
"3@ c #D1A979",
"4@ c #BC9E73",
"5@ c #CCA777",
"6@ c #EAB980",
"7@ c #FFCD90",
"8@ c #FFD595",
"9@ c #FDD782",
"0@ c #413678",
"a@ c #0000AE",
"b@ c #000077",
"c@ c #010193",
"d@ c #0C0CE4",
"e@ c #38389E",
"f@ c #EEC585",
"g@ c #FFDA9D",
"h@ c #FFC992",
"i@ c #FFC88F",
"j@ c #FFC990",
"k@ c #FFCE93",
"l@ c #FFD094",
"m@ c #FFCC92",
"n@ c #C9A174",
"o@ c #EDBD88",
"p@ c #FAD287",
"q@ c #3A2F7F",
"r@ c #0000BA",
"s@ c #0000B0",
"t@ c #0101B2",
"u@ c #1111ED",
"v@ c #1919C1",
"w@ c #95887C",
"x@ c #DCAC6E",
"y@ c #FFD393",
"z@ c #FFCD94",
"A@ c #FFCA93",
"B@ c #FFC991",
"C@ c #FFC78E",
"D@ c #FFCB91",
"E@ c #E0B581",
"F@ c #BB9A6F",
"G@ c #FFDC97",
"H@ c #C1A173",
"I@ c #0E0B9A",
"J@ c #0000B5",
"K@ c #0101B6",
"L@ c #1010E0",
"M@ c #1616EC",
"N@ c #A68156",
"O@ c #E7AC6B",
"P@ c #FFC582",
"Q@ c #FFCF8F",
"R@ c #FFD195",
"S@ c #FFD296",
"T@ c #FFD396",
"U@ c #FFD193",
"V@ c #FFD28F",
"W@ c #D2A96B",
"X@ c #2F2482",
"Y@ c #0000C1",
"Z@ c #0000C0",
"`@ c #0000BF",
" # c #0101BF",
".# c #1212F0",
"+# c #767698",
"@# c #9C866E",
"## c #A9865D",
"$# c #C0915D",
"%# c #C89760",
"&# c #C29360",
"*# c #AD8A61",
"=# c #9D8971",
"-# c #7F7A7A",
";# c #70708F",
"># c #6F6F91",
",# c #575788",
"'# c #464687",
")# c #2F2F87",
"!# c #15158F",
"~# c #0101A8",
"{# c #1313FB",
"]# c #57579F",
"^# c #343487",
"/# c #434388",
" ", " ",
" ", " ",
" ", " ",
" . + @ # ", " I Q T = ",
" $ % & * = - ; > , ' ) ! ", " Q 7.e.r.i.8.E E 3.r.6.J ",
" ~ { ] ^ / = ( _ : < [ } | 1 2 3 4 5 6 ", " H ~ n 4.r.p.p.p.p.8.R > 5.^ w.,.-.{ v ",
" 7 8 9 0 a b c d e f g h i j k l m n o p q r ", " { 9.^ & P t.p.p.p.p.p.8.I 5 q K L <.;.;.;.-.' ",
" s t u v _ f d d d w x y z A B C D E F G H I J K L ", " { %.H +.y.p.p.p.p.p.e.Y 2 a n.K F $.*.$.@.} ] N ",
" M N O _ c e d d d _ P Q R S T U V W X Y Z ` ... ", " x D :.y.p.p.p.p.p.p.r.R 8 C.u ..F A ) A Z M h $ ",
" +.@.#.$.d d d d %.&._ *.=.-.;.>.,.'.).!.~. ", " f =.q.p.p.p.p.p.p.p.p.i.( e 6 $.` l B M g ",
" {.].^./.(.d d _.$.:._ <.[.}.|.1.2.3.4.5. ", " ` ;.q.p.p.p.p.p.a.K.a.p.p.4.L -.` l N % ",
" 6.7.7.4 8.e : w 9.0.a.b.c.2 d.e.f.g.h.i.j.k. ", " V =.-.>.q.y.p.p.p.L.L.K.i.w.,.-.;.$.<.q.u.2. ",
" l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.o o z.A.B./.b C.D. ", " D { =.-.;.>.1.1.9.( h.h.Q &.-.-.-.;.9.p.p.p.r.! ",
" E.F.G.].o H.z.I.J.K.L.M.N.O.P.o o o Q.R.S._.b B.T. ", " U j.o.-.;.-.;.-.P x.Q.^.R.~ *.-.;.;.>.1.q.y.p.i.2. ",
" U.V.W.X.f.f.7.Y.Z.`. + + +.+++].o o o.n z.q.@+#+$+%+ ", " H./.! *.;.;.;.o.x./.(.(.(.J.| -.-.;.-.-.;.,.9.u.p.7. ",
" &+ +*+=+].o -+;+>+ + + + +,+'+H.o o o o o H.)+o !+~+{+ ", " !.(.k.#.;.-.=./ !.(.(.(.(.Q.X.-.;.;.;.;.-.-.;.;.1.w.6. ",
" ]+ +^+/+H.o.(+_+ + + + + +:+<+z.o o o o o o o 7.n H.[+}+ ", " ~.(.H.G ;.-.D j.(.(.(.(.(.!.O.-.-.;.;.;.-.;.-.;.-.;.,.O. ",
" |+ +1+2+3+4+5+6+ + + + + +7+8+H.o o f.9+f.9+f.F 0+a+b+o.c+ ", " ~.(.v.@ *.$.+ d.(.(.(.(.(.E.o.-.-.;.;.-.;.;.;.*.=.=.*.$.v ",
" &+ +d+e+f+g+h+i+ + + + + +j+k+].f.9+l+m+n+o+p+q+r+s+t+u+v+ ", " ~.(.l.- Y T ; < (.(.(.(.(.J.&.-.;.;.$.@.[ ] _ ) ) Z B B f ",
" w+ +x+y+z+A+B+C+ + + + + +D+E+9+F+G+H+I+J+K+L+M+N+O+ ", " P.(.F.X c.I.X f.(.(.(.(.(.G.=.-.=.] A Z Z Z Z z f $ ",
" P+Q+R+S+T+U+V+W+ + + + +X+Y+Z+`+ @I+J+Z .@+@E. ", " l.!.R.s.F.I.g.W.(.(.(.(.R.E .[ A Z Z Z B g $ ",
" @@#@$@%@&@*@=@-@;@>@,@'@)@!@~@{@]@^@I+/@(@_@ ", " . , ; - 0 M.b.V.U.R.Y.z.u n.7 c Z Z B g # + ",
" :@<@[@}@|@1@2@3@4@5@6@7@8@9@0@L+a@b@c@d@e@ ", " : w p Z.D.A.S.p u i M.A.A.S.* Z B h z ] C ",
" f@g@h@i@i@j@k@l@|@m@n@o@p@q@r@s@t@u@p v@ ", " s D.D.A.A.A.A.A.A.A.i B.B.b A Z Z @.-.` ",
" w@x@y@z@A@B@i@C@D@E@F@G@H@I@L+J@K@L@p M@ ", " 1 y C.D.A.A.A.A.A.M.u Z.e c A Z Z [ ;.&. ",
" N@O@P@Q@R@S@T@U@V@W@X@Y@Z@Y@`@ #.#p +# ", " 8 y d C.A.A.A.C.B.t * B Z Z Z A #.=.m ",
" @###$#%#&#*#=#-#;#>#,#'#)#!#~#{#]# ", " 3 9 r t r 9 8 o @ $ # f j l B #.V ",
" ^#/# ", " j k ",
" ", " ",
" ", " ",
" ", " ",
" "}; " "
};

View file

@ -39,6 +39,10 @@
#ifdef HAVE_IMAGE #ifdef HAVE_IMAGE
#include "SDL_image.h" #include "SDL_image.h"
#elif 1
#define LOAD_XPM //I want XPM!
#include "IMG_xpm.c" //Alam: I don't want to add SDL_Image.dll/so
#define HAVE_IMAGE //I have SDL_Image, sortof
#endif #endif
#ifdef HAVE_IMAGE #ifdef HAVE_IMAGE

View file

@ -66,6 +66,7 @@ static boolean midimode;
static Mix_Music *music; static Mix_Music *music;
static UINT8 music_volume, midi_volume, sfx_volume; static UINT8 music_volume, midi_volume, sfx_volume;
static float loop_point; static float loop_point;
static boolean songpaused;
#ifdef HAVE_LIBGME #ifdef HAVE_LIBGME
static Music_Emu *gme; static Music_Emu *gme;
@ -102,6 +103,7 @@ void I_StartupSound(void)
} }
sound_started = true; sound_started = true;
songpaused = false;
Mix_AllocateChannels(256); Mix_AllocateChannels(256);
} }
@ -176,7 +178,7 @@ static Mix_Chunk *ds2chunk(void *stream)
return NULL; // would and/or did wrap, can't store. return NULL; // would and/or did wrap, can't store.
break; break;
} }
sound = Z_Malloc(newsamples<<2, PU_SOUND, NULL); // samples * frequency shift * bytes per sample * channels sound = malloc(newsamples<<2); // samples * frequency shift * bytes per sample * channels
s = (SINT8 *)stream; s = (SINT8 *)stream;
d = (INT16 *)sound; d = (INT16 *)sound;
@ -304,7 +306,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
gme_track_info(emu, &info, 0); gme_track_info(emu, &info, 0);
len = (info->play_length * 441 / 10) << 2; len = (info->play_length * 441 / 10) << 2;
mem = Z_Malloc(len, PU_SOUND, NULL); mem = malloc(len);
gme_play(emu, len >> 1, mem); gme_play(emu, len >> 1, mem);
gme_delete(emu); gme_delete(emu);
@ -376,7 +378,7 @@ void *I_GetSfx(sfxinfo_t *sfx)
gme_track_info(emu, &info, 0); gme_track_info(emu, &info, 0);
len = (info->play_length * 441 / 10) << 2; len = (info->play_length * 441 / 10) << 2;
mem = Z_Malloc(len, PU_SOUND, NULL); mem = malloc(len);
gme_play(emu, len >> 1, mem); gme_play(emu, len >> 1, mem);
gme_delete(emu); gme_delete(emu);
@ -450,7 +452,7 @@ static void mix_gme(void *udata, Uint8 *stream, int len)
(void)udata; (void)udata;
// no gme? no music. // no gme? no music.
if (!gme || gme_track_ended(gme)) if (!gme || gme_track_ended(gme) || songpaused)
return; return;
// play gme into stream // play gme into stream
@ -458,7 +460,7 @@ static void mix_gme(void *udata, Uint8 *stream, int len)
// apply volume to stream // apply volume to stream
for (i = 0, p = (short *)stream; i < len/2; i++, p++) 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 #endif
@ -476,12 +478,14 @@ void I_PauseSong(INT32 handle)
{ {
(void)handle; (void)handle;
Mix_PauseMusic(); Mix_PauseMusic();
songpaused = true;
} }
void I_ResumeSong(INT32 handle) void I_ResumeSong(INT32 handle)
{ {
(void)handle; (void)handle;
Mix_ResumeMusic(); Mix_ResumeMusic();
songpaused = false;
} }
// //

View file

@ -65,7 +65,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"buzz1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Electric zap"}, {"buzz1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Electric zap"},
{"buzz2", 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"}, {"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 {"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"}, {"fire", false, 8, 32, -1, NULL, 0, -1, -1, LUMPERROR, "Flamethrower"},
{"grind", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Metallic grinding"}, {"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 {"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 {"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"}, {"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"}, {"rainin", true, 24, 4, -1, NULL, 0, -1, -1, LUMPERROR, "Rain"},
{"litng1", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning"}, {"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! {"bnce1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"}, // Boing!
{"bnce2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Scatter"}, // 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"}, {"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"}, {"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"}, {"ding", false, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Ding"},
{"dmpain", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Machine damage"}, {"dmpain", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Machine damage"},
{"drown", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drowning"}, {"drown", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drowning"},
{"fizzle", false, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Electric fizzle"}, {"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 {"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"}, {"ghit" , false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Goop splash"},
{"gloop", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "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"}, {"spring", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spring"},
{"statu1", true, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Pushing a statue"}, {"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"}, {"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"}, {"supert", true, 127, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Transformation"},
{"telept", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Dash"}, {"telept", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Dash"},
{"tink" , false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Tink"}, {"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"}, {"trfire", true, 60, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Laser fired"},
{"trpowr", true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"}, {"trpowr", true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"},
{"turhit", false, 40, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Laser hit"}, {"turhit", false, 40, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Laser hit"},
{"wdjump", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Whirlwind jump"}, {"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"}, {"mswarp", false, 60, 16, -1, NULL, 0, -1, -1, LUMPERROR, "Spinning out"},
{"mspogo", false, 60, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Breaking through"}, {"mspogo", false, 60, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Breaking through"},
{"boingf", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bouncing"}, {"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 {"xideya", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Success"}, // Xmas
{"nbmper", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, {"nbmper", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"},
{"nxbump", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, // Xmas {"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"}, {"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 {"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"}, {"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 {"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"}, {"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 {"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"}, {"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++"}, {"hoop3", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hoop++"},
{"hidden", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"}, {"hidden", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"},
{"prloop", false, 104, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Gust of wind"}, {"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 // Mario
{"koopfr" , true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Fire"}, {"koopfr" , true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Fire"},
{"mario1", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hitting a ceiling"}, {"mario1", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hit"},
{"mario2", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Koopa shell"}, {"mario2", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bonk"},
{"mario3", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power-up"}, {"mario3", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power-up"},
{"mario4", true, 78, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got coin"}, {"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"}, {"mario6", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"},
{"mario7", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Fire"}, {"mario7", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Fire"},
{"mario8", false, 48, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Hurt"}, {"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"}, {"marioa", true, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "One-up"},
{"thwomp", true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Thwomp"}, {"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"}, {"s3k3d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pop"},
{"s3k3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame Shield"}, {"s3k3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame Shield"},
{"s3k3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble 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"}, {"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning Shield"},
{"s3k42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Twinspin"}, {"s3k42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Twinspin"},
{"s3k43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame burst"}, {"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"}, {"s3k45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning zap"},
{"s3k46", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Transformation"}, {"s3k46", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Transformation"},
{"s3k47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising dust"}, {"s3k47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising dust"},
{"s3k48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Metallic clink"}, {"s3k48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pulse"},
{"s3k49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling rock"}, {"s3k49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Impact"},
{"s3k4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Grab"}, {"s3k4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Grab"},
{"s3k4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Water splash"}, {"s3k4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Water splash"},
{"s3k4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy hit"}, {"s3k4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy hit"},
{"s3k4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing bullet"}, {"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"}, {"s3k4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flamethrower"},
{"s3k50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Siren"}, {"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"}, {"s3k52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spike"},
{"s3k53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"}, {"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 {"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"}, {"s3k55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical movement"},
{"s3k56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy landing"}, {"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"}, {"s3k58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical movement"},
{"s3k59", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crumbling"}, {"s3k59", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crumbling"},
{"s3k5a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, {"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"}, {"s3k62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"},
{"s3k63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"}, {"s3k63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"},
{"s3k64", false, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Clatter"}, {"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 {"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 clear"}, {"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"}, {"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"}, {"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"}, {"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"}, {"s3k6c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"},
{"s3k6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s3k6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3k6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical damage"}, {"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"}, {"s3k89", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Advanced technology"},
{"s3k8a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Boing"}, {"s3k8a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Boing"},
{"s3k8b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful hit"}, {"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, ""}, {"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"}, {"s3k8f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Opening"},
{"s3k90", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Impact"}, {"s3k90", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Impact"},
{"s3k91", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Closed"}, {"s3k91", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Closed"},
{"s3k92", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ghost"}, {"s3k92", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ghost"},
{"s3k93", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rebuilding"}, {"s3k93", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rebuilding"},
{"s3k94", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spike"}, {"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"}, {"s3k96", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling object"},
{"s3k97", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wind"}, {"s3k97", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wind"},
{"s3k98", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling spike"}, {"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 {"s3kc3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Levitation"}, // ditto
{"s3kc4s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing laser"}, {"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 {"s3kc4l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing laser"}, // ditto
{"s3kc5s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s3kc5s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Revving up"},
{"s3kc5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto {"s3kc5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Revving up"}, // ditto
{"s3kc6s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"}, {"s3kc6s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"},
{"s3kc6l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"}, // ditto {"s3kc6l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"}, // ditto
{"s3kc7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, {"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, ""}, {"s3kd1s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3kd1l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto {"s3kd1l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto
{"s3kd2s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turning"}, {"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, ""}, {"s3kd3s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3kd3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto {"s3kd3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto
{"s3kd4s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Engine"}, {"s3kd4s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Engine"},

View file

@ -142,6 +142,8 @@ typedef enum
sfx_steam1, sfx_steam1,
sfx_steam2, sfx_steam2,
sfx_wbreak, sfx_wbreak,
sfx_ambmac,
sfx_spsmsh,
sfx_rainin, sfx_rainin,
sfx_litng1, sfx_litng1,
@ -252,6 +254,8 @@ typedef enum
sfx_trpowr, sfx_trpowr,
sfx_turhit, sfx_turhit,
sfx_wdjump, sfx_wdjump,
sfx_shrpsp,
sfx_shrpgo,
sfx_mswarp, sfx_mswarp,
sfx_mspogo, sfx_mspogo,
sfx_boingf, sfx_boingf,
@ -276,6 +280,7 @@ typedef enum
sfx_xideya, // Xmas sfx_xideya, // Xmas
sfx_nbmper, sfx_nbmper,
sfx_nxbump, // Xmas sfx_nxbump, // Xmas
sfx_ncchip,
sfx_ncitem, sfx_ncitem,
sfx_nxitem, // Xmas sfx_nxitem, // Xmas
sfx_ngdone, sfx_ngdone,
@ -290,7 +295,14 @@ typedef enum
sfx_hoop3, sfx_hoop3,
sfx_hidden, sfx_hidden,
sfx_prloop, 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 // Mario
sfx_koopfr, sfx_koopfr,

View file

@ -79,7 +79,6 @@ static patch_t *race1;
static patch_t *race2; static patch_t *race2;
static patch_t *race3; static patch_t *race3;
static patch_t *racego; static patch_t *racego;
static patch_t *ttlnum;
static patch_t *nightslink; static patch_t *nightslink;
static patch_t *curweapon; static patch_t *curweapon;
static patch_t *normring; static patch_t *normring;
@ -112,6 +111,8 @@ static patch_t *yelstat;
static patch_t *nbracket; static patch_t *nbracket;
static patch_t *nhud[12]; static patch_t *nhud[12];
static patch_t *nsshud; static patch_t *nsshud;
static patch_t *nbon[12];
static patch_t *nssbon;
static patch_t *narrow[9]; static patch_t *narrow[9];
static patch_t *nredar[8]; // Red arrow static patch_t *nredar[8]; // Red arrow
static patch_t *drillbar; static patch_t *drillbar;
@ -309,8 +310,12 @@ void ST_LoadGraphics(void)
yelstat = W_CachePatchName("YELSTAT", PU_HUDGFX); yelstat = W_CachePatchName("YELSTAT", PU_HUDGFX);
nbracket = W_CachePatchName("NBRACKET", PU_HUDGFX); nbracket = W_CachePatchName("NBRACKET", PU_HUDGFX);
for (i = 0; i < 12; ++i) for (i = 0; i < 12; ++i)
{
nhud[i] = W_CachePatchName(va("NHUD%d", i+1), PU_HUDGFX); 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); nsshud = W_CachePatchName("NSSHUD", PU_HUDGFX);
nssbon = W_CachePatchName("NSSBON", PU_HUDGFX);
minicaps = W_CachePatchName("MINICAPS", PU_HUDGFX); minicaps = W_CachePatchName("MINICAPS", PU_HUDGFX);
for (i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
@ -659,9 +664,9 @@ static void ST_drawTime(void)
else else
{ {
// Counting down the hidetime? // 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) if (tics < 3*TICRATE)
ST_drawRaceNum(tics); ST_drawRaceNum(tics);
downwards = true; downwards = true;
@ -669,15 +674,15 @@ static void ST_drawTime(void)
else else
{ {
// Hidetime finish! // Hidetime finish!
if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (leveltime < ((hidetime+1)*TICRATE))) if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (stplyr->realtime < ((hidetime+1)*TICRATE)))
ST_drawRaceNum(hidetime*TICRATE - leveltime); ST_drawRaceNum(hidetime*TICRATE - stplyr->realtime);
// Time limit? // 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) if (tics < 3*TICRATE)
ST_drawRaceNum(tics); ST_drawRaceNum(tics);
} }
@ -735,18 +740,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)); ST_DrawPatchFromHud(HUD_RINGS, ((!stplyr->spectator && stplyr->rings <= 0 && leveltime/5 & 1) ? sboredrings : sborings), ((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS));
if (objectplacing) ringnum = ((objectplacing) ? op_currentdoomednum : max(stplyr->rings, 0));
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);
if (cv_timetic.value == 2) // Yes, even in modeattacking if (cv_timetic.value == 2) // Yes, even in modeattacking
ST_DrawNumFromHud(HUD_RINGSNUMTICS, ringnum, V_PERPLAYER|((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS)); ST_DrawNumFromHud(HUD_RINGSNUMTICS, ringnum, V_PERPLAYER|((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS));
@ -1098,7 +1092,8 @@ static void ST_drawInput(void)
((!stplyr->powers[pw_carry] ((!stplyr->powers[pw_carry]
&& (stplyr->pflags & PF_APPLYAUTOBRAKE) && (stplyr->pflags & PF_APPLYAUTOBRAKE)
&& !(stplyr->cmd.sidemove || stplyr->cmd.forwardmove) && !(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), ? 0 : V_GRAYMAP),
"AUTOBRAKE"); "AUTOBRAKE");
y -= 8; y -= 8;
@ -1124,13 +1119,10 @@ void ST_drawLevelTitle(tic_t titletime)
if (!(titletime > 2 && titletime-3 < 110)) if (!(titletime > 2 && titletime-3 < 110))
return; return;
lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2));
if (actnum > 0) if (actnum > 0)
{ lvlttlxpos -= V_LevelActNumWidth(actnum);
ttlnum = W_CachePatchName(va("TTL%.2d", actnum), PU_CACHE);
lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2)) - SHORT(ttlnum->width);
}
else
lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2));
ttlnumxpos = lvlttlxpos + V_LevelNameWidth(lvlttl); ttlnumxpos = lvlttlxpos + V_LevelNameWidth(lvlttl);
zonexpos = ttlnumxpos - V_LevelNameWidth(M_GetText("ZONE")); zonexpos = ttlnumxpos - V_LevelNameWidth(M_GetText("ZONE"));
@ -1190,7 +1182,7 @@ void ST_drawLevelTitle(tic_t titletime)
#endif #endif
if (actnum) if (actnum)
V_DrawScaledPatch(ttlnumxpos, zoney, V_PERPLAYER, ttlnum); V_DrawLevelActNum(ttlnumxpos, zoney, V_PERPLAYER, actnum);
V_DrawLevelTitle(lvlttlxpos, lvlttly, V_PERPLAYER, lvlttl); V_DrawLevelTitle(lvlttlxpos, lvlttly, V_PERPLAYER, lvlttl);
@ -1394,17 +1386,17 @@ static void ST_drawNightsRecords(void)
V_DrawCenteredString(BASEVIDWIDTH/2, 60, aflag, V_DrawCenteredString(BASEVIDWIDTH/2, 60, aflag,
va(M_GetText("\x80GET\x82 %d\x80 %s%s%s!"), stplyr->capsule->health, va(M_GetText("\x80GET\x82 %d\x80 %s%s%s!"), stplyr->capsule->health,
(stplyr->textvar == 3) ? M_GetText("MORE ") : "", (stplyr->textvar == 3) ? M_GetText("MORE ") : "",
(G_IsSpecialStage(gamemap)) ? "SPHERE" : "RING", (G_IsSpecialStage(gamemap)) ? "SPHERE" : "CHIP",
(stplyr->capsule->health > 1) ? "S" : "")); (stplyr->capsule->health > 1) ? "S" : ""));
} }
// End Bonus // End Bonus
else if (stplyr->textvar == 4) 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_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->finishedspheres));
V_DrawRightAlignedString(BASEVIDWIDTH/2 + 56, 140, V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings * 50)); 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); ST_DrawNightsOverlayNum((BASEVIDWIDTH/2 + 56)<<FRACBITS, 160<<FRACBITS, FRACUNIT, aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_AZURE);
// If new record, say so! // If new record, say so!
@ -1462,15 +1454,15 @@ static void ST_drawNiGHTSHUD(void)
{ {
INT32 origamount; INT32 origamount;
INT32 minlink = 1; INT32 minlink = 1;
INT32 total_ringcount; INT32 total_spherecount;
const boolean oldspecialstage = (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS));
// When debugging, show "0 Link".
if (cv_debug & DBG_NIGHTSBASIC)
minlink = 0;
// Cheap hack: don't display when the score is showing (it popping up for a split second when exiting a map is intentional) // 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; minlink = INT32_MAX;
// When debugging, show "0 Link".
else if (cv_debug & DBG_NIGHTSBASIC)
minlink = 0;
// Drill meter // Drill meter
if ( if (
@ -1576,25 +1568,37 @@ static void ST_drawNiGHTSHUD(void)
// Begin drawing brackets/chip display // Begin drawing brackets/chip display
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
if (LUA_HudEnabled(hud_nightsrings)) if (LUA_HudEnabled(hud_nightsspheres))
{ {
#endif #endif
ST_DrawTopLeftOverlayPatch(16, 8, nbracket); ST_DrawTopLeftOverlayPatch(16, 8, nbracket);
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
ST_DrawTopLeftOverlayPatch(24, 16, nsshud); ST_DrawTopLeftOverlayPatch(24, 16, (
#ifdef MANIASPHERES
(stplyr->bonustime && (leveltime & 4)) ? nssbon :
#endif
nsshud));
else else
ST_DrawTopLeftOverlayPatch(24, 16, nhud[(leveltime/2)%12]); ST_DrawTopLeftOverlayPatch(24, 16, *(((stplyr->bonustime) ? nbon : nhud)+((leveltime/2)%12)));
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
{ {
INT32 i; INT32 i;
total_ringcount = 0; total_spherecount = 0;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/ && players[i].rings) if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/ && players[i].spheres)
total_ringcount += players[i].rings; total_spherecount += players[i].spheres;
} }
else 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) if (stplyr->capsule)
{ {
@ -1650,28 +1654,48 @@ static void ST_drawNiGHTSHUD(void)
amount = (origamount - stplyr->capsule->health); amount = (origamount - stplyr->capsule->health);
amount = (amount * length)/origamount; 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); V_DrawScaledPatch(15 + cfill + 1, 8 + 35, V_PERPLAYER|V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulefill);
} }
if (total_ringcount >= stplyr->capsule->health) if (total_spherecount >= stplyr->capsule->health)
ST_DrawTopLeftOverlayPatch(40, 8 + 5, nredar[leveltime%8]); ST_DrawTopLeftOverlayPatch(40, 8 + 5, nredar[leveltime&7]);
else 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 else
ST_DrawTopLeftOverlayPatch(40, 8 + 5, narrow[8]); ST_DrawTopLeftOverlayPatch(40, 8 + 5, narrow[8]);
if (total_ringcount >= 100) if (total_spherecount >= 100)
V_DrawTallNum((total_ringcount >= 1000) ? 76 : 72, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_ringcount); V_DrawTallNum((total_spherecount >= 1000) ? 76 : 72, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_spherecount);
else 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 #ifdef HAVE_BLUA
} }
#endif #endif
// Score // Score
if (!stplyr->exiting if (!stplyr->exiting && !oldspecialstage
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
&& LUA_HudEnabled(hud_nightsscore) && LUA_HudEnabled(hud_nightsscore)
#endif #endif
@ -1714,6 +1738,7 @@ static void ST_drawNiGHTSHUD(void)
{ {
INT32 realnightstime = stplyr->nightstime/TICRATE; INT32 realnightstime = stplyr->nightstime/TICRATE;
INT32 numbersize; INT32 numbersize;
UINT8 col = ((realnightstime < 10) ? SKINCOLOR_RED : SKINCOLOR_SUPERGOLD4);
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
{ {
@ -1744,46 +1769,66 @@ static void ST_drawNiGHTSHUD(void)
else else
numbersize = 48/2; numbersize = 48/2;
ST_DrawNightsOverlayNum((160 + numbersize)<<FRACBITS, 14<<FRACBITS, FRACUNIT, V_PERPLAYER|V_SNAPTOTOP, realnightstime, nightsnum, if ((oldspecialstage && leveltime & 2)
((realnightstime < 10) ? SKINCOLOR_RED : SKINCOLOR_SUPERGOLD4)); && (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 // Show exact time in debug
if (cv_debug & DBG_NIGHTSBASIC) 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))); V_DrawString(160 + numbersize + 8, 24, V_SNAPTOTOP|((realnightstime < 10) ? V_REDMAP : V_YELLOWMAP), va("%02d", G_TicsToCentiseconds(stplyr->nightstime)));
} }
// Show pickup durations if (oldspecialstage)
if (cv_debug & DBG_NIGHTSBASIC)
{ {
UINT16 pwr; if (leveltime < 5*TICRATE)
if (stplyr->powers[pw_nights_superloop])
{ {
pwr = stplyr->powers[pw_nights_superloop]; INT32 aflag = V_PERPLAYER;
V_DrawSmallScaledPatch(110, 44, 0, W_CachePatchName("NPRUA0",PU_CACHE)); tic_t drawtime = (5*TICRATE) - leveltime;
V_DrawThinString(106, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); if (drawtime < TICRATE/2)
} aflag |= (9 - 9*drawtime/(TICRATE/2)) << V_ALPHASHIFT;
// This one, not quite as much so.
if (stplyr->powers[pw_nights_helper]) V_DrawCenteredString(BASEVIDWIDTH/2, 60, aflag,
{ va(M_GetText("\x80GET\x82 %d\x80 SPHERE%s!"), ssspheres,
pwr = stplyr->powers[pw_nights_helper]; (ssspheres > 1) ? "S" : ""));
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)));
} }
} }
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 #ifdef HAVE_BLUA
if (LUA_HudEnabled(hud_nightsrecords)) if (LUA_HudEnabled(hud_nightsrecords))
#endif #endif
ST_drawNightsRecords(); ST_drawNightsRecords();
}
} }
static inline void ST_drawWeaponSelect(INT32 xoffs, INT32 y) static inline void ST_drawWeaponSelect(INT32 xoffs, INT32 y)
@ -1952,7 +1997,7 @@ static void ST_drawTextHUD(void)
} }
else if (stplyr->spectator && (gametype != GT_COOP || stplyr->playerstate == PST_LIVE)) 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...")) textHUDdraw(M_GetText("\x82""Wait for the stage to end..."))
else if (gametype == GT_COOP) else if (gametype == GT_COOP)
{ {
@ -2070,22 +2115,22 @@ num:
#undef SEP #undef SEP
} }
static void ST_drawSpecialStageHUD(void) /*static void ST_drawSpecialStageHUD(void)
{ {
if (totalrings > 0) if (ssspheres > 0)
{ {
if (hudinfo[HUD_SS_TOTALRINGS].x) 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) 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 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_DrawPatchFromHud(HUD_GETRINGS, getall, V_HUDTRANS);
ST_DrawNumFromHud(HUD_GETRINGSNUM, totalrings, V_HUDTRANS); ST_DrawNumFromHud(HUD_GETRINGSNUM, ssspheres, V_HUDTRANS);
} }
if (sstimer) if (sstimer)
@ -2095,7 +2140,7 @@ static void ST_drawSpecialStageHUD(void)
} }
else else
ST_DrawPatchFromHud(HUD_TIMEUP, timeup, V_HUDTRANS); ST_DrawPatchFromHud(HUD_TIMEUP, timeup, V_HUDTRANS);
} }*/
static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offset) static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offset)
{ {
@ -2231,7 +2276,7 @@ static void ST_overlayDrawer(void)
//hu_showscores = auto hide score/time/rings when tab rankings are shown //hu_showscores = auto hide score/time/rings when tab rankings are shown
if (!(hu_showscores && (netgame || multiplayer))) if (!(hu_showscores && (netgame || multiplayer)))
{ {
if (maptol & TOL_NIGHTS) if (maptol & TOL_NIGHTS || G_IsSpecialStage(gamemap))
ST_drawNiGHTSHUD(); ST_drawNiGHTSHUD();
else else
{ {
@ -2340,10 +2385,6 @@ static void ST_overlayDrawer(void)
if (gametype == GT_RACE || gametype == GT_COMPETITION) if (gametype == GT_RACE || gametype == GT_COMPETITION)
ST_drawRaceHUD(); ST_drawRaceHUD();
// Special Stage HUD
if (!useNightsSS && G_IsSpecialStage(gamemap) && stplyr == &players[displayplayer])
ST_drawSpecialStageHUD();
// Emerald Hunt Indicators // Emerald Hunt Indicators
if (cv_itemfinder.value && M_SecretUnlocked(SECRET_ITEMFINDER)) if (cv_itemfinder.value && M_SecretUnlocked(SECRET_ITEMFINDER))
ST_doItemFinderIconsAndSound(); ST_doItemFinderIconsAndSound();
@ -2362,15 +2403,18 @@ static void ST_overlayDrawer(void)
} }
// This is where we draw all the fun cheese if you have the chasecam off! // This is where we draw all the fun cheese if you have the chasecam off!
if ((stplyr == &players[displayplayer] && !camera.chase) if (!(maptol & TOL_NIGHTS))
|| ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase))
{ {
ST_drawFirstPersonHUD(); if ((stplyr == &players[displayplayer] && !camera.chase)
if (cv_powerupdisplay.value) || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase))
ST_drawPowerupHUD(); // same as it ever was... {
ST_drawFirstPersonHUD();
if (cv_powerupdisplay.value)
ST_drawPowerupHUD(); // same as it ever was...
}
else if (cv_powerupdisplay.value == 2)
ST_drawPowerupHUD(); // same as it ever was...
} }
else if (cv_powerupdisplay.value == 2)
ST_drawPowerupHUD(); // same as it ever was...
} }
else if (!(netgame || multiplayer) && cv_powerupdisplay.value == 2) else if (!(netgame || multiplayer) && cv_powerupdisplay.value == 2)
ST_drawPowerupHUD(); // same as it ever was... ST_drawPowerupHUD(); // same as it ever was...

View file

@ -622,7 +622,7 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t
if (scrn & V_FLIP) if (scrn & V_FLIP)
{ {
flip = true; flip = true;
x -= FixedMul((SHORT(patch->width) - SHORT(patch->leftoffset))<<FRACBITS, pscale); x -= FixedMul((SHORT(patch->width) - SHORT(patch->leftoffset))<<FRACBITS, pscale) + 1;
} }
else else
x -= FixedMul(SHORT(patch->leftoffset)<<FRACBITS, pscale); x -= FixedMul(SHORT(patch->leftoffset)<<FRACBITS, pscale);
@ -1236,7 +1236,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
{ // Clear the entire screen, from dest to deststop. Yes, this really works. { // Clear the entire screen, from dest to deststop. Yes, this really works.
memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp); memset(screens[0], (c&255), vid.width * vid.height * vid.bpp);
return; return;
} }
@ -1299,7 +1299,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
c &= 255; c &= 255;
for (;(--h >= 0) && dest < deststop; dest += vid.width) for (;(--h >= 0) && dest < deststop; dest += vid.width)
memset(dest, (UINT8)(c&255), w * vid.bpp); memset(dest, c, w * vid.bpp);
} }
// //
@ -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; INT32 w, c, cx = x, cy = y, dupx, dupy, scrwidth, center = 0, left = 0;
const char *ch = string; const char *ch = string;
INT32 charflags = 0; INT32 charflags = (option & V_CHARCOLORMASK);
const UINT8 *colormap = NULL; const UINT8 *colormap = NULL;
INT32 spacewidth = 4, charwidth = 0; INT32 spacewidth = 4, charwidth = 0;
@ -1642,10 +1642,9 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string)
dupx = dupy = 1; dupx = dupy = 1;
scrwidth = vid.width/vid.dupx; scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2; left = (scrwidth - BASEVIDWIDTH)/2;
scrwidth -= left;
} }
charflags = (option & V_CHARCOLORMASK);
switch (option & V_SPACINGMASK) switch (option & V_SPACINGMASK)
{ {
case V_MONOSPACE: case V_MONOSPACE:
@ -1703,7 +1702,7 @@ void V_DrawString(INT32 x, INT32 y, INT32 option, const char *string)
else else
w = SHORT(hu_font[c]->width) * dupx; w = SHORT(hu_font[c]->width) * dupx;
if (cx+left > scrwidth) if (cx > scrwidth)
break; break;
if (cx+left + w < 0) //left boundary check if (cx+left + w < 0) //left boundary check
{ {
@ -1756,6 +1755,7 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string)
dupx = dupy = 1; dupx = dupy = 1;
scrwidth = vid.width/vid.dupx; scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2; left = (scrwidth - BASEVIDWIDTH)/2;
scrwidth -= left;
} }
charflags = (option & V_CHARCOLORMASK); charflags = (option & V_CHARCOLORMASK);
@ -1815,7 +1815,8 @@ void V_DrawSmallString(INT32 x, INT32 y, INT32 option, const char *string)
} }
else else
w = SHORT(hu_font[c]->width) * dupx / 2; w = SHORT(hu_font[c]->width) * dupx / 2;
if (cx+left > scrwidth)
if (cx > scrwidth)
break; break;
if (cx+left + w < 0) //left boundary check if (cx+left + w < 0) //left boundary check
{ {
@ -1862,6 +1863,7 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string)
dupx = dupy = 1; dupx = dupy = 1;
scrwidth = vid.width/vid.dupx; scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2; left = (scrwidth - BASEVIDWIDTH)/2;
scrwidth -= left;
} }
charflags = (option & V_CHARCOLORMASK); charflags = (option & V_CHARCOLORMASK);
@ -1919,7 +1921,7 @@ void V_DrawThinString(INT32 x, INT32 y, INT32 option, const char *string)
else else
w = (SHORT(tny_font[c]->width) * dupx); w = (SHORT(tny_font[c]->width) * dupx);
if (cx+left > scrwidth) if (cx > scrwidth)
break; break;
if (cx+left + w < 0) //left boundary check if (cx+left + w < 0) //left boundary check
{ {
@ -1962,6 +1964,7 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
dupx = dupy = 1; dupx = dupy = 1;
scrwidth = vid.width/vid.dupx; scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2; left = (scrwidth - BASEVIDWIDTH)/2;
scrwidth -= left;
} }
switch (option & V_SPACINGMASK) switch (option & V_SPACINGMASK)
@ -2016,9 +2019,9 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
else else
w = SHORT(hu_font[c]->width) * dupx; w = SHORT(hu_font[c]->width) * dupx;
if ((cx>>FRACBITS)+left > scrwidth) if ((cx>>FRACBITS) > scrwidth)
break; break;
if (cx+left + w < 0) //left boundary check if ((cx>>FRACBITS)+left + w < 0) //left boundary check
{ {
cx += w<<FRACBITS; cx += w<<FRACBITS;
continue; continue;
@ -2076,6 +2079,16 @@ void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits)
} while (--digits); } while (--digits);
} }
// Draw an act number for a level title
// Todo: actually draw two-digit numbers as two act num patches
void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, INT32 num)
{
if (num < 0 || num > 19)
return; // not supported
V_DrawScaledPatch(x, y, flags, ttlnum[num]);
}
// Write a string using the credit font // Write a string using the credit font
// NOTE: the text is centered for screens larger than the base width // NOTE: the text is centered for screens larger than the base width
// //
@ -2118,7 +2131,7 @@ void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string)
} }
w = SHORT(cred_font[c]->width) * dupx; w = SHORT(cred_font[c]->width) * dupx;
if ((cx>>FRACBITS) + w > scrwidth) if ((cx>>FRACBITS) > scrwidth)
break; break;
V_DrawSciencePatch(cx, cy, option, cred_font[c], FRACUNIT); V_DrawSciencePatch(cx, cy, option, cred_font[c], FRACUNIT);
@ -2154,8 +2167,10 @@ INT32 V_CreditStringWidth(const char *string)
// //
void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, 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; const char *ch = string;
INT32 charflags = (option & V_CHARCOLORMASK);
const UINT8 *colormap = NULL;
if (option & V_NOSCALESTART) if (option & V_NOSCALESTART)
{ {
@ -2164,21 +2179,32 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string)
scrwidth = vid.width; scrwidth = vid.width;
} }
else else
dupx = dupy = 1;
for (;;)
{ {
c = *ch++; dupx = dupy = 1;
if (!c) scrwidth = vid.width/vid.dupx;
left = (scrwidth - BASEVIDWIDTH)/2;
scrwidth -= left;
}
for (;;ch++)
{
if (!*ch)
break; 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; cx = x;
cy += 12*dupy; cy += 12*dupy;
continue; continue;
} }
c = toupper(c) - LT_FONTSTART; c = toupper(*ch) - LT_FONTSTART;
if (c < 0 || c >= LT_FONTSIZE || !lt_font[c]) if (c < 0 || c >= LT_FONTSIZE || !lt_font[c])
{ {
cx += 16*dupx; cx += 16*dupx;
@ -2186,17 +2212,18 @@ void V_DrawLevelTitle(INT32 x, INT32 y, INT32 option, const char *string)
} }
w = SHORT(lt_font[c]->width) * dupx; w = SHORT(lt_font[c]->width) * dupx;
if (cx + w > scrwidth)
break;
//left boundary check if (cx > scrwidth)
if (cx < 0) break;
if (cx+left + w < 0) //left boundary check
{ {
cx += w; cx += w;
continue; 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; cx += w;
} }
} }
@ -2210,6 +2237,8 @@ INT32 V_LevelNameWidth(const char *string)
for (i = 0; i < strlen(string); i++) for (i = 0; i < strlen(string); i++)
{ {
if (string[i] & 0x80)
continue;
c = toupper(string[i]) - LT_FONTSTART; c = toupper(string[i]) - LT_FONTSTART;
if (c < 0 || c >= LT_FONTSIZE || !lt_font[c]) if (c < 0 || c >= LT_FONTSIZE || !lt_font[c])
w += 16; w += 16;
@ -2240,6 +2269,16 @@ INT32 V_LevelNameHeight(const char *string)
return w; return w;
} }
// For ST_drawLevelTitle
// Returns the width of the act num patch
INT32 V_LevelActNumWidth(INT32 num)
{
if (num < 0 || num > 19)
return 0; // not a valid number
return SHORT(ttlnum[num]->width);
}
// //
// Find string width from hu_font chars // Find string width from hu_font chars
// //
@ -2265,11 +2304,9 @@ INT32 V_StringWidth(const char *string, INT32 option)
for (i = 0; i < strlen(string); i++) for (i = 0; i < strlen(string); i++)
{ {
c = string[i]; if (string[i] & 0x80)
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09
continue; continue;
c = toupper(string[i]) - HU_FONTSTART;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
w += spacewidth; w += spacewidth;
else else
@ -2307,11 +2344,9 @@ INT32 V_SmallStringWidth(const char *string, INT32 option)
for (i = 0; i < strlen(string); i++) for (i = 0; i < strlen(string); i++)
{ {
c = string[i]; if (string[i] & 0x80)
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09
continue; continue;
c = toupper(string[i]) - HU_FONTSTART;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE || !hu_font[c]) if (c < 0 || c >= HU_FONTSIZE || !hu_font[c])
w += spacewidth; w += spacewidth;
else else
@ -2346,11 +2381,9 @@ INT32 V_ThinStringWidth(const char *string, INT32 option)
for (i = 0; i < strlen(string); i++) for (i = 0; i < strlen(string); i++)
{ {
c = string[i]; if (string[i] & 0x80)
if ((UINT8)c >= 0x80 && (UINT8)c <= 0x89) //color parsing! -Inuyasha 2.16.09
continue; continue;
c = toupper(string[i]) - HU_FONTSTART;
c = toupper(c) - HU_FONTSTART;
if (c < 0 || c >= HU_FONTSIZE || !tny_font[c]) if (c < 0 || c >= HU_FONTSIZE || !tny_font[c])
w += spacewidth; w += spacewidth;
else else

View file

@ -185,10 +185,12 @@ void V_DrawStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
// Draw tall nums, used for menu, HUD, intermission // Draw tall nums, used for menu, HUD, intermission
void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num); void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num);
void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits); void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits);
void V_DrawLevelActNum(INT32 x, INT32 y, INT32 flags, INT32 num);
// Find string width from lt_font chars // Find string width from lt_font chars
INT32 V_LevelNameWidth(const char *string); INT32 V_LevelNameWidth(const char *string);
INT32 V_LevelNameHeight(const char *string); INT32 V_LevelNameHeight(const char *string);
INT32 V_LevelActNumWidth(INT32 num); // act number width
void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string); void V_DrawCreditString(fixed_t x, fixed_t y, INT32 option, const char *string);
INT32 V_CreditStringWidth(const char *string); INT32 V_CreditStringWidth(const char *string);

View file

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

View file

@ -161,7 +161,7 @@ static BOOL wasPlaying;
//static INT cdVolume = 0; // current cd volume (0-31) //static INT cdVolume = 0; // current cd volume (0-31)
// 0-31 like Music & Sfx, though CD hardware volume is 0-255. // 0-31 like Music & Sfx, though CD hardware volume is 0-255.
consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// allow Update for next/loop track // allow Update for next/loop track
// some crap cd drivers take up to // some crap cd drivers take up to

View file

@ -70,15 +70,15 @@ typedef union
UINT32 score, total; // fake score, total UINT32 score, total; // fake score, total
UINT32 tics; // time UINT32 tics; // time
patch_t *ttlnum; // act number being displayed INT32 actnum; // act number being displayed
patch_t *ptotal; // TOTAL patch_t *ptotal; // TOTAL
UINT8 gotlife; // Number of extra lives obtained UINT8 gotlife; // Number of extra lives obtained
} coop; } coop;
struct struct
{ {
char passed1[29]; // KNUCKLES GOT / CRAWLA HONCHO char passed1[29]; // KNUCKLES GOT / CRAWLA HONCHO
char passed2[17]; // A CHAOS EMERALD / GOT THEM ALL! char passed2[17]; // A CHAOS EMERALD? / GOT THEM ALL!
char passed3[15]; // CAN NOW BECOME char passed3[15]; // CAN NOW BECOME
char passed4[SKINNAMESIZE+7]; // SUPER CRAWLA HONCHO char passed4[SKINNAMESIZE+7]; // SUPER CRAWLA HONCHO
INT32 passedx1; INT32 passedx1;
@ -288,8 +288,8 @@ void Y_IntermissionDrawer(void)
V_DrawLevelTitle(data.coop.passedx1, 49, 0, data.coop.passed1); V_DrawLevelTitle(data.coop.passedx1, 49, 0, data.coop.passed1);
V_DrawLevelTitle(data.coop.passedx2, 49+V_LevelNameHeight(data.coop.passed2)+2, 0, data.coop.passed2); V_DrawLevelTitle(data.coop.passedx2, 49+V_LevelNameHeight(data.coop.passed2)+2, 0, data.coop.passed2);
if (mapheaderinfo[gamemap-1]->actnum) if (data.coop.actnum)
V_DrawScaledPatch(244, 57, 0, data.coop.ttlnum); V_DrawLevelActNum(244, 57, 0, data.coop.actnum);
bonusy = 150; bonusy = 150;
// Total // Total
@ -315,6 +315,9 @@ void Y_IntermissionDrawer(void)
INT32 xoffset1 = 0; // Line 1 x offset INT32 xoffset1 = 0; // Line 1 x offset
INT32 xoffset2 = 0; // Line 2 x offset INT32 xoffset2 = 0; // Line 2 x offset
INT32 xoffset3 = 0; // Line 3 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; UINT8 drawsection = 0;
if (gottoken) // first to be behind everything else if (gottoken) // first to be behind everything else
@ -324,71 +327,130 @@ void Y_IntermissionDrawer(void)
if (intertic <= 2*TICRATE) if (intertic <= 2*TICRATE)
animatetic = 0; animatetic = 0;
else if (!animatetic && data.spec.bonus.points == 0 && data.spec.passed3[0] != '\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); INT32 animatetimer = (intertic - animatetic);
if (animatetimer <= 8) if (animatetimer <= 14)
{ {
xoffset1 = -(animatetimer * 40); xoffset1 = -(animatetimer * scradjust);
xoffset2 = -((animatetimer-2) * 40); xoffset2 = -((animatetimer-2) * scradjust);
xoffset3 = -((animatetimer-4) * scradjust);
xoffset4 = -((animatetimer-6) * scradjust);
xoffset5 = -((animatetimer-8) * scradjust);
if (xoffset2 > 0) xoffset2 = 0; 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; drawsection = 1;
xoffset1 = (16-animatetimer) * 40; xoffset1 = (22-animatetimer) * scradjust;
xoffset2 = (18-animatetimer) * 40; xoffset2 = (24-animatetimer) * scradjust;
xoffset3 = (20-animatetimer) * 40; xoffset3 = (26-animatetimer) * scradjust;
xoffset4 = (28-animatetimer) * scradjust;
xoffset5 = (30-animatetimer) * scradjust;
xoffset6 = (32-animatetimer) * scradjust;
if (xoffset1 < 0) xoffset1 = 0; if (xoffset1 < 0) xoffset1 = 0;
if (xoffset2 < 0) xoffset2 = 0; if (xoffset2 < 0) xoffset2 = 0;
if (xoffset3 < 0) xoffset3 = 0;
if (xoffset4 < 0) xoffset4 = 0;
if (xoffset5 < 0) xoffset5 = 0;
} }
else else
{
drawsection = 1; drawsection = 1;
if (animatetimer == 32)
S_StartSound(NULL, sfx_s3k68);
}
} }
if (drawsection == 1) 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; ttheight = 16;
V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1);
ttheight += V_LevelNameHeight(data.spec.passed3) + 2; ttheight += V_LevelNameHeight(data.spec.passed3) + 2;
V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3); V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3);
ttheight += V_LevelNameHeight(data.spec.passed4) + 2; ttheight += V_LevelNameHeight(data.spec.passed4) + 2;
V_DrawLevelTitle(data.spec.passedx4 + xoffset3, ttheight, 0, data.spec.passed4); V_DrawLevelTitle(data.spec.passedx4 + xoffset3, ttheight, 0, data.spec.passed4);
}
else if (data.spec.passed1[0] != '\0') ttheight = 108;
{ V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset4 - (V_LevelNameWidth(ringtext)/2), ttheight, 0, ringtext);
ttheight = 24; ttheight += V_LevelNameHeight(ringtext) + 2;
V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset5 - (V_LevelNameWidth(tut1text)/2), ttheight, 0, tut1text);
ttheight += V_LevelNameHeight(data.spec.passed2) + 2; ttheight += V_LevelNameHeight(tut1text) + 2;
V_DrawLevelTitle(data.spec.passedx2 + xoffset2, ttheight, 0, data.spec.passed2); V_DrawLevelTitle(BASEVIDWIDTH/2 + xoffset6 - (V_LevelNameWidth(tut2text)/2), ttheight, 0, tut2text);
} }
else else
{ {
ttheight = 24 + (V_LevelNameHeight(data.spec.passed2)/2) + 2; if (data.spec.passed1[0] != '\0')
V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2); {
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 // draw the emeralds
//if (intertic & 1) //if (intertic & 1)
{ {
boolean drawthistic = !(ALL7EMERALDS(emeralds) && (intertic & 1));
INT32 emeraldx = 152 - 3*28; 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))) if (!stagefailed)
V_DrawScaledPatch(emeraldx, 74, 0, emeraldpics[0][i]); {
emeraldx += 28; fixed_t adjust = 2*(FINESINE(FixedAngle((intertic + 1)<<(FRACBITS-4)) & FINEMASK));
V_DrawFixedPatch(152<<FRACBITS, (74<<FRACBITS) - adjust, FRACUNIT, 0, emeraldpics[0][em], NULL);
}
} }
else if (em < 7)
if (em < 7)
{ {
static UINT8 emeraldbounces = 0; static UINT8 emeraldbounces = 0;
static INT32 emeraldmomy = 20; static INT32 emeraldmomy = 20;
static INT32 emeraldy = -40; 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; emeraldx = 152 + (em-3)*28;
if (intertic <= 1) if (intertic <= 1)
@ -399,7 +461,7 @@ void Y_IntermissionDrawer(void)
} }
else else
{ {
if (emeralds & (1 << em)) if (!stagefailed)
{ {
if (emeraldbounces < 3) if (emeraldbounces < 3)
{ {
@ -427,29 +489,11 @@ void Y_IntermissionDrawer(void)
emeraldy = 74; 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) else if (intertype == int_match || intertype == int_race)
{ {
@ -831,7 +875,7 @@ void Y_Ticker(void)
if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback) if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback)
{ {
if (M_UpdateUnlockablesAndExtraEmblems()) if (M_UpdateUnlockablesAndExtraEmblems())
S_StartSound(NULL, sfx_ncitem); S_StartSound(NULL, sfx_s3k68);
G_SaveGameData(); G_SaveGameData();
} }
@ -850,7 +894,7 @@ void Y_Ticker(void)
{ {
INT32 i; INT32 i;
UINT32 oldscore = data.spec.score; UINT32 oldscore = data.spec.score;
boolean skip = false; boolean skip = false, super = false;
if (!intertic) // first time only if (!intertic) // first time only
{ {
@ -862,15 +906,22 @@ void Y_Ticker(void)
return; return;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && (players[i].cmd.buttons & BT_USE)) if (playeringame[i])
skip = true; {
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) if ((intertic - tallydonetic) > (3*TICRATE)/2)
{ {
endtic = intertic + 4*TICRATE; // 4 second pause after end of tally 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; return;
} }
@ -887,7 +938,7 @@ void Y_Ticker(void)
if (!data.spec.bonus.points) if (!data.spec.bonus.points)
{ {
tallydonetic = intertic; 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 endtic = intertic + 4*TICRATE; // 4 second pause after end of tally
S_StartSound(NULL, (gottoken ? sfx_token : sfx_chchng)); // cha-ching! 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 ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback)
{ {
if (M_UpdateUnlockablesAndExtraEmblems()) if (M_UpdateUnlockablesAndExtraEmblems())
S_StartSound(NULL, sfx_ncitem); S_StartSound(NULL, sfx_s3k68);
G_SaveGameData(); G_SaveGameData();
} }
@ -1132,11 +1183,7 @@ void Y_StartIntermission(void)
data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_STATIC); data.coop.ptotal = W_CachePatchName("YB_TOTAL", PU_STATIC);
// get act number // get act number
if (mapheaderinfo[prevmap]->actnum) data.coop.actnum = mapheaderinfo[gamemap-1]->actnum;
data.coop.ttlnum = W_CachePatchName(va("TTL%.2d", mapheaderinfo[prevmap]->actnum),
PU_STATIC);
else
data.coop.ttlnum = W_CachePatchName("TTL01", PU_STATIC);
// get background patches // get background patches
widebgpatch = W_CachePatchName("INTERSCW", PU_STATIC); widebgpatch = W_CachePatchName("INTERSCW", PU_STATIC);
@ -1286,7 +1333,7 @@ void Y_StartIntermission(void)
data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0'; data.spec.passed1[sizeof data.spec.passed1 - 1] = '\0';
strcpy(data.spec.passed2, "GOT THEM ALL!"); 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"); strcpy(data.spec.passed3, "CAN NOW BECOME");
snprintf(data.spec.passed4, snprintf(data.spec.passed4,
@ -1307,6 +1354,11 @@ void Y_StartIntermission(void)
else else
strcpy(data.spec.passed1, "YOU GOT"); strcpy(data.spec.passed1, "YOU GOT");
strcpy(data.spec.passed2, "A CHAOS EMERALD"); 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.passedx1 = (BASEVIDWIDTH - V_LevelNameWidth(data.spec.passed1))/2;
data.spec.passedx2 = (BASEVIDWIDTH - V_LevelNameWidth(data.spec.passed2))/2; data.spec.passedx2 = (BASEVIDWIDTH - V_LevelNameWidth(data.spec.passed2))/2;
@ -1745,7 +1797,7 @@ static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct)
if (!playeringame[i]) continue; if (!playeringame[i]) continue;
sharedringtotal += players[i].rings; sharedringtotal += players[i].rings;
} }
if (!sharedringtotal || sharedringtotal < nummaprings) if (!sharedringtotal || nummaprings == -1 || sharedringtotal < nummaprings)
data.coop.gotperfbonus = 0; data.coop.gotperfbonus = 0;
else else
data.coop.gotperfbonus = 1; data.coop.gotperfbonus = 1;
@ -1857,7 +1909,7 @@ static void Y_AwardSpecialStageBonus(void)
if (!playeringame[i] || players[i].lives < 1) // not active or game over if (!playeringame[i] || players[i].lives < 1) // not active or game over
Y_SetNullBonus(&players[i], &localbonus); 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); Y_SetLinkBonus(&players[i], &localbonus);
else else
Y_SetRingBonus(&players[i], &localbonus); Y_SetRingBonus(&players[i], &localbonus);
@ -1938,7 +1990,6 @@ static void Y_UnloadData(void)
{ {
case int_coop: case int_coop:
// unload the coop and single player patches // unload the coop and single player patches
UNLOAD(data.coop.ttlnum);
UNLOAD(data.coop.bonuspatches[3]); UNLOAD(data.coop.bonuspatches[3]);
UNLOAD(data.coop.bonuspatches[2]); UNLOAD(data.coop.bonuspatches[2]);
UNLOAD(data.coop.bonuspatches[1]); UNLOAD(data.coop.bonuspatches[1]);