From 8abb6129c1f38d01f6171cab79c950cec5896c46 Mon Sep 17 00:00:00 2001 From: lachwright Date: Sun, 29 Sep 2019 20:18:40 +0800 Subject: [PATCH] Hardcode pumice ball Current known issues: players detached from the ball via any means other than jumping or pain do not have their ball reset properly --- src/d_player.h | 3 +- src/dehacked.c | 10 ++++ src/hardware/hw_light.c | 1 + src/info.c | 59 +++++++++++++++++++++ src/info.h | 10 ++++ src/p_enemy.c | 111 +++++++++++++++++++++++++++++++++++++++- src/p_map.c | 53 +++++++++++++++++++ src/p_user.c | 79 ++++++++++++++++++++++++---- 8 files changed, 313 insertions(+), 13 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index c133af703..e26c9602f 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -234,7 +234,8 @@ typedef enum CR_ZOOMTUBE, CR_ROPEHANG, CR_MACESPIN, - CR_MINECART + CR_MINECART, + CR_ROLLOUT } carrytype_t; // pw_carry // Player powers. (don't edit this comment) diff --git a/src/dehacked.c b/src/dehacked.c index 1664c6cb2..ff33c4ce1 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2435,6 +2435,8 @@ static actionpointer_t actionpointers[] = {{A_LavafallLava}, "A_LAVAFALLLAVA"}, {{A_FallingLavaCheck}, "A_FALLINGLAVACHECK"}, {{A_FireShrink}, "A_FIRESHRINK"}, + {{A_RolloutSpawn}, "A_ROLLOUTSPAWN"}, + {{A_RolloutRock}, "A_ROLLOUTROCK"}, {{NULL}, "NONE"}, // This NULL entry must be the last in the list @@ -5842,6 +5844,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_LAVAFALL_LAVA3", "S_LAVAFALLROCK", + // Rollout Rock + "S_ROLLOUTSPAWN", + "S_ROLLOUTROCK", + // RVZ scenery "S_BIGFERNLEAF", "S_BIGFERN1", @@ -7572,6 +7578,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_LAVAFALL_LAVA", "MT_LAVAFALLROCK", + "MT_ROLLOUTSPAWN", + "MT_ROLLOUTROCK", + "MT_BIGFERNLEAF", "MT_BIGFERN", "MT_JUNGLEPALM", @@ -8579,6 +8588,7 @@ struct { {"CR_ROPEHANG",CR_ROPEHANG}, {"CR_MACESPIN",CR_MACESPIN}, {"CR_MINECART",CR_MINECART}, + {"CR_ROLLOUT", CR_ROLLOUT}, // Ring weapons (ringweapons_t) // Useful for A_GiveWeapon diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 57dfc57ab..81f00cdf2 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -257,6 +257,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_WSPB &lspr[NOLIGHT], // SPR_STPT &lspr[NOLIGHT], // SPR_BMNE + &lspr[NOLIGHT], // SPR_PUMI // Monitor Boxes &lspr[NOLIGHT], // SPR_MSTV diff --git a/src/info.c b/src/info.c index b82c64e52..31488cad5 100644 --- a/src/info.c +++ b/src/info.c @@ -146,6 +146,7 @@ char sprnames[NUMSPRITES + 1][5] = "WSPB", // Wall spike base "STPT", // Starpost "BMNE", // Big floating mine + "PUMI", // Rollout Rock // Monitor Boxes "MSTV", // MiSc TV sprites @@ -2472,6 +2473,10 @@ state_t states[NUMSTATES] = {SPR_LFAL, 2|FF_FULLBRIGHT|FF_ANIMATE, 9, {NULL}, 2, 3, S_NULL}, // S_LAVAFALL_LAVA3 {SPR_LFAL, 11|FF_ANIMATE|FF_RANDOMANIM, 12, {NULL}, 3, 3, S_LAVAFALLROCK}, // S_LAVAFALLROCK + // Rollout Rock + {SPR_NULL, 0, 1, {A_RolloutSpawn}, 256*FRACUNIT, MT_ROLLOUTROCK, S_ROLLOUTSPAWN}, // S_ROLLOUTSPAWN + {SPR_PUMI, 0, 1, {A_RolloutRock}, 63*FRACUNIT/64, 6*FRACUNIT/10, S_ROLLOUTROCK}, // S_ROLLOUTROCK + // RVZ scenery {SPR_JPLA, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BIGFERNLEAF {SPR_JPLA, 1, 1, {NULL}, 0, 0, S_BIGFERN2}, // S_BIGFERN1 @@ -12726,6 +12731,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_ROLLOUTSPAWN + 1305, // doomednum + S_ROLLOUTSPAWN, // 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 + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SPAWNCEILING, // flags + S_NULL // raisestate + }, + + { // MT_ROLLOUTROCK + -1, // doomednum + S_ROLLOUTROCK, // 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*FRACUNIT, // speed + 30*FRACUNIT, // radius + 60*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_PUSHABLE|MF_SOLID|MF_SLIDEME, // flags + S_NULL // raisestate + }, + { // MT_BIGFERNLEAF -1, // doomednum S_BIGFERNLEAF, // spawnstate diff --git a/src/info.h b/src/info.h index 8d2023c3d..be49d64f7 100644 --- a/src/info.h +++ b/src/info.h @@ -270,6 +270,8 @@ void A_LavafallRocks(); void A_LavafallLava(); void A_FallingLavaCheck(); void A_FireShrink(); +void A_RolloutSpawn(); +void A_RolloutRock(); // ratio of states to sprites to mobj types is roughly 6 : 1 : 1 #define NUMMOBJFREESLOTS 512 @@ -396,6 +398,7 @@ typedef enum sprite SPR_WSPB, // Wall spike base SPR_STPT, // Starpost SPR_BMNE, // Big floating mine + SPR_PUMI, // Rollout Rock // Monitor Boxes SPR_MSTV, // MiSc TV sprites @@ -2595,6 +2598,10 @@ typedef enum state S_LAVAFALL_LAVA3, S_LAVAFALLROCK, + // Rollout Rock + S_ROLLOUTSPAWN, + S_ROLLOUTROCK, + // RVZ scenery S_BIGFERNLEAF, S_BIGFERN1, @@ -4347,6 +4354,9 @@ typedef enum mobj_type MT_LAVAFALL_LAVA, MT_LAVAFALLROCK, + MT_ROLLOUTSPAWN, + MT_ROLLOUTROCK, + MT_BIGFERNLEAF, MT_BIGFERN, MT_JUNGLEPALM, diff --git a/src/p_enemy.c b/src/p_enemy.c index e37eea19d..19bb30b29 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -300,6 +300,8 @@ void A_LavafallRocks(mobj_t *actor); void A_LavafallLava(mobj_t *actor); void A_FallingLavaCheck(mobj_t *actor); void A_FireShrink(mobj_t *actor); +void A_RolloutSpawn(mobj_t *actor); +void A_RolloutRock(mobj_t *actor); //for p_enemy.c @@ -13838,4 +13840,111 @@ void A_FireShrink(mobj_t *actor) actor->destscale = locvar1; actor->scalespeed = FRACUNIT/locvar2; -} \ No newline at end of file +} + +// Function: A_RolloutSpawn +// +// Description: Spawns a new Rollout Rock when the currently spawned rock is destroyed or moves far enough away. +// +// var1 = Distance currently spawned rock should travel before spawning a new one +// var2 = Object type to spawn +// +void A_RolloutSpawn(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RolloutSpawn", actor)) + return; +#endif + + if (!(actor->target) + || P_MobjWasRemoved(actor->target) + || P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) > locvar1) + { + actor->target = P_SpawnMobj(actor->x, actor->y, actor->z, locvar2); + } +} + +// Function: A_RolloutRock +// +// Description: Thinker for Rollout Rock. +// +// var1 = Drag +// var2 = Vertical bobbing speed factor +// +void A_RolloutRock(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RolloutRock", actor)) + return; +#endif + + UINT8 maxframes = actor->info->reactiontime; + fixed_t pi = (22*FRACUNIT/7); + fixed_t circumference = FixedMul(2 * pi, actor->radius); + fixed_t oldspeed = P_AproxDistance(actor->momx, actor->momy), newspeed, topspeed = actor->info->speed; + mobj_t *target = actor->target; + player_t *player; + boolean inwater = actor->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER); + + actor->friction = FRACUNIT; + + if (inwater) + { + fixed_t height; + if (actor->eflags & MFE_VERTICALFLIP) + { + height = actor->waterbottom + (actor->height>>2); + if (actor->z + actor->height > height) + { + actor->z = height; + actor->momz = 0; + } + } + else + { + height = actor->watertop - (actor->height>>2); + if (actor->z < height) + { + actor->z = height; + actor->momz = 0; + } + } + actor->momz += P_MobjFlip(actor) * FixedMul(locvar2, actor->scale); + } + + if (oldspeed > topspeed) + { + actor->momx = FixedMul(FixedDiv(actor->momx, oldspeed), topspeed); + actor->momy = FixedMul(FixedDiv(actor->momy, oldspeed), topspeed); + } + + actor->momx = FixedMul(actor->momx, locvar1); + actor->momy = FixedMul(actor->momy, locvar1); + + newspeed = P_AproxDistance(actor->momx, actor->momy); + + if (newspeed < actor->scale >> 1) + { + actor->momx = 0; + actor->momy = 0; + } + else if (newspeed > actor->scale) + { + actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); + actor->movefactor += newspeed; + if (actor->movefactor > circumference / maxframes) + { + actor->reactiontime++; + actor->reactiontime %= maxframes; + actor->movefactor = 0; + } + } + + actor->frame = actor->reactiontime % maxframes; +} diff --git a/src/p_map.c b/src/p_map.c index cc9209ea8..2dedff36a 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -920,6 +920,59 @@ static boolean PIT_CheckThing(mobj_t *thing) P_DamageMobj(thing, tmthing, tmthing, 1, 0); } + if (thing->type == MT_ROLLOUTROCK) + { + if (tmthing->player) + { + if (tmthing->player->powers[pw_carry] == CR_ROLLOUT) + { + return true; + } + if ((thing->flags & MF_PUSHABLE) // carrying a player + && ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP)) + && (P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < (thing->radius)) + && (P_MobjFlip(tmthing)*tmthing->momz <= 0) + && ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2)) + || (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2)))) + { + thing->flags &= ~MF_PUSHABLE; + P_SetTarget(&thing->target, tmthing); + P_ResetPlayer(tmthing->player); + P_SetPlayerMobjState(tmthing, S_PLAY_WALK); + tmthing->player->powers[pw_carry] = CR_ROLLOUT; + P_SetTarget(&tmthing->tracer, thing); + return false; + } + } + else if (tmthing->type == thing->type) + { + if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height) + return true; + + fixed_t tempmomx = thing->momx, tempmomy = thing->momy; + thing->momx = tmthing->momx; + thing->momy = tmthing->momy; + tmthing->momx = tempmomx; + tmthing->momy = tempmomy; + } + } + else if (tmthing->type == MT_ROLLOUTROCK) + { + if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !thing->health) + return true; + + if (thing->flags & MF_SPRING) + { + P_DoSpring(thing, tmthing); + return true; + } + else if (thing->flags & MF_MONITOR && thing->flags & MF_SHOOTABLE && !(tmthing->flags & MF_PUSHABLE)) // carrying a player + { + P_KillMobj(thing, tmthing, tmthing->target, 0); + return true; + } + } + if (thing->type == MT_VULTURE && tmthing->type == MT_VULTURE) { fixed_t dx = thing->x - tmthing->x; diff --git a/src/p_user.c b/src/p_user.c index 1ca955e49..c7d5095d8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -948,6 +948,17 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) if (player->powers[pw_carry] == CR_ROPEHANG) P_SetTarget(&player->mo->tracer, NULL); + if (player->powers[pw_carry] == CR_ROLLOUT) + { + if (player->mo->tracer && !P_MobjWasRemoved(player->mo->tracer)) + { + player->mo->tracer->flags |= MF_PUSHABLE; + P_SetTarget(&player->mo->tracer->target, NULL); + } + P_SetTarget(&player->mo->tracer, NULL); + player->powers[pw_carry] = CR_NONE; + } + { angle_t ang; fixed_t fallbackspeed; @@ -4292,6 +4303,8 @@ void P_DoJump(player_t *player, boolean soundandstate) { player->mo->momz = 9*FRACUNIT; player->powers[pw_carry] = CR_NONE; + player->mo->tracer->flags |= MF_PUSHABLE; + P_SetTarget(&player->mo->tracer->target, NULL); P_SetTarget(&player->mo->tracer, NULL); } else if (player->powers[pw_carry] == CR_ROPEHANG) @@ -4300,6 +4313,14 @@ void P_DoJump(player_t *player, boolean soundandstate) player->powers[pw_carry] = CR_NONE; P_SetTarget(&player->mo->tracer, NULL); } + else if (player->powers[pw_carry] == CR_ROLLOUT) + { + player->mo->momz = 9*FRACUNIT + player->mo->tracer->momz; + player->powers[pw_carry] = CR_NONE; + player->mo->tracer->flags |= MF_PUSHABLE; + P_SetTarget(&player->mo->tracer->target, NULL); + P_SetTarget(&player->mo->tracer, NULL); + } else if (player->mo->eflags & MFE_GOOWATER) { player->mo->momz = 7*FRACUNIT; @@ -11121,6 +11142,8 @@ void P_PlayerThink(player_t *player) // deez New User eXperiences. { + angle_t diff = 0; + UINT8 factor; // Directionchar! // Camera angle stuff. if (player->exiting // no control, no modification @@ -11149,6 +11172,13 @@ void P_PlayerThink(player_t *player) case CR_GENERIC: player->drawangle = player->mo->tracer->angle; break; + case CR_ROLLOUT: + if (cmd->forwardmove || cmd->sidemove) // only when you're pressing movement keys + { // inverse direction! + diff = ((player->mo->angle + R_PointToAngle2(0, 0, -cmd->forwardmove<sidemove<drawangle); + factor = 4; + } + break; /* -- in case we wanted to have the camera freely movable during zoom tubes case CR_ZOOMTUBE:*/ case CR_ROPEHANG: @@ -11169,9 +11199,6 @@ void P_PlayerThink(player_t *player) ; else { - angle_t diff; - UINT8 factor; - if (player->pflags & PF_SLIDING) { #if 0 // fun hydrocity style horizontal spin @@ -11207,15 +11234,15 @@ void P_PlayerThink(player_t *player) diff = (player->mo->angle - player->drawangle); factor = 8; } + } - if (diff) - { - if (diff > ANGLE_180) - diff = InvAngle(InvAngle(diff)/factor); - else - diff /= factor; - player->drawangle += diff; - } + if (diff) + { + if (diff > ANGLE_180) + diff = InvAngle(InvAngle(diff)/factor); + else + diff /= factor; + player->drawangle += diff; } // Autobrake! check ST_drawInput if you modify this @@ -11831,6 +11858,36 @@ void P_PlayerAfterThink(player_t *player) } break; } + case CR_ROLLOUT: + { + mobj_t *mo = player->mo, *rock = player->mo->tracer; + UINT8 walktics = mo->state->tics - P_GetPlayerControlDirection(player); + + if (!rock || P_MobjWasRemoved(rock)) + { + P_SetTarget(&player->mo->tracer, NULL); + player->powers[pw_carry] = CR_NONE; + break; + } + + if (player->cmd.forwardmove || player->cmd.sidemove) + { + rock->movedir = (player->cmd.angleturn << FRACBITS) + R_PointToAngle2(0, 0, player->cmd.forwardmove << FRACBITS, -player->cmd.sidemove << FRACBITS); + P_Thrust(rock, rock->movedir, rock->scale >> 1); + } + + mo->momx = rock->momx; + mo->momy = rock->momy; + mo->momz = 0; + + if (player->panim == PA_WALK && mo->tics > walktics) + { + mo->tics = walktics; + } + + P_TeleportMove(player->mo, rock->x, rock->y, rock->z + rock->height); + break; + } default: break; }