diff --git a/src/dehacked.c b/src/dehacked.c index 875c81cf..33e65c4b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -990,7 +990,7 @@ static const struct { {"2D",TOL_2D}, {"MARIO",TOL_MARIO}, {"NIGHTS",TOL_NIGHTS}, - //{"OLDBRAK",TOL_ERZ3}, + {"TV",TOL_TV}, {"XMAS",TOL_XMAS}, {"CHRISTMAS",TOL_XMAS}, @@ -1838,7 +1838,11 @@ static actionpointer_t actionpointers[] = {{A_SPBChase}, "A_SPBCHASE"}, // SRB2kart {{A_MineExplode}, "A_MINEEXPLODE"}, // SRB2kart {{A_BallhogExplode}, "A_BALLHOGEXPLODE"}, // SRB2kart - {{A_LightningFollowPlayer}, "A_LIGHTNINGFOLLOWPLAYER"}, //SRB2kart + {{A_LightningFollowPlayer},"A_LIGHTNINGFOLLOWPLAYER"}, //SRB2kart + {{A_RandomShadowFrame}, "A_RANDOMSHADOWFRAME"}, //SRB2kart + {{A_RoamingShadowThinker}, "A_ROAMINGSHADOWTHINKER"}, //SRB2kart + {{A_ReaperThinker}, "A_REAPERTHINKER"}, //SRB2kart + {{A_MementosTPParticles}, "A_MEMENTOSTPPARTICLES"}, //SRB2kart {{A_OrbitNights}, "A_ORBITNIGHTS"}, {{A_GhostMe}, "A_GHOSTME"}, {{A_SetObjectState}, "A_SETOBJECTSTATE"}, @@ -6800,6 +6804,38 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_KLIT11", "S_KLIT12", + // Midnight Channel stuff: + "S_SPOTLIGHT", // Spotlight decoration + "S_RANDOMSHADOW", // Random Shadow. They're static and don't do nothing. + "S_GARU1", + "S_GARU2", + "S_GARU3", + "S_TGARU", + "S_TGARU1", + "S_TGARU2", + "S_TGARU3", // Wind attack used by Roaming Shadows on Players. + "S_ROAMINGSHADOW", // Roaming Shadow (the one that uses above's wind attack or smth) + "S_MAYONAKAARROW", // Arrow sign + + // Mementos stuff: + "S_REAPER_INVIS", // Reaper waiting for spawning + "S_REAPER", // Reaper main frame where its thinker is handled + "S_MEMENTOSTP", // Mementos teleporter state. (Used for spawning particles) + + // JackInTheBox + "S_JITB1", + "S_JITB2", + "S_JITB3", + "S_JITB4", + "S_JITB5", + "S_JITB6", + + // Color Drive + "S_CDMOONSP", + "S_CDBUSHSP", + "S_CDTREEASP", + "S_CDTREEBSP", + #ifdef SEENAMES "S_NAMECHECK", #endif @@ -7452,6 +7488,26 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_KARMAHITBOX", "MT_KARMAWHEEL", + // Midnight Channel stuff: + "MT_SPOTLIGHT", // Spotlight Object + "MT_RANDOMSHADOW", // Random static Shadows. + "MT_ROAMINGSHADOW", // Roaming Shadows. + "MT_MAYONAKAARROW", // Arrow static signs for Mayonaka + + // Mementos stuff + "MT_REAPERWAYPOINT", + "MT_REAPER", + "MT_MEMENTOSTP", + "MT_MEMENTOSPARTICLE", + + "MT_JACKINTHEBOX", + + // Color Drive: + "MT_CDMOON", + "MT_CDBUSH", + "MT_CDTREEA", + "MT_CDTREEB", + #ifdef SEENAMES "MT_NAMECHECK", #endif diff --git a/src/doomstat.h b/src/doomstat.h index 83917fe4..4b0c6f60 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -302,7 +302,7 @@ enum TypeOfLevel TOL_2D = 0x0100, ///< 2D TOL_MARIO = 0x0200, ///< Mario TOL_NIGHTS = 0x0400, ///< NiGHTS - //TOL_ERZ3 = 0x0800, ///< ERZ3 + TOL_TV = 0x0800, ///< Midnight Channel specific: draw TV like overlay on HUD TOL_XMAS = 0x1000 ///< Christmas NiGHTS //TOL_KART = 0x4000 ///< Kart 32768 }; diff --git a/src/info.c b/src/info.c index 7c77132e..f8ffb632 100644 --- a/src/info.c +++ b/src/info.c @@ -57,11 +57,12 @@ char sprnames[NUMSPRITES + 1][5] = //SRB2kart Sprites "SPRG","BSPR","RNDM","RPOP","SGNS","FAST","DSHR","BOST","BOSM","KFRE", "KINV","KINF","WIPD","DRIF","DUST","RSHE","FITM","BANA","ORBN","JAWZ", - "SSMN","KRBM","BHOG","BHBM","SPBM","THNS","SINK","SITR","KBLN","DEZL", - "POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM","SACO", - "CRAB","SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB","ARRO", - "ITEM","ITMO","ITMI","ITMN","WANT","PBOM","RETI","AIDU","KSPK","LZI1", - "LZI2","KLIT","VIEW" + "SSMN","KRBM","BHOG","BHBM","BLIG","LIGH","THNS","SINK","SITR","KBLN", + "DEZL","POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB","CHOM", + "SACO","CRAB","SHAD","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA","ISTB", + "ARRO","ITEM","ITMO","ITMI","ITMN","WANT","PBOM","RETI","AIDU","KSPK", + "LZI1","LZI2","KLIT", "SPTL", "ENM1", "GARU", "MARR", "REAP", "JITB", + "CDMO", "CDBU", "VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -3042,9 +3043,14 @@ state_t states[NUMSTATES] = {SPR_SPBM, 8, 1, {NULL}, 0, 0, S_PLAYERBOMB1}, // S_PLAYERBOMB20 {SPR_RNDM, FF_ANIMATE, -1, {NULL}, 23, 3, S_NULL}, // S_PLAYERITEM {SPR_FITM, FF_ANIMATE, -1, {NULL}, 23, 3, S_NULL}, // S_PLAYERFAKE +<<<<<<< HEAD +======= {SPR_PBOM, 0, -1, {NULL}, 0, 0, S_NULL}, // S_KARMAWHEEL - +>>>>>>> master + + {SPR_PBOM, 4, -1, {NULL}, 0, 0, S_NULL}, // S_KARMAWHEEL + // Oh no it's annoying lightning states....... // Lightning Sparks (it's the ones we'll use for the radius) {SPR_KSPK, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK2}, // S_KSPARK1 @@ -3060,7 +3066,7 @@ state_t states[NUMSTATES] = {SPR_KSPK, FF_TRANS50|FF_FULLBRIGHT|5, 2, {A_LightningFollowPlayer}, 0, 0, S_KSPARK12}, // S_KSPARK11 {SPR_NULL, FF_FULLBRIGHT, 1, {A_LightningFollowPlayer}, 0, 0, S_KSPARK13}, // S_KSPARK12 {SPR_KSPK, FF_TRANS60|FF_FULLBRIGHT|6, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_KSPARK13 - + // The straight bolt... {SPR_LZI1, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO12}, // S_LZIO11 {SPR_NULL, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO13}, // S_LZIO12 @@ -3071,7 +3077,7 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO18}, // S_LZIO17 {SPR_LZI1, FF_TRANS50|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO19}, // S_LZIO18 {SPR_LZI1, FF_TRANS70|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_LZIO19 - + {SPR_NULL, FF_FULLBRIGHT, 6, {A_LightningFollowPlayer}, 0, 0, S_LZIO22}, // S_LZIO21 {SPR_LZI2, FF_FULLBRIGHT|1, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO23}, // S_LZIO22 {SPR_LZI2, FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO24}, // S_LZIO23 @@ -3081,7 +3087,7 @@ state_t states[NUMSTATES] = {SPR_LZI2, FF_TRANS30|FF_FULLBRIGHT|2, 2, {A_LightningFollowPlayer}, 0, 0, S_LZIO28}, // S_LZIO27 {SPR_NULL, 0, 4, {A_LightningFollowPlayer}, 0, 0, S_LZIO29}, // S_LZIO28 {SPR_LZI2, FF_TRANS70|FF_FULLBRIGHT, 2, {A_LightningFollowPlayer}, 0, 0, S_NULL}, // S_LZIO29 - + // The slanted bolt. Man these states are boring as all heck to do. {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT2}, // S_KLIT1 {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT3}, // S_KLIT2 @@ -3094,7 +3100,43 @@ state_t states[NUMSTATES] = {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|4, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT10}, // S_KLIT9 {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT11}, // S_KLIT10 {SPR_KLIT, FF_FULLBRIGHT|FF_PAPERSPRITE|5, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT12}, // S_KLIT11 - {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT1}, // S_KLIT12 + {SPR_NULL, FF_FULLBRIGHT|FF_PAPERSPRITE, 2, {A_LightningFollowPlayer}, 0, 0, S_KLIT1}, // S_KLIT12 + + // Midnight Channel stuff, yay more boring states! + {SPR_SPTL, 0, -1, {NULL}, 0, 0, S_SPOTLIGHT}, // S_SPOTLIGHT + {SPR_ENM1, 0, 1, {A_RandomShadowFrame}, 0, 0, S_RANDOMSHADOW}, // S_RANDOMSHADOW + + {SPR_GARU, 0, 2, {NULL}, 0, 0, S_GARU2}, // S_GARU1 + {SPR_GARU, 1, 2, {NULL}, 0, 0, S_GARU3}, // S_GARU2 + {SPR_GARU, 2, 2, {NULL}, 0, 0, S_NULL}, // S_GARU3 + + {SPR_NULL, 0, 2, {NULL}, 0, 0, S_TGARU1}, // S_TGARU0 + {SPR_GARU, FF_TRANS30, 2, {NULL}, 0, 0, S_GARU2}, // S_TGARU1 + {SPR_GARU, 1|FF_TRANS30, 2, {NULL}, 0, 0, S_GARU3}, // S_TGARU2 + {SPR_GARU, 2|FF_TRANS30, 2, {NULL}, 0, 0, S_NULL}, // S_TGARU3 + + {SPR_ENM1, 2, 1, {A_RoamingShadowThinker}, 0, 0, S_ROAMINGSHADOW}, //S_ROAMINGSHADOW + + {SPR_MARR, 0, 1, {A_MayonakaArrow}, 0, 0, S_MAYONAKAARROW}, //S_MAYONAKAARROW + + //Mementos stuff + {SPR_NULL, 0, TICRATE*20, {NULL}, 0, 0, S_REAPER}, //S_REAPER_INVIS TODO: DON'T FORGET TO CHANGE THAT BACK TO 130*TICRATE WHEN TESTING IS OVER + {SPR_REAP, 0, 1, {A_ReaperThinker}, 0, 0, S_REAPER}, //S_REAPER + {SPR_NULL, 0, 1, {A_MementosTPParticles}, 0, 0, S_MEMENTOSTP}, //S_MEMENTOSTP + + //JackInTheBox + {SPR_JITB, 0, 4, {NULL}, 0, 0, S_JITB2}, // S_JITB1 + {SPR_JITB, 1, 4, {NULL}, 0, 0, S_JITB3}, // S_JITB2 + {SPR_JITB, 2, 4, {NULL}, 0, 0, S_JITB4}, // S_JITB3 + {SPR_JITB, 3, 4, {NULL}, 0, 0, S_JITB5}, // S_JITB4 + {SPR_JITB, 2, 4, {NULL}, 0, 0, S_JITB6}, // S_JITB5 + {SPR_JITB, 1, 4, {NULL}, 0, 0, S_JITB1}, // S_JITB6 + + // Color Drive Stuff: + {SPR_CDMO, 0, -1, {NULL}, 0, 0, S_CDMOONSP}, // S_CDMOONSP + {SPR_CDBU, 0, -1, {NULL}, 0, 0, S_CDBUSHSP}, // S_CDBUSHSP + {SPR_CDBU, 1, -1, {NULL}, 0, 0, S_CDTREEASP}, // S_CDTREEASP + {SPR_CDBU, 2, -1, {NULL}, 0, 0, S_CDTREEBSP}, // S_CDTREEBSP #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK @@ -17214,6 +17256,360 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + // Midnight Channel stuff: + + { // MT_SPOTLIGHT + 3124, // doomednum + S_SPOTLIGHT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 16*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_RANDOMSHADOW + 3120, // doomednum + S_RANDOMSHADOW, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_PAIN, // flags + S_NULL // raisestate + }, + + { // MT_ROAMINGSHADOW + 3121, // doomednum + S_ROAMINGSHADOW, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID|MF_PAIN|MF_SPECIAL|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + { // MT_MAYONAKAARROW + 3122, // doomednum + S_MAYONAKAARROW, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 64*FRACUNIT, // radius + 128*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + // Mementos stuff + { // MT_REAPERWAYPOINT + 3199, // 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 + 0, // speed + 64*FRACUNIT, // radius + 128*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_REAPER + 3202, // doomednum + S_REAPER_INVIS, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 64*FRACUNIT, // radius + 128*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_MEMENTOSTP + 3201, // doomednum + S_MEMENTOSTP, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 512*FRACUNIT, // radius + 16*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_MEMENTOSPARTICLE + -1, // doomednum + S_THOK, // 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 + 32<extravalue1) // Hack that spawns thoks that look like random shadows. Otherwise the state would overwrite our frame and that's a pain. + { + fake = P_SpawnMobj(actor->x, actor->y, actor->z, MT_THOK); + fake->sprite = SPR_ENM1; + fake->frame = P_RandomRange(0, 6); + P_SetScale(fake, FRACUNIT*3/2); + fake->scale = FRACUNIT*3/2; + fake->destscale = FRACUNIT*3/2; + fake->angle = actor->angle; + fake->tics = -1; + actor->flags2 |= MF2_DONTDRAW; + actor->extravalue1 = 1; + } + + P_SetScale(actor, FRACUNIT*3/2); + + // I have NO CLUE how to hardcode all of that fancy Linedef Executor shit so the fire spinout will be done by these entities directly. + if (P_LookForPlayers(actor, false, false, 380<target && !actor->target->player->powers[pw_flashing] + && !actor->target->player->kartstuff[k_invincibilitytimer] + && !actor->target->player->kartstuff[k_growshrinktimer] + && !actor->target->player->kartstuff[k_spinouttimer] + && P_IsObjectOnGround(actor->target) + && actor->z == actor->target->z) + { + P_DamageMobj(actor->target, actor, actor, 1); + P_InstaThrust(actor->target, actor->angle, 16<target->x, actor->target->y, actor->target->z, MT_THOK); + P_SetMobjStateNF(fire, S_QUICKBOOM1); + P_SetScale(fire, 4<color = SKINCOLOR_RED; + S_StartSound(actor->target, sfx_fire2); + } + } + return; +} + +// A_RoamingShadowThinker +// Thinker for Midnight Channel's Roaming Shadows: +void A_RoamingShadowThinker(mobj_t *actor) +{ + mobj_t *wind; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RoamingShadowThinker", (actor))) + return; +#endif + // extravalue1 replaces "movetimer" + // extravalue2 replaces "stoptimer" + + P_SetScale(actor, FRACUNIT*3/2); + if (!actor->extravalue2) + { + P_InstaThrust(actor, actor->angle, 8<extravalue1 = ((actor->extravalue1) ? (actor->extravalue1-1) : (TICRATE*5+1)); // deplete timer if set, set to 5 ticrate otherwise. + if (actor->extravalue1 == 1) // if timer reaches 1, do a u-turn. + { + actor->extravalue1 = 0; + actor->extravalue2 = 60; + } + // Search for and attack Players venturing too close in front of us. + + if (P_LookForPlayers(actor, false, false, 256<target && !actor->target->player->powers[pw_flashing] + && !actor->target->player->kartstuff[k_invincibilitytimer] + && !actor->target->player->kartstuff[k_growshrinktimer] + && !actor->target->player->kartstuff[k_spinouttimer]) + { + // send them flying and spawn the WIND! + P_InstaThrust(actor->target, 0, 0); + P_DamageMobj(actor->target, actor, actor, 1); + P_SetObjectMomZ(actor->target, 16<target, sfx_wind1); + + // Spawn the WIND: + wind = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_THOK); // Opaque layer: + P_SetMobjState(wind, S_GARU1); + P_SetScale(wind, FRACUNIT*3/2); + wind = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_THOK); // Translucent layer: + P_SetMobjState(wind, S_TGARU0); + P_SetScale(wind, FRACUNIT*3/2); + wind->destscale = 30<angle += ANG1*3; + actor->extravalue2--; + } + return; +} + +// A_MayonakaArrow +// Used for the arrow sprite animations in Mayonaka. It's only extra visual bullshit to make em more random. + +void A_MayonakaArrow(mobj_t *actor) +{ + INT32 flip = 0; + INT32 iswarning; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MayonakaArrow", (actor))) + return; +#endif + + iswarning = actor->spawnpoint->options & MTF_OBJECTSPECIAL; // is our object a warning sign? + // "animtimer" is replaced by "extravalue1" here. + actor->extravalue1 = ((actor->extravalue1) ? (actor->extravalue1+1) : (P_RandomRange(0, (iswarning) ? (TICRATE/2) : TICRATE*3))); + flip = ((actor->spawnpoint->options & 1) ? (3) : (0)); // flip adds 3 frames, which is the flipped version of the sign. + // special warning behavior: + if (iswarning) + flip = 6; + + actor->frame = flip + actor->extravalue2*3; + + if (actor->extravalue1 >= TICRATE*7/2) + { + actor->extravalue1 = 0; // reset to 0 and start a new cycle. + // special behavior for warning sign; swap from warning to sneaker & reverse + if (iswarning) + actor->extravalue2 = (actor->extravalue2) ? (0) : (1); + } + else if (actor->extravalue1 > TICRATE*7/2 -4) + actor->frame = flip+2; + else if (actor->extravalue1 > TICRATE*3 && leveltime%2 > 0) + actor->frame = flip+1; + + actor->frame |= FF_PAPERSPRITE; + actor->momz = 0; + return; +} + +// A_MementosTPParticles +// Mementos teleporters particles effects. Short and simple. + +void A_MementosTPParticles(mobj_t *actor) +{ + mobj_t *particle; + mobj_t *mo2; + int i = 0; + thinker_t *th; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_MementosTPParticles", (actor))) + return; +#endif + + for (; i<4; i++) + { + particle = P_SpawnMobj(actor->x + (P_RandomRange(-256, 256)<y + (P_RandomRange(-256, 256)<z + (P_RandomRange(48, 256)<frame = 0; + particle->color = ((i%2) ? (SKINCOLOR_RED) : (SKINCOLOR_BLACK)); + particle->destscale = 1; + P_HomingAttack(particle, actor); + } + + // Although this is mostly used to spawn particles, we will also save the OTHER teleport inside actor->target. That way teleporting doesn't require a thinker iteration. + // Doesn't seem like much given the small amount of mobjs this map has but heh. + if (!actor->target) + { + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + if (mo2->type == MT_MEMENTOSTP && mo2 != actor) + { + P_SetTarget(&actor->target, mo2); // The main target we're pursing. + break; + } + } + } +} + +// A_ReaperThinker +// Mementos's Reaper's thinker. A huge pain in the Derek Bum to translate from Lua to this shite if you ask me. + +void A_ReaperThinker(mobj_t *actor) +{ + mobj_t *particle; // particles to spawn + int i = 0; // for loops + angle_t an = ANGLE_22h; // Reminder that angle constants suck. + + //Waypoint stuff: + mobj_t *mo2; + thinker_t *th; + + //Player targetting stuff: + INT32 maxscore = 0; // we target the player with the highest score so yeah there you go. + player_t *player; // used as a shortcut in a loop. + mobj_t *targetplayermo; // the player mo we can eventually target, or whatever. + + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_ReaperThinker", (actor))) + return; +#endif + + // We don't have custom variables or whatever so we'll do with whatever the fuck we have left. + + if (actor->health == 1000) // if health is 1000, set it to a small scale and have it start growing with destscale. Then set the health to uh, not 1000. + { + actor->scale = 1; + actor->destscale = 2<scalespeed = FRACUNIT/24; // Should take a bit less than 2 seconds to fully grow. + S_StartSound(NULL, sfx_chain); + actor->health--; // now we have 999 health, so that above won't happen again. Awesome. + } + + if (actor->scale < 2<x + (P_RandomRange(-60, 60)<y + (P_RandomRange(-60, 60)<z, MT_THOK); + particle->momz = 20<color = ((i%2 !=0) ? (SKINCOLOR_RED) : (SKINCOLOR_BLACK)); + particle->frame = 0; + P_SetScale(particle, FRACUNIT/2); + } + + // Spawn particles in some edgy circle or w/e. + + if (leveltime%5 != 0) // spawn the thing under that every tic. + return; + + i=0; + for (; i<15; i++) // spawn in a circle formation or w/e. + { + particle = P_SpawnMobj(actor->x, actor->y, actor->z, MT_THOK); + particle->momz = 20<color = ((i%2 !=0) ? (SKINCOLOR_RED) : (SKINCOLOR_BLACK)); + particle->frame = 0; + P_SetScale(particle, FRACUNIT/2); + P_InstaThrust(particle, an*i, 30<flags = MF_NOGRAVITY|MF_PAIN|MF_SPECIAL|MF_NOCLIP|MF_NOCLIPHEIGHT; // set our flags to be a damaging thing. + // Handle animation: + if (!(leveltime%5)) + actor->extravalue2 = (actor->extravalue2 < 9) ? (actor->extravalue2+1) : (0); // Ghetto animation, but hey it works for what it's worth + + // Chain sfx + if (!S_SoundPlaying(actor, sfx_chain)) + S_StartSound(actor, sfx_chain); + + actor->frame = actor->extravalue2; // yes i'm that bad at maths don't @ me. + + if (!actor->target) + { + if (actor->hnext) + { + P_SetTarget(&actor->target, actor->hnext); // Default back to last waypoint. + return; + } + + // We have no target and oughta find one, so let's scan through thinkers for a waypoint of angle 0, or something. + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_REAPERWAYPOINT) + continue; + if (mo2->spawnpoint->angle != 0) + continue; + + P_SetTarget(&actor->target, mo2); // The main target we're pursing. + P_SetTarget(&actor->hnext, mo2); // The last waypoint we hit. We will default back to that if a player goes out of our range! + actor->extravalue1 = 0; // This will store the angle of the last waypoint we touched. This will essentially be useful later on. + if (!actor->tracer) // If we already have a tracer (Waypoint #0), don't do anything. + { + P_SetTarget(&actor->tracer, mo2); // Because our target might be a player OR a waypoint, we need some sort of fallback option. This will always be waypoint 0. + break; + } + } + } + else // Awesome, we now have a target. + { + // Follow target: + P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y), 20<angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + + // The player we should target if it's near us: + for (i=0; imo && player->kartstuff[k_bumper] && player->score >= maxscore) + { + targetplayermo = player->mo; + maxscore = player->score; + } + } + + // Try to target that player: + if (targetplayermo) + { + if (P_LookForPlayers(actor, false, false, 1024<target == targetplayermo && actor->target && !actor->target->player->powers[pw_flashing] + && !actor->target->player->kartstuff[k_invincibilitytimer] + && !actor->target->player->kartstuff[k_growshrinktimer] + && !actor->target->player->kartstuff[k_spinouttimer])) + P_SetTarget(&actor->target, actor->hnext); + // if the above isn't correct, then we should go back to targetting waypoints or something. + } + } + + // Waypoint behavior. + if (actor->target->type == MT_REAPERWAYPOINT) + { + + if (R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y) < 22<target, NULL); // remove target so we can default back to first waypoint if things go ham. + + // If we reach close to a waypoint, then we should go to the NEXT one. + for (th = thinkercap.next; th != &thinkercap; th = th->next) + { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_REAPERWAYPOINT) + continue; + if (mo2->spawnpoint->angle != actor->extravalue1+1) + continue; + + P_SetTarget(&actor->target, mo2); // The main target we're pursing. + P_SetTarget(&actor->hnext, mo2); // The last waypoint we hit. We will default back to that if a player goes out of our range! + actor->extravalue1++; // This will store the angle of the last waypoint we touched. This will essentially be useful later on. + break; + } + } + + + if (!actor->target) // If we have no target, revert back to waypoint 0. + { + actor->extravalue1 = 0; + P_SetTarget(&actor->target, actor->tracer); + } + } + else // if our target ISN'T a waypoint, then it can only be a player. + { + if (!P_CheckSight(actor, actor->target) || R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y) > 1024<target, actor->hnext); + } + } +} + //} // Function: A_OrbitNights diff --git a/src/p_inter.c b/src/p_inter.c index c1bcbf53..0c3c4689 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -378,6 +378,16 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // We now identify by object type, not sprite! Tails 04-11-2001 switch (special->type) { + case MT_MEMENTOSTP: // Mementos teleport + // Teleport player to the other teleporter (special->target). We'll assume there's always only ever 2. + if (!special->target) + return; // foolproof crash prevention check!!!!! + + P_TeleportMove(player->mo, special->target->x, special->target->y, special->target->z + (48<mo->angle = special->target->angle; + P_SetObjectMomZ(player->mo, 12<mo, player->mo->angle, 20<kartstuff[k_itemamount] && player->kartstuff[k_itemtype] != special->threshold)) return; diff --git a/src/sounds.c b/src/sounds.c index 02ad0853..e1bf870b 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -813,6 +813,9 @@ sfxinfo_t S_sfx[NUMSFX] = {"kpogos", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"ddash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"zio3", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"wind1", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"fire2", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"chain", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"mcitm1", false, 110, 8, -1, NULL, 0, -1, -1, LUMPERROR}, {"chaooo", false, 110, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"itfree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, diff --git a/src/sounds.h b/src/sounds.h index 2516b646..eedc7f38 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -888,6 +888,9 @@ typedef enum sfx_kpogos, sfx_ddash, sfx_zio3, + sfx_wind1, + sfx_fire2, + sfx_chain, sfx_mcitm1, sfx_chaooo, sfx_itfree, diff --git a/src/st_stuff.c b/src/st_stuff.c index e86e28a4..5ba00015 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -124,6 +124,10 @@ static patch_t *minicaps; static patch_t *gotrflag; static patch_t *gotbflag; +// Midnight Channel: +static patch_t *hud_tv1; +static patch_t *hud_tv2; + // SRB2kart // @@ -345,6 +349,10 @@ void ST_LoadGraphics(void) ngradeletters[i] = W_CachePatchName(va("GRADE%d", i), PU_HUDGFX); K_LoadKartHUDGraphics(); + + // Midnight Channel: + hud_tv1 = W_CachePatchName("HUD_TV1", PU_HUDGFX); + hud_tv2 = W_CachePatchName("HUD_TV2", PU_HUDGFX); } // made separate so that skins code can reload custom face graphics @@ -1985,6 +1993,17 @@ static void ST_overlayDrawer(void) ST_drawDebugInfo(); } +// MayonakaStatic: draw Midnight Channel's TV-like borders +static void ST_MayonakaStatic(void) +{ + INT32 flag = (leveltime%2) ? V_90TRANS : V_70TRANS; + + V_DrawFixedPatch(0, 0, FRACUNIT, V_SNAPTOTOP|V_SNAPTOLEFT|flag, hud_tv1, NULL); + V_DrawFixedPatch(320<typeoflevel & TOL_TV) // Very specific Midnight Channel stuff. + ST_MayonakaStatic(); } }