diff --git a/src/b_bot.c b/src/b_bot.c index 0f2c80d55b73f7515be7afbe135d27f34de1f79e..dc65c9c16b8dd8f8bfa98dca65fbfd022d6d02ea 100644 --- a/src/b_bot.c +++ b/src/b_bot.c @@ -212,7 +212,7 @@ boolean B_CheckRespawn(player_t *player) // Check if Sonic is busy first. // If he's doing any of these things, he probably doesn't want to see us. - if (sonic->player->pflags & (PF_GLIDING|PF_SLIDING|PF_NIGHTSMODE) + if (sonic->player->pflags & (PF_GLIDING|PF_SLIDING|PF_BOUNCING) || (sonic->player->panim != PA_IDLE && sonic->player->panim != PA_WALK) || (sonic->player->powers[pw_carry])) return false; diff --git a/src/command.c b/src/command.c index 36c75910994ce6bd678b288feabf67883a897400..d72f845ad37cfbf942ed278990ecac749382c44e 100644 --- a/src/command.c +++ b/src/command.c @@ -1165,7 +1165,7 @@ found: if (var == &cv_forceskin) { var->value = R_SkinAvailable(var->string); - if (!R_SkinUnlock(var->value)) + if (!R_SkinUsable(-1, var->value)) var->value = -1; } else @@ -1361,6 +1361,16 @@ static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth) return; } + if (var == &cv_forceskin) + { + INT32 skin = R_SkinAvailable(value); + if ((stricmp(value, "None")) && ((skin == -1) || !R_SkinUsable(-1, skin))) + { + CONS_Printf("Please provide a valid skin name (\"None\" disables).\n"); + return; + } + } + // Only add to netcmd buffer if in a netgame, otherwise, just change it. if (netgame || multiplayer) { @@ -1478,7 +1488,7 @@ void CV_AddValue(consvar_t *var, INT32 increment) else if (newvalue >= numskins) newvalue = -1; } while ((oldvalue != newvalue) - && !(R_SkinUnlock(newvalue))); + && !(R_SkinUsable(-1, newvalue))); } else newvalue = var->value + increment; diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 574cce7ab80902ef59ef3b7914353b9a1d1dcdf0..2db27a693cda8f4f4041265cc2c605e1afa0cf77 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -528,6 +528,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->skincolor = players[i].skincolor; rsp->skin = LONG(players[i].skin); + rsp->availabilities = LONG(players[i].availabilities); // Just in case Lua does something like // modify these at runtime rsp->camerascale = (fixed_t)LONG(players[i].camerascale); @@ -551,7 +552,6 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->playerspinheight = (fixed_t)LONG(players[i].spinheight); rsp->speed = (fixed_t)LONG(players[i].speed); - rsp->jumping = players[i].jumping; rsp->secondjump = players[i].secondjump; rsp->fly1 = players[i].fly1; rsp->glidetime = (tic_t)LONG(players[i].glidetime); @@ -657,6 +657,7 @@ static void resynch_read_player(resynch_pak *rsp) players[i].skincolor = rsp->skincolor; players[i].skin = LONG(rsp->skin); + players[i].availabilities = LONG(rsp->availabilities); // Just in case Lua does something like // modify these at runtime players[i].camerascale = (fixed_t)LONG(rsp->camerascale); @@ -680,7 +681,6 @@ static void resynch_read_player(resynch_pak *rsp) players[i].spinheight = (fixed_t)LONG(rsp->playerspinheight); players[i].speed = (fixed_t)LONG(rsp->speed); - players[i].jumping = rsp->jumping; players[i].secondjump = rsp->secondjump; players[i].fly1 = rsp->fly1; players[i].glidetime = (tic_t)LONG(rsp->glidetime); @@ -1364,6 +1364,7 @@ static boolean SV_SendServerConfig(INT32 node) // which is nice and easy for us to detect memset(netbuffer->u.servercfg.playerskins, 0xFF, sizeof(netbuffer->u.servercfg.playerskins)); memset(netbuffer->u.servercfg.playercolor, 0xFF, sizeof(netbuffer->u.servercfg.playercolor)); + memset(netbuffer->u.servercfg.playeravailabilities, 0xFF, sizeof(netbuffer->u.servercfg.playeravailabilities)); for (i = 0; i < MAXPLAYERS; i++) { @@ -1371,6 +1372,7 @@ static boolean SV_SendServerConfig(INT32 node) continue; netbuffer->u.servercfg.playerskins[i] = (UINT8)players[i].skin; netbuffer->u.servercfg.playercolor[i] = (UINT8)players[i].skincolor; + netbuffer->u.servercfg.playeravailabilities[i] = (UINT32)LONG(players[i].availabilities); } memcpy(netbuffer->u.servercfg.server_context, server_context, 8); @@ -2308,12 +2310,7 @@ static void ResetNode(INT32 node); void CL_ClearPlayer(INT32 playernum) { if (players[playernum].mo) - { - // Don't leave a NiGHTS ghost! - if ((players[playernum].pflags & PF_NIGHTSMODE) && players[playernum].mo->tracer) - P_RemoveMobj(players[playernum].mo->tracer); P_RemoveMobj(players[playernum].mo); - } memset(&players[playernum], 0, sizeof (player_t)); } @@ -3497,10 +3494,12 @@ static void HandlePacketFromAwayNode(SINT8 node) for (j = 0; j < MAXPLAYERS; j++) { if (netbuffer->u.servercfg.playerskins[j] == 0xFF - && netbuffer->u.servercfg.playercolor[j] == 0xFF) + && netbuffer->u.servercfg.playercolor[j] == 0xFF + && netbuffer->u.servercfg.playeravailabilities[j] == 0xFFFFFFFF) continue; // not in game playeringame[j] = true; + players[j].availabilities = (UINT32)LONG(netbuffer->u.servercfg.playeravailabilities[j]); SetPlayerSkinByNum(j, (INT32)netbuffer->u.servercfg.playerskins[j]); players[j].skincolor = netbuffer->u.servercfg.playercolor[j]; } diff --git a/src/d_clisrv.h b/src/d_clisrv.h index 3823295398465efa2f1c47aa0df0f2497c0d78d7..1ca82fdc517026f314fdd8c16b568e06666e406f 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -172,6 +172,7 @@ typedef struct UINT8 skincolor; INT32 skin; + UINT32 availabilities; // Just in case Lua does something like // modify these at runtime fixed_t camerascale; @@ -195,7 +196,6 @@ typedef struct fixed_t playerspinheight; fixed_t speed; - UINT8 jumping; UINT8 secondjump; UINT8 fly1; tic_t glidetime; @@ -284,6 +284,7 @@ typedef struct // 0xFF == not in game; else player skin num UINT8 playerskins[MAXPLAYERS]; UINT8 playercolor[MAXPLAYERS]; + UINT32 playeravailabilities[MAXPLAYERS]; UINT8 gametype; UINT8 modifiedgame; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 0fc5ddc8560fb82b63ed630dd5647672659759fc..6b97eb5b7c7eae08460a26476ef69ffb92b18a36 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1011,7 +1011,7 @@ UINT8 CanChangeSkin(INT32 playernum) return true; // Force skin in effect. - if (client && (cv_forceskin.value != -1) && !(adminplayer == playernum && serverplayer == -1)) + if ((cv_forceskin.value != -1) || (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0')) return false; // Can change skin in intermission and whatnot. @@ -1109,6 +1109,8 @@ static void SendNameAndColor(void) if (!Playing()) return; + players[consoleplayer].availabilities = R_GetSkinAvailabilities(); + // If you're not in a netgame, merely update the skin, color, and name. if (!netgame) { @@ -1127,7 +1129,7 @@ static void SendNameAndColor(void) SetPlayerSkinByNum(consoleplayer, 0); CV_StealthSet(&cv_skin, skins[0].name); } - else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUnlock(foundskin)) + else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin)) { boolean notsame; @@ -1174,7 +1176,7 @@ static void SendNameAndColor(void) // check if player has the skin loaded (cv_skin may have // the name of a skin that was available in the previous game) cv_skin.value = R_SkinAvailable(cv_skin.string); - if ((cv_skin.value < 0) || !R_SkinUnlock(cv_skin.value)) + if ((cv_skin.value < 0) || !R_SkinUsable(consoleplayer, cv_skin.value)) { CV_StealthSet(&cv_skin, DEFAULTSKIN); cv_skin.value = 0; @@ -1182,6 +1184,7 @@ static void SendNameAndColor(void) // Finally write out the complete packet and send it off. WRITESTRINGN(p, cv_playername.zstring, MAXPLAYERNAME); + WRITEUINT32(p, (UINT32)players[consoleplayer].availabilities); WRITEUINT8(p, (UINT8)cv_playercolor.value); WRITEUINT8(p, (UINT8)cv_skin.value); SendNetXCmd(XD_NAMEANDCOLOR, buf, p - buf); @@ -1224,6 +1227,8 @@ static void SendNameAndColor2(void) if (!Playing()) return; + players[secondplaya].availabilities = R_GetSkinAvailabilities(); + // If you're not in a netgame, merely update the skin, color, and name. if (botingame) { @@ -1252,7 +1257,7 @@ static void SendNameAndColor2(void) SetPlayerSkinByNum(secondplaya, forcedskin); CV_StealthSet(&cv_skin2, skins[forcedskin].name); } - else if ((foundskin = R_SkinAvailable(cv_skin2.string)) != -1 && R_SkinUnlock(foundskin)) + else if ((foundskin = R_SkinAvailable(cv_skin2.string)) != -1 && R_SkinUsable(secondplaya, foundskin)) { boolean notsame; @@ -1307,6 +1312,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) #endif READSTRINGN(*cp, name, MAXPLAYERNAME); + p->availabilities = READUINT32(*cp); color = READUINT8(*cp); skin = READUINT8(*cp); @@ -1323,6 +1329,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) if (server && (p != &players[consoleplayer] && p != &players[secondarydisplayplayer])) { boolean kick = false; + INT32 s; // team colors if (G_GametypeHasTeams()) @@ -1337,6 +1344,16 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum) if (!p->skincolor) kick = true; + // availabilities + for (s = 0; s < MAXSKINS; s++) + { + if (!skins[s].availability && (p->availabilities & (1 << s))) + { + kick = true; + break; + } + } + if (kick) { XBOXSTATIC UINT8 buf[2]; @@ -4043,13 +4060,6 @@ static void Command_Archivetest_f(void) */ static void ForceSkin_OnChange(void) { - if ((server || adminplayer == consoleplayer) && ((cv_forceskin.value == -1 && stricmp(cv_forceskin.string, "None")) || !(R_SkinUnlock(cv_forceskin.value)))) - { - CONS_Printf("Please provide a valid skin name (\"None\" disables).\n"); - CV_SetValue(&cv_forceskin, -1); - return; - } - // NOT in SP, silly! if (!(netgame || multiplayer)) return; @@ -4058,7 +4068,7 @@ static void ForceSkin_OnChange(void) CONS_Printf("The server has lifted the forced skin restrictions.\n"); else { - CONS_Printf("The server is restricting all players to skin \"%s\".\n",skins[cv_forceskin.value].realname); + CONS_Printf("The server is restricting all players to skin \"%s\".\n",skins[cv_forceskin.value].name); ForceAllSkins(cv_forceskin.value); } } diff --git a/src/d_player.h b/src/d_player.h index 1c57e61677a85f9b05c053b010db98c5302c7271..4e4a53a084674ad11707c6410554bbcee84f5f7c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -32,19 +32,21 @@ // Extra abilities/settings for skins (combinable stuff) typedef enum { - SF_SUPER = 1, // Can turn super in singleplayer/co-op mode. - SF_SUPERANIMS = 1<<1, // If super, use the super sonic animations - SF_SUPERSPIN = 1<<2, // Should spin frames be played while super? - SF_HIRES = 1<<3, // Draw the sprite 2x as small? + SF_SUPER = 1, // Can turn super in singleplayer/co-op mode? + SF_NOSUPERSPIN = 1<<1, // Should spin frames be played while super? + SF_NOSPINDASHDUST = 1<<2, // Spawn dust particles when charging a spindash? + SF_HIRES = 1<<3, // Draw the sprite at different size? SF_NOSKID = 1<<4, // No skid particles etc SF_NOSPEEDADJUST = 1<<5, // Skin-specific version of disablespeedadjust SF_RUNONWATER = 1<<6, // Run on top of water FOFs? - SF_NOJUMPSPIN = 1<<7, // SPR2_JUMP defaults to SPR2_SPRG instead of SPR2_SPIN, falling states used, and player height is full when jumping? + SF_NOJUMPSPIN = 1<<7, // SPR2_JUMP defaults to SPR2_SPRG instead of SPR2_ROLL, falling states used, and player height is full when jumping? SF_NOJUMPDAMAGE = 1<<8, // Don't damage enemies, etc whilst jumping? SF_STOMPDAMAGE = 1<<9, // Always damage enemies, etc by landing on them, no matter your vunerability? SF_MARIODAMAGE = SF_NOJUMPDAMAGE|SF_STOMPDAMAGE, // The Mario method of being able to damage enemies, etc. SF_MACHINE = 1<<10, // Beep boop. Are you a robot? - SF_NOSPINDASHDUST = 1<<11, // Don't spawn dust particles when charging a spindash + SF_DASHMODE = 1<<11, // Sonic Advance 2 style top speed increase? + SF_FASTEDGE = 1<<12, // Faster edge teeter? + SF_MULTIABILITY = 1<<13, // Revenge of Final Demo. // free up to and including 1<<31 } skinflags_t; @@ -65,7 +67,7 @@ typedef enum CA_JUMPBOOST, CA_AIRDRILL, CA_JUMPTHOK, - CA_DASHMODE, + CA_BOUNCE, CA_TWINSPIN } charability_t; @@ -74,7 +76,7 @@ typedef enum { CA2_NONE=0, CA2_SPINDASH, - CA2_MULTIABILITY, + CA2_GUNSLINGER, CA2_MELEE } charability2_t; @@ -118,10 +120,8 @@ typedef enum // Did you get a time-over? PF_TIMEOVER = 1<<10, - // Ready for Super? - PF_SUPERREADY = 1<<11, - // Character action status + PF_STARTJUMP = 1<<11, PF_JUMPED = 1<<12, PF_SPINNING = 1<<13, PF_STARTDASH = 1<<14, @@ -133,12 +133,11 @@ typedef enum // Sliding (usually in water) like Labyrinth/Oil Ocean PF_SLIDING = 1<<17, + // Bouncing + PF_BOUNCING = 1<<18, + /*** NIGHTS STUFF ***/ - // Is the player in NiGHTS mode? - PF_NIGHTSMODE = 1<<18, PF_TRANSFERTOCLOSEST = 1<<19, - - // Spill rings after falling PF_NIGHTSFALL = 1<<20, PF_DRILLING = 1<<21, PF_SKIDDOWN = 1<<22, @@ -157,10 +156,10 @@ typedef enum // Used shield ability PF_SHIELDABILITY = 1<<28, - // Force jump damage? - PF_FORCEJUMPDAMAGE = 1<<29 + // Jump damage? + PF_NOJUMPDAMAGE = 1<<29, - // free up to and including 1<<31 + // up to 1<<31 is free } pflags_t; typedef enum @@ -171,7 +170,7 @@ typedef enum PA_EDGE, PA_WALK, PA_RUN, - PA_PEEL, + PA_DASH, PA_PAIN, PA_ROLL, PA_JUMP, @@ -223,6 +222,10 @@ typedef enum CR_GENERIC, // Tails carry. CR_PLAYER, + // NiGHTS mode. Not technically a CARRYING, but doesn't stack with any of the others, so might as well go here. + CR_NIGHTSMODE, + // Old Brak sucks hard, but this gimmick could be used for something better, so we might as well continue supporting it. + CR_BRAKGOOP, // Specific level gimmicks. CR_ZOOMTUBE, CR_ROPEHANG, @@ -262,9 +265,7 @@ typedef enum pw_nights_helper, pw_nights_linkfreeze, - //for linedef exec 427 - pw_nocontrol, - pw_ingoop, // In goop + pw_nocontrol, //for linedef exec 427 NUMPOWERS } powertype_t; @@ -340,6 +341,7 @@ typedef struct player_s UINT8 skincolor; INT32 skin; + UINT32 availabilities; UINT32 score; // player score fixed_t dashspeed; // dashing speed @@ -377,7 +379,6 @@ typedef struct player_s UINT8 gotcontinue; // Got continue from this stage? fixed_t speed; // Player's speed (distance formula of MOMX and MOMY values) - UINT8 jumping; // Holding down jump button UINT8 secondjump; // Jump counter UINT8 fly1; // Tails flying diff --git a/src/dehacked.c b/src/dehacked.c index de940c8adea2ca2093df7e9d8ad52adc2b768ac5..32b1c1ca30cbc29c1a74557272dd756648e8f77d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -432,22 +432,20 @@ static void readAnimTex(MYFILE *f, INT32 num) } */ -static boolean findFreeSlot(INT32 *num, UINT16 wadnum) +static boolean findFreeSlot(INT32 *num) { // Send the character select entry to a free slot. - while (*num < 32 && (!(PlayerMenu[*num].status & IT_DISABLED) || description[*num].wadnum == wadnum)) // Will kill hidden characters from other files, but that's okay. + while (*num < 32 && (description[*num].used)) *num = *num+1; // No more free slots. :( if (*num >= 32) return false; - PlayerMenu[*num].status = IT_CALL; - description[*num].wadnum = wadnum; description[*num].picname[0] = '\0'; // Redesign your logo. (See M_DrawSetupChoosePlayerMenu in m_menu.c...) // Found one! ^_^ - return true; + return (description[*num].used = true); } // Reads a player. @@ -479,7 +477,7 @@ static void readPlayer(MYFILE *f, INT32 num) { char *playertext = NULL; - if (!slotfound && (slotfound = findFreeSlot(&num, f->wad)) == false) + if (!slotfound && (slotfound = findFreeSlot(&num)) == false) goto done; for (i = 0; i < MAXLINELEN-3; i++) @@ -528,7 +526,7 @@ static void readPlayer(MYFILE *f, INT32 num) if (fastcmp(word, "PICNAME")) { - if (!slotfound && (slotfound = findFreeSlot(&num, f->wad)) == false) + if (!slotfound && (slotfound = findFreeSlot(&num)) == false) goto done; DEH_WriteUndoline(word, &description[num].picname[0], UNDO_NONE); @@ -536,12 +534,6 @@ static void readPlayer(MYFILE *f, INT32 num) } else if (fastcmp(word, "STATUS")) { - // Limit the status to only IT_DISABLED and IT_CALL - if (i) - i = IT_CALL; - else - i = IT_DISABLED; - /* You MAY disable previous entries if you so desire... But try to enable something that's already enabled and you will be sent to a free slot. @@ -549,15 +541,15 @@ static void readPlayer(MYFILE *f, INT32 num) Because of this, you are allowed to edit any previous entries you like, but only if you signal that you are purposely doing so by disabling and then reenabling the slot. */ - if (i != IT_DISABLED && !slotfound && (slotfound = findFreeSlot(&num, f->wad)) == false) + if (i && !slotfound && (slotfound = findFreeSlot(&num)) == false) goto done; - DEH_WriteUndoline(word, va("%d", PlayerMenu[num].status), UNDO_NONE); - PlayerMenu[num].status = (INT16)i; + DEH_WriteUndoline(word, va("%d", description[num].used), UNDO_NONE); + description[num].used = (!!i); } else if (fastcmp(word, "SKINNAME")) { // Send to free slot. - if (!slotfound && (slotfound = findFreeSlot(&num, f->wad)) == false) + if (!slotfound && (slotfound = findFreeSlot(&num)) == false) goto done; DEH_WriteUndoline(word, description[num].skinname, UNDO_NONE); @@ -3925,12 +3917,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PLAY_WAIT", "S_PLAY_WALK", "S_PLAY_RUN", - "S_PLAY_PEEL", + "S_PLAY_DASH", "S_PLAY_PAIN", + "S_PLAY_STUN", "S_PLAY_DEAD", "S_PLAY_DRWN", - "S_PLAY_SPIN", - "S_PLAY_DASH", + "S_PLAY_ROLL", "S_PLAY_GASP", "S_PLAY_JUMP", "S_PLAY_SPRING", @@ -3938,6 +3930,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PLAY_EDGE", "S_PLAY_RIDE", + // CA2_SPINDASH + "S_PLAY_SPINDASH", + // CA_FLY/SWIM "S_PLAY_FLY", "S_PLAY_SWIM", @@ -3948,30 +3943,25 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PLAY_CLING", "S_PLAY_CLIMB", + // CA_FLOAT/CA_SLOWFALL + "S_PLAY_FLOAT", + "S_PLAY_FLOAT_RUN", + + // CA_BOUNCE + "S_PLAY_BOUNCE", + "S_PLAY_BOUNCE_LANDING", + + // CA2_GUNSLINGER + "S_PLAY_FIRE", + "S_PLAY_FIRE_FINISH", + // CA_TWINSPIN "S_PLAY_TWINSPIN", // CA2_MELEE "S_PLAY_MELEE", "S_PLAY_MELEE_FINISH", - - // SF_SUPERANIMS - "S_PLAY_SUPER_STND", - "S_PLAY_SUPER_WALK", - "S_PLAY_SUPER_RUN", - "S_PLAY_SUPER_PEEL", - "S_PLAY_SUPER_PAIN", - "S_PLAY_SUPER_STUN", - "S_PLAY_SUPER_DEAD", - "S_PLAY_SUPER_DRWN", - "S_PLAY_SUPER_SPIN", - "S_PLAY_SUPER_GASP", - "S_PLAY_SUPER_JUMP", - "S_PLAY_SUPER_SPRING", - "S_PLAY_SUPER_FALL", - "S_PLAY_SUPER_EDGE", - "S_PLAY_SUPER_RIDE", - "S_PLAY_SUPER_FLOAT", + "S_PLAY_MELEE_LANDING", // SF_SUPER "S_PLAY_SUPERTRANS1", @@ -4010,7 +4000,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PLAY_NIGHTS_STAND", "S_PLAY_NIGHTS_FLOAT", - "S_PLAY_NIGHTS_PAIN", + "S_PLAY_NIGHTS_STUN", "S_PLAY_NIGHTS_PULL", "S_PLAY_NIGHTS_ATTACK", @@ -5935,14 +5925,18 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FOUR2", "S_FIVE2", + "S_LOCKON1", + "S_LOCKON2", + // Tag Sign - "S_TTAG1", + "S_TTAG", // Got Flag Sign - "S_GOTFLAG1", - "S_GOTFLAG2", - "S_GOTFLAG3", - "S_GOTFLAG4", + "S_GOTFLAG", + "S_GOTREDFLAG", + "S_GOTBLUEFLAG", + + "S_CORK", // Red Ring "S_RRNG1", @@ -6733,9 +6727,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_SCORE", // score logo "MT_DROWNNUMBERS", // Drowning Timer "MT_GOTEMERALD", // Chaos Emerald (intangible) + "MT_LOCKON", // Target "MT_TAG", // Tag Sign "MT_GOTFLAG", // Got Flag sign - "MT_GOTFLAG2", // Got Flag sign // Ambient Sounds "MT_AWATERA", // Ambient Water Sound 1 @@ -6749,6 +6743,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_RANDOMAMBIENT", "MT_RANDOMAMBIENT2", + "MT_CORK", + // Ring Weapons "MT_REDRING", "MT_BOUNCERING", @@ -6972,10 +6968,8 @@ static const char *const PLAYERFLAG_LIST[] = { // Did you get a time-over? "TIMEOVER", - // Ready for Super? - "SUPERREADY", - // Character action status + "STARTJUMP", "JUMPED", "SPINNING", "STARTDASH", @@ -6987,12 +6981,11 @@ static const char *const PLAYERFLAG_LIST[] = { // Sliding (usually in water) like Labyrinth/Oil Ocean "SLIDING", + // Bouncing + "BOUNCING", + /*** NIGHTS STUFF ***/ - // Is the player in NiGHTS mode? - "NIGHTSMODE", "TRANSFERTOCLOSEST", - - // Spill rings after falling "NIGHTSFALL", "DRILLING", "SKIDDOWN", @@ -7006,7 +6999,7 @@ static const char *const PLAYERFLAG_LIST[] = { "ANALOGMODE", // Analog mode? "CANCARRY", // Can carry? "SHIELDABILITY", // Thokked with shield ability - "FORCEJUMPDAMAGE", // Force jump damage + "NOJUMPDAMAGE", // No jump damage NULL // stop loop here. }; @@ -7155,8 +7148,7 @@ static const char *const POWERS_LIST[] = { "NIGHTS_LINKFREEZE", //for linedef exec 427 - "NOCONTROL", - "INGOOP" // In goop + "NOCONTROL" }; static const char *const HUDITEMS_LIST[] = { @@ -7248,14 +7240,15 @@ struct { // Frame settings {"FF_FRAMEMASK",FF_FRAMEMASK}, - {"FF_VERTICALFLIP",FF_VERTICALFLIP}, - {"FF_PAPERSPRITE",FF_PAPERSPRITE}, + {"FF_SPR2SUPER",FF_SPR2SUPER}, {"FF_SPR2ENDSTATE",FF_SPR2ENDSTATE}, {"FF_SPR2MIDSTART",FF_SPR2MIDSTART}, {"FF_ANIMATE",FF_ANIMATE}, {"FF_RANDOMANIM",FF_RANDOMANIM}, {"FF_GLOBALANIM",FF_GLOBALANIM}, {"FF_FULLBRIGHT",FF_FULLBRIGHT}, + {"FF_VERTICALFLIP",FF_VERTICALFLIP}, + {"FF_PAPERSPRITE",FF_PAPERSPRITE}, {"FF_TRANSMASK",FF_TRANSMASK}, {"FF_TRANSSHIFT",FF_TRANSSHIFT}, // new preshifted translucency (used in source) @@ -7380,6 +7373,8 @@ struct { {"CR_NONE",CR_NONE}, {"CR_GENERIC",CR_GENERIC}, {"CR_PLAYER",CR_PLAYER}, + {"CR_NIGHTSMODE",CR_NIGHTSMODE}, + {"CR_BRAKGOOP",CR_BRAKGOOP}, {"CR_ZOOMTUBE",CR_ZOOMTUBE}, {"CR_ROPEHANG",CR_ROPEHANG}, {"CR_MACESPIN",CR_MACESPIN}, @@ -7395,8 +7390,8 @@ struct { // Character flags (skinflags_t) {"SF_SUPER",SF_SUPER}, - {"SF_SUPERANIMS",SF_SUPERANIMS}, - {"SF_SUPERSPIN",SF_SUPERSPIN}, + {"SF_NOSUPERSPIN",SF_NOSUPERSPIN}, + {"SF_NOSPINDASHDUST",SF_NOSPINDASHDUST}, {"SF_HIRES",SF_HIRES}, {"SF_NOSKID",SF_NOSKID}, {"SF_NOSPEEDADJUST",SF_NOSPEEDADJUST}, @@ -7406,7 +7401,9 @@ struct { {"SF_STOMPDAMAGE",SF_STOMPDAMAGE}, {"SF_MARIODAMAGE",SF_MARIODAMAGE}, {"SF_MACHINE",SF_MACHINE}, - {"SF_NOSPINDASHDUST",SF_NOSPINDASHDUST}, + {"SF_DASHMODE",SF_DASHMODE}, + {"SF_FASTEDGE",SF_FASTEDGE}, + {"SF_MULTIABILITY",SF_MULTIABILITY}, // Character abilities! // Primary @@ -7424,12 +7421,12 @@ struct { {"CA_JUMPBOOST",CA_JUMPBOOST}, {"CA_AIRDRILL",CA_AIRDRILL}, {"CA_JUMPTHOK",CA_JUMPTHOK}, - {"CA_DASHMODE",CA_DASHMODE}, + {"CA_BOUNCE",CA_BOUNCE}, {"CA_TWINSPIN",CA_TWINSPIN}, // Secondary {"CA2_NONE",CA2_NONE}, // now slot 0! {"CA2_SPINDASH",CA2_SPINDASH}, - {"CA2_MULTIABILITY",CA2_MULTIABILITY}, + {"CA2_GUNSLINGER",CA2_GUNSLINGER}, {"CA2_MELEE",CA2_MELEE}, // Sound flags @@ -7498,7 +7495,7 @@ struct { {"PA_EDGE",PA_EDGE}, {"PA_WALK",PA_WALK}, {"PA_RUN",PA_RUN}, - {"PA_PEEL",PA_PEEL}, + {"PA_DASH",PA_DASH}, {"PA_PAIN",PA_PAIN}, {"PA_ROLL",PA_ROLL}, {"PA_JUMP",PA_JUMP}, diff --git a/src/doomdef.h b/src/doomdef.h index a35c17ba6cb971663fe7d44a4ca6836ec19fe9f4..73ecf7dc9daec2f20ee057d31d638df4f2f5e8b8 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -222,7 +222,7 @@ extern FILE *logstream; // NOTE: it needs more than this to increase the number of players... #define MAXPLAYERS 32 -#define MAXSKINS MAXPLAYERS +#define MAXSKINS 32 #define PLAYERSMASK (MAXPLAYERS-1) #define MAXPLAYERNAME 21 @@ -543,4 +543,7 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Experimental attempts at preventing MF_PAPERCOLLISION objects from getting stuck in walls. //#define PAPER_COLLISIONCORRECTION +/// Hudname padding. +#define SKINNAMEPADDING + #endif // __DOOMDEF__ diff --git a/src/g_game.c b/src/g_game.c index d3793f6df5c9c876211b6702ad311276554e10c1..8bd71d123dfd0905cbf8ebea8434bb6c67d43bcb 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1014,9 +1014,8 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) if (cv_analog.value || twodlevel || (player->mo && (player->mo->flags2 & MF2_TWOD)) || (!demoplayback && (player->climbing - || (player->pflags & PF_NIGHTSMODE) - || (player->pflags & PF_SLIDING) - || (player->pflags & PF_FORCESTRAFE)))) // Analog + || (player->powers[pw_carry] == CR_NIGHTSMODE) + || (player->pflags & (PF_SLIDING|PF_FORCESTRAFE))))) // Analog forcestrafe = true; if (forcestrafe) // Analog { @@ -1119,7 +1118,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics) cmd->buttons |= BT_USE; // Camera Controls - if (cv_debug || cv_analog.value || demoplayback || objectplacing || player->pflags & PF_NIGHTSMODE) + if (cv_debug || cv_analog.value || demoplayback || objectplacing || player->powers[pw_carry] == CR_NIGHTSMODE) { if (PLAYER1INPUTDOWN(gc_camleft)) cmd->buttons |= BT_CAMLEFT; @@ -1305,9 +1304,8 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) if (cv_analog2.value || twodlevel || (player->mo && (player->mo->flags2 & MF2_TWOD)) || player->climbing - || (player->pflags & PF_NIGHTSMODE) - || (player->pflags & PF_SLIDING) - || (player->pflags & PF_FORCESTRAFE)) // Analog + || (player->powers[pw_carry] == CR_NIGHTSMODE) + || (player->pflags & (PF_SLIDING|PF_FORCESTRAFE))) // Analog forcestrafe = true; if (forcestrafe) // Analog { @@ -1407,7 +1405,7 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics) cmd->buttons |= BT_USE; // Camera Controls - if (cv_debug || cv_analog2.value || player->pflags & PF_NIGHTSMODE) + if (cv_debug || cv_analog2.value || player->powers[pw_carry] == CR_NIGHTSMODE) { if (PLAYER2INPUTDOWN(gc_camleft)) cmd->buttons |= BT_CAMLEFT; @@ -2071,6 +2069,7 @@ void G_PlayerReborn(INT32 player) UINT8 mare; UINT8 skincolor; INT32 skin; + UINT32 availabilities; tic_t jointime; boolean spectator; INT16 bot; @@ -2095,6 +2094,7 @@ void G_PlayerReborn(INT32 player) skincolor = players[player].skincolor; skin = players[player].skin; + availabilities = players[player].availabilities; camerascale = players[player].camerascale; shieldscale = players[player].shieldscale; charability = players[player].charability; @@ -2140,6 +2140,7 @@ void G_PlayerReborn(INT32 player) // save player config truth reborn p->skincolor = skincolor; p->skin = skin; + p->availabilities = availabilities; p->camerascale = camerascale; p->shieldscale = shieldscale; p->charability = charability; @@ -3913,12 +3914,8 @@ void G_WriteGhostTic(mobj_t *ghost) if (!(demoflags & DF_GHOST)) return; // No ghost data to write. - if (ghost->player && ghost->player->pflags & PF_NIGHTSMODE && ghost->tracer) - { - // We're talking about the NiGHTS thing, not the normal platforming thing! + if (ghost->player && ghost->player->powers[pw_carry] == CR_NIGHTSMODE) // We're talking about the NiGHTS thing, not the normal platforming thing! ziptic |= GZT_NIGHTS; - ghost = ghost->tracer; - } ziptic_p = demo_p++; // the ziptic, written at the end of this function @@ -4100,11 +4097,9 @@ void G_ConsGhostTic(void) demo_p++; if (ziptic & GZT_SPR2) demo_p++; - if(ziptic & GZT_NIGHTS) { - if (!testmo->player || !(testmo->player->pflags & PF_NIGHTSMODE) || !testmo->tracer) + if (ziptic & GZT_NIGHTS) { + if (!testmo->player || !(testmo->player->powers[pw_carry] == CR_NIGHTSMODE)) nightsfail = true; - else - testmo = testmo->tracer; } if (ziptic & GZT_EXTRA) diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index cdd778caa372c2f90ed96e86fe52ab063243a040..a49a788e66c59713c6a14038fb36a7e2b2ef3528 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -404,7 +404,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_SPLA &lspr[NOLIGHT], // SPR_SMOK &lspr[NOLIGHT], // SPR_BUBL - &lspr[SUPERSPARK_L], // SPR_WZAP + &lspr[RINGLIGHT_L], // SPR_WZAP &lspr[SUPERSPARK_L], // SPR_TFOG &lspr[NIGHTSLIGHT_L], // SPR_SEED // Sonic CD flower seed &lspr[NOLIGHT], // SPR_PRTL @@ -412,9 +412,12 @@ light_t *t_lspr[NUMSPRITES] = // Game Indicators &lspr[NOLIGHT], // SPR_SCOR &lspr[NOLIGHT], // SPR_DRWN + &lspr[NOLIGHT], // SPR_LCKN &lspr[NOLIGHT], // SPR_TTAG &lspr[NOLIGHT], // SPR_GFLG + &lspr[NOLIGHT], // SPR_CORK + // Ring Weapons &lspr[RINGLIGHT_L], // SPR_RRNG &lspr[RINGLIGHT_L], // SPR_RNGB diff --git a/src/hu_stuff.c b/src/hu_stuff.c index de6561337771951e80cfc64d41b4aa2d0ec65fce..f6275631ca718d59695e9848df55d72aa8c04805 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1226,9 +1226,9 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I } else { - if (players[tab[i].num].powers[pw_super]) + if (players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS] || players[tab[i].num].mo->state > &states[S_PLAY_SUPER_TRANS9])) { - colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); + colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE); V_DrawSmallMappedPatch (x, y-4, 0, superprefix[players[tab[i].num].skin], colormap); } else diff --git a/src/info.c b/src/info.c index 6b3019781a4a2e02589e3881f51329c78c0a47f4..7d6e1fededd5797f7c8f6043c038f65088e86389 100644 --- a/src/info.c +++ b/src/info.c @@ -301,9 +301,12 @@ char sprnames[NUMSPRITES + 1][5] = // Game Indicators "SCOR", // Score logo "DRWN", // Drowning Timer + "LCKN", // Target "TTAG", // Tag Sign "GFLG", // Got Flag sign + "CORK", + // Ring Weapons "RRNG", // Red Ring "RNGB", // Bounce Ring @@ -390,12 +393,12 @@ char spr2names[NUMPLAYERSPRITES][5] = "WAIT", "WALK", "RUN_", - "PEEL", + "DASH", "PAIN", + "STUN", "DEAD", "DRWN", - "SPIN", - "DASH", + "ROLL", "GASP", "JUMP", "SPNG", @@ -403,8 +406,7 @@ char spr2names[NUMPLAYERSPRITES][5] = "EDGE", "RIDE", - "SIGN", - "LIFE", + "SPIN", "FLY_", "SWIM", @@ -414,32 +416,24 @@ char spr2names[NUMPLAYERSPRITES][5] = "CLNG", "CLMB", + "FLT_", + "FRUN", + + "BNCE", + "BLND", + + "FIRE", + "TWIN", "MLEE", + "MLEL", "TRNS", - "SSTD", - "SWLK", - "SRUN", - "SPEE", - "SPAN", - "SSTN", - "SDTH", - "SDRN", - "SSPN", - "SGSP", - "SJMP", - "SSPG", - "SFAL", - "SEDG", - "SRID", - "SFLT", - - "NTRN", + "NSTD", "NFLT", - "NPAN", + "NSTN", "NPUL", "NATK", @@ -469,7 +463,10 @@ char spr2names[NUMPLAYERSPRITES][5] = "DRL9", "DRLA", "DRLB", - "DRLC" + "DRLC", + + "SIGN", + "LIFE" }; enum playersprite free_spr2 = SPR2_FIRSTFREESLOT; @@ -503,19 +500,22 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_WAIT|FF_ANIMATE, -1, {NULL}, 0, 16, S_NULL}, // S_PLAY_WAIT {SPR_PLAY, SPR2_WALK, 4, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_WALK {SPR_PLAY, SPR2_RUN , 2, {NULL}, 0, 0, S_PLAY_RUN}, // S_PLAY_RUN - {SPR_PLAY, SPR2_PEEL, 2, {NULL}, 0, 0, S_PLAY_PEEL}, // S_PLAY_PEEL + {SPR_PLAY, SPR2_DASH, 2, {NULL}, 0, 0, S_PLAY_DASH}, // S_PLAY_DASH {SPR_PLAY, SPR2_PAIN|FF_ANIMATE, 350, {NULL}, 0, 4, S_PLAY_FALL}, // S_PLAY_PAIN + {SPR_PLAY, SPR2_STUN|FF_ANIMATE, 350, {NULL}, 0, 4, S_PLAY_FALL}, // S_PLAY_STUN {SPR_PLAY, SPR2_DEAD|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_DEAD {SPR_PLAY, SPR2_DRWN|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_DRWN - {SPR_PLAY, SPR2_SPIN, 1, {NULL}, 0, 0, S_PLAY_SPIN}, // S_PLAY_SPIN - {SPR_PLAY, SPR2_DASH, 2, {NULL}, 0, 0, S_PLAY_DASH}, // S_PLAY_DASH + {SPR_PLAY, SPR2_ROLL, 1, {NULL}, 0, 0, S_PLAY_ROLL}, // S_PLAY_ROLL {SPR_PLAY, SPR2_GASP|FF_ANIMATE, 14, {NULL}, 0, 4, S_PLAY_WALK}, // S_PLAY_GASP {SPR_PLAY, SPR2_JUMP, 1, {NULL}, 0, 0, S_PLAY_JUMP}, // S_PLAY_JUMP {SPR_PLAY, SPR2_SPNG, 2, {NULL}, 0, 0, S_PLAY_SPRING}, // S_PLAY_SPRING {SPR_PLAY, SPR2_FALL, 2, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_FALL - {SPR_PLAY, SPR2_EDGE|FF_ANIMATE, -1, {NULL}, 0, 12, S_NULL}, // S_PLAY_EDGE + {SPR_PLAY, SPR2_EDGE, 12, {NULL}, 0, 0, S_PLAY_EDGE}, // S_PLAY_EDGE {SPR_PLAY, SPR2_RIDE, 4, {NULL}, 0, 0, S_PLAY_RIDE}, // S_PLAY_RIDE + // CA2_SPINDASH + {SPR_PLAY, SPR2_SPIN, 2, {NULL}, 0, 0, S_PLAY_SPINDASH}, // S_PLAY_SPINDASH + // CA_FLY/CA_SWIM {SPR_PLAY, SPR2_FLY , 2, {NULL}, 0, 0, S_PLAY_FLY}, // S_PLAY_FLY {SPR_PLAY, SPR2_SWIM, 2, {NULL}, 0, 0, S_PLAY_SWIM}, // S_PLAY_SWIM @@ -526,45 +526,40 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_CLNG|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_CLING {SPR_PLAY, SPR2_CLMB, 5, {NULL}, 0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB + // CA_FLOAT/CA_SLOWFALL + {SPR_PLAY, SPR2_FLT , 7, {NULL}, 0, 0, S_PLAY_FLOAT}, // S_PLAY_FLOAT + {SPR_PLAY, SPR2_FRUN, 7, {NULL}, 0, 0, S_PLAY_FLOAT_RUN}, // S_PLAY_FLOAT_RUN + + // CA_BOUNCE + {SPR_PLAY, SPR2_BNCE|FF_ANIMATE, -1, {NULL}, 0, 0, S_NULL}, // S_PLAY_BOUNCE + {SPR_PLAY, SPR2_BLND|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_BOUNCE, 0, S_PLAY_BOUNCE_LANDING}, // S_PLAY_BOUNCE_LANDING + + // CA2_GUNSLINGER + {SPR_PLAY, SPR2_FIRE|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_FIRE_FINISH, 0, S_PLAY_FIRE}, // S_PLAY_FIRE + {SPR_PLAY, SPR2_FIRE, 15, {NULL}, S_PLAY_STND, 0, S_PLAY_STND}, // S_PLAY_FIRE_FINISH + // CA_TWINSPIN {SPR_PLAY, SPR2_TWIN|FF_SPR2ENDSTATE, 1, {NULL}, S_PLAY_JUMP, 0, S_PLAY_TWINSPIN}, // S_PLAY_TWINSPIN // CA2_MELEE {SPR_PLAY, SPR2_MLEE|FF_SPR2ENDSTATE, 1, {NULL}, S_PLAY_MELEE_FINISH, 0, S_PLAY_MELEE}, // S_PLAY_MELEE - {SPR_PLAY, SPR2_MLEE, 20, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_MELEE_FINISH - - // SF_SUPERANIMS - {SPR_PLAY, SPR2_SSTD|FF_ANIMATE, -1, {NULL}, 0, 7, S_NULL}, // S_PLAY_SUPER_STND - {SPR_PLAY, SPR2_SWLK, 7, {NULL}, 0, 0, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_WALK - {SPR_PLAY, SPR2_SRUN, 7, {NULL}, 0, 0, S_PLAY_SUPER_RUN}, // S_PLAY_SUPER_RUN - {SPR_PLAY, SPR2_SPEE, 7, {NULL}, 0, 0, S_PLAY_SUPER_PEEL}, // S_PLAY_SUPER_PEEL - {SPR_PLAY, SPR2_SPAN|FF_ANIMATE, 350, {NULL}, 0, 4, S_PLAY_SUPER_FALL}, // S_PLAY_SUPER_PAIN - {SPR_PLAY, SPR2_SSTN|FF_ANIMATE, 350, {NULL}, 0, 4, S_PLAY_SUPER_FALL}, // S_PLAY_SUPER_STUN - {SPR_PLAY, SPR2_SDTH|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_SUPER_DEAD - {SPR_PLAY, SPR2_SDRN|FF_ANIMATE, -1, {NULL}, 0, 4, S_NULL}, // S_PLAY_SUPER_DRWN - {SPR_PLAY, SPR2_SSPN, 1, {NULL}, 0, 0, S_PLAY_SUPER_SPIN}, // S_PLAY_SUPER_SPIN - {SPR_PLAY, SPR2_SGSP|FF_ANIMATE, 14, {NULL}, 0, 4, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_GASP - {SPR_PLAY, SPR2_SJMP, 1, {NULL}, 0, 0, S_PLAY_SUPER_JUMP}, // S_PLAY_SUPER_JUMP - {SPR_PLAY, SPR2_SSPG, 2, {NULL}, 0, 0, S_PLAY_SUPER_SPRING}, // S_PLAY_SUPER_SPRING - {SPR_PLAY, SPR2_SFAL, 2, {NULL}, 0, 0, S_PLAY_SUPER_FALL}, // S_PLAY_SUPER_FALL - {SPR_PLAY, SPR2_SEDG|FF_ANIMATE, -1, {NULL}, 0, 12, S_NULL}, // S_PLAY_SUPER_EDGE - {SPR_PLAY, SPR2_SRID, 4, {NULL}, 0, 0, S_PLAY_SUPER_RIDE}, // S_PLAY_SUPER_RIDE - {SPR_PLAY, SPR2_SFLT, 7, {NULL}, 0, 0, S_PLAY_SUPER_FLOAT}, // S_PLAY_SUPER_FLOAT + {SPR_PLAY, SPR2_MLEE, 70, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_MELEE_FINISH + {SPR_PLAY, SPR2_MLEL, 35, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_MELEE_LANDING // SF_SUPER - {SPR_PLAY, SPR2_TRNS, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS2}, // S_PLAY_SUPER_TRANS - {SPR_PLAY, SPR2_TRNS, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS3}, // S_PLAY_SUPER_TRANS2 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS4}, // S_PLAY_SUPER_TRANS3 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS5}, // S_PLAY_SUPER_TRANS4 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS6}, // S_PLAY_SUPER_TRANS5 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS7}, // S_PLAY_SUPER_TRANS6 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS8}, // S_PLAY_SUPER_TRANS7 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS9}, // S_PLAY_SUPER_TRANS8 - {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 16, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_SUPER_TRANS9 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS2}, // S_PLAY_SUPER_TRANS + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS3}, // S_PLAY_SUPER_TRANS2 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS4}, // S_PLAY_SUPER_TRANS3 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS5}, // S_PLAY_SUPER_TRANS4 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS6}, // S_PLAY_SUPER_TRANS5 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS7}, // S_PLAY_SUPER_TRANS6 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS8}, // S_PLAY_SUPER_TRANS7 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS9}, // S_PLAY_SUPER_TRANS8 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 16, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_SUPER_TRANS9 {SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY}, //S_OBJPLACE_DUMMY - // 1-Up Box Sprites (uses player sprite) + // 1-Up box sprites (uses player sprite) {SPR_PLAY, SPR2_LIFE, 2, {NULL}, 0, 16, S_PLAY_BOX2}, // S_PLAY_BOX1 {SPR_NULL, 0, 1, {NULL}, 0, 0, S_PLAY_BOX1}, // S_PLAY_BOX2 {SPR_PLAY, SPR2_LIFE, 4, {NULL}, 0, 4, S_PLAY_ICON2}, // S_PLAY_ICON1 @@ -575,50 +570,50 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_SIGN, 1, {NULL}, 0, 24, S_PLAY_SIGN}, // S_PLAY_SIGN // NiGHTS Player, transforming - {SPR_PLAY, SPR2_NTRN, 4, {A_Scream}, 0, 0, S_PLAY_NIGHTS_TRANS2}, // S_PLAY_NIGHTS_TRANS - {SPR_PLAY, SPR2_NTRN, 4, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS3}, // S_PLAY_NIGHTS_TRANS2 - {SPR_PLAY, SPR2_NTRN|FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS4}, // S_PLAY_NIGHTS_TRANS3 - {SPR_PLAY, SPR2_NTRN, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS5}, // S_PLAY_NIGHTS_TRANS4 - {SPR_PLAY, SPR2_NTRN, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS6}, // S_PLAY_NIGHTS_TRANS5 - {SPR_PLAY, SPR2_NTRN, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS7}, // S_PLAY_NIGHTS_TRANS6 - {SPR_PLAY, SPR2_NTRN, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS8}, // S_PLAY_NIGHTS_TRANS7 - {SPR_PLAY, SPR2_NTRN, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS9}, // S_PLAY_NIGHTS_TRANS8 - {SPR_PLAY, SPR2_NTRN, 16, {NULL}, 0, 0, S_PLAY_NIGHTS_FLOAT}, // S_PLAY_NIGHTS_TRANS9 - - // NiGHTS Player, Stand, Floating, Pain, Pull and Attack - {SPR_PLAY, SPR2_NSTD, 7, {NULL}, 0, 0, S_PLAY_NIGHTS_STAND}, // S_PLAY_NIGHTS_STAND - {SPR_PLAY, SPR2_NFLT, 7, {NULL}, 0, 0, S_PLAY_NIGHTS_FLOAT}, // S_PLAY_NIGHTS_FLOAT - {SPR_PLAY, SPR2_NPAN, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_PAIN}, // S_PLAY_NIGHTS_PAIN - {SPR_PLAY, SPR2_NPUL, 1, {NULL}, 0, 0, S_PLAY_NIGHTS_PULL}, // S_PLAY_NIGHTS_PULL + {SPR_PLAY, SPR2_TRNS, 4, {A_Scream}, 0, 0, S_PLAY_NIGHTS_TRANS2}, // S_PLAY_NIGHTS_TRANS + {SPR_PLAY, SPR2_TRNS, 4, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS3}, // S_PLAY_NIGHTS_TRANS2 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS4}, // S_PLAY_NIGHTS_TRANS3 + {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS5}, // S_PLAY_NIGHTS_TRANS4 + {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS6}, // S_PLAY_NIGHTS_TRANS5 + {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS7}, // S_PLAY_NIGHTS_TRANS6 + {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS8}, // S_PLAY_NIGHTS_TRANS7 + {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS9}, // S_PLAY_NIGHTS_TRANS8 + {SPR_PLAY, SPR2_TRNS, 16, {NULL}, 0, 0, S_PLAY_NIGHTS_FLOAT}, // S_PLAY_NIGHTS_TRANS9 + + // NiGHTS Player, stand, float, pain, pull and attack + {SPR_PLAY, SPR2_NSTD, 7, {NULL}, 0, 0, S_PLAY_NIGHTS_STAND}, // S_PLAY_NIGHTS_STAND + {SPR_PLAY, SPR2_NFLT, 7, {NULL}, 0, 0, S_PLAY_NIGHTS_FLOAT}, // S_PLAY_NIGHTS_FLOAT + {SPR_PLAY, SPR2_NSTN, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_STUN}, // S_PLAY_NIGHTS_STUN + {SPR_PLAY, SPR2_NPUL, 1, {NULL}, 0, 0, S_PLAY_NIGHTS_PULL}, // S_PLAY_NIGHTS_PULL {SPR_PLAY, SPR2_NATK, 1, {NULL}, 0, 0, S_PLAY_NIGHTS_ATTACK}, // S_PLAY_NIGHTS_ATTACK - // NiGHTS Player, Flying and Drilling - {SPR_PLAY, SPR2_NGT0, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY0}, // S_PLAY_NIGHTS_FLY0 - {SPR_PLAY, SPR2_DRL0, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL0}, // S_PLAY_NIGHTS_DRILL0 - {SPR_PLAY, SPR2_NGT1, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY1}, // S_PLAY_NIGHTS_FLY1 - {SPR_PLAY, SPR2_DRL1, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL1}, // S_PLAY_NIGHTS_DRILL1 - {SPR_PLAY, SPR2_NGT2, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY2}, // S_PLAY_NIGHTS_FLY2 - {SPR_PLAY, SPR2_DRL2, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL2}, // S_PLAY_NIGHTS_DRILL2 - {SPR_PLAY, SPR2_NGT3, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY3}, // S_PLAY_NIGHTS_FLY3 - {SPR_PLAY, SPR2_DRL3, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL3}, // S_PLAY_NIGHTS_DRILL3 - {SPR_PLAY, SPR2_NGT4, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY4}, // S_PLAY_NIGHTS_FLY4 - {SPR_PLAY, SPR2_DRL4, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL4}, // S_PLAY_NIGHTS_DRILL4 - {SPR_PLAY, SPR2_NGT5, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY5}, // S_PLAY_NIGHTS_FLY5 - {SPR_PLAY, SPR2_DRL5, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL5}, // S_PLAY_NIGHTS_DRILL5 - {SPR_PLAY, SPR2_NGT6, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY6}, // S_PLAY_NIGHTS_FLY6 - {SPR_PLAY, SPR2_DRL6, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL6}, // S_PLAY_NIGHTS_DRILL6 - {SPR_PLAY, SPR2_NGT7, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY7}, // S_PLAY_NIGHTS_FLY7 - {SPR_PLAY, SPR2_DRL7, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL7}, // S_PLAY_NIGHTS_DRILL7 - {SPR_PLAY, SPR2_NGT8, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY8}, // S_PLAY_NIGHTS_FLY8 - {SPR_PLAY, SPR2_DRL8, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL8}, // S_PLAY_NIGHTS_DRILL8 - {SPR_PLAY, SPR2_NGT9, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY9}, // S_PLAY_NIGHTS_FLY9 - {SPR_PLAY, SPR2_DRL9, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL9}, // S_PLAY_NIGHTS_DRILL9 - {SPR_PLAY, SPR2_NGTA, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLYA}, // S_PLAY_NIGHTS_FLYA - {SPR_PLAY, SPR2_DRLA, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILLA}, // S_PLAY_NIGHTS_DRILLA - {SPR_PLAY, SPR2_NGTB, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLYB}, // S_PLAY_NIGHTS_FLYB - {SPR_PLAY, SPR2_DRLB, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILLB}, // S_PLAY_NIGHTS_DRILLB - {SPR_PLAY, SPR2_NGTC, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLYC}, // S_PLAY_NIGHTS_FLYC - {SPR_PLAY, SPR2_DRLC, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILLC}, // S_PLAY_NIGHTS_DRILLC + // NiGHTS Player, flying and drilling + {SPR_PLAY, SPR2_NGT0, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY0}, // S_PLAY_NIGHTS_FLY0 + {SPR_PLAY, SPR2_DRL0, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL0}, // S_PLAY_NIGHTS_DRILL0 + {SPR_PLAY, SPR2_NGT1, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY1}, // S_PLAY_NIGHTS_FLY1 + {SPR_PLAY, SPR2_DRL1, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL1}, // S_PLAY_NIGHTS_DRILL1 + {SPR_PLAY, SPR2_NGT2, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY2}, // S_PLAY_NIGHTS_FLY2 + {SPR_PLAY, SPR2_DRL2, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL2}, // S_PLAY_NIGHTS_DRILL2 + {SPR_PLAY, SPR2_NGT3, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY3}, // S_PLAY_NIGHTS_FLY3 + {SPR_PLAY, SPR2_DRL3, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL3}, // S_PLAY_NIGHTS_DRILL3 + {SPR_PLAY, SPR2_NGT4, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY4}, // S_PLAY_NIGHTS_FLY4 + {SPR_PLAY, SPR2_DRL4, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL4}, // S_PLAY_NIGHTS_DRILL4 + {SPR_PLAY, SPR2_NGT5, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY5}, // S_PLAY_NIGHTS_FLY5 + {SPR_PLAY, SPR2_DRL5, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL5}, // S_PLAY_NIGHTS_DRILL5 + {SPR_PLAY, SPR2_NGT6, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY6}, // S_PLAY_NIGHTS_FLY6 + {SPR_PLAY, SPR2_DRL6, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL6}, // S_PLAY_NIGHTS_DRILL6 + {SPR_PLAY, SPR2_NGT7, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY7}, // S_PLAY_NIGHTS_FLY7 + {SPR_PLAY, SPR2_DRL7, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL7}, // S_PLAY_NIGHTS_DRILL7 + {SPR_PLAY, SPR2_NGT8, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY8}, // S_PLAY_NIGHTS_FLY8 + {SPR_PLAY, SPR2_DRL8, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL8}, // S_PLAY_NIGHTS_DRILL8 + {SPR_PLAY, SPR2_NGT9, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLY9}, // S_PLAY_NIGHTS_FLY9 + {SPR_PLAY, SPR2_DRL9, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILL9}, // S_PLAY_NIGHTS_DRILL9 + {SPR_PLAY, SPR2_NGTA, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLYA}, // S_PLAY_NIGHTS_FLYA + {SPR_PLAY, SPR2_DRLA, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILLA}, // S_PLAY_NIGHTS_DRILLA + {SPR_PLAY, SPR2_NGTB, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLYB}, // S_PLAY_NIGHTS_FLYB + {SPR_PLAY, SPR2_DRLB, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILLB}, // S_PLAY_NIGHTS_DRILLB + {SPR_PLAY, SPR2_NGTC, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_FLYC}, // S_PLAY_NIGHTS_FLYC + {SPR_PLAY, SPR2_DRLC, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_DRILLC}, // S_PLAY_NIGHTS_DRILLC // Blue Crawla {SPR_POSS, 0, 5, {A_Look}, 0, 0, S_POSS_STND}, // S_POSS_STND @@ -2535,13 +2530,17 @@ state_t states[NUMSTATES] = {SPR_DRWN, 10, 40, {NULL}, 0, 0, S_NULL}, // S_FOUR2 {SPR_DRWN, 11, 40, {NULL}, 0, 0, S_NULL}, // S_FIVE2 - {SPR_TTAG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_TTAG1 + {SPR_LCKN, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON1 + {SPR_LCKN, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON2 + + {SPR_TTAG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_TTAG // CTF Sign - {SPR_GFLG, 0, 1, {NULL}, 0, 0, S_GOTFLAG2}, // S_GOTFLAG1 - {SPR_GFLG, 1, 1, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG2 - {SPR_GFLG, 0, 1, {NULL}, 0, 0, S_GOTFLAG4}, // S_GOTFLAG3 - {SPR_GFLG, 2, 1, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG4 + {SPR_GFLG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG + {SPR_GFLG, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTREDFLAG + {SPR_GFLG, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTBLUEFLAG + + {SPR_CORK, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORK // Red Rings (thrown) {SPR_RRNG, FF_FULLBRIGHT, 1, {A_ThrownRing}, 0, 0, S_RRNG2}, // S_RRNG1 @@ -3062,7 +3061,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MT_THOK, // painchance sfx_None, // painsound S_NULL, // meleestate - S_PLAY_SPIN, // missilestate + S_PLAY_ROLL, // missilestate S_PLAY_DEAD, // deathstate S_PLAY_DRWN, // xdeathstate sfx_None, // deathsound @@ -4581,7 +4580,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 30*FRACUNIT, // speed 11*FRACUNIT, // radius 8*FRACUNIT, // height - 0, // display offset + 100, // display offset 100, // mass 0, // damage sfx_None, // activesound @@ -7127,7 +7126,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_ATTRACT_ICON1, // spawnstate 1, // spawnhealth S_NULL, // seestate - sfx_s3k41, // seesound + sfx_attrsg, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate @@ -12032,7 +12031,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8, // speed 8*FRACUNIT, // radius 8*FRACUNIT, // height - 0, // display offset + 113, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -12059,7 +12058,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8, // speed 8*FRACUNIT, // radius 16*FRACUNIT, // height - 0, // display offset + 112, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -12067,9 +12066,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_TAG + { // MT_LOCKON -1, // doomednum - S_TTAG1, // spawnstate + S_LOCKON1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -12086,17 +12085,17 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8, // speed 16*FRACUNIT, // radius 32*FRACUNIT, // height - 0, // display offset + 111, // display offset 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags S_NULL // raisestate }, - { // MT_GOTFLAG + { // MT_TAG -1, // doomednum - S_GOTFLAG1, // spawnstate + S_TTAG, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -12111,9 +12110,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 8, // speed - 64*FRACUNIT, // radius + 16*FRACUNIT, // radius 32*FRACUNIT, // height - 0, // display offset + 111, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -12121,9 +12120,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_GOTFLAG2 + { // MT_GOTFLAG -1, // doomednum - S_GOTFLAG3, // spawnstate + S_GOTFLAG, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -12140,7 +12139,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 8, // speed 64*FRACUNIT, // radius 32*FRACUNIT, // height - 0, // display offset + 111, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -12426,6 +12425,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_CORK + -1, // doomednum + S_CORK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_corkp, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_SMOKE1, // deathstate + S_NULL, // xdeathstate + sfx_corkh, // deathsound + 60*FRACUNIT, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_REDRING -1, // doomednum S_RRNG1, // spawnstate diff --git a/src/info.h b/src/info.h index 0cca7896e8ccde82d10f5ac0ee31785b9cbdcc64..4b21e98ec43e234283dfbe441d399257063df869 100644 --- a/src/info.h +++ b/src/info.h @@ -450,7 +450,7 @@ typedef enum sprite SPR_ARMB, // Armageddon Shield Ring, Back SPR_WIND, // Whirlwind Shield Orb SPR_MAGN, // Attract Shield Orb - SPR_ELEM, // Elemental Shield Orb and Fire + SPR_ELEM, // Elemental Shield Orb SPR_FORC, // Force Shield Orb SPR_PITY, // Pity Shield Orb SPR_FIRS, // Flame Shield Orb @@ -507,9 +507,12 @@ typedef enum sprite // Game Indicators SPR_SCOR, // Score logo SPR_DRWN, // Drowning Timer + SPR_LCKN, // Target SPR_TTAG, // Tag Sign SPR_GFLG, // Got Flag sign + SPR_CORK, + // Ring Weapons SPR_RRNG, // Red Ring SPR_RNGB, // Bounce Ring @@ -594,21 +597,21 @@ typedef enum sprite NUMSPRITES } spritenum_t; -// Make sure to be conscious of FF_FRAMEMASK whenever you change this table. -// Currently, FF_FRAMEMASK is 0x1ff, or 511 - and NUMSPRITEFREESLOTS is 256. -// Since this is zero-based, there can be at most 256 different SPR2_'s without changing that. +// Make sure to be conscious of FF_FRAMEMASK and the fact sprite2 is stored as a UINT8 whenever you change this table. +// Currently, FF_FRAMEMASK is 0xff, or 255 - but the second half is used by FF_SPR2SUPER, so the limitation is 0x7f. +// Since this is zero-based, there can be at most 128 different SPR2_'s without changing that. enum playersprite { SPR2_STND = 0, SPR2_WAIT, SPR2_WALK, SPR2_RUN , - SPR2_PEEL, + SPR2_DASH, SPR2_PAIN, + SPR2_STUN, SPR2_DEAD, SPR2_DRWN, // drown - SPR2_SPIN, - SPR2_DASH, // spindash charge + SPR2_ROLL, SPR2_GASP, SPR2_JUMP, SPR2_SPNG, // spring @@ -616,8 +619,7 @@ enum playersprite SPR2_EDGE, SPR2_RIDE, - SPR2_SIGN, // end sign head - SPR2_LIFE, // life monitor icon + SPR2_SPIN, // spindash SPR2_FLY , SPR2_SWIM, @@ -627,36 +629,28 @@ enum playersprite SPR2_CLNG, // cling SPR2_CLMB, // climb + SPR2_FLT , // float + SPR2_FRUN, // float run + + SPR2_BNCE, // bounce + SPR2_BLND, // bounce landing + + SPR2_FIRE, // fire + SPR2_TWIN, // twinspin SPR2_MLEE, // melee + SPR2_MLEL, // melee land + + SPR2_TRNS, // transformation - SPR2_TRNS, // super transformation - SPR2_SSTD, // super stand - SPR2_SWLK, // super walk - SPR2_SRUN, // super run - SPR2_SPEE, // super peelout - SPR2_SPAN, // super pain - SPR2_SSTN, // super stun - SPR2_SDTH, // super death - SPR2_SDRN, // super drown - SPR2_SSPN, // super spin - SPR2_SGSP, // super gasp - SPR2_SJMP, // super jump - SPR2_SSPG, // super spring - SPR2_SFAL, // super fall - SPR2_SEDG, // super edge - SPR2_SRID, // super ride - SPR2_SFLT, // super float - - SPR2_NTRN, // NiGHTS transformation SPR2_NSTD, // NiGHTS stand SPR2_NFLT, // NiGHTS float - SPR2_NPAN, // NiGHTS pain + SPR2_NSTN, // NiGHTS stun SPR2_NPUL, // NiGHTS pull SPR2_NATK, // NiGHTS attack - // NiGHTS flight. + // NiGHTS flight SPR2_NGT0, SPR2_NGT1, SPR2_NGT2, @@ -671,7 +665,7 @@ enum playersprite SPR2_NGTB, SPR2_NGTC, - // NiGHTS drill. + // NiGHTS drill SPR2_DRL0, SPR2_DRL1, SPR2_DRL2, @@ -686,8 +680,11 @@ enum playersprite SPR2_DRLB, SPR2_DRLC, + SPR2_SIGN, // end sign head + SPR2_LIFE, // life monitor icon + SPR2_FIRSTFREESLOT, - SPR2_LASTFREESLOT = SPR2_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1, + SPR2_LASTFREESLOT = 0x7f, NUMPLAYERSPRITES }; @@ -713,19 +710,22 @@ typedef enum state S_PLAY_WAIT, S_PLAY_WALK, S_PLAY_RUN, - S_PLAY_PEEL, + S_PLAY_DASH, S_PLAY_PAIN, + S_PLAY_STUN, S_PLAY_DEAD, S_PLAY_DRWN, - S_PLAY_SPIN, - S_PLAY_DASH, + S_PLAY_ROLL, S_PLAY_GASP, - S_PLAY_JUMP, // spin jump + S_PLAY_JUMP, S_PLAY_SPRING, S_PLAY_FALL, S_PLAY_EDGE, S_PLAY_RIDE, + // CA2_SPINDASH + S_PLAY_SPINDASH, + // CA_FLY/SWIM S_PLAY_FLY, S_PLAY_SWIM, @@ -736,30 +736,25 @@ typedef enum state S_PLAY_CLING, S_PLAY_CLIMB, + // CA_FLOAT/CA_SLOWFALL + S_PLAY_FLOAT, + S_PLAY_FLOAT_RUN, + + // CA_BOUNCE + S_PLAY_BOUNCE, + S_PLAY_BOUNCE_LANDING, + + // CA2_GUNSLINGER + S_PLAY_FIRE, + S_PLAY_FIRE_FINISH, + // CA_TWINSPIN S_PLAY_TWINSPIN, // CA2_MELEE S_PLAY_MELEE, S_PLAY_MELEE_FINISH, - - // SF_SUPERANIMS - S_PLAY_SUPER_STND, - S_PLAY_SUPER_WALK, - S_PLAY_SUPER_RUN, - S_PLAY_SUPER_PEEL, - S_PLAY_SUPER_PAIN, - S_PLAY_SUPER_STUN, - S_PLAY_SUPER_DEAD, - S_PLAY_SUPER_DRWN, - S_PLAY_SUPER_SPIN, - S_PLAY_SUPER_GASP, - S_PLAY_SUPER_JUMP, // see note above - S_PLAY_SUPER_SPRING, - S_PLAY_SUPER_FALL, - S_PLAY_SUPER_EDGE, - S_PLAY_SUPER_RIDE, - S_PLAY_SUPER_FLOAT, + S_PLAY_MELEE_LANDING, // SF_SUPER S_PLAY_SUPER_TRANS, @@ -798,7 +793,7 @@ typedef enum state S_PLAY_NIGHTS_STAND, S_PLAY_NIGHTS_FLOAT, - S_PLAY_NIGHTS_PAIN, + S_PLAY_NIGHTS_STUN, S_PLAY_NIGHTS_PULL, S_PLAY_NIGHTS_ATTACK, @@ -2725,14 +2720,18 @@ typedef enum state S_FOUR2, S_FIVE2, + S_LOCKON1, + S_LOCKON2, + // Tag Sign - S_TTAG1, + S_TTAG, // Got Flag Sign - S_GOTFLAG1, - S_GOTFLAG2, - S_GOTFLAG3, - S_GOTFLAG4, + S_GOTFLAG, + S_GOTREDFLAG, + S_GOTBLUEFLAG, + + S_CORK, // Red Ring S_RRNG1, @@ -3542,9 +3541,9 @@ typedef enum mobj_type MT_SCORE, // score logo MT_DROWNNUMBERS, // Drowning Timer MT_GOTEMERALD, // Chaos Emerald (intangible) + MT_LOCKON, // Target MT_TAG, // Tag Sign MT_GOTFLAG, // Got Flag sign - MT_GOTFLAG2, // Got Flag sign // Ambient Sounds MT_AWATERA, // Ambient Water Sound 1 @@ -3558,6 +3557,8 @@ typedef enum mobj_type MT_RANDOMAMBIENT, MT_RANDOMAMBIENT2, + MT_CORK, + // Ring Weapons MT_REDRING, MT_BOUNCERING, diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 4d48521cab4a26de0c75e8a75366b44fe242226c..71f6a7e655d9aaa0f96f54fa72cbe51f1ef02e80 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -445,10 +445,32 @@ static int lib_pIsValidSprite2(lua_State *L) INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); - lua_pushboolean(L, (mobj->skin && (((skin_t *)mobj->skin)->sprites[spr2].numframes > 0))); + lua_pushboolean(L, (mobj->skin && (((skin_t *)mobj->skin)->sprites[spr2].numframes))); return 1; } +// P_SpawnLockOn doesn't exist either, but we want to expose making a local mobj without encouraging hacks. + +static int lib_pSpawnLockOn(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + mobj_t *lockon = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + statenum_t state = luaL_checkinteger(L, 3); + NOHUD + INLEVEL + if (!lockon) + return LUA_ErrInvalid(L, "mobj_t"); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + if (player == &players[consoleplayer] || player == &players[secondarydisplayplayer] || player == &players[displayplayer]) // Only display it on your own view. + { + mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + visual->target = lockon; + P_SetMobjStateNF(visual, state); + } + return 0; +} + static int lib_pSpawnMissile(lua_State *L) { mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -793,6 +815,17 @@ static int lib_pStealPlayerScore(lua_State *L) return 0; } +static int lib_pGetJumpFlags(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + NOHUD + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + lua_pushinteger(L, P_GetJumpFlags(player)); + return 1; +} + static int lib_pPlayerInPain(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -1055,11 +1088,12 @@ static int lib_pLookForEnemies(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); boolean nonenemies = lua_opttrueboolean(L, 2); + boolean bullet = lua_optboolean(L, 3); NOHUD INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); - lua_pushboolean(L, P_LookForEnemies(player, nonenemies)); + LUA_PushUserdata(L, P_LookForEnemies(player, nonenemies, bullet), META_MOBJ); return 1; } @@ -2327,6 +2361,7 @@ static luaL_Reg lib[] = { {"P_SpawnMobj",lib_pSpawnMobj}, {"P_RemoveMobj",lib_pRemoveMobj}, {"P_IsValidSprite2", lib_pIsValidSprite2}, + {"P_SpawnLockOn", lib_pSpawnLockOn}, {"P_SpawnMissile",lib_pSpawnMissile}, {"P_SpawnXYZMissile",lib_pSpawnXYZMissile}, {"P_SpawnPointMissile",lib_pSpawnPointMissile}, @@ -2354,6 +2389,7 @@ static luaL_Reg lib[] = { {"P_GetPlayerControlDirection",lib_pGetPlayerControlDirection}, {"P_AddPlayerScore",lib_pAddPlayerScore}, {"P_StealPlayerScore",lib_pStealPlayerScore}, + {"P_GetJumpFlags",lib_pGetJumpFlags}, {"P_PlayerInPain",lib_pPlayerInPain}, {"P_DoPlayerPain",lib_pDoPlayerPain}, {"P_ResetPlayer",lib_pResetPlayer}, diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 93febf209424fb616c69c503c6b405946415dbd0..2fcccab6683052b927dcbaed7d3284e8515ba49c 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -511,7 +511,8 @@ static int mobj_set(lua_State *L) for (i = 0; i < numskins; i++) if (fastcmp(skins[i].name, skin)) { - mo->skin = &skins[i]; + if (!mo->player || R_SkinUsable(mo->player-players, i)) + mo->skin = &skins[i]; return 0; } return luaL_error(L, "mobj.skin '%s' not found!", skin); diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 0900528ed016ab0b62b013392805361af2d6e5d3..6223094257320dd62cd2f6dc12673c922e47b818 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -194,8 +194,6 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->gotcontinue); else if (fastcmp(field,"speed")) lua_pushfixed(L, plr->speed); - else if (fastcmp(field,"jumping")) - lua_pushboolean(L, plr->jumping); else if (fastcmp(field,"secondjump")) lua_pushinteger(L, plr->secondjump); else if (fastcmp(field,"fly1")) @@ -459,8 +457,6 @@ static int player_set(lua_State *L) plr->gotcontinue = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"speed")) plr->speed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"jumping")) - plr->jumping = luaL_checkboolean(L, 3); else if (fastcmp(field,"secondjump")) plr->secondjump = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"fly1")) diff --git a/src/m_cheat.c b/src/m_cheat.c index ce95197990a07a2d5075941ff7aaef048c88bfef..8ae6706621de55902c60aaec540a288695a8ef8b 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -942,7 +942,7 @@ boolean OP_FreezeObjectplace(void) if (!objectplacing) return false; - if ((maptol & TOL_NIGHTS) && (players[consoleplayer].pflags & PF_NIGHTSMODE)) + if ((maptol & TOL_NIGHTS) && (players[consoleplayer].powers[pw_carry] == CR_NIGHTSMODE)) return false; return true; @@ -1255,7 +1255,7 @@ void Command_ObjectPlace_f(void) { objectplacing = true; - if ((players[0].pflags & PF_NIGHTSMODE)) + if ((players[0].powers[pw_carry] == CR_NIGHTSMODE)) return; if (!COM_CheckParm("-silent")) @@ -1326,7 +1326,7 @@ void Command_ObjectPlace_f(void) // Don't touch the NiGHTS Objectplace stuff. // ... or if the mo mysteriously vanished. - if (!players[0].mo || (players[0].pflags & PF_NIGHTSMODE)) + if (!players[0].mo || (players[0].powers[pw_carry] == CR_NIGHTSMODE)) return; // If still in dummy state, get out of it. diff --git a/src/m_menu.c b/src/m_menu.c index cec55fa726cdc7c7048a6249b3881e4ad42d9791..fb8aeedad1252f9c733b5e94ba5cfd7ed030e18f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -109,41 +109,45 @@ typedef enum const char *quitmsg[NUM_QUITMESSAGES]; // Stuff for customizing the player select screen Tails 09-22-2003 +// A rare case. +// External files modify this menu, so we can't call it static. +// And I'm too lazy to go through and rename it everywhere. ARRGH! description_t description[32] = { - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0}, - {"???", "", "", 0, 0, 0} + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0}, + {false, "???", "", "", 0, 0} }; +static INT16 char_on = 0; static char *char_notes = NULL; static fixed_t char_scroll = 0; @@ -171,7 +175,6 @@ static saveinfo_t savegameinfo[MAXSAVEGAMES]; // Extra info about the save games INT16 startmap; // Mario, NiGHTS, or just a plain old normal game? static INT16 itemOn = 1; // menu item skull is on, Hack by Tails 09-18-2002 -static boolean lastdirection = true; // toaster - Only You Can Prevent Hacks - true is for forward, false is for backwards static INT16 skullAnimCounter = 10; // skull animation counter static boolean setupcontrols_secondaryplayer; @@ -272,6 +275,7 @@ static void M_ChooseNightsAttack(INT32 choice); static void M_ModeAttackRetry(INT32 choice); static void M_ModeAttackEndGame(INT32 choice); static void M_SetGuestReplay(INT32 choice); +static void M_HandleChoosePlayerMenu(INT32 choice); static void M_ChoosePlayer(INT32 choice); menu_t SP_GameStatsDef, SP_LevelStatsDef; static menu_t SP_TimeAttackDef, SP_ReplayDef, SP_GuestReplayDef, SP_GhostDef; @@ -764,7 +768,7 @@ static menuitem_t SP_TimeAttackMenu[] = enum { - talevelback, + talevel, taplayer, taguest, @@ -862,7 +866,7 @@ static menuitem_t SP_NightsAttackMenu[] = enum { - nalevelback, + nalevel, narecords, naguest, @@ -882,43 +886,10 @@ static menuitem_t SP_LevelStatsMenu[] = {IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleLevelStats, 0}, // dummy menuitem for the control func }; -// A rare case. -// External files modify this menu, so we can't call it static. -// And I'm too lazy to go through and rename it everywhere. ARRGH! -menuitem_t PlayerMenu[32] = -{ - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0}, - {IT_DISABLED, NULL, NULL, M_ChoosePlayer, 0} +// Player menu dummy +static menuitem_t SP_PlayerMenu[] = +{ + {IT_NOTHING | IT_KEYHANDLER, NULL, "", M_HandleChoosePlayerMenu, 0}, // dummy menuitem for the control func }; // ----------------------------------- @@ -1681,9 +1652,9 @@ static menu_t SP_NightsGhostDef = menu_t SP_PlayerDef = { "M_PICKP", - sizeof (PlayerMenu)/sizeof (menuitem_t),//player_end, + sizeof (SP_PlayerMenu)/sizeof (menuitem_t), &SP_MainDef, - PlayerMenu, + SP_PlayerMenu, M_DrawSetupChoosePlayerMenu, 24, 32, 0, @@ -2170,8 +2141,6 @@ static boolean M_ChangeStringCvar(INT32 choice) static void M_NextOpt(void) { INT16 oldItemOn = itemOn; // prevent infinite loop - lastdirection = true; - do { if (itemOn + 1 > currentMenu->numitems - 1) @@ -2184,8 +2153,6 @@ static void M_NextOpt(void) static void M_PrevOpt(void) { INT16 oldItemOn = itemOn; // prevent infinite loop - lastdirection = false; - do { if (!itemOn) @@ -2456,8 +2423,7 @@ boolean M_Responder(event_t *ev) case KEY_DOWNARROW: M_NextOpt(); S_StartSound(NULL, sfx_menu1); - if (currentMenu == &SP_PlayerDef - || currentMenu == &MISC_ChangeGameTypeDef) + if (currentMenu == &MISC_ChangeGameTypeDef) { Z_Free(char_notes); char_notes = NULL; @@ -2467,8 +2433,7 @@ boolean M_Responder(event_t *ev) case KEY_UPARROW: M_PrevOpt(); S_StartSound(NULL, sfx_menu1); - if (currentMenu == &SP_PlayerDef - || currentMenu == &MISC_ChangeGameTypeDef) + if (currentMenu == &MISC_ChangeGameTypeDef) { Z_Free(char_notes); char_notes = NULL; @@ -3537,7 +3502,7 @@ static void M_PatchSkinNameTable(void) for (j = 0; j < MAXSKINS; j++) { - if (skins[j].name[0] != '\0' && R_SkinUnlock(j)) + if (skins[j].name[0] != '\0' && R_SkinUsable(-1, j)) { skins_cons_t[j].strvalue = skins[j].realname; skins_cons_t[j].value = j+1; @@ -5380,19 +5345,19 @@ static void M_SetupChoosePlayer(INT32 choice) UINT8 i; UINT8 firstvalid = 255; UINT8 lastvalid = 0; + boolean allowed = false; char *name; (void)choice; - if (PlayerMenu[0].status & (IT_DYBIGSPACE)) // Correcting a hack that may be made below. - PlayerMenu[0].status = (IT_DISABLED|(PlayerMenu[0].status & IT_CENTER)); + SP_PlayerMenu[0].status &= ~IT_DYBIGSPACE; // Correcting a hack that may be made below. for (i = 0; i < 32; i++) // Handle charsels, availability, and unlocks. { - if (PlayerMenu[i].status != IT_DISABLED) // If the character's disabled through SOC, there's nothing we can do for it. + if (description[i].used) // If the character's disabled through SOC, there's nothing we can do for it. { name = strtok(Z_StrDup(description[i].skinname), "&"); skinnum = R_SkinAvailable(name); - if ((skinnum != -1) && (R_SkinUnlock(skinnum))) + if ((skinnum != -1) && (R_SkinUsable(-1, skinnum))) { // Handling order. if (firstvalid == 255) @@ -5404,14 +5369,13 @@ static void M_SetupChoosePlayer(INT32 choice) } lastvalid = i; - // Handling visibility. - if (PlayerMenu[i].status & (IT_DISABLED|IT_CENTER)) - PlayerMenu[i].status = IT_CALL; + if (i == char_on) + allowed = true; + if (description[i].picname[0] == '\0') strncpy(description[i].picname, skins[skinnum].charsel, 8); } - else // Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. - PlayerMenu[i].status = (IT_DISABLED|IT_CENTER); + // else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. Z_Free(name); } } @@ -5427,7 +5391,7 @@ static void M_SetupChoosePlayer(INT32 choice) } else // We're being forced into a specific character, so might as well. { - PlayerMenu[0].status = (IT_CALL|IT_DYBIGSPACE|(PlayerMenu[0].status & IT_CENTER)); // This is a hack to make a non-IT_CALL character in slot 0 not softlock the game. IT_DYBIGSPACE is a dummy flag, whilst IT_CENTER is preserved. + SP_PlayerMenu[0].status |= IT_DYBIGSPACE; // This is a dummy flag hack to make a non-IT_CALL character in slot 0 not softlock the game. M_ChoosePlayer(0); return; } @@ -5441,9 +5405,77 @@ static void M_SetupChoosePlayer(INT32 choice) SP_PlayerDef.prevMenu = currentMenu; M_SetupNextMenu(&SP_PlayerDef); - char_scroll = itemOn*128*FRACUNIT; // finish scrolling the menu + if (!allowed) + char_on = firstvalid; + char_scroll = 0; // finish scrolling the menu Z_Free(char_notes); - char_notes = NULL; + char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[char_on].notes); +} + +// +// M_HandleChoosePlayerMenu +// +// Reacts to your key inputs. Basically a mini menu thinker. +// +static void M_HandleChoosePlayerMenu(INT32 choice) +{ + boolean exitmenu = false; // exit to previous menu + INT32 selectval; + + switch (choice) + { + case KEY_DOWNARROW: + if ((selectval = description[char_on].next) != char_on) + { + S_StartSound(NULL,sfx_s3kb7); + char_on = selectval; + char_scroll = -128*FRACUNIT; + Z_Free(char_notes); + char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[char_on].notes); + } + else if (!char_scroll) + { + S_StartSound(NULL,sfx_s3kb7); + char_scroll = 16*FRACUNIT; + } + break; + + case KEY_UPARROW: + if ((selectval = description[char_on].prev) != char_on) + { + S_StartSound(NULL,sfx_s3kb7); + char_on = selectval; + char_scroll = 128*FRACUNIT; + Z_Free(char_notes); + char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[char_on].notes); + } + else if (!char_scroll) + { + S_StartSound(NULL,sfx_s3kb7); + char_scroll = -16*FRACUNIT; + } + break; + + case KEY_ENTER: + S_StartSound(NULL, sfx_menu1); + M_ChoosePlayer(char_on); + break; + + case KEY_ESCAPE: + exitmenu = true; + break; + + default: + break; + } + + if (exitmenu) + { + if (currentMenu->prevMenu) + M_SetupNextMenu(currentMenu->prevMenu); + else + M_ClearMenus(true); + } } // Draw the choose player setup menu, had some fun with player anim @@ -5453,7 +5485,6 @@ static void M_DrawSetupChoosePlayerMenu(void) patch_t *patch; INT32 i, o; UINT8 prev, next; - boolean loophack = false; // Black BG V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); @@ -5462,37 +5493,20 @@ static void M_DrawSetupChoosePlayerMenu(void) // Character select profile images!1 M_DrawTextBox(0, my, 16, 20); - i = (itemOn*128 - (char_scroll / FRACUNIT)); - - if (!char_notes) - { - if (i) // turns out this and the preceding check is better then (abs(i) > 128) - { - o = (lastdirection) ? -1 : 1; - char_scroll = (itemOn + o)*128*FRACUNIT; - i = -o*128; - } - char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[itemOn].notes); - } - - if (abs(i) > 1) - char_scroll += i*FRACUNIT>>2; + if (abs(char_scroll) > FRACUNIT) + char_scroll -= (char_scroll>>2); else // close enough. - char_scroll = itemOn*128*FRACUNIT; // just be exact now. + char_scroll = 0; // just be exact now. - o = ((char_scroll / FRACUNIT) + 16); + o = (char_scroll >> FRACBITS) + 16; - if (o < 0) // This hack is to prevent visual glitches when looping from the last character to the 1st character. - loophack = true; - - if (loophack) + if (o < 0) // A little hacky... + { + i = description[char_on].prev; o += 128; - - i = (o / 128); - o = (o % 128); - - if (loophack) - i = description[i].prev; + } + else + i = char_on; // Get prev character... prev = description[i].prev; @@ -5503,7 +5517,7 @@ static void M_DrawSetupChoosePlayerMenu(void) next = description[i].next; // Draw prev character if it's visible and its number isn't greater than the current one or there's more than two - if (o < 32) // (prev != i) was previously a part of this, but we don't need to check again after above. + if (o < 32) { patch = W_CachePatchName(description[prev].picname, PU_CACHE); if (SHORT(patch->width) >= 256) @@ -5523,31 +5537,24 @@ static void M_DrawSetupChoosePlayerMenu(void) V_DrawCroppedPatch(8<<FRACBITS, (my + 168 - o)<<FRACBITS, FRACUNIT, 0, patch, 0, 0, SHORT(patch->width), o); W_UnlockCachedPatch(patch); } - - // current character - if (PlayerMenu[i].status & IT_DISABLED) // Prevent flickering. - i = (lastdirection) ? prev : next; // This actually causes duplication at slow scroll speeds (<16FU per tic), but thankfully we always go quickly. } - if (!(PlayerMenu[i].status & IT_DISABLED)) + patch = W_CachePatchName(description[i].picname, PU_CACHE); + if (o >= 0 && o <= 32) { - patch = W_CachePatchName(description[i].picname, PU_CACHE); - if (o >= 0 && o <= 32) - { - if (SHORT(patch->width) >= 256) - V_DrawSmallScaledPatch(8, my + 40 - o, 0, patch); - else - V_DrawScaledPatch(8, my + 40 - o, 0, patch); - } + if (SHORT(patch->width) >= 256) + V_DrawSmallScaledPatch(8, my + 40 - o, 0, patch); else - { - if (SHORT(patch->width) >= 256) - V_DrawCroppedPatch(8<<FRACBITS, (my + 8)<<FRACBITS, FRACUNIT/2, 0, patch, 0, (o - 32)*2, SHORT(patch->width), SHORT(patch->height)); - else - V_DrawCroppedPatch(8<<FRACBITS, (my + 8)<<FRACBITS, FRACUNIT, 0, patch, 0, o - 32, SHORT(patch->width), SHORT(patch->height)); - } - W_UnlockCachedPatch(patch); + V_DrawScaledPatch(8, my + 40 - o, 0, patch); + } + else + { + if (SHORT(patch->width) >= 256) + V_DrawCroppedPatch(8<<FRACBITS, (my + 8)<<FRACBITS, FRACUNIT/2, 0, patch, 0, (o-32)*2, SHORT(patch->width), SHORT(patch->height)); + else + V_DrawCroppedPatch(8<<FRACBITS, (my + 8)<<FRACBITS, FRACUNIT, 0, patch, 0, (o-32), SHORT(patch->width), SHORT(patch->height)); } + W_UnlockCachedPatch(patch); // draw title (or big pic) M_DrawMenuTitle(); @@ -5565,10 +5572,10 @@ static void M_ChoosePlayer(INT32 choice) boolean ultmode = (ultimate_selectable && SP_PlayerDef.prevMenu == &SP_LoadDef && saveSlotSelected == NOSAVESLOT); // skip this if forcecharacter or no characters available - if (!(PlayerMenu[choice].status & IT_DYBIGSPACE)) + if (!(SP_PlayerMenu[0].status & IT_DYBIGSPACE)) { // M_SetupChoosePlayer didn't call us directly, that means we've been properly set up. - char_scroll = itemOn*128*FRACUNIT; // finish scrolling the menu + char_scroll = 0; // finish scrolling the menu M_DrawSetupChoosePlayerMenu(); // draw the finally selected character one last time for the fadeout } M_ClearMenus(true); @@ -6002,7 +6009,7 @@ void M_DrawTimeAttackMenu(void) x = SP_TimeAttackDef.x; y = SP_TimeAttackDef.y; - V_DrawString(x, y + SP_TimeAttackMenu[talevelback].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[talevelback].text); + V_DrawString(x, y + SP_TimeAttackMenu[talevel].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[talevel].text); ncv = (consvar_t *)SP_TimeAttackMenu[taplayer].itemaction; V_DrawString(x, y + SP_TimeAttackMenu[taplayer].alphaKey, V_TRANSLUCENT, SP_TimeAttackMenu[taplayer].text); @@ -6177,7 +6184,7 @@ void M_DrawNightsAttackMenu(void) // ALWAYS DRAW level even when not on this menu! if (currentMenu != &SP_NightsAttackDef) - V_DrawString(SP_NightsAttackDef.x, SP_NightsAttackDef.y + SP_TimeAttackMenu[nalevelback].alphaKey, V_TRANSLUCENT, SP_NightsAttackMenu[nalevelback].text); + V_DrawString(SP_NightsAttackDef.x, SP_NightsAttackDef.y + SP_TimeAttackMenu[nalevel].alphaKey, V_TRANSLUCENT, SP_NightsAttackMenu[nalevel].text); } static void M_NightsAttackLevelSelect(INT32 choice) @@ -7207,7 +7214,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) if (setupm_fakeskin < 0) setupm_fakeskin = numskins-1; } - while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUnlock(setupm_fakeskin))); + while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin))); } else if (itemOn == 1) // player color { @@ -7227,7 +7234,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) if (setupm_fakeskin > numskins-1) setupm_fakeskin = 0; } - while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUnlock(setupm_fakeskin))); + while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin))); } else if (itemOn == 1) // player color { diff --git a/src/m_menu.h b/src/m_menu.h index 004ebaeb332b8f0191b95d51cf0f8292c318df17..2e20789efc09792618ac9650b1c7d74edcd8835e 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -149,8 +149,6 @@ typedef struct menuitem_s UINT8 alphaKey; } menuitem_t; -extern menuitem_t PlayerMenu[32]; - typedef struct menu_s { const char *menutitlepic; @@ -174,10 +172,10 @@ extern menu_t SP_LoadDef; // Stuff for customizing the player select screen typedef struct { + boolean used; char notes[441]; char picname[8]; char skinname[SKINNAMESIZE*2+2]; // skin&skin\0 - UINT16 wadnum; // for duplicate characters UINT8 prev; UINT8 next; } description_t; diff --git a/src/p_enemy.c b/src/p_enemy.c index 08a79b8cf1adc11c3619235e53dd23f4513dff54..c1c6c5ebbd9eff35ef8b860597fa9ae02b59b09c 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4182,12 +4182,15 @@ void A_SignPlayer(mobj_t *actor) actor->frame += Color_Opposite[actor->target->player->skincolor*2+1]; } - // spawn an overlay of the player's face. - ov = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY); - P_SetTarget(&ov->target, actor); - ov->color = actor->target->player->skincolor; - ov->skin = skin; - P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN + if (skin->sprites[SPR2_SIGN].numframes) + { + // spawn an overlay of the player's face. + ov = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY); + P_SetTarget(&ov->target, actor); + ov->color = actor->target->player->skincolor; + ov->skin = skin; + P_SetMobjState(ov, actor->info->seestate); // S_PLAY_SIGN + } } // Function: A_OverlayThink @@ -4517,7 +4520,7 @@ void A_MinusDigging(mobj_t *actor) // If we're close enough to our target, pop out of the ground if (P_AproxDistance(actor->target->x-actor->x, actor->target->y-actor->y) < actor->radius - && abs(actor->target->z - actor->z) < actor->height) + && abs(actor->target->z - actor->z) < 2*actor->height) P_SetMobjState(actor, actor->info->missilestate); // Snap to ground @@ -5608,7 +5611,7 @@ void A_MixUp(mobj_t *actor) // and grab their xyz coords for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE - && !players[i].exiting && !players[i].powers[pw_super]) + && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) { if ((netgame || multiplayer) && players[i].spectator) // Ignore spectators continue; @@ -5727,7 +5730,7 @@ void A_MixUp(mobj_t *actor) for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super]) + && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) { if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators continue; @@ -5777,7 +5780,7 @@ void A_MixUp(mobj_t *actor) for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super]) + && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) { if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators continue; @@ -5807,7 +5810,7 @@ void A_MixUp(mobj_t *actor) if (teleported[i]) { if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super]) + && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) { if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators continue; @@ -5949,7 +5952,7 @@ void A_RecyclePowers(mobj_t *actor) for (j = 0; j < NUMPOWERS; j++) { - if (j == pw_flashing || j == pw_underwater || j == pw_spacetime + if (j == pw_flashing || j == pw_underwater || j == pw_spacetime || j == pw_carry || j == pw_tailsfly || j == pw_extralife || j == pw_nocontrol || j == pw_super) continue; players[recv_pl].powers[j] = powers[send_pl][j]; @@ -8235,7 +8238,7 @@ void A_OrbitNights(mobj_t* actor) #endif if (!actor->target || !actor->target->player || - !(actor->target->player->pflags & PF_NIGHTSMODE) || !actor->target->player->nightstime + !(actor->target->player->powers[pw_carry] == CR_NIGHTSMODE) || !actor->target->player->nightstime // Also remove this object if they no longer have a NiGHTS helper || (ishelper && !actor->target->player->powers[pw_nights_helper])) { diff --git a/src/p_floor.c b/src/p_floor.c index f401271d1398c827107bf88ec59f1d8866d02b3c..d16c8b9ffe76bdf55d625a8fc956651f9c7d7aad 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1776,9 +1776,9 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_SCORE: case MT_DROWNNUMBERS: case MT_GOTEMERALD: + case MT_LOCKON: case MT_TAG: case MT_GOTFLAG: - case MT_GOTFLAG2: case MT_HOOP: case MT_HOOPCOLLIDE: case MT_NIGHTSCORE: diff --git a/src/p_inter.c b/src/p_inter.c index c7a15275af3b4a1c112a18fba38da7f1b57d362c..f5255a2f7d1d74ebbdead3d6100dc4474a9bcffd 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -367,11 +367,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; } - if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) - || ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) + if (((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING)) + || ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_NOJUMPDAMAGE) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) || (player->pflags & (PF_SPINNING|PF_GLIDING)) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) - || ((player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) + || ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) || player->powers[pw_invulnerability] || player->powers[pw_super] || elementalpierce) // Do you possess the ability to subdue the object? { @@ -379,9 +379,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { if (elementalpierce == 2) P_DoBubbleBounce(player); - else + else if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) toucher->momz = -toucher->momz; } + if (player->pflags & PF_BOUNCING) + P_DoAbilityBounce(player, false); toucher->momx = -toucher->momx; toucher->momy = -toucher->momy; P_DamageMobj(special, toucher, toucher, 1, 0); @@ -406,7 +408,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) //////////////////////////////////////////////////////// /////ENEMIES!!////////////////////////////////////////// //////////////////////////////////////////////////////// - if (special->type == MT_GSNAPPER && !(((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) + if (special->type == MT_GSNAPPER && !(((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING)) || player->powers[pw_invulnerability] || player->powers[pw_super] || elementalpierce) && toucher->z < special->z + special->height && toucher->z + toucher->height > special->z) { @@ -416,23 +418,30 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) else if (special->type == MT_SHARP && ((special->state == &states[special->info->xdeathstate]) || (toucher->z > special->z + special->height/2))) { - // Cannot hit sharp from above or when red and angry - P_DamageMobj(toucher, special, special, 1, 0); + if (player->pflags & PF_BOUNCING) + { + toucher->momz = -toucher->momz; + P_DoAbilityBounce(player, false); + } + else // Cannot hit sharp from above or when red and angry + P_DamageMobj(toucher, special, special, 1, 0); } - else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) - || ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) + else if (((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING)) + || ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_NOJUMPDAMAGE) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) || (player->pflags & (PF_SPINNING|PF_GLIDING)) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) - || ((player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) + || ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) || player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object? { if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1)) { if (elementalpierce == 2) P_DoBubbleBounce(player); - else + else if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) toucher->momz = -toucher->momz; } + if (player->pflags & PF_BOUNCING) + P_DoAbilityBounce(player, false); P_DamageMobj(special, toucher, toucher, 1, 0); } @@ -756,12 +765,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } else //Initial transformation. Don't allow second chances in special stages! { - if (player->pflags & PF_NIGHTSMODE) + if (player->powers[pw_carry] == CR_NIGHTSMODE) return; S_StartSound(toucher, sfx_supert); } - if (!(netgame || multiplayer) && !(player->pflags & PF_NIGHTSMODE)) + if (!(netgame || multiplayer) && !(player->powers[pw_carry] == CR_NIGHTSMODE)) P_SetTarget(&special->tracer, toucher); P_NightserizePlayer(player, special->health); // Transform! return; @@ -885,7 +894,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; // make sure everything is as it should be, THEN take rings from players in special stages - if (player->pflags & PF_NIGHTSMODE && !toucher->target) + if (player->powers[pw_carry] == CR_NIGHTSMODE && !toucher->target) return; if (player->mare != special->threshold) // wrong mare @@ -923,7 +932,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->bumpertime < TICRATE/4) { S_StartSound(toucher, special->info->seesound); - if (player->pflags & PF_NIGHTSMODE) + if (player->powers[pw_carry] == CR_NIGHTSMODE) { player->bumpertime = TICRATE/2; if (special->threshold > 0) @@ -979,14 +988,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } return; case MT_NIGHTSSUPERLOOP: - if (player->bot || !(player->pflags & PF_NIGHTSMODE)) + if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) player->powers[pw_nights_superloop] = (UINT16)special->info->speed; else { for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) + if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) players[i].powers[pw_nights_superloop] = (UINT16)special->info->speed; if (special->info->deathsound != sfx_None) S_StartSound(NULL, special->info->deathsound); @@ -1001,14 +1010,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSDRILLREFILL: - if (player->bot || !(player->pflags & PF_NIGHTSMODE)) + if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) player->drillmeter = special->info->speed; else { for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) + if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) players[i].drillmeter = special->info->speed; if (special->info->deathsound != sfx_None) S_StartSound(NULL, special->info->deathsound); @@ -1023,7 +1032,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSHELPER: - if (player->bot || !(player->pflags & PF_NIGHTSMODE)) + if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) { @@ -1037,7 +1046,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { mobj_t *flickyobj; for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && players[i].pflags & PF_NIGHTSMODE) { + if (playeringame[i] && players[i].mo && players[i].powers[pw_carry] == CR_NIGHTSMODE) { players[i].powers[pw_nights_helper] = (UINT16)special->info->speed; flickyobj = P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z + players[i].mo->info->height, MT_NIGHTOPIANHELPER); P_SetTarget(&flickyobj->target, players[i].mo); @@ -1055,7 +1064,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSEXTRATIME: - if (player->bot || !(player->pflags & PF_NIGHTSMODE)) + if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) { @@ -1066,7 +1075,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) else { for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) + if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) { players[i].nightstime += special->info->speed; players[i].startedtime += special->info->speed; @@ -1085,7 +1094,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } break; case MT_NIGHTSLINKFREEZE: - if (player->bot || !(player->pflags & PF_NIGHTSMODE)) + if (player->bot || !(player->powers[pw_carry] == CR_NIGHTSMODE)) return; if (!G_IsSpecialStage(gamemap)) { @@ -1095,7 +1104,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) else { for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) + if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) { players[i].powers[pw_nights_linkfreeze] += (UINT16)special->info->speed; players[i].linktimer = 2*TICRATE; @@ -1153,7 +1162,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (G_IsSpecialStage(gamemap)) { for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) + if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) players[i].drillmeter += TICRATE/2; } else if (player->bot) @@ -1336,9 +1345,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) toucher->momz = -toucher->momz; if (player->pflags & PF_GLIDING) { - player->pflags &= ~(PF_GLIDING|PF_JUMPED); + player->pflags &= ~(PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE); P_SetPlayerMobjState(toucher, S_PLAY_FALL); } + player->homing = 0; // Play a bounce sound? S_StartSound(toucher, special->info->painsound); @@ -1346,7 +1356,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_BLACKEGGMAN_GOOPFIRE: - if (toucher->state != &states[S_PLAY_PAIN] && !player->powers[pw_flashing]) + if (!player->powers[pw_flashing]) { toucher->momx = 0; toucher->momy = 0; @@ -1354,13 +1364,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (toucher->momz != 0) special->momz = toucher->momz; - player->powers[pw_ingoop] = 2; - - if (player->powers[pw_carry] == CR_GENERIC) - { - P_SetTarget(&toucher->tracer, NULL); - player->powers[pw_carry] = CR_NONE; - } + player->powers[pw_carry] = CR_BRAKGOOP; + P_SetTarget(&toucher->tracer, special); P_ResetPlayer(player); @@ -1372,8 +1377,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_SetMobjState(special->target, special->target->info->raisestate); } } - else - player->powers[pw_ingoop] = 0; return; case MT_EGGSHIELD: { @@ -1403,17 +1406,18 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) toucher->momz = -toucher->momz; if (player->pflags & PF_GLIDING) { - player->pflags &= ~(PF_GLIDING|PF_JUMPED); + player->pflags &= ~(PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE); P_SetPlayerMobjState(toucher, S_PLAY_FALL); } + player->homing = 0; // Play a bounce sound? S_StartSound(toucher, special->info->painsound); return; } - else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) - || ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) - || ((player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) + else if (((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING)) + || ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_NOJUMPDAMAGE) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) + || ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) || (player->pflags & (PF_SPINNING|PF_GLIDING)) || player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object? { @@ -1463,7 +1467,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { player->powers[pw_carry] = CR_MACESPIN; S_StartSound(toucher, sfx_spin); - P_SetPlayerMobjState(toucher, S_PLAY_SPIN); + P_SetPlayerMobjState(toucher, S_PLAY_ROLL); } else player->powers[pw_carry] = CR_GENERIC; @@ -2597,7 +2601,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) } player->powers[pw_flashing] = flashingtics; - P_SetPlayerMobjState(target, S_PLAY_NIGHTS_PAIN); + P_SetPlayerMobjState(target, S_PLAY_NIGHTS_STUN); S_StartSound(target, sfx_nghurt); if (oldnightstime > 10*TICRATE @@ -2724,7 +2728,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) { - player->pflags &= ~(PF_SLIDING|PF_NIGHTSMODE); + player->pflags &= ~PF_SLIDING; player->powers[pw_carry] = CR_NONE; @@ -2820,10 +2824,7 @@ static inline void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *so P_InstaThrust(player->mo, ang, fallbackspeed); - if (player->charflags & SF_SUPERANIMS) - P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_STUN); - else - P_SetPlayerMobjState(player->mo, player->mo->info->painstate); + P_SetPlayerMobjState(player->mo, S_PLAY_STUN); P_ResetPlayer(player); @@ -3069,7 +3070,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (player->pflags & PF_GODMODE) return false; - if (!(target->player->pflags & (PF_NIGHTSMODE|PF_NIGHTSFALL)) && (maptol & TOL_NIGHTS)) + if (!(target->player->powers[pw_carry] == CR_NIGHTSMODE || target->player->pflags & PF_NIGHTSFALL) && (maptol & TOL_NIGHTS)) return false; switch (damagetype) @@ -3091,7 +3092,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da } } - if (player->pflags & PF_NIGHTSMODE) // NiGHTS damage handling + if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS damage handling { if (!force) { diff --git a/src/p_local.h b/src/p_local.h index 9b7c16702121bb514bfbe6cbd89cb09f40956a65..a1b07e952d4d531aae8d8d0f850a77c1a07d5b7d 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -130,6 +130,7 @@ void P_ResetCamera(player_t *player, camera_t *thiscam); boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam); void P_SlideCameraMove(camera_t *thiscam); boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled); +pflags_t P_GetJumpFlags(player_t *player); boolean P_PlayerInPain(player_t *player); void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor); void P_ResetPlayer(player_t *player); @@ -150,11 +151,16 @@ void P_GivePlayerRings(player_t *player, INT32 num_rings); void P_GivePlayerLives(player_t *player, INT32 numlives); UINT8 P_GetNextEmerald(void); void P_GiveEmerald(boolean spawnObj); +#if 0 void P_ResetScore(player_t *player); +#else +#define P_ResetScore(player) player->scoreadd = 0 +#endif boolean P_AutoPause(void); void P_DoJumpShield(player_t *player); void P_DoBubbleBounce(player_t *player); +void P_DoAbilityBounce(player_t *player, boolean changemomz); void P_BlackOw(player_t *player); void P_ElementalFire(player_t *player, boolean cropcircle); @@ -169,12 +175,16 @@ fixed_t P_ReturnThrustX(mobj_t *mo, angle_t angle, fixed_t move); fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move); void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move); -boolean P_LookForEnemies(player_t *player, boolean nonenemies); +mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet); void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user boolean P_SuperReady(player_t *player); void P_DoJump(player_t *player, boolean soundandstate); +#if 0 boolean P_AnalogMove(player_t *player); +#else +#define P_AnalogMove(player) (player->pflags & PF_ANALOGMODE) +#endif boolean P_TransferToNextMare(player_t *player); UINT8 P_FindLowestMare(void); void P_FindEmerald(void); diff --git a/src/p_map.c b/src/p_map.c index 9d1991237e38e208e3d3654b9a53666e1cf8a340..a74c9f1e2faa5608ff323f7a521ce088f0a0fa0a 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -115,7 +115,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) fixed_t offx, offy; fixed_t vertispeed = spring->info->mass; fixed_t horizspeed = spring->info->damage; - UINT8 jumping, secondjump; + UINT8 secondjump; if (object->eflags & MFE_SPRUNG) // Object was already sprung this tic return false; @@ -124,20 +124,25 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) if (object->player && object->player->spectator) return false; - if (object->player && (object->player->pflags & PF_NIGHTSMODE)) + if (object->player && (object->player->powers[pw_carry] == CR_NIGHTSMODE)) { /*Someone want to make these work like bumpers?*/ return false; } -#ifdef ESLOPE - object->standingslope = NULL; // Okay, now we can't return - no launching off at silly angles for you. -#endif + if (object->player + && ((object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY) + || (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2))) + { + S_StartSound(object, sfx_s3k8b); + horizspeed = FixedMul(horizspeed, (4*FRACUNIT)/3); + vertispeed = FixedMul(vertispeed, (6*FRACUNIT)/5); // aprox square root of above + } object->eflags |= MFE_SPRUNG; // apply this flag asap! spring->flags &= ~(MF_SOLID|MF_SPECIAL); // De-solidify - if (horizspeed && vertispeed) // Mimic SA + if ((horizspeed && vertispeed) || (object->player && object->player->homing)) // Mimic SA { object->momx = object->momy = 0; P_TryMove(object, spring->x, spring->y, true); @@ -203,32 +208,36 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) } } - pflags = object->player->pflags & (PF_JUMPED|PF_SPINNING|PF_THOKKED|PF_SHIELDABILITY); // I still need these. - jumping = object->player->jumping; + pflags = object->player->pflags & (PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_THOKKED|PF_SHIELDABILITY|PF_BOUNCING); // I still need these. secondjump = object->player->secondjump; P_ResetPlayer(object->player); if (spring->info->painchance) { - object->player->pflags |= PF_JUMPED; + object->player->pflags |= P_GetJumpFlags(object->player); P_SetPlayerMobjState(object, S_PLAY_JUMP); } - else if (P_MobjFlip(object)*vertispeed > 0) - P_SetPlayerMobjState(object, S_PLAY_SPRING); - else if (P_MobjFlip(object)*vertispeed < 0) - P_SetPlayerMobjState(object, S_PLAY_FALL); - else // horizontal spring + else if (!vertispeed || (pflags & PF_BOUNCING)) // horizontal spring or bouncing { - if (pflags & (PF_JUMPED|PF_SPINNING) && (object->player->panim == PA_ROLL || object->player->panim == PA_JUMP || object->player->panim == PA_FALL)) + if ((pflags & PF_BOUNCING) + || (pflags & (PF_JUMPED|PF_SPINNING) && (object->player->panim == PA_ROLL || object->player->panim == PA_JUMP || object->player->panim == PA_FALL))) { object->player->pflags |= pflags; - object->player->jumping = jumping; object->player->secondjump = secondjump; } else P_SetPlayerMobjState(object, S_PLAY_WALK); } + else if (P_MobjFlip(object)*vertispeed > 0) + P_SetPlayerMobjState(object, S_PLAY_SPRING); + else + P_SetPlayerMobjState(object, S_PLAY_FALL); } + +#ifdef ESLOPE + object->standingslope = NULL; // Okay, now we know it's not going to be relevant - no launching off at silly angles for you. +#endif + return true; } @@ -324,9 +333,6 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) if (tails->bot == 1) return; - if (sonic->pflags & PF_NIGHTSMODE) - return; - if ((sonic->mo->eflags & MFE_VERTICALFLIP) != (tails->mo->eflags & MFE_VERTICALFLIP)) return; // Both should be in same gravity @@ -377,6 +383,7 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) else { if (sonic-players == consoleplayer && botingame) CV_SetValue(&cv_analog2, true); + P_SetTarget(&sonic->mo->tracer, NULL); sonic->powers[pw_carry] = CR_NONE; } } @@ -460,9 +467,9 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - // CA_DASHMODE users destroy spikes and monitors, CA_TWINSPIN users and CA2_MELEE users destroy spikes. + // SF_DASHMODE users destroy spikes and monitors, CA_TWINSPIN users and CA2_MELEE users destroy spikes. if ((tmthing->player) - && (((tmthing->player->charability == CA_DASHMODE) && (tmthing->player->dashmode >= 3*TICRATE) + && (((tmthing->player->charflags & SF_DASHMODE) && (tmthing->player->dashmode >= 3*TICRATE) && (thing->flags & (MF_MONITOR) || thing->type == MT_SPIKE)) || ((((tmthing->player->charability == CA_TWINSPIN) && (tmthing->player->panim == PA_ABILITY)) || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)) @@ -499,7 +506,7 @@ static boolean PIT_CheckThing(mobj_t *thing) // Don't collide with your buddies while NiGHTS-flying. if (tmthing->player && thing->player && (maptol & TOL_NIGHTS) - && ((tmthing->player->pflags & PF_NIGHTSMODE) || (thing->player->pflags & PF_NIGHTSMODE))) + && ((tmthing->player->powers[pw_carry] == CR_NIGHTSMODE) || (thing->player->powers[pw_carry] == CR_NIGHTSMODE))) return true; blockdist = thing->radius + tmthing->radius; @@ -785,7 +792,7 @@ static boolean PIT_CheckThing(mobj_t *thing) { // Hop on the missile for a ride! thing->player->powers[pw_carry] = CR_GENERIC; - thing->player->pflags &= ~PF_JUMPED; + thing->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); P_SetTarget(&thing->tracer, tmthing); P_SetTarget(&tmthing->target, thing); // Set owner to the player P_SetTarget(&tmthing->tracer, NULL); // Disable homing-ness @@ -896,7 +903,7 @@ static boolean PIT_CheckThing(mobj_t *thing) // must be flying in the SAME DIRECTION as the last time you came through. // not (your direction) xor (stored direction) // In other words, you can't u-turn and respawn rings near the drone. - if (pl->bonustime && (pl->pflags & PF_NIGHTSMODE) && (INT32)leveltime > droneobj->extravalue2 && ( + if (pl->bonustime && (pl->powers[pw_carry] == CR_NIGHTSMODE) && (INT32)leveltime > droneobj->extravalue2 && ( !(pl->anotherflyangle >= 90 && pl->anotherflyangle <= 270) ^ (droneobj->extravalue1 >= 90 && droneobj->extravalue1 <= 270) )) @@ -928,11 +935,13 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->eflags & MFE_VERTICALFLIP) { if (thing->z + thing->height <= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) - && thing->z + thing->height + thing->momz >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz) + && thing->z + thing->height + thing->momz >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz + && !(thing->player->charability == CA_BOUNCE && thing->player->panim == PA_ABILITY && thing->eflags & MFE_VERTICALFLIP)) P_DamageMobj(thing, tmthing, tmthing, 1, 0); } else if (thing->z >= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) - && thing->z + thing->momz <= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz) + && thing->z + thing->momz <= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz + && !(thing->player->charability == CA_BOUNCE && thing->player->panim == PA_ABILITY && !(thing->eflags & MFE_VERTICALFLIP))) P_DamageMobj(thing, tmthing, tmthing, 1, 0); } else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tmthing->player) // unfortunate player falls into spike?! @@ -940,11 +949,13 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->eflags & MFE_VERTICALFLIP) { if (tmthing->z + tmthing->height <= thing->z - FixedMul(FRACUNIT, thing->scale) - && tmthing->z + tmthing->height + tmthing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)) + && tmthing->z + tmthing->height + tmthing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale) + && !(tmthing->player->charability == CA_BOUNCE && tmthing->player->panim == PA_ABILITY && tmthing->eflags & MFE_VERTICALFLIP)) P_DamageMobj(tmthing, thing, thing, 1, 0); } else if (tmthing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) - && tmthing->z + tmthing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)) + && tmthing->z + tmthing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) + && !(tmthing->player->charability == CA_BOUNCE && tmthing->player->panim == PA_ABILITY && !(tmthing->eflags & MFE_VERTICALFLIP))) P_DamageMobj(tmthing, thing, thing, 1, 0); } @@ -1005,7 +1016,10 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->player-players == consoleplayer && botingame) CV_SetValue(&cv_analog2, true); if (thing->player->powers[pw_carry] == CR_PLAYER) + { + P_SetTarget(&thing->tracer, NULL); thing->player->powers[pw_carry] = CR_NONE; + } } if (thing->player) @@ -1063,11 +1077,10 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->flags & MF_MONITOR && (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING) || ((tmthing->player->pflags & PF_JUMPED) - && (tmthing->player->pflags & PF_FORCEJUMPDAMAGE - || !(tmthing->player->charflags & SF_NOJUMPSPIN) + && (!(tmthing->player->pflags & PF_NOJUMPDAMAGE) || (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2) - || ((tmthing->player->charflags & SF_STOMPDAMAGE) + || ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING) && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0)) || elementalpierce)) { @@ -1084,11 +1097,15 @@ static boolean PIT_CheckThing(mobj_t *thing) { if (elementalpierce == 2) P_DoBubbleBounce(player); - else + else if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) *momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically. } if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough. + { + if (player->pflags & PF_BOUNCING) + P_DoAbilityBounce(player, false); return false; + } else *z -= *momz; // to ensure proper collision. } @@ -1105,11 +1122,10 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (thing->flags & MF_MONITOR && tmthing->player && (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING) || ((tmthing->player->pflags & PF_JUMPED) - && (tmthing->player->pflags & PF_FORCEJUMPDAMAGE - || !(tmthing->player->charflags & SF_NOJUMPSPIN) + && (!(tmthing->player->pflags & PF_NOJUMPDAMAGE) || (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2) - || ((tmthing->player->charflags & SF_STOMPDAMAGE) + || ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING) && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))) && !((thing->type == MT_RING_REDBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_RING_BLUEBOX && tmthing->player->ctfteam != 2))) ; @@ -1512,7 +1528,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)) ; else if (!((rover->flags & FF_BLOCKPLAYER && thing->player) - || (rover->flags & FF_BLOCKOTHERS && !thing->player) + || (rover->flags & FF_BLOCKOTHERS && !thing->player) || rover->flags & FF_QUICKSAND)) continue; @@ -2890,7 +2906,7 @@ isblocking: slidemo->player->climbing = 5; } - slidemo->player->pflags &= ~(PF_GLIDING|PF_SPINNING|PF_JUMPED|PF_THOKKED); + slidemo->player->pflags &= ~(PF_GLIDING|PF_SPINNING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED); slidemo->player->glidetime = 0; slidemo->player->secondjump = 0; diff --git a/src/p_mobj.c b/src/p_mobj.c index 8f6b9797efbe2b01cd14a63ef269134a2e3039dc..520f9ad07d45a1da1f4b102e9ad7886029861862 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -187,32 +187,41 @@ static void P_CyclePlayerMobjState(mobj_t *mobj) // // P_GetMobjSprite2 +// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing. +// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version. // UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2) { player_t *player = mobj->player; skin_t *skin = ((skin_t *)mobj->skin); + UINT8 super = (spr2 & FF_SPR2SUPER); if (!skin) return 0; - while ((skin->sprites[spr2].numframes <= 0) + while (!(skin->sprites[spr2].numframes) && spr2 != SPR2_STND) { + if (spr2 & FF_SPR2SUPER) + { + spr2 &= ~FF_SPR2SUPER; + continue; + } + switch(spr2) { - case SPR2_PEEL: - spr2 = SPR2_RUN; - break; case SPR2_RUN: spr2 = SPR2_WALK; break; + case SPR2_STUN: + spr2 = SPR2_PAIN; + break; case SPR2_DRWN: spr2 = SPR2_DEAD; break; - case SPR2_DASH: - spr2 = SPR2_SPIN; + case SPR2_SPIN: + spr2 = SPR2_ROLL; break; case SPR2_GASP: spr2 = SPR2_SPNG; @@ -221,7 +230,7 @@ UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2) spr2 = ((player ? player->charflags : skin->flags) - & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_SPIN; + & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL; break; case SPR2_SPNG: // spring spr2 = SPR2_FALL; @@ -233,11 +242,11 @@ UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2) spr2 = SPR2_FALL; break; - case SPR2_FLY: + case SPR2_FLY : spr2 = SPR2_SPNG; break; case SPR2_SWIM: - spr2 = SPR2_FLY; + spr2 = SPR2_FLY ; break; case SPR2_TIRE: spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; @@ -247,91 +256,59 @@ UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2) spr2 = SPR2_FLY; break; case SPR2_CLMB: - spr2 = SPR2_SPIN; + spr2 = SPR2_ROLL; break; case SPR2_CLNG: spr2 = SPR2_CLMB; break; - case SPR2_TWIN: - spr2 = SPR2_SPIN; - break; - - case SPR2_MLEE: - spr2 = SPR2_TWIN; - break; - - // Super sprites fallback to regular sprites - case SPR2_SWLK: + case SPR2_FLT : spr2 = SPR2_WALK; break; - case SPR2_SRUN: - spr2 = SPR2_RUN; - break; - case SPR2_SPEE: - spr2 = SPR2_PEEL; - break; - case SPR2_SPAN: - spr2 = SPR2_PAIN; - break; - case SPR2_SSTN: - spr2 = SPR2_SPAN; - break; - case SPR2_SDTH: - spr2 = SPR2_DEAD; - break; - case SPR2_SDRN: - spr2 = SPR2_DRWN; - break; - case SPR2_SSPN: - spr2 = SPR2_SPIN; + case SPR2_FRUN: + spr2 = SPR2_RUN ; break; - case SPR2_SGSP: - spr2 = SPR2_GASP; - break; - case SPR2_SJMP: - spr2 = ((player - ? player->charflags - : skin->flags) - & SF_NOJUMPSPIN) ? SPR2_SSPG : SPR2_SSPN; - break; - case SPR2_SSPG: - spr2 = SPR2_SPNG; + + case SPR2_DASH: + spr2 = SPR2_FRUN; break; - case SPR2_SFAL: + + case SPR2_BNCE: spr2 = SPR2_FALL; break; - case SPR2_SEDG: - spr2 = SPR2_EDGE; + case SPR2_BLND: + spr2 = SPR2_ROLL; break; - case SPR2_SRID: - spr2 = SPR2_RIDE; + + case SPR2_TWIN: + spr2 = SPR2_ROLL; break; - case SPR2_SFLT: - spr2 = SPR2_SWLK; + + case SPR2_MLEE: + spr2 = SPR2_TWIN; break; // NiGHTS sprites. - case SPR2_NTRN: - spr2 = SPR2_TRNS; - break; case SPR2_NSTD: - spr2 = SPR2_SSTD; + spr2 = SPR2_STND; + super = FF_SPR2SUPER; break; case SPR2_NFLT: - spr2 = (skin->flags & SF_SUPERANIMS) ? SPR2_SFLT : SPR2_FALL; // This is skin-exclusive so the default NiGHTS skin changing system plays nice. + spr2 = SPR2_FLT ; + super = FF_SPR2SUPER; break; - case SPR2_NPUL: - spr2 = SPR2_NFLT; + case SPR2_NSTN: + spr2 = SPR2_STUN; break; - case SPR2_NPAN: - spr2 = SPR2_NPUL; + case SPR2_NPUL: + spr2 = SPR2_NSTN; break; case SPR2_NATK: - spr2 = SPR2_SSPN; + spr2 = SPR2_ROLL; + super = FF_SPR2SUPER; break; /*case SPR2_NGT0: - spr2 = SPR2_STND; + spr2 = SPR2_NFLT; break;*/ case SPR2_NGT1: case SPR2_NGT7: @@ -390,7 +367,10 @@ UINT8 P_GetMobjSprite2(mobj_t *mobj, UINT8 spr2) spr2 = SPR2_STND; break; } + + spr2 |= super; } + return spr2; } @@ -427,45 +407,17 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) else if (state == S_PLAY_SWIM && !(player->mo->eflags & MFE_UNDERWATER)) return P_SetPlayerMobjState(player->mo, S_PLAY_FLY); - // Catch state changes for Super Sonic - if (player->powers[pw_super] && (player->charflags & SF_SUPERANIMS)) - { - switch (state) - { - case S_PLAY_STND: - case S_PLAY_WAIT: - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_STND); - case S_PLAY_WALK: - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_WALK); - case S_PLAY_RUN: - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_RUN); - case S_PLAY_PEEL: - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_PEEL); - case S_PLAY_PAIN: - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_PAIN); - case S_PLAY_DEAD: - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_DEAD); - case S_PLAY_DRWN: - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_DRWN); - case S_PLAY_SPIN: - if (!(player->charflags & SF_SUPERSPIN)) - return true; - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_SPIN); - case S_PLAY_GASP: - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_GASP); - case S_PLAY_JUMP: - if (!(player->charflags & SF_SUPERSPIN)) - return true; - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_JUMP); - case S_PLAY_SPRING: - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_SPRING); - case S_PLAY_FALL: - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_FALL); - case S_PLAY_EDGE: - return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_EDGE); - default: - break; + // Catch SF_NOSUPERSPIN jumps for Supers + if (player->powers[pw_super] && (player->charflags & SF_NOSUPERSPIN)) + { + if (state == S_PLAY_JUMP) + { + if (player->mo->state-states == S_PLAY_WALK) + return P_SetPlayerMobjState(mobj, S_PLAY_FLOAT); + return true; } + else if (player->mo->state-states == S_PLAY_FLOAT && state == S_PLAY_STND) + return true; } // You were in pain state after taking a hit, and you're moving out of pain state now? else if (mobj->state == &states[mobj->info->painstate] && player->powers[pw_flashing] == flashingtics && state != mobj->info->painstate) @@ -481,61 +433,56 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) { case S_PLAY_STND: case S_PLAY_WAIT: - case S_PLAY_SUPER_STND: player->panim = PA_IDLE; break; case S_PLAY_EDGE: - case S_PLAY_SUPER_EDGE: player->panim = PA_EDGE; break; case S_PLAY_WALK: - case S_PLAY_SUPER_WALK: - case S_PLAY_SUPER_FLOAT: + case S_PLAY_FLOAT: player->panim = PA_WALK; break; case S_PLAY_RUN: - case S_PLAY_SUPER_RUN: + case S_PLAY_FLOAT_RUN: player->panim = PA_RUN; break; - case S_PLAY_PEEL: - case S_PLAY_SUPER_PEEL: - player->panim = PA_PEEL; + case S_PLAY_DASH: + player->panim = PA_DASH; break; case S_PLAY_PAIN: - case S_PLAY_SUPER_PAIN: - case S_PLAY_SUPER_STUN: + case S_PLAY_STUN: player->panim = PA_PAIN; break; - case S_PLAY_SPIN: - //case S_PLAY_DASH: -- everyone can ROLL thanks to zoom tubes... - case S_PLAY_SUPER_SPIN: + case S_PLAY_ROLL: + //case S_PLAY_SPINDASH: -- everyone can ROLL thanks to zoom tubes... player->panim = PA_ROLL; break; case S_PLAY_JUMP: - case S_PLAY_SUPER_JUMP: player->panim = PA_JUMP; break; case S_PLAY_SPRING: - case S_PLAY_SUPER_SPRING: player->panim = PA_SPRING; break; case S_PLAY_FALL: - case S_PLAY_SUPER_FALL: player->panim = PA_FALL; break; case S_PLAY_FLY: case S_PLAY_SWIM: case S_PLAY_GLIDE: + case S_PLAY_BOUNCE: + case S_PLAY_BOUNCE_LANDING: case S_PLAY_TWINSPIN: player->panim = PA_ABILITY; break; - case S_PLAY_DASH: // ...but the act of SPINDASHING is charability2 specific. + case S_PLAY_SPINDASH: // ...but the act of SPINDASHING is charability2 specific. + case S_PLAY_FIRE: + case S_PLAY_FIRE_FINISH: case S_PLAY_MELEE: case S_PLAY_MELEE_FINISH: + case S_PLAY_MELEE_LANDING: player->panim = PA_ABILITY2; break; case S_PLAY_RIDE: - case S_PLAY_SUPER_RIDE: player->panim = PA_RIDE; break; default: @@ -562,7 +509,9 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) mobj->tics = st->tics; // Adjust the player's animation speed to match their velocity. - if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST)) + if (player->panim == PA_EDGE && (player->charflags & SF_FASTEDGE)) + mobj->tics = 2; + else if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST)) { fixed_t speed;// = FixedDiv(player->speed, FixedMul(mobj->scale, player->mo->movefactor)); if (player->panim == PA_FALL) @@ -598,7 +547,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) else mobj->tics = 2; } - else if (P_IsObjectOnGround(mobj) || player->powers[pw_super]) // Only if on the ground or superflying. + else if (P_IsObjectOnGround(mobj) || ((player->charability == CA_FLOAT || player->charability == CA_SLOWFALL) && player->secondjump == 1) || player->powers[pw_super]) // Only if on the ground or superflying. { if (player->panim == PA_WALK) { @@ -609,7 +558,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) else mobj->tics = 4; } - else if ((player->panim == PA_RUN) || (player->panim == PA_PEEL)) + else if ((player->panim == PA_RUN) || (player->panim == PA_DASH)) { if (speed > 52<<FRACBITS) mobj->tics = 1; @@ -627,7 +576,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; UINT8 numframes; - UINT8 spr2 = P_GetMobjSprite2(mobj, st->frame & FF_FRAMEMASK); + UINT8 spr2 = P_GetMobjSprite2(mobj, (((player->powers[pw_super]) ? FF_SPR2SUPER : 0)|st->frame) & FF_FRAMEMASK); if (skin) numframes = skin->sprites[spr2].numframes; @@ -1646,11 +1595,8 @@ static void P_PlayerFlip(mobj_t *mo) G_GhostAddFlip(); // Flip aiming to match! - if (mo->player->pflags & PF_NIGHTSMODE) // NiGHTS doesn't use flipcam - { - if (mo->tracer) - mo->tracer->eflags ^= MFE_VERTICALFLIP; - } + if (mo->player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS doesn't use flipcam + ; else if (mo->player->pflags & PF_FLIPCAM) { mo->player->aiming = InvAngle(mo->player->aiming); @@ -1746,7 +1692,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) || (mo->player->charability == CA_FLY && (mo->player->powers[pw_tailsfly] || mo->state-states == S_PLAY_FLY_TIRED))) gravityadd = gravityadd/3; // less gravity while flying/gliding - if (mo->player->climbing || (mo->player->pflags & PF_NIGHTSMODE)) + if (mo->player->climbing || (mo->player->powers[pw_carry] == CR_NIGHTSMODE)) gravityadd = 0; if (!(mo->flags2 & MF2_OBJECTFLIP) != !(mo->player->powers[pw_gravityboots])) // negated to turn numeric into bool - would be double negated, but not needed if both would be @@ -1898,9 +1844,12 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy) // spinning friction if (player->pflags & PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH)) { - const fixed_t ns = FixedDiv(549*ORIG_FRICTION,500*FRACUNIT); - mo->momx = FixedMul(mo->momx, ns); - mo->momy = FixedMul(mo->momy, ns); + if (twodlevel || player->mo->flags2 & MF2_TWOD) // Otherwise handled in P_3DMovement + { + const fixed_t ns = FixedDiv(549*ORIG_FRICTION,500*FRACUNIT); + mo->momx = FixedMul(mo->momx, ns); + mo->momy = FixedMul(mo->momy, ns); + } } else if (abs(player->rmomx) < FixedMul(STOPSPEED, mo->scale) && abs(player->rmomy) < FixedMul(STOPSPEED, mo->scale) @@ -2326,7 +2275,7 @@ void P_XYMovement(mobj_t *mo) // Check the gravity status. P_CheckGravity(mo, false); - if (player && !moved && player->pflags & PF_NIGHTSMODE && mo->target) + if (player && !moved && player->powers[pw_carry] == CR_NIGHTSMODE && mo->target) { angle_t fa; @@ -2369,7 +2318,7 @@ void P_XYMovement(mobj_t *mo) if (player && player->homing) // no friction for homing return; - if (player && player->pflags & PF_NIGHTSMODE) + if (player && player->powers[pw_carry] == CR_NIGHTSMODE) return; // no friction for NiGHTS players #ifdef ESLOPE @@ -2592,6 +2541,9 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); + if (mo->player && mo->player->pflags & PF_GODMODE) + return false; + if (((mo->z <= mo->subsector->sector->floorheight && !(mo->eflags & MFE_VERTICALFLIP) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_FLOOR)) || (mo->z + mo->height >= mo->subsector->sector->ceilingheight @@ -3151,7 +3103,7 @@ static void P_PlayerZMovement(mobj_t *mo) else mo->z = mo->floorz; - if (mo->player->pflags & PF_NIGHTSMODE) + if (mo->player->powers[pw_carry] == CR_NIGHTSMODE) { // bounce off floor if you were flying towards it if ((mo->eflags & MFE_VERTICALFLIP && mo->player->flyangle > 0 && mo->player->flyangle < 180) @@ -3259,60 +3211,69 @@ static void P_PlayerZMovement(mobj_t *mo) // aren't pressing any controls. if (!(mo->player->cmd.forwardmove || mo->player->cmd.sidemove) && !mo->player->cmomx && !mo->player->cmomy && !(mo->player->pflags & PF_SPINNING)) { - mo->momx = mo->momx/2; - mo->momy = mo->momy/2; + mo->momx >>= 1; + mo->momy >>= 1; } } - if (mo->health) + if (mo->health && !P_CheckDeathPitCollide(mo)) { if (mo->player->pflags & PF_GLIDING) // ground gliding { mo->player->skidtime = TICRATE; mo->tics = -1; } - else if (mo->player->charability2 == CA2_MELEE && mo->player->panim == PA_ABILITY2) + else if (mo->player->charability2 == CA2_MELEE && (mo->player->panim == PA_ABILITY2 && mo->state-states != S_PLAY_MELEE_LANDING)) { - P_InstaThrust(mo, mo->angle, 0); - P_SetPlayerMobjState(mo, S_PLAY_STND); + P_SetPlayerMobjState(mo, S_PLAY_MELEE_LANDING); + mo->tics = (mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(mo->movefactor)))>>FRACBITS; + S_StartSound(mo, sfx_s3k8b); + mo->player->pflags |= PF_FULLSTASIS; } else if (mo->player->pflags & PF_JUMPED || (mo->player->pflags & (PF_SPINNING|PF_USEDOWN)) != (PF_SPINNING|PF_USEDOWN) || mo->player->powers[pw_tailsfly] || mo->state-states == S_PLAY_FLY_TIRED) { if (mo->player->cmomx || mo->player->cmomy) { - if (mo->player->charability == CA_DASHMODE && mo->player->dashmode >= 3*TICRATE && mo->player->panim != PA_PEEL) - P_SetPlayerMobjState(mo, S_PLAY_PEEL); - else if (mo->player->speed >= FixedMul(mo->player->runspeed, mo->scale) && mo->player->panim != PA_RUN) + if (mo->player->charflags & SF_DASHMODE && mo->player->dashmode >= 3*TICRATE && mo->player->panim != PA_DASH) + P_SetPlayerMobjState(mo, S_PLAY_DASH); + else if (mo->player->speed >= FixedMul(mo->player->runspeed, mo->scale) + && (mo->player->panim != PA_RUN || mo->state-states == S_PLAY_FLOAT_RUN)) P_SetPlayerMobjState(mo, S_PLAY_RUN); - else if ((mo->player->rmomx || mo->player->rmomy) && (mo->player->panim != PA_WALK || mo->state-states == S_PLAY_SUPER_FLOAT)) + else if ((mo->player->rmomx || mo->player->rmomy) + && (mo->player->panim != PA_WALK || mo->state-states == S_PLAY_FLOAT)) P_SetPlayerMobjState(mo, S_PLAY_WALK); else if (!mo->player->rmomx && !mo->player->rmomy && mo->player->panim != PA_IDLE) P_SetPlayerMobjState(mo, S_PLAY_STND); } else { - if (mo->player->charability == CA_DASHMODE && mo->player->dashmode >= 3*TICRATE && mo->player->panim != PA_PEEL) - P_SetPlayerMobjState(mo, S_PLAY_PEEL); - if (mo->player->speed >= FixedMul(mo->player->runspeed, mo->scale) && mo->player->panim != PA_RUN) + if (mo->player->charflags & SF_DASHMODE && mo->player->dashmode >= 3*TICRATE && mo->player->panim != PA_DASH) + P_SetPlayerMobjState(mo, S_PLAY_DASH); + else if (mo->player->speed >= FixedMul(mo->player->runspeed, mo->scale) + && (mo->player->panim != PA_RUN || mo->state-states == S_PLAY_FLOAT_RUN)) P_SetPlayerMobjState(mo, S_PLAY_RUN); - else if ((mo->momx || mo->momy) && (mo->player->panim != PA_WALK || mo->state-states == S_PLAY_SUPER_FLOAT)) + else if ((mo->momx || mo->momy) + && (mo->player->panim != PA_WALK || mo->state-states == S_PLAY_FLOAT)) P_SetPlayerMobjState(mo, S_PLAY_WALK); else if (!mo->momx && !mo->momy && mo->player->panim != PA_IDLE) P_SetPlayerMobjState(mo, S_PLAY_STND); } } - if (mo->player->pflags & PF_JUMPED) - mo->player->pflags &= ~PF_SPINNING; - else if (!(mo->player->pflags & PF_USEDOWN)) + if ((mo->player->charability2 == CA2_SPINDASH) && !(mo->player->pflags & PF_THOKKED) && (mo->player->cmd.buttons & BT_USE) && (FixedHypot(mo->momx, mo->momy) > (5*mo->scale))) + { + mo->player->pflags |= PF_SPINNING; + P_SetPlayerMobjState(mo, S_PLAY_ROLL); + S_StartSound(mo, sfx_spin); + } + else mo->player->pflags &= ~PF_SPINNING; if (!(mo->player->pflags & PF_GLIDING)) - mo->player->pflags &= ~(PF_JUMPED|PF_FORCEJUMPDAMAGE); + mo->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); - mo->player->pflags &= ~(PF_THOKKED|PF_CANCARRY/*|PF_GLIDING*/); - mo->player->jumping = 0; + mo->player->pflags &= ~(PF_STARTJUMP|PF_THOKKED|PF_CANCARRY/*|PF_GLIDING*/); mo->player->secondjump = 0; mo->player->glidetime = 0; mo->player->climbing = 0; @@ -3346,6 +3307,16 @@ static void P_PlayerZMovement(mobj_t *mo) clipmomz = false; } } + + if (mo->player->pflags & PF_BOUNCING) + { + P_MobjCheckWater(mo); + mo->momz *= -1; + P_DoAbilityBounce(mo->player, true); + if (mo->player->scoreadd) + mo->player->scoreadd--; + clipmomz = false; + } } } if (!(mo->player->pflags & PF_SPINNING)) @@ -3394,7 +3365,7 @@ nightsdone: else mo->z = mo->ceilingz - mo->height; - if (mo->player->pflags & PF_NIGHTSMODE) + if (mo->player->powers[pw_carry] == CR_NIGHTSMODE) { // bounce off ceiling if you were flying towards it if ((mo->eflags & MFE_VERTICALFLIP && mo->player->flyangle > 180 && mo->player->flyangle <= 359) @@ -3607,8 +3578,8 @@ static boolean P_SceneryZMovement(mobj_t *mo) // boolean P_CanRunOnWater(player_t *player, ffloor_t *rover) { - if (!(player->pflags & PF_NIGHTSMODE) && !player->homing - && ((player->powers[pw_super] || player->charflags & SF_RUNONWATER) && player->mo->ceilingz-*rover->topheight >= player->mo->height) + if (!player->powers[pw_carry] && !player->homing + && ((player->powers[pw_super] || player->charflags & SF_RUNONWATER || player->dashmode >= 3*TICRATE) && player->mo->ceilingz-*rover->topheight >= player->mo->height) && (rover->flags & FF_SWIMMABLE) && !(player->pflags & PF_SPINNING) && player->speed > FixedMul(player->runspeed, player->mo->scale) && !(player->pflags & PF_SLIDING) && abs(player->mo->z - *rover->topheight) < FixedMul(30*FRACUNIT, player->mo->scale)) @@ -4013,7 +3984,7 @@ void P_DestroyRobots(void) continue; // not a mobj thinker mo = (mobj_t *)think; - if (mo->health <= 0 || !(mo->flags & MF_ENEMY || mo->flags & MF_BOSS)) + if (mo->health <= 0 || !(mo->flags & (MF_ENEMY|MF_BOSS))) continue; // not a valid enemy if (mo->type == MT_PLAYER) // Don't chase after other players! @@ -4036,7 +4007,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled || (thiscam == &camera2 && players[secondarydisplayplayer].mo && (players[secondarydisplayplayer].mo->flags2 & MF2_TWOD))) itsatwodlevel = true; - if (player->pflags & PF_FLIPCAM && !(player->pflags & PF_NIGHTSMODE) && player->mo->eflags & MFE_VERTICALFLIP) + if (player->pflags & PF_FLIPCAM && !(player->powers[pw_carry] == CR_NIGHTSMODE) && player->mo->eflags & MFE_VERTICALFLIP) postimg = postimg_flip; else if (player->awayviewtics) { @@ -4169,6 +4140,9 @@ static void P_PlayerMobjThinker(mobj_t *mobj) // momentum movement mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN; + if (mobj->state-states == S_PLAY_BOUNCE_LANDING) + goto animonly; // no need for checkposition - doesn't move at ALL + // Zoom tube if (mobj->tracer) { @@ -4289,9 +4263,9 @@ static void P_PlayerMobjThinker(mobj_t *mobj) } else { - if (!(mobj->player->pflags & PF_NIGHTSMODE)) // "jumping" is used for drilling - mobj->player->jumping = 0; - mobj->player->pflags &= ~PF_JUMPED; + if (!(mobj->player->powers[pw_carry] == CR_NIGHTSMODE)) // used for drilling + mobj->player->pflags &= ~PF_STARTJUMP; + mobj->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly]) { mobj->player->secondjump = 0; @@ -5491,10 +5465,10 @@ static void P_Boss7Thinker(mobj_t *mobj) if (players[i].mo->health <= 0) continue; - if (players[i].powers[pw_ingoop]) + if (players[i].powers[pw_carry] == CR_BRAKGOOP) { closestNum = -1; - closestdist = 16384*FRACUNIT; // Just in case... + closestdist = INT32_MAX; // Just in case... // Find waypoint he is closest to for (th = thinkercap.next; th != &thinkercap; th = th->next) @@ -6903,7 +6877,7 @@ void P_MobjThinker(mobj_t *mobj) return; if (/*(mobj->target) -- the following is implicit by P_AddShield && (mobj->target->player) - && */ (mobj->target->player->homing)) + && */ (mobj->target->player->homing) && (mobj->target->player->pflags & PF_SHIELDABILITY)) { P_SetMobjState(mobj, mobj->info->painstate); mobj->tics++; @@ -7038,6 +7012,25 @@ void P_MobjThinker(mobj_t *mobj) return; } break; + case MT_LOCKON: + if (!mobj->target) + { + P_RemoveMobj(mobj); + return; + } + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + + mobj->eflags |= (mobj->target->eflags & MFE_VERTICALFLIP); + + mobj->destscale = mobj->target->destscale; + P_SetScale(mobj, mobj->target->scale); + + if (!(mobj->eflags & MFE_VERTICALFLIP)) + mobj->z = mobj->target->z + mobj->target->height + FixedMul((16 + abs((leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale); + else + mobj->z = mobj->target->z - FixedMul((16 + abs((leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale) - mobj->height; + break; case MT_DROWNNUMBERS: if (!mobj->target) { @@ -7309,7 +7302,6 @@ void P_MobjThinker(mobj_t *mobj) ns = 4 * FRACUNIT; mo2->momx = FixedMul(FINESINE(fa),ns); mo2->momy = FixedMul(FINECOSINE(fa),ns); - mo2->angle = fa << ANGLETOFINESHIFT; if (P_RandomChance(FRACUNIT/4)) // I filled a spreadsheet trying to get the equivalent chance to the original P_RandomByte hack! S_StartSound(mo2, mobj->info->deathsound); @@ -7321,6 +7313,7 @@ void P_MobjThinker(mobj_t *mobj) P_SetTarget(&flicky->target, mo2); flicky->momx = mo2->momx; flicky->momy = mo2->momy; + flicky->angle = fa << ANGLETOFINESHIFT; } mobj->fuse--; @@ -7652,7 +7645,7 @@ void P_MobjThinker(mobj_t *mobj) } else if (mobj->tracer && mobj->tracer->player) { - if (!(mobj->tracer->player->pflags & PF_NIGHTSMODE)) + if (!(mobj->tracer->player->powers[pw_carry] == CR_NIGHTSMODE)) { mobj->flags &= ~MF_NOGRAVITY; mobj->flags2 &= ~MF2_DONTDRAW; @@ -7704,7 +7697,7 @@ void P_MobjThinker(mobj_t *mobj) P_SetTarget(&mobj->target, NULL); } - if (mobj->tracer->player->pflags & PF_NIGHTSMODE) + if (mobj->tracer->player->powers[pw_carry] == CR_NIGHTSMODE) { if (mobj->tracer->player->bonustime) { diff --git a/src/p_pspr.h b/src/p_pspr.h index 97d7adb94b283e2af5ced1d559e8d96a25fba46e..0734b78eca2c8500a013a71240aa29823fc50168 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -35,9 +35,11 @@ #pragma interface #endif -/// \brief Frame flags: only the frame number - 0 to 511 (Frames from 0 to 63, Sprite2 number uses full range) -#define FF_FRAMEMASK 0x1ff +/// \brief Frame flags: only the frame number - 0 to 256 (Frames from 0 to 63, Sprite2 number uses 0 to 127 plus FF_SPR2SUPER) +#define FF_FRAMEMASK 0xff +/// \brief Frame flags - SPR2: Super sprite2 +#define FF_SPR2SUPER 0x80 /// \brief Frame flags - SPR2: A change of state at the end of Sprite2 animation #define FF_SPR2ENDSTATE 0x1000 /// \brief Frame flags - SPR2: 50% of starting in middle of Sprite2 animation diff --git a/src/p_saveg.c b/src/p_saveg.c index 6abb4d14c37aa81ff9474aee88be93b315f1e920..3853dc7e63826c08a337de65aeea322a9aba6b94 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -152,7 +152,6 @@ static void P_NetArchivePlayers(void) WRITESINT8(save_p, players[i].xtralife); WRITEUINT8(save_p, players[i].gotcontinue); WRITEFIXED(save_p, players[i].speed); - WRITEUINT8(save_p, players[i].jumping); WRITEUINT8(save_p, players[i].secondjump); WRITEUINT8(save_p, players[i].fly1); WRITEUINT8(save_p, players[i].scoreadd); @@ -332,7 +331,6 @@ static void P_NetUnArchivePlayers(void) players[i].xtralife = READSINT8(save_p); // Ring Extra Life counter players[i].gotcontinue = READUINT8(save_p); // got continue from stage players[i].speed = READFIXED(save_p); // Player's speed (distance formula of MOMX and MOMY values) - players[i].jumping = READUINT8(save_p); // Jump counter players[i].secondjump = READUINT8(save_p); players[i].fly1 = READUINT8(save_p); // Tails flying players[i].scoreadd = READUINT8(save_p); // Used for multiple enemy attack bonus diff --git a/src/p_setup.c b/src/p_setup.c index 14b0ad0003d6ec09ec2aff9434b05034cd296a03..a0c745e6085f3b6ec00278943b5edd1ab54a62a9 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2777,8 +2777,6 @@ boolean P_SetupLevel(boolean skipprecip) for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) { - players[i].pflags &= ~PF_NIGHTSMODE; - // Start players with pity shields if possible players[i].pity = -1; diff --git a/src/p_spec.c b/src/p_spec.c index ddcdfbd539666da21081a07f368147a82db118cb..d682c6a3065fbf72ea8ed837f2f0433cdb0ddb2d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3575,7 +3575,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers P_DamageMobj(player->mo, NULL, NULL, 1, 0); break; case 2: // Damage (Water) - if ((roversector || P_MobjReadyToTrigger(player->mo, sector)) && (player->powers[pw_underwater] || player->pflags & PF_NIGHTSMODE)) + if ((roversector || P_MobjReadyToTrigger(player->mo, sector)) && (player->powers[pw_underwater] || player->powers[pw_carry] == CR_NIGHTSMODE)) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_WATER); break; case 3: // Damage (Fire) @@ -3792,7 +3792,7 @@ DoneSection2: if (!(player->pflags & PF_SPINNING)) player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); } player->powers[pw_flashing] = TICRATE/3; @@ -3953,7 +3953,7 @@ DoneSection2: if (!(player->pflags & PF_SPINNING) && P_IsObjectOnGround(player->mo) && (player->charability2 == CA2_SPINDASH)) { player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); S_StartAttackSound(player->mo, sfx_spin); if (abs(player->rmomx) < FixedMul(5*FRACUNIT, player->mo->scale) @@ -4030,12 +4030,12 @@ DoneSection2: player->powers[pw_carry] = CR_ZOOMTUBE; player->speed = speed; player->pflags |= PF_SPINNING; - player->pflags &= ~(PF_JUMPED|PF_GLIDING|PF_SLIDING|PF_CANCARRY); + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_SLIDING|PF_CANCARRY); player->climbing = 0; - if (player->mo->state-states != S_PLAY_SPIN) + if (player->mo->state-states != S_PLAY_ROLL) { - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); S_StartSound(player->mo, sfx_spin); } } @@ -4110,12 +4110,12 @@ DoneSection2: player->powers[pw_carry] = CR_ZOOMTUBE; player->speed = speed; player->pflags |= PF_SPINNING; - player->pflags &= ~(PF_JUMPED|PF_GLIDING|PF_SLIDING|PF_CANCARRY); + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_SLIDING|PF_CANCARRY); player->climbing = 0; - if (player->mo->state-states != S_PLAY_SPIN) + if (player->mo->state-states != S_PLAY_ROLL) { - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); S_StartSound(player->mo, sfx_spin); } } @@ -4128,7 +4128,7 @@ DoneSection2: { player->laps++; - if (player->pflags & PF_NIGHTSMODE) + if (player->powers[pw_carry] == CR_NIGHTSMODE) player->drillmeter += 48*20; if (player->laps >= (UINT8)cv_numlaps.value) @@ -4418,7 +4418,7 @@ DoneSection2: S_StartSound(player->mo, sfx_s3k4a); - player->pflags &= ~(PF_JUMPED|PF_GLIDING|PF_SLIDING|PF_CANCARRY); + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_SLIDING|PF_CANCARRY); player->climbing = 0; P_SetThingPosition(player->mo); P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); @@ -7301,7 +7301,7 @@ static inline boolean PIT_PushThing(mobj_t *thing) return false; // Allow this to affect pushable objects at some point? - if (thing->player && (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) || thing->player->pflags & PF_NIGHTSMODE)) + if (thing->player && (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) || thing->player->powers[pw_carry] == CR_NIGHTSMODE)) { INT32 dist; INT32 speed; @@ -7332,7 +7332,7 @@ static inline boolean PIT_PushThing(mobj_t *thing) // Written with bits and pieces of P_HomingAttack if ((speed > 0) && (P_CheckSight(thing, tmpusher->source))) { - if (!(thing->player->pflags & PF_NIGHTSMODE)) + if (thing->player->powers[pw_carry] != CR_NIGHTSMODE) { // only push wrt Z if health & 1 (mapthing has ambush flag) if (tmpusher->source->health & 1) @@ -7661,11 +7661,11 @@ void T_Pusher(pusher_t *p) { if (p->slider && thing->player) { - boolean jumped = (thing->player->pflags & PF_JUMPED); + pflags_t jumped = (thing->player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE)); P_ResetPlayer (thing->player); if (jumped) - thing->player->pflags |= PF_JUMPED; + thing->player->pflags |= jumped; thing->player->pflags |= PF_SLIDING; P_SetPlayerMobjState (thing, thing->info->painstate); // Whee! diff --git a/src/p_telept.c b/src/p_telept.c index 671accb0f777b3fafc15a7e6b36e8ebbb344314c..f70c4664c810c2f38568377b8eaca471826b63f7 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -163,6 +163,7 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle if (playeringame[p] && players[p].mo && players[p].powers[pw_carry] == CR_PLAYER && players[p].mo->tracer == thing) { players[p].powers[pw_carry] = CR_NONE; + P_SetTarget(&players[p].mo->tracer, NULL); break; } thing->player->cmomx = thing->player->cmomy = 0; diff --git a/src/p_user.c b/src/p_user.c index a6df976fec6eee81fe653219b545030e4deb99c8..d46f5130e68f809cfafba796fed7a55dcb2175ec 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -325,6 +325,7 @@ void P_GiveEmerald(boolean spawnObj) } } +#if 0 // // P_ResetScore // @@ -335,6 +336,7 @@ void P_ResetScore(player_t *player) player->scoreadd = 0; } +#endif // // P_FindLowestMare @@ -574,12 +576,11 @@ static void P_DeNightserizePlayer(player_t *player) thinker_t *th; mobj_t *mo2; - player->pflags &= ~PF_NIGHTSMODE; + player->powers[pw_carry] = CR_NONE; player->powers[pw_underwater] = 0; - player->pflags &= ~(PF_USEDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_THOKKED|PF_SPINNING|PF_DRILLING|PF_TRANSFERTOCLOSEST); + player->pflags &= ~(PF_USEDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SPINNING|PF_DRILLING|PF_TRANSFERTOCLOSEST); player->secondjump = 0; - player->jumping = 0; player->homing = 0; player->climbing = 0; player->mo->fuse = 0; @@ -609,7 +610,7 @@ static void P_DeNightserizePlayer(player_t *player) { INT32 i; for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) + if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) players[i].nightstime = 1; // force everyone else to fall too. player->exiting = 3*TICRATE; stagefailed = true; // NIGHT OVER @@ -643,14 +644,14 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) { INT32 oldmare; - // Bots can't be super, silly!1 :P + // Bots can't be NiGHTSerized, silly!1 :P if (player->bot) return; - if (!(player->pflags & PF_NIGHTSMODE)) + if (player->powers[pw_carry] != CR_NIGHTSMODE) player->mo->height = P_GetPlayerHeight(player); // Just to make sure jumping into the drone doesn't result in a squashed hitbox. - player->pflags &= ~(PF_USEDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_THOKKED|PF_SHIELDABILITY|PF_SPINNING|PF_DRILLING); + player->pflags &= ~(PF_USEDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY|PF_SPINNING|PF_DRILLING); player->homing = 0; player->mo->fuse = 0; player->speed = 0; @@ -658,6 +659,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->secondjump = 0; player->powers[pw_shield] = SH_NONE; + player->powers[pw_super] = 0; player->mo->flags |= MF_NOGRAVITY; @@ -696,7 +698,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) if (G_IsSpecialStage(gamemap)) { for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]/* && players[i].pflags & PF_NIGHTSMODE*/) + if (playeringame[i]/* && players[i].powers[pw_carry] == CR_NIGHTSMODE*/) total_rings += players[i].rings; } @@ -764,7 +766,14 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) player->texttimer = (UINT8)(110 - timeinmap); } - player->pflags |= PF_NIGHTSMODE; + player->powers[pw_carry] = CR_NIGHTSMODE; +} + +pflags_t P_GetJumpFlags(player_t *player) +{ + if (player->charflags & SF_NOJUMPDAMAGE) + return (PF_JUMPED|PF_NOJUMPDAMAGE); + return PF_JUMPED; } // @@ -870,9 +879,11 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) // Useful when you want to kill everything the player is doing. void P_ResetPlayer(player_t *player) { - player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_JUMPED|PF_FORCEJUMPDAMAGE|PF_GLIDING|PF_THOKKED|PF_CANCARRY|PF_SHIELDABILITY); - player->powers[pw_carry] = CR_NONE; - player->jumping = 0; + player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_THOKKED|PF_CANCARRY|PF_SHIELDABILITY|PF_BOUNCING); + + if (!(player->powers[pw_carry] == CR_NIGHTSMODE || player->powers[pw_carry] == CR_BRAKGOOP)) + player->powers[pw_carry] = CR_NONE; + player->secondjump = 0; player->glidetime = 0; player->homing = 0; @@ -963,6 +974,7 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_TRANS); player->mo->momx = player->mo->momy = player->mo->momz = 0; + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); if (giverings) player->rings = 50; @@ -1000,7 +1012,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) { // Pseudo-shared score for multiplayer special stages. INT32 i; for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) + if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) { oldscore = players[i].marescore; @@ -1185,7 +1197,7 @@ boolean P_IsObjectInGoop(mobj_t *mo) // boolean P_IsObjectOnGround(mobj_t *mo) { - if (P_IsObjectInGoop(mo)) + if (P_IsObjectInGoop(mo) && !(mo->player && mo->player->pflags & PF_BOUNCING)) { /* // It's a crazy hack that checking if you're on the ground @@ -1570,6 +1582,12 @@ void P_SpawnThokMobj(player_t *player) // scale P_SetScale(mobj, player->mo->scale); mobj->destscale = player->mo->scale; + + if (type == MT_THOK) // spintrail-specific modification for MT_THOK + { + mobj->frame = FF_TRANS70; + mobj->fuse = mobj->tics; + } } P_SetTarget(&mobj->target, player->mo); // the one thing P_SpawnGhostMobj doesn't do @@ -1666,7 +1684,7 @@ void P_DoPlayerExit(player_t *player) if (player->climbing) { player->climbing = 0; - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); } player->powers[pw_underwater] = 0; @@ -1752,10 +1770,13 @@ static void P_CheckBustableBlocks(player_t *player) oldx = player->mo->x; oldy = player->mo->y; - P_UnsetThingPosition(player->mo); - player->mo->x += player->mo->momx; - player->mo->y += player->mo->momy; - P_SetThingPosition(player->mo); + if (!(player->pflags & PF_BOUNCING)) // Bouncers only get to break downwards, not sideways + { + P_UnsetThingPosition(player->mo); + player->mo->x += player->mo->momx; + player->mo->y += player->mo->momy; + P_SetThingPosition(player->mo); + } for (node = player->mo->touching_sectorlist; node; node = node->m_sectorlist_next) { @@ -1775,13 +1796,13 @@ static void P_CheckBustableBlocks(player_t *player) { // If it's an FF_SPINBUST, you have to either be jumping, or coming down // onto the top from a spin. - if (rover->flags & FF_SPINBUST && ((!(player->pflags & PF_JUMPED) && !(player->pflags & PF_SPINNING)) || (player->pflags & PF_STARTDASH))) + if (rover->flags & FF_SPINBUST && ((!(player->pflags & PF_JUMPED) && !(player->pflags & PF_SPINNING) && !(player->pflags & PF_BOUNCING)) || (player->pflags & PF_STARTDASH))) continue; // if it's not an FF_SHATTER, you must be spinning (and not jumping) // or be super // or have CA_GLIDEANDCLIMB - // or be in dashmode with CA_DASHMODE + // or be in dashmode with SF_DASHMODE // or be using CA_TWINSPIN // or be using CA2_MELEE // or are drilling in NiGHTS @@ -1790,7 +1811,8 @@ static void P_CheckBustableBlocks(player_t *player) && !((player->pflags & PF_SPINNING) && !(player->pflags & PF_JUMPED)) && !(player->powers[pw_super]) && !(player->charability == CA_GLIDEANDCLIMB) - && !((player->charability == CA_DASHMODE) && (player->dashmode >= 3*TICRATE)) + && !(player->pflags & PF_BOUNCING) + && !((player->charflags & SF_DASHMODE) && (player->dashmode >= 3*TICRATE)) && !((player->charability == CA_TWINSPIN) && (player->panim == PA_ABILITY)) && !(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) && !(player->pflags & PF_DRILLING) @@ -1800,6 +1822,7 @@ static void P_CheckBustableBlocks(player_t *player) // Only players with CA_GLIDEANDCLIMB, or CA_TWINSPIN/CA2_MELEE users can break this rock... if (!(rover->flags & FF_SHATTER) && (rover->flags & FF_ONLYKNUX) && !(player->charability == CA_GLIDEANDCLIMB + || (player->pflags & PF_BOUNCING) || ((player->charability == CA_TWINSPIN) && (player->panim == PA_ABILITY)) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2))) continue; @@ -1807,6 +1830,13 @@ static void P_CheckBustableBlocks(player_t *player) topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); + if (((player->charability == CA_TWINSPIN) && (player->panim == PA_ABILITY)) + || ((P_MobjFlip(player->mo)*player->mo->momz < 0) && (player->pflags & PF_BOUNCING || ((player->charability2 == CA2_MELEE) && (player->panim == PA_ABILITY2))))) + { + topheight -= player->mo->momz; + bottomheight -= player->mo->momz; + } + // Height checks if (rover->flags & FF_SHATTERBOTTOM) { @@ -1865,10 +1895,13 @@ static void P_CheckBustableBlocks(player_t *player) } } bustupdone: - P_UnsetThingPosition(player->mo); - player->mo->x = oldx; - player->mo->y = oldy; - P_SetThingPosition(player->mo); + if (!(player->pflags & PF_BOUNCING)) + { + P_UnsetThingPosition(player->mo); + player->mo->x = oldx; + player->mo->y = oldy; + P_SetThingPosition(player->mo); + } } static void P_CheckBouncySectors(player_t *player) @@ -1986,7 +2019,7 @@ static void P_CheckBouncySectors(player_t *player) if (player->pflags & PF_SPINNING) { player->pflags &= ~PF_SPINNING; - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); player->pflags |= PF_THOKKED; } } @@ -1998,7 +2031,7 @@ static void P_CheckBouncySectors(player_t *player) if (player->pflags & PF_SPINNING) { player->pflags &= ~PF_SPINNING; - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); player->pflags |= PF_THOKKED; } } @@ -2006,7 +2039,7 @@ static void P_CheckBouncySectors(player_t *player) if ((player->pflags & PF_SPINNING) && player->speed < FixedMul(1<<FRACBITS, player->mo->scale) && player->mo->momz) { player->pflags &= ~PF_SPINNING; - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); } goto bouncydone; @@ -2091,8 +2124,8 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player) || (timeleft == 1*TICRATE + 1) // 0 ) { fixed_t height = (player->mo->eflags & MFE_VERTICALFLIP) - ? player->mo->z - FixedMul(8*FRACUNIT - mobjinfo[MT_DROWNNUMBERS].height, player->mo->scale) - : player->mo->z + player->mo->height + FixedMul(8*FRACUNIT, player->mo->scale); + ? player->mo->z - FixedMul(8*FRACUNIT + mobjinfo[MT_DROWNNUMBERS].height, FixedMul(player->mo->scale, player->shieldscale)) + : player->mo->z + player->mo->height + FixedMul(8*FRACUNIT, FixedMul(player->mo->scale, player->shieldscale)); mobj_t *numbermobj = P_SpawnMobj(player->mo->x, player->mo->y, height, MT_DROWNNUMBERS); @@ -2228,7 +2261,7 @@ static void P_DoBubbleBreath(player_t *player) fixed_t z = player->mo->z; mobj_t *bubble = NULL; - if (!(player->mo->eflags & MFE_UNDERWATER) || ((player->powers[pw_shield] & SH_PROTECTWATER) && !(player->pflags & PF_NIGHTSMODE)) || player->spectator) + if (!(player->mo->eflags & MFE_UNDERWATER) || ((player->powers[pw_shield] & SH_PROTECTWATER) && !(player->powers[pw_carry] == CR_NIGHTSMODE)) || player->spectator) return; if (player->charflags & SF_MACHINE) @@ -2263,7 +2296,7 @@ static void P_DoBubbleBreath(player_t *player) P_SetScale(bubble, bubble->destscale); } - if (player->pflags & PF_NIGHTSMODE) // NiGHTS Super doesn't spawn flight bubbles + if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS Super doesn't spawn flight bubbles return; // Tails stirs up the water while flying in it @@ -2317,33 +2350,28 @@ static void P_DoPlayerHeadSigns(player_t *player) } } } - else if (gametype == GT_CTF) + else if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) // If you have the flag (duh). { - if (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)) // If you have the flag (duh). + // Spawn a got-flag message over the head of the player that + // has it (but not on your own screen if you have the flag). + if (splitscreen || player != &players[consoleplayer]) { - // Spawn a got-flag message over the head of the player that - // has it (but not on your own screen if you have the flag). - if (splitscreen || player != &players[consoleplayer]) + mobj_t *sign = P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, + player->mo->z+player->mo->momz, MT_GOTFLAG); + if (player->mo->eflags & MFE_VERTICALFLIP) + { + sign->z += player->mo->height-P_GetPlayerHeight(player)-mobjinfo[MT_GOTFLAG].height-FixedMul(16*FRACUNIT, player->mo->scale); + sign->eflags |= MFE_VERTICALFLIP; + } + else + sign->z += P_GetPlayerHeight(player)+FixedMul(16*FRACUNIT, player->mo->scale); + if (leveltime & 4) { if (player->gotflag & GF_REDFLAG) - { - if (!(player->mo->eflags & MFE_VERTICALFLIP)) - P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, - player->mo->z+P_GetPlayerHeight(player)+FixedMul(16*FRACUNIT, player->mo->scale)+player->mo->momz, MT_GOTFLAG); - else - P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, - player->mo->z+player->mo->height-P_GetPlayerHeight(player)-mobjinfo[MT_GOTFLAG].height-FixedMul(16*FRACUNIT, player->mo->scale)+player->mo->momz, MT_GOTFLAG)->eflags |= MFE_VERTICALFLIP; - } - if (player->gotflag & GF_BLUEFLAG) - { - if (!(player->mo->eflags & MFE_VERTICALFLIP)) - P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, - player->mo->z+P_GetPlayerHeight(player)+FixedMul(16*FRACUNIT, player->mo->scale)+player->mo->momz, MT_GOTFLAG2); - else - P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, - player->mo->z+player->mo->height-P_GetPlayerHeight(player)-mobjinfo[MT_GOTFLAG2].height-FixedMul(16*FRACUNIT, player->mo->scale)+player->mo->momz, MT_GOTFLAG2)->eflags |= MFE_VERTICALFLIP; - } + P_SetMobjStateNF(sign, S_GOTREDFLAG); } + else if (player->gotflag & GF_BLUEFLAG) + P_SetMobjStateNF(sign, S_GOTBLUEFLAG); } } } @@ -2748,21 +2776,21 @@ static void P_DoClimbing(player_t *player) P_InstaThrust(player->mo, player->mo->angle, FixedMul(4*FRACUNIT, player->mo->scale)); // Lil' boost up. player->climbing = 0; - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); } if (skyclimber) { player->climbing = 0; - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); } } else { player->climbing = 0; - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); } @@ -2780,7 +2808,7 @@ static void P_DoClimbing(player_t *player) if (cmd->buttons & BT_USE && !(player->pflags & PF_JUMPSTASIS)) { player->climbing = 0; - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); P_SetObjectMomZ(player->mo, 4*FRACUNIT, false); P_InstaThrust(player->mo, player->mo->angle, FixedMul(-4*FRACUNIT, player->mo->scale)); @@ -3407,18 +3435,14 @@ static void P_DoSuperStuff(player_t *player) { mobj_t *spark; ticcmd_t *cmd = &player->cmd; - if (player->mo->state >= &states[S_PLAY_SUPER_TRANS] && player->mo->state <= &states[S_PLAY_SUPER_TRANS9]) + if (player->mo->state >= &states[S_PLAY_SUPER_TRANS] + && (player->mo->state < &states[S_PLAY_SUPER_TRANS9] + || (player->mo->state == &states[S_PLAY_SUPER_TRANS9] && player->mo->tics > 1))) // needed to prevent one-frame old colour... return; // don't do anything right now, we're in the middle of transforming! - if (player->pflags & PF_NIGHTSMODE) + if (player->powers[pw_carry] == CR_NIGHTSMODE) return; // NiGHTS Super doesn't mix with normal super - // Does player have all emeralds? If so, flag the "Ready For Super!" - if (ALL7EMERALDS(emeralds) && player->rings >= 50) - player->pflags |= PF_SUPERREADY; - else - player->pflags &= ~PF_SUPERREADY; - if (player->powers[pw_super]) { // If you're super and not Sonic, de-superize! @@ -3491,42 +3515,8 @@ static void P_DoSuperStuff(player_t *player) if (gametype != GT_COOP) player->powers[pw_flashing] = flashingtics-1; - if (player->mo->health > 0) - { - if (player->pflags & PF_JUMPED) - P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); - else if (player->pflags & PF_SPINNING && player->mo->state-states != S_PLAY_DASH) - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); - else switch (player->mo->state-states) - { - default: - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - break; - case S_PLAY_DASH: - break; - case S_PLAY_SUPER_WALK: - P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - break; - case S_PLAY_SUPER_RUN: - P_SetPlayerMobjState(player->mo, S_PLAY_RUN); - break; - case S_PLAY_SUPER_PEEL: - P_SetPlayerMobjState(player->mo, S_PLAY_PEEL); - break; - case S_PLAY_SUPER_PAIN: - P_SetPlayerMobjState(player->mo, S_PLAY_PAIN); - break; - case S_PLAY_SUPER_SPRING: - P_SetPlayerMobjState(player->mo, S_PLAY_SPRING); - break; - case S_PLAY_SUPER_FALL: - P_SetPlayerMobjState(player->mo, S_PLAY_FALL); - break; - case S_PLAY_SUPER_RIDE: - P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); - break; - } - } + if ((player->mo->health > 0) && (player->mo->sprite2 & FF_SPR2SUPER)) + P_SetPlayerMobjState(player->mo, player->mo->state-states); // Inform the netgame that the champion has fallen in the heat of battle. if (gametype != GT_COOP) @@ -3553,10 +3543,10 @@ static void P_DoSuperStuff(player_t *player) // boolean P_SuperReady(player_t *player) { - if (player->pflags & PF_SUPERREADY && !player->powers[pw_super] && !player->powers[pw_tailsfly] + if ((ALL7EMERALDS(emeralds) && player->rings >= 50) && !player->powers[pw_super] && !player->powers[pw_tailsfly] && !(player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_invulnerability] - && !(maptol & TOL_NIGHTS) // don't turn 'regular super' in nights levels + && !(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) return true; @@ -3614,7 +3604,7 @@ void P_DoJump(player_t *player, boolean soundandstate) else if (player->mo->momz < 0) // still descending? player->mo->momz = (39*(FRACUNIT/4))>>1; // just default to the jump height. } - else if (!(player->pflags & PF_JUMPED)) // Spin Attack + else if (!(player->pflags & PF_JUMPED)) // Jump { if (player->mo->ceilingz-player->mo->floorz <= player->mo->height-1) return; @@ -3624,6 +3614,7 @@ void P_DoJump(player_t *player, boolean soundandstate) { player->mo->momz = 9*FRACUNIT; player->powers[pw_carry] = CR_NONE; + P_SetTarget(&player->mo->tracer, NULL); if (player-players == consoleplayer && botingame) CV_SetValue(&cv_analog2, true); } @@ -3631,6 +3622,7 @@ void P_DoJump(player_t *player, boolean soundandstate) { player->mo->momz = 9*FRACUNIT; player->powers[pw_carry] = CR_NONE; + P_SetTarget(&player->mo->tracer, NULL); } else if (player->powers[pw_carry] == CR_ROPEHANG) { @@ -3643,7 +3635,7 @@ void P_DoJump(player_t *player, boolean soundandstate) player->mo->momz = 7*FRACUNIT; if (player->charability == CA_JUMPBOOST && onground) { - if (player->charability2 == CA2_MULTIABILITY) + if (player->charflags & SF_MULTIABILITY) player->mo->momz += FixedMul(FRACUNIT/4, dist6); else player->mo->momz += FixedMul(FRACUNIT/8, dist6); @@ -3653,37 +3645,23 @@ void P_DoJump(player_t *player, boolean soundandstate) player->mo->momz = 24*FRACUNIT; else if (player->powers[pw_super]) { - if (player->charability == CA_FLOAT) - player->mo->momz = 28*FRACUNIT; //Obscene jump height anyone? - else if (player->charability == CA_SLOWFALL) - player->mo->momz = 37*(FRACUNIT/2); //Less obscene because during super, floating propells oneself upward. - else // Default super jump momentum. - player->mo->momz = 13*FRACUNIT; + player->mo->momz = 13*FRACUNIT; // Add a boost for super characters with float/slowfall and multiability. - if (player->charability2 == CA2_MULTIABILITY && - (player->charability == CA_FLOAT || player->charability == CA_SLOWFALL)) - player->mo->momz += 2*FRACUNIT; - else if (player->charability == CA_JUMPBOOST) + if (player->charability == CA_JUMPBOOST) { - if (player->charability2 == CA2_MULTIABILITY) + if (player->charflags & SF_MULTIABILITY) player->mo->momz += FixedMul(FRACUNIT/4, dist6); else player->mo->momz += FixedMul(FRACUNIT/8, dist6); } } - else if (player->charability2 == CA2_MULTIABILITY && - (player->charability == CA_FLOAT || player->charability == CA_SLOWFALL)) - { - // Multiability exceptions, since some abilities cannot effectively use it and need a boost. - player->mo->momz = 12*FRACUNIT; // Increased jump height due to ineffective repeat. - } else { player->mo->momz = 39*(FRACUNIT/4); // Default jump momentum. if (player->charability == CA_JUMPBOOST && onground) { - if (player->charability2 == CA2_MULTIABILITY) + if (player->charflags & SF_MULTIABILITY) player->mo->momz += FixedMul(FRACUNIT/4, dist6); else player->mo->momz += FixedMul(FRACUNIT/8, dist6); @@ -3694,7 +3672,7 @@ void P_DoJump(player_t *player, boolean soundandstate) if (player->mo->eflags & MFE_UNDERWATER) player->mo->momz = FixedMul(player->mo->momz, FixedDiv(117*FRACUNIT, 200*FRACUNIT)); - player->jumping = 1; + player->pflags |= PF_STARTJUMP; } factor = player->jumpfactor; @@ -3702,7 +3680,7 @@ void P_DoJump(player_t *player, boolean soundandstate) if (twodlevel || (player->mo->flags2 & MF2_TWOD)) factor += player->jumpfactor / 10; - if (player->charability2 == CA2_MULTIABILITY && player->charability == CA_DOUBLEJUMP) + if (player->charflags & SF_MULTIABILITY && player->charability == CA_DOUBLEJUMP) factor -= max(0, player->secondjump * player->jumpfactor / ((player->actionspd >> FRACBITS) + 1)); // Reduce the jump height each time P_SetObjectMomZ(player->mo, FixedMul(factor, player->mo->momz), false); // Custom height @@ -3726,7 +3704,7 @@ void P_DoJump(player_t *player, boolean soundandstate) } player->mo->eflags &= ~MFE_APPLYPMOMZ; - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player);; if (soundandstate) { @@ -3804,10 +3782,9 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) { player->mo->momx = player->cmomx; player->mo->momy = player->cmomy; - player->pflags |= PF_STARTDASH|PF_SPINNING; + player->pflags |= (PF_USEDOWN|PF_STARTDASH|PF_SPINNING); player->dashspeed = player->mindash; - P_SetPlayerMobjState(player->mo, S_PLAY_DASH); - player->pflags |= PF_USEDOWN; + P_SetPlayerMobjState(player->mo, S_PLAY_SPINDASH); if (!player->spectator) S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh. } @@ -3831,34 +3808,133 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) } } - // If not moving up or down, and travelling faster than a speed of four while not holding + // If not moving up or down, and travelling faster than a speed of five while not holding // down the spin button and not spinning. // AKA Just go into a spin on the ground, you idiot. ;) else if ((cmd->buttons & BT_USE || ((twodlevel || (player->mo->flags2 & MF2_TWOD)) && cmd->forwardmove < -20)) && !player->climbing && !player->mo->momz && onground && (player->speed > FixedMul(5<<FRACBITS, player->mo->scale) || !canstand) && !(player->pflags & (PF_USEDOWN|PF_SPINNING))) { - player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + player->pflags |= (PF_USEDOWN|PF_SPINNING); + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); if (!player->spectator) S_StartSound(player->mo, sfx_spin); - player->pflags |= PF_USEDOWN; + } + else + // Catapult the player from a spindash rev! + if (onground && !(player->pflags & PF_USEDOWN) && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING)) + { + player->pflags &= ~PF_STARTDASH; + if (player->powers[pw_carry] == CR_BRAKGOOP) + player->dashspeed = 0; + + if (!((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE)) + { + if (player->dashspeed) + { + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + P_InstaThrust(player->mo, player->mo->angle, (player->speed = FixedMul(player->dashspeed, player->mo->scale))); // catapult forward ho!! + } + else + { + P_SetPlayerMobjState(player->mo, S_PLAY_STND); + player->pflags &= ~PF_SPINNING; + } + + if (!player->spectator) + S_StartSound(player->mo, sfx_zoom); + } + + player->dashspeed = 0; + } + break; + case CA2_GUNSLINGER: + if (!player->mo->momz && onground && !player->weapondelay && canstand) + { + if (player->speed > FixedMul(10<<FRACBITS, player->mo->scale)) + {} + else + { + mobj_t *lockon = P_LookForEnemies(player, false, true); + if (lockon) + { + if (player == &players[consoleplayer] || player == &players[secondarydisplayplayer] || player == &players[displayplayer]) // Only display it on your own view. + { + mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + visual->target = lockon; + } + } + if ((cmd->buttons & BT_USE) && !(player->pflags & PF_USEDOWN)) + { + mobj_t *bullet; + + P_SetPlayerMobjState(player->mo, S_PLAY_FIRE); + +#define zpos(posmo) (posmo->z + (posmo->height - mobjinfo[player->revitem].height)/2) + if (lockon) + { + player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockon->x, lockon->y); + bullet = P_SpawnPointMissile(player->mo, lockon->x, lockon->y, zpos(lockon), player->revitem, player->mo->x, player->mo->y, zpos(player->mo)); + if (!demoplayback || P_AnalogMove(player)) + { + if (player == &players[consoleplayer]) + localangle = player->mo->angle; + else if (player == &players[secondarydisplayplayer]) + localangle2 = player->mo->angle; + } + } + else + { + bullet = P_SpawnPointMissile(player->mo, player->mo->x + P_ReturnThrustX(NULL, player->mo->angle, FRACUNIT), player->mo->y + P_ReturnThrustY(NULL, player->mo->angle, FRACUNIT), zpos(player->mo), player->revitem, player->mo->x, player->mo->y, zpos(player->mo)); + if (bullet) + { + bullet->flags &= ~MF_NOGRAVITY; + bullet->momx >>= 1; + bullet->momy >>= 1; + } + } +#undef zpos + + P_SetTarget(&player->mo->tracer, NULL); + player->mo->momx >>= 1; + player->mo->momy >>= 1; + player->pflags |= PF_USEDOWN; + P_SetWeaponDelay(player, TICRATE/2); + } + } } break; case CA2_MELEE: // Melee attack - if (!(player->panim == PA_ABILITY2) && (cmd->buttons & BT_USE) && player->speed < FixedMul(10<<FRACBITS, player->mo->scale) + if (player->panim != PA_ABILITY2 && (cmd->buttons & BT_USE) && !player->mo->momz && onground && !(player->pflags & PF_USEDOWN) && canstand) { P_ResetPlayer(player); - player->mo->z += P_MobjFlip(player->mo); - player->mo->momx = player->cmomx = 0; - player->mo->momy = player->cmomy = 0; - P_SetObjectMomZ(player->mo, player->mindash, false); - P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->maxdash, player->mo->scale)); - P_SetPlayerMobjState(player->mo, S_PLAY_MELEE); + player->pflags |= PF_THOKKED; +#if 0 + if ((player->charability == CA_TWINSPIN) && (player->speed > FixedMul(player->runspeed, player->mo->scale))) + { + P_DoJump(player, false); + player->pflags &= ~PF_STARTJUMP; + player->mo->momz = FixedMul(player->mo->momz, 3*FRACUNIT/2); // NOT 1.5 times the jump height, but 2.25 times. + P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN); + S_StartSound(player->mo, sfx_s3k8b); + } + else +#endif + { + player->mo->z += P_MobjFlip(player->mo); + P_SetObjectMomZ(player->mo, player->mindash, false); + if (player->mo->eflags & MFE_UNDERWATER) + player->mo->momz >>= 1; + if (FixedMul(player->speed, FINECOSINE(((player->mo->angle - R_PointToAngle2(0, 0, player->rmomx, player->rmomy)) >> ANGLETOFINESHIFT) & FINEMASK)) < FixedMul(player->maxdash, player->mo->scale)) + P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->maxdash, player->mo->scale)); + player->mo->momx += player->cmomx; + player->mo->momy += player->cmomy; + P_SetPlayerMobjState(player->mo, S_PLAY_MELEE); + S_StartSound(player->mo, sfx_s3k42); + } player->pflags |= PF_USEDOWN; - S_StartSound(player->mo, sfx_s3k8b); } break; } @@ -3884,43 +3960,16 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) } } - // Catapult the player from a spindash rev! - if (onground && !(player->pflags & PF_USEDOWN) && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING)) - { - player->pflags &= ~PF_STARTDASH; - if (player->powers[pw_ingoop]) - player->dashspeed = 0; - - if (!((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE)) - { - if (player->dashspeed) - { - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); - P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->dashspeed, player->mo->scale)); // catapult forward ho!! - } - else - { - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - player->pflags &= ~PF_SPINNING; - } - - if (!player->spectator) - S_StartSound(player->mo, sfx_zoom); - } - - player->dashspeed = 0; - } - if (onground && player->pflags & PF_STARTDASH) { - if (player->mo->state-states != S_PLAY_DASH) - P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + if (player->mo->state-states != S_PLAY_SPINDASH) + P_SetPlayerMobjState(player->mo, S_PLAY_SPINDASH); // Spawn spin dash dust if (!(player->charflags & SF_NOSPINDASHDUST) && !(player->mo->eflags & MFE_GOOWATER)) P_DoSpinDashDust(player); } else if (onground && player->pflags & PF_SPINNING && !(player->panim == PA_ROLL)) - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); } // @@ -3937,17 +3986,16 @@ void P_DoJumpShield(player_t *player) player->pflags &= ~PF_JUMPED; P_DoJump(player, false); - player->jumping = 0; player->secondjump = 0; player->pflags |= PF_THOKKED|PF_SHIELDABILITY; - player->pflags &= ~PF_SPINNING; + player->pflags &= ~(PF_STARTJUMP|PF_SPINNING|PF_BOUNCING); if (electric) { mobj_t *spark; INT32 i; #define numangles 6 #define limitangle (360/numangles) - angle_t travelangle = player->mo->angle + P_RandomRange(-limitangle, limitangle)*ANG1; + const angle_t travelangle = player->mo->angle + P_RandomRange(-limitangle, limitangle)*ANG1; for (i = 0; i < numangles; i++) { spark = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_THUNDERCOIN_SPARK); @@ -3961,7 +4009,7 @@ void P_DoJumpShield(player_t *player) } else { - player->pflags &= ~PF_JUMPED; + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); P_SetPlayerMobjState(player->mo, S_PLAY_FALL); S_StartSound(player->mo, sfx_wdjump); } @@ -3974,17 +4022,44 @@ void P_DoJumpShield(player_t *player) // void P_DoBubbleBounce(player_t *player) { - player->pflags &= ~(PF_JUMPED|PF_SHIELDABILITY); + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SHIELDABILITY); S_StartSound(player->mo, sfx_s3k44); + P_MobjCheckWater(player->mo); P_DoJump(player, false); if (player->charflags & SF_NOJUMPSPIN) P_SetPlayerMobjState(player->mo, S_PLAY_FALL); player->pflags |= PF_THOKKED; - player->jumping = 0; + player->pflags &= ~PF_STARTJUMP; player->secondjump = UINT8_MAX; player->mo->momz = FixedMul(player->mo->momz, 5*FRACUNIT/4); } +// +// P_DoAbilityBounce +// +// CA_BOUNCE landing handling +// +void P_DoAbilityBounce(player_t *player, boolean changemomz) +{ + fixed_t prevmomz; + if (player->mo->state-states == S_PLAY_BOUNCE_LANDING) + return; + if (changemomz) + { + prevmomz = player->mo->momz; + if (P_MobjFlip(player->mo)*prevmomz < 0) + prevmomz = 0; + else if (player->mo->eflags & MFE_UNDERWATER) + prevmomz /= 2; + P_DoJump(player, false); + player->pflags &= ~(PF_STARTJUMP|PF_JUMPED); + player->mo->momz = (FixedMul(player->mo->momz, 3*FRACUNIT/2) + prevmomz)/2; + } + S_StartSound(player->mo, sfx_boingf); + P_SetPlayerMobjState(player->mo, S_PLAY_BOUNCE_LANDING); + player->pflags |= PF_BOUNCING|PF_THOKKED; +} + // // P_Telekinesis // @@ -4044,9 +4119,20 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) // static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) { + mobj_t *lockon = NULL; + if (player->pflags & PF_JUMPSTASIS) return; + if ((player->charability == CA_HOMINGTHOK) && !player->homing && (player->pflags & PF_JUMPED) && (!(player->pflags & PF_THOKKED) || (player->charflags & SF_MULTIABILITY)) && (lockon = P_LookForEnemies(player, true, false))) + { + if (player == &players[consoleplayer] || player == &players[secondarydisplayplayer] || player == &players[displayplayer]) // Only display it on your own view. + { + mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + visual->target = lockon; + } + } + if (cmd->buttons & BT_USE && !(player->pflags & PF_JUMPDOWN) && !player->exiting && !P_PlayerInPain(player)) { if (player->mo->tracer && player->powers[pw_carry] == CR_MACESPIN) @@ -4067,7 +4153,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) case CA_TELEKINESIS: if (player->pflags & PF_JUMPED) { - if (!(player->pflags & PF_THOKKED) || (player->charability2 == CA2_MULTIABILITY)) + if (!(player->pflags & PF_THOKKED) || (player->charflags & SF_MULTIABILITY)) { P_Telekinesis(player, -FixedMul(player->actionspd, player->mo->scale), // -ve thrust (pulling towards player) @@ -4131,6 +4217,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) else if (player->powers[pw_carry] == CR_MACESPIN && player->mo->tracer) { player->powers[pw_carry] = CR_NONE; + P_SetTarget(&player->mo->tracer, NULL); player->powers[pw_flashing] = TICRATE/4; } else @@ -4159,15 +4246,14 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) case CA_THOK: case CA_HOMINGTHOK: case CA_JUMPTHOK: // Credit goes to CZ64 and Sryder13 for the original - case CA_DASHMODE: // Credit goes to Iceman404 // Now it's Sonic's abilities turn! // THOK! - if (!(player->pflags & PF_THOKKED) || (player->charability2 == CA2_MULTIABILITY)) + if (!(player->pflags & PF_THOKKED) || (player->charflags & SF_MULTIABILITY)) { // Catapult the player fixed_t actionspd = player->actionspd; - if (player->charability == CA_DASHMODE) + if (player->charflags & SF_DASHMODE) actionspd = max(player->normalspeed, FixedDiv(player->speed, player->mo->scale)); if (player->mo->eflags & MFE_UNDERWATER) @@ -4197,13 +4283,20 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) P_SpawnThokMobj(player); - if (player->charability == CA_HOMINGTHOK && !player->homing) + if (player->charability == CA_HOMINGTHOK) { - if (P_LookForEnemies(player, true)) + P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockon)); + if (lockon) { - if (player->mo->tracer) - player->homing = 3*TICRATE; + player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockon->x, lockon->y); + player->homing = 3*TICRATE; } + else + { + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + player->pflags &= ~PF_JUMPED; + } + player->pflags &= ~PF_NOJUMPDAMAGE; } player->pflags &= ~(PF_SPINNING|PF_STARTDASH); @@ -4223,13 +4316,13 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->powers[pw_tailsfly] = tailsflytics + 1; // Set the fly timer - player->pflags &= ~(PF_JUMPED|PF_SPINNING|PF_STARTDASH); + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING|PF_STARTDASH); player->pflags |= (PF_THOKKED|PF_CANCARRY); } break; case CA_GLIDEANDCLIMB: // Now Knuckles-type abilities are checked. - if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) + if (!(player->pflags & PF_THOKKED) || player->charflags & SF_MULTIABILITY) { INT32 glidespeed = player->actionspd; @@ -4242,14 +4335,9 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } break; case CA_DOUBLEJUMP: // Double-Jump - if (!(player->pflags & PF_THOKKED) || ((player->charability2 == CA2_MULTIABILITY) && (player->secondjump < (player->actionspd >> FRACBITS)))) + if (!(player->pflags & PF_THOKKED) || ((player->charflags & SF_MULTIABILITY) && (player->secondjump < (player->actionspd >> FRACBITS)))) { - // Allow infinite double jumping if super. - if (!player->powers[pw_super]) - player->pflags |= PF_THOKKED; - else - player->secondjump = 0; - + player->pflags |= PF_THOKKED; player->pflags &= ~PF_JUMPED; P_DoJump(player, true); player->secondjump++; @@ -4257,11 +4345,21 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) break; case CA_FLOAT: // Float case CA_SLOWFALL: // Slow descent hover - if (!player->secondjump) + if (!(player->pflags & PF_THOKKED) || player->charflags & SF_MULTIABILITY) + { + if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE) + P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + else if (player->speed >= FixedMul(player->runspeed, player->mo->scale)) + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT_RUN); + else + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT); + player->pflags |= PF_THOKKED; + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SPINNING); player->secondjump = 1; + } break; case CA_TELEKINESIS: - if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) + if (!(player->pflags & PF_THOKKED) || player->charflags & SF_MULTIABILITY) { P_Telekinesis(player, FixedMul(player->actionspd, player->mo->scale), // +ve thrust (pushing away from player) @@ -4269,7 +4367,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } break; case CA_FALLSWITCH: - if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) + if (!(player->pflags & PF_THOKKED) || player->charflags & SF_MULTIABILITY) { player->mo->momz = -player->mo->momz; P_SpawnThokMobj(player); @@ -4277,15 +4375,26 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) } break; case CA_AIRDRILL: - if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) + if (!(player->pflags & PF_THOKKED) || player->charflags & SF_MULTIABILITY) { player->flyangle = 56 + (60-(player->actionspd>>FRACBITS))/3; player->pflags |= PF_THOKKED; S_StartSound(player->mo, sfx_spndsh); } break; + case CA_BOUNCE: + if (!(player->pflags & PF_THOKKED) || player->charflags & SF_MULTIABILITY) + { + P_SetPlayerMobjState(player->mo, S_PLAY_BOUNCE); + player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); + player->pflags |= PF_THOKKED|PF_BOUNCING; + player->mo->momx >>= 1; + player->mo->momy >>= 1; + player->mo->momz >>= 1; + } + break; case CA_TWINSPIN: - if (!(player->pflags & PF_THOKKED) || player->charability2 == CA2_MULTIABILITY) + if (!(player->pflags & PF_THOKKED) || player->charflags & SF_MULTIABILITY) { player->pflags |= PF_THOKKED; S_StartSound(player->mo, sfx_s3k42); @@ -4337,20 +4446,17 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if ((gametype != GT_CTF || !player->gotflag) && !player->exiting) { - if (player->secondjump == 1) + if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP) { - if (player->charability == CA_FLOAT) - player->mo->momz = 0; - else if (player->charability == CA_SLOWFALL) - { - if (player->powers[pw_super]) - { - if (P_MobjFlip(player->mo)*player->mo->momz < gravity*16) - player->mo->momz = P_MobjFlip(player->mo)*gravity*16; //Float upward 4x as fast while super. - } - else if (P_MobjFlip(player->mo)*player->mo->momz < -gravity*4) - player->mo->momz = P_MobjFlip(player->mo)*-gravity*4; - } + fixed_t potentialmomz; + if (player->charability == CA_SLOWFALL) + potentialmomz = -gravity*4; + else + potentialmomz = ((player->speed < 10*player->mo->scale) + ? (player->speed - 10*player->mo->scale)/5 + : 0); + if (P_MobjFlip(player->mo)*player->mo->momz < potentialmomz) + player->mo->momz = P_MobjFlip(player->mo)*potentialmomz; player->pflags &= ~PF_SPINNING; } } @@ -4360,25 +4466,34 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->pflags &= ~PF_JUMPDOWN; // Repeat abilities, but not double jump! - if (player->charability2 == CA2_MULTIABILITY && player->charability != CA_DOUBLEJUMP) - player->secondjump = 0; - else if (player->charability == CA_FLOAT && player->secondjump == 1) - player->secondjump = 2; + if (player->secondjump == 1 && player->charability != CA_DOUBLEJUMP) + { + if (player->charflags & SF_MULTIABILITY) + { + player->pflags |= (PF_JUMPED|PF_NOJUMPDAMAGE); + player->secondjump = 0; + } + else + player->secondjump = 2; + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + } // If letting go of the jump button while still on ascent, cut the jump height. - if (player->pflags & PF_JUMPED && P_MobjFlip(player->mo)*player->mo->momz > 0 && player->jumping == 1) + if (((player->pflags & (PF_JUMPED|PF_STARTJUMP)) == (PF_JUMPED|PF_STARTJUMP)) && (P_MobjFlip(player->mo)*player->mo->momz > 0)) { player->mo->momz >>= 1; - player->jumping = 0; + player->pflags &= ~PF_STARTJUMP; } } } +#if 0 boolean P_AnalogMove(player_t *player) { return player->pflags & PF_ANALOGMODE; } +#endif // // P_GetPlayerControlDirection @@ -4484,6 +4599,8 @@ static void P_2dMovement(player_t *player) player->skidtime = 0; } } + if (player->pflags & PF_BOUNCING) + player->pflags &= ~PF_BOUNCING; if (player->pflags & PF_SPINNING && !player->exiting) { player->pflags &= ~PF_SPINNING; @@ -4643,6 +4760,7 @@ static void P_3dMovement(player_t *player) angle_t dangle; // replaces old quadrants bits fixed_t normalspd = FixedMul(player->normalspeed, player->mo->scale); boolean analogmove = false; + boolean spin = (player->pflags & PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH)); fixed_t oldMagnitude, newMagnitude; #ifdef ESLOPE vector3_t totalthrust; @@ -4672,6 +4790,8 @@ static void P_3dMovement(player_t *player) player->skidtime = 0; } } + if (player->pflags & PF_BOUNCING) + player->pflags &= ~PF_BOUNCING; if (player->pflags & PF_SPINNING && !player->exiting) { player->pflags &= ~PF_SPINNING; @@ -4790,15 +4910,40 @@ static void P_3dMovement(player_t *player) topspeed = normalspd; } + if (spin) // Prevent gaining speed whilst rolling! + { + const fixed_t ns = FixedDiv(549*ORIG_FRICTION,500*FRACUNIT); // P_XYFriction + if (onground) + topspeed = FixedMul(oldMagnitude, ns); + else + topspeed = oldMagnitude; + } + // Better maneuverability while flying - if(player->powers[pw_tailsfly]) + if (player->powers[pw_tailsfly]) { thrustfactor = player->thrustfactor*2; acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration; } + else + { + if (player->pflags & PF_BOUNCING) + { + if (player->mo->state-states == S_PLAY_BOUNCE_LANDING) + { + thrustfactor = player->thrustfactor*8; + acceleration = player->accelstart/8 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration/8; + } + else + { + thrustfactor = (3*player->thrustfactor)/4; + acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration; + } + } - if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration... - acceleration = FixedMul(acceleration<<FRACBITS, player->mo->movefactor)>>FRACBITS; + if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration... + acceleration = FixedMul(acceleration<<FRACBITS, player->mo->movefactor)>>FRACBITS; + } // Forward movement if (player->climbing) @@ -4819,12 +4964,11 @@ static void P_3dMovement(player_t *player) // Allow a bit of movement while spinning if (player->pflags & PF_SPINNING) { - if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0)) + if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0) + || (player->pflags & PF_STARTDASH)) movepushforward = 0; - else if (!(player->pflags & PF_STARTDASH)) - movepushforward = FixedDiv(movepushforward, 16*FRACUNIT); else - movepushforward = 0; + movepushforward = FixedDiv(movepushforward, 16*FRACUNIT); } movepushforward = FixedMul(movepushforward, player->mo->scale); @@ -4862,12 +5006,11 @@ static void P_3dMovement(player_t *player) { // Stupid little movement prohibitor hack // that REALLY shouldn't belong in analog code. - if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0)) + if ((mforward && cmd->forwardmove > 0) || (mbackward && cmd->forwardmove < 0) + || (player->pflags & PF_STARTDASH)) movepushforward = 0; - else if (!(player->pflags & PF_STARTDASH)) - movepushforward = FixedDiv(movepushforward, 16*FRACUNIT); else - movepushforward = 0; + movepushforward = FixedDiv(movepushforward, 16*FRACUNIT); } movepushsideangle = controldirection; @@ -4898,10 +5041,10 @@ static void P_3dMovement(player_t *player) // Allow a bit of movement while spinning if (player->pflags & PF_SPINNING) { - if (!(player->pflags & PF_STARTDASH)) - movepushside = FixedDiv(movepushside,16*FRACUNIT); - else + if ((player->pflags & PF_STARTDASH)) movepushside = 0; + else + movepushside = FixedDiv(movepushside,16*FRACUNIT); } // Finally move the player now that his speed/direction has been decided. @@ -4951,7 +5094,7 @@ static void P_3dMovement(player_t *player) if (newMagnitude > topspeed) { fixed_t tempmomx, tempmomy; - if (oldMagnitude > topspeed) + if (oldMagnitude > topspeed && !spin) { if (newMagnitude > oldMagnitude) { @@ -5101,25 +5244,16 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad if (player->exiting) return; - /* - In some ways worse, in some ways better. - I did the following this way because the player object has to deal with touchspecials too, not just solids. - There were all sorts of fun bugs when the player got to touch the goal a frame earlier than it should've. - Technically, we lose out on being blocked by MF_SOLID objects, but official stages don't use them on the track. - I know we probably could've kept around MT_NIGHTSCHAR in some fashion, having an invisible hitbox following the - player around... but I'd already removed all its references, restructured the way the chaos emerald follows - the player around to fill the player->mo->tracer gap left behind, and NiGHTS is a lag magnet (lagnet?) - enough as it is... so whatever. - ~toast - */ - { - fixed_t prevx = player->mo->x; - fixed_t prevy = player->mo->y; + { boolean notallowed; - player->mo->flags |= MF_NOCLIPTHING; // player = NULL; // YIKES - notallowed = (!(P_TryMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, true))); - P_TeleportMove(player->mo, prevx, prevy, player->mo->z); - player->mo->flags &= ~MF_NOCLIPTHING; // player = player; // unyikes + mobj_t *hack = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_NULL); + hack->flags = MF_NOGRAVITY; + hack->radius = player->mo->radius; + hack->height = player->mo->height; + hack->z = player->mo->z; + P_SetThingPosition(hack); + notallowed = (!(P_TryMove(hack, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, true))); + P_RemoveMobj(hack); if (notallowed) return; } @@ -5550,7 +5684,7 @@ static void P_DoNiGHTSCapsule(player_t *player) else if (player->mo->z < player->capsule->z+(player->capsule->height/3)) player->mo->momz = 2*FRACUNIT; - if (player->pflags & PF_NIGHTSMODE) + if (player->powers[pw_carry] == CR_NIGHTSMODE) { if (player->mo->momx || player->mo->momy || player->mo->momz) { @@ -5628,7 +5762,7 @@ static void P_DoNiGHTSCapsule(player_t *player) P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); }*/ - if (player->pflags & PF_NIGHTSMODE) + if (player->powers[pw_carry] == CR_NIGHTSMODE) { // 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); @@ -5642,7 +5776,7 @@ static void P_DoNiGHTSCapsule(player_t *player) // Find the player with the lowest time remaining and award points based on that time instead. lowest_time = player->finishedtime; for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) + if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) if (players[i].finishedtime < lowest_time) lowest_time = players[i].finishedtime; P_AddPlayerScore(player, (lowest_time/TICRATE) * 100); @@ -5715,7 +5849,7 @@ static void P_NiGHTSMovement(player_t *player) player->drillmeter = TICRATE/10; } - if (!(player->pflags & PF_NIGHTSMODE)) + if (!(player->powers[pw_carry] == CR_NIGHTSMODE)) { P_DeNightserizePlayer(player); return; @@ -5726,7 +5860,7 @@ static void P_NiGHTSMovement(player_t *player) boolean capsule = false; // NiGHTS special stages have a pseudo-shared timer, so check if ANYONE is feeding the capsule. for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] /*&& players[i].pflags & PF_NIGHTSMODE*/ + if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/ && (players[i].capsule && players[i].capsule->reactiontime)) capsule = true; if (!capsule @@ -5937,21 +6071,19 @@ static void P_NiGHTSMovement(player_t *player) if (player->bumpertime) { - player->jumping = 1; - player->pflags |= PF_DRILLING; + player->pflags |= (PF_STARTJUMP|PF_DRILLING); newangle = (INT16)player->flyangle; } else if (cmd->buttons & BT_JUMP && player->drillmeter && player->drilldelay == 0) { - if (!player->jumping) + if (!(player->pflags & PF_STARTJUMP)) firstdrill = true; - player->jumping = 1; - player->pflags |= PF_DRILLING; + player->pflags |= (PF_STARTJUMP|PF_DRILLING); } else { - player->jumping = 0; + player->pflags &= ~PF_STARTJUMP; if (cmd->sidemove != 0) moved = true; @@ -6392,7 +6524,7 @@ static void P_SkidStuff(player_t *player) if (!onground) { player->skidtime = 0; - player->pflags &= ~(PF_GLIDING|PF_JUMPED); + player->pflags &= ~(PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE); P_SetPlayerMobjState(player->mo, S_PLAY_FALL); } // Get up and brush yourself off, idiot. @@ -6409,16 +6541,18 @@ static void P_SkidStuff(player_t *player) // Spawn a particle every 3 tics. else if (!(player->skidtime % 3)) { - mobj_t *particle = P_SpawnMobj(player->mo->x + P_RandomRange(-player->mo->radius, player->mo->radius), player->mo->y + P_RandomRange(-player->mo->radius, player->mo->radius), - player->mo->z + (player->mo->eflags & MFE_VERTICALFLIP ? player->mo->height - mobjinfo[MT_PARTICLE].height : 0), - MT_PARTICLE); + mobj_t *particle = P_SpawnMobjFromMobj(player->mo, P_RandomRange(-player->mo->radius, player->mo->radius), P_RandomRange(-player->mo->radius, player->mo->radius), 0, MT_SPINDUST); particle->tics = 10; - particle->eflags |= player->mo->eflags & MFE_VERTICALFLIP; - P_SetScale(particle, player->mo->scale >> 2); - particle->destscale = player->mo->scale << 2; - particle->scalespeed = FixedMul(particle->scalespeed, player->mo->scale); // scale the scaling speed! + particle->destscale = (2*player->mo->scale)/3; + P_SetScale(particle, particle->destscale); P_SetObjectMomZ(particle, FRACUNIT, false); + + if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version + P_SetMobjState(particle, S_SPINDUST_BUBBLE1); + else if (player->powers[pw_shield] == SH_ELEMENTAL) + P_SetMobjState(particle, S_SPINDUST_FIRE1); + S_StartSound(player->mo, sfx_s3k7e); // the proper "Knuckles eats dirt" sfx. } } @@ -6430,16 +6564,17 @@ static void P_SkidStuff(player_t *player) // Spawn a particle every 3 tics. if (!(player->skidtime % 3)) { - mobj_t *particle = P_SpawnMobj(player->mo->x, player->mo->y, - player->mo->z + (player->mo->eflags & MFE_VERTICALFLIP ? player->mo->height - mobjinfo[MT_PARTICLE].height : 0), - MT_PARTICLE); + mobj_t *particle = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SPINDUST); particle->tics = 10; - particle->eflags |= player->mo->eflags & MFE_VERTICALFLIP; - P_SetScale(particle, player->mo->scale >> 2); - particle->destscale = player->mo->scale << 2; - particle->scalespeed = FixedMul(particle->scalespeed, player->mo->scale); // scale the scaling speed! + particle->destscale = (2*player->mo->scale)/3; + P_SetScale(particle, particle->destscale); P_SetObjectMomZ(particle, FRACUNIT, false); + + if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version + P_SetMobjState(particle, S_SPINDUST_BUBBLE1); + else if (player->powers[pw_shield] == SH_ELEMENTAL) + P_SetMobjState(particle, S_SPINDUST_FIRE1); } } else if (P_AproxDistance(pmx, pmy) >= FixedMul(player->runspeed/2, player->mo->scale) // if you were moving faster than half your run speed last frame @@ -6456,11 +6591,10 @@ static void P_SkidStuff(player_t *player) // If your push angle is more than this close to a full 180 degrees, trigger a skid. if (dang > ANGLE_157h) { - player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; - S_StartSound(player->mo, sfx_skid); if (player->panim != PA_WALK) P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - player->mo->tics = player->skidtime; + player->mo->tics = player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; + S_StartSound(player->mo, sfx_skid); } } } @@ -6497,9 +6631,10 @@ static void P_MovePlayer(player_t *player) runspd = FixedMul(runspd, player->mo->movefactor); // Control relinquishing stuff! - if (player->powers[pw_ingoop]) - player->pflags |= PF_FULLSTASIS; - else if (player->pflags & PF_GLIDING && player->skidtime) + if ((player->powers[pw_carry] == CR_BRAKGOOP) + || (player->pflags & PF_GLIDING && player->skidtime) + || (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2) + || (player->charability2 == CA2_MELEE && player->mo->state-states == S_PLAY_MELEE_LANDING)) player->pflags |= PF_FULLSTASIS; else if (player->powers[pw_nocontrol]) { @@ -6550,7 +6685,7 @@ static void P_MovePlayer(player_t *player) // Locate the capsule for this mare. else if (maptol & TOL_NIGHTS) { - if ((player->pflags & PF_NIGHTSMODE) + if ((player->powers[pw_carry] == CR_NIGHTSMODE) && !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS] && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6] // NOT 9 - it's 6 when the player turns their supercolor. && !(player->exiting))) @@ -6583,7 +6718,7 @@ static void P_MovePlayer(player_t *player) } // Test revamped NiGHTS movement. - if (player->pflags & PF_NIGHTSMODE) + if (player->powers[pw_carry] == CR_NIGHTSMODE) { P_NiGHTSMovement(player); // No more goto blockchecking, let's just do all that here =D @@ -6642,16 +6777,22 @@ static void P_MovePlayer(player_t *player) if ((cmd->forwardmove != 0 || cmd->sidemove != 0) || (player->powers[pw_super] && !onground)) { // If the player is in dashmode, here's their peelout. - if (player->charability == CA_DASHMODE && player->dashmode >= 3*TICRATE && player->panim == PA_RUN && !player->skidtime && (onground || player->powers[pw_super])) - P_SetPlayerMobjState (player->mo, S_PLAY_PEEL); + if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim == PA_RUN && !player->skidtime && (onground || ((player->charability == CA_FLOAT || player->charability == CA_SLOWFALL) && player->secondjump == 1) || player->powers[pw_super])) + P_SetPlayerMobjState (player->mo, S_PLAY_DASH); // If the player is moving fast enough, // break into a run! - else if (player->speed >= runspd && player->panim == PA_WALK && !player->skidtime && (onground || player->powers[pw_super])) - P_SetPlayerMobjState (player->mo, S_PLAY_RUN); + else if (player->speed >= runspd && player->panim == PA_WALK && !player->skidtime + && (onground || ((player->charability == CA_FLOAT || player->charability == CA_SLOWFALL) && player->secondjump == 1) || player->powers[pw_super])) + { + if (!onground) + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT_RUN); + else + P_SetPlayerMobjState(player->mo, S_PLAY_RUN); + } - // Super floating at slow speeds has its own special animation. - else if (player->powers[pw_super] && player->panim == PA_IDLE && !onground) - P_SetPlayerMobjState (player->mo, S_PLAY_SUPER_FLOAT); + // Floating at slow speeds has its own special animation. + else if ((((player->charability == CA_FLOAT || player->charability == CA_SLOWFALL) && player->secondjump == 1) || player->powers[pw_super]) && player->panim == PA_IDLE && !onground) + P_SetPlayerMobjState (player->mo, S_PLAY_FLOAT); // Otherwise, just walk. else if ((player->rmomx || player->rmomy) && player->panim == PA_IDLE) @@ -6660,19 +6801,28 @@ static void P_MovePlayer(player_t *player) // If your peelout animation is playing, and you're // going too slow, switch back to the run. - if (player->charability == CA_DASHMODE && player->panim == PA_PEEL && player->dashmode < 3*TICRATE) + if (player->charflags & SF_DASHMODE && player->panim == PA_DASH && player->dashmode < 3*TICRATE) P_SetPlayerMobjState(player->mo, S_PLAY_RUN); // If your running animation is playing, and you're // going too slow, switch back to the walking frames. if (player->panim == PA_RUN && player->speed < runspd) { - if (!onground && player->powers[pw_super]) - P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_FLOAT); + if (!onground && (((player->charability == CA_FLOAT || player->charability == CA_SLOWFALL) && player->secondjump == 1) || player->powers[pw_super])) + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT); else P_SetPlayerMobjState(player->mo, S_PLAY_WALK); } + // Correct floating when ending up on the ground. + if (onground) + { + if (player->mo->state-states == S_PLAY_FLOAT) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else if (player->mo->state-states == S_PLAY_FLOAT_RUN) + P_SetPlayerMobjState(player->mo, S_PLAY_RUN); + } + // If Springing (or nojumpspinning), but travelling DOWNWARD, change back! if ((player->panim == PA_SPRING && P_MobjFlip(player->mo)*player->mo->momz < 0) || ((((player->charflags & SF_NOJUMPSPIN) && (player->pflags & PF_JUMPED) && player->panim == PA_JUMP)) @@ -6696,10 +6846,8 @@ static void P_MovePlayer(player_t *player) if (onground && player->pflags & PF_JUMPED && !(player->pflags & PF_GLIDING) && P_MobjFlip(player->mo)*player->mo->momz < 0) { - player->pflags &= ~PF_JUMPED; - player->jumping = 0; + player->pflags &= ~(PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY); player->secondjump = 0; - player->pflags &= ~PF_THOKKED; P_SetPlayerMobjState(player->mo, S_PLAY_STND); } @@ -6710,7 +6858,7 @@ static void P_MovePlayer(player_t *player) P_SetPlayerMobjState(player->mo, S_PLAY_WALK); else { - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); } player->pflags &= ~PF_GLIDING; @@ -6718,6 +6866,19 @@ static void P_MovePlayer(player_t *player) player->climbing = 0; } + if ((!(player->charability == CA_BOUNCE) || player->gotflag) // If you can't bounce, then why the heck would you be bouncing? + && (player->pflags & PF_BOUNCING)) + { + if (onground) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else + { + player->pflags |= P_GetJumpFlags(player); + P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); + } + player->pflags &= ~PF_BOUNCING; + } + // Glide MOMZ // AKA my own gravity. =) if (player->pflags & PF_GLIDING) @@ -6764,10 +6925,9 @@ static void P_MovePlayer(player_t *player) P_ResetPlayer(player); // down, stop gliding. if (onground) P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - else if (player->charability2 == CA2_MULTIABILITY - && player->charability == CA_GLIDEANDCLIMB) + else if (player->charflags & SF_MULTIABILITY) { - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); } else @@ -6794,6 +6954,30 @@ static void P_MovePlayer(player_t *player) player->mo->momz = 0; } } + else if (player->pflags & PF_BOUNCING) + { + if (!(player->pflags & PF_JUMPDOWN) || (onground && P_MobjFlip(player->mo)*player->mo->momz <= 0)) // If not holding the jump button OR on flat ground + { + P_ResetPlayer(player); // down, stop bouncing. + player->pflags |= PF_THOKKED; + if (onground) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else if (player->charflags & SF_MULTIABILITY) + { + player->pflags |= P_GetJumpFlags(player); + P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); + } + else + { + player->mo->momx >>= 1; + player->mo->momy >>= 1; + player->mo->momz >>= 1; + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + } + } + } + else if (player->mo->state-states == S_PLAY_BOUNCE) + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); // If you're running fast enough, you can create splashes as you run in shallow water. if (!player->climbing @@ -6837,7 +7021,7 @@ static void P_MovePlayer(player_t *player) P_SetPlayerMobjState(player->mo, S_PLAY_WALK); else { - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); } } @@ -6858,7 +7042,7 @@ static void P_MovePlayer(player_t *player) { const fixed_t actionspd = player->actionspd/100; - if (player->charability2 == CA2_MULTIABILITY) + if (player->charflags & SF_MULTIABILITY) { // Adventure-style flying by just holding the button down if (cmd->buttons & BT_JUMP && !(player->pflags & PF_STASIS) && !player->exiting) @@ -6987,7 +7171,7 @@ static void P_MovePlayer(player_t *player) #endif } // Otherwise, face the direction you're travelling. - else if (player->panim == PA_WALK || player->panim == PA_RUN || player->panim == PA_PEEL || player->panim == PA_ROLL || player->panim == PA_JUMP + else if (player->panim == PA_WALK || player->panim == PA_RUN || player->panim == PA_DASH || player->panim == PA_ROLL || player->panim == PA_JUMP || (player->panim == PA_ABILITY && player->mo->state-states == S_PLAY_GLIDE)) player->mo->angle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy); @@ -7005,6 +7189,19 @@ static void P_MovePlayer(player_t *player) if (player->pflags & PF_JUMPED && !player->exiting && player->mo->health) { + mobj_t *lockon = NULL; + if (!player->powers[pw_super] && player->powers[pw_shield] == SH_ATTRACT && !(player->pflags & PF_THOKKED)) + { + if ((lockon = P_LookForEnemies(player, false, false))) + { + if (player == &players[consoleplayer] || player == &players[secondarydisplayplayer] || player == &players[displayplayer]) // Only display it on your own view. + { + mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + visual->target = lockon; + P_SetMobjStateNF(visual, visual->info->spawnstate+1); + } + } + } if (cmd->buttons & BT_USE) // Spin button effects { if (player->powers[pw_super]) // Super can't use shield actives, only passives @@ -7013,13 +7210,16 @@ static void P_MovePlayer(player_t *player) && (player->speed > 5*player->mo->scale) // FixedMul(5<<FRACBITS, player->mo->scale), but scale is FRACUNIT-based && (P_MobjFlip(player->mo)*player->mo->momz <= 0)) { - if (player->panim == PA_PAIN || player->panim == PA_JUMP || player->panim == PA_FALL - || (player->panim == PA_WALK && player->mo->state-states != S_PLAY_SUPER_FLOAT)) - P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_FLOAT); + if (player->panim != PA_RUN && player->panim != PA_WALK) + { + if (player->speed >= FixedMul(player->runspeed, player->mo->scale)) + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT_RUN); + else + P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT); + } player->mo->momz = 0; - player->pflags &= ~PF_SPINNING; - player->jumping = 0; // don't cut jump height after bouncing off something + player->pflags &= ~(PF_STARTJUMP|PF_SPINNING); } } else @@ -7055,10 +7255,11 @@ static void P_MovePlayer(player_t *player) case SH_ATTRACT: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; player->homing = 2; - if (P_LookForEnemies(player, false) && player->mo->tracer) + P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, lockon)); + if (lockon) { - player->pflags |= PF_FORCEJUMPDAMAGE; - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockon->x, lockon->y); + player->pflags &= ~PF_NOJUMPDAMAGE; S_StartSound(player->mo, sfx_s3k40); player->homing = 3*TICRATE; } @@ -7068,8 +7269,9 @@ static void P_MovePlayer(player_t *player) // Elemental/Bubblewrap shield activation case SH_ELEMENTAL: case SH_BUBBLEWRAP: - player->pflags |= PF_FORCEJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY; - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + player->pflags |= PF_THOKKED|PF_SHIELDABILITY; + player->pflags &= ~PF_NOJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); player->secondjump = 0; player->mo->momx = player->mo->momy = 0; P_SetObjectMomZ(player->mo, -24*FRACUNIT, false); @@ -7187,8 +7389,8 @@ static void P_MovePlayer(player_t *player) fixed_t oldheight = player->mo->height; // Less height while spinning. Good for spinning under things...? - if ((player->mo->state == &states[player->mo->info->painstate] || player->mo->state == &states[S_PLAY_SUPER_PAIN]) - || (!(player->charflags & SF_NOJUMPSPIN) && (player->pflags & PF_JUMPED)) + if ((player->mo->state == &states[player->mo->info->painstate]) + || ((player->pflags & PF_JUMPED) && !(player->pflags & PF_NOJUMPDAMAGE && player->charflags & SF_NOJUMPSPIN)) || (player->pflags & PF_SPINNING) || player->powers[pw_tailsfly] || player->pflags & PF_GLIDING || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED)) @@ -7207,7 +7409,7 @@ static void P_MovePlayer(player_t *player) if ((player->charability2 == CA2_SPINDASH) && !(player->pflags & PF_SPINNING)) { player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); } else if (player->mo->ceilingz - player->mo->floorz < player->mo->height) { @@ -7489,7 +7691,7 @@ static void P_DoRopeHang(player_t *player) { P_SetTarget(&player->mo->tracer, NULL); - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); player->powers[pw_carry] = CR_NONE; if (!(player->pflags & PF_SLIDING) && (player->pflags & PF_JUMPED) @@ -7587,7 +7789,7 @@ static void P_DoRopeHang(player_t *player) { if (player->mo->tracer->flags & MF_SLIDEME) { - player->pflags |= PF_JUMPED; + player->pflags |= P_GetJumpFlags(player); if (!(player->pflags & PF_SLIDING) && (player->pflags & PF_JUMPED) && !(player->panim == PA_JUMP)) @@ -7701,13 +7903,18 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) // P_LookForEnemies // Looks for something you can hit - Used for homing attack // If nonenemies is true, includes monitors and springs! +// If bullet is true, you can look up and the distance is further, +// but your total angle span you can look is limited to compensate. // -boolean P_LookForEnemies(player_t *player, boolean nonenemies) +mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) { mobj_t *mo; thinker_t *think; mobj_t *closestmo = NULL; - angle_t an; + const UINT32 targetmask = (MF_ENEMY|MF_BOSS|(nonenemies ? (MF_MONITOR|MF_SPRING) : 0)); + const fixed_t maxdist = FixedMul((bullet ? RING_DIST*2 : RING_DIST), player->mo->scale); + const angle_t span = (bullet ? ANG30 : ANGLE_90); + fixed_t dist, closestdist = 0; for (think = thinkercap.next; think != &thinkercap; think = think->next) { @@ -7715,9 +7922,10 @@ boolean P_LookForEnemies(player_t *player, boolean nonenemies) continue; // not a mobj thinker mo = (mobj_t *)think; - if ((nonenemies && !(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING))) - || (!nonenemies && !(mo->flags & (MF_ENEMY|MF_BOSS)))) - continue; // not a valid enemy + if (!(mo->flags & targetmask + || mo->type == MT_FAKEMOBILE // hehehehe + || mo->type == MT_EGGSHIELD)) + continue; // not a valid target if (mo->health <= 0) // dead continue; @@ -7731,16 +7939,32 @@ boolean P_LookForEnemies(player_t *player, boolean nonenemies) if ((mo->flags & (MF_ENEMY|MF_BOSS)) && !(mo->flags & MF_SHOOTABLE)) // don't aim at something you can't shoot at anyway (see Egg Guard or Minus) continue; - if (mo->type == MT_DETON) // Don't be STUPID, Sonic! + if (!bullet && mo->type == MT_DETON) // Don't be STUPID, Sonic! continue; - if (((mo->z > player->mo->z+FixedMul(MAXSTEPMOVE, player->mo->scale)) && !(player->mo->eflags & MFE_VERTICALFLIP)) - || ((mo->z+mo->height < player->mo->z+player->mo->height-FixedMul(MAXSTEPMOVE, player->mo->scale)) && (player->mo->eflags & MFE_VERTICALFLIP))) // Reverse gravity check - Flame. - continue; // Don't home upwards! + { + fixed_t zdist = (player->mo->z + player->mo->height/2) - (mo->z + mo->height/2); + dist = P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y); + if (bullet) + { + if ((R_PointToAngle2(0, 0, dist, zdist) + span) > span*2) + continue; // Don't home outside of desired angle! + } + else // Don't home upwards! + { + if (player->mo->eflags & MFE_VERTICALFLIP) + { + if (mo->z+mo->height < player->mo->z+player->mo->height-FixedMul(MAXSTEPMOVE, player->mo->scale)) + continue; + } + else if (mo->z > player->mo->z+FixedMul(MAXSTEPMOVE, player->mo->scale)) + continue; + } - if (P_AproxDistance(P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y), - player->mo->z-mo->z) > FixedMul(RING_DIST, player->mo->scale)) - continue; // out of range + dist = P_AproxDistance(dist, zdist); + if (dist > maxdist) + continue; // out of range + } if ((twodlevel || player->mo->flags2 & MF2_TWOD) && abs(player->mo->y-mo->y) > player->mo->radius) @@ -7749,35 +7973,25 @@ boolean P_LookForEnemies(player_t *player, boolean nonenemies) if (mo->type == MT_PLAYER) // Don't chase after other players! continue; - if (closestmo && P_AproxDistance(P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y), - player->mo->z-mo->z) > P_AproxDistance(P_AproxDistance(player->mo->x-closestmo->x, - player->mo->y-closestmo->y), player->mo->z-closestmo->z)) + if (closestmo && dist > closestdist) continue; - an = R_PointToAngle2(player->mo->x, player->mo->y, mo->x, mo->y) - player->mo->angle; - - if (an > ANGLE_90 && an < ANGLE_270) + if ((R_PointToAngle2(player->mo->x, player->mo->y, mo->x, mo->y) - player->mo->angle + span) > span*2) continue; // behind back if (!P_CheckSight(player->mo, mo)) continue; // out of sight closestmo = mo; + closestdist = dist; } - if (closestmo) - { - // Found a target monster - P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, closestmo)); - player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, closestmo->x, closestmo->y); - return true; - } - - return false; + return closestmo; } void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target { + fixed_t zdist; fixed_t dist; fixed_t ns = 0; @@ -7798,8 +8012,8 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target } // change slope - dist = P_AproxDistance(P_AproxDistance(enemy->x - source->x, enemy->y - source->y), - enemy->z - source->z); + zdist = ((P_MobjFlip(source) == -1) ? (enemy->z + enemy->height) - (source->z + source->height) : (enemy->z - source->z)); + dist = P_AproxDistance(P_AproxDistance(enemy->x - source->x, enemy->y - source->y), zdist); if (dist < 1) dist = 1; @@ -7823,7 +8037,7 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns); source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), ns); - source->momz = FixedMul(FixedDiv(enemy->z - source->z, dist), ns); + source->momz = FixedMul(FixedDiv(zdist, dist), ns); } // Search for emeralds @@ -8092,9 +8306,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall subsector_t *newsubsec; fixed_t f1, f2; - cameranoclip = (player->pflags & (PF_NOCLIP|PF_NIGHTSMODE)) || (player->mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)); // Noclipping player camera noclips too!! + cameranoclip = (player->powers[pw_carry] == CR_NIGHTSMODE || player->pflags & PF_NOCLIP) || (player->mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)); // Noclipping player camera noclips too!! - if (!(player->climbing || (player->pflags & PF_NIGHTSMODE) || player->playerstate == PST_DEAD)) + if (!(player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD)) { if (player->spectator) // force cam off for spectators return true; @@ -8141,7 +8355,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // if (leveltime > 0 && timeinmap <= 0) // return true; - if (player->pflags & PF_NIGHTSMODE) + if (player->powers[pw_carry] == CR_NIGHTSMODE) { focusangle = player->mo->angle; focusaiming = 0; @@ -8170,7 +8384,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camspeed = cv_cam_speed.value; camstill = cv_cam_still.value; camrotate = cv_cam_rotate.value; - camdist = FixedMul(cv_cam_dist.value, FixedMul(player->camerascale, mo->scale)); + camdist = FixedMul(cv_cam_dist.value, mo->scale); camheight = FixedMul(cv_cam_height.value, FixedMul(player->camerascale, mo->scale)); } else // Camera 2 @@ -8178,7 +8392,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camspeed = cv_cam2_speed.value; camstill = cv_cam2_still.value; camrotate = cv_cam2_rotate.value; - camdist = FixedMul(cv_cam2_dist.value, FixedMul(player->camerascale, mo->scale)); + camdist = FixedMul(cv_cam2_dist.value, mo->scale); camheight = FixedMul(cv_cam2_height.value, FixedMul(player->camerascale, mo->scale)); } @@ -8198,7 +8412,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall angle = ANGLE_90; else if (camstill || resetcalled || player->playerstate == PST_DEAD) angle = thiscam->angle; - else if (player->pflags & PF_NIGHTSMODE) // NiGHTS Level + else if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS Level { if ((player->pflags & PF_TRANSFERTOCLOSEST) && player->axis1 && player->axis2) { @@ -8237,7 +8451,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall thiscam->angle = angle; } - if (!objectplacing && !(twodlevel || (mo->flags2 & MF2_TWOD)) && !(player->pflags & PF_NIGHTSMODE) && displayplayer == consoleplayer) + if (!objectplacing && !(twodlevel || (mo->flags2 & MF2_TWOD)) && (player->powers[pw_carry] != CR_NIGHTSMODE) && displayplayer == consoleplayer) { #ifdef REDSANALOG if ((player->cmd.buttons & (BT_CAMLEFT|BT_CAMRIGHT)) == (BT_CAMLEFT|BT_CAMRIGHT)); else @@ -8283,7 +8497,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall // sets ideal cam pos if (twodlevel || (mo->flags2 & MF2_TWOD)) dist = 480<<FRACBITS; - else if (player->pflags & PF_NIGHTSMODE) + else if (player->powers[pw_carry] == CR_NIGHTSMODE) dist = 320<<FRACBITS; else { @@ -8293,11 +8507,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (P_AnalogMove(player)) dist = FixedMul(dist, 6*FRACUNIT/5); - if (player->climbing || player->exiting || player->playerstate == PST_DEAD || (player->powers[pw_carry] && player->powers[pw_carry] != CR_PLAYER)) + if (player->climbing || player->exiting || player->playerstate == PST_DEAD || (player->powers[pw_carry] == CR_ROPEHANG || player->powers[pw_carry] == CR_GENERIC || player->powers[pw_carry] == CR_MACESPIN)) dist <<= 1; } - checkdist = dist; + checkdist = (dist = FixedMul(dist, player->camerascale)); if (checkdist < 128*FRACUNIT) checkdist = 128*FRACUNIT; @@ -8635,7 +8849,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall else player->mo->flags2 &= ~MF2_SHADOW; -/* if (!resetcalled && (player->pflags & PF_NIGHTSMODE && player->exiting)) +/* if (!resetcalled && (player->powers[pw_carry] == CR_NIGHTSMODE && player->exiting)) { // Don't let the camera match your movement. thiscam->momz = 0; @@ -8932,17 +9146,21 @@ void P_PlayerThink(player_t *player) } } #endif - if (player->pflags & PF_GLIDING) + if (!player->mo->health) + ; + else if (player->pflags & PF_GLIDING) { if (player->panim != PA_ABILITY) P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE); } - else if ((player->pflags & PF_JUMPED) && !player->powers[pw_super] && ((player->charflags & SF_NOJUMPSPIN && player->pflags & PF_FORCEJUMPDAMAGE && player->panim != PA_ROLL) || (!(player->charflags & SF_NOJUMPSPIN) && player->panim != PA_JUMP))) + else if ((player->pflags & PF_JUMPED && !(player->pflags & PF_NOJUMPDAMAGE)) + && ((player->charflags & SF_NOJUMPSPIN && player->panim != PA_ROLL) + || (!(player->charflags & SF_NOJUMPSPIN) && player->panim != PA_JUMP))) { if (!(player->charflags & SF_NOJUMPSPIN)) P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); - else if (player->pflags & PF_FORCEJUMPDAMAGE) - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + else if (!(player->pflags & PF_NOJUMPDAMAGE)) + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); } if (player->flashcount) @@ -9002,7 +9220,7 @@ void P_PlayerThink(player_t *player) player->pflags |= PF_TIMEOVER; - if (player->pflags & PF_NIGHTSMODE) + if (player->powers[pw_carry] == CR_NIGHTSMODE) { P_DeNightserizePlayer(player); S_StartScreamSound(player->mo, sfx_s3k66); @@ -9128,7 +9346,7 @@ void P_PlayerThink(player_t *player) // Even if not NiGHTS, pull in nearby objects when walking around as John Q. Elliot. if (!objectplacing && !((netgame || multiplayer) && player->spectator) - && maptol & TOL_NIGHTS && (!(player->pflags & PF_NIGHTSMODE) || player->powers[pw_nights_helper])) + && maptol & TOL_NIGHTS && (player->powers[pw_carry] != CR_NIGHTSMODE || player->powers[pw_nights_helper])) { thinker_t *th; mobj_t *mo2; @@ -9187,7 +9405,7 @@ void P_PlayerThink(player_t *player) { P_DoZoomTube(player); if (!(player->panim == PA_ROLL)) - P_SetPlayerMobjState(player->mo, S_PLAY_SPIN); + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); } player->rmomx = player->rmomy = 0; // no actual momentum from your controls P_ResetScore(player); @@ -9238,7 +9456,7 @@ void P_PlayerThink(player_t *player) #endif // check for use - if (!(player->pflags & PF_NIGHTSMODE)) + if (player->powers[pw_carry] != CR_NIGHTSMODE) { if (cmd->buttons & BT_USE) player->pflags |= PF_USEDOWN; @@ -9256,7 +9474,7 @@ void P_PlayerThink(player_t *player) if (player->powers[pw_invulnerability] && player->powers[pw_invulnerability] < UINT16_MAX) player->powers[pw_invulnerability]--; - if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && ((player->pflags & PF_NIGHTSMODE) || player->powers[pw_flashing] < flashingtics)) + if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && ((player->powers[pw_carry] == CR_NIGHTSMODE) || player->powers[pw_flashing] < flashingtics)) player->powers[pw_flashing]--; if (player->powers[pw_tailsfly] && player->powers[pw_tailsfly] < UINT16_MAX && player->charability != CA_SWIM) // tails fly counter @@ -9301,12 +9519,20 @@ void P_PlayerThink(player_t *player) if (player->powers[pw_super]) player->powers[pw_super]++; - if (player->powers[pw_ingoop]) + if (player->powers[pw_carry] == CR_BRAKGOOP) { - if (player->mo->state == &states[S_PLAY_STND]) - player->mo->tics = 2; + if (!player->powers[pw_flashing]) + { + if (player->mo->state != &states[S_PLAY_STND]) + P_SetPlayerMobjState(player->mo, S_PLAY_STND); + else + player->mo->tics = 2; + } + else + P_SetTarget(&player->mo->tracer, NULL); - player->powers[pw_ingoop]--; + if (!player->mo->tracer) + player->powers[pw_carry] = CR_NONE; } if (player->bumpertime) @@ -9349,16 +9575,20 @@ void P_PlayerThink(player_t *player) player->pflags &= ~PF_SLIDING; #define dashmode player->dashmode - // Dash mode ability for Metal Sonic - if ((player->charability == CA_DASHMODE) && !(player->gotflag) && !(maptol & TOL_NIGHTS)) // woo, dashmode! no nights tho. + // Dash mode - thanks be to Iceman404 + if ((player->charflags & SF_DASHMODE) && !(player->gotflag) && !(maptol & TOL_NIGHTS)) // woo, dashmode! no nights tho. { - if (player->speed >= FixedMul(player->runspeed, player->mo->scale) || (player->pflags & PF_STARTDASH)) + boolean totallyradical = player->speed >= FixedMul(player->runspeed, player->mo->scale); + boolean floating = (player->secondjump == 1); + + if ((totallyradical && !floating) || (player->pflags & PF_STARTDASH)) { - dashmode++; // Counter. Adds 1 to dash mode per tic in top speed. + if (dashmode < 3*TICRATE + 3) + dashmode++; // Counter. Adds 1 to dash mode per tic in top speed. if (dashmode == 3*TICRATE) // This isn't in the ">=" equation because it'd cause the sound to play infinitely. S_StartSound(player->mo, sfx_s3ka2); // If the player enters dashmode, play this sound on the the tic it starts. } - else if (!(player->pflags & PF_SPINNING)) + else if ((!totallyradical || !floating) && !(player->pflags & PF_SPINNING)) { if (dashmode > 3) dashmode -= 3; // Rather than lose it all, it gently counts back down! @@ -9373,23 +9603,28 @@ void P_PlayerThink(player_t *player) } else if (P_IsObjectOnGround(player->mo)) // Activate dash mode if we're on the ground. { - if (player->normalspeed < skins[player->skin].actionspd) // If the player normalspeed is not currently at actionspd in dash mode, add speed each tic - player->normalspeed = player->normalspeed + 1*FRACUNIT/5; // Enter Dash Mode smoothly. + if (player->normalspeed < skins[player->skin].normalspeed*2) // If the player normalspeed is not currently at normalspeed*2 in dash mode, add speed each tic + player->normalspeed += FRACUNIT/5; // Enter Dash Mode smoothly. if (player->jumpfactor < FixedMul(skins[player->skin].jumpfactor, 5*FRACUNIT/4)) // Boost jump height. - player->jumpfactor = player->jumpfactor + 1*FRACUNIT/300; + player->jumpfactor += FRACUNIT/300; } - dashmode = min(dashmode, 3*TICRATE + 3); - - if (player->normalspeed >= skins[player->skin].actionspd) + if (player->normalspeed >= skins[player->skin].normalspeed*2) { mobj_t *ghost = P_SpawnGhostMobj(player->mo); // Spawns afterimages ghost->fuse = 2; // Makes the images fade quickly } } - else + else if (dashmode) + { + if (dashmode >= 3*TICRATE) // catch getting the flag! + { + player->normalspeed = skins[player->skin].normalspeed; + player->jumpfactor = skins[player->skin].jumpfactor; + } dashmode = 0; + } #undef dashmode /* // Colormap verification @@ -9465,7 +9700,7 @@ void P_PlayerAfterThink(player_t *player) return; } - if (player->pflags & PF_NIGHTSMODE) + if (player->powers[pw_carry] == CR_NIGHTSMODE) { player->powers[pw_gravityboots] = 0; //player->mo->eflags &= ~MFE_VERTICALFLIP; @@ -9585,18 +9820,16 @@ void P_PlayerAfterThink(player_t *player) } else if (player->pflags & PF_SLIDING) P_SetPlayerMobjState(player->mo, player->mo->info->painstate); - else if (player->pflags & PF_JUMPED - && ((!player->powers[pw_super] && player->panim != PA_JUMP) - || player->mo->state == &states[player->mo->info->painstate]) - && !(player->charflags & SF_NOJUMPSPIN)) - P_SetPlayerMobjState(player->mo, S_PLAY_JUMP); + /* if (player->powers[pw_carry] == CR_NONE && player->mo->tracer && !player->homing) + P_SetTarget(&player->mo->tracer, NULL); + else */ if (player->powers[pw_carry] == CR_PLAYER && player->mo->tracer) { player->mo->height = FixedDiv(P_GetPlayerHeight(player), FixedDiv(14*FRACUNIT,10*FRACUNIT)); if (player->mo->tracer->player && !(player->mo->tracer->player->pflags & PF_CANCARRY)) - player->powers[pw_carry] = CR_NONE; + player->powers[pw_carry] = CR_NONE; if (player->mo->eflags & MFE_VERTICALFLIP) { @@ -9641,7 +9874,10 @@ void P_PlayerAfterThink(player_t *player) if (P_AproxDistance(player->mo->x - player->mo->tracer->x, player->mo->y - player->mo->tracer->y) > player->mo->radius) player->powers[pw_carry] = CR_NONE; - P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); + if (player->powers[pw_carry] != CR_NONE) + P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); + else + P_SetTarget(&player->mo->tracer, NULL); if (player-players == consoleplayer && botingame) CV_SetValue(&cv_analog2, (player->powers[pw_carry] != CR_PLAYER)); @@ -9687,27 +9923,31 @@ void P_PlayerAfterThink(player_t *player) player->mo->momy = (player->mo->tracer->y - player->mo->y)*2; player->mo->momz = (player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2) - player->mo->z)*2; P_TeleportMove(player->mo, player->mo->tracer->x, player->mo->tracer->y, player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2)); - player->pflags |= PF_JUMPED|PF_FORCEJUMPDAMAGE; - player->secondjump = 0; - player->pflags &= ~PF_THOKKED; - - if (cmd->forwardmove > 0) - player->mo->tracer->target->lastlook += 2; - else if (cmd->forwardmove < 0 && player->mo->tracer->target->lastlook > player->mo->tracer->target->movecount) - player->mo->tracer->target->lastlook -= 2; - - if (!(player->mo->tracer->target->flags & MF_SLIDEME) // Noclimb on chain parameters gives this - && !(twodlevel || player->mo->flags2 & MF2_TWOD)) // why on earth would you want to turn them in 2D mode? + if (!player->powers[pw_flashing]) // handle getting hurt { - player->mo->tracer->target->health += cmd->sidemove; - player->mo->angle += cmd->sidemove<<ANGLETOFINESHIFT; // 2048 --> ANGLE_MAX + player->pflags |= PF_JUMPED; + player->pflags &= ~PF_NOJUMPDAMAGE; + player->secondjump = 0; + player->pflags &= ~PF_THOKKED; - if (!demoplayback || P_AnalogMove(player)) + if (cmd->forwardmove > 0) + player->mo->tracer->target->lastlook += 2; + else if (cmd->forwardmove < 0 && player->mo->tracer->target->lastlook > player->mo->tracer->target->movecount) + player->mo->tracer->target->lastlook -= 2; + + if (!(player->mo->tracer->target->flags & MF_SLIDEME) // Noclimb on chain parameters gives this + && !(twodlevel || player->mo->flags2 & MF2_TWOD)) // why on earth would you want to turn them in 2D mode? { - if (player == &players[consoleplayer]) - localangle = player->mo->angle; // Adjust the local control angle. - else if (player == &players[secondarydisplayplayer]) - localangle2 = player->mo->angle; + player->mo->tracer->target->health += cmd->sidemove; + player->mo->angle += cmd->sidemove<<ANGLETOFINESHIFT; // 2048 --> ANGLE_MAX + + if (!demoplayback || P_AnalogMove(player)) + { + if (player == &players[consoleplayer]) + localangle = player->mo->angle; // Adjust the local control angle. + else if (player == &players[secondarydisplayplayer]) + localangle2 = player->mo->angle; + } } } } diff --git a/src/r_draw.c b/src/r_draw.c index 2c1f18826bbe355bc6760bf66f38961f0e82cfbf..29f57b35d8714080f512221d9d9dabfbc2c5be88 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -194,10 +194,10 @@ const UINT8 Color_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_BROWN,8, // SKINCOLOR_PEACH - ditto SKINCOLOR_PEACH,8, // SKINCOLOR_BROWN - ditto SKINCOLOR_GREEN,5, // SKINCOLOR_RED - SKINCOLOR_CYAN,8, // SKINCOLOR_CRIMSON - ditto - SKINCOLOR_BLUE,12, // SKINCOLOR_ORANGE + SKINCOLOR_CYAN,8, // SKINCOLOR_CRIMSON - ditto + SKINCOLOR_BLUE,11, // SKINCOLOR_ORANGE SKINCOLOR_TAN,8, // SKINCOLOR_RUST - ditto - SKINCOLOR_LAVENDER,8, // SKINCOLOR_GOLD - ditto + SKINCOLOR_LAVENDER,8, // SKINCOLOR_GOLD SKINCOLOR_TEAL,8, // SKINCOLOR_YELLOW - ditto SKINCOLOR_RUST,8, // SKINCOLOR_TAN - ditto SKINCOLOR_MAGENTA,3, // SKINCOLOR_MOSS @@ -206,15 +206,15 @@ const UINT8 Color_Opposite[MAXSKINCOLORS*2] = SKINCOLOR_PASTEL,8, // SKINCOLOR_EMERALD - ditto SKINCOLOR_ROSY,8, // SKINCOLOR_AQUA - ditto SKINCOLOR_YELLOW,8, // SKINCOLOR_TEAL - ditto - SKINCOLOR_CRIMSON,8, // SKINCOLOR_CYAN - ditto + SKINCOLOR_CRIMSON,8, // SKINCOLOR_CYAN - ditto SKINCOLOR_ORANGE,9, // SKINCOLOR_BLUE SKINCOLOR_PINK,8, // SKINCOLOR_AZURE - ditto SKINCOLOR_EMERALD,8, // SKINCOLOR_PASTEL - ditto - SKINCOLOR_PERIDOT,10, // SKINCOLOR_PURPLE - ditto - SKINCOLOR_GOLD,8, // SKINCOLOR_LAVENDER - ditto + SKINCOLOR_PERIDOT,10, // SKINCOLOR_PURPLE + SKINCOLOR_GOLD,10, // SKINCOLOR_LAVENDER SKINCOLOR_MOSS,8, // SKINCOLOR_MAGENTA - ditto SKINCOLOR_AZURE,8, // SKINCOLOR_PINK - ditto - SKINCOLOR_AQUA,14 // SKINCOLOR_ROSY - ditto + SKINCOLOR_AQUA,14 // SKINCOLOR_ROSY }; CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; diff --git a/src/r_main.c b/src/r_main.c index 4cff0ff8302c843b97497b1961673d7d171cf328..f970762f4efa60b40668aaa5c0e80b00a0eee67b 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -1000,7 +1000,7 @@ void R_SetupFrame(player_t *player, boolean skybox) chasecam = (cv_chasecam.value != 0); } - if (player->climbing || (player->pflags & PF_NIGHTSMODE) || player->playerstate == PST_DEAD) + if (player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD) chasecam = true; // force chasecam on else if (player->spectator) // no spectator chasecam chasecam = false; // force chasecam off diff --git a/src/r_things.c b/src/r_things.c index cbfcae21c8721179922e7abb0c6d0c3b90183433..2f8e7c91a94b3161208ea31783149f45a1db7943 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1182,7 +1182,7 @@ static void R_ProjectSprite(mobj_t *thing) { sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2]; if (rot >= sprdef->numframes) { - CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[SPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, spr2names[thing->sprite2], sizeu5(rot)); + CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(rot)); thing->sprite = states[S_UNKNOWN].sprite; thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; @@ -2492,7 +2492,11 @@ static void Sk_SetDefaultValue(skin_t *skin) skin->flags = 0; strcpy(skin->realname, "Someone"); +#ifdef SKINNAMEPADDING + strcpy(skin->hudname, " ???"); +#else strcpy(skin->hudname, "???"); +#endif strncpy(skin->charsel, "CHRSONIC", 8); strncpy(skin->face, "MISSING", 8); strncpy(skin->superface, "MISSING", 8); @@ -2554,16 +2558,29 @@ void R_InitSkins(void) numskins = 0; } +UINT32 R_GetSkinAvailabilities(void) +{ + INT32 s; + UINT32 response = 0; + + for (s = 0; s < MAXSKINS; s++) + { + if (skins[s].availability && unlockables[skins[s].availability - 1].unlocked) + response |= (1 << s); + } + return response; +} + // returns true if available in circumstances, otherwise nope // warning don't use with an invalid skinnum other than -1 which always returns true -boolean R_SkinUnlock(INT32 skinnum) +boolean R_SkinUsable(INT32 playernum, INT32 skinnum) { return ((skinnum == -1) // Simplifies things elsewhere, since there's already plenty of checks for less-than-0... || (!skins[skinnum].availability) - || (unlockables[skins[skinnum].availability - 1].unlocked) + || ((playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked)) || (modeattacking) // If you have someone else's run you might as well take a look || (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1. - || (netgame && !(server || adminplayer == consoleplayer) && (cv_forceskin.value == skinnum)) // Force 2. + || (netgame && (cv_forceskin.value == skinnum)) // Force 2. ); } @@ -2588,7 +2605,7 @@ void SetPlayerSkin(INT32 playernum, const char *skinname) INT32 i = R_SkinAvailable(skinname); player_t *player = &players[playernum]; - if ((i != -1) && (!P_IsLocalPlayer(player) || R_SkinUnlock(i))) + if ((i != -1) && R_SkinUsable(playernum, i)) { SetPlayerSkinByNum(playernum, i); return; @@ -2610,8 +2627,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) skin_t *skin = &skins[skinnum]; UINT8 newcolor = 0; - if ((skinnum >= 0 && skinnum < numskins) // Make sure it exists! - && (!P_IsLocalPlayer(player) || R_SkinUnlock(skinnum))) // ...but is it allowed? We must always allow external players to change skin. The server should vet that... + if (skinnum >= 0 && skinnum < numskins && R_SkinUsable(playernum, skinnum)) // Make sure it exists! { player->skin = skinnum; @@ -2653,7 +2669,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) if (player->mo) { - if ((player->pflags & PF_NIGHTSMODE) && (skin->sprites[SPR2_NGT0].numframes == 0)) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. + if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (skin->sprites[SPR2_NGT0].numframes == 0)) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. { skin = &skins[DEFAULTNIGHTSSKIN]; newcolor = ((skin->flags & SF_SUPER) ? skin->supercolor : skin->prefcolor); @@ -2663,16 +2679,16 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) player->mo->color = newcolor; P_SetScale(player->mo, player->mo->scale); player->mo->radius = FixedMul(skin->radius, player->mo->scale); + + P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames } return; } - else if (skinnum >= 0 && skinnum < numskins) - skinnum = 255; // Cheeky emulation. if (P_IsLocalPlayer(player)) - CONS_Alert(CONS_WARNING, M_GetText("Skin %d not found\n"), skinnum); + CONS_Alert(CONS_WARNING, M_GetText("Requested skin not found\n")); else if(server || adminplayer == consoleplayer) - CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); + CONS_Alert(CONS_WARNING, "Player %d (%s) skin not found\n", playernum, player_names[playernum]); SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin } @@ -2701,6 +2717,12 @@ static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) return INT16_MAX; // not found } +#ifdef SKINNAMEPADDING +#define HUDNAMEWRITE(value) snprintf(skin->hudname, sizeof(skin->hudname), "%5s", value) +#else +#define HUDNAMEWRITE(value) STRBUFCPY(skin->hudname, value) +#endif + // // Find skin sprites, sounds & optional status bar face, & add them // @@ -2793,7 +2815,7 @@ void R_AddSkins(UINT16 wadnum) } if (!hudname) { - STRBUFCPY(skin->hudname, skin->name); + HUDNAMEWRITE(skin->name); strupr(skin->hudname); for (value = skin->hudname; *value; value++) if (*value == '_') *value = ' '; // turn _ into spaces. @@ -2806,12 +2828,12 @@ void R_AddSkins(UINT16 wadnum) for (value = skin->realname; *value; value++) if (*value == '_') *value = ' '; // turn _ into spaces. if (!hudname) - STRBUFCPY(skin->hudname, skin->realname); + HUDNAMEWRITE(skin->realname); } else if (!stricmp(stoken, "hudname")) { // Life icon name (eg. "K.T.E") hudname = true; - STRBUFCPY(skin->hudname, value); + HUDNAMEWRITE(value); for (value = skin->hudname; *value; value++) if (*value == '_') *value = ' '; // turn _ into spaces. if (!realname) @@ -2905,8 +2927,8 @@ void R_AddSkins(UINT16 wadnum) // these are uppercase so they can be concatenated with SF_ // 1, true, yes are all valid values GETFLAG(SUPER) - GETFLAG(SUPERANIMS) - GETFLAG(SUPERSPIN) + GETFLAG(NOSUPERSPIN) + GETFLAG(NOSPINDASHDUST) GETFLAG(HIRES) GETFLAG(NOSKID) GETFLAG(NOSPEEDADJUST) @@ -2916,7 +2938,9 @@ void R_AddSkins(UINT16 wadnum) GETFLAG(STOMPDAMAGE) GETFLAG(MARIODAMAGE) GETFLAG(MACHINE) - GETFLAG(NOSPINDASHDUST) + GETFLAG(DASHMODE) + GETFLAG(FASTEDGE) + GETFLAG(MULTIABILITY) #undef GETFLAG else // let's check if it's a sound, otherwise error out @@ -2962,20 +2986,35 @@ next_token: // Add sprites { - UINT16 z; + UINT16 newlastlump; UINT8 sprite2; lump++; // start after S_SKIN lastlump = W_CheckNumForNamePwad("S_END",wadnum,lump); // stop at S_END + // old wadding practices die hard -- stop at S_SKIN or S_START if they come before S_END. - z = W_CheckNumForNamePwad("S_SKIN",wadnum,lump); - if (z < lastlump) lastlump = z; - z = W_CheckNumForNamePwad("S_START",wadnum,lump); - if (z < lastlump) lastlump = z; + newlastlump = W_CheckNumForNamePwad("S_SKIN",wadnum,lump); + if (newlastlump < lastlump) lastlump = newlastlump; + newlastlump = W_CheckNumForNamePwad("S_START",wadnum,lump); + if (newlastlump < lastlump) lastlump = newlastlump; + + // ...and let's handle super, too + newlastlump = W_CheckNumForNamePwad("S_SUPER",wadnum,lump); + if (newlastlump < lastlump) + { + newlastlump++; + // load all sprite sets we are aware of... for super! + for (sprite2 = 0; sprite2 < free_spr2; sprite2++) + R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, lastlump); + + newlastlump--; + lastlump = newlastlump; // okay, make the normal sprite set loading end there + } - // load all sprite sets we are aware of. + // load all sprite sets we are aware of... for normal stuff. for (sprite2 = 0; sprite2 < free_spr2; sprite2++) R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, lump, lastlump); + } R_FlushTranslationColormapCache(); @@ -3000,6 +3039,8 @@ next_token: return; } +#undef HUDNAMEWRITE + #ifdef DELFILE void R_DelSkins(UINT16 wadnum) { diff --git a/src/r_things.h b/src/r_things.h index 572884d21149071f0ad25797f5ac5bbf3a6486ae..3907fd2ae265717ff1b81ca46bc2183763d944b4 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -29,8 +29,6 @@ #define VISSPRITESPERCHUNK (1 << VISSPRITECHUNKBITS) #define VISSPRITEINDEXMASK (VISSPRITESPERCHUNK - 1) -#define DEFAULTNIGHTSSKIN 0 - // Constant arrays used for psprite clipping // and initializing clipping. extern INT16 negonearray[MAXVIDWIDTH]; @@ -71,6 +69,7 @@ void R_DrawMasked(void); // should be all lowercase!! S_SKIN processing does a strlwr #define DEFAULTSKIN "sonic" #define DEFAULTSKIN2 "tails" // secondary player +#define DEFAULTNIGHTSSKIN 0 typedef struct { @@ -118,7 +117,7 @@ typedef struct // specific sounds per skin sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table - spritedef_t sprites[NUMPLAYERSPRITES]; + spritedef_t sprites[NUMPLAYERSPRITES*2]; // contains super versions too UINT8 availability; // lock? } skin_t; @@ -204,7 +203,8 @@ extern skin_t skins[MAXSKINS + 1]; void SetPlayerSkin(INT32 playernum,const char *skinname); void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 -boolean R_SkinUnlock(INT32 skinnum); +boolean R_SkinUsable(INT32 playernum, INT32 skinnum); +UINT32 R_GetSkinAvailabilities(void); INT32 R_SkinAvailable(const char *name); void R_AddSkins(UINT16 wadnum); diff --git a/src/s_sound.c b/src/s_sound.c index 971961897344cca46ed3f5481303f484025855a0..d3189d7b48d0e813704c65a76a6e938a43b53136 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -611,6 +611,7 @@ void S_StartSound(const void *origin, sfxenum_t sfx_id) case sfx_forcsg: case sfx_elemsg: case sfx_armasg: + case sfx_attrsg: case sfx_s3k3e: case sfx_s3k3f: case sfx_s3k41: diff --git a/src/sounds.c b/src/sounds.c index b551b73b5c8ed7762ba9c26fa08b2bbb0b7a0bdd..395015296001e17d7bc528ea49bfb249c83157d0 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -170,6 +170,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"forcsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Force GET! {"elemsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Elemental GET! {"armasg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Armaggeddon GET! + {"attrsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Attract GET! {"shldls", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // You LOSE! {"spdpad", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"spkdth", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, @@ -188,6 +189,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"mswarp", false, 60, 16, -1, NULL, 0, -1, -1, LUMPERROR}, {"mspogo", false, 60, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"boingf", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"corkp", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"corkh", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Menu, interface {"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR}, diff --git a/src/sounds.h b/src/sounds.h index 42fa4c3089d30274f0f4b19dd88dad1bd515618b..0442ebb055cb57e9a257bc1aa47e8dfb16bfeed8 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -233,6 +233,7 @@ typedef enum sfx_forcsg, sfx_elemsg, sfx_armasg, + sfx_attrsg, sfx_shldls, sfx_spdpad, sfx_spkdth, @@ -251,6 +252,8 @@ typedef enum sfx_mswarp, sfx_mspogo, sfx_boingf, + sfx_corkp, + sfx_corkh, // Menu, interface sfx_chchng, diff --git a/src/st_stuff.c b/src/st_stuff.c index a226a90251b8753cdd08f5fddc851ad77b8e5f1a..4af3199a19d231216572b95c0ace17c4b4760a63 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -581,16 +581,16 @@ static void ST_drawDebugInfo(void) { V_DrawRightAlignedString(320, height - 104, V_MONOSPACE, va("SHIELD: %5x", stplyr->powers[pw_shield])); V_DrawRightAlignedString(320, height - 96, V_MONOSPACE, va("SCALE: %5d%%", (stplyr->mo->scale*100)/FRACUNIT)); - V_DrawRightAlignedString(320, height - 88, V_MONOSPACE, va("DASH: %3d/%3d", stplyr->dashspeed>>FRACBITS, stplyr->maxdash>>FRACBITS)); + V_DrawRightAlignedString(320, height - 88, V_MONOSPACE, va("CARRY: %5x", stplyr->powers[pw_carry])); V_DrawRightAlignedString(320, height - 80, V_MONOSPACE, va("AIR: %4d, %3d", stplyr->powers[pw_underwater], stplyr->powers[pw_spacetime])); // Flags V_DrawRightAlignedString(304-92, height - 72, V_MONOSPACE, "PF:"); - V_DrawString(304-90, height - 72, (stplyr->jumping) ? V_GREENMAP : V_REDMAP, "JM"); + V_DrawString(304-90, height - 72, (stplyr->pflags & PF_STARTJUMP) ? V_GREENMAP : V_REDMAP, "SJ"); V_DrawString(304-72, height - 72, (stplyr->pflags & PF_JUMPED) ? V_GREENMAP : V_REDMAP, "JD"); V_DrawString(304-54, height - 72, (stplyr->pflags & PF_SPINNING) ? V_GREENMAP : V_REDMAP, "SP"); V_DrawString(304-36, height - 72, (stplyr->pflags & PF_STARTDASH) ? V_GREENMAP : V_REDMAP, "ST"); - V_DrawString(304-18, height - 72, (stplyr->pflags & PF_THOKKED) ? V_GREENMAP : V_REDMAP, "TH"); + V_DrawString(304-18, height - 72, (stplyr->pflags & PF_THOKKED) ? V_GREENMAP : V_REDMAP, "TH"); V_DrawString(304, height - 72, (stplyr->pflags & PF_SHIELDABILITY) ? V_GREENMAP : V_REDMAP, "SH"); V_DrawRightAlignedString(320, height - 64, V_MONOSPACE, va("CEILZ: %6d", stplyr->mo->ceilingz>>FRACBITS)); @@ -717,7 +717,7 @@ static void ST_drawLives(void) // skincolor face/super UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->mo->color, GTC_CACHE); patch_t *face = faceprefix[stplyr->skin]; - if (stplyr->powers[pw_super] || stplyr->pflags & PF_NIGHTSMODE) + if ((stplyr->powers[pw_super] && (stplyr->mo->state < &states[S_PLAY_SUPER_TRANS] || stplyr->mo->state > &states[S_PLAY_SUPER_TRANS9])) || (stplyr->powers[pw_carry] == CR_NIGHTSMODE && skins[stplyr->skin].flags & SF_SUPER)) face = superprefix[stplyr->skin]; V_DrawSmallMappedPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0), V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag,face, colormap); @@ -1080,7 +1080,7 @@ static void ST_drawNiGHTSHUD(void) #ifdef HAVE_BLUA LUA_HudEnabled(hud_nightsdrill) && #endif - stplyr->pflags & PF_NIGHTSMODE) + stplyr->powers[pw_carry] == CR_NIGHTSMODE) { INT32 locx, locy; INT32 dfill; @@ -1166,7 +1166,7 @@ static void ST_drawNiGHTSHUD(void) INT32 i; total_ringcount = 0; for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] /*&& players[i].pflags & PF_NIGHTSMODE*/ && players[i].rings) + if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/ && players[i].rings) total_ringcount += players[i].rings; } else @@ -1299,7 +1299,7 @@ static void ST_drawNiGHTSHUD(void) tic_t lowest_time = stplyr->nightstime; INT32 i; for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE && players[i].nightstime < lowest_time) + if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE && players[i].nightstime < lowest_time) lowest_time = players[i].nightstime; realnightstime = lowest_time/TICRATE; } @@ -1486,14 +1486,30 @@ static void ST_drawMatchHUD(void) static inline void ST_drawRaceHUD(void) { - if (leveltime > TICRATE && leveltime <= 2*TICRATE) - V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(race3->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, race3); - else if (leveltime > 2*TICRATE && leveltime <= 3*TICRATE) - V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(race2->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, race2); - else if (leveltime > 3*TICRATE && leveltime <= 4*TICRATE) - V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(race1->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, race1); - else if (leveltime > 4*TICRATE && leveltime <= 5*TICRATE) - V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(racego->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, racego); + if (leveltime >= TICRATE && leveltime < 5*TICRATE) + { + INT32 height = (BASEVIDHEIGHT/2); + INT32 bounce = (leveltime % TICRATE); + patch_t *racenum; + switch (leveltime/TICRATE) + { + case 1: + racenum = race3; + break; + case 2: + racenum = race2; + break; + case 3: + racenum = race1; + break; + default: + racenum = racego; + break; + } + if (bounce < 3) + height -= (2 - bounce); + V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(racenum->width))/2), (INT32)(SCY(height)), V_NOSCALESTART, racenum); + } if (circuitmap) {