From 26d13db548c2f7e2b4f43142cf4337d8fd281857 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 14 May 2018 01:19:24 +0100 Subject: [PATCH] * Crushtacean! * Behaves a bit differently to the one in DSZres.pk3. * Can now punch DSZ mines! * Also has mapthingnum 126 instead of 610. * Some other mapthingnum changes. * DSZ2 stalagmite is now 1009, formerly 999. * Big DSZ gargoyle is now 1011, formerly 1009. --- src/dehacked.c | 42 +++++-- src/hardware/hw_light.c | 1 + src/info.c | 109 ++++++++++++++++- src/info.h | 47 +++++-- src/p_enemy.c | 262 ++++++++++++++++++++++++++++++++++++++++ src/p_inter.c | 14 +++ src/p_map.c | 63 +++++++--- src/p_mobj.c | 69 ++++++----- src/sounds.c | 4 +- 9 files changed, 534 insertions(+), 77 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 7013c0379..5c5d1004a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1705,6 +1705,10 @@ static actionpointer_t actionpointers[] = {{A_SharpChase}, "A_SHARPCHASE"}, {{A_SharpSpin}, "A_SHARPSPIN"}, {{A_SharpDecel}, "A_SHARPDECEL"}, + {{A_CrushstaceanWalk}, "A_CRUSHSTACEANWALK"}, + {{A_CrushstaceanPunch}, "A_CRUSHSTACEANPUNCH"}, + {{A_CrushclawAim}, "A_CRUSHCLAWAIM"}, + {{A_CrushclawLaunch}, "A_CRUSHCLAWLAUNCH"}, {{A_VultureVtol}, "A_VULTUREVTOL"}, {{A_VultureCheck}, "A_VULTURECHECK"}, {{A_SkimChase}, "A_SKIMCHASE"}, @@ -3686,6 +3690,21 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SPINCUSHION_STOP3", "S_SPINCUSHION_STOP4", + // Crushstacean + "S_CRUSHSTACEAN_ROAM1", + "S_CRUSHSTACEAN_ROAM2", + "S_CRUSHSTACEAN_ROAM3", + "S_CRUSHSTACEAN_ROAM4", + "S_CRUSHSTACEAN_ROAMPAUSE", + "S_CRUSHSTACEAN_PUNCH1", + "S_CRUSHSTACEAN_PUNCH2", + "S_CRUSHCLAW_AIM", + "S_CRUSHCLAW_OUT", + "S_CRUSHCLAW_STAY", + "S_CRUSHCLAW_IN", + "S_CRUSHCLAW_WAIT", + "S_CRUSHCHAIN", + // Jet Jaw "S_JETJAW_ROAM1", "S_JETJAW_ROAM2", @@ -6160,31 +6179,34 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_TAILSOVERLAY", // c: // Enemies - "MT_BLUECRAWLA", - "MT_REDCRAWLA", - "MT_GFZFISH", // Greenflower Fish - "MT_GOLDBUZZ", - "MT_REDBUZZ", + "MT_BLUECRAWLA", // Crawla (Blue) + "MT_REDCRAWLA", // Crawla (Red) + "MT_GFZFISH", // SDURF + "MT_GOLDBUZZ", // Buzz (Gold) + "MT_REDBUZZ", // Buzz (Red) "MT_JETTBOMBER", // Jetty-Syn Bomber "MT_JETTGUNNER", // Jetty-Syn Gunner "MT_CRAWLACOMMANDER", // Crawla Commander "MT_DETON", // Deton "MT_SKIM", // Skim mine dropper - "MT_TURRET", - "MT_POPUPTURRET", + "MT_TURRET", // Industrial Turret + "MT_POPUPTURRET", // Pop-Up Turret "MT_SPINCUSHION", // Spincushion + "MT_CRUSHSTACEAN", // Crushstacean + "MT_CRUSHCLAW", // Big meaty claw + "MT_CRUSHCHAIN", // Chain "MT_JETJAW", // Jet Jaw "MT_SNAILER", // Snailer - "MT_VULTURE", // Vulture + "MT_VULTURE", // BASH "MT_POINTY", // Pointy "MT_POINTYBALL", // Pointy Ball "MT_ROBOHOOD", // Robo-Hood "MT_FACESTABBER", // CastleBot FaceStabber "MT_EGGGUARD", // Egg Guard - "MT_EGGSHIELD", // Egg Shield for Egg Guard + "MT_EGGSHIELD", // Egg Guard's shield "MT_GSNAPPER", // Green Snapper "MT_MINUS", // Minus - "MT_SPRINGSHELL", // Spring Shell (no drop) + "MT_SPRINGSHELL", // Spring Shell "MT_YELLOWSHELL", // Spring Shell (yellow) "MT_UNIDUS", // Unidus "MT_UNIBALL", // Unidus Ball diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index feb9565b5..870dfb724 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -161,6 +161,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_TRET &lspr[NOLIGHT], // SPR_TURR &lspr[NOLIGHT], // SPR_SHRP + &lspr[NOLIGHT], // SPR_CRAB &lspr[NOLIGHT], // SPR_JJAW &lspr[NOLIGHT], // SPR_SNLR &lspr[NOLIGHT], // SPR_VLTR diff --git a/src/info.c b/src/info.c index 9c546e370..268944318 100644 --- a/src/info.c +++ b/src/info.c @@ -49,14 +49,15 @@ char sprnames[NUMSPRITES + 1][5] = "TRET", // Industrial Turret "TURR", // Pop-Up Turret "SHRP", // Sharp + "CRAB", // Crushstacean "JJAW", // Jet Jaw "SNLR", // Snailer - "VLTR", // Vulture + "VLTR", // BASH "PNTY", // Pointy "ARCH", // Robo-Hood "CBFS", // Castlebot Facestabber "SPSH", // Egg Guard - "ESHI", // Egg Shield for Egg Guard + "ESHI", // Egg Guard's shield "GSNP", // Green Snapper "MNUS", // Minus "SSHL", // Spring Shell @@ -904,6 +905,21 @@ state_t states[NUMSTATES] = {SPR_SHRP, 5, 4, {A_FaceTarget}, 0, 0, S_SPINCUSHION_STOP4}, // S_SPINCUSHION_STOP3 {SPR_SHRP, 4, 4, {A_SetObjectFlags}, MF_PAIN, 1, S_SPINCUSHION_LOOK}, // S_SPINCUSHION_STOP4 + // Crushstacean + {SPR_CRAB, 0, 3, {A_CrushstaceanWalk}, 0, S_CRUSHSTACEAN_ROAMPAUSE, S_CRUSHSTACEAN_ROAM2}, // S_CRUSHSTACEAN_ROAM1 + {SPR_CRAB, 1, 3, {A_CrushstaceanWalk}, 0, S_CRUSHSTACEAN_ROAMPAUSE, S_CRUSHSTACEAN_ROAM3}, // S_CRUSHSTACEAN_ROAM2 + {SPR_CRAB, 0, 3, {A_CrushstaceanWalk}, 0, S_CRUSHSTACEAN_ROAMPAUSE, S_CRUSHSTACEAN_ROAM4}, // S_CRUSHSTACEAN_ROAM3 + {SPR_CRAB, 2, 3, {A_CrushstaceanWalk}, 0, S_CRUSHSTACEAN_ROAMPAUSE, S_CRUSHSTACEAN_ROAM1}, // S_CRUSHSTACEAN_ROAM4 + {SPR_CRAB, 0, 40, {NULL}, 0, 0, S_CRUSHSTACEAN_ROAM1}, // S_CRUSHSTACEAN_ROAMPAUSE + {SPR_CRAB, 0, 10, {NULL}, 0, 0, S_CRUSHSTACEAN_PUNCH2}, // S_CRUSHSTACEAN_PUNCH1 + {SPR_CRAB, 0, -1, {A_CrushstaceanPunch}, 0, 0, S_CRUSHSTACEAN_ROAMPAUSE}, // S_CRUSHSTACEAN_PUNCH2 + {SPR_CRAB, 3, 1, {A_CrushclawAim}, 0, 0, S_CRUSHCLAW_AIM}, // S_CRUSHCLAW_AIM + {SPR_CRAB, 3, 1, {A_CrushclawLaunch}, 0, S_CRUSHCLAW_STAY, S_CRUSHCLAW_OUT}, // S_CRUSHCLAW_OUT + {SPR_CRAB, 3, 10, {NULL}, 0, 0, S_CRUSHCLAW_IN}, // S_CRUSHCLAW_STAY + {SPR_CRAB, 3, 1, {A_CrushclawLaunch}, 1, S_CRUSHCLAW_WAIT, S_CRUSHCLAW_IN}, // S_CRUSHCLAW_IN + {SPR_CRAB, 3, 37, {NULL}, 0, 0, S_CRUSHCLAW_AIM}, // S_CRUSHCLAW_WAIT + {SPR_CRAB, 4, -1, {NULL}, 0, 0, S_NULL}, // S_CRUSHCHAIN + // Jet Jaw {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM2}, // S_JETJAW_ROAM1 {SPR_JJAW, 0, 1, {A_JetJawRoam}, 0, 0, S_JETJAW_ROAM3}, // S_JETJAW_ROAM2 @@ -3455,7 +3471,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - 8, // speed + 0, // speed 0, // radius 0, // height 0, // display offset @@ -3544,7 +3560,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MT_THOK, // damage sfx_None, // activesound MF_SOLID|MF_SHOOTABLE, // flags - (statenum_t)MT_NULL // raisestate + MT_NULL // raisestate }, { // MT_TAILSOVERLAY @@ -3925,6 +3941,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_CRUSHSTACEAN + 126, // doomednum + S_CRUSHSTACEAN_ROAM1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 32, // reactiontime + sfx_s3k6b, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_CRUSHSTACEAN_PUNCH1, // missilestate + S_XPLD_FLICKY, // deathstate + S_NULL, // xdeathstate + sfx_pop, // deathsound + 8, // speed + 24*FRACUNIT, // radius + 32*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE, // flags + S_NULL // raisestate + }, + + { // MT_CRUSHCLAW + -1, // doomednum + S_CRUSHCLAW_AIM, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 16, // reactiontime + sfx_s3k6b, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_CRUSHCLAW_OUT,// missilestate + S_XPLD1, // deathstate + S_NULL, // xdeathstate + sfx_pop, // deathsound + 1, // speed + 32*FRACUNIT, // radius + 24*FRACUNIT, // height + 0, // display offset + (sfx_s3k49<<8), // mass + 0, // damage + sfx_s3kd2l, // activesound + MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MT_CRUSHCHAIN // raisestate + }, + + { // MT_CRUSHCHAIN + -1, // doomednum + S_CRUSHCHAIN, // spawnstate + 0, // 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 + 0, // radius + 0, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_JETJAW 113, // doomednum S_JETJAW_ROAM1, // spawnstate @@ -8997,7 +9094,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = }, { // MT_BIGGARGOYLE - 1009, // doomednum + 1011, // doomednum S_BIGGARGOYLE, // spawnstate 1000, // spawnhealth S_NULL, // seestate @@ -9267,7 +9364,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = }, { // MT_DSZ2STALAGMITE - 999, // doomednum + 1009, // doomednum S_DSZ2STALAGMITE, // spawnstate 1000, // spawnhealth S_NULL, // seestate diff --git a/src/info.h b/src/info.h index 436cfc29c..38ebacadb 100644 --- a/src/info.h +++ b/src/info.h @@ -104,6 +104,10 @@ void A_SnailerThink(); void A_SharpChase(); void A_SharpSpin(); void A_SharpDecel(); +void A_CrushstaceanWalk(); +void A_CrushstaceanPunch(); +void A_CrushclawAim(); +void A_CrushclawLaunch(); void A_VultureVtol(); void A_VultureCheck(); void A_SkimChase(); @@ -257,14 +261,15 @@ typedef enum sprite SPR_TRET, // Industrial Turret SPR_TURR, // Pop-Up Turret SPR_SHRP, // Sharp + SPR_CRAB, // Crushstacean SPR_JJAW, // Jet Jaw SPR_SNLR, // Snailer - SPR_VLTR, // Vulture + SPR_VLTR, // BASH SPR_PNTY, // Pointy SPR_ARCH, // Robo-Hood SPR_CBFS, // Castlebot Facestabber SPR_SPSH, // Egg Guard - SPR_ESHI, // Egg Shield for Egg Guard + SPR_ESHI, // Egg Guard's shield SPR_GSNP, // Green Snapper SPR_MNUS, // Minus SPR_SSHL, // Spring Shell @@ -1022,6 +1027,21 @@ typedef enum state S_SPINCUSHION_STOP3, S_SPINCUSHION_STOP4, + // Crushstacean + S_CRUSHSTACEAN_ROAM1, + S_CRUSHSTACEAN_ROAM2, + S_CRUSHSTACEAN_ROAM3, + S_CRUSHSTACEAN_ROAM4, + S_CRUSHSTACEAN_ROAMPAUSE, + S_CRUSHSTACEAN_PUNCH1, + S_CRUSHSTACEAN_PUNCH2, + S_CRUSHCLAW_AIM, + S_CRUSHCLAW_OUT, + S_CRUSHCLAW_STAY, + S_CRUSHCLAW_IN, + S_CRUSHCLAW_WAIT, + S_CRUSHCHAIN, + // Jet Jaw S_JETJAW_ROAM1, S_JETJAW_ROAM2, @@ -3518,28 +3538,31 @@ typedef enum mobj_type MT_TAILSOVERLAY, // c: // Enemies - MT_BLUECRAWLA, - MT_REDCRAWLA, - MT_GFZFISH, // Greenflower Fish - MT_GOLDBUZZ, - MT_REDBUZZ, + MT_BLUECRAWLA, // Crawla (Blue) + MT_REDCRAWLA, // Crawla (Red) + MT_GFZFISH, // SDURF + MT_GOLDBUZZ, // Buzz (Gold) + MT_REDBUZZ, // Buzz (Red) MT_JETTBOMBER, // Jetty-Syn Bomber MT_JETTGUNNER, // Jetty-Syn Gunner MT_CRAWLACOMMANDER, // Crawla Commander MT_DETON, // Deton MT_SKIM, // Skim mine dropper - MT_TURRET, - MT_POPUPTURRET, + MT_TURRET, // Industrial Turret + MT_POPUPTURRET, // Pop-Up Turret MT_SPINCUSHION, // Spincushion + MT_CRUSHSTACEAN, // Crushstacean + MT_CRUSHCLAW, // Big meaty claw + MT_CRUSHCHAIN, // Chain MT_JETJAW, // Jet Jaw MT_SNAILER, // Snailer - MT_VULTURE, // Vulture + MT_VULTURE, // BASH MT_POINTY, // Pointy MT_POINTYBALL, // Pointy Ball MT_ROBOHOOD, // Robo-Hood - MT_FACESTABBER, // CastleBot FaceStabber + MT_FACESTABBER, // Castlebot Facestabber MT_EGGGUARD, // Egg Guard - MT_EGGSHIELD, // Egg Shield for Egg Guard + MT_EGGSHIELD, // Egg Guard's shield MT_GSNAPPER, // Green Snapper MT_MINUS, // Minus MT_SPRINGSHELL, // Spring Shell diff --git a/src/p_enemy.c b/src/p_enemy.c index 12c9d8dec..5a1257cdd 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -65,6 +65,10 @@ void A_SnailerThink(mobj_t *actor); void A_SharpChase(mobj_t *actor); void A_SharpSpin(mobj_t *actor); void A_SharpDecel(mobj_t *actor); +void A_CrushstaceanWalk(mobj_t *actor); +void A_CrushstaceanPunch(mobj_t *actor); +void A_CrushclawAim(mobj_t *actor); +void A_CrushclawLaunch(mobj_t *actor); void A_VultureVtol(mobj_t *actor); void A_VultureCheck(mobj_t *actor); void A_SkimChase(mobj_t *actor); @@ -1615,6 +1619,264 @@ void A_SharpDecel(mobj_t *actor) P_SetMobjState(actor, actor->info->xdeathstate); } +// Function: A_CrushstaceanWalk +// +// Description: Crushstacean movement +// +// var1 = speed (actor info's speed if 0) +// var2 = state to switch to when blocked (spawnstate if 0) +// +void A_CrushstaceanWalk(mobj_t *actor) +{ + INT32 locvar1 = (var1 ? var1 : (INT32)actor->info->speed); + INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate); + angle_t ang = actor->angle + ((actor->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CrushstaceanWalk", actor)) + return; +#endif + + actor->reactiontime--; + + if (!P_TryMove(actor, + actor->x + P_ReturnThrustX(actor, ang, locvar1*actor->scale), + actor->y + P_ReturnThrustY(actor, ang, locvar1*actor->scale), + false) + || (actor->reactiontime-- <= 0)) + { + actor->flags2 ^= MF2_AMBUSH; + P_SetMobjState(actor, locvar2); + actor->reactiontime = actor->info->reactiontime; + } +} + +// Function: A_CrushstaceanPunch +// +// Description: Crushstacean attack +// +// var1 = unused +// var2 = state to go to if unsuccessful (spawnstate if 0) +// +void A_CrushstaceanPunch(mobj_t *actor) +{ + //INT32 locvar1 = var1; + INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate); +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CrushstaceanPunch", actor)) + return; +#endif + + if (!actor->tracer) + return; + + if (!actor->target) + { + P_SetMobjState(actor, locvar2); + return; + } + + actor->tracer->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + P_SetMobjState(actor->tracer, actor->tracer->info->missilestate); + actor->tracer->extravalue1 = actor->tracer->extravalue2 = 0; + S_StartSound(actor, actor->info->attacksound); +} + +// Function: A_CrushclawAim +// +// Description: Crushstacean claw aiming +// +// var1 = unused +// var2 = unused +// +void A_CrushclawAim(mobj_t *actor) +{ + //INT32 locvar1 = var1; + //INT32 locvar2 = var2; + mobj_t *crab = actor->tracer; + angle_t ang; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CrushclawAim", actor)) + return; +#endif + + if (!crab) + { + P_RemoveMobj(actor); + return; // there is only one step and it is crab + } + + if (crab->target || P_LookForPlayers(crab, true, false, 600*crab->scale)) + ang = R_PointToAngle2(crab->x, crab->y, crab->target->x, crab->target->y); + else + ang = crab->angle + ((crab->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270); + ang -= actor->angle; + +#define anglimit ANGLE_22h +#define angfactor 5 + if (ang < ANGLE_180) + { + if (ang > anglimit) + ang = anglimit; + ang /= angfactor; + } + else + { + ang = InvAngle(ang); + if (ang > anglimit) + ang = anglimit; + ang = InvAngle(ang/angfactor); + } + actor->angle += ang; +#undef anglimit +#undef angfactor + + P_TeleportMove(actor, + crab->x + P_ReturnThrustX(actor, actor->angle, 40*crab->scale), + crab->y + P_ReturnThrustY(actor, actor->angle, 40*crab->scale), + crab->z + 20*crab->scale); + + if (!crab->target || (statenum_t)(crab->state-states) == crab->info->missilestate) + return; + + if (((ang + ANG1) < ANG2) || P_AproxDistance(crab->x - crab->target->x, crab->y - crab->target->y) < 333*crab->scale) + P_SetMobjState(crab, crab->info->missilestate); +} + +// Function: A_CrushclawLaunch +// +// Description: Crushstacean claw launching +// +// var1: +// 0 - forwards +// anything else - backwards +// var2 = state to change to when done +// +void A_CrushclawLaunch(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *crab = actor->tracer; +#ifdef HAVE_BLUA + if (LUA_CallAction("A_CrushclawLaunch", actor)) + return; +#endif + + if (!crab) + { + mobj_t *chainnext; + while (actor) + { + chainnext = actor->target; + P_RemoveMobj(actor); + actor = chainnext; + } + return; // there is only one step and it is crab + } + + if (!actor->extravalue1) + { + S_StartSound(actor, actor->info->activesound); + actor->extravalue1 = ((locvar1) ? -1 : 32); + } + else if (actor->extravalue1 != 1) + actor->extravalue1 -= 1; + +#define CSEGS 5 + if (!actor->target) + { + mobj_t *prevchain = actor; + UINT8 i = 0; + for (i = 0; (i < CSEGS); i++) + { + mobj_t *newchain = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->info->raisestate); + prevchain->target = newchain; + prevchain = newchain; + } + actor->target->angle = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y); + } + + if ((!locvar1) && crab->target) + { +#define anglimit ANGLE_22h +#define angfactor 7 + angle_t ang = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y) - actor->target->angle; + if (ang < ANGLE_180) + { + if (ang > anglimit) + ang = anglimit; + ang /= angfactor; + } + else + { + ang = InvAngle(ang); + if (ang > anglimit) + ang = anglimit; + ang /= angfactor; + ang = InvAngle(ang); + } + actor->target->angle += ang; + actor->angle = actor->target->angle; + } + + actor->extravalue2 += actor->extravalue1; + + if (!P_TryMove(actor, + actor->target->x + P_ReturnThrustX(actor, actor->target->angle, actor->extravalue2*actor->scale), + actor->target->y + P_ReturnThrustY(actor, actor->target->angle, actor->extravalue2*actor->scale), + true) + && !locvar1) + { + actor->extravalue1 = 0; + actor->extravalue2 = FixedHypot(actor->x - actor->target->x, actor->y - actor->target->y)>>FRACBITS; + P_SetMobjState(actor, locvar2); + S_StopSound(actor); + S_StartSound(actor, sfx_s3k49); + } + else + { + actor->z = actor->target->z; + if ((!locvar1 && (actor->extravalue2 > 256)) || (locvar1 && (actor->extravalue2 < 16))) + { + if (locvar1) // In case of retracting, resume crab and remove the chain. + { + mobj_t *chain = actor->target, *chainnext; + while (chain) + { + chainnext = chain->target; + P_RemoveMobj(chain); + chain = chainnext; + } + actor->extravalue2 = 0; + actor->angle = R_PointToAngle2(crab->x, crab->y, actor->x, actor->y); + P_SetTarget(&actor->target, NULL); + P_SetTarget(&crab->target, NULL); + P_SetMobjState(crab, crab->state->nextstate); + } + actor->extravalue1 = 0; + P_SetMobjState(actor, locvar2); + S_StopSound(actor); + } + } + + if (!actor->target) + return; + + { + mobj_t *chain = actor->target->target; + fixed_t dx = (actor->x - actor->target->x)/CSEGS, dy = (actor->y - actor->target->y)/CSEGS, dz = (actor->z - actor->target->z)/CSEGS; + fixed_t idx = dx, idy = dy, idz = dz; + while (chain) + { + P_TeleportMove(chain, actor->target->x + idx, actor->target->y + idy, actor->target->z + idz); + idx += dx; + idy += dy; + idz += dz; + chain = chain->target; + } + } +#undef CSEGS +} + // Function: A_VultureVtol // // Description: Vulture rising up to match target's height diff --git a/src/p_inter.c b/src/p_inter.c index ae39ffe79..8de008570 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2354,6 +2354,20 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->momx = target->momy = target->momz = 0; break; + case MT_CRUSHSTACEAN: + if (target->tracer) + { + mobj_t *chain = target->tracer->target, *chainnext; + while (chain) + { + chainnext = chain->target; + P_RemoveMobj(chain); + chain = chainnext; + } + P_KillMobj(target->tracer, inflictor, source, damagetype); + } + break; + case MT_EGGMOBILE3: { thinker_t *th; diff --git a/src/p_map.c b/src/p_map.c index 3834dfb6f..a7a12c2ec 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -633,28 +633,51 @@ static boolean PIT_CheckThing(mobj_t *thing) #endif // Billiards mines! - if (thing->type == MT_BIGMINE && tmthing->type == MT_BIGMINE) + if (thing->type == MT_BIGMINE) { - if (!tmthing->momx && !tmthing->momy) - return true; - if ((statenum_t)(thing->state-states) != thing->info->spawnstate) - return true; - if (thing->z > tmthing->z + tmthing->height) - return true; // overhead - if (thing->z + thing->height < tmthing->z) - return true; // underneath + if (tmthing->type == MT_BIGMINE) + { + if (!tmthing->momx && !tmthing->momy) + return true; + if ((statenum_t)(thing->state-states) >= thing->info->meleestate) + return true; + if (thing->z > tmthing->z + tmthing->height) + return true; // overhead + if (thing->z + thing->height < tmthing->z) + return true; // underneath - thing->momx = tmthing->momx/3; - thing->momy = tmthing->momy/3; - thing->momz = tmthing->momz/3; - tmthing->momx /= -8; - tmthing->momy /= -8; - tmthing->momz /= -8; - if (thing->info->activesound) - S_StartSound(thing, thing->info->activesound); - P_SetMobjState(thing, thing->info->meleestate); - P_SetTarget(&thing->tracer, tmthing->tracer); - return true; + thing->momx = tmthing->momx/3; + thing->momy = tmthing->momy/3; + thing->momz = tmthing->momz/3; + tmthing->momx /= -8; + tmthing->momy /= -8; + tmthing->momz /= -8; + if (thing->info->activesound) + S_StartSound(thing, thing->info->activesound); + P_SetMobjState(thing, thing->info->meleestate); + P_SetTarget(&thing->tracer, tmthing->tracer); + return true; + } + else if (tmthing->type == MT_CRUSHCLAW) + { + if (tmthing->extravalue1 <= 0) + return true; + if ((statenum_t)(thing->state-states) >= thing->info->meleestate) + return true; + if (thing->z > tmthing->z + tmthing->height) + return true; // overhead + if (thing->z + thing->height < tmthing->z) + return true; // underneath + + thing->momx = P_ReturnThrustX(tmthing, tmthing->angle, 2*tmthing->extravalue1*tmthing->scale/3); + thing->momy = P_ReturnThrustY(tmthing, tmthing->angle, 2*tmthing->extravalue1*tmthing->scale/3); + if (thing->info->activesound) + S_StartSound(thing, thing->info->activesound); + P_SetMobjState(thing, thing->info->meleestate); + if (tmthing->tracer) + P_SetTarget(&thing->tracer, tmthing->tracer->target); + return false; + } } // When solid spikes move, assume they just popped up and teleport things on top of them to hurt. diff --git a/src/p_mobj.c b/src/p_mobj.c index d35237414..095892c96 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8514,41 +8514,56 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) } break; case MT_UNIDUS: - { - INT32 i; - mobj_t *ball; - // Spawn "damage" number of "painchance" spikeball mobjs - // threshold is the distance they should keep from the MT_UNIDUS (touching radius + ball painchance) - for (i = 0; i < mobj->info->damage; i++) { - ball = P_SpawnMobj(x, y, z, mobj->info->painchance); - ball->destscale = mobj->scale; - P_SetScale(ball, mobj->scale); - P_SetTarget(&ball->target, mobj); - ball->movedir = FixedAngle(FixedMul(FixedDiv(i<info->damage<threshold = ball->radius + mobj->radius + FixedMul(ball->info->painchance, ball->scale); + INT32 i; + mobj_t *ball; + // Spawn "damage" number of "painchance" spikeball mobjs + // threshold is the distance they should keep from the MT_UNIDUS (touching radius + ball painchance) + for (i = 0; i < mobj->info->damage; i++) + { + ball = P_SpawnMobj(x, y, z, mobj->info->painchance); + ball->destscale = mobj->scale; + P_SetScale(ball, mobj->scale); + P_SetTarget(&ball->target, mobj); + ball->movedir = FixedAngle(FixedMul(FixedDiv(i<info->damage<threshold = ball->radius + mobj->radius + FixedMul(ball->info->painchance, ball->scale); - var1 = ball->state->var1, var2 = ball->state->var2; - ball->state->action.acp1(ball); + var1 = ball->state->var1, var2 = ball->state->var2; + ball->state->action.acp1(ball); + } } break; - } case MT_POINTY: - { - INT32 q; - mobj_t *ball, *lastball = mobj; - - for (q = 0; q < mobj->info->painchance; q++) { - ball = P_SpawnMobj(x, y, z, mobj->info->mass); - ball->destscale = mobj->scale; - P_SetScale(ball, mobj->scale); - P_SetTarget(&lastball->tracer, ball); - P_SetTarget(&ball->target, mobj); - lastball = ball; + INT32 q; + mobj_t *ball, *lastball = mobj; + + for (q = 0; q < mobj->info->painchance; q++) + { + ball = P_SpawnMobj(x, y, z, mobj->info->mass); + ball->destscale = mobj->scale; + P_SetScale(ball, mobj->scale); + P_SetTarget(&lastball->tracer, ball); + P_SetTarget(&ball->target, mobj); + lastball = ball; + } + } + break; + case MT_CRUSHSTACEAN: + { + mobj_t *bigmeatyclaw; + angle_t ang = mobj->angle + ((mobj->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270); + bigmeatyclaw = P_SpawnMobjFromMobj(mobj, + P_ReturnThrustX(mobj, ang, 40<angle = ang; + P_SetTarget(&mobj->tracer, bigmeatyclaw); + P_SetTarget(&bigmeatyclaw->tracer, mobj); + mobj->reactiontime >>= 1; } break; - } case MT_BIGMINE: mobj->extravalue1 = FixedHypot(mobj->x, mobj->y)>>FRACBITS; break; diff --git a/src/sounds.c b/src/sounds.c index e9c9e2995..d4ec46d90 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -340,7 +340,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Unknown possibilities"}, {"s3k69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Switch click"}, {"s3k6a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Special stage clear"}, - {"s3k6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s3k6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Punch"}, {"s3k6c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"}, {"s3k6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s3k6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical damage"}, @@ -465,7 +465,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3kd1s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"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, "Turning"}, // ditto + {"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 {"s3kd4s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Engine"},