diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 6685cd5ee..4ec9cdb20 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -544,6 +544,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i) rsp->thokitem = (UINT32)LONG(players[i].thokitem); //mobjtype_t rsp->spinitem = (UINT32)LONG(players[i].spinitem); //mobjtype_t rsp->revitem = (UINT32)LONG(players[i].revitem); //mobjtype_t + rsp->followitem = (UINT32)LONG(players[i].followitem); //mobjtype_t rsp->actionspd = (fixed_t)LONG(players[i].actionspd); rsp->mindash = (fixed_t)LONG(players[i].mindash); rsp->maxdash = (fixed_t)LONG(players[i].maxdash); @@ -673,6 +674,7 @@ static void resynch_read_player(resynch_pak *rsp) players[i].thokitem = (UINT32)LONG(rsp->thokitem); //mobjtype_t players[i].spinitem = (UINT32)LONG(rsp->spinitem); //mobjtype_t players[i].revitem = (UINT32)LONG(rsp->revitem); //mobjtype_t + players[i].followitem = (UINT32)LONG(rsp->followitem); //mobjtype_t players[i].actionspd = (fixed_t)LONG(rsp->actionspd); players[i].mindash = (fixed_t)LONG(rsp->mindash); players[i].maxdash = (fixed_t)LONG(rsp->maxdash); diff --git a/src/d_clisrv.h b/src/d_clisrv.h index b9a4eec3e..bdf332665 100644 --- a/src/d_clisrv.h +++ b/src/d_clisrv.h @@ -189,6 +189,7 @@ typedef struct UINT32 thokitem; // mobjtype_t UINT32 spinitem; // mobjtype_t UINT32 revitem; // mobjtype_t + UINT32 followitem; // mobjtype_t fixed_t actionspd; fixed_t mindash; fixed_t maxdash; diff --git a/src/d_player.h b/src/d_player.h index bf0b303b8..e1350fe67 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -369,6 +369,8 @@ typedef struct player_s mobjtype_t thokitem; // Object # to spawn for the thok mobjtype_t spinitem; // Object # to spawn for spindash/spinning mobjtype_t revitem; // Object # to spawn for spindash/spinning + mobjtype_t followitem; // Object # to spawn for Smiles + mobj_t *followmobj; // Smiles all around fixed_t actionspd; // Speed of thok/glide/fly fixed_t mindash; // Minimum spindash speed diff --git a/src/dehacked.c b/src/dehacked.c index cddbd1a0e..9df077672 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1804,6 +1804,7 @@ static actionpointer_t actionpointers[] = {{A_FlickyHeightCheck}, "A_FLICKYHEIGHTCHECK"}, {{A_FlickyFlutter}, "A_FLICKYFLUTTER"}, {{A_FlameParticle}, "A_FLAMEPARTICLE"}, + {{A_FadeOverlay}, "A_FADEOVERLAY"}, {{NULL}, "NONE"}, @@ -2831,6 +2832,11 @@ static void readmaincfg(MYFILE *f) bootmap = (INT16)value; //titlechanged = true; } + else if (fastcmp(word, "STARTCHAR")) + { + startchar = (INT16)value; + char_on = -1; + } else deh_warning("Maincfg: unknown word '%s'", word); } @@ -3460,15 +3466,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PLAY_MELEE_LANDING", // SF_SUPER - "S_PLAY_SUPERTRANS1", - "S_PLAY_SUPERTRANS2", - "S_PLAY_SUPERTRANS3", - "S_PLAY_SUPERTRANS4", - "S_PLAY_SUPERTRANS5", - "S_PLAY_SUPERTRANS6", - "S_PLAY_SUPERTRANS7", - "S_PLAY_SUPERTRANS8", - "S_PLAY_SUPERTRANS9", // This has special significance in the code. If you add more frames, search for it and make the appropriate changes. + "S_PLAY_SUPER_TRANS1", + "S_PLAY_SUPER_TRANS2", + "S_PLAY_SUPER_TRANS3", + "S_PLAY_SUPER_TRANS4", + "S_PLAY_SUPER_TRANS5", + "S_PLAY_SUPER_TRANS6", // This has special significance in the code. If you add more frames, search for it and make the appropriate changes. // technically the player goes here but it's an infinite tic state "S_OBJPLACE_DUMMY", @@ -3484,15 +3487,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PLAY_SIGN", // NiGHTS character (uses player sprite) - "S_PLAY_NIGHTS_TRANS", + "S_PLAY_NIGHTS_TRANS1", "S_PLAY_NIGHTS_TRANS2", "S_PLAY_NIGHTS_TRANS3", "S_PLAY_NIGHTS_TRANS4", "S_PLAY_NIGHTS_TRANS5", "S_PLAY_NIGHTS_TRANS6", - "S_PLAY_NIGHTS_TRANS7", - "S_PLAY_NIGHTS_TRANS8", - "S_PLAY_NIGHTS_TRANS9", "S_PLAY_NIGHTS_STAND", "S_PLAY_NIGHTS_FLOAT", @@ -3527,6 +3527,20 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PLAY_NIGHTS_FLYC", "S_PLAY_NIGHTS_DRILLC", + // c: + "S_TAILSOVERLAY_STAND", + "S_TAILSOVERLAY_0DEGREES", + "S_TAILSOVERLAY_PLUS30DEGREES", + "S_TAILSOVERLAY_PLUS60DEGREES", + "S_TAILSOVERLAY_MINUS30DEGREES", + "S_TAILSOVERLAY_MINUS60DEGREES", + "S_TAILSOVERLAY_RUN", + "S_TAILSOVERLAY_FLY", + "S_TAILSOVERLAY_TIRE", + "S_TAILSOVERLAY_PAIN", + "S_TAILSOVERLAY_GASP", + "S_TAILSOVERLAY_EDGE", + // Blue Crawla "S_POSS_STND", "S_POSS_RUN1", @@ -5881,6 +5895,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_THOK", // Thok! mobj "MT_PLAYER", + "MT_TAILSOVERLAY", // c: // Enemies "MT_BLUECRAWLA", diff --git a/src/g_game.c b/src/g_game.c index 19abd516b..df933c4cb 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2144,6 +2144,7 @@ void G_PlayerReborn(INT32 player) UINT32 thokitem; UINT32 spinitem; UINT32 revitem; + UINT32 followitem; fixed_t actionspd; fixed_t mindash; fixed_t maxdash; @@ -2215,6 +2216,7 @@ void G_PlayerReborn(INT32 player) thokitem = players[player].thokitem; spinitem = players[player].spinitem; revitem = players[player].revitem; + followitem = players[player].followitem; actionspd = players[player].actionspd; mindash = players[player].mindash; maxdash = players[player].maxdash; @@ -2252,6 +2254,7 @@ void G_PlayerReborn(INT32 player) p->thokitem = thokitem; p->spinitem = spinitem; p->revitem = revitem; + p->followitem = followitem; p->actionspd = actionspd; p->mindash = mindash; p->maxdash = maxdash; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index b49d3eb96..7e09079cf 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1180,7 +1180,7 @@ void HU_Erase(void) // IN-LEVEL MULTIPLAYER RANKINGS //====================================================================== -#define supercheckdef ((players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS] || players[tab[i].num].mo->state > &states[S_PLAY_SUPER_TRANS9])) || (players[tab[i].num].powers[pw_carry] == CR_NIGHTSMODE && skins[players[tab[i].num].skin].flags & SF_SUPER)) +#define supercheckdef ((players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS1] || players[tab[i].num].mo->state >= &states[S_PLAY_SUPER_TRANS6])) || (players[tab[i].num].powers[pw_carry] == CR_NIGHTSMODE && skins[players[tab[i].num].skin].flags & SF_SUPER)) #define greycheckdef ((players[tab[i].num].mo && players[tab[i].num].mo->health <= 0) || players[tab[i].num].spectator) // diff --git a/src/info.c b/src/info.c index d62111640..acb12379a 100644 --- a/src/info.c +++ b/src/info.c @@ -479,6 +479,19 @@ char spr2names[NUMPLAYERSPRITES][5] = "DRLB", "DRLC", + "TAL0", + "TAL1", + "TAL2", + "TAL3", + "TAL4", + "TAL5", + "TAL6", + "TAL7", + "TAL8", + "TAL9", + "TALA", + "TALB", + "SIGN", "LIFE" }; @@ -562,8 +575,21 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_NGTB, // SPR2_DRLB, SPR2_NGTC, // SPR2_DRLC, + 0, // SPR2_TAL0, + SPR2_TAL0, // SPR2_TAL1, + SPR2_TAL1, // SPR2_TAL2, + SPR2_TAL2, // SPR2_TAL3, + SPR2_TAL1, // SPR2_TAL4, + SPR2_TAL4, // SPR2_TAL5, + SPR2_TAL0, // SPR2_TAL6, + SPR2_TAL3, // SPR2_TAL7, + SPR2_TAL7, // SPR2_TAL8, + SPR2_TAL0, // SPR2_TAL9, + SPR2_TAL9, // SPR2_TALA, + SPR2_TAL0, // SPR2_TALB, + 0, // SPR2_SIGN, - 0, // SPR2_LIFE + 0, // SPR2_LIFE, }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -644,15 +670,12 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_MLEL, 35, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_MELEE_LANDING // SF_SUPER - {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_PLAY, SPR2_TRNS|FF_SPR2SUPER, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS2}, // S_PLAY_SUPER_TRANS1 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER, 3, {NULL}, 0, 0, S_PLAY_SUPER_TRANS3}, // S_PLAY_SUPER_TRANS2 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_SUPER_TRANS4}, // S_PLAY_SUPER_TRANS3 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_SUPER_TRANS5}, // S_PLAY_SUPER_TRANS4 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_SUPER_TRANS6}, // S_PLAY_SUPER_TRANS5 + {SPR_PLAY, SPR2_TRNS|FF_SPR2SUPER|FF_FULLBRIGHT, 20, {A_FadeOverlay}, 0, 0, S_PLAY_FALL}, // S_PLAY_SUPER_TRANS6 {SPR_NULL, 0, -1, {NULL}, 0, 0, S_OBJPLACE_DUMMY}, //S_OBJPLACE_DUMMY @@ -667,15 +690,12 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_SIGN, 1, {NULL}, 0, 24, S_PLAY_SIGN}, // S_PLAY_SIGN // NiGHTS Player, transforming - {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 + {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS2}, // S_PLAY_NIGHTS_TRANS1 + {SPR_PLAY, SPR2_TRNS, 3, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS3}, // S_PLAY_NIGHTS_TRANS2 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS4}, // S_PLAY_NIGHTS_TRANS3 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS5}, // S_PLAY_NIGHTS_TRANS4 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_PLAY_NIGHTS_TRANS6}, // S_PLAY_NIGHTS_TRANS5 + {SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT, 25, {A_FadeOverlay}, 4, 0, S_PLAY_NIGHTS_FLOAT}, // S_PLAY_NIGHTS_TRANS5 // NiGHTS Player, stand, float, pain, pull and attack {SPR_PLAY, SPR2_NSTD, 7, {NULL}, 0, 0, S_PLAY_NIGHTS_STAND}, // S_PLAY_NIGHTS_STAND @@ -712,6 +732,20 @@ state_t states[NUMSTATES] = {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 + // c: + {SPR_PLAY, SPR2_TAL0|FF_SPR2MIDSTART, 5, {NULL}, 0, 0, S_TAILSOVERLAY_STAND}, // S_TAILSOVERLAY_STAND + {SPR_PLAY, SPR2_TAL1|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_0DEGREES}, // S_TAILSOVERLAY_0DEGREES + {SPR_PLAY, SPR2_TAL2|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PLUS30DEGREES}, // S_TAILSOVERLAY_PLUS30DEGREES + {SPR_PLAY, SPR2_TAL3|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PLUS60DEGREES}, // S_TAILSOVERLAY_PLUS60DEGREES + {SPR_PLAY, SPR2_TAL4|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_MINUS30DEGREES}, // S_TAILSOVERLAY_MINUS30DEGREES + {SPR_PLAY, SPR2_TAL5|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_MINUS60DEGREES}, // S_TAILSOVERLAY_MINUS60DEGREES + {SPR_PLAY, SPR2_TAL6|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_RUN}, // S_TAILSOVERLAY_RUN + {SPR_PLAY, SPR2_TAL7|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_FLY}, // S_TAILSOVERLAY_FLY + {SPR_PLAY, SPR2_TAL8|FF_SPR2MIDSTART, 4, {NULL}, 0, 0, S_TAILSOVERLAY_TIRE}, // S_TAILSOVERLAY_TIRE + {SPR_PLAY, SPR2_TAL9|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_PAIN}, // S_TAILSOVERLAY_PAIN + {SPR_PLAY, SPR2_TALA|FF_SPR2MIDSTART, 35, {NULL}, 0, 0, S_TAILSOVERLAY_GASP}, // S_TAILSOVERLAY_GASP + {SPR_PLAY, SPR2_TALB , 35, {NULL}, 0, 0, S_TAILSOVERLAY_EDGE}, // S_TAILSOVERLAY_EDGE + // Blue Crawla {SPR_POSS, 0, 5, {A_Look}, 0, 0, S_POSS_STND}, // S_POSS_STND {SPR_POSS, 0, 3, {A_Chase}, 0, 0, S_POSS_RUN2}, // S_POSS_RUN1 @@ -3235,6 +3269,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = (statenum_t)MT_NULL // raisestate }, + { // MT_TAILSOVERLAY + -1, // doomednum + S_INVISIBLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 16*FRACUNIT, // radius + 48*FRACUNIT, // height + 2, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_BLUECRAWLA 100, // doomednum S_POSS_STND, // spawnstate @@ -11703,7 +11764,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_ELEMENTAL, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 2, // display offset + 4, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -11730,7 +11791,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_ATTRACT, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 2, // display offset + 4, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -11757,7 +11818,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_FORCE, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 2, // display offset + 4, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -11784,7 +11845,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_ARMAGEDDON, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 2, // display offset + 4, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -11811,7 +11872,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_WHIRLWIND, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 2, // display offset + 4, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -11838,7 +11899,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_PITY, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 2, // display offset + 4, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -11865,7 +11926,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_FLAMEAURA, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - -2, // display offset + -4, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -11892,7 +11953,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_BUBBLEWRAP, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - 2, // display offset + 4, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -11919,7 +11980,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = SH_THUNDERCOIN, // speed 64*FRACUNIT, // radius 64*FRACUNIT, // height - -2, // display offset + -4, // display offset 16, // mass 0, // damage sfx_None, // activesound @@ -14957,7 +15018,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // speed 16*FRACUNIT, // radius 48*FRACUNIT, // height - 0, // display offset + 1, // display offset 1000, // mass 8, // damage sfx_None, // activesound diff --git a/src/info.h b/src/info.h index 7bc7e673a..ea2103393 100644 --- a/src/info.h +++ b/src/info.h @@ -216,6 +216,7 @@ void A_FlickyCheck(); void A_FlickyHeightCheck(); void A_FlickyFlutter(); void A_FlameParticle(); +void A_FadeOverlay(); // ratio of states to sprites to mobj types is roughly 6 : 1 : 1 #define NUMMOBJFREESLOTS 256 @@ -685,6 +686,20 @@ typedef enum playersprite SPR2_DRLB, SPR2_DRLC, + // c: + SPR2_TAL0, + SPR2_TAL1, + SPR2_TAL2, + SPR2_TAL3, + SPR2_TAL4, + SPR2_TAL5, + SPR2_TAL6, + SPR2_TAL7, + SPR2_TAL8, + SPR2_TAL9, + SPR2_TALA, + SPR2_TALB, + SPR2_SIGN, // end sign head SPR2_LIFE, // life monitor icon @@ -763,15 +778,12 @@ typedef enum state S_PLAY_MELEE_LANDING, // SF_SUPER - S_PLAY_SUPER_TRANS, + S_PLAY_SUPER_TRANS1, S_PLAY_SUPER_TRANS2, S_PLAY_SUPER_TRANS3, S_PLAY_SUPER_TRANS4, S_PLAY_SUPER_TRANS5, S_PLAY_SUPER_TRANS6, - S_PLAY_SUPER_TRANS7, - S_PLAY_SUPER_TRANS8, - S_PLAY_SUPER_TRANS9, // technically the player goes here but it's an infinite tic state S_OBJPLACE_DUMMY, @@ -787,15 +799,12 @@ typedef enum state S_PLAY_SIGN, // NiGHTS character (uses player sprite) - S_PLAY_NIGHTS_TRANS, + S_PLAY_NIGHTS_TRANS1, S_PLAY_NIGHTS_TRANS2, S_PLAY_NIGHTS_TRANS3, S_PLAY_NIGHTS_TRANS4, S_PLAY_NIGHTS_TRANS5, S_PLAY_NIGHTS_TRANS6, - S_PLAY_NIGHTS_TRANS7, - S_PLAY_NIGHTS_TRANS8, - S_PLAY_NIGHTS_TRANS9, S_PLAY_NIGHTS_STAND, S_PLAY_NIGHTS_FLOAT, @@ -830,6 +839,20 @@ typedef enum state S_PLAY_NIGHTS_FLYC, S_PLAY_NIGHTS_DRILLC, + // c: + S_TAILSOVERLAY_STAND, + S_TAILSOVERLAY_0DEGREES, + S_TAILSOVERLAY_PLUS30DEGREES, + S_TAILSOVERLAY_PLUS60DEGREES, + S_TAILSOVERLAY_MINUS30DEGREES, + S_TAILSOVERLAY_MINUS60DEGREES, + S_TAILSOVERLAY_RUN, + S_TAILSOVERLAY_FLY, + S_TAILSOVERLAY_TIRE, + S_TAILSOVERLAY_PAIN, + S_TAILSOVERLAY_GASP, + S_TAILSOVERLAY_EDGE, + // Blue Crawla S_POSS_STND, S_POSS_RUN1, @@ -3206,6 +3229,7 @@ typedef enum mobj_type MT_THOK, // Thok! mobj MT_PLAYER, + MT_TAILSOVERLAY, // c: // Enemies MT_BLUECRAWLA, diff --git a/src/lua_hook.h b/src/lua_hook.h index fe5706f56..822edf79f 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -47,6 +47,7 @@ enum hook { hook_ShieldSpecial, hook_MobjMoveBlocked, hook_MapThingSpawn, + hook_FollowMobj, hook_MAX // last hook }; @@ -85,5 +86,6 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 #define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities #define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked) boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type +boolean LUAh_FollowMobj(player_t *player, mobj_t *mo); // Hook for P_PlayerAfterThink Smiles mobj-following #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 3dd3f932f..0a7ef801e 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -58,6 +58,7 @@ const char *const hookNames[hook_MAX+1] = { "ShieldSpecial", "MobjMoveBlocked", "MapThingSpawn", + "FollowMobj", NULL }; @@ -197,6 +198,7 @@ static int lib_addHook(lua_State *L) case hook_SpinSpecial: case hook_JumpSpinSpecial: case hook_PlayerSpawn: + case hook_FollowMobj: lastp = &playerhooks; break; case hook_LinedefExecute: @@ -1138,4 +1140,42 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing) return hooked; } +// Hook for P_PlayerAfterThink Smiles mobj-following +boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_FollowMobj/8] & (1<<(hook_FollowMobj%8)))) + return 0; + + lua_settop(gL, 0); + + for (hookp = playerhooks; hookp; hookp = hookp->next) + if (hookp->type == hook_FollowMobj) + { + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, mobj, META_MOBJ); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return hooked; +} + #endif diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 7c55012d2..12b2646d0 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -174,6 +174,10 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->spinitem); else if (fastcmp(field,"revitem")) lua_pushinteger(L, plr->revitem); + else if (fastcmp(field,"followitem")) + lua_pushinteger(L, plr->followitem); + else if (fastcmp(field,"followmobj")) + LUA_PushUserdata(L, plr->followmobj, META_MOBJ); else if (fastcmp(field,"actionspd")) lua_pushfixed(L, plr->actionspd); else if (fastcmp(field,"mindash")) @@ -441,6 +445,10 @@ static int player_set(lua_State *L) plr->spinitem = luaL_checkinteger(L, 3); else if (fastcmp(field,"revitem")) plr->revitem = luaL_checkinteger(L, 3); + else if (fastcmp(field,"followitem")) + plr->followitem = luaL_checkinteger(L, 3); + else if (fastcmp(field,"followmobj")) + plr->followmobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); else if (fastcmp(field,"actionspd")) plr->actionspd = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"mindash")) diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index f93513c49..1a70a82d9 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -35,6 +35,7 @@ enum skin { skin_thokitem, skin_spinitem, skin_revitem, + skin_followitem, skin_actionspd, skin_mindash, skin_maxdash, @@ -73,6 +74,7 @@ static const char *const skin_opt[] = { "thokitem", "spinitem", "revitem", + "followitem", "actionspd", "mindash", "maxdash", @@ -162,6 +164,9 @@ static int skin_get(lua_State *L) case skin_revitem: lua_pushinteger(L, skin->revitem); break; + case skin_followitem: + lua_pushinteger(L, skin->followitem); + break; case skin_actionspd: lua_pushfixed(L, skin->actionspd); break; diff --git a/src/m_menu.c b/src/m_menu.c index 748c78ad1..10faadfdf 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -149,7 +149,7 @@ description_t description[32] = {false, "???", "", "", 0, 0}, {false, "???", "", "", 0, 0} }; -static INT16 char_on = 0; +INT16 char_on = -1, startchar = 1; static char *char_notes = NULL; static fixed_t char_scroll = 0; @@ -6738,7 +6738,15 @@ static void M_SetupChoosePlayer(INT32 choice) SP_PlayerDef.prevMenu = currentMenu; M_SetupNextMenu(&SP_PlayerDef); if (!allowed) + { char_on = firstvalid; + if (startchar > 0 && startchar < 32) + { + INT16 workchar = startchar; + while (workchar--) + char_on = description[char_on].next; + } + } char_scroll = 0; // finish scrolling the menu Z_Free(char_notes); char_notes = V_WordWrap(0, 21*8, V_ALLOWLOWERCASE, description[char_on].notes); diff --git a/src/m_menu.h b/src/m_menu.h index 8040b63e6..aa80445c8 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -232,6 +232,7 @@ extern CV_PossibleValue_t gametype_cons_t[]; extern INT16 startmap; extern INT32 ultimate_selectable; +extern INT16 char_on, startchar; #define MAXSAVEGAMES 31 //note: last save game is "no save" #define NOSAVESLOT 0 //slot where Play Without Saving appears diff --git a/src/p_enemy.c b/src/p_enemy.c index 4d80ea479..c8bb0cfec 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -244,6 +244,7 @@ void A_FlickyCheck(mobj_t *actor); void A_FlickyHeightCheck(mobj_t *actor); void A_FlickyFlutter(mobj_t *actor); void A_FlameParticle(mobj_t *actor); +void A_FadeOverlay(mobj_t *actor); // // ENEMY THINKING @@ -10492,3 +10493,39 @@ void A_FlameParticle(mobj_t *actor) type); P_SetObjectMomZ(particle, locvar1<momx = actor->momy = actor->momz = 0; + + fade = P_SpawnGhostMobj(actor); + fade->frame = actor->frame; + + if (!(locvar1 & 2)) + { + fade->fuse = 15; + fade->flags2 |= MF2_BOSSNOTRAP; + } + else + fade->fuse = 20; + + if (!(locvar1 & 4)) + P_SetTarget(&actor->tracer, fade); +} diff --git a/src/p_floor.c b/src/p_floor.c index 9ac6a3896..c72de6b70 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1751,6 +1751,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node) { case MT_NULL: case MT_UNKNOWN: + case MT_TAILSOVERLAY: case MT_THOK: case MT_GHOST: case MT_OVERLAY: diff --git a/src/p_mobj.c b/src/p_mobj.c index c22b81795..cefc3129e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -322,7 +322,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 (player->panim == PA_EDGE && (player->charflags & SF_FASTEDGE)) + if (state == S_PLAY_STND && player->powers[pw_super] && skins[player->skin].sprites[SPR2_WAIT|FF_SPR2SUPER].numframes == 0) // if no super wait, don't wait at all + mobj->tics = -1; + else if (player->panim == PA_EDGE && (player->charflags & SF_FASTEDGE)) mobj->tics = 2; else if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST)) { @@ -6646,10 +6648,21 @@ void P_MobjThinker(mobj_t *mobj) } } - if ((mobj->type == MT_GHOST || mobj->type == MT_THOK) && mobj->fuse > 0 // Not guaranteed to be MF_SCENERY or not MF_SCENERY! - && (signed)(mobj->frame >> FF_TRANSSHIFT) < (NUMTRANSMAPS-1) - mobj->fuse / 2) - // fade out when nearing the end of fuse... - mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - mobj->fuse / 2) << FF_TRANSSHIFT); + if ((mobj->type == MT_GHOST || mobj->type == MT_THOK) && mobj->fuse > 0) // Not guaranteed to be MF_SCENERY or not MF_SCENERY! + { + if (mobj->flags2 & MF2_BOSSNOTRAP) // "fast" flag + { + if ((signed)((mobj->frame & FF_TRANSMASK) >> FF_TRANSSHIFT) < (NUMTRANSMAPS-1) - (2*mobj->fuse)/3) + // fade out when nearing the end of fuse... + mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - (2*mobj->fuse)/3) << FF_TRANSSHIFT); + } + else + { + if ((signed)((mobj->frame & FF_TRANSMASK) >> FF_TRANSSHIFT) < (NUMTRANSMAPS-1) - mobj->fuse / 2) + // fade out when nearing the end of fuse... + mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - mobj->fuse / 2) << FF_TRANSSHIFT); + } + } if (mobj->flags2 & MF2_MACEROTATE) { diff --git a/src/p_saveg.c b/src/p_saveg.c index 8efe7027b..bb89b643a 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -56,6 +56,7 @@ typedef enum AWAYVIEW = 0x08, FIRSTAXIS = 0x10, SECONDAXIS = 0x20, + FOLLOW = 0x40, } player_saveflags; // @@ -220,6 +221,9 @@ static void P_NetArchivePlayers(void) if (players[i].axis2) flags |= SECONDAXIS; + if (players[i].followmobj) + flags |= FOLLOW; + WRITEINT16(save_p, players[i].lastsidehit); WRITEINT16(save_p, players[i].lastlinehit); @@ -245,6 +249,9 @@ static void P_NetArchivePlayers(void) if (flags & AWAYVIEW) WRITEUINT32(save_p, players[i].awayviewmobj->mobjnum); + if (flags & FOLLOW) + WRITEUINT32(save_p, players[i].followmobj->mobjnum); + WRITEFIXED(save_p, players[i].camerascale); WRITEFIXED(save_p, players[i].shieldscale); @@ -254,6 +261,7 @@ static void P_NetArchivePlayers(void) WRITEUINT32(save_p, (UINT32)players[i].thokitem); WRITEUINT32(save_p, (UINT32)players[i].spinitem); WRITEUINT32(save_p, (UINT32)players[i].revitem); + WRITEUINT32(save_p, (UINT32)players[i].followitem); WRITEFIXED(save_p, players[i].actionspd); WRITEFIXED(save_p, players[i].mindash); WRITEFIXED(save_p, players[i].maxdash); @@ -413,6 +421,9 @@ static void P_NetUnArchivePlayers(void) if (flags & AWAYVIEW) players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save_p); + if (flags & FOLLOW) + players[i].followmobj = (mobj_t *)(size_t)READUINT32(save_p); + players[i].viewheight = cv_viewheight.value<player->awayviewmobj, P_FindNewPosition(temp))) CONS_Debug(DBG_GAMELOGIC, "awayviewmobj not found on %d\n", mobj->type); } + if (mobj->player && mobj->player->followmobj) + { + temp = (UINT32)(size_t)mobj->player->followmobj; + mobj->player->followmobj = NULL; + if (!P_SetTarget(&mobj->player->followmobj, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "followmobj not found on %d\n", mobj->type); + } } } } diff --git a/src/p_user.c b/src/p_user.c index cfe9b334b..a2e1f4111 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -591,6 +591,7 @@ static void P_DeNightserizePlayer(player_t *player) player->mo->flags &= ~MF_NOGRAVITY; player->mo->skin = &skins[player->skin]; + player->followitem = skins[player->skin].followitem; player->mo->color = player->skincolor; // Restore aiming angle @@ -665,14 +666,16 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) if (skins[player->skin].sprites[SPR2_NGT0].numframes == 0) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin. { player->mo->skin = &skins[DEFAULTNIGHTSSKIN]; - player->mo->color = skins[DEFAULTNIGHTSSKIN].prefcolor; + if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) + player->mo->color = skins[DEFAULTNIGHTSSKIN].prefcolor; + player->followitem = skins[DEFAULTNIGHTSSKIN].followitem; } player->nightstime = player->startedtime = nighttime*TICRATE; player->bonustime = false; P_RestoreMusic(player); - P_SetPlayerMobjState(player->mo, S_PLAY_NIGHTS_TRANS); + P_SetPlayerMobjState(player->mo, S_PLAY_NIGHTS_TRANS1); if (gametype == GT_RACE || gametype == GT_COMPETITION) { @@ -999,10 +1002,10 @@ void P_DoSuperTransformation(player_t *player, boolean giverings) S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi // Transformation animation - P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_TRANS); + P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_TRANS1); player->mo->momx = player->mo->momy = player->mo->momz = 0; - player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE); + player->pflags |= PF_NOJUMPDAMAGE; // just to avoid recurling but still allow thok if (giverings) player->rings = 50; @@ -1551,9 +1554,7 @@ void P_SwitchShield(player_t *player, UINT16 shieldtype) // mobj_t *P_SpawnGhostMobj(mobj_t *mobj) { - mobj_t *ghost; - - ghost = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_GHOST); + mobj_t *ghost = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_GHOST); P_SetScale(ghost, mobj->scale); ghost->destscale = mobj->scale; @@ -1579,6 +1580,14 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) if (mobj->flags2 & MF2_OBJECTFLIP) ghost->flags |= MF2_OBJECTFLIP; + if (mobj->player && mobj->player->followmobj) + { + mobj_t *ghost2 = P_SpawnGhostMobj(mobj->player->followmobj); + P_SetTarget(&ghost2->tracer, ghost); + P_SetTarget(&ghost->tracer, ghost2); + ghost2->flags2 |= MF2_LINKDRAW; + } + return ghost; } @@ -3648,9 +3657,8 @@ 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] - || (player->mo->state == &states[S_PLAY_SUPER_TRANS9] && player->mo->tics > 1))) // needed to prevent one-frame old colour... + if (player->mo->state >= &states[S_PLAY_SUPER_TRANS1] + && player->mo->state < &states[S_PLAY_SUPER_TRANS6]) return; // don't do anything right now, we're in the middle of transforming! if (player->powers[pw_carry] == CR_NIGHTSMODE) @@ -3687,14 +3695,19 @@ static void P_DoSuperStuff(player_t *player) return; } + player->mo->color = (player->pflags & PF_GODMODE && cv_debug == 0) + ? (SKINCOLOR_SUPERSILVER1 + 5*(((signed)leveltime >> 1) % 7)) // A wholesome easter egg. + : skins[player->skin].supercolor + abs( ( (player->powers[pw_super] >> 1) % 9) - 4); // This is where super flashing is handled. + + G_GhostAddColor(GHC_SUPER); + + if (player->mo->state == &states[S_PLAY_SUPER_TRANS6]) // stop here for now + return; + // Deplete one ring every second while super if ((leveltime % TICRATE == 0) && !(player->exiting)) player->rings--; - player->mo->color = (player->pflags & PF_GODMODE && cv_debug == 0) - ? (SKINCOLOR_SUPERSILVER1 + 5*((leveltime >> 1) % 7)) // A wholesome easter egg. - : skins[player->skin].supercolor + (unsigned)abs( ( (signed)(leveltime >> 1) % 9) - 4); // This is where super flashing is handled. - if ((cmd->forwardmove != 0 || cmd->sidemove != 0 || player->powers[pw_carry]) && !(leveltime % TICRATE) && (player->mo->momx || player->mo->momy)) { @@ -3703,8 +3716,6 @@ static void P_DoSuperStuff(player_t *player) P_SetScale(spark, player->mo->scale); } - G_GhostAddColor(GHC_SUPER); - // Ran out of rings while super! if (player->rings <= 0 || player->exiting) { @@ -6081,14 +6092,14 @@ static void P_NiGHTSMovement(player_t *player) && (players[i].capsule && players[i].capsule->reactiontime)) capsule = true; if (!capsule - && !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS] - && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS9]) + && !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] + && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6]) && !player->exiting) player->nightstime--; } else if (gametype != GT_RACE && gametype != GT_COMPETITION - && !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS] - && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS9]) + && !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] + && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6]) && !(player->capsule && player->capsule->reactiontime) && !player->exiting) player->nightstime--; @@ -6227,8 +6238,8 @@ static void P_NiGHTSMovement(player_t *player) return; } - if (player->mo->state >= &states[S_PLAY_NIGHTS_TRANS] - && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS9]) + if (player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] + && player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6]) { player->mo->momx = player->mo->momy = player->mo->momz = 0; return; @@ -6832,7 +6843,7 @@ static void P_MovePlayer(player_t *player) fixed_t runspd; - 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_TRANS1] && player->mo->state <= &states[S_PLAY_SUPER_TRANS6]) { player->mo->momx = player->mo->momy = player->mo->momz = 0; return; @@ -6901,12 +6912,12 @@ static void P_MovePlayer(player_t *player) else if (maptol & TOL_NIGHTS) { 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))) + && (player->exiting + || !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1] + && player->mo->state < &states[S_PLAY_NIGHTS_TRANS6]))) { skin_t *skin = ((skin_t *)(player->mo->skin)); - player->mo->color = (skin->flags & SF_SUPER) ? skin->supercolor + (unsigned)abs(((signed)(leveltime >> 1) % 9) - 4) : player->mo->color; // This is where super flashing is handled. + player->mo->color = (skin->flags & SF_SUPER) ? skin->supercolor + abs((((player->startedtime - player->nightstime) >> 1) % 9) - 4) : player->mo->color; // This is where super flashing is handled. } if (!player->capsule && !player->bonustime) @@ -9725,7 +9736,8 @@ void P_PlayerThink(player_t *player) ticmiss++; P_DoRopeHang(player); - P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); + if (player->mo->state-states != S_PLAY_RIDE) + P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); P_DoJumpStuff(player, &player->cmd); } else //if (player->powers[pw_carry] == CR_ZOOMTUBE) @@ -9896,10 +9908,17 @@ void P_PlayerThink(player_t *player) { mobj_t *gmobj = P_SpawnGhostMobj(player->mo); gmobj->fuse = 2; + if (gmobj->tracer) + gmobj->tracer->fuse = 2; if (leveltime & 1) { gmobj->frame &= ~FF_TRANSMASK; gmobj->frame |= tr_trans70<tracer) + { + gmobj->tracer->frame &= ~FF_TRANSMASK; + gmobj->tracer->frame |= tr_trans70<powers[pw_nocontrol] = 0; //pw_super acts as a timer now - if (player->powers[pw_super]) + if (player->powers[pw_super] + && (player->mo->state < &states[S_PLAY_SUPER_TRANS1] + || player->mo->state > &states[S_PLAY_SUPER_TRANS6])) player->powers[pw_super]++; if (player->powers[pw_carry] == CR_BRAKGOOP) @@ -10165,6 +10186,11 @@ void P_PlayerAfterThink(player_t *player) if (thiscam && thiscam->chase) P_MoveChaseCamera(player, thiscam, false); } + if (player->followmobj) + { + P_RemoveMobj(player->followmobj); + player->followmobj = NULL; + } return; } @@ -10343,7 +10369,10 @@ void P_PlayerAfterThink(player_t *player) player->powers[pw_carry] = CR_NONE; if (player->powers[pw_carry] != CR_NONE) - P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); + { + if (player->mo->state-states != S_PLAY_RIDE) + P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); + } else P_SetTarget(&player->mo->tracer, NULL); @@ -10362,7 +10391,8 @@ void P_PlayerAfterThink(player_t *player) player->mo->z = player->mo->tracer->z - FixedDiv(player->mo->height, 3*FRACUNIT/2); player->mo->momx = player->mo->momy = player->mo->momz = 0; P_SetThingPosition(player->mo); - P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); + if (player->mo->state-states != S_PLAY_RIDE) + P_SetPlayerMobjState(player->mo, S_PLAY_RIDE); // Controllable missile if (player->mo->tracer->type == MT_BLACKEGGMAN_MISSILE) @@ -10456,4 +10486,224 @@ void P_PlayerAfterThink(player_t *player) if (P_IsObjectOnGround(player->mo)) player->mo->pmomz = 0; + + if (player->followmobj && (player->spectator || player->mo->health <= 0 || player->followmobj->type != player->followitem)) + { + P_RemoveMobj(player->followmobj); + player->followmobj = NULL; + } + + if (!player->spectator && player->mo->health && player->followitem) + { + if (!player->followmobj || P_MobjWasRemoved(player->followmobj)) + { + player->followmobj = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, player->followitem); + P_SetTarget(&player->followmobj->tracer, player->mo); + player->followmobj->flags2 |= MF2_LINKDRAW; + } + + if (player->followmobj) + { +#ifdef HAVE_BLUA + if (LUAh_FollowMobj(player, player->followmobj) || P_MobjWasRemoved(player->followmobj)) + {;} + else +#endif + { + switch (player->followmobj->type) + { + case MT_TAILSOVERLAY: // c: + { + // init... + boolean smilesonground = P_IsObjectOnGround(player->mo); + angle_t horizangle = player->drawangle; + fixed_t zoffs = 0; + fixed_t backwards = -1*FRACUNIT; + boolean doroll = (player->panim == PA_ROLL || player->panim == PA_JUMP); + angle_t rollangle; + boolean panimchange; + INT32 ticnum = 0; + statenum_t chosenstate; + + if (!player->followmobj->skin) + { + player->followmobj->skin = player->mo->skin; + P_SetMobjState(player->followmobj, S_TAILSOVERLAY_STAND); + player->followmobj->movecount = -1; + } + + panimchange = (player->followmobj->movecount != (INT32)player->panim); + + // initial position... + if (doroll) + { + fixed_t testval, zdist; + if (player->speed < FRACUNIT) + testval = FRACUNIT; + else + { + testval = (FixedMul(player->speed, FINECOSINE((horizangle - R_PointToAngle2(0, 0, player->rmomx, player->rmomy)) >> ANGLETOFINESHIFT))); + if (testval < FRACUNIT) + testval = FRACUNIT; + } + if (smilesonground && !player->mo->reactiontime) + zdist = (player->mo->z - player->followmobj->threshold); + else + zdist = player->mo->momz; + rollangle = R_PointToAngle2(0, 0, testval, -P_MobjFlip(player->mo)*zdist); + zoffs = 3*FRACUNIT + 12*FINESINE(rollangle >> ANGLETOFINESHIFT); + backwards = -12*FINECOSINE(rollangle >> ANGLETOFINESHIFT); + } + else if (player->panim == PA_RUN) + backwards = -5*FRACUNIT; + else if (player->panim == PA_SPRING) + { + zoffs += 4*FRACUNIT; + backwards /= 2; + } + else if (player->panim == PA_PAIN) + backwards /= 16; + else if (player->mo->state-states == S_PLAY_GASP) + { + backwards /= 16; + zoffs += 12*FRACUNIT; + } + else if (player->mo->state-states == S_PLAY_EDGE) + { + backwards /= 16; + zoffs = 3*FRACUNIT; + } + else if (player->panim == PA_ABILITY2) + { + zoffs = -7*FRACUNIT; + backwards = -9*FRACUNIT; + } + else if (player->mo->sprite2 == SPR2_FLY || player->mo->sprite2 == SPR2_TIRE) + backwards = -5*FRACUNIT; + + // sprite... + if (doroll) + { + statenum_t add = ((rollangle > ANGLE_180) ? 2 : 0); + if (add) + rollangle = InvAngle(rollangle); + rollangle += ANG15; // modify the thresholds to be nice clean numbers + if (rollangle > ANG60) + chosenstate = S_TAILSOVERLAY_PLUS60DEGREES + add; + else if (rollangle > ANG30) + chosenstate = S_TAILSOVERLAY_PLUS30DEGREES + add; + else + chosenstate = S_TAILSOVERLAY_0DEGREES; + } + else if (player->panim == PA_SPRING) + chosenstate = S_TAILSOVERLAY_MINUS60DEGREES; + else if (player->panim == PA_FALL || player->mo->state-states == S_PLAY_RIDE) + chosenstate = S_TAILSOVERLAY_PLUS60DEGREES; + else if (player->panim == PA_PAIN) + chosenstate = S_TAILSOVERLAY_PAIN; + else if (player->mo->state-states == S_PLAY_GASP) + chosenstate = S_TAILSOVERLAY_GASP; + else if (player->mo->state-states == S_PLAY_EDGE) + chosenstate = S_TAILSOVERLAY_EDGE; + else if (player->panim == PA_RUN) + chosenstate = S_TAILSOVERLAY_RUN; + else if (player->panim == PA_WALK) + { + if (!smilesonground) + chosenstate = S_TAILSOVERLAY_PLUS30DEGREES; + else if (player->speed >= FixedMul(player->runspeed/2, player->mo->scale)) + chosenstate = S_TAILSOVERLAY_0DEGREES; + else + chosenstate = S_TAILSOVERLAY_MINUS30DEGREES; + } + else if (player->mo->sprite2 == SPR2_FLY) + chosenstate = S_TAILSOVERLAY_FLY; + else if (player->mo->sprite2 == SPR2_TIRE) + chosenstate = S_TAILSOVERLAY_TIRE; + else if (player->panim == PA_ABILITY2) + chosenstate = S_TAILSOVERLAY_PLUS30DEGREES; + else if (player->panim == PA_IDLE) + chosenstate = S_TAILSOVERLAY_STAND; + else + chosenstate = S_INVISIBLE; + + // state... + if (panimchange) + { + player->followmobj->sprite2 = -1; + P_SetMobjState(player->followmobj, chosenstate); + } + else + { + if (player->followmobj->state != states+chosenstate) + { + if (states[chosenstate].sprite == SPR_PLAY) + player->followmobj->sprite2 = P_GetSkinSprite2(((skin_t *)player->followmobj->skin), (states[chosenstate].frame & FF_FRAMEMASK), player); + P_SetMobjState(player->followmobj, chosenstate); + } + } + + if (player->fly1 != 0 && player->powers[pw_tailsfly] != 0 && !smilesonground) + P_SetMobjState(player->followmobj, chosenstate); + + // animation... + if (player->panim == PA_SPRING || player->panim == PA_FALL || player->mo->state-states == S_PLAY_RIDE) + { + if (FixedDiv(abs(player->mo->momz), player->mo->scale) < 20<panim == PA_PAIN) + ticnum = 2; + else if (player->mo->state-states == S_PLAY_GASP) + player->followmobj->tics = -1; + else if (player->mo->sprite2 == SPR2_TIRE) + ticnum = 4; + else if (player->panim != PA_IDLE) + ticnum = player->mo->tics; + + if (ticnum && player->followmobj->tics > ticnum) + player->followmobj->tics = ticnum; + + // final handling... + player->followmobj->color = player->mo->color; + player->followmobj->threshold = player->mo->z; + player->followmobj->movecount = player->panim; + player->followmobj->angle = horizangle; + player->followmobj->scale = player->mo->scale; + P_SetScale(player->followmobj, player->mo->scale); + player->followmobj->destscale = player->mo->destscale; + player->followmobj->radius = player->mo->radius; + player->followmobj->height = player->mo->height; + zoffs = FixedMul(zoffs, player->followmobj->scale); + + if (player->mo->eflags & MFE_VERTICALFLIP) + { + player->followmobj->eflags |= MFE_VERTICALFLIP; + player->followmobj->flags2 |= MF2_OBJECTFLIP; + zoffs = player->mo->height - player->followmobj->height - zoffs; + } + else + { + player->followmobj->eflags &= ~MFE_VERTICALFLIP; + player->followmobj->flags2 &= ~MF2_OBJECTFLIP; + } + + P_UnsetThingPosition(player->followmobj); + player->followmobj->x = player->mo->x + P_ReturnThrustX(player->followmobj, player->followmobj->angle, FixedMul(backwards, player->followmobj->scale)); + player->followmobj->y = player->mo->y + P_ReturnThrustY(player->followmobj, player->followmobj->angle, FixedMul(backwards, player->followmobj->scale)); + player->followmobj->z = player->mo->z + zoffs; + P_SetThingPosition(player->followmobj); + } + break; + default: + var1 = 1; + var2 = 0; + A_CapeChase(player->followmobj); + break; + } + } + } + } } diff --git a/src/r_things.c b/src/r_things.c index 116782c3c..9ab7b5d1e 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1385,12 +1385,12 @@ static void R_ProjectSprite(mobj_t *thing) // specific translucency if (!cv_translucency.value) ; // no translucency - else if (oldthing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) + else if (oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility) vis->transmap = transtables + ((tr_trans80-1)<frame & FF_TRANSMASK) vis->transmap = transtables + (oldthing->frame & FF_TRANSMASK) - 0x10000; - if ((oldthing->frame & FF_FULLBRIGHT) || (oldthing->flags2 & MF2_SHADOW)) + if (oldthing->frame & FF_FULLBRIGHT || oldthing->flags2 & MF2_SHADOW || thing->flags2 & MF2_SHADOW) vis->cut |= SC_FULLBRIGHT; if (vis->cut & SC_FULLBRIGHT @@ -2438,7 +2438,7 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) while (!(skin->sprites[spr2].numframes) && spr2 != SPR2_STND - && ++i != 32) // recursion limiter + && ++i < 32) // recursion limiter { if (spr2 & FF_SPR2SUPER) { @@ -2525,6 +2525,7 @@ static void Sk_SetDefaultValue(skin_t *skin) skin->thokitem = -1; skin->spinitem = -1; skin->revitem = -1; + skin->followitem = 0; skin->highresscale = FRACUNIT; @@ -2638,6 +2639,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) player->thokitem = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem; player->spinitem = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem; player->revitem = skin->revitem < 0 ? (mobjtype_t)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; + player->followitem = skin->followitem; player->actionspd = skin->actionspd; player->mindash = skin->mindash; @@ -2663,13 +2665,21 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) player->skincolor = newcolor = skin->prefcolor; } + if (player->followmobj) + { + P_RemoveMobj(player->followmobj); + player->followmobj = NULL; + } + if (player->mo) { fixed_t radius = FixedMul(skin->radius, player->mo->scale); 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->prefcolor; // will be updated in thinker to flashing + player->followitem = skin->followitem; + if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) + newcolor = skin->prefcolor; // will be updated in thinker to flashing } player->mo->skin = skin; if (newcolor) @@ -2803,6 +2813,7 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) FULLPROCESS(thokitem) FULLPROCESS(spinitem) FULLPROCESS(revitem) + FULLPROCESS(followitem) #undef FULLPROCESS #define GETFRACBITS(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value)<skin, stplyr->mo->color, GTC_CACHE); patch_t *face = faceprefix[stplyr->skin]; - 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)) + if (stplyr->powers[pw_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); + if (cv_translucenthud.value == 10 && stplyr->powers[pw_super] == 1 && stplyr->mo->tracer) + { + INT32 v_supertrans = (stplyr->mo->tracer->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; + if (v_supertrans < 10) + { + v_supertrans <<= V_ALPHASHIFT; + colormap = R_GetTranslationColormap(stplyr->skin, stplyr->mo->tracer->color, GTC_CACHE); + V_DrawSmallMappedPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0), + V_SNAPTOLEFT|V_SNAPTOBOTTOM|v_supertrans|v_splitflag,face, colormap); + } + } } else if (stplyr->skincolor) {