From 6e07631cc9851ca8a4d9ac0e6aa143fe6fdd75b0 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 3 Jun 2018 22:41:54 +0100 Subject: [PATCH] MONSTER COMMIT. OLD SPECIAL STAGES: * Spheres in old special stages instead of rings! * Individual timers in old special stages instead of a global one! * Old special stages use a variant of the NiGHTS HUD now! * Special stage damage in old special stages loses 5 seconds of time instead of 10 rings/spheres! * All damage gained through old special stages is converted to special stage damage! As a consequence, the special spikeball has no need to be special anymore. * Made emerald gaining function be based on special stage number rather than gained emeralds! * Consistency with... NiGHTS SPECIAL STAGES: * Spheres now flash in bonus time. https://cdn.discordapp.com/attachments/400761370800422922/452590553100713984/srb20032.gif * Sphere and ring mapthingnums are now less fucked up in 'em. (Rings are 300, same as usual, while Spheres are now 1706 replacing NiGHTS Wings.) SPECIAL STAGES IN GENERAL: * useNightsSS is now dead. Each individual special stage is now assessed for NiGHTS-mode behaviour based on maptol & TOL_NIGHTS. * CRAWLA HONCHO\n CAN NOW BE\n SUPER CRAWLA HONCHO end tally modification now also includes a mini-tutorial on turning super. https://cdn.discordapp.com/attachments/400761370800422922/452844894113759233/srb20036.gif * SONIC GOT A CHAOS EMERALD? https://cdn.discordapp.com/attachments/400761370800422922/452623869497573386/srb20034.gif NiGHTS NON-SPECIAL STAGES: * Colour Chips and Star Chips! Replaces Spheres and Rings of NiGHTS Special Stages. * Colour Chips turn yellow in bonus time. * Ideya! * Its own "drowning" music! * All of the object types for Dream Hill. * GIF: https://cdn.discordapp.com/attachments/400761370800422922/452844894113759233/srb20036.gif RANDOM BS: * Turn super with the spin button instead of the jump button! * Followmobj now correctly set with P_SetTarget instead of pointer assignment. * Emerald hunt uses new sprites! * Made unlock noise different from emblem gain noise! (It's the CRAWLA HONCHO CAN NOW TURN yadda yadda sound from S3K now.) --- src/d_clisrv.c | 22 ++-- src/d_clisrv.h | 3 +- src/d_netcmd.c | 7 +- src/d_player.h | 5 +- src/dehacked.c | 70 +++++++---- src/doomstat.h | 3 +- src/f_finale.c | 2 +- src/g_game.c | 6 +- src/hardware/hw_light.c | 13 +- src/hu_stuff.c | 5 +- src/hu_stuff.h | 2 +- src/info.c | 256 ++++++++++++++++++++++++++++++---------- src/info.h | 83 ++++++++----- src/lua_hud.h | 2 +- src/lua_playerlib.c | 14 ++- src/m_cheat.c | 22 ++-- src/p_enemy.c | 19 ++- src/p_inter.c | 228 ++++++++++++++++++++--------------- src/p_local.h | 1 + src/p_mobj.c | 216 ++++++++++++++++----------------- src/p_mobj.h | 4 +- src/p_saveg.c | 16 +-- src/p_setup.c | 71 +++++++---- src/p_setup.h | 1 + src/p_spec.c | 14 +-- src/p_tick.c | 89 +++++++------- src/p_user.c | 161 ++++++++++++++----------- src/r_things.c | 2 +- src/screen.c | 7 +- src/sounds.c | 14 ++- src/sounds.h | 4 +- src/st_stuff.c | 211 ++++++++++++++++++++------------- src/y_inter.c | 104 ++++++++++------ 33 files changed, 1006 insertions(+), 671 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 5832b2c27..14677b8a1 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -513,7 +513,8 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->powers[j] = (UINT16)SHORT(players[i].powers[j]); // Score is resynched in the rspfirm resync packet - rsp->rings = LONG(players[i].rings); + rsp->rings = SHORT(players[i].rings); + rsp->spheres = SHORT(players[i].spheres); rsp->lives = players[i].lives; rsp->continues = players[i].continues; rsp->scoreadd = players[i].scoreadd; @@ -643,7 +644,8 @@ static void resynch_read_player(resynch_pak *rsp) players[i].powers[j] = (UINT16)SHORT(rsp->powers[j]); // Score is resynched in the rspfirm resync packet - players[i].rings = LONG(rsp->rings); + players[i].rings = SHORT(rsp->rings); + players[i].spheres = SHORT(rsp->spheres); players[i].lives = rsp->lives; players[i].continues = rsp->continues; players[i].scoreadd = rsp->scoreadd; @@ -2377,11 +2379,11 @@ static void CL_RemovePlayer(INT32 playernum) if (gametype == GT_CTF) P_PlayerFlagBurst(&players[playernum], false); // Don't take the flag with you! - // If in a special stage, redistribute the player's rings across + // If in a special stage, redistribute the player's spheres across // the remaining players. if (G_IsSpecialStage(gamemap)) { - INT32 i, count, increment, rings; + INT32 i, count, increment, spheres; for (i = 0, count = 0; i < MAXPLAYERS; i++) { @@ -2390,19 +2392,19 @@ static void CL_RemovePlayer(INT32 playernum) } count--; - rings = players[playernum].rings; - increment = rings/count; + spheres = players[playernum].spheres; + increment = spheres/count; for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && i != playernum) { - if (rings < increment) - P_GivePlayerRings(&players[i], rings); + if (spheres < increment) + P_GivePlayerSpheres(&players[i], spheres); else - P_GivePlayerRings(&players[i], increment); + P_GivePlayerSpheres(&players[i], increment); - rings -= increment; + spheres -= increment; } } } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index bdf332665..bdb85a76c 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -164,7 +164,8 @@ typedef struct UINT16 powers[NUMPOWERS]; // Score is resynched in the confirm resync packet - INT32 rings; + INT16 rings; + INT16 spheres; SINT8 lives; SINT8 continues; UINT8 scoreadd; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index e01178155..bd1f93512 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -309,8 +309,8 @@ consvar_t cv_overtime = {"overtime", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, consvar_t cv_rollingdemos = {"rollingdemos", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -static CV_PossibleValue_t timetic_cons_t[] = {{0, "Normal"}, {1, "Centiseconds"}, {2, "Mania"}, {3, "Tics"}, {0, NULL}}; -consvar_t cv_timetic = {"timerres", "Normal", CV_SAVE, timetic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // use tics in display +static CV_PossibleValue_t timetic_cons_t[] = {{0, "Classic"}, {1, "Centiseconds"}, {2, "Mania"}, {3, "Tics"}, {0, NULL}}; +consvar_t cv_timetic = {"timerres", "Classic", CV_SAVE, timetic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; static CV_PossibleValue_t powerupdisplay_cons_t[] = {{0, "Never"}, {1, "First-person only"}, {2, "Always"}, {0, NULL}}; consvar_t cv_powerupdisplay = {"powerupdisplay", "First-person only", CV_SAVE, powerupdisplay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -2682,8 +2682,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum) // Clear player score and rings if a spectator. if (players[playernum].spectator) { - players[playernum].score = 0; - players[playernum].rings = 0; + players[playernum].score = players[playernum].rings = 0; if (players[playernum].mo) players[playernum].mo->health = 1; } diff --git a/src/d_player.h b/src/d_player.h index e1350fe67..24c4f9252 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -324,7 +324,8 @@ typedef struct player_s angle_t drawangle; // player's ring count - INT32 rings; + INT16 rings; + INT16 spheres; SINT8 pity; // i pity the fool. INT32 currentweapon; // current weapon selected. @@ -460,7 +461,7 @@ typedef struct player_s tic_t marebegunat; // Leveltime when mare begun tic_t startedtime; // Time which you started this mare with. tic_t finishedtime; // Time it took you to finish the mare (used for display) - INT16 finishedrings; // The rings you had left upon finishing the mare + INT16 finishedspheres; // The spheres you had left upon finishing the mare UINT32 marescore; // score for this nights stage UINT32 lastmarescore; // score for the last mare UINT8 lastmare; // previous mare diff --git a/src/dehacked.c b/src/dehacked.c index c25e9e1fa..ca17614ed 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2673,10 +2673,6 @@ static void readmaincfg(MYFILE *f) sstage_start = (INT16)value; sstage_end = (INT16)(sstage_start+6); // 7 special stages total } - else if (fastcmp(word, "USENIGHTSSS")) - { - useNightsSS = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y'); - } else if (fastcmp(word, "REDTEAM")) { skincolor_redteam = (UINT8)get_number(word2); @@ -3799,6 +3795,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Egg Shield for Egg Guard "S_EGGSHIELD", + "S_EGGSHIELDBREAK", // Green Snapper "S_GSNAPPER_STND", @@ -4367,8 +4364,17 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_RING", // Blue Sphere for special stages - "S_BLUEBALL", - "S_BLUEBALLSPARK", + "S_BLUESPHERE", + "S_BLUESPHEREBONUS", + "S_BLUESPHERESPARK", + + // NiGHTS Chip + "S_NIGHTSCHIP", + "S_NIGHTSCHIPBONUS", + + // NiGHTS Star + "S_NIGHTSSTAR", + "S_NIGHTSSTARXMAS", // Gravity Wells for special stages "S_GRAVWELLGREEN", @@ -4426,8 +4432,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_CEMG6", "S_CEMG7", - // Emeralds (for hunt) - "S_EMER1", + // Emerald hunt shards + "S_SHRD1", + "S_SHRD2", + "S_SHRD3", // Bubble Source "S_BUBBLES1", @@ -4709,7 +4717,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Arrow "S_ARROW", - "S_TEMPSHI", "S_ARROWBONK", // Trapgoyle Demon fire @@ -4739,6 +4746,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_POLYGONTREE", "S_BUSHTREE", "S_BUSHREDTREE", + "S_SPRINGTREE", // THZ flowers "S_THZFLOWERA", // THZ1 Steam flower @@ -6007,9 +6015,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_NIGHTSCORE90_2", "S_NIGHTSCORE100_2", - "S_NIGHTSWING", - "S_NIGHTSWING_XMAS", - // NiGHTS Paraloop Powerups "S_NIGHTSSUPERLOOP", "S_NIGHTSDRILLREFILL", @@ -6027,14 +6032,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_ORBITEM6", "S_ORBITEM7", "S_ORBITEM8", - "S_ORBITEM9", - "S_ORBITEM10", - "S_ORBITEM11", - "S_ORBITEM12", - "S_ORBITEM13", - "S_ORBITEM14", - "S_ORBITEM15", - "S_ORBITEM16", + "S_ORBIDYA1", + "S_ORBIDYA2", + "S_ORBIDYA3", + "S_ORBIDYA4", + "S_ORBIDYA5", // "Flicky" helper "S_NIGHTOPIANHELPER1", @@ -6047,6 +6049,26 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_NIGHTOPIANHELPER8", "S_NIGHTOPIANHELPER9", + // Nightopian + "S_PIAN0", + "S_PIAN1", + "S_PIAN2", + "S_PIAN3", + "S_PIAN4", + "S_PIAN5", + "S_PIAN6", + "S_PIANSING", + + // Shleep + "S_SHLEEP1", + "S_SHLEEP2", + "S_SHLEEP3", + "S_SHLEEP4", + "S_SHLEEPBOUNCE1", + "S_SHLEEPBOUNCE2", + "S_SHLEEPBOUNCE3", + + // Secret badniks and hazards, shhhh "S_HIVEELEMENTAL_LOOK", "S_HIVEELEMENTAL_PREPARE1", @@ -6322,7 +6344,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Collectible Items "MT_RING", "MT_FLINGRING", // Lost ring - "MT_BLUEBALL", // Blue sphere replacement for special stages + "MT_BLUESPHERE", // Blue sphere replacement for special stages "MT_REDTEAMRING", //Rings collectable by red team. "MT_BLUETEAMRING", //Rings collectable by blue team. "MT_TOKEN", // Special Stage Token @@ -6466,6 +6488,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_POLYGONTREE", "MT_BUSHTREE", "MT_BUSHREDTREE", + "MT_SPRINGTREE", // Techno Hill Scenery "MT_THZFLOWER1", @@ -6778,7 +6801,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_HOOPCOLLIDE", // Collision detection for NiGHTS hoops "MT_HOOPCENTER", // Center of a hoop "MT_NIGHTSCORE", - "MT_NIGHTSWING", + "MT_NIGHTSCHIP", // NiGHTS Chip + "MT_NIGHTSSTAR", // NiGHTS Star "MT_NIGHTSSUPERLOOP", "MT_NIGHTSDRILLREFILL", "MT_NIGHTSHELPER", @@ -6786,6 +6810,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_NIGHTSLINKFREEZE", "MT_EGGCAPSULE", "MT_NIGHTOPIANHELPER", // the actual helper object that orbits you + "MT_PIAN", // decorative singing friend + "MT_SHLEEP", // almost-decorative sleeping enemy // Secret badniks and hazards, shhhh "MT_HIVEELEMENTAL", diff --git a/src/doomstat.h b/src/doomstat.h index d4735f6b2..3a2084e29 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -134,7 +134,6 @@ extern boolean hidetitlepics; extern INT16 bootmap; //bootmap for loading a map on startup extern boolean looptitle; -extern boolean useNightsSS; // CTF colors. extern UINT8 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor_bluering; @@ -175,7 +174,7 @@ extern cutscene_t *cutscenes[128]; extern INT16 nextmapoverride; extern boolean skipstats; -extern UINT32 totalrings; // Total # of rings in a level +extern UINT32 ssspheres; // Total # of spheres in a level // Fun extra stuff extern INT16 lastmap; // Last level you were at (returning from special stages). diff --git a/src/f_finale.c b/src/f_finale.c index db62ddf09..2191e8673 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1345,7 +1345,7 @@ void F_GameEvaluationDrawer(void) ++timesBeatenUltimate; if (M_UpdateUnlockablesAndExtraEmblems()) - S_StartSound(NULL, sfx_ncitem); + S_StartSound(NULL, sfx_s3k68); G_SaveGameData(); } diff --git a/src/g_game.c b/src/g_game.c index 509ccf0ab..79f62bcd1 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -116,7 +116,7 @@ INT32 secondarydisplayplayer; // for splitscreen tic_t gametic; tic_t levelstarttic; // gametic at level start -UINT32 totalrings; // for intermission +UINT32 ssspheres; // old special stage INT16 lastmap; // last level you were at (returning from special stages) tic_t timeinmap; // Ticker for time spent in level (used for levelcard display) @@ -129,7 +129,6 @@ boolean hidetitlepics = false; INT16 bootmap; //bootmap for loading a map on startup boolean looptitle = false; -boolean useNightsSS = false; UINT8 skincolor_redteam = SKINCOLOR_RED; UINT8 skincolor_blueteam = SKINCOLOR_BLUE; @@ -2201,7 +2200,7 @@ void G_PlayerReborn(INT32 player) p->pflags |= PF_JUMPDOWN; p->playerstate = PST_LIVE; - p->rings = 0; // 0 rings + p->rings = p->spheres = 0; // 0 rings p->panim = PA_IDLE; // standing animation //if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there @@ -3209,7 +3208,6 @@ void G_LoadGameSettings(void) spstage_start = 1; sstage_start = 50; sstage_end = 57; // 8 special stages in vanilla SRB2 - useNightsSS = false; //true; // initialize free sfx slots for skin sounds S_InitRuntimeSounds(); diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index fbec957f7..aee6f9396 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -229,10 +229,12 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_TOKE &lspr[REDBALL_L], // SPR_RFLG &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_CEMG - &lspr[NOLIGHT], // SPR_EMER + &lspr[NOLIGHT], // SPR_SHRD // Interactive Objects &lspr[NOLIGHT], // SPR_BBLS @@ -298,6 +300,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_TRE3 &lspr[NOLIGHT], // SPR_TRE4 &lspr[NOLIGHT], // SPR_TRE5 + &lspr[NOLIGHT], // SPR_TRE6 // Techno Hill Scenery &lspr[NOLIGHT], // SPR_THZP @@ -498,6 +501,9 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_HSCR &lspr[NOLIGHT], // SPR_NPRU &lspr[NOLIGHT], // SPR_CAPS + &lspr[INVINCIBLE_L], // SPR_IDYA + &lspr[NOLIGHT], // SPR_NTPN + &lspr[NOLIGHT], // SPR_SHLP // Secret badniks and hazards, shhhh &lspr[NOLIGHT], // SPR_HIVE @@ -538,9 +544,6 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_ROIO &lspr[NOLIGHT], // SPR_ROIP - // Blue Spheres - &lspr[NOLIGHT], // SPR_BBAL - // Gravity Well Objects &lspr[NOLIGHT], // SPR_GWLG &lspr[NOLIGHT], // SPR_GWLR diff --git a/src/hu_stuff.c b/src/hu_stuff.c index a13801388..456f97bac 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -89,7 +89,7 @@ patch_t *tallinfin; // coop hud //------------------------------------------- -patch_t *emeraldpics[3][7]; // 0 = normal, 1 = tiny, 2 = coinbox +patch_t *emeraldpics[3][8]; // 0 = normal, 1 = tiny, 2 = coinbox static patch_t *emblemicon; patch_t *tokenicon; static patch_t *exiticon; @@ -256,6 +256,7 @@ void HU_LoadGraphics(void) emeraldpics[0][4] = W_CachePatchName("CHAOS5", PU_HUDGFX); emeraldpics[0][5] = W_CachePatchName("CHAOS6", PU_HUDGFX); emeraldpics[0][6] = W_CachePatchName("CHAOS7", PU_HUDGFX); + emeraldpics[0][7] = W_CachePatchName("CHAOS8", PU_HUDGFX); emeraldpics[1][0] = W_CachePatchName("TEMER1", PU_HUDGFX); emeraldpics[1][1] = W_CachePatchName("TEMER2", PU_HUDGFX); @@ -264,6 +265,7 @@ void HU_LoadGraphics(void) emeraldpics[1][4] = W_CachePatchName("TEMER5", PU_HUDGFX); emeraldpics[1][5] = W_CachePatchName("TEMER6", PU_HUDGFX); emeraldpics[1][6] = W_CachePatchName("TEMER7", PU_HUDGFX); + //emeraldpics[1][7] = W_CachePatchName("TEMER8", PU_HUDGFX); -- unused emeraldpics[2][0] = W_CachePatchName("EMBOX1", PU_HUDGFX); emeraldpics[2][1] = W_CachePatchName("EMBOX2", PU_HUDGFX); @@ -272,6 +274,7 @@ void HU_LoadGraphics(void) emeraldpics[2][4] = W_CachePatchName("EMBOX5", PU_HUDGFX); emeraldpics[2][5] = W_CachePatchName("EMBOX6", PU_HUDGFX); emeraldpics[2][6] = W_CachePatchName("EMBOX7", PU_HUDGFX); + //emeraldpics[2][7] = W_CachePatchName("EMBOX8", PU_HUDGFX); -- unused } // Initialise Heads up diff --git a/src/hu_stuff.h b/src/hu_stuff.h index fb1fa1817..46c47b59e 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -63,7 +63,7 @@ extern patch_t *tallnum[10]; extern patch_t *nightsnum[10]; extern patch_t *lt_font[LT_FONTSIZE]; extern patch_t *cred_font[CRED_FONTSIZE]; -extern patch_t *emeraldpics[3][7]; +extern patch_t *emeraldpics[3][8]; extern patch_t *rflagico; extern patch_t *bflagico; extern patch_t *rmatcico; diff --git a/src/info.c b/src/info.c index e791c7728..f02fba8d2 100644 --- a/src/info.c +++ b/src/info.c @@ -118,10 +118,12 @@ char sprnames[NUMSPRITES + 1][5] = "TOKE", // Special Stage Token "RFLG", // Red CTF Flag "BFLG", // Blue CTF Flag - "NWNG", // NiGHTS Wing collectable item. + "SPHR", // Sphere + "NCHP", // NiGHTS chip + "NSTR", // NiGHTS star "EMBM", // Emblem "CEMG", // Chaos Emeralds - "EMER", // Emerald Hunt + "SHRD", // Emerald hunt shards // Interactive Objects "BBLS", // water bubble source @@ -187,6 +189,7 @@ char sprnames[NUMSPRITES + 1][5] = "TRE3", // Frozen Hillside "TRE4", // Polygon "TRE5", // Bush tree + "TRE6", // Spring tree // Techno Hill Scenery "THZP", // THZ1 Steam Flower @@ -392,6 +395,9 @@ char sprnames[NUMSPRITES + 1][5] = "NSCR", // NiGHTS score sprite "NPRU", // Nights Powerups "CAPS", // Capsule thingy for NiGHTS + "IDYA", // Ideya + "NTPN", // Nightopian + "SHLP", // Shleep // Secret badniks and hazards, shhhh "HIVE", @@ -432,9 +438,6 @@ char sprnames[NUMSPRITES + 1][5] = "ROIO", "ROIP", - // Blue Spheres - "BBAL", - // Gravity Well Objects "GWLG", "GWLR", @@ -715,7 +718,7 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_SUPER_TRANS4}, // S_PLAY_SUPER_TRANS3 {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_SUPER_TRANS5}, // S_PLAY_SUPER_TRANS4 {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_SUPER_TRANS6}, // S_PLAY_SUPER_TRANS5 - {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 20, {A_FadeOverlay}, 0, 0, S_PLAY_FALL}, // S_PLAY_SUPER_TRANS6 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 20, {A_FadeOverlay}, 0, 0, S_PLAY_FLOAT}, // S_PLAY_SUPER_TRANS6 {SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY}, //S_OBJPLACE_DUMMY @@ -1021,7 +1024,8 @@ state_t states[NUMSTATES] = {SPR_SPSH, 10, 1, {A_GuardChase}, 0, 0, S_EGGGUARD_RUN4}, // S_EGGGUARD_RUN3 {SPR_SPSH, 11, 1, {A_GuardChase}, 0, 0, S_EGGGUARD_RUN1}, // S_EGGGUARD_RUN4 - {SPR_ESHI, 0, 8, {A_EggShield}, 0, 0, S_EGGSHIELD}, // S_EGGSHIELD + {SPR_ESHI, 0, 8, {A_EggShield}, 0, 0, S_EGGSHIELD}, // S_EGGSHIELD + {SPR_ESHI, 0, TICRATE/2, {NULL}, 0, 0, S_NULL}, // S_EGGSHIELDBREAK // Green Snapper {SPR_GSNP, 0, 1, {A_Look}, 0, 0, S_GSNAPPER_STND}, // S_GSNAPPER_STND @@ -1591,18 +1595,22 @@ state_t states[NUMSTATES] = // Ring {SPR_RING, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_RING}, // S_RING - // Blue Sphere Replacement for special stages - {SPR_BBAL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEBALL - {SPR_BBAL, 0, 20, {NULL}, 0, 0, S_NULL}, // S_BLUEBALLSPARK + // Blue Sphere for special stages + {SPR_SPHR, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERE + {SPR_SPHR, FF_FULLBRIGHT|FF_RANDOMANIM|FF_ANIMATE, -1, {NULL}, 1, 4, S_NULL}, // S_BLUESPHEREBONUS + {SPR_SPHR, 0, 20, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERESPARK + + // NiGHTS Chip + {SPR_NCHP, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 15, 2, S_NULL}, // S_NIGHTSCHIP + {SPR_NCHP, FF_FULLBRIGHT|FF_ANIMATE|16, -1, {NULL}, 15, 2, S_NULL}, // S_NIGHTSCHIPBONUS + + // NiGHTS Star + {SPR_NSTR, FF_ANIMATE, -1, {NULL}, 14, 2, S_NULL}, // S_NIGHTSSTAR + {SPR_NSTR, 15, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSSTARXMAS // Gravity Well sprites for Egg Rock's Special Stage - {SPR_GWLG, 0, 1, {NULL}, 0, 0, S_GRAVWELLGREEN2}, // S_GRAVWELLGREEN - {SPR_GWLG, 1, 1, {NULL}, 0, 0, S_GRAVWELLGREEN3}, // S_GRAVWELLGREEN2 - {SPR_GWLG, 2, 1, {NULL}, 0, 0, S_GRAVWELLGREEN}, // S_GRAVWELLGREEN3 - - {SPR_GWLR, 0, 1, {NULL}, 0, 0, S_GRAVWELLRED2}, // S_GRAVWELLRED - {SPR_GWLR, 1, 1, {NULL}, 0, 0, S_GRAVWELLRED3}, // S_GRAVWELLRED2 - {SPR_GWLR, 2, 1, {NULL}, 0, 0, S_GRAVWELLRED}, // S_GRAVWELLRED3 + {SPR_GWLG, FF_ANIMATE, -1, {NULL}, 2, 1, S_NULL}, // S_GRAVWELLGREEN + {SPR_GWLR, FF_ANIMATE, -1, {NULL}, 2, 1, S_NULL}, // S_GRAVWELLRED // Individual Team Rings (now with shield attracting action! =P) {SPR_TRNG, FF_ANIMATE|FF_GLOBALANIM, -1, {NULL}, 23, 1, S_TEAMRING}, // S_TEAMRING @@ -1651,8 +1659,10 @@ state_t states[NUMSTATES] = {SPR_CEMG, FF_FULLBRIGHT|5, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG6 {SPR_CEMG, FF_FULLBRIGHT|6, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG7 - // Emeralds (for hunt) - {SPR_EMER, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EMER1 + // Emerald hunt shards + {SPR_SHRD, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHRD1 + {SPR_SHRD, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SHRD2 + {SPR_SHRD, 2, -1, {NULL}, 0, 0, S_NULL}, // S_SHRD3 // Bubble Source {SPR_BBLS, 0, 8, {A_BubbleSpawn}, 2048, 0, S_BUBBLES2}, // S_BUBBLES1 @@ -1934,7 +1944,6 @@ state_t states[NUMSTATES] = {SPR_CBLL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CANNONBALL1 {SPR_AROW, 0, -1, {NULL}, 0, 0, S_NULL}, // S_ARROW - {SPR_ESHI, 0, TICRATE/2, {NULL}, 0, 0, S_NULL}, // S_TEMPSHI {SPR_AROW, FF_ANIMATE, TICRATE, {A_ArrowBonks}, 7, 2, S_NULL}, // S_ARROWBONK {SPR_CFIR, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_DEMONFIRE2}, // S_DEMONFIRE1 @@ -1963,6 +1972,7 @@ state_t states[NUMSTATES] = {SPR_TRE4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_POLYGONTREE {SPR_TRE5, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BUSHTREE {SPR_TRE5, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BUSHREDTREE + {SPR_TRE6, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SPRINGTREE // THZ flowers {SPR_THZP, FF_ANIMATE, -1, {NULL}, 7, 4, S_NULL}, // S_THZFLOWERA @@ -3301,9 +3311,6 @@ state_t states[NUMSTATES] = {SPR_NSCR, FF_FULLBRIGHT|18, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE90_2 {SPR_NSCR, FF_FULLBRIGHT|19, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE100_2 - {SPR_NWNG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSWING - {SPR_NWNG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSWING_XMAS - // NiGHTS Paraloop Powerups {SPR_NPRU, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSSUPERLOOP {SPR_NPRU, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSDRILLREFILL @@ -3313,7 +3320,7 @@ state_t states[NUMSTATES] = {SPR_CAPS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGCAPSULE - // Orbiting Chaos Emeralds for NiGHTS + // Orbiting Chaos Emeralds/Ideya for NiGHTS {SPR_CEMG, FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM1}, // S_ORBITEM1 {SPR_CEMG, FF_FULLBRIGHT|1, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM2}, // S_ORBITEM2 {SPR_CEMG, FF_FULLBRIGHT|2, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM3}, // S_ORBITEM3 @@ -3322,14 +3329,11 @@ state_t states[NUMSTATES] = {SPR_CEMG, FF_FULLBRIGHT|5, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM6}, // S_ORBITEM6 {SPR_CEMG, FF_FULLBRIGHT|6, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM7}, // S_ORBITEM7 {SPR_CEMG, FF_FULLBRIGHT|7, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM8 - {SPR_CEMG, FF_FULLBRIGHT|8, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM9 - {SPR_CEMG, FF_FULLBRIGHT|9, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM10 - {SPR_CEMG, FF_FULLBRIGHT|10, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM11 - {SPR_CEMG, FF_FULLBRIGHT|11, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM12 - {SPR_CEMG, FF_FULLBRIGHT|12, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM13 - {SPR_CEMG, FF_FULLBRIGHT|13, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM14 - {SPR_CEMG, FF_FULLBRIGHT|14, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM15 - {SPR_CEMG, FF_FULLBRIGHT|15, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM16 + {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA1}, // S_ORBIDYA1 + {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|1, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA2}, // S_ORBIDYA2 + {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|2, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA3}, // S_ORBIDYA3 + {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|3, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA4}, // S_ORBIDYA4 + {SPR_IDYA, FF_TRANS20|FF_FULLBRIGHT|4, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBIDYA5}, // S_ORBIDYA5 // Flicky helper for NiGHTS {SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER2}, // S_NIGHTOPIANHELPER1 @@ -3342,6 +3346,25 @@ state_t states[NUMSTATES] = {SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER9}, // S_NIGHTOPIANHELPER8 {SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER1}, // S_NIGHTOPIANHELPER9 + // Nightopian + {SPR_NTPN, 0, 4, {A_Look}, 0, 0, S_PIAN0}, // S_PIAN0 + {SPR_NTPN, 0, 4, {A_JetgThink}, 0, 0, S_PIAN2}, // S_PIAN1 + {SPR_NTPN, 1, 4, {NULL}, 0, 0, S_PIAN3}, // S_PIAN2 + {SPR_NTPN, 2, 4, {NULL}, 0, 0, S_PIAN4}, // S_PIAN3 + {SPR_NTPN, 3, 4, {NULL}, 0, 0, S_PIAN5}, // S_PIAN4 + {SPR_NTPN, 2, 4, {NULL}, 0, 0, S_PIAN6}, // S_PIAN5 + {SPR_NTPN, 1, 4, {NULL}, 0, 0, S_PIAN1}, // S_PIAN6 + {SPR_NTPN, 5|FF_ANIMATE, 4, {NULL}, 1, 4, S_PIAN1}, // S_PIANSING + + // Shleep + {SPR_SHLP, 0, 15, {NULL}, 0, 0, S_SHLEEP2}, // S_SHLEEP1 + {SPR_SHLP, 1, 15, {NULL}, 0, 0, S_SHLEEP3}, // S_SHLEEP2 + {SPR_SHLP, 2, 15, {NULL}, 0, 0, S_SHLEEP4}, // S_SHLEEP3 + {SPR_SHLP, 1, 15, {NULL}, 0, 0, S_SHLEEP1}, // S_SHLEEP4 + {SPR_SHLP, 3, 1, {A_Scream}, 0, 0, S_SHLEEPBOUNCE2}, // S_SHLEEPBOUNCE1 + {SPR_SHLP, 3, 1, {A_ZThrust}, 9, 0, S_SHLEEPBOUNCE3}, // S_SHLEEPBOUNCE2 + {SPR_SHLP, 3, 400, {A_SetObjectFlags}, MF_SLIDEME|MF_ENEMY|MF_BOUNCE|MF_NOCLIP|MF_NOCLIPHEIGHT, 0, S_NULL}, // S_SHLEEPBOUNCE3 + // Secret badniks and hazards, shhhh {SPR_HIVE, 0, 5, {A_Look}, 1, 1, S_HIVEELEMENTAL_LOOK}, // S_HIVEELEMENTAL_LOOK {SPR_HIVE, 0, 14, {A_PlaySound}, sfx_s3k76, 1, S_HIVEELEMENTAL_PREPARE2}, // S_HIVEELEMENTAL_PREPARE1 @@ -4337,7 +4360,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_s3k7b, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_TEMPSHI, // deathstate + S_EGGSHIELDBREAK,// deathstate S_NULL, // xdeathstate sfx_wbreak, // deathsound 3, // speed @@ -5729,9 +5752,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BLUEBALL - -1, // doomednum - S_BLUEBALL, // spawnstate + { // MT_BLUESPHERE + 1706, // doomednum + S_BLUESPHERE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -5742,7 +5765,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_BLUEBALLSPARK, // deathstate + S_BLUESPHERESPARK, // deathstate S_NULL, // xdeathstate sfx_s3k65, // deathsound 38*FRACUNIT, // speed @@ -5753,7 +5776,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // damage sfx_None, // activesound MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags - S_NULL // raisestate + S_BLUESPHEREBONUS // raisestate }, { // MT_REDTEAMRING @@ -5825,7 +5848,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // missilestate S_SPRK1, // deathstate S_NULL, // xdeathstate - sfx_token, // deathsound + sfx_None, // deathsound 0, // speed 8*FRACUNIT, // radius 16*FRACUNIT, // height @@ -6103,7 +6126,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_EMERHUNT 320, // doomednum - S_EMER1, // spawnstate + S_SHRD1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -6118,8 +6141,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_cgot, // deathsound 8, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height + 12*FRACUNIT, // radius + 42*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage @@ -6588,7 +6611,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = }, { // MT_SPIKEBALL - -1, // doomednum + 521, // doomednum S_SPIKEBALL1, // spawnstate 1000, // spawnhealth S_NULL, // seestate @@ -6604,7 +6627,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 10*FRACUNIT, // speed - 4*FRACUNIT, // radius + 12*FRACUNIT, // radius 8*FRACUNIT, // height 0, // display offset DMG_SPIKE, // mass @@ -8803,7 +8826,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_GFZTREE 806, // doomednum - S_GFZTREE, // spawnstate + S_GFZTREE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -8830,7 +8853,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_GFZBERRYTREE 807, // doomednum - S_GFZBERRYTREE, // spawnstate + S_GFZBERRYTREE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -8857,7 +8880,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_GFZCHERRYTREE 808, // doomednum - S_GFZCHERRYTREE, // spawnstate + S_GFZCHERRYTREE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -8884,7 +8907,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_CHECKERTREE 810, // doomednum - S_CHECKERTREE, // spawnstate + S_CHECKERTREE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -8911,7 +8934,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_CHECKERSUNSETTREE 811, // doomednum - S_CHECKERSUNSETTREE, // spawnstate + S_CHECKERSUNSETTREE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -8938,7 +8961,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_FHZTREE 812, // doomednum - S_FHZTREE, // spawnstate + S_FHZTREE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -8965,7 +8988,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_FHZPINKTREE 813, // doomednum - S_FHZPINKTREE, // spawnstate + S_FHZPINKTREE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -8992,7 +9015,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_POLYGONTREE 814, // doomednum - S_POLYGONTREE, // spawnstate + S_POLYGONTREE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -9019,7 +9042,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_BUSHTREE 815, // doomednum - S_BUSHTREE, // spawnstate + S_BUSHTREE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -9046,7 +9069,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_BUSHREDTREE 816, // doomednum - S_BUSHREDTREE, // spawnstate + S_BUSHREDTREE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -9071,6 +9094,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SPRINGTREE + 1600, // doomednum + S_SPRINGTREE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_THZFLOWER1 900, // doomednum S_THZFLOWERA, // spawnstate @@ -14406,7 +14456,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // painchance sfx_None, // painsound S_ORBITEM1, // meleestate - S_NULL, // missilestate + S_ORBIDYA1, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound @@ -16131,11 +16181,11 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_NIGHTSWING - 1706, // doomednum - S_NIGHTSWING, // spawnstate + { // MT_NIGHTSCHIP + -1, // doomednum + S_NIGHTSCHIP, // spawnstate 1000, // spawnhealth - S_NIGHTSWING_XMAS, // seestate + S_NULL, // seestate sfx_None, // seesound 8, // reactiontime sfx_None, // attacksound @@ -16146,14 +16196,41 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // missilestate S_SPRK1, // deathstate S_NULL, // xdeathstate - sfx_None, // deathsound + sfx_ncchip, // deathsound 1, // speed - 12*FRACUNIT, // radius + 16*FRACUNIT, // radius 24*FRACUNIT, // height 0, // display offset 4, // mass 0, // damage - sfx_ncitem, // activesound + sfx_None, // activesound + MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NIGHTSCHIPBONUS // raisestate + }, + + { // MT_NIGHTSSTAR + -1, // doomednum + S_NIGHTSSTAR, // spawnstate + 1000, // spawnhealth + S_NIGHTSSTARXMAS, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_s3k33, // painsound + S_RING, // meleestate + S_NULL, // missilestate + S_SPRK1, // deathstate + S_NULL, // xdeathstate + sfx_ncitem, // deathsound + 1, // speed + 16*FRACUNIT, // radius + 24*FRACUNIT, // height + 0, // display offset + 4, // mass + 0, // damage + sfx_None, // activesound MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags S_NULL // raisestate }, @@ -16320,7 +16397,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - // the flicky that orbits the player when they have a Nightopian helper { // MT_NIGHTOPIANHELPER -1, // doomednum S_NIGHTOPIANHELPER1, // spawnstate @@ -16348,6 +16424,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_PIAN + 1602, // doomednum + S_PIAN0, // spawnstate + 1000, // spawnhealth + S_PIAN1, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 200, // painchance + sfx_None, // painsound + S_PIANSING, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + FRACUNIT, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_SLIDEME|MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_SHLEEP + 1601, // doomednum + S_SHLEEP1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 200, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_SHLEEPBOUNCE1, // deathstate + S_NULL, // xdeathstate + sfx_peww, // deathsound + 0, // speed + 24*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_SLIDEME|MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_HIVEELEMENTAL 3190, // doomednum S_HIVEELEMENTAL_LOOK, // spawnstate diff --git a/src/info.h b/src/info.h index 5f84b22d4..4e316efdb 100644 --- a/src/info.h +++ b/src/info.h @@ -337,10 +337,12 @@ typedef enum sprite SPR_TOKE, // Special Stage Token SPR_RFLG, // Red CTF Flag SPR_BFLG, // Blue CTF Flag - SPR_NWNG, // NiGHTS Wing collectable item. + SPR_SPHR, // Sphere + SPR_NCHP, // NiGHTS chip + SPR_NSTR, // NiGHTS star SPR_EMBM, // Emblem SPR_CEMG, // Chaos Emeralds - SPR_EMER, // Emerald Hunt + SPR_SHRD, // Emerald Hunt // Interactive Objects SPR_BBLS, // water bubble source @@ -406,6 +408,7 @@ typedef enum sprite SPR_TRE3, // Frozen Hillside SPR_TRE4, // Polygon SPR_TRE5, // Bush tree + SPR_TRE6, // Spring tree // Techno Hill Scenery SPR_THZP, // THZ1 Steam Flower @@ -611,6 +614,9 @@ typedef enum sprite SPR_NSCR, // NiGHTS score sprite SPR_NPRU, // Nights Powerups SPR_CAPS, // Capsule thingy for NiGHTS + SPR_IDYA, // Ideya + SPR_NTPN, // Nightopian + SPR_SHLP, // Shleep // Secret badniks and hazards, shhhh SPR_HIVE, @@ -651,9 +657,6 @@ typedef enum sprite SPR_ROIO, SPR_ROIP, - // Blue Spheres - SPR_BBAL, - // Gravity Well Objects SPR_GWLG, SPR_GWLR, @@ -1149,6 +1152,7 @@ typedef enum state // Egg Shield for Egg Guard S_EGGSHIELD, + S_EGGSHIELDBREAK, // Green Snapper S_GSNAPPER_STND, @@ -1717,17 +1721,21 @@ typedef enum state S_RING, // Blue Sphere for special stages - S_BLUEBALL, - S_BLUEBALLSPARK, + S_BLUESPHERE, + S_BLUESPHEREBONUS, + S_BLUESPHERESPARK, + + // NiGHTS Chip + S_NIGHTSCHIP, + S_NIGHTSCHIPBONUS, + + // NiGHTS Star + S_NIGHTSSTAR, + S_NIGHTSSTARXMAS, // Gravity Wells for special stages S_GRAVWELLGREEN, - S_GRAVWELLGREEN2, - S_GRAVWELLGREEN3, - S_GRAVWELLRED, - S_GRAVWELLRED2, - S_GRAVWELLRED3, // Individual Team Rings S_TEAMRING, @@ -1776,8 +1784,10 @@ typedef enum state S_CEMG6, S_CEMG7, - // Emeralds (for hunt) - S_EMER1, + // Emerald hunt shards + S_SHRD1, + S_SHRD2, + S_SHRD3, // Bubble Source S_BUBBLES1, @@ -2061,7 +2071,6 @@ typedef enum state // Arrow S_ARROW, - S_TEMPSHI, S_ARROWBONK, // Trapgoyle Demon fire @@ -2091,6 +2100,7 @@ typedef enum state S_POLYGONTREE, S_BUSHTREE, S_BUSHREDTREE, + S_SPRINGTREE, // THZ flowers S_THZFLOWERA, // THZ1 Steam flower @@ -3359,9 +3369,6 @@ typedef enum state S_NIGHTSCORE90_2, S_NIGHTSCORE100_2, - S_NIGHTSWING, - S_NIGHTSWING_XMAS, - // NiGHTS Paraloop Powerups S_NIGHTSSUPERLOOP, S_NIGHTSDRILLREFILL, @@ -3379,14 +3386,11 @@ typedef enum state S_ORBITEM6, S_ORBITEM7, S_ORBITEM8, - S_ORBITEM9, - S_ORBITEM10, - S_ORBITEM11, - S_ORBITEM12, - S_ORBITEM13, - S_ORBITEM14, - S_ORBITEM15, - S_ORBITEM16, + S_ORBIDYA1, + S_ORBIDYA2, + S_ORBIDYA3, + S_ORBIDYA4, + S_ORBIDYA5, // "Flicky" helper S_NIGHTOPIANHELPER1, @@ -3399,6 +3403,25 @@ typedef enum state S_NIGHTOPIANHELPER8, S_NIGHTOPIANHELPER9, + // Nightopian + S_PIAN0, + S_PIAN1, + S_PIAN2, + S_PIAN3, + S_PIAN4, + S_PIAN5, + S_PIAN6, + S_PIANSING, + + // Shleep + S_SHLEEP1, + S_SHLEEP2, + S_SHLEEP3, + S_SHLEEP4, + S_SHLEEPBOUNCE1, + S_SHLEEPBOUNCE2, + S_SHLEEPBOUNCE3, + // Secret badniks and hazards, shhhh S_HIVEELEMENTAL_LOOK, S_HIVEELEMENTAL_PREPARE1, @@ -3694,7 +3717,7 @@ typedef enum mobj_type // Collectible Items MT_RING, MT_FLINGRING, // Lost ring - MT_BLUEBALL, // Blue sphere replacement for special stages + MT_BLUESPHERE, // Blue sphere replacement for special stages MT_REDTEAMRING, //Rings collectable by red team. MT_BLUETEAMRING, //Rings collectable by blue team. MT_TOKEN, // Special Stage token for special stage @@ -3838,6 +3861,7 @@ typedef enum mobj_type MT_POLYGONTREE, MT_BUSHTREE, MT_BUSHREDTREE, + MT_SPRINGTREE, // Techno Hill Scenery MT_THZFLOWER1, @@ -4150,7 +4174,8 @@ typedef enum mobj_type MT_HOOPCOLLIDE, // Collision detection for NiGHTS hoops MT_HOOPCENTER, // Center of a hoop MT_NIGHTSCORE, - MT_NIGHTSWING, + MT_NIGHTSCHIP, // NiGHTS Chip + MT_NIGHTSSTAR, // NiGHTS Star MT_NIGHTSSUPERLOOP, MT_NIGHTSDRILLREFILL, MT_NIGHTSHELPER, @@ -4158,6 +4183,8 @@ typedef enum mobj_type MT_NIGHTSLINKFREEZE, MT_EGGCAPSULE, MT_NIGHTOPIANHELPER, // the actual helper object that orbits you + MT_PIAN, // decorative singing friend + MT_SHLEEP, // almost-decorative sleeping enemy // Secret badniks and hazards, shhhh MT_HIVEELEMENTAL, diff --git a/src/lua_hud.h b/src/lua_hud.h index beaca7883..c1479d5ef 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -24,7 +24,7 @@ enum hud { // NiGHTS mode hud_nightslink, hud_nightsdrill, - hud_nightsrings, + hud_nightsspheres, hud_nightsscore, hud_nightstime, hud_nightsrecords, diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 12b2646d0..8a1079c36 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -130,6 +130,8 @@ static int player_get(lua_State *L) lua_pushangle(L, plr->drawangle); else if (fastcmp(field,"rings")) lua_pushinteger(L, plr->rings); + else if (fastcmp(field,"spheres")) + lua_pushinteger(L, plr->spheres); else if (fastcmp(field,"pity")) lua_pushinteger(L, plr->pity); else if (fastcmp(field,"currentweapon")) @@ -294,8 +296,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->startedtime); else if (fastcmp(field,"finishedtime")) lua_pushinteger(L, plr->finishedtime); - else if (fastcmp(field,"finishedrings")) - lua_pushinteger(L, plr->finishedrings); + else if (fastcmp(field,"finishedspheres")) + lua_pushinteger(L, plr->finishedspheres); else if (fastcmp(field,"marescore")) lua_pushinteger(L, plr->marescore); else if (fastcmp(field,"lastmarescore")) @@ -396,6 +398,8 @@ static int player_set(lua_State *L) plr->drawangle = luaL_checkangle(L, 3); else if (fastcmp(field,"rings")) plr->rings = (INT32)luaL_checkinteger(L, 3); + else if (fastcmp(field,"spheres")) + plr->spheres = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"pity")) plr->pity = (SINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"currentweapon")) @@ -448,7 +452,7 @@ static int player_set(lua_State *L) else if (fastcmp(field,"followitem")) plr->followitem = luaL_checkinteger(L, 3); else if (fastcmp(field,"followmobj")) - plr->followmobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&plr->followmobj, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ))); else if (fastcmp(field,"actionspd")) plr->actionspd = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"mindash")) @@ -570,8 +574,8 @@ static int player_set(lua_State *L) plr->startedtime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"finishedtime")) plr->finishedtime = (tic_t)luaL_checkinteger(L, 3); - else if (fastcmp(field,"finishedrings")) - plr->finishedrings = (INT16)luaL_checkinteger(L, 3); + else if (fastcmp(field,"finishedspheres")) + plr->finishedspheres = (INT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"marescore")) plr->marescore = (UINT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"lastmarescore")) diff --git a/src/m_cheat.c b/src/m_cheat.c index 174e2780d..81a8702fd 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -728,7 +728,7 @@ void Command_Setrings_f(void) // P_GivePlayerRings does value clamping players[consoleplayer].rings = 0; P_GivePlayerRings(&players[consoleplayer], atoi(COM_Argv(1))); - if (!G_IsSpecialStage(gamemap) || !useNightsSS) + if (!G_IsSpecialStage(gamemap) || !(maptol & TOL_NIGHTS)) players[consoleplayer].totalring -= atoi(COM_Argv(1)); //undo totalring addition done in P_GivePlayerRings G_SetGameModified(multiplayer); @@ -1010,7 +1010,7 @@ void OP_NightsObjectplace(player_t *player) mt->options = (UINT16)((player->mo->z - fheight)>>FRACBITS); mt->angle = (INT16)(mt->angle+(INT16)((FixedInt(FixedDiv(temp*FRACUNIT, 360*(FRACUNIT/256))))<<8)); - P_SpawnHoopsAndRings(mt); + P_SpawnHoopsAndRings(mt, false); } // This places a bumper! @@ -1024,26 +1024,26 @@ void OP_NightsObjectplace(player_t *player) P_SpawnMapThing(mt); } - // This places a ring! + // This places a sphere! if (cmd->buttons & BT_WEAPONNEXT) { player->pflags |= PF_ATTACKDOWN; if (!OP_HeightOkay(player, false)) return; - mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_RING].doomednum, false); - P_SpawnHoopsAndRings(mt); + mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_BLUESPHERE].doomednum, false); + P_SpawnHoopsAndRings(mt, false); } - // This places a wing item! + // This places a ring! if (cmd->buttons & BT_WEAPONPREV) { player->pflags |= PF_ATTACKDOWN; if (!OP_HeightOkay(player, false)) return; - mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_NIGHTSWING].doomednum, false); - P_SpawnHoopsAndRings(mt); + mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_RING].doomednum, false); + P_SpawnHoopsAndRings(mt, false); } // This places a custom object as defined in the console cv_mapthingnum. @@ -1077,12 +1077,12 @@ void OP_NightsObjectplace(player_t *player) if (mt->type == 300 // Ring || mt->type == 308 || mt->type == 309 // Team Rings - || mt->type == 1706 // Nights Wing + || mt->type == 1706 // Sphere || (mt->type >= 600 && mt->type <= 609) // Placement patterns || mt->type == 1705 || mt->type == 1713 // NiGHTS Hoops || mt->type == 1800) // Mario Coin { - P_SpawnHoopsAndRings(mt); + P_SpawnHoopsAndRings(mt, false); } else P_SpawnMapThing(mt); @@ -1227,7 +1227,7 @@ void OP_ObjectplaceMovement(player_t *player) || mt->type == 1705 || mt->type == 1713 // NiGHTS Hoops || mt->type == 1800) // Mario Coin { - P_SpawnHoopsAndRings(mt); + P_SpawnHoopsAndRings(mt, false); } else P_SpawnMapThing(mt); diff --git a/src/p_enemy.c b/src/p_enemy.c index 2c55210b7..2f1fa842e 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8604,10 +8604,12 @@ void A_OrbitNights(mobj_t* actor) return; #endif - if (!actor->target || !actor->target->player || - !(actor->target->player->powers[pw_carry] == CR_NIGHTSMODE) || !actor->target->player->nightstime + if (!actor->target + || (actor->target->player && + // if NiGHTS special stage and not NiGHTSmode. + (((maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && !(actor->target->player->powers[pw_carry] == CR_NIGHTSMODE)) // Also remove this object if they no longer have a NiGHTS helper - || (ishelper && !actor->target->player->powers[pw_nights_helper])) + || (ishelper && !actor->target->player->powers[pw_nights_helper])))) { P_RemoveMobj(actor); return; @@ -8633,7 +8635,7 @@ void A_OrbitNights(mobj_t* actor) } P_SetThingPosition(actor); - if (ishelper) // Flash a helper that's about to be removed. + if (ishelper && actor->target->player) // Flash a helper that's about to be removed. { if ((actor->target->player->powers[pw_nights_helper] < TICRATE) && (actor->target->player->powers[pw_nights_helper] & 1)) @@ -11185,7 +11187,7 @@ void A_FlameParticle(mobj_t *actor) // // Description: Makes a pretty overlay (primarily for super/NiGHTS transformation). // -// var1 = bit 1 = don't halt momentum, bit 2 = don't make fast, bit 3 = don't set tracer +// var1 = bit 1 = bit 1 = don't make fast, bit 2 = don't set tracer // var2 = unused // void A_FadeOverlay(mobj_t *actor) @@ -11199,13 +11201,10 @@ void A_FadeOverlay(mobj_t *actor) return; #endif - if (!(locvar1 & 1)) - actor->momx = actor->momy = actor->momz = 0; - fade = P_SpawnGhostMobj(actor); fade->frame = actor->frame; - if (!(locvar1 & 2)) + if (!(locvar1 & 1)) { fade->fuse = 15; fade->flags2 |= MF2_BOSSNOTRAP; @@ -11213,7 +11212,7 @@ void A_FadeOverlay(mobj_t *actor) else fade->fuse = 20; - if (!(locvar1 & 4)) + if (!(locvar1 & 2)) P_SetTarget(&actor->tracer, fade); } diff --git a/src/p_inter.c b/src/p_inter.c index fed459d6a..33a5abcd2 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -23,6 +23,7 @@ #include "hu_stuff.h" #include "lua_hook.h" #include "m_cond.h" // unlockables, emblems, etc +#include "p_setup.h" #include "m_cheat.h" // objectplace #include "m_misc.h" #include "v_video.h" // video flags for CEchos @@ -471,40 +472,49 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) /* FALLTHRU */ case MT_RING: case MT_FLINGRING: - if (!(P_CanPickupItem(player, false))) - return; - - special->momx = special->momy = special->momz = 0; - P_GivePlayerRings(player, 1); - - if ((maptol & TOL_NIGHTS) && special->type != MT_FLINGRING) - P_DoNightsScore(player); - break; - case MT_COIN: case MT_FLINGCOIN: if (!(P_CanPickupItem(player, false))) return; - special->momx = special->momy = 0; + special->momx = special->momy = special->momz = 0; P_GivePlayerRings(player, 1); - if ((maptol & TOL_NIGHTS) && special->type != MT_FLINGCOIN) + if ((maptol & TOL_NIGHTS) && special->type != MT_FLINGRING && special->type != MT_FLINGCOIN) P_DoNightsScore(player); break; - case MT_BLUEBALL: + case MT_BLUESPHERE: if (!(P_CanPickupItem(player, false))) return; - P_GivePlayerRings(player, 1); - special->momx = special->momy = special->momz = 0; - special->destscale = FixedMul(8*FRACUNIT, special->scale); + P_GivePlayerSpheres(player, 1); + + special->destscale = ((player->powers[pw_carry] == CR_NIGHTSMODE) ? 4 : 2)*special->scale; if (states[special->info->deathstate].tics > 0) special->scalespeed = FixedDiv(FixedDiv(special->destscale, special->scale), states[special->info->deathstate].tics<scalespeed = 4*FRACUNIT/5; + if (maptol & TOL_NIGHTS) + P_DoNightsScore(player); + break; + case MT_NIGHTSCHIP: + if (!(P_CanPickupItem(player, false))) + return; + + special->momx = special->momy = special->momz = 0; + P_GivePlayerSpheres(player, 1); + + if (maptol & TOL_NIGHTS) + P_DoNightsScore(player); + break; + case MT_NIGHTSSTAR: + if (!(P_CanPickupItem(player, false))) + return; + + special->momx = special->momy = special->momz = 0; + if (maptol & TOL_NIGHTS) P_DoNightsScore(player); break; @@ -562,7 +572,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_AddPlayerScore(player, 1000); if (gametype != GT_COOP || modeattacking) // score only? + { + S_StartSound(toucher, sfx_chchng); break; + } tokenlist += special->health; @@ -574,10 +587,17 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) players->gotcontinue = true; if (P_IsLocalPlayer(player)) S_StartSound(NULL, sfx_s3kac); + else + S_StartSound(toucher, sfx_chchng); } + else + S_StartSound(toucher, sfx_chchng); } else + { token++; + S_StartSound(toucher, sfx_token); + } break; @@ -602,7 +622,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) players[i].exiting = (14*TICRATE)/5 + 1; } - S_StartSound(NULL, sfx_lvpass); + //S_StartSound(NULL, sfx_lvpass); } break; @@ -733,45 +753,71 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // NiGHTS gameplay items and powerups // // ********************************** // case MT_NIGHTSDRONE: - if (player->bot) - return; - if (player->exiting) - return; - if (player->bonustime) { - if (G_IsSpecialStage(gamemap)) //After-mare bonus time/emerald reward in special stages. - { - // only allow the player with the emerald in-hand to leave. - if (toucher->tracer - && toucher->tracer->type == MT_GOTEMERALD) - { - } - else // Make sure that SOMEONE has the emerald, at least! - { - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo->tracer - && players[i].mo->tracer->type == MT_GOTEMERALD) - return; - // Well no one has an emerald, so exit anyway! - } - P_GiveEmerald(false); - // Don't play Ideya sound in special stage mode - } - else - S_StartSound(toucher, special->info->activesound); - } - else //Initial transformation. Don't allow second chances in special stages! - { - if (player->powers[pw_carry] == CR_NIGHTSMODE) + boolean spec = G_IsSpecialStage(gamemap); + if (player->bot) return; + if (player->exiting) + return; + if (player->bonustime) + { + if (spec) //After-mare bonus time/emerald reward in special stages. + { + // only allow the player with the emerald in-hand to leave. + if (toucher->tracer + && toucher->tracer->type == MT_GOTEMERALD) + {} + else // Make sure that SOMEONE has the emerald, at least! + { + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i] && players[i].playerstate == PST_LIVE + && players[i].mo->tracer + && players[i].mo->tracer->type == MT_GOTEMERALD) + return; + // Well no one has an emerald, so exit anyway! + } + P_GiveEmerald(false); + // Don't play Ideya sound in special stage mode + } + else + S_StartSound(toucher, special->info->activesound); + } + else //Initial transformation. Don't allow second chances in special stages! + { + if (player->powers[pw_carry] == CR_NIGHTSMODE) + return; - S_StartSound(toucher, sfx_supert); + S_StartSound(toucher, sfx_supert); + } + P_SwitchSpheresBonusMode(false); + if (!(netgame || multiplayer) && !(player->powers[pw_carry] == CR_NIGHTSMODE)) + P_SetTarget(&special->tracer, toucher); + P_NightserizePlayer(player, special->health); // Transform! + if (!spec) + { + if (toucher->tracer) // Move the ideya over to the drone! + { + mobj_t *hnext = special->hnext; + P_SetTarget(&special->hnext, toucher->tracer); + P_SetTarget(&special->hnext->hnext, hnext); // Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo. + P_SetTarget(&special->hnext->target, special); + P_SetTarget(&toucher->tracer, NULL); + if (hnext) + { + special->hnext->extravalue1 = (angle_t)(hnext->extravalue1 - 72*ANG1); + if (special->hnext->extravalue1 > hnext->extravalue1) + special->hnext->extravalue1 -= (72*ANG1)/special->hnext->extravalue1; + } + } + if (player->exiting) // ...then move it back? + { + mobj_t *hnext = special; + while ((hnext = hnext->hnext)) + P_SetTarget(&hnext->target, toucher); + } + } + return; } - if (!(netgame || multiplayer) && !(player->powers[pw_carry] == CR_NIGHTSMODE)) - P_SetTarget(&special->tracer, toucher); - P_NightserizePlayer(player, special->health); // Transform! - return; case MT_NIGHTSLOOPHELPER: // One second delay if (special->fuse < toucher->fuse - TICRATE) @@ -876,8 +922,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } } - if (!(mo2->type == MT_NIGHTSWING || mo2->type == MT_RING || mo2->type == MT_COIN - || mo2->type == MT_BLUEBALL + if (!(mo2->type == MT_RING || mo2->type == MT_COIN || mo2->type == MT_BLUESPHERE + || mo2->type == MT_NIGHTSCHIP || mo2->type == MT_NIGHTSSTAR || ((mo2->type == MT_EMBLEM) && (mo2->reactiontime & GE_NIGHTSPULL)))) continue; @@ -903,16 +949,16 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; if (G_IsSpecialStage(gamemap) && !player->exiting) - { // In special stages, share rings. Everyone gives up theirs to the player who touched the capsule + { // In special stages, share spheres. Everyone gives up theirs to the player who touched the capsule for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && (&players[i] != player) && players[i].rings > 0) + if (playeringame[i] && (&players[i] != player) && players[i].spheres > 0) { - player->rings += players[i].rings; - players[i].rings = 0; + player->spheres += players[i].spheres; + players[i].spheres = 0; } } - if (player->rings <= 0 || player->exiting) + if (player->spheres <= 0 || player->exiting) return; // Mark the player as 'pull into the capsule' @@ -1120,17 +1166,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) HU_DoCEcho(M_GetText("\\\\\\\\\\\\\\\\Link Freeze")); } break; - case MT_NIGHTSWING: - if (G_IsSpecialStage(gamemap) && useNightsSS) - { // Pseudo-ring. - S_StartSound(toucher, special->info->painsound); - player->totalring++; - } - else - S_StartSound(toucher, special->info->activesound); - - P_DoNightsScore(player); - break; case MT_HOOPCOLLIDE: // This produces a kind of 'domino effect' with the hoop's pieces. for (; special->hprev != NULL; special = special->hprev); // Move to the first sprite in the hoop @@ -1496,12 +1531,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) player->pflags |= PF_JUMPSTASIS; return; - case MT_SPECIALSPIKEBALL: - if (!useNightsSS && G_IsSpecialStage(gamemap)) // Only for old special stages - P_SpecialStageDamage(player, special, NULL); - else - P_DamageMobj(toucher, special, special, 1, 0); - return; case MT_EGGMOBILE2_POGO: // sanity checks if (!special->target || !special->target->health) @@ -2070,8 +2099,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL)) P_SetTarget(&target->tracer, inflictor); - if (!useNightsSS && G_IsSpecialStage(gamemap) && target->player && sstimer > 6) - sstimer = 6; // Just let P_Ticker take care of the rest. + if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && target->player && target->player->nightstime > 6) + target->player->nightstime = 6; // Just let P_Ticker take care of the rest. if (target->flags & (MF_ENEMY|MF_BOSS)) target->momx = target->momy = target->momz = 0; @@ -2633,20 +2662,10 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) player->drillmeter -= 5*20; else { - if (source && source->player) - { - if (player->nightstime > 20*TICRATE) - player->nightstime -= 20*TICRATE; - else - player->nightstime = 1; - } + if (player->nightstime > 5*TICRATE) + player->nightstime -= 5*TICRATE; else - { - if (player->nightstime > 5*TICRATE) - player->nightstime -= 5*TICRATE; - else - player->nightstime = 1; - } + player->nightstime = 1; } if (player->pflags & PF_TRANSFERTOCLOSEST) @@ -2670,7 +2689,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) && player->nightstime < 10*TICRATE) { //S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH - S_ChangeMusicInternal("_drown",false); + S_ChangeMusicInternal((((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? "_ntime" : "_drown"), false); } } } @@ -3000,11 +3019,13 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN // P_SpecialStageDamage // // Do old special stage-style damaging -// Removes 10 rings from the player, or knocks off their shield if they have one. +// Removes 5 seconds from the player, or knocks off their shield if they have one. // If they don't have anything, just knock the player back anyway (this doesn't kill them). // void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) { + tic_t oldnightstime = player->nightstime; + if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) return; @@ -3015,17 +3036,24 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) } else { - P_PlayRinglossSound(player->mo); - if (player->rings >= 10) - player->rings -= 10; + S_StartSound(player->mo, sfx_nghurt); + if (player->nightstime > 5*TICRATE) + player->nightstime -= 5*TICRATE; else - player->rings = 0; + player->nightstime = 0; } P_DoPlayerPain(player, inflictor, source); if (gametype == GT_CTF && player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)) P_PlayerFlagBurst(player, false); + + if (oldnightstime > 10*TICRATE + && player->nightstime < 10*TICRATE) + { + //S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH + S_ChangeMusicInternal((((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? "_ntime" : "_drown"), false); + } } /** Damages an object, which may or may not be a player. @@ -3175,6 +3203,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return true; } + if (G_IsSpecialStage(gamemap)) + { + P_SpecialStageDamage(player, inflictor, source); + return true; + } + if (!force && inflictor && inflictor->flags & MF_FIRE) { if (player->powers[pw_shield] & SH_PROTECTFIRE) diff --git a/src/p_local.h b/src/p_local.h index da4c70b0f..682fb7b55 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -146,6 +146,7 @@ void P_SpawnShieldOrb(player_t *player); void P_SwitchShield(player_t *player, UINT16 shieldtype); mobj_t *P_SpawnGhostMobj(mobj_t *mobj); void P_GivePlayerRings(player_t *player, INT32 num_rings); +void P_GivePlayerSpheres(player_t *player, INT32 num_spheres); void P_GivePlayerLives(player_t *player, INT32 numlives); void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound); UINT8 P_GetNextEmerald(void); diff --git a/src/p_mobj.c b/src/p_mobj.c index dbf5f5880..587615448 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2513,7 +2513,9 @@ static boolean P_ZMovement(mobj_t *mo) case MT_RING: // Ignore still rings case MT_COIN: - case MT_BLUEBALL: + case MT_BLUESPHERE: + case MT_NIGHTSCHIP: + case MT_NIGHTSSTAR: case MT_REDTEAMRING: case MT_BLUETEAMRING: case MT_FLINGRING: @@ -2550,10 +2552,6 @@ static boolean P_ZMovement(mobj_t *mo) if (!(mo->momx || mo->momy || mo->momz)) return true; break; - case MT_NIGHTSWING: - if (!(mo->momx || mo->momy || mo->momz)) - return true; - break; case MT_FLAMEJET: case MT_VERTICALFLAMEJET: if (!(mo->flags & MF_BOUNCE)) @@ -7225,7 +7223,7 @@ void P_MobjThinker(mobj_t *mobj) else if (mobj->health <= 0) // Dead things think differently than the living. switch (mobj->type) { - case MT_BLUEBALL: + case MT_BLUESPHERE: if ((mobj->tics>>2)+1 > 0 && (mobj->tics>>2)+1 <= tr_trans60) // tr_trans50 through tr_trans90, shifting once every second frame mobj->frame = (NUMTRANSMAPS-((mobj->tics>>2)+1))<target, NULL); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo - && players[i].mare == mobj->threshold && players[i].rings > 0) + && players[i].mare == mobj->threshold && players[i].spheres > 0) { fixed_t dist = P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y); if (dist < shortest) @@ -7775,8 +7773,8 @@ void P_MobjThinker(mobj_t *mobj) } if (!bonustime) { - mobj->flags &= ~MF_NOGRAVITY; - P_SetMobjState(mobj, S_NIGHTSDRONE1); + /*mobj->flags &= ~MF_NOGRAVITY; + P_SetMobjState(mobj, S_NIGHTSDRONE1);*/ mobj->flags2 |= MF2_DONTDRAW; } } @@ -7848,7 +7846,9 @@ void P_MobjThinker(mobj_t *mobj) mobj->flags2 &= ~MF2_DONTDRAW; } mobj->angle += ANG10; - if (mobj->z <= mobj->floorz) + if (mobj->flags2 & MF2_DONTDRAW) + mobj->momz = 0; + else if (mobj->z <= mobj->floorz) mobj->momz = 5*FRACUNIT; } break; @@ -7881,7 +7881,9 @@ void P_MobjThinker(mobj_t *mobj) break; case MT_RING: case MT_COIN: - case MT_BLUEBALL: + case MT_BLUESPHERE: + case MT_NIGHTSCHIP: + case MT_NIGHTSSTAR: case MT_REDTEAMRING: case MT_BLUETEAMRING: // No need to check water. Who cares? @@ -7899,10 +7901,6 @@ void P_MobjThinker(mobj_t *mobj) else A_AttractChase(mobj); break; - case MT_NIGHTSWING: - if (mobj->flags2 & MF2_NIGHTSPULL) - P_NightsItemChase(mobj); - break; case MT_EMBLEM: if (mobj->flags2 & MF2_NIGHTSPULL) P_NightsItemChase(mobj); @@ -8025,7 +8023,7 @@ void P_MobjThinker(mobj_t *mobj) { mobj_t *missile; - if (mobj->target->player && mobj->target->player->nightstime) + if (mobj->target->player && mobj->target->player->powers[pw_carry] == CR_NIGHTSMODE) { fixed_t oldval = mobjinfo[mobj->extravalue1].speed; @@ -8726,7 +8724,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; case MT_RING: case MT_COIN: - case MT_BLUEBALL: nummaprings++; default: break; @@ -8861,7 +8858,6 @@ void P_RemoveMobj(mobj_t *mobj) if (mobj->spawnpoint && (mobj->type == MT_RING || mobj->type == MT_COIN - || mobj->type == MT_BLUEBALL || mobj->type == MT_REDTEAMRING || mobj->type == MT_BLUETEAMRING || P_WeaponOrPanel(mobj->type)) @@ -8881,7 +8877,7 @@ void P_RemoveMobj(mobj_t *mobj) if (mobj->player && mobj->player->followmobj) { P_RemoveMobj(mobj->player->followmobj); - mobj->player->followmobj = NULL; + P_SetTarget(&mobj->player->followmobj, NULL); } mobj->health = 0; // Just because @@ -9314,7 +9310,7 @@ void P_SpawnPlayer(INT32 playernum) p->spectator = p->outofcoop = (((multiplayer || netgame) && gametype == GT_COOP) // only question status in coop && ((leveltime > 0 - && ((G_IsSpecialStage(gamemap) && useNightsSS) // late join special stage + && ((G_IsSpecialStage(gamemap) && (maptol & TOL_NIGHTS)) // late join special stage || (cv_coopstarposts.value == 2 && (p->jointime < 1 || p->outofcoop)))) // late join or die in new coop || (((cv_cooplives.value == 1) || !P_GetLives(p)) && p->lives <= 0))); // game over and can't redistribute lives } @@ -9383,7 +9379,7 @@ void P_SpawnPlayer(INT32 playernum) P_SetupStateAnimation(mobj, mobj->state); mobj->health = 1; - p->rings = 0; + p->rings = p->spheres = 0; p->playerstate = PST_LIVE; p->bonustime = false; @@ -9402,6 +9398,22 @@ void P_SpawnPlayer(INT32 playernum) mobj->radius = FixedMul(skins[p->skin].radius, mobj->scale); mobj->height = P_GetPlayerHeight(p); + if (!leveltime && ((maptol & TOL_NIGHTS) == TOL_NIGHTS) != (G_IsSpecialStage(gamemap))) // non-special NiGHTS stage or special non-NiGHTS stage + { + if (maptol & TOL_NIGHTS) + { + if (p == players) // this is totally the wrong place to do this aaargh. + { + mobj_t *idya = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_GOTEMERALD); + P_SetTarget(&idya->target, mobj); + P_SetMobjState(idya, mobjinfo[MT_GOTEMERALD].missilestate); + P_SetTarget(&mobj->tracer, idya); + } + } + else if (sstimer) + p->nightstime = sstimer; + } + // Spawn with a pity shield if necessary. P_DoPityCheck(p); } @@ -9715,10 +9727,6 @@ void P_SpawnMapThing(mapthing_t *mthing) return; } - if (!G_RingSlingerGametype() || !cv_specialrings.value) - if (P_WeaponOrPanel(i)) - return; // Don't place weapons/panels in non-ringslinger modes - if (i == MT_EMERHUNT) { // Emerald Hunt is Coop only. @@ -9752,6 +9760,10 @@ void P_SpawnMapThing(mapthing_t *mthing) if ((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS)) return; + if (!G_RingSlingerGametype() || !cv_specialrings.value) + if (P_WeaponOrPanel(i)) + return; // Don't place weapons/panels in non-ringslinger modes + // Altering monitor spawns via cvars // If MF_GRENADEBOUNCE is set in the monitor's info, // skip this step. (Used for gold monitors) @@ -10754,8 +10766,9 @@ ML_EFFECT4 : Don't clip inside the ground mthing->mobj = mobj; } -void P_SpawnHoopsAndRings(mapthing_t *mthing) +void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) { + mobjtype_t ringthing = MT_RING; mobj_t *mobj = NULL; INT32 r, i; fixed_t x, y, z, finalx, finaly, finalz; @@ -11034,59 +11047,26 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing) return; } - // Wing logo item. - else if (mthing->type == mobjinfo[MT_NIGHTSWING].doomednum) - { - z = -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); - - mthing->z = (INT16)(z>>FRACBITS); - - mobj = P_SpawnMobj(x, y, z, MT_NIGHTSWING); - mobj->spawnpoint = mthing; - - if (G_IsSpecialStage(gamemap) && useNightsSS) - P_SetMobjState(mobj, mobj->info->meleestate); - else if (maptol & TOL_XMAS) - P_SetMobjState(mobj, mobj->info->seestate); - - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - mobj->flags2 |= MF2_AMBUSH; - mthing->mobj = mobj; - } // All manners of rings and coins else if (mthing->type == mobjinfo[MT_RING].doomednum || mthing->type == mobjinfo[MT_COIN].doomednum || - mthing->type == mobjinfo[MT_REDTEAMRING].doomednum || mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum) + mthing->type == mobjinfo[MT_REDTEAMRING].doomednum || mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum || + mthing->type == mobjinfo[MT_BLUESPHERE].doomednum) { - mobjtype_t ringthing = MT_RING; - - // No rings in Ultimate! - if (ultimatemode && !(G_IsSpecialStage(gamemap) || maptol & TOL_NIGHTS)) - return; // Which ringthing to use - switch (mthing->type) - { - case 1800: - ringthing = MT_COIN; - break; - case 308: // No team rings in non-CTF - ringthing = (gametype == GT_CTF) ? MT_REDTEAMRING : MT_RING; - break; - case 309: // No team rings in non-CTF - ringthing = (gametype == GT_CTF) ? MT_BLUETEAMRING : MT_RING; - break; - default: - // Spawn rings as blue spheres in special stages, ala S3+K. - if (G_IsSpecialStage(gamemap) && useNightsSS) - ringthing = MT_BLUEBALL; - break; - } + if (mthing->type == mobjinfo[MT_COIN].doomednum) + ringthing = MT_COIN; + else if (mthing->type == mobjinfo[MT_REDTEAMRING].doomednum) // No team rings in non-CTF + ringthing = (gametype == GT_CTF) ? MT_REDTEAMRING : MT_RING; + else if (mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum) // Ditto + ringthing = (gametype == GT_CTF) ? MT_BLUETEAMRING : MT_RING; + else if (mthing->type == mobjinfo[MT_BLUESPHERE].doomednum) + ringthing = MT_BLUESPHERE; + + if ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) + ringthing = ((ringthing == MT_BLUESPHERE) ? MT_NIGHTSCHIP : MT_NIGHTSSTAR); + else if (ringthing != MT_BLUESPHERE && ultimatemode) + return; // No rings in Ultimate! // Set proper height if (mthing->options & MTF_OBJECTFLIP) @@ -11130,8 +11110,14 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing) } mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - mobj->flags2 |= MF2_AMBUSH; mthing->mobj = mobj; + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; + + if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) + P_SetMobjState(mobj, mobj->info->raisestate); + else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); } // *** // Special placement patterns @@ -11141,17 +11127,13 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing) else if (mthing->type == 600 || mthing->type == 601) { INT32 dist = 64*FRACUNIT; - mobjtype_t ringthing = MT_RING; if (mthing->type == 601) dist = 128*FRACUNIT; - // No rings in Ultimate! - if (ultimatemode && !(G_IsSpecialStage(gamemap) || maptol & TOL_NIGHTS)) - return; - - // Spawn rings as blue spheres in special stages, ala S3+K. - if (G_IsSpecialStage(gamemap) && useNightsSS) - ringthing = MT_BLUEBALL; + if ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) + ringthing = MT_NIGHTSSTAR; + else if (ultimatemode) + return; // No rings in Ultimate! for (r = 1; r <= 5; r++) { @@ -11187,31 +11169,30 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing) mobj->angle = FixedAngle(mthing->angle*FRACUNIT); if (mthing->options & MTF_AMBUSH) mobj->flags2 |= MF2_AMBUSH; + + if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); } } // Diagonal rings (handles both types) else if (mthing->type == 602 || mthing->type == 603) // Diagonal rings (5) { - angle_t angle = FixedAngle(mthing->angle*FRACUNIT); - mobjtype_t ringthing = MT_RING; INT32 iterations = 5; if (mthing->type == 603) iterations = 10; - // No rings in Ultimate! - if (ultimatemode && !(G_IsSpecialStage(gamemap) || maptol & TOL_NIGHTS)) - return; + if ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) + ringthing = MT_NIGHTSSTAR; + else if (ultimatemode) + return; // No rings in Ultimate! - // Spawn rings as blue spheres in special stages, ala S3+K. - if (G_IsSpecialStage(gamemap) && useNightsSS) - ringthing = MT_BLUEBALL; - - angle >>= ANGLETOFINESHIFT; + closestangle = FixedAngle(mthing->angle*FRACUNIT); + fa = (closestangle >> ANGLETOFINESHIFT); for (r = 1; r <= iterations; r++) { - x += FixedMul(64*FRACUNIT, FINECOSINE(angle)); - y += FixedMul(64*FRACUNIT, FINESINE(angle)); + x += FixedMul(64*FRACUNIT, FINECOSINE(fa)); + y += FixedMul(64*FRACUNIT, FINESINE(fa)); if (mthing->options & MTF_OBJECTFLIP) { @@ -11242,9 +11223,12 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing) mobj->flags2 |= MF2_OBJECTFLIP; } - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); + mobj->angle = closestangle; if (mthing->options & MTF_AMBUSH) mobj->flags2 |= MF2_AMBUSH; + + if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); } } // Rings of items (all six of them) @@ -11252,7 +11236,6 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing) { INT32 numitems = 8; INT32 size = 96*FRACUNIT; - mobjtype_t itemToSpawn = MT_NIGHTSWING; if (mthing->type & 1) { @@ -11277,30 +11260,24 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing) { case 604: case 605: - itemToSpawn = MT_RING; + ringthing = MT_BLUESPHERE; break; case 608: case 609: - itemToSpawn = (i & 1) ? MT_NIGHTSWING : MT_RING; + ringthing = (i & 1) ? MT_RING : MT_BLUESPHERE; break; case 606: case 607: - itemToSpawn = MT_NIGHTSWING; + ringthing = MT_RING; break; default: break; } - // No rings in Ultimate! - if (itemToSpawn == MT_RING) - { - if (ultimatemode && !(G_IsSpecialStage(gamemap) || (maptol & TOL_NIGHTS))) - continue; - - // Spawn rings as blue spheres in special stages, ala S3+K. - if (G_IsSpecialStage(gamemap) && useNightsSS) - itemToSpawn = MT_BLUEBALL; - } + if ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) + ringthing = ((ringthing == MT_BLUESPHERE) ? MT_NIGHTSCHIP : MT_NIGHTSSTAR); + else if (ringthing == MT_RING && ultimatemode) + continue; // No rings in Ultimate! fa = i*FINEANGLES/numitems; v[0] = FixedMul(FINECOSINE(fa),size); @@ -11315,16 +11292,23 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing) finaly = y + v[1]; finalz = z + v[2]; - mobj = P_SpawnMobj(finalx, finaly, finalz, itemToSpawn); + mobj = P_SpawnMobj(finalx, finaly, finalz, ringthing); mobj->z -= mobj->height/2; - if (itemToSpawn == MT_NIGHTSWING) + if (mthing->options & MTF_OBJECTFLIP) { - if (G_IsSpecialStage(gamemap) && useNightsSS) - P_SetMobjState(mobj, mobj->info->meleestate); - else if ((maptol & TOL_XMAS)) - P_SetMobjState(mobj, mobj->info->seestate); + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; } + + mobj->angle = closestangle; + if (mthing->options & MTF_AMBUSH) + mobj->flags2 |= MF2_AMBUSH; + + if (bonustime && (ringthing == MT_BLUESPHERE || ringthing == MT_NIGHTSCHIP)) + P_SetMobjState(mobj, mobj->info->raisestate); + else if ((maptol & TOL_XMAS) && (ringthing == MT_NIGHTSSTAR)) + P_SetMobjState(mobj, mobj->info->seestate); } return; } diff --git a/src/p_mobj.h b/src/p_mobj.h index 405dca77e..f7b2d8f36 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -314,7 +314,7 @@ typedef struct mobj_s mobjtype_t type; const mobjinfo_t *info; // &mobjinfo[mobj->type] - INT32 health; // for player this is rings + 1 + INT32 health; // for player this is rings + 1 -- no it isn't, not any more!! // Movement direction, movement generation (zig-zagging). angle_t movedir; // dirtype_t 0-7; also used by Deton for up/down angle @@ -435,7 +435,7 @@ void P_MovePlayerToStarpost(INT32 playernum); void P_AfterPlayerSpawn(INT32 playernum); void P_SpawnMapThing(mapthing_t *mthing); -void P_SpawnHoopsAndRings(mapthing_t *mthing); +void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime); void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle); void P_SpawnPrecipitation(void); void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, statenum_t nstate, angle_t rotangle, boolean spawncenter); diff --git a/src/p_saveg.c b/src/p_saveg.c index 029df08f4..2e47f2077 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -116,7 +116,8 @@ static void P_NetArchivePlayers(void) WRITEANGLE(save_p, players[i].drawangle); WRITEANGLE(save_p, players[i].awayviewaiming); WRITEINT32(save_p, players[i].awayviewtics); - WRITEINT32(save_p, players[i].rings); + WRITEINT16(save_p, players[i].rings); + WRITEINT16(save_p, players[i].spheres); WRITESINT8(save_p, players[i].pity); WRITEINT32(save_p, players[i].currentweapon); @@ -201,7 +202,7 @@ static void P_NetArchivePlayers(void) WRITEUINT32(save_p, players[i].marebegunat); WRITEUINT32(save_p, players[i].startedtime); WRITEUINT32(save_p, players[i].finishedtime); - WRITEINT16(save_p, players[i].finishedrings); + WRITEINT16(save_p, players[i].finishedspheres); WRITEUINT32(save_p, players[i].marescore); WRITEUINT32(save_p, players[i].lastmarescore); WRITEUINT8(save_p, players[i].lastmare); @@ -303,7 +304,8 @@ static void P_NetUnArchivePlayers(void) players[i].drawangle = READANGLE(save_p); players[i].awayviewaiming = READANGLE(save_p); players[i].awayviewtics = READINT32(save_p); - players[i].rings = READINT32(save_p); + players[i].rings = READINT16(save_p); + players[i].spheres = READINT16(save_p); players[i].pity = READSINT8(save_p); players[i].currentweapon = READINT32(save_p); @@ -388,7 +390,7 @@ static void P_NetUnArchivePlayers(void) players[i].marebegunat = READUINT32(save_p); players[i].startedtime = READUINT32(save_p); players[i].finishedtime = READUINT32(save_p); - players[i].finishedrings = READINT16(save_p); + players[i].finishedspheres = READINT16(save_p); players[i].marescore = READUINT32(save_p); players[i].lastmarescore = READUINT32(save_p); players[i].lastmare = READUINT8(save_p); @@ -1986,7 +1988,7 @@ static void LoadMobjThinker(actionf_p1 thinker) if (mapthings[spawnpointnum].type == 1705 || mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case { - P_SpawnHoopsAndRings(&mapthings[spawnpointnum]); + P_SpawnHoopsAndRings(&mapthings[spawnpointnum], false); return; } @@ -3261,7 +3263,7 @@ static void P_NetArchiveMisc(void) WRITEUINT32(save_p, tokenlist); WRITEUINT32(save_p, leveltime); - WRITEUINT32(save_p, totalrings); + WRITEUINT32(save_p, ssspheres); WRITEINT16(save_p, lastmap); WRITEUINT16(save_p, emeralds); @@ -3338,7 +3340,7 @@ static inline boolean P_NetUnArchiveMisc(void) // get the time leveltime = READUINT32(save_p); - totalrings = READUINT32(save_p); + ssspheres = READUINT32(save_p); lastmap = READINT16(save_p); emeralds = READUINT16(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index a9fc57652..076c8dba7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -808,7 +808,7 @@ void P_ReloadRings(void) mapthing_t *hoopsToRespawn[4096]; mapthing_t *mt = mapthings; - // scan the thinkers to find rings/wings/hoops to unset + // scan the thinkers to find rings/spheres/hoops to unset for (th = thinkercap.next; th != &thinkercap; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) @@ -826,7 +826,8 @@ void P_ReloadRings(void) } continue; } - if (!(mo->type == MT_RING || mo->type == MT_NIGHTSWING || mo->type == MT_COIN || mo->type == MT_BLUEBALL)) + if (!(mo->type == MT_RING || mo->type == MT_COIN || mo->type == MT_BLUESPHERE + || mo->type == MT_NIGHTSCHIP || mo->type == MT_NIGHTSSTAR)) continue; // Don't auto-disintegrate things being pulled to us @@ -840,9 +841,9 @@ void P_ReloadRings(void) for (i = 0; i < nummapthings; i++, mt++) { // Notice an omission? We handle hoops differently. - if (mt->type == 300 || mt->type == 308 || mt->type == 309 - || mt->type == 1706 || (mt->type >= 600 && mt->type <= 609) - || mt->type == 1800) + if (mt->type == mobjinfo[MT_RING].doomednum || mt->type == mobjinfo[MT_REDTEAMRING].doomednum || mt->type == mobjinfo[MT_BLUETEAMRING].doomednum + || mt->type == mobjinfo[MT_BLUESPHERE].doomednum || mt->type == mobjinfo[MT_COIN].doomednum + || (mt->type >= 600 && mt->type <= 609)) // circles { mt->mobj = NULL; @@ -850,12 +851,35 @@ void P_ReloadRings(void) mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS) ->sector->floorheight>>FRACBITS); - P_SpawnHoopsAndRings (mt); + P_SpawnHoopsAndRings(mt, true); } } 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; + + // scan the thinkers to find spheres to switch + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo = (mobj_t *)th; + + if (mo->type != MT_BLUESPHERE && mo->type != MT_NIGHTSCHIP) + continue; + + if (!mo->health) + continue; + + P_SetMobjState(mo, ((bonustime) ? mo->info->raisestate : mo->info->spawnstate)); } } @@ -1025,20 +1049,22 @@ static void P_LoadThings(void) } //decrement spawn values to the actual number because zero is valid. - if (emer1) - P_SpawnMobj(huntemeralds[emer1 - 1]->x<y<z<x<y<z<x<y<z<x<y<z<x<y<z<x<y<z<z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS) ->sector->floorheight>>FRACBITS); - P_SpawnHoopsAndRings (mt); + P_SpawnHoopsAndRings(mt, false); } } } @@ -2298,7 +2324,7 @@ static void P_LevelInitStuff(void) // circuit, race and competition stuff circuitmap = false; numstarposts = 0; - totalrings = timeinmap = 0; + ssspheres = timeinmap = 0; // special stage stagefailed = false; @@ -2334,6 +2360,7 @@ static void P_LevelInitStuff(void) players[i].xtralife = players[i].deadtimer = players[i].numboxes = players[i].totalring = players[i].laps = 0; players[i].rings = 0; + players[i].spheres = 0; players[i].aiming = 0; players[i].pflags &= ~PF_GAMETYPEOVER; @@ -2341,7 +2368,7 @@ static void P_LevelInitStuff(void) 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].startedtime = players[i].finishedtime = players[i].finishedspheres = 0; players[i].lastmare = players[i].marebegunat = 0; // Don't show anything diff --git a/src/p_setup.h b/src/p_setup.h index a42ac5b76..569501531 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -72,6 +72,7 @@ void P_DeleteFlickies(INT16 i); // Needed for NiGHTS void P_ReloadRings(void); +void P_SwitchSpheresBonusMode(boolean bonustime); void P_DeleteGrades(INT16 i); void P_AddGradesForMare(INT16 i, UINT8 mare, char *gtext); UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare); diff --git a/src/p_spec.c b/src/p_spec.c index e77a783e9..2999d94ac 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2868,7 +2868,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) // Unlocked something? if (M_UpdateUnlockablesAndExtraEmblems()) { - S_StartSound(NULL, sfx_ncitem); + S_StartSound(NULL, sfx_s3k68); G_SaveGameData(); // only save if unlocked something } } @@ -3527,7 +3527,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers if (player->exiting || player->bot) // Don't do anything for bots or players who have just finished break; - if (!(player->powers[pw_shield] || player->rings > 0)) // Don't do anything if no shield or rings anyway + if (!(player->powers[pw_shield] || player->spheres > 0)) // Don't do anything if no shield or spheres anyway break; P_SpecialStageDamage(player, NULL, NULL); @@ -3775,8 +3775,8 @@ DoneSection2: case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return if (player->bot) break; - if (!useNightsSS && G_IsSpecialStage(gamemap) && sstimer > 6) - sstimer = 6; // Just let P_Ticker take care of the rest. + if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6) + player->nightstime = 6; // Just let P_Ticker take care of the rest. // Exit (for FOF exits; others are handled in P_PlayerThink in p_user.c) { @@ -4643,7 +4643,7 @@ static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector) switch(GETSECSPECIAL(sector->special, 4)) { case 2: // Level Exit / GOAL Sector / Flag Return - if (!useNightsSS && G_IsSpecialStage(gamemap)) + if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap)) { // Special stage GOAL sector // requires touching floor. @@ -5502,7 +5502,7 @@ void P_InitSpecials(void) // Defaults in case levels don't have them set. sstimer = 90*TICRATE + 6; - totalrings = 1; + ssspheres = 1; CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false; @@ -5596,7 +5596,7 @@ void P_SpawnSpecials(INT32 fromnetsave) { case 10: // Time for special stage sstimer = (sector->floorheight>>FRACBITS) * TICRATE + 6; // Time to finish - totalrings = sector->ceilingheight>>FRACBITS; // Ring count for special stage + ssspheres = sector->ceilingheight>>FRACBITS; // Ring count for special stage break; case 11: // Custom global gravity! diff --git a/src/p_tick.c b/src/p_tick.c index 658b1e4ea..483b161a4 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -424,7 +424,7 @@ void P_DoTeamscrambling(void) static inline void P_DoSpecialStageStuff(void) { - boolean inwater = false; + boolean stillalive = false; INT32 i; // Can't drown in a special stage @@ -436,68 +436,59 @@ static inline void P_DoSpecialStageStuff(void) players[i].powers[pw_underwater] = players[i].powers[pw_spacetime] = 0; } - if (sstimer < 15*TICRATE+6 && sstimer > 7 && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)) - S_SpeedMusic(1.4f); + //if (sstimer < 15*TICRATE+6 && sstimer > 7 && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)) + //S_SpeedMusic(1.4f); - if (sstimer < 7 && sstimer > 0) // The special stage time is up! + if (sstimer && !objectplacing) { - sstimer = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - players[i].exiting = (14*TICRATE)/5 + 1; - players[i].pflags &= ~PF_GLIDING; - } - - if (i == consoleplayer) - S_StartSound(NULL, sfx_lose); - } - - if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC) - S_SpeedMusic(1.0f); - - stagefailed = true; - } - - if (sstimer > 1) // As long as time isn't up... - { - UINT32 ssrings = 0; + UINT16 countspheres = 0; // Count up the rings of all the players and see if // they've collected the required amount. for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) { - ssrings += players[i].rings; + tic_t oldnightstime = players[i].nightstime; + countspheres += players[i].spheres; // If in water, deplete timer 6x as fast. - if ((players[i].mo->eflags & MFE_TOUCHWATER) - || (players[i].mo->eflags & MFE_UNDERWATER)) - inwater = true; + if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) + players[i].nightstime -= 5; + if (--players[i].nightstime > 6) + { + if (P_IsLocalPlayer(&players[i]) && oldnightstime > 10*TICRATE && players[i].nightstime <= 10*TICRATE) + S_ChangeMusicInternal("_drown", false); + stillalive = true; + } + else if (!players[i].exiting) + { + players[i].exiting = (14*TICRATE)/5 + 1; + players[i].pflags &= ~(PF_GLIDING|PF_BOUNCING); + players[i].nightstime = 0; + if (P_IsLocalPlayer(&players[i])) + S_StartSound(NULL, sfx_s3k66); + } } - if (ssrings >= totalrings && totalrings > 0) + if (stillalive) { - // Halt all the players - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - { - players[i].mo->momx = players[i].mo->momy = 0; - players[i].exiting = (14*TICRATE)/5 + 1; - } + if (countspheres >= ssspheres) + { + // Halt all the players + for (i = 0; i < MAXPLAYERS; i++) + if (playeringame[i]) + { + players[i].mo->momx = players[i].mo->momy = 0; + players[i].exiting = (14*TICRATE)/5 + 1; + } - sstimer = 0; - - P_GiveEmerald(true); + sstimer = 0; + P_GiveEmerald(true); + } } - - // Decrement the timer - if (!objectplacing) + else { - if (inwater) - sstimer -= 6; - else - sstimer--; + sstimer = 0; + stagefailed = true; } } } @@ -608,7 +599,7 @@ void P_Ticker(boolean run) // Keep track of how long they've been playing! totalplaytime++; - if (!useNightsSS && G_IsSpecialStage(gamemap)) + if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap)) P_DoSpecialStageStuff(); if (runemeraldmanager) diff --git a/src/p_user.c b/src/p_user.c index a28c8f445..8d05d2b01 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -283,22 +283,9 @@ boolean P_PlayerMoving(INT32 pnum) // UINT8 P_GetNextEmerald(void) { - if (!useNightsSS) // In order - { - if (!(emeralds & EMERALD1)) return 0; - if (!(emeralds & EMERALD2)) return 1; - if (!(emeralds & EMERALD3)) return 2; - if (!(emeralds & EMERALD4)) return 3; - if (!(emeralds & EMERALD5)) return 4; - if (!(emeralds & EMERALD6)) return 5; - return 6; - } - else // Depends on stage - { - if (gamemap < sstage_start || gamemap > sstage_end) - return 0; - return (UINT8)(gamemap - sstage_start); - } + if (gamemap < sstage_start || gamemap > sstage_end) + return 0; + return (UINT8)(gamemap - sstage_start); } // @@ -309,20 +296,20 @@ UINT8 P_GetNextEmerald(void) // void P_GiveEmerald(boolean spawnObj) { - INT32 i; - UINT8 em; + UINT8 em = P_GetNextEmerald(); S_StartSound(NULL, sfx_cgot); // Got the emerald! - em = P_GetNextEmerald(); emeralds |= (1 << em); - if (spawnObj) + if (spawnObj && playeringame[consoleplayer]) { - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - P_SetMobjState(P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z + players[i].mo->info->height, MT_GOTEMERALD), - mobjinfo[MT_GOTEMERALD].spawnstate + em); - + // The Chaos Emerald begins to orbit us! + UINT8 em = P_GetNextEmerald(); + // Only give it to ONE person! + mobj_t *emmo = P_SpawnMobjFromMobj(players[consoleplayer].mo, 0, 0, players[consoleplayer].mo->height, MT_GOTEMERALD); + P_SetTarget(&emmo->target, players[consoleplayer].mo); + P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); + P_SetTarget(&players[consoleplayer].mo->tracer, emmo); } } @@ -692,10 +679,10 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) oldmare = player->mare; - if (P_TransferToNextMare(player) == false) + if (!P_TransferToNextMare(player)) { INT32 i; - INT32 total_rings = 0; + INT32 total_spheres = 0; P_SetTarget(&player->mo->target, NULL); @@ -703,7 +690,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) { for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]/* && players[i].powers[pw_carry] == CR_NIGHTSMODE*/) - total_rings += players[i].rings; + total_spheres += players[i].spheres; } for (i = 0; i < MAXPLAYERS; i++) @@ -716,13 +703,13 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) players[i].lastmare = players[i].mare; if (G_IsSpecialStage(gamemap)) { - players[i].finishedrings = (INT16)total_rings; - P_AddPlayerScore(player, total_rings * 50); + players[i].finishedspheres = (INT16)total_spheres; + P_AddPlayerScore(player, total_spheres * 50); } else { - players[i].finishedrings = (INT16)(players[i].rings); - P_AddPlayerScore(&players[i], (players[i].rings) * 50); + players[i].finishedspheres = (INT16)(players[i].spheres); + P_AddPlayerScore(&players[i], (players[i].spheres) * 50); } // Add score to leaderboards now @@ -733,20 +720,20 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) players[i].lastmarescore = players[i].marescore; players[i].marescore = 0; - players[i].rings = 0; + players[i].spheres = 0; P_DoPlayerExit(&players[i]); } } else if (oldmare != player->mare) { /// \todo Handle multi-mare special stages. - // Ring bonus - P_AddPlayerScore(player, (player->rings) * 50); + // Spheres bonus + P_AddPlayerScore(player, (player->spheres) * 50); player->lastmare = (UINT8)oldmare; player->texttimer = 4*TICRATE; player->textvar = 4; // Score and grades - player->finishedrings = (INT16)(player->rings); + player->finishedspheres = (INT16)(player->spheres); // Add score to temp leaderboards if (!(netgame||multiplayer) && P_IsLocalPlayer(player)) @@ -757,7 +744,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->marescore = 0; player->marebegunat = leveltime; - player->rings = 0; + player->spheres = 0; } else { @@ -857,7 +844,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) } else { - ang = R_PointToAngle2(player->mo->momx, player->mo->momy, 0, 0); + ang = ((player->mo->momx || player->mo->momy) ? R_PointToAngle2(player->mo->momx, player->mo->momy, 0, 0) : player->drawangle); fallbackspeed = FixedMul(4*FRACUNIT, player->mo->scale); } @@ -923,8 +910,7 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings) player->rings += num_rings; - if (!G_IsSpecialStage(gamemap) || !useNightsSS) - player->totalring += num_rings; + player->totalring += num_rings; // Can only get up to 9999 rings, sorry! if (player->rings > 9999) @@ -956,6 +942,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 // @@ -1035,10 +1041,11 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi + player->mo->momx = player->mo->momy = player->mo->momz = player->cmomx = player->cmomy = player->rmomx = player->rmomy = 0; + // Transformation animation P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_TRANS1); - player->mo->momx = player->mo->momy = player->mo->momz = 0; player->pflags |= PF_NOJUMPDAMAGE; // just to avoid recurling but still allow thok if (giverings) @@ -3793,12 +3800,15 @@ static void P_DoSuperStuff(player_t *player) // boolean P_SuperReady(player_t *player) { - if ((ALL7EMERALDS(emeralds) && player->rings >= 50) && !player->powers[pw_super] && !player->powers[pw_tailsfly] - && !(player->powers[pw_shield] & SH_NOSTACK) + if (!player->powers[pw_super] && !player->powers[pw_invulnerability] - && !(maptol & TOL_NIGHTS || (player->powers[pw_carry] == CR_NIGHTSMODE)) // don't turn 'regular super' in nights levels - && player->pflags & PF_JUMPED - && player->charflags & SF_SUPER) + && !player->powers[pw_tailsfly] + && (player->charflags & SF_SUPER) + && (player->pflags & PF_JUMPED) + && !(player->powers[pw_shield] & SH_NOSTACK) + && !(maptol & TOL_NIGHTS) + && ALL7EMERALDS(emeralds) + && (player->rings >= 50)) return true; return false; @@ -4484,12 +4494,12 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } else if (player->pflags & PF_SLIDING || (gametype == GT_CTF && player->gotflag)) ; - else if (P_SuperReady(player)) + /*else if (P_SuperReady(player)) { // If you can turn super and aren't already, // and you don't have a shield, do it! P_DoSuperTransformation(player, false); - } + }*/ else if (player->pflags & PF_JUMPED) { #ifdef HAVE_BLUA @@ -5953,10 +5963,10 @@ static void P_DoNiGHTSCapsule(player_t *player) if (G_IsSpecialStage(gamemap)) { // In special stages, share rings. Everyone gives up theirs to the capsule player always, because we can't have any individualism here! for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && (&players[i] != player) && players[i].rings > 0) + if (playeringame[i] && (&players[i] != player) && players[i].spheres > 0) { - player->rings += players[i].rings; - players[i].rings = 0; + player->spheres += players[i].spheres; + players[i].spheres = 0; } } @@ -5965,9 +5975,9 @@ static void P_DoNiGHTSCapsule(player_t *player) && player->mo->y == player->capsule->y && player->mo->z == player->capsule->z+(player->capsule->height/3)) { - if (player->rings > 0) + if (player->spheres > 0) { - player->rings--; + player->spheres--; player->capsule->health--; player->capsule->extravalue1++; @@ -5999,9 +6009,6 @@ static void P_DoNiGHTSCapsule(player_t *player) if (G_IsSpecialStage(gamemap)) { - // The Chaos Emerald begins to orbit us! - mobj_t *emmo; - UINT8 em = P_GetNextEmerald(); tic_t lowest_time; /*for (i = 0; i < MAXPLAYERS; i++) @@ -6016,8 +6023,10 @@ static void P_DoNiGHTSCapsule(player_t *player) if (player->powers[pw_carry] == CR_NIGHTSMODE) { + // The Chaos Emerald begins to orbit us! + UINT8 em = P_GetNextEmerald(); // Only give it to ONE person, and THAT player has to get to the goal! - emmo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->info->height, MT_GOTEMERALD); + mobj_t *emmo = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height, MT_GOTEMERALD); P_SetTarget(&emmo->target, player->mo); P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); P_SetTarget(&player->mo->tracer, emmo); @@ -6035,18 +6044,24 @@ static void P_DoNiGHTSCapsule(player_t *player) } else { - for (i = 0; i < 16; i++) + /*for (i = 0; i < 16; i++) { mobj_t *flicky = P_InternalFlickySpawn(player->capsule, 0, ((i%4) + 1)*2*FRACUNIT, true); flicky->z += player->capsule->height/2; flicky->angle = (i*(ANGLE_MAX/16)); P_InstaThrust(flicky, flicky->angle, 8*FRACUNIT); - } + }*/ + mobj_t *idya = P_SpawnMobjFromMobj(player->mo, 0, 0, player->mo->height, MT_GOTEMERALD); + idya->extravalue2 = player->mare/5; + P_SetTarget(&idya->target, player->mo); + P_SetMobjState(idya, mobjinfo[MT_GOTEMERALD].missilestate + ((player->mare + 1) % 5)); + P_SetTarget(&player->mo->tracer, idya); } for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mare == player->mare) P_SetTarget(&players[i].capsule, NULL); // Remove capsule from everyone now that it is dead! S_StartScreamSound(player->mo, sfx_ngdone); + P_SwitchSpheresBonusMode(true); } } else @@ -6139,7 +6154,7 @@ static void P_NiGHTSMovement(player_t *player) } else if (P_IsLocalPlayer(player) && player->nightstime == 10*TICRATE) // S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH - S_ChangeMusicInternal("_drown",false); + S_ChangeMusicInternal((((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? "_ntime" : "_drown"), false); if (player->mo->z < player->mo->floorz) @@ -7477,7 +7492,7 @@ static void P_MovePlayer(player_t *player) #endif { if (!(player->pflags & (PF_USEDOWN|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player is not holding down BT_USE, or having used an ability previously - && (!(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX))) // thokked is optional if you're bubblewrapped + && (!(player->powers[pw_shield] & SH_NOSTACK) || !(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX))) // thokked is optional if you're bubblewrapped/turning super { // Force shield activation if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) @@ -7490,6 +7505,11 @@ static void P_MovePlayer(player_t *player) { switch (player->powers[pw_shield] & SH_NOSTACK) { + // Super! + case SH_NONE: + if (P_SuperReady(player)) + P_DoSuperTransformation(player, false); + break; // Whirlwind/Thundercoin shield activation case SH_WHIRLWIND: case SH_THUNDERCOIN: @@ -9563,11 +9583,8 @@ void P_PlayerThink(player_t *player) // If 11 seconds are left on the timer, // begin the drown music for countdown! - if (countdown == 11*TICRATE - 1) - { - if (P_IsLocalPlayer(player)) - S_ChangeMusicInternal("_drown", false); - } + if (countdown == 11*TICRATE - 1 && P_IsLocalPlayer(player)) + S_ChangeMusicInternal("_drown", false); // If you've hit the countdown and you haven't made // it to the exit, you're a goner! @@ -9667,7 +9684,7 @@ void P_PlayerThink(player_t *player) if (gametype != GT_COOP) player->score = 0; player->mo->health = 1; - player->rings = 0; + player->rings = player->spheres = 0; } else if ((netgame || multiplayer) && player->lives <= 0 && gametype != GT_COOP) { @@ -9720,8 +9737,8 @@ void P_PlayerThink(player_t *player) mo2 = (mobj_t *)th; - if (!(mo2->type == MT_NIGHTSWING || mo2->type == MT_RING || mo2->type == MT_COIN - || mo2->type == MT_BLUEBALL)) + if (!(mo2->type == MT_RING || mo2->type == MT_COIN || mo2->type == MT_BLUESPHERE + || mo2->type == MT_NIGHTSCHIP || mo2->type == MT_NIGHTSSTAR)) continue; if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > FixedMul(128*FRACUNIT, player->mo->scale)) @@ -10210,7 +10227,7 @@ void P_PlayerAfterThink(player_t *player) if (player->followmobj) { P_RemoveMobj(player->followmobj); - player->followmobj = NULL; + P_SetTarget(&player->followmobj, NULL); } return; } @@ -10495,14 +10512,14 @@ void P_PlayerAfterThink(player_t *player) if (player->followmobj && (player->spectator || player->mo->health <= 0 || player->followmobj->type != player->followitem)) { P_RemoveMobj(player->followmobj); - player->followmobj = NULL; + P_SetTarget(&player->followmobj, NULL); } if (!player->spectator && player->mo->health && player->followitem) { if (!player->followmobj || P_MobjWasRemoved(player->followmobj)) { - player->followmobj = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, player->followitem); + P_SetTarget(&player->followmobj, P_SpawnMobjFromMobj(player->mo, 0, 0, 0, player->followitem)); P_SetTarget(&player->followmobj->tracer, player->mo); player->followmobj->flags2 |= MF2_LINKDRAW; } diff --git a/src/r_things.c b/src/r_things.c index b0cb3ab8e..9e858aba9 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2673,7 +2673,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) if (player->followmobj) { P_RemoveMobj(player->followmobj); - player->followmobj = NULL; + P_SetTarget(&player->followmobj, NULL); } if (player->mo) diff --git a/src/screen.c b/src/screen.c index cd97b62fa..9bbcb995c 100644 --- a/src/screen.c +++ b/src/screen.c @@ -446,10 +446,11 @@ void SCR_ClosedCaptions(void) { if (splitscreen) basey -= 8; - else if (((maptol & TOL_NIGHTS) && (modeattacking == ATTACKING_NIGHTS)) - || (cv_powerupdisplay.value == 2) + else if ((modeattacking == ATTACKING_NIGHTS) + || (!(maptol & TOL_NIGHTS) + && ((cv_powerupdisplay.value == 2) || (cv_powerupdisplay.value == 1 && ((stplyr == &players[displayplayer] && !camera.chase) - || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase)))) + || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase)))))) basey -= 16; } diff --git a/src/sounds.c b/src/sounds.c index d3a0ac373..4070839ab 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -141,7 +141,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"bnce1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"}, // Boing! {"bnce2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Scatter"}, // Boing! {"cannon", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful shot"}, - {"cgot" , true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Chaos Emerald"}, // Got Emerald! Tails 09-02-2001 + {"cgot" , true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Emerald"}, // Got Emerald! Tails 09-02-2001 {"cybdth", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Explosion"}, {"deton", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous beeping"}, {"ding", false, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Ding"}, @@ -214,11 +214,12 @@ sfxinfo_t S_sfx[NUMSFX] = {"xideya", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Success"}, // Xmas {"nbmper", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, {"nxbump", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, // Xmas + {"ncchip", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got chip"}, {"ncitem", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got special"}, {"nxitem", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got special"}, // Xmas {"ngdone", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bonus time start"}, {"nxdone", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bonus time start"}, // Xmas - {"drill1", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drill start"}, + {"drill1", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drill"}, {"drill2", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drill"}, {"ncspec", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power-up"}, // Tails 12-15-2003 {"nghurt", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hurt"}, @@ -228,12 +229,13 @@ sfxinfo_t S_sfx[NUMSFX] = {"hoop3", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hoop++"}, {"hidden", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"}, {"prloop", false, 104, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Gust of wind"}, - {"timeup", true, 256, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous Countdown"}, + {"ngjump", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"}, + {"peww", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pew"}, // Halloween {"lntsit", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cacolantern awake"}, {"lntdie", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cacolantern death"}, - {"pumpkn", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pumpkin smash"}, + {"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 @@ -334,10 +336,10 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"}, {"s3k63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"}, {"s3k64", false, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Clatter"}, - {"s3k65", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got blue sphere"}, // Blue Spheres + {"s3k65", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got sphere"}, // Blue Spheres {"s3k66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Special stage end"}, {"s3k67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing missile"}, - {"s3k68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Unknown possibilities"}, + {"s3k68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"}, {"s3k69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Switch click"}, {"s3k6a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Special stage clear"}, {"s3k6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Punch"}, diff --git a/src/sounds.h b/src/sounds.h index 56189f55f..5fffc7b2e 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -280,6 +280,7 @@ typedef enum sfx_xideya, // Xmas sfx_nbmper, sfx_nxbump, // Xmas + sfx_ncchip, sfx_ncitem, sfx_nxitem, // Xmas sfx_ngdone, @@ -294,7 +295,8 @@ typedef enum sfx_hoop3, sfx_hidden, sfx_prloop, - sfx_timeup, // Was gonna be played when less than ten seconds are on the clock; uncomment uses of this to see it in-context + sfx_ngjump, + sfx_peww, // Halloween sfx_lntsit, diff --git a/src/st_stuff.c b/src/st_stuff.c index a513a028c..031aa61db 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -112,6 +112,8 @@ static patch_t *yelstat; static patch_t *nbracket; static patch_t *nhud[12]; static patch_t *nsshud; +static patch_t *nbon[12]; +static patch_t *nssbon; static patch_t *narrow[9]; static patch_t *nredar[8]; // Red arrow static patch_t *drillbar; @@ -309,8 +311,12 @@ void ST_LoadGraphics(void) yelstat = W_CachePatchName("YELSTAT", PU_HUDGFX); nbracket = W_CachePatchName("NBRACKET", PU_HUDGFX); for (i = 0; i < 12; ++i) + { nhud[i] = W_CachePatchName(va("NHUD%d", i+1), PU_HUDGFX); + nbon[i] = W_CachePatchName(va("NBON%d", i+1), PU_HUDGFX); + } nsshud = W_CachePatchName("NSSHUD", PU_HUDGFX); + nssbon = W_CachePatchName("NSSBON", PU_HUDGFX); minicaps = W_CachePatchName("MINICAPS", PU_HUDGFX); for (i = 0; i < 8; ++i) @@ -735,18 +741,7 @@ static inline void ST_drawRings(void) ST_DrawPatchFromHud(HUD_RINGS, ((!stplyr->spectator && stplyr->rings <= 0 && leveltime/5 & 1) ? sboredrings : sborings), ((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS)); - if (objectplacing) - ringnum = op_currentdoomednum; - else if (!useNightsSS && G_IsSpecialStage(gamemap)) - { - INT32 i; - ringnum = 0; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && players[i].rings > 0) - ringnum += players[i].rings; - } - else - ringnum = max(stplyr->rings, 0); + ringnum = ((objectplacing) ? op_currentdoomednum : max(stplyr->rings, 0)); if (cv_timetic.value == 2) // Yes, even in modeattacking ST_DrawNumFromHud(HUD_RINGSNUMTICS, ringnum, V_PERPLAYER|((stplyr->spectator) ? V_HUDTRANSHALF : V_HUDTRANS)); @@ -1394,17 +1389,17 @@ static void ST_drawNightsRecords(void) V_DrawCenteredString(BASEVIDWIDTH/2, 60, aflag, va(M_GetText("\x80GET\x82 %d\x80 %s%s%s!"), stplyr->capsule->health, (stplyr->textvar == 3) ? M_GetText("MORE ") : "", - (G_IsSpecialStage(gamemap)) ? "SPHERE" : "RING", + (G_IsSpecialStage(gamemap)) ? "SPHERE" : "CHIP", (stplyr->capsule->health > 1) ? "S" : "")); } // End Bonus else if (stplyr->textvar == 4) { - V_DrawString(BASEVIDWIDTH/2 - 56, 140, aflag, (G_IsSpecialStage(gamemap)) ? "SPHERES:" : "RINGS:"); + V_DrawString(BASEVIDWIDTH/2 - 56, 140, aflag, (G_IsSpecialStage(gamemap)) ? "SPHERES:" : "CHIPS:"); V_DrawString(BASEVIDWIDTH/2 - 56, 148, aflag, "BONUS:"); - V_DrawRightAlignedString(BASEVIDWIDTH/2 + 56, 140, V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings)); - V_DrawRightAlignedString(BASEVIDWIDTH/2 + 56, 140, V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings * 50)); + V_DrawRightAlignedString(BASEVIDWIDTH/2 + 56, 140, V_ORANGEMAP|aflag, va("%d", stplyr->finishedspheres)); + V_DrawRightAlignedString(BASEVIDWIDTH/2 + 56, 148, V_ORANGEMAP|aflag, va("%d", stplyr->finishedspheres * 50)); ST_DrawNightsOverlayNum((BASEVIDWIDTH/2 + 56)<lastmarescore, nightsnum, SKINCOLOR_AZURE); // If new record, say so! @@ -1462,15 +1457,15 @@ static void ST_drawNiGHTSHUD(void) { INT32 origamount; INT32 minlink = 1; - INT32 total_ringcount; - - // When debugging, show "0 Link". - if (cv_debug & DBG_NIGHTSBASIC) - minlink = 0; + INT32 total_spherecount; + const boolean oldspecialstage = (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)); // Cheap hack: don't display when the score is showing (it popping up for a split second when exiting a map is intentional) - if (stplyr->texttimer && stplyr->textvar == 4) + if (oldspecialstage || (stplyr->texttimer && stplyr->textvar == 4)) minlink = INT32_MAX; + // When debugging, show "0 Link". + else if (cv_debug & DBG_NIGHTSBASIC) + minlink = 0; // Drill meter if ( @@ -1576,25 +1571,35 @@ static void ST_drawNiGHTSHUD(void) // Begin drawing brackets/chip display #ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_nightsrings)) + if (LUA_HudEnabled(hud_nightsspheres)) { #endif ST_DrawTopLeftOverlayPatch(16, 8, nbracket); if (G_IsSpecialStage(gamemap)) - ST_DrawTopLeftOverlayPatch(24, 16, nsshud); + ST_DrawTopLeftOverlayPatch(24, 16, ((stplyr->bonustime && (leveltime & 4)) ? nssbon : nsshud)); + else if (stplyr->bonustime) + ST_DrawTopLeftOverlayPatch(24, 16, nbon[(leveltime/2)%12]); else ST_DrawTopLeftOverlayPatch(24, 16, nhud[(leveltime/2)%12]); if (G_IsSpecialStage(gamemap)) { INT32 i; - total_ringcount = 0; + total_spherecount = 0; for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/ && players[i].rings) - total_ringcount += players[i].rings; + if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/ && players[i].spheres) + total_spherecount += players[i].spheres; } else - total_ringcount = stplyr->rings; + total_spherecount = stplyr->spheres; + + /*if (oldspecialstage) + { + if (total_spherecount < ssspheres) + total_spherecount = ssspheres - total_spherecount; + else + total_spherecount = 0; + }*/ if (stplyr->capsule) { @@ -1650,28 +1655,48 @@ static void ST_drawNiGHTSHUD(void) amount = (origamount - stplyr->capsule->health); amount = (amount * length)/origamount; - for (cfill = 0; cfill < amount && cfill < 88; ++cfill) + for (cfill = 0; cfill < amount && cfill < length; ++cfill) V_DrawScaledPatch(15 + cfill + 1, 8 + 35, V_PERPLAYER|V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulefill); } - if (total_ringcount >= stplyr->capsule->health) - ST_DrawTopLeftOverlayPatch(40, 8 + 5, nredar[leveltime%8]); + if (total_spherecount >= stplyr->capsule->health) + ST_DrawTopLeftOverlayPatch(40, 8 + 5, nredar[leveltime&7]); else - ST_DrawTopLeftOverlayPatch(40, 8 + 5, narrow[(leveltime/2)%8]); + ST_DrawTopLeftOverlayPatch(40, 8 + 5, narrow[(leveltime/2)&7]); + } + else if (oldspecialstage && total_spherecount < ssspheres) + { + INT32 cfill, amount; + const INT32 length = 88; + UINT8 em = P_GetNextEmerald(); + ST_DrawTopLeftOverlayPatch(72, 8, nbracket); + + if (em <= 7) + ST_DrawTopLeftOverlayPatch(80, 8 + 8, emeraldpics[0][em]); + + ST_DrawTopLeftOverlayPatch(40, 8 + 5, narrow[(leveltime/2)&7]); + + // Lil' white box! + V_DrawScaledPatch(15, 8 + 34, V_PERPLAYER|V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulebar); + + amount = (total_spherecount * length)/ssspheres; + + for (cfill = 0; cfill < amount && cfill < length; ++cfill) + V_DrawScaledPatch(15 + cfill + 1, 8 + 35, V_PERPLAYER|V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulefill); } else ST_DrawTopLeftOverlayPatch(40, 8 + 5, narrow[8]); - if (total_ringcount >= 100) - V_DrawTallNum((total_ringcount >= 1000) ? 76 : 72, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_ringcount); + if (total_spherecount >= 100) + V_DrawTallNum((total_spherecount >= 1000) ? 76 : 72, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_spherecount); else - V_DrawTallNum(68, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_ringcount); + V_DrawTallNum(68, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_spherecount); #ifdef HAVE_BLUA } #endif // Score - if (!stplyr->exiting + if (!stplyr->exiting && !oldspecialstage #ifdef HAVE_BLUA && LUA_HudEnabled(hud_nightsscore) #endif @@ -1714,6 +1739,7 @@ static void ST_drawNiGHTSHUD(void) { INT32 realnightstime = stplyr->nightstime/TICRATE; INT32 numbersize; + UINT8 col = ((realnightstime < 10) ? SKINCOLOR_RED : SKINCOLOR_SUPERGOLD4); if (G_IsSpecialStage(gamemap)) { @@ -1744,46 +1770,66 @@ static void ST_drawNiGHTSHUD(void) else numbersize = 48/2; - ST_DrawNightsOverlayNum((160 + numbersize)<mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))) + col = SKINCOLOR_ORANGE; + + ST_DrawNightsOverlayNum((160 + numbersize)<nightstime))); } - // Show pickup durations - if (cv_debug & DBG_NIGHTSBASIC) + if (oldspecialstage) { - UINT16 pwr; - - if (stplyr->powers[pw_nights_superloop]) + if (leveltime < 5*TICRATE) { - pwr = stplyr->powers[pw_nights_superloop]; - V_DrawSmallScaledPatch(110, 44, 0, W_CachePatchName("NPRUA0",PU_CACHE)); - V_DrawThinString(106, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); - } - - if (stplyr->powers[pw_nights_helper]) - { - pwr = stplyr->powers[pw_nights_helper]; - V_DrawSmallScaledPatch(150, 44, 0, W_CachePatchName("NPRUC0",PU_CACHE)); - V_DrawThinString(146, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); - } - - if (stplyr->powers[pw_nights_linkfreeze]) - { - pwr = stplyr->powers[pw_nights_linkfreeze]; - V_DrawSmallScaledPatch(190, 44, 0, W_CachePatchName("NPRUE0",PU_CACHE)); - V_DrawThinString(186, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); + INT32 aflag = V_PERPLAYER; + tic_t drawtime = (5*TICRATE) - leveltime; + if (drawtime < TICRATE/2) + aflag |= (9 - 9*drawtime/(TICRATE/2)) << V_ALPHASHIFT; + // This one, not quite as much so. + V_DrawCenteredString(BASEVIDWIDTH/2, 60, aflag, + va(M_GetText("\x80GET\x82 %d\x80 SPHERE%s!"), ssspheres, + (ssspheres > 1) ? "S" : "")); } } + else + { + // Show pickup durations + if (cv_debug & DBG_NIGHTSBASIC) + { + UINT16 pwr; - // Records/extra text + if (stplyr->powers[pw_nights_superloop]) + { + pwr = stplyr->powers[pw_nights_superloop]; + V_DrawSmallScaledPatch(110, 44, 0, W_CachePatchName("NPRUA0",PU_CACHE)); + V_DrawThinString(106, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); + } + + if (stplyr->powers[pw_nights_helper]) + { + pwr = stplyr->powers[pw_nights_helper]; + V_DrawSmallScaledPatch(150, 44, 0, W_CachePatchName("NPRUC0",PU_CACHE)); + V_DrawThinString(146, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); + } + + if (stplyr->powers[pw_nights_linkfreeze]) + { + pwr = stplyr->powers[pw_nights_linkfreeze]; + V_DrawSmallScaledPatch(190, 44, 0, W_CachePatchName("NPRUE0",PU_CACHE)); + V_DrawThinString(186, 52, V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); + } + } + + // Records/extra text #ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_nightsrecords)) + if (LUA_HudEnabled(hud_nightsrecords)) #endif - ST_drawNightsRecords(); + ST_drawNightsRecords(); + } } static inline void ST_drawWeaponSelect(INT32 xoffs, INT32 y) @@ -1952,7 +1998,7 @@ static void ST_drawTextHUD(void) } else if (stplyr->spectator && (gametype != GT_COOP || stplyr->playerstate == PST_LIVE)) { - if (G_IsSpecialStage(gamemap) && useNightsSS) + if (G_IsSpecialStage(gamemap) && (maptol & TOL_NIGHTS)) textHUDdraw(M_GetText("\x82""Wait for the stage to end...")) else if (gametype == GT_COOP) { @@ -2070,22 +2116,22 @@ num: #undef SEP } -static void ST_drawSpecialStageHUD(void) +/*static void ST_drawSpecialStageHUD(void) { - if (totalrings > 0) + if (ssspheres > 0) { if (hudinfo[HUD_SS_TOTALRINGS].x) - ST_DrawNumFromHud(HUD_SS_TOTALRINGS, totalrings, V_HUDTRANS); + ST_DrawNumFromHud(HUD_SS_TOTALRINGS, ssspheres, V_HUDTRANS); else if (cv_timetic.value == 2) - V_DrawTallNum(hudinfo[HUD_RINGSNUMTICS].x, hudinfo[HUD_SS_TOTALRINGS].y, hudinfo[HUD_RINGSNUMTICS].f|V_PERPLAYER|V_HUDTRANS, totalrings); + V_DrawTallNum(hudinfo[HUD_RINGSNUMTICS].x, hudinfo[HUD_SS_TOTALRINGS].y, hudinfo[HUD_RINGSNUMTICS].f|V_PERPLAYER|V_HUDTRANS, ssspheres); else - V_DrawTallNum(hudinfo[HUD_RINGSNUM].x, hudinfo[HUD_SS_TOTALRINGS].y, hudinfo[HUD_RINGSNUM].f|V_PERPLAYER|V_HUDTRANS, totalrings); + V_DrawTallNum(hudinfo[HUD_RINGSNUM].x, hudinfo[HUD_SS_TOTALRINGS].y, hudinfo[HUD_RINGSNUM].f|V_PERPLAYER|V_HUDTRANS, ssspheres); } - if (leveltime < 5*TICRATE && totalrings > 0) + if (leveltime < 5*TICRATE && ssspheres > 0) { ST_DrawPatchFromHud(HUD_GETRINGS, getall, V_HUDTRANS); - ST_DrawNumFromHud(HUD_GETRINGSNUM, totalrings, V_HUDTRANS); + ST_DrawNumFromHud(HUD_GETRINGSNUM, ssspheres, V_HUDTRANS); } if (sstimer) @@ -2095,7 +2141,7 @@ static void ST_drawSpecialStageHUD(void) } else ST_DrawPatchFromHud(HUD_TIMEUP, timeup, V_HUDTRANS); -} +}*/ static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offset) { @@ -2231,7 +2277,7 @@ static void ST_overlayDrawer(void) //hu_showscores = auto hide score/time/rings when tab rankings are shown if (!(hu_showscores && (netgame || multiplayer))) { - if (maptol & TOL_NIGHTS) + if (maptol & TOL_NIGHTS || G_IsSpecialStage(gamemap)) ST_drawNiGHTSHUD(); else { @@ -2340,10 +2386,6 @@ static void ST_overlayDrawer(void) if (gametype == GT_RACE || gametype == GT_COMPETITION) ST_drawRaceHUD(); - // Special Stage HUD - if (!useNightsSS && G_IsSpecialStage(gamemap) && stplyr == &players[displayplayer]) - ST_drawSpecialStageHUD(); - // Emerald Hunt Indicators if (cv_itemfinder.value && M_SecretUnlocked(SECRET_ITEMFINDER)) ST_doItemFinderIconsAndSound(); @@ -2362,15 +2404,18 @@ static void ST_overlayDrawer(void) } // This is where we draw all the fun cheese if you have the chasecam off! - if ((stplyr == &players[displayplayer] && !camera.chase) - || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase)) + if (!(maptol & TOL_NIGHTS)) { - ST_drawFirstPersonHUD(); - if (cv_powerupdisplay.value) + if ((stplyr == &players[displayplayer] && !camera.chase) + || ((splitscreen && stplyr == &players[secondarydisplayplayer]) && !camera2.chase)) + { + ST_drawFirstPersonHUD(); + if (cv_powerupdisplay.value) + ST_drawPowerupHUD(); + } + else if (cv_powerupdisplay.value == 2) ST_drawPowerupHUD(); } - else if (cv_powerupdisplay.value == 2) - ST_drawPowerupHUD(); } #ifdef HAVE_BLUA diff --git a/src/y_inter.c b/src/y_inter.c index ed9cc4185..2194dc96f 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -78,7 +78,7 @@ typedef union struct { 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 passed4[SKINNAMESIZE+7]; // SUPER CRAWLA HONCHO INT32 passedx1; @@ -315,6 +315,8 @@ void Y_IntermissionDrawer(void) INT32 xoffset1 = 0; // Line 1 x offset INT32 xoffset2 = 0; // Line 2 x offset INT32 xoffset3 = 0; // Line 3 x offset + INT32 xoffset4 = 0; // Bonus line x offset + INT32 xoffset5 = 0; // Score line x offset UINT8 drawsection = 0; if (gottoken) // first to be behind everything else @@ -324,28 +326,40 @@ void Y_IntermissionDrawer(void) if (intertic <= 2*TICRATE) animatetic = 0; else if (!animatetic && data.spec.bonus.points == 0 && data.spec.passed3[0] != '\0') - animatetic = intertic; + animatetic = intertic + TICRATE; - if (animatetic) + if (animatetic && intertic >= animatetic) { INT32 animatetimer = (intertic - animatetic); - if (animatetimer <= 8) + if (animatetimer <= 12) { xoffset1 = -(animatetimer * 40); xoffset2 = -((animatetimer-2) * 40); + xoffset4 = -((animatetimer-4) * 40); + xoffset5 = -((animatetimer-6) * 40); if (xoffset2 > 0) xoffset2 = 0; + if (xoffset4 > 0) xoffset4 = 0; + if (xoffset5 > 0) xoffset5 = 0; } - else if (animatetimer <= 19) + else if (animatetimer < 28) { drawsection = 1; - xoffset1 = (16-animatetimer) * 40; - xoffset2 = (18-animatetimer) * 40; - xoffset3 = (20-animatetimer) * 40; + xoffset1 = (20-animatetimer) * 40; + xoffset2 = (22-animatetimer) * 40; + xoffset3 = (24-animatetimer) * 40; + xoffset4 = (26-animatetimer) * 40; + xoffset5 = (28-animatetimer) * 40; if (xoffset1 < 0) xoffset1 = 0; if (xoffset2 < 0) xoffset2 = 0; + if (xoffset3 < 0) xoffset3 = 0; + if (xoffset4 < 0) xoffset4 = 0; } else + { drawsection = 1; + if (animatetimer == 28) + S_StartSound(NULL, sfx_s3k68); + } } if (drawsection == 1) @@ -356,39 +370,60 @@ void Y_IntermissionDrawer(void) V_DrawLevelTitle(data.spec.passedx3 + xoffset2, ttheight, 0, data.spec.passed3); ttheight += V_LevelNameHeight(data.spec.passed4) + 2; V_DrawLevelTitle(data.spec.passedx4 + xoffset3, ttheight, 0, data.spec.passed4); - } - else if (data.spec.passed1[0] != '\0') - { - ttheight = 24; - V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); - ttheight += V_LevelNameHeight(data.spec.passed2) + 2; - V_DrawLevelTitle(data.spec.passedx2 + xoffset2, ttheight, 0, data.spec.passed2); + + V_DrawCenteredString(BASEVIDWIDTH/2 + xoffset4, 108 - 4, 0, "\x86""50 RINGS, NO SHIELD"); + V_DrawCenteredString(BASEVIDWIDTH/2 + xoffset5, 124 - 4, 0, "\x86""PRESS ""\x82""JUMP""\x86"", THEN ""\x82""SPIN"); } else { - ttheight = 24 + (V_LevelNameHeight(data.spec.passed2)/2) + 2; - V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2); + if (data.spec.passed1[0] != '\0') + { + ttheight = 24; + V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); + ttheight += V_LevelNameHeight(data.spec.passed2) + 2; + V_DrawLevelTitle(data.spec.passedx2 + xoffset2, ttheight, 0, data.spec.passed2); + } + else + { + ttheight = 24 + (V_LevelNameHeight(data.spec.passed2)/2) + 2; + V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2); + } + + V_DrawScaledPatch(152 + xoffset4, 108, 0, data.spec.bonuspatch); + V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 109, 0, data.spec.bonus.points); + V_DrawScaledPatch(152 + xoffset5, 124, 0, data.spec.pscore); + V_DrawTallNum(BASEVIDWIDTH + xoffset5 - 68, 125, 0, data.spec.score); } // draw the emeralds //if (intertic & 1) { + boolean drawthistic = !(ALL7EMERALDS(emeralds) && (intertic & 1)); INT32 emeraldx = 152 - 3*28; INT32 em = (gamemap - sstage_start); - for (i = 0; i < 7; ++i) + if (em == 7) { - if ((i != em) && !(intertic & 1) && (emeralds & (1 << i))) - V_DrawScaledPatch(emeraldx, 74, 0, emeraldpics[0][i]); - emeraldx += 28; + if (!stagefailed) + { + fixed_t adjust = 2*(FINESINE(FixedAngle((intertic + 1)<<(FRACBITS-4)) & FINEMASK)); + V_DrawFixedPatch(152< (3*TICRATE)/2) { @@ -896,7 +927,7 @@ void Y_Ticker(void) if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && !demoplayback) { if (M_UpdateUnlockablesAndExtraEmblems()) - S_StartSound(NULL, sfx_ncitem); + S_StartSound(NULL, sfx_s3k68); G_SaveGameData(); } @@ -1307,6 +1338,11 @@ void Y_StartIntermission(void) else strcpy(data.spec.passed1, "YOU GOT"); strcpy(data.spec.passed2, "A CHAOS EMERALD"); + if (gamemap > (sstage_start + 5)) + { + data.spec.passed2[15] = '?'; + data.spec.passed2[16] = '\0'; + } } data.spec.passedx1 = (BASEVIDWIDTH - V_LevelNameWidth(data.spec.passed1))/2; data.spec.passedx2 = (BASEVIDWIDTH - V_LevelNameWidth(data.spec.passed2))/2; @@ -1857,7 +1893,7 @@ static void Y_AwardSpecialStageBonus(void) if (!playeringame[i] || players[i].lives < 1) // not active or game over Y_SetNullBonus(&players[i], &localbonus); - else if (useNightsSS) // Link instead of Score + else if (maptol & TOL_NIGHTS) // Link instead of Rings Y_SetLinkBonus(&players[i], &localbonus); else Y_SetRingBonus(&players[i], &localbonus);