diff --git a/src/d_player.h b/src/d_player.h index eff8e54f5..8648b3608 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -235,6 +235,7 @@ typedef enum CR_ROPEHANG, CR_MACESPIN, CR_MINECART, + CR_ROLLOUT, CR_PTERABYTE } carrytype_t; // pw_carry diff --git a/src/dehacked.c b/src/dehacked.c index d19f43f9c..bb1785695 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2437,6 +2437,8 @@ static actionpointer_t actionpointers[] = {{A_FireShrink}, "A_FIRESHRINK"}, {{A_SpawnPterabytes}, "A_SPAWNPTERABYTES"}, {{A_PterabyteHover}, "A_PTERABYTEHOVER"}, + {{A_RolloutSpawn}, "A_ROLLOUTSPAWN"}, + {{A_RolloutRock}, "A_ROLLOUTROCK"}, {{NULL}, "NONE"}, // This NULL entry must be the last in the list @@ -5854,6 +5856,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", @@ -7587,6 +7593,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", @@ -8594,8 +8603,8 @@ struct { {"CR_ROPEHANG",CR_ROPEHANG}, {"CR_MACESPIN",CR_MACESPIN}, {"CR_MINECART",CR_MINECART}, + {"CR_ROLLOUT", CR_ROLLOUT}, {"CR_PTERABYTE",CR_PTERABYTE}, - // Ring weapons (ringweapons_t) // Useful for A_GiveWeapon {"RW_AUTO",RW_AUTO}, diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index f3b2b4f87..e5e9e77a7 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -258,6 +258,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 6800ba4be..076f12d40 100644 --- a/src/info.c +++ b/src/info.c @@ -147,6 +147,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 @@ -2483,6 +2484,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 @@ -12818,6 +12823,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 98a5db4ca..8663b0576 100644 --- a/src/info.h +++ b/src/info.h @@ -272,6 +272,8 @@ void A_FallingLavaCheck(); void A_FireShrink(); void A_SpawnPterabytes(); void A_PterabyteHover(); +void A_RolloutSpawn(); +void A_RolloutRock(); // ratio of states to sprites to mobj types is roughly 6 : 1 : 1 #define NUMMOBJFREESLOTS 512 @@ -399,6 +401,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 @@ -2608,6 +2611,10 @@ typedef enum state S_LAVAFALL_LAVA3, S_LAVAFALLROCK, + // Rollout Rock + S_ROLLOUTSPAWN, + S_ROLLOUTROCK, + // RVZ scenery S_BIGFERNLEAF, S_BIGFERN1, @@ -4363,6 +4370,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 7ad65c1d0..359bc7d3b 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -302,6 +302,8 @@ void A_FallingLavaCheck(mobj_t *actor); void A_FireShrink(mobj_t *actor); void A_SpawnPterabytes(mobj_t *actor); void A_PterabyteHover(mobj_t *actor); +void A_RolloutSpawn(mobj_t *actor); +void A_RolloutRock(mobj_t *actor); //for p_enemy.c @@ -13909,4 +13911,108 @@ void A_PterabyteHover(mobj_t *actor) ang = actor->extravalue1*ANG1; fa = (ang >> ANGLETOFINESHIFT) & FINEMASK; actor->z += FINESINE(fa); -} \ 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; + 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 1455f3a4f..14b69b575 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -954,6 +954,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_PTERABYTE && tmthing->player) P_DoPterabyteCarry(tmthing->player, thing); diff --git a/src/p_user.c b/src/p_user.c index 4895095f2..ec431a86a 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; @@ -4295,6 +4306,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) @@ -4303,6 +4316,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; @@ -11124,6 +11145,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 @@ -11152,6 +11175,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: @@ -11172,9 +11202,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 @@ -11210,15 +11237,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 @@ -11864,6 +11891,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; + } case CR_PTERABYTE: // being carried by a Pterabyte { mobj_t *ptera = player->mo->tracer;