diff --git a/src/deh_tables.c b/src/deh_tables.c index 7a730b6ce..8cc5a5691 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -289,6 +289,7 @@ actionpointer_t actionpointers[] = {{A_SSMineFlash}, "A_SSMINEFLASH"}, {{A_LandMineExplode}, "A_LANDMINEEXPLODE"}, {{A_BallhogExplode}, "A_BALLHOGEXPLODE"}, + {{A_SpecialStageBombExplode},"A_SPECIALSTAGEBOMBEXPLODE"}, {{A_LightningFollowPlayer}, "A_LIGHTNINGFOLLOWPLAYER"}, {{A_FZBoomFlash}, "A_FZBOOMFLASH"}, {{A_FZBoomSmoke}, "A_FZBOOMSMOKE"}, @@ -4369,6 +4370,17 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_EERIEFOG4", "S_EERIEFOG5", + // Chaos Chute + "S_SPECIALSTAGEARCH", + "S_SPECIALSTAGEBOMB", + "S_SPECIALSTAGEBOMB_DISARM", + "S_SPECIALSTAGEBOMB_EXPLODE", + "S_SPECIALSTAGEBOMB_DISAPPEAR", + "S_SPECIALSTAGEBOMB_FLICKER1", + "S_SPECIALSTAGEBOMB_FLICKER2", + "S_SPECIALSTAGEBOMB_FLICKERLOOP", + "S_SPECIALSTAGEBOMB_RESET", + // SMK ports "S_SMK_PIPE1", // Generic pipes "S_SMK_PIPE2", @@ -5727,6 +5739,10 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_EERIEFOG", "MT_EERIEFOGGEN", + // Chaos Chute + "MT_SPECIALSTAGEARCH", + "MT_SPECIALSTAGEBOMB", + // SMK ports "MT_SMK_PIPE", "MT_SMK_MOLESPAWNER", diff --git a/src/info.c b/src/info.c index 0a311d369..7c8f93e6d 100644 --- a/src/info.c +++ b/src/info.c @@ -797,6 +797,10 @@ char sprnames[NUMSPRITES + 1][5] = // Eerie Grove "EGFG", + // Chaos Chute + "SARC", + "SSBM", + // SMK ports "SMKP", "MTYM", @@ -5088,6 +5092,17 @@ state_t states[NUMSTATES] = {SPR_EGFG, FF_TRANS90|FF_FULLBRIGHT|3, 7, {A_SetRandomTics}, 5, 9, S_EERIEFOG5}, // S_EERIEFOG4 {SPR_EGFG, FF_TRANS90|FF_FULLBRIGHT|4, 7, {A_SetRandomTics}, 5, 9, S_EERIEFOG1}, // S_EERIEFOG5 + // Chaos Chute + {SPR_SARC, FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_SPECIALSTAGEARCH + {SPR_SSBM, FF_GLOBALANIM|FF_ANIMATE|0, -1, {NULL}, 3, 3, S_NULL}, // S_SPECIALSTAGEBOMB + {SPR_SSBM, 0, 1, {A_SetObjectFlags}, MF_NOCLIPTHING, 2, S_SPECIALSTAGEBOMB_EXPLODE}, // S_SPECIALSTAGEBOMB_DISARM + {SPR_NULL, 0, 0, {A_SpecialStageBombExplode}, 0, 0, S_SPECIALSTAGEBOMB_DISAPPEAR}, // S_SPECIALSTAGEBOMB_EXPLODE + {SPR_NULL, 0, 28*TICRATE, {A_Pain}, 0, 0, S_SPECIALSTAGEBOMB_FLICKER1}, // S_SPECIALSTAGEBOMB_DISAPPEAR + {SPR_SSBM, FF_GLOBALANIM|FF_ANIMATE|0, 1, {NULL}, 3, 3, S_SPECIALSTAGEBOMB_FLICKER2}, // S_SPECIALSTAGEBOMB_FLICKER1 + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_SPECIALSTAGEBOMB_FLICKERLOOP}, // S_SPECIALSTAGEBOMB_FLICKER2 + {SPR_NULL, 0, 0, {A_Repeat}, TICRATE, S_SPECIALSTAGEBOMB_FLICKER1, S_SPECIALSTAGEBOMB_RESET}, // S_SPECIALSTAGEBOMB_FLICKERLOOP + {SPR_NULL, 0, 0, {A_SetObjectFlags}, MF_NOCLIPTHING, 1, S_SPECIALSTAGEBOMB}, // S_SPECIALSTAGEBOMB_RESET + // SMK ports {SPR_SMKP, 0, -1, {NULL}, 0, 0, S_SMK_PIPE1}, // S_SMK_PIPE1 {SPR_SMKP, 1, -1, {NULL}, 0, 0, S_SMK_PIPE2}, // S_SMK_PIPE2 @@ -28300,6 +28315,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SPECIALSTAGEARCH + 3889, // doomednum + S_SPECIALSTAGEARCH, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // 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 + 16*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_SPECIALSTAGEBOMB + 3890, // doomednum + S_SPECIALSTAGEBOMB, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_SPECIALSTAGEBOMB_DISARM, // painstate + 0, // painchance + sfx_s24b, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 60*FRACUNIT, // radius + 100*FRACUNIT, // height + 0, // dispoffset + 7, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL, // flags + S_SPECIALSTAGEBOMB_EXPLODE // raisestate + }, + { // MT_SMK_PIPE 3970, // doomednum S_SMK_PIPE1, // spawnstate diff --git a/src/info.h b/src/info.h index 1a4054638..e50c5cb60 100644 --- a/src/info.h +++ b/src/info.h @@ -282,6 +282,7 @@ enum actionnum A_SSMINEEXPLODE, A_LANDMINEEXPLODE, A_BALLHOGEXPLODE, + A_SPECIALSTAGEBOMBEXPLODE, A_LIGHTNINGFOLLOWPLAYER, A_FZBOOMFLASH, A_FZBOOMSMOKE, @@ -557,6 +558,7 @@ void A_SSMineFlash(); void A_LandMineExplode(); void A_LandMineExplode(); void A_BallhogExplode(); +void A_SpecialStageBombExplode(); void A_LightningFollowPlayer(); void A_FZBoomFlash(); void A_FZBoomSmoke(); @@ -1351,6 +1353,10 @@ typedef enum sprite // Eerie Grove SPR_EGFG, + // Chaos Chute + SPR_SARC, + SPR_SSBM, + // SMK ports SPR_SMKP, SPR_MTYM, @@ -5526,6 +5532,17 @@ typedef enum state S_EERIEFOG4, S_EERIEFOG5, + // Chaos Chute + S_SPECIALSTAGEARCH, + S_SPECIALSTAGEBOMB, + S_SPECIALSTAGEBOMB_DISARM, + S_SPECIALSTAGEBOMB_EXPLODE, + S_SPECIALSTAGEBOMB_DISAPPEAR, + S_SPECIALSTAGEBOMB_FLICKER1, + S_SPECIALSTAGEBOMB_FLICKER2, + S_SPECIALSTAGEBOMB_FLICKERLOOP, + S_SPECIALSTAGEBOMB_RESET, + // SMK ports S_SMK_PIPE1, // Generic pipes S_SMK_PIPE2, @@ -6919,6 +6936,10 @@ typedef enum mobj_type MT_EERIEFOG, MT_EERIEFOGGEN, + // Chaos Chute + MT_SPECIALSTAGEARCH, + MT_SPECIALSTAGEBOMB, + // SMK ports MT_SMK_PIPE, MT_SMK_MOLESPAWNER, diff --git a/src/k_kart.c b/src/k_kart.c index c4c48c630..848a7acdc 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4524,7 +4524,7 @@ void K_MineFlashScreen(mobj_t *source) } // Spawns the purely visual explosion -void K_SpawnMineExplosion(mobj_t *source, UINT8 color, tic_t delay) +void K_SpawnMineExplosion(mobj_t *source, skincolornum_t color, tic_t delay) { INT32 i, radius, height; mobj_t *smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING); @@ -4612,6 +4612,38 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color, tic_t delay) #undef MINEQUAKEDIST +void K_SpawnLandMineExplosion(mobj_t *source, skincolornum_t color, tic_t delay) +{ + mobj_t *smoldering; + mobj_t *expl; + UINT8 i; + + // Spawn smoke remains: + smoldering = P_SpawnMobj(source->x, source->y, source->z, MT_SMOLDERING); + P_SetScale(smoldering, source->scale); + smoldering->tics = TICRATE*3; + smoldering->hitlag = delay; + + // spawn a few physics explosions + for (i = 0; i < 15; i++) + { + expl = P_SpawnMobj(source->x, source->y, source->z + source->scale, MT_BOOMEXPLODE); + expl->color = color; + expl->tics = (i+1); + expl->hitlag = delay; + expl->renderflags |= RF_DONTDRAW; + + //K_MatchGenericExtraFlags(expl, actor); + P_SetScale(expl, source->scale*4); + + expl->momx = P_RandomRange(PR_EXPLOSION, -3, 3)*source->scale/2; + expl->momy = P_RandomRange(PR_EXPLOSION, -3, 3)*source->scale/2; + + // 100/45 = 2.22 fu/t + expl->momz = ((i+1)*source->scale*5/2)*P_MobjFlip(expl); + } +} + fixed_t K_ItemScaleForPlayer(player_t *player) { switch (player->itemscale) diff --git a/src/k_kart.h b/src/k_kart.h index e33580f81..0f310d403 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -120,7 +120,8 @@ void K_DebtStingPlayer(player_t *player, mobj_t *source); void K_GiveBumpersToPlayer(player_t *player, player_t *victim, UINT8 amount); void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount); void K_MineFlashScreen(mobj_t *source); -void K_SpawnMineExplosion(mobj_t *source, UINT8 color, tic_t delay); +void K_SpawnMineExplosion(mobj_t *source, skincolornum_t color, tic_t delay); +void K_SpawnLandMineExplosion(mobj_t *source, skincolornum_t color, tic_t delay); void K_RunFinishLineBeam(void); UINT16 K_DriftSparkColor(player_t *player, INT32 charge); void K_SpawnBoostTrail(player_t *player); diff --git a/src/p_enemy.c b/src/p_enemy.c index b8bedfc5e..f874e1f1a 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -318,6 +318,7 @@ void A_SSMineExplode(mobj_t *actor); void A_SSMineFlash(mobj_t *actor); void A_LandMineExplode(mobj_t *actor); void A_BallhogExplode(mobj_t *actor); +void A_SpecialStageBombExplode(mobj_t *actor); void A_LightningFollowPlayer(mobj_t *actor); void A_FZBoomFlash(mobj_t *actor); void A_FZBoomSmoke(mobj_t *actor); @@ -13068,12 +13069,7 @@ void A_SSMineFlash(mobj_t *actor) void A_LandMineExplode(mobj_t *actor) { - - mobj_t *expl; - INT32 colour = SKINCOLOR_KETCHUP; // we spell words properly here - INT32 i; - mobj_t *smoldering; - + skincolornum_t colour = SKINCOLOR_KETCHUP; // we spell words properly here tic_t delay = actor->reactiontime; if (LUA_CallAction(A_LANDMINEEXPLODE, actor)) @@ -13090,33 +13086,10 @@ void A_LandMineExplode(mobj_t *actor) if (actor->target && !P_MobjWasRemoved(actor->target)) colour = actor->target->color; - // Spawn smoke remains: - smoldering = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMOLDERING); - P_SetScale(smoldering, actor->scale); - smoldering->tics = TICRATE*3; - smoldering->hitlag = delay; + K_SpawnLandMineExplosion(actor, colour, delay); actor->fuse = actor->tics; // disappear when this state ends. - // spawn a few physics explosions - for (i = 0; i < 15; i++) - { - expl = P_SpawnMobj(actor->x, actor->y, actor->z + actor->scale, MT_BOOMEXPLODE); - expl->color = colour; - expl->tics = (i+1); - expl->hitlag = delay; - expl->renderflags |= RF_DONTDRAW; - - //K_MatchGenericExtraFlags(expl, actor); - P_SetScale(expl, actor->scale*4); - - expl->momx = P_RandomRange(PR_EXPLOSION, -3, 3)*actor->scale/2; - expl->momy = P_RandomRange(PR_EXPLOSION, -3, 3)*actor->scale/2; - - // 100/45 = 2.22 fu/t - expl->momz = ((i+1)*actor->scale*5/2)*P_MobjFlip(expl); - } - Obj_SpawnBrolyKi(actor, delay); } @@ -13134,6 +13107,14 @@ void A_BallhogExplode(mobj_t *actor) return; } +void A_SpecialStageBombExplode(mobj_t *actor) +{ + if (LUA_CallAction(A_SPECIALSTAGEBOMBEXPLODE, actor)) + return; + + K_SpawnLandMineExplosion(actor, SKINCOLOR_KETCHUP, actor->hitlag); +} + // A_LightningFollowPlayer: // Dumb simple function that gives a mobj its target's momentums without updating its angle. void A_LightningFollowPlayer(mobj_t *actor) diff --git a/src/p_inter.c b/src/p_inter.c index 6176201ec..89654574a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -556,6 +556,26 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_SetTarget(&special->target, toucher); S_StartSound(special, sfx_s1a2); return; + + case MT_SPECIALSTAGEBOMB: + // only attempt to damage the player if they're not invincible + if (!(player->invincibilitytimer > 0 + || K_IsBigger(toucher, special) == true + || K_PlayerGuard(player) == true + || player->hyudorotimer > 0)) + { + if (P_DamageMobj(toucher, special, special, 1, DMG_STUMBLE)) + { + P_SetMobjState(special, special->info->painstate); + special->eflags |= MFE_DAMAGEHITLAG; + return; + } + } + // if we didn't damage the player, just explode + P_SetMobjState(special, special->info->painstate); + P_SetMobjState(special, special->info->raisestate); // immediately explode visually + return; + case MT_CDUFO: // SRB2kart if (special->fuse || !P_CanPickupItem(player, 1)) return;