diff --git a/src/dehacked.c b/src/dehacked.c index a76e7c9f0..c4b8ca3bc 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -4450,8 +4450,18 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_GSNAPPER4", // Minus + "S_MINUS_INIT", "S_MINUS_STND", - "S_MINUS_DIGGING", + "S_MINUS_DIGGING1", + "S_MINUS_DIGGING2", + "S_MINUS_DIGGING3", + "S_MINUS_DIGGING4", + "S_MINUS_BURST0", + "S_MINUS_BURST1", + "S_MINUS_BURST2", + "S_MINUS_BURST3", + "S_MINUS_BURST4", + "S_MINUS_BURST5", "S_MINUS_POPUP", "S_MINUS_UPWARD1", "S_MINUS_UPWARD2", @@ -4470,6 +4480,15 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_MINUS_DOWNWARD7", "S_MINUS_DOWNWARD8", + // Minus dirt + "S_MINUSDIRT1", + "S_MINUSDIRT2", + "S_MINUSDIRT3", + "S_MINUSDIRT4", + "S_MINUSDIRT5", + "S_MINUSDIRT6", + "S_MINUSDIRT7", + // Spring Shell "S_SSHELL_STND", "S_SSHELL_RUN1", @@ -7157,6 +7176,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_EGGSHIELD", // Egg Guard's shield "MT_GSNAPPER", // Green Snapper "MT_MINUS", // Minus + "MT_MINUSDIRT", // Minus dirt "MT_SPRINGSHELL", // Spring Shell "MT_YELLOWSHELL", // Spring Shell (yellow) "MT_UNIDUS", // Unidus diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 4c4e369e6..874670266 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -173,6 +173,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_ESHI &lspr[NOLIGHT], // SPR_GSNP &lspr[NOLIGHT], // SPR_MNUS + &lspr[NOLIGHT], // SPR_MNUD &lspr[NOLIGHT], // SPR_SSHL &lspr[NOLIGHT], // SPR_UNID &lspr[NOLIGHT], // SPR_CANA diff --git a/src/info.c b/src/info.c index cc0ad09f7..d5b9271b3 100644 --- a/src/info.c +++ b/src/info.c @@ -61,6 +61,7 @@ char sprnames[NUMSPRITES + 1][5] = "ESHI", // Egg Guard's shield "GSNP", // Green Snapper "MNUS", // Minus + "MNUD", // Minus dirt "SSHL", // Spring Shell "UNID", // Unidus "CANA", // Canarivore @@ -1060,8 +1061,18 @@ state_t states[NUMSTATES] = {SPR_GSNP, 3, 2, {A_Chase}, 0, 0, S_GSNAPPER1}, // S_GSNAPPER4 // Minus - {SPR_NULL, 0, 1, {A_Look}, 0, 0, S_MINUS_STND}, // S_MINUS_STND - {SPR_MNUS, 16, 1, {A_MinusDigging}, 0, 0, S_MINUS_DIGGING}, // S_MINUS_DIGGING + {SPR_MNUD, 0, 1, {NULL}, 0, 0, S_MINUS_STND}, // S_MINUS_INIT (required for objectplace to work) + {SPR_NULL, 0, 10, {A_Look}, 0, 0, S_MINUS_STND}, // S_MINUS_STND + {SPR_NULL, 0, 1, {A_MinusDigging}, 1, 0, S_MINUS_DIGGING2}, // S_MINUS_DIGGING1 + {SPR_NULL, 0, 1, {A_MinusDigging}, 0, 0, S_MINUS_DIGGING3}, // S_MINUS_DIGGING2 + {SPR_NULL, 0, 1, {A_MinusDigging}, 0, 0, S_MINUS_DIGGING4}, // S_MINUS_DIGGING3 + {SPR_NULL, 0, 1, {A_MinusDigging}, 0, 0, S_MINUS_DIGGING1}, // S_MINUS_DIGGING4 + {SPR_NULL, 0, 25, {NULL}, 0, 0, S_MINUS_POPUP}, // S_MINUS_BURST0 + {SPR_MNUD, FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUS_BURST2}, // S_MINUS_BURST1 + {SPR_MNUD, 1|FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUS_BURST3}, // S_MINUS_BURST2 + {SPR_MNUD, 2|FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUS_BURST4}, // S_MINUS_BURST3 + {SPR_MNUD, 3|FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUS_BURST5}, // S_MINUS_BURST4 + {SPR_MNUD, 4|FF_ANIMATE, 5, {NULL}, 1, 2, S_MINUSDIRT2}, // S_MINUS_BURST5 {SPR_MNUS, 0, 1, {A_MinusPopup}, 0, 0, S_MINUS_UPWARD1}, // S_MINUS_POPUP {SPR_MNUS, 0, 1, {A_MinusCheck}, 0, 0, S_MINUS_UPWARD2}, // S_MINUS_UPWARD1 {SPR_MNUS, 1, 1, {A_MinusCheck}, 0, 0, S_MINUS_UPWARD3}, // S_MINUS_UPWARD2 @@ -1080,6 +1091,14 @@ state_t states[NUMSTATES] = {SPR_MNUS, 14, 1, {A_MinusCheck}, 0, 0, S_MINUS_DOWNWARD8}, // S_MINUS_DOWNWARD7 {SPR_MNUS, 15, 1, {A_MinusCheck}, 0, 0, S_MINUS_DOWNWARD1}, // S_MINUS_DOWNWARD8 + {SPR_MNUD, FF_ANIMATE, 6, {NULL}, 1, 5, S_MINUSDIRT2}, // S_MINUSDIRT1 + {SPR_MNUD, 5, 8, {NULL}, 3, 5, S_MINUSDIRT3}, // S_MINUSDIRT2 + {SPR_MNUD, 4, 8, {NULL}, 3, 5, S_MINUSDIRT4}, // S_MINUSDIRT3 + {SPR_MNUD, 3, 8, {NULL}, 3, 5, S_MINUSDIRT5}, // S_MINUSDIRT4 + {SPR_MNUD, 2, 8, {NULL}, 3, 5, S_MINUSDIRT6}, // S_MINUSDIRT5 + {SPR_MNUD, 1, 8, {NULL}, 3, 5, S_MINUSDIRT7}, // S_MINUSDIRT6 + {SPR_MNUD, 0, 8, {NULL}, 3, 5, S_NULL}, // S_MINUSDIRT7 + // Spring Shell {SPR_SSHL, 0, 4, {A_Look}, 0, 0, S_SSHELL_STND}, // S_SSHELL_STND {SPR_SSHL, 0, 4, {A_Chase}, 0, 0, S_SSHELL_RUN2}, // S_SSHELL_RUN1 @@ -4687,29 +4706,56 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_MINUS 121, // doomednum - S_MINUS_STND, // spawnstate + S_MINUS_INIT, // spawnstate 1, // spawnhealth - S_MINUS_DIGGING,// seestate + S_MINUS_DIGGING1,// seestate sfx_None, // seesound 32, // reactiontime - sfx_s3k82, // attacksound + sfx_s3kccs, // attacksound S_NULL, // painstate 200, // painchance sfx_None, // painsound - S_MINUS_DOWNWARD1,// meleestate + S_MINUS_BURST0, // meleestate S_MINUS_POPUP, // missilestate S_XPLD_FLICKY, // deathstate S_NULL, // xdeathstate sfx_pop, // deathsound - 12, // speed + 17, // speed 24*FRACUNIT, // radius 32*FRACUNIT, // height 0, // display offset 100, // mass 0, // damage - sfx_mindig, // activesound - MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE, // flags - S_MINUS_UPWARD1 // raisestate + sfx_s3kd3s, // activesound + MF_ENEMY|MF_NOCLIPTHING, // flags + S_MINUS_BURST1 // raisestate + }, + + { // MT_MINUSDIRT + -1, // doomednum + S_MINUSDIRT1, // spawnstate + 1, // 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 + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIPTHING, // flags + S_NULL // raisestate }, { // MT_SPRINGSHELL diff --git a/src/info.h b/src/info.h index 6e544d2d6..fd60902ff 100644 --- a/src/info.h +++ b/src/info.h @@ -301,6 +301,7 @@ typedef enum sprite SPR_ESHI, // Egg Guard's shield SPR_GSNP, // Green Snapper SPR_MNUS, // Minus + SPR_MNUD, // Minus dirt SPR_SSHL, // Spring Shell SPR_UNID, // Unidus SPR_CANA, // Canarivore @@ -1208,8 +1209,18 @@ typedef enum state S_GSNAPPER4, // Minus + S_MINUS_INIT, S_MINUS_STND, - S_MINUS_DIGGING, + S_MINUS_DIGGING1, + S_MINUS_DIGGING2, + S_MINUS_DIGGING3, + S_MINUS_DIGGING4, + S_MINUS_BURST0, + S_MINUS_BURST1, + S_MINUS_BURST2, + S_MINUS_BURST3, + S_MINUS_BURST4, + S_MINUS_BURST5, S_MINUS_POPUP, S_MINUS_UPWARD1, S_MINUS_UPWARD2, @@ -1228,6 +1239,15 @@ typedef enum state S_MINUS_DOWNWARD7, S_MINUS_DOWNWARD8, + // Minus dirt + S_MINUSDIRT1, + S_MINUSDIRT2, + S_MINUSDIRT3, + S_MINUSDIRT4, + S_MINUSDIRT5, + S_MINUSDIRT6, + S_MINUSDIRT7, + // Spring Shell S_SSHELL_STND, S_SSHELL_RUN1, @@ -3935,6 +3955,7 @@ typedef enum mobj_type MT_EGGSHIELD, // Egg Guard's shield MT_GSNAPPER, // Green Snapper MT_MINUS, // Minus + MT_MINUSDIRT, // Minus dirt MT_SPRINGSHELL, // Spring Shell MT_YELLOWSHELL, // Spring Shell (yellow) MT_UNIDUS, // Unidus diff --git a/src/p_enemy.c b/src/p_enemy.c index 9dbb6e46e..2d4b39ff0 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -5143,56 +5143,110 @@ void A_ShootBullet(mobj_t *actor) S_StartSound(actor, actor->info->attacksound); } +static mobj_t *minus; + +static boolean PIT_MinusCarry(mobj_t *thing) +{ + if (minus->type == thing->type) + return true; + + if (!(thing->flags & MF_SHOOTABLE) || !(thing->flags & MF_ENEMY)) + return true; + + if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius * 3) + return true; + + if (abs(thing->z - minus->z) > minus->height) + return true; + + minus->tracer = thing; + minus->tracer->flags &= ~MF_PUSHABLE; + + return true; +} + // Function: A_MinusDigging // // Description: Minus digging in the ground. // -// var1 = unused +// var1 = If 1, play digging sound. // var2 = unused // void A_MinusDigging(mobj_t *actor) { + INT32 locvar1 = var1; + INT32 rad = 32; + angle_t fa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t dis = actor->info->speed*4; + fixed_t x = FINECOSINE(fa)*dis + actor->x + FRACUNIT*P_RandomRange(-rad, rad); + fixed_t y = FINESINE(fa)*dis + actor->y + FRACUNIT*P_RandomRange(-rad, rad); + fixed_t mz = (actor->eflags & MFE_VERTICALFLIP) ? actor->ceilingz : actor->floorz; + #ifdef HAVE_BLUA if (LUA_CallAction("A_MinusDigging", actor)) return; #endif - actor->flags &= ~MF_SPECIAL; - actor->flags &= ~MF_SHOOTABLE; if (!actor->target) { - A_Look(actor); + P_SetMobjState(actor, actor->info->spawnstate); return; } - if (actor->reactiontime) + mobj_t *par = P_SpawnMobj(actor->x, actor->y, mz, MT_MINUSDIRT); + if (actor->eflags & MFE_VERTICALFLIP) + par->eflags |= MFE_VERTICALFLIP; + P_TryMove(par, x, y, false); + + // If close enough, prepare to attack + if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < actor->radius*2) { - actor->reactiontime--; + P_SetMobjState(actor, actor->info->meleestate); + P_TryMove(actor, actor->target->x, actor->target->y, false); + S_StartSound(actor, actor->info->attacksound); + + // Spawn growing dirt pile. + mobj_t *par = P_SpawnMobj(actor->x, actor->y, mz, MT_MINUSDIRT); + P_SetMobjState(par, actor->info->raisestate); + P_SetScale(par, actor->scale*2); + if (actor->eflags & MFE_VERTICALFLIP) + par->eflags |= MFE_VERTICALFLIP; return; } - // Dirt trail - P_SpawnGhostMobj(actor); - - actor->flags |= MF_NOCLIPTHING; - var1 = 3; - A_Chase(actor); - actor->flags &= ~MF_NOCLIPTHING; - // Play digging sound - if (!(leveltime & 15)) - S_StartSound(actor, actor->info->activesound); + if (locvar1 == 1) + A_PlayActiveSound(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) < 2*actor->height) - P_SetMobjState(actor, actor->info->missilestate); + // Move + var1 = 3; + A_Chase(actor); - // Snap to ground - if (actor->eflags & MFE_VERTICALFLIP) - actor->z = actor->ceilingz - actor->height; + // Carry over shit, maybe + if (!actor->tracer) + { + fixed_t radius = 3*actor->radius; + fixed_t yh = (unsigned)(actor->y + radius - bmaporgy) >> MAPBLOCKSHIFT; + fixed_t yl = (unsigned)(actor->y - radius - bmaporgy) >> MAPBLOCKSHIFT; + fixed_t xh = (unsigned)(actor->x + radius - bmaporgx) >> MAPBLOCKSHIFT; + fixed_t xl = (unsigned)(actor->x - radius - bmaporgx) >> MAPBLOCKSHIFT; + fixed_t bx, by; + + BMBOUNDFIX(xl, xh, yl, yh); + + minus = actor; + + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + P_BlockThingsIterator(bx, by, PIT_MinusCarry); + } else - actor->z = actor->floorz; + { + if (P_TryMove(actor->tracer, actor->x, actor->y, false)) + actor->tracer->z = mz; + else + actor->tracer = NULL; + } } // Function: A_MinusPopup @@ -5204,45 +5258,56 @@ void A_MinusDigging(mobj_t *actor) // void A_MinusPopup(mobj_t *actor) { + INT32 num = 6; + angle_t ani = FixedAngle(FRACUNIT*360/num); + INT32 i; + #ifdef HAVE_BLUA if (LUA_CallAction("A_MinusPopup", actor)) return; #endif - P_SetObjectMomZ(actor, 10*FRACUNIT, false); - actor->flags |= MF_SPECIAL; - actor->flags |= MF_SHOOTABLE; + if (actor->eflags & MFE_VERTICALFLIP) + actor->momz = -10*FRACUNIT; + else + actor->momz = 10*FRACUNIT; + + actor->flags |= MF_SPECIAL|MF_SHOOTABLE; + S_StartSound(actor, sfx_s3k82); + for (i = 1; i <= num; i++) + { + mobj_t *rock = P_SpawnMobj(actor->x, actor->y, actor->z + actor->height/4, MT_ROCKCRUMBLE1); + P_Thrust(rock, ani*i, FRACUNIT); + rock->momz = 3*FRACUNIT; + P_SetScale(rock, FRACUNIT/3); + } + P_RadiusAttack(actor, actor, 2*actor->radius, 0); + if (actor->tracer) + P_DamageMobj(actor->tracer, actor, actor, 1, 0); - // Sound for busting out of the ground. - S_StartSound(actor, actor->info->attacksound); } // Function: A_MinusCheck // // Description: If the minus hits the floor, dig back into the ground. // -// var1 = unused +// var1 = State to switch to (if 0, use seestate). // var2 = unused // void A_MinusCheck(mobj_t *actor) { + INT32 locvar1 = var1; + #ifdef HAVE_BLUA if (LUA_CallAction("A_MinusCheck", actor)) return; #endif - if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) - || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)) - { - actor->flags &= ~MF_SPECIAL; - actor->flags &= ~MF_SHOOTABLE; - actor->reactiontime = TICRATE; - P_SetMobjState(actor, actor->info->seestate); - return; - } - // 'Falling' animation - if (P_MobjFlip(actor)*actor->momz < 0 && actor->state < &states[actor->info->meleestate]) - P_SetMobjState(actor, actor->info->meleestate); + if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz) || (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)) + { + P_SetMobjState(actor, locvar1 ? locvar1 : actor->info->seestate); + actor->flags = actor->info->flags; + } } // Function: A_ChickenCheck diff --git a/src/sounds.c b/src/sounds.c index 84b2c8a0c..5cfa59508 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -456,7 +456,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3kcas", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Energy"}, {"s3kcal", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Energy"}, // ditto {"s3kcbs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, - {"s3kcbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominuous rumbling"}, // ditto + {"s3kcbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, // ditto {"s3kccs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Collapsing"}, {"s3kccl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Collapsing"}, // ditto {"s3kcds", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, @@ -471,8 +471,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3kd1l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto {"s3kd2s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turning"}, {"s3kd2l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Moving chain"}, // ditto - {"s3kd3s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, - {"s3kd3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto + {"s3kd3s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Digging"}, + {"s3kd3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Digging"}, // ditto {"s3kd4s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Engine"}, {"s3kd4l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Engine"}, // ditto {"s3kd5s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling lava"},