From a21e509a944f8a029d790569b38133622ccd4dc9 Mon Sep 17 00:00:00 2001 From: Lach Date: Wed, 19 Jul 2023 21:47:41 +1000 Subject: [PATCH 1/8] Hardcode MT_DASHRING & MT_RAINBOWDASHRING --- src/d_player.h | 6 +- src/deh_tables.c | 18 +++ src/info.c | 71 ++++++++++ src/info.h | 21 +++ src/k_kart.c | 36 ++--- src/k_objects.h | 9 ++ src/objects/CMakeLists.txt | 1 + src/objects/dash-rings.c | 266 +++++++++++++++++++++++++++++++++++++ src/p_inter.c | 5 + src/p_mobj.c | 20 +++ src/sounds.c | 7 +- src/sounds.h | 3 + 12 files changed, 443 insertions(+), 20 deletions(-) create mode 100644 src/objects/dash-rings.c diff --git a/src/d_player.h b/src/d_player.h index f1d8e02bd..e9b237166 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -129,6 +129,7 @@ typedef enum // Specific level gimmicks. CR_SLIDING, CR_ZOOMTUBE, + CR_DASHRING, } carrytype_t; // carry /* @@ -691,6 +692,9 @@ struct player_t UINT8 trickboostdecay; // used to know how long you've waited UINT8 trickboost; // Trick boost. This one is weird and has variable speed. Dear god. + UINT8 dashRingPullTics; // Timer during which the player is pulled towards a dash ring + UINT8 dashRingPushTics; // Timer during which the player displays effects and has no gravity after being thrust by a dash ring + tic_t ebrakefor; // Ebrake timer, used for visuals. UINT16 faultflash; // Used for misc FAULT visuals @@ -804,7 +808,7 @@ struct player_t UINT8 ringboxdelay; // Delay until Ring Box auto-activates UINT8 ringboxaward; // Where did we stop? - + fixed_t outrun; // Milky Way road effect uint8_t public_key[PUBKEYLENGTH]; diff --git a/src/deh_tables.c b/src/deh_tables.c index edbb93eba..10453cf52 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4236,6 +4236,20 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_FZSLOWSMOKE4", "S_FZSLOWSMOKE5", + // Dash Rings + "S_DASHRING_HORIZONTAL", + "S_DASHRING_30DEGREES", + "S_DASHRING_60DEGREES", + "S_DASHRING_VERTICAL", + "S_DASHRING_HORIZONTAL_FLASH1", + "S_DASHRING_HORIZONTAL_FLASH2", + "S_DASHRING_30DEGREES_FLASH1", + "S_DASHRING_30DEGREES_FLASH2", + "S_DASHRING_60DEGREES_FLASH1", + "S_DASHRING_60DEGREES_FLASH2", + "S_DASHRING_VERTICAL_FLASH1", + "S_DASHRING_VERTICAL_FLASH2", + // Various plants "S_SONICBUSH", @@ -5603,6 +5617,10 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_FZEROBOOM", + // Dash Rings + "MT_DASHRING", + "MT_RAINBOWDASHRING", + // Various plants "MT_SONICBUSH", diff --git a/src/info.c b/src/info.c index 749b2a6af..fc26bf3d7 100644 --- a/src/info.c +++ b/src/info.c @@ -717,6 +717,9 @@ char sprnames[NUMSPRITES + 1][5] = "FZSM", // F-Zero NO CONTEST explosion "FZBM", + // Dash Rings + "RAIR", + // Various plants "SBUS", @@ -4918,6 +4921,20 @@ state_t states[NUMSTATES] = {SPR_SMOK, 3, 30, {NULL}, 0, 0, S_FZSLOWSMOKE5}, // S_FZSLOWSMOKE4 {SPR_SMOK, 4, 30, {NULL}, 0, 0, S_NULL}, // S_FZSLOWSMOKE5 + // Dash Rings + {SPR_RAIR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_DASHRING_HORIZONTAL + {SPR_RAIR, 1, -1, {NULL}, 0, 0, S_NULL}, // S_DASHRING_30DEGREES + {SPR_RAIR, 2, -1, {NULL}, 0, 0, S_NULL}, // S_DASHRING_60DEGREES + {SPR_RAIR, 3, -1, {NULL}, 0, 0, S_NULL}, // S_DASHRING_VERTICAL + {SPR_NULL, 0, TICRATE/3 - 2, {NULL}, 0, 0, S_DASHRING_HORIZONTAL_FLASH2}, // S_DASHRING_HORIZONTAL_FLASH1 + {SPR_RAIR, FF_ADD|0, 2, {NULL}, 0, 0, S_DASHRING_HORIZONTAL_FLASH1}, // S_DASHRING_HORIZONTAL_FLASH2 + {SPR_NULL, 0, TICRATE/3 - 2, {NULL}, 0, 0, S_DASHRING_30DEGREES_FLASH2}, // S_DASHRING_30DEGREES_FLASH1 + {SPR_RAIR, FF_ADD|1, 2, {NULL}, 0, 0, S_DASHRING_30DEGREES_FLASH1}, // S_DASHRING_30DEGREES_FLASH2 + {SPR_NULL, 0, TICRATE/3 - 2, {NULL}, 0, 0, S_DASHRING_60DEGREES_FLASH2}, // S_DASHRING_60DEGREES_FLASH1 + {SPR_RAIR, FF_ADD|2, 2, {NULL}, 0, 0, S_DASHRING_60DEGREES_FLASH1}, // S_DASHRING_60DEGREES_FLASH2 + {SPR_NULL, 0, TICRATE/3 - 2, {NULL}, 0, 0, S_DASHRING_VERTICAL_FLASH2}, // S_DASHRING_VERTICAL_FLASH1 + {SPR_RAIR, FF_ADD|3, 2, {NULL}, 0, 0, S_DASHRING_VERTICAL_FLASH1}, // S_DASHRING_VERTICAL_FLASH2 + // Various plants {SPR_SBUS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SONICBUSH @@ -26726,6 +26743,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_DASHRING + 3441, // doomednum + S_DASHRING_HORIZONTAL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_dashr, // 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 + 0, // speed + 112*FRACUNIT, // radius + 192*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_SPECIAL, // flags + S_NULL // raisestate + }, + + { // MT_RAINBOWDASHRING + 3442, // doomednum + S_DASHRING_HORIZONTAL, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_rainbr, // 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 + 0, // speed + 112*FRACUNIT, // radius + 192*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_SPECIAL, // flags + S_NULL // raisestate + }, + { // MT_SONICBUSH, 715, // doomednum S_SONICBUSH, // spawnstate diff --git a/src/info.h b/src/info.h index f8258fadd..b77591fb2 100644 --- a/src/info.h +++ b/src/info.h @@ -1268,6 +1268,9 @@ typedef enum sprite SPR_FZSM, // F-Zero NO CONTEST explosion SPR_FZBM, + // Dash Rings + SPR_RAIR, + // Various plants SPR_SBUS, @@ -5366,6 +5369,20 @@ typedef enum state S_FZSLOWSMOKE4, S_FZSLOWSMOKE5, + // Dash Rings + S_DASHRING_HORIZONTAL, + S_DASHRING_30DEGREES, + S_DASHRING_60DEGREES, + S_DASHRING_VERTICAL, + S_DASHRING_HORIZONTAL_FLASH1, + S_DASHRING_HORIZONTAL_FLASH2, + S_DASHRING_30DEGREES_FLASH1, + S_DASHRING_30DEGREES_FLASH2, + S_DASHRING_60DEGREES_FLASH1, + S_DASHRING_60DEGREES_FLASH2, + S_DASHRING_VERTICAL_FLASH1, + S_DASHRING_VERTICAL_FLASH2, + // Various plants S_SONICBUSH, @@ -6768,6 +6785,10 @@ typedef enum mobj_type MT_FZEROBOOM, + // Dash Rings + MT_DASHRING, + MT_RAINBOWDASHRING, + // Various plants MT_SONICBUSH, diff --git a/src/k_kart.c b/src/k_kart.c index 31ee0be8e..cd33715ac 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2027,7 +2027,7 @@ void K_SpawnMagicianParticles(mobj_t *mo, int spread) { fixed_t hmomentum = P_RandomRange(PR_DECORATION, spread * -1, spread) * mo->scale; fixed_t vmomentum = P_RandomRange(PR_DECORATION, spread * -1, spread) * mo->scale; - UINT16 color = P_RandomKey(PR_DECORATION, numskincolors); + UINT16 color = P_RandomKey(PR_DECORATION, numskincolors); fixed_t ang = FixedAngle(P_RandomRange(PR_DECORATION, 0, 359)*FRACUNIT); SINT8 flip = 1; @@ -2679,7 +2679,7 @@ void K_TryHurtSoundExchange(mobj_t *victim, mobj_t *attacker) return; } - // In a perfect world we could move this here, but there's + // In a perfect world we could move this here, but there's // a few niche situations where we want a pain sound from // the victim, but no confirm sound from the attacker. // (ex: DMG_STING) @@ -4148,7 +4148,7 @@ static boolean K_IsLosingSliptideZip(player_t *player) return true; if (!K_Sliptiding(player) && player->sliptideZip < MIN_WAVEDASH_CHARGE) return true; - if (!K_Sliptiding(player) && player->drift == 0 + if (!K_Sliptiding(player) && player->drift == 0 && P_IsObjectOnGround(player->mo) && player->sneakertimer == 0 && player->driftboost == 0) return true; @@ -4211,7 +4211,7 @@ void K_UpdateSliptideZipIndicator(player_t *player) if (leveltime % 2 == 0) mobj->renderflags |= RF_TRANS50; } - else + else { // Storing boost mobj->rollangle += 3*ANG15/4; @@ -4357,7 +4357,7 @@ INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A { if (inflictor->type == MT_SPBEXPLOSION && inflictor->movefactor) { - if (modeattacking & ATTACKING_SPB) + if (modeattacking & ATTACKING_SPB) { P_DamageMobj(player->mo, inflictor, source, 1, DMG_INSTAKILL); player->SPBdistance = 0; @@ -4676,7 +4676,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I speed, FixedMul( FixedDiv(source->player->speed, topspeed), - deltaFactor + deltaFactor ) )); } @@ -7747,6 +7747,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_UpdateDraft(player); K_UpdateEngineSounds(player); // Thanks, VAda! + Obj_DashRingPlayerThink(player); + // update boost angle if not spun out if (!player->spinouttimer && !player->wipeoutslow) player->boostangle = player->mo->angle; @@ -8065,7 +8067,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->guardCooldown) player->guardCooldown--; - + if (player->whip && P_MobjWasRemoved(player->whip)) P_SetTarget(&player->whip, NULL); @@ -8952,7 +8954,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player) bestPoint = pDist; - bestDist = + bestDist = P_AproxDistance( (result.x >> FRACBITS) - (line[0].x >> FRACBITS), (result.y >> FRACBITS) - (line[0].y >> FRACBITS)); @@ -9113,7 +9115,7 @@ INT16 K_UpdateSteeringValue(INT16 inputSteering, INT16 destSteering) INT16 diff = destSteering - inputSteering; INT16 outputSteering = inputSteering; - + // We switched steering directions, lighten up on easing for a more responsive countersteer. // (Don't do this for steering 0, let digital inputs tap-adjust!) if ((inputSteering > 0 && destSteering < 0) || (inputSteering < 0 && destSteering > 0)) @@ -9257,13 +9259,13 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) fixed_t finalhandleboost = player->handleboost; // If you're sliptiding, don't interact with handling boosts. - // You need turning power proportional to your speed, no matter what! + // You need turning power proportional to your speed, no matter what! fixed_t topspeed = K_GetKartSpeed(player, false, false); if (K_Sliptiding(player)) { finalhandleboost = FixedMul(5*SLIPTIDEHANDLING/4, FixedDiv(player->speed, topspeed)); } - + if (finalhandleboost > 0 && player->respawn.state == RESPAWNST_NONE) { turnfixed = FixedMul(turnfixed, FRACUNIT + finalhandleboost); @@ -9348,7 +9350,7 @@ void K_SpawnDriftBoostExplosion(player_t *player, int stage) break; case 2: - + overlay->fuse = 32; S_StartSound(player->mo, sfx_kc5b); break; @@ -9616,7 +9618,7 @@ static void K_KartDrift(player_t *player, boolean onground) && player->speed >= K_GetKartSpeed(player, false, true)) // and we're above the threshold to spawn dust... { keepsliptide = true; // Then keep your current sliptide, but note the behavior change for sliptidezip handling. - } + } else { if (!player->drift) @@ -9625,7 +9627,7 @@ static void K_KartDrift(player_t *player, boolean onground) player->aizdriftstrat = ((player->drift > 0) ? 1 : -1); } } - + if ((player->aizdriftstrat && !player->drift) || (keepsliptide)) { @@ -9635,7 +9637,7 @@ static void K_KartDrift(player_t *player, boolean onground) { // Give charge proportional to your angle. Sharp turns are rewarding, slow analog slides are not—remember, this is giving back the speed you gave up. UINT16 addCharge = FixedInt( - FixedMul(10*FRACUNIT, + FixedMul(10*FRACUNIT, FixedDiv(abs(player->steering)*FRACUNIT, (9*KART_FULLTURN/10)*FRACUNIT) )); addCharge = min(10, max(addCharge, 1)); @@ -9647,7 +9649,7 @@ static void K_KartDrift(player_t *player, boolean onground) if (player->sliptideZip >= MIN_WAVEDASH_CHARGE && (player->sliptideZip - addCharge) < MIN_WAVEDASH_CHARGE) S_StartSound(player->mo, sfx_waved5); - } + } if (abs(player->aizdrifttilt) < ANGLE_22h) { @@ -10411,7 +10413,7 @@ static void K_KartSpindash(player_t *player) player->spindash++; if (!S_SoundPlaying(player->mo, sfx_kc38)) S_StartSound(player->mo, sfx_kc38); - } + } if (player->spindash >= SPINDASHTHRUSTTIME) { diff --git a/src/k_objects.h b/src/k_objects.h index e00b4813f..ca2bec744 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -183,6 +183,15 @@ void Obj_SymbolSpawn(mobj_t *mobj); void Obj_SymbolSetup(mobj_t *mobj, mapthing_t *mthing); void Obj_SymbolThink(mobj_t *mobj); +/* Dash Rings */ +void Obj_RegularDashRingSpawn(mobj_t *mobj); +void Obj_RainbowDashRingSpawn(mobj_t *mobj); +void Obj_DashRingSetup(mobj_t *mobj, mapthing_t *mthing); +void Obj_RainbowDashRingThink(mobj_t *mobj); +void Obj_DashRingTouch(mobj_t *mobj, player_t *player); +void Obj_DashRingPlayerThink(player_t *player); +boolean Obj_DashRingPlayerHasNoGravity(player_t *player); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index ca07bc1eb..2e0f65913 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -25,4 +25,5 @@ target_sources(SRB2SDL2 PRIVATE battle-ufo.cpp powerup-aura.cpp symbol.c + dash-rings.c ) diff --git a/src/objects/dash-rings.c b/src/objects/dash-rings.c new file mode 100644 index 000000000..80822d03f --- /dev/null +++ b/src/objects/dash-rings.c @@ -0,0 +1,266 @@ +#include "../p_local.h" +#include "../k_kart.h" +#include "../s_sound.h" + +// Dash Rings are scaled by this much relative to the map scale +#define DASHRING_SCALE (3*FRACUNIT/2) + +// Dash Ring angles are defined by their mapthing's args[0] (previously used mapthing->options flags, hence the selections) +#define DASHRING_TYPE_HORIZONTAL 0 +#define DASHRING_TYPE_30DEGREES 1 +#define DASHRING_TYPE_60DEGREES 4 +#define DASHRING_TYPE_VERTICAL 8 + +// Dash Rings must be this far apart for players to interact with them in succession +#define DASHRING_MIN_SPACING_HORIZONTAL (512*FRACUNIT) +#define DASHRING_MIN_SPACING_VERTICAL (384*FRACUNIT) + +// timer values +#define DASHRING_PULL_TICS 5 +#define DASHRING_PUSH_TICS (TICRATE/2) +#define DASHRING_ANTIGRAVITY_TICS 5 + +// base launch speed +#define DASHRING_BASE_LAUNCH_SPEED (48*FRACUNIT) + +// factor of distance traveled per tic while being pulled towards a Dash Ring +#define DASHRING_PULL_FACTOR (FRACUNIT/3) + +static const skincolornum_t ring_colors[] = { + SKINCOLOR_GREY, // 1x + SKINCOLOR_TAN, // 1.25x + SKINCOLOR_YELLOW, // 1.5x + SKINCOLOR_TANGERINE, // 1.75x + SKINCOLOR_KETCHUP, // 2x + SKINCOLOR_MOONSET, // 2.25x + SKINCOLOR_ULTRAMARINE, // 2.5x + +}; + +static const skincolornum_t rainbow_colors[] = { + SKINCOLOR_PINK, + SKINCOLOR_CREAMSICLE, + SKINCOLOR_TAN, + SKINCOLOR_TURTLE, + SKINCOLOR_TURQUOISE, + SKINCOLOR_THISTLE, +}; + +void Obj_RegularDashRingSpawn(mobj_t *mobj) +{ + P_SetScale(mobj, mobj->destscale = FixedMul(mobj->scale, DASHRING_SCALE)); + mobj->renderflags |= RF_SEMIBRIGHT; + + P_SetTarget(&mobj->tracer, P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_OVERLAY)); + P_SetTarget(&mobj->tracer->target, mobj); + P_SetMobjState(mobj->tracer, S_DASHRING_HORIZONTAL_FLASH1); + mobj->tracer->color = SKINCOLOR_WHITE; + mobj->tracer->renderflags |= RF_SEMIBRIGHT; +} + +void Obj_RainbowDashRingSpawn(mobj_t *mobj) +{ + P_SetScale(mobj, mobj->destscale = FixedMul(mobj->scale, DASHRING_SCALE)); + mobj->renderflags |= RF_FULLBRIGHT; +} + +void Obj_DashRingSetup(mobj_t *mobj, mapthing_t *mthing) +{ + static const UINT8 numColors = sizeof(rainbow_colors) / sizeof(skincolornum_t); + const UINT8 additionalThrust = mthing->args[1]; + statenum_t ringState, overlayState; + + mobj->extravalue1 = mthing->args[0]; + mobj->cusval = 4 + additionalThrust; + + switch (mobj->extravalue1) + { + case DASHRING_TYPE_30DEGREES: + ringState = S_DASHRING_30DEGREES; + overlayState = S_DASHRING_30DEGREES_FLASH1; + break; + case DASHRING_TYPE_60DEGREES: + ringState = S_DASHRING_60DEGREES; + overlayState = S_DASHRING_60DEGREES_FLASH1; + break; + case DASHRING_TYPE_VERTICAL: + ringState = S_DASHRING_VERTICAL; + overlayState = S_DASHRING_VERTICAL_FLASH1; + break; + case DASHRING_TYPE_HORIZONTAL: + default: + ringState = S_DASHRING_HORIZONTAL; + overlayState = S_DASHRING_HORIZONTAL_FLASH1; + break; + } + + P_SetMobjState(mobj, ringState); + if (!P_MobjWasRemoved(mobj->tracer)) + P_SetMobjState(mobj->tracer, overlayState); + + mobj->spriteyoffset = mobj->info->height >> 1; // I think this is to center the sprite within its hitbox regardless of height + mobj->color = ring_colors[min(additionalThrust, numColors - 1)]; +} + +void Obj_RainbowDashRingThink(mobj_t *mobj) +{ + static const UINT8 numColors = sizeof(rainbow_colors) / sizeof(skincolornum_t); + mobj->color = rainbow_colors[(leveltime / 2) % numColors]; +} + +static boolean DashRingsAreTooClose(mobj_t *ring1, mobj_t *ring2) +{ + if (ring1 == ring2) + return true; + + if ((FixedHypot(ring2->x - ring1->x, ring2->y - ring1->y) < FixedMul(DASHRING_MIN_SPACING_HORIZONTAL, mapobjectscale)) + && (abs(ring1->z - ring2->z) < FixedMul(DASHRING_MIN_SPACING_VERTICAL, mapobjectscale))) + return true; + + return false; +} + +void Obj_DashRingTouch(mobj_t *ring, player_t *player) +{ + if (player->carry != CR_NONE) + { + if (player->carry != CR_DASHRING) // being carried by something else + return; + + if (player->dashRingPullTics > 0) // being pulled into a dash ring already + return; + + if (player->dashRingPushTics > 0 && !P_MobjWasRemoved(player->mo->tracer) && DashRingsAreTooClose(player->mo->tracer, ring)) // dash ring is too close to recently used dash ring + return; + } + + P_SetTarget(&player->mo->tracer, ring); + player->carry = CR_DASHRING; + player->dashRingPullTics = DASHRING_PULL_TICS; + player->dashRingPushTics = 0; +} + +static fixed_t GetPlayerDashRingZ(player_t *player, mobj_t *ring) +{ + return (ring->z + (ring->height >> 1) - (player->mo->height >> 1)); +} + +static void DashRingLaunch(player_t *player, mobj_t *ring) +{ + mobj_t *ghost = P_SpawnGhostMobj(ring); + const fixed_t launchSpeed = FixedMul(DASHRING_BASE_LAUNCH_SPEED * ring->cusval / 4, mapobjectscale); + angle_t pitch; + + ghost->destscale = ring->scale * 8; + ghost->scalespeed = ring->scale / 12; + ghost->old_z = ghost->z += P_MobjFlip(ring) * FixedMul(ghost->spriteyoffset, ghost->scale); // apply sprite offset to physical position instead, so ghost is centered + ghost->spriteyoffset = 0; + + P_MoveOrigin(player->mo, ring->x, ring->y, GetPlayerDashRingZ(player, ring)); + player->dashRingPullTics = 0; + player->dashRingPushTics = DASHRING_PUSH_TICS; + + player->mo->rollangle = 0; + player->flashing = 0; + player->fastfall = 0; + + switch (ring->extravalue1) + { + case DASHRING_TYPE_30DEGREES: + pitch = 30 * ANG1; + break; + case DASHRING_TYPE_60DEGREES: + pitch = 60 * ANG1; + break; + case DASHRING_TYPE_VERTICAL: + pitch = 90 * ANG1; + break; + case DASHRING_TYPE_HORIZONTAL: + default: + pitch = 0; + break; + } + + P_InstaThrust(player->mo, ring->angle, P_ReturnThrustX(NULL, pitch, launchSpeed)); + player->mo->momz = P_MobjFlip(ring) * P_ReturnThrustY(NULL, pitch, launchSpeed); + + S_StartSound(player->mo, ring->info->seesound); +} + +static void RegularDashRingLaunch(player_t *player, mobj_t *ring) +{ + player->springstars = TICRATE/2; + player->springcolor = ring->color; + DashRingLaunch(player, ring); +} + +static void RainbowDashRingLaunch(player_t *player, mobj_t *ring) +{ + player->mo->eflags &= ~MFE_SPRUNG; + player->trickpanel = 1; + player->pflags |= PF_TRICKDELAY; + K_DoPogoSpring(player->mo, 0, 0); + DashRingLaunch(player, ring); +} + +void Obj_DashRingPlayerThink(player_t *player) +{ + if (player->carry != CR_DASHRING) + return; + + if (player->dashRingPullTics > 0) + { + mobj_t *ring = player->mo->tracer; + + if (P_MobjWasRemoved(player->mo->tracer)) + { + player->carry = CR_NONE; + player->dashRingPullTics = 0; + } + else + { + player->mo->momx = FixedMul(DASHRING_PULL_FACTOR, ring->x - player->mo->x); + player->mo->momy = FixedMul(DASHRING_PULL_FACTOR, ring->y - player->mo->y); + player->mo->momz = FixedMul(DASHRING_PULL_FACTOR, GetPlayerDashRingZ(player, ring) - player->mo->z); + player->mo->rollangle = (angle_t)FixedMul(DASHRING_PULL_FACTOR, (fixed_t)player->mo->rollangle); + + if (--player->dashRingPullTics == 0) + { + if (ring->type == MT_DASHRING) + { + RegularDashRingLaunch(player, ring); + } + else + { + RainbowDashRingLaunch(player, ring); + } + } + } + } + + if (player->dashRingPushTics > 0) + { + if (leveltime & 1) + { + mobj_t *ghost = P_SpawnGhostMobj(player->mo); + ghost->colorized = true; + ghost->fuse = 3; + } + + if (--player->dashRingPushTics == 0) + { + player->carry = CR_NONE; + P_SetTarget(&player->mo->tracer, NULL); + } + } +} + +boolean Obj_DashRingPlayerHasNoGravity(player_t *player) +{ + if (player->dashRingPullTics > 0) + return true; + + if (player->dashRingPushTics >= DASHRING_PUSH_TICS - DASHRING_ANTIGRAVITY_TICS) + return true; + + return false; +} diff --git a/src/p_inter.c b/src/p_inter.c index edc48a28b..66e860aec 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -664,6 +664,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) Obj_SuperFlickyPlayerCollide(special, toucher); return; + case MT_DASHRING: + case MT_RAINBOWDASHRING: + Obj_DashRingTouch(special, player); + return; + default: // SOC or script pickup P_SetTarget(&special->target, toucher); break; diff --git a/src/p_mobj.c b/src/p_mobj.c index ae19e7844..fc35e3a39 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1159,6 +1159,11 @@ fixed_t P_GetMobjGravity(mobj_t *mo) gravityadd = FixedMul(TUMBLEGRAVITY, gravityadd); } + if (mo->player->carry == CR_DASHRING && Obj_DashRingPlayerHasNoGravity(mo->player)) + { + gravityadd = 0; + } + if (K_IsHoldingDownTop(mo->player)) { gravityadd *= 3; @@ -9593,6 +9598,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) return false; } break; + case MT_RAINBOWDASHRING: + Obj_RainbowDashRingThink(mobj); + break; default: // check mobj against possible water content, before movement code P_MobjCheckWater(mobj); @@ -10980,6 +10988,12 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_SYMBOL: Obj_SymbolSpawn(mobj); break; + case MT_DASHRING: + Obj_RegularDashRingSpawn(mobj); + break; + case MT_RAINBOWDASHRING: + Obj_RainbowDashRingSpawn(mobj); + break; default: break; } @@ -13504,6 +13518,12 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj) Obj_SymbolSetup(mobj, mthing); break; } + case MT_DASHRING: + case MT_RAINBOWDASHRING: + { + Obj_DashRingSetup(mobj, mthing); + break; + } default: break; } diff --git a/src/sounds.c b/src/sounds.c index ff4eee2bd..ee245babb 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -475,7 +475,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising dust"}, // Kart AIZ dust {"s3k48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pulse"}, {"s3k49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Impact"}, // Kart bump sound - {"s3k4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Grab"}, + {"s3k4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Grab"}, {"s3k4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Splash"}, {"s3k4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy hit"}, {"s3k4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing bullet"}, @@ -505,7 +505,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k65", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got sphere"}, // Blue Spheres {"s3k66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Special stage end"}, {"s3k67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing missile"}, - {"s3k68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"}, // Kart final lap + {"s3k68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"}, // Kart final lap {"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"}, // Kart finish {"s3k6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Punch"}, @@ -1197,6 +1197,9 @@ sfxinfo_t S_sfx[NUMSFX] = {"fhurt1", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Whipped {"fhurt2", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Hunting + {"dashr", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Regular Dash Ring + {"rainbr", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Rainbow Dash Ring + // SRB2Kart - Engine sounds // Engine class A {"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, diff --git a/src/sounds.h b/src/sounds.h index afbc0831c..a91cfd06f 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1265,6 +1265,9 @@ typedef enum sfx_fhurt1, sfx_fhurt2, + sfx_dashr, + sfx_rainbr, + // Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy... // Engine class A - Low Speed, Low Weight sfx_krta00, From 476d53d3058832b2ad646feed6f0130e5ead4225 Mon Sep 17 00:00:00 2001 From: Lach Date: Thu, 20 Jul 2023 19:02:13 +1000 Subject: [PATCH 2/8] WIP: Hardcode MT_BOOSTPAD --- src/deh_tables.c | 9 +++++++++ src/info.c | 37 +++++++++++++++++++++++++++++++++++++ src/info.h | 15 +++++++++++++++ src/p_enemy.c | 26 +++++++++++++++++++++++++- src/p_mobj.c | 3 +++ 5 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 10453cf52..d43c6457e 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -301,6 +301,7 @@ actionpointer_t actionpointers[] = {{A_InvincSparkleRotate}, "A_INVINCSPARKLEROTATE"}, {{A_SpawnItemDebrisCloud}, "A_SPAWNITEMDEBRISCLOUD"}, {{A_RingShooterFace}, "A_RINGSHOOTERFACE"}, + {{A_TextureAnimate}, "A_TEXTUREANIMATE"}, {{NULL}, "NONE"}, @@ -4250,6 +4251,11 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_DASHRING_VERTICAL_FLASH1", "S_DASHRING_VERTICAL_FLASH2", + // Boost pads + "S_BOOSTPAD", + "S_BOOSTPAD_SMALL", + "S_BOOSTPAD_TINY", + // Various plants "S_SONICBUSH", @@ -5621,6 +5627,9 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_DASHRING", "MT_RAINBOWDASHRING", + // Boost pads + "MT_BOOSTPAD", + // Various plants "MT_SONICBUSH", diff --git a/src/info.c b/src/info.c index fc26bf3d7..8aabe2828 100644 --- a/src/info.c +++ b/src/info.c @@ -720,6 +720,11 @@ char sprnames[NUMSPRITES + 1][5] = // Dash Rings "RAIR", + // Boost pads + "BSTP", + "BSTS", + "BSTT", + // Various plants "SBUS", @@ -4935,6 +4940,11 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, TICRATE/3 - 2, {NULL}, 0, 0, S_DASHRING_VERTICAL_FLASH2}, // S_DASHRING_VERTICAL_FLASH1 {SPR_RAIR, FF_ADD|3, 2, {NULL}, 0, 0, S_DASHRING_VERTICAL_FLASH1}, // S_DASHRING_VERTICAL_FLASH2 + // Boost pads + {SPR_BSTP, FF_FLOORSPRITE, 1, {A_TextureAnimate}, 5, 2, S_BOOSTPAD}, // S_BOOSTPAD + {SPR_BSTS, FF_FLOORSPRITE, 1, {A_TextureAnimate}, 5, 2, S_BOOSTPAD_SMALL}, // S_BOOSTPAD_SMALL + {SPR_BSTT, FF_FLOORSPRITE, 1, {A_TextureAnimate}, 5, 2, S_BOOSTPAD_TINY}, // S_BOOSTPAD_TINY + // Various plants {SPR_SBUS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SONICBUSH @@ -26797,6 +26807,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BOOSTPAD + 510, // doomednum + S_BOOSTPAD, // 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 + 91*FRACUNIT, // radius + 16*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_ENEMY|MF_SPECIAL, // flags + S_NULL // raisestate + }, + { // MT_SONICBUSH, 715, // doomednum S_SONICBUSH, // spawnstate diff --git a/src/info.h b/src/info.h index b77591fb2..ea8b21b2b 100644 --- a/src/info.h +++ b/src/info.h @@ -294,6 +294,7 @@ enum actionnum A_INVINCSPARKLEROTATE, A_SPAWNITEMDEBRISCLOUD, A_RINGSHOOTERFACE, + A_TEXTUREANIMATE, NUMACTIONS }; @@ -568,6 +569,7 @@ void A_FlameShieldPaper(); void A_InvincSparkleRotate(); void A_SpawnItemDebrisCloud(); void A_RingShooterFace(); +void A_TextureAnimate(); extern boolean actionsoverridden[NUMACTIONS]; @@ -1271,6 +1273,11 @@ typedef enum sprite // Dash Rings SPR_RAIR, + // Boost pads + SPR_BSTP, + SPR_BSTS, + SPR_BSTT, + // Various plants SPR_SBUS, @@ -5383,6 +5390,11 @@ typedef enum state S_DASHRING_VERTICAL_FLASH1, S_DASHRING_VERTICAL_FLASH2, + // Boost pads + S_BOOSTPAD, + S_BOOSTPAD_SMALL, + S_BOOSTPAD_TINY, + // Various plants S_SONICBUSH, @@ -6789,6 +6801,9 @@ typedef enum mobj_type MT_DASHRING, MT_RAINBOWDASHRING, + // Boost pads + MT_BOOSTPAD, + // Various plants MT_SONICBUSH, diff --git a/src/p_enemy.c b/src/p_enemy.c index 478a7441b..bf4165281 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -330,6 +330,7 @@ void A_FlameShieldPaper(mobj_t *actor); void A_InvincSparkleRotate(mobj_t *actor); void A_SpawnItemDebrisCloud(mobj_t *actor); void A_RingShooterFace(mobj_t *actor); +void A_TextureAnimate(mobj_t *actor); //for p_enemy.c @@ -13721,7 +13722,8 @@ A_SpawnItemDebrisCloud (mobj_t *actor) } } -// sets the actor's +// Assumes the actor is the screen of a Ring Shooter +// Changes the screen to display the WANTED icon of the Ring Shooter's owner, stretching it to match the screen's dimensions // vars do nothing void A_RingShooterFace(mobj_t *actor) { @@ -13732,3 +13734,25 @@ void A_RingShooterFace(mobj_t *actor) Obj_UpdateRingShooterFace(actor); } + +// Syncs the actor's frame with the animated texture ticker in P_UpdateSpecials +// Call continuously to simulate an animated texture +// var1 and var2 act like FF_ANIMATE, i.e.: +// var1 = number of additional frames to cycle through +// var2 = number of tics to display each frame +void A_TextureAnimate(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + state_t *state = actor->state; + + if (LUA_CallAction(A_TEXTUREANIMATE, actor)) + { + return; + } + + if (actor->frame & FF_ANIMATE) // this doesn't work if you're animating on your own as well + return; + + actor->frame = (actor->frame & ~FF_FRAMEMASK) | ((state->frame & FF_FRAMEMASK) + ((leveltime / state->var2) % (state->var1 + 1))) +} diff --git a/src/p_mobj.c b/src/p_mobj.c index fc35e3a39..67c60aa93 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10438,6 +10438,9 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) case MT_DRIFTCLIP: thing->shadowscale = FRACUNIT/3; break; + case MT_BOOSTPAD: + thing->shadowscale = 0; + break; default: if (thing->flags & (MF_ENEMY|MF_BOSS)) thing->shadowscale = FRACUNIT; From dc4a25d823b1b4fd96b51ae8254e03cc7115f022 Mon Sep 17 00:00:00 2001 From: Lach Date: Thu, 20 Jul 2023 19:11:02 +1000 Subject: [PATCH 3/8] Add Dash Ring variables to net archive --- src/p_saveg.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 655e915ff..c3db1351f 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -185,7 +185,7 @@ static boolean P_UnArchivePlayer(savebuffer_t *save) savedata.bots[pid].score = READUINT32(save->p); } - return (pid == 0xFE); + return (pid == 0xFE); } static void P_NetArchivePlayers(savebuffer_t *save) @@ -500,6 +500,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].trickboostdecay); WRITEUINT8(save->p, players[i].trickboost); + WRITEUINT8(save->p, players[i].dashRingPullTics); + WRITEUINT8(save->p, players[i].dashRingPushTics); + WRITEUINT32(save->p, players[i].ebrakefor); WRITEUINT32(save->p, players[i].roundscore); @@ -918,6 +921,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].trickboostdecay = READUINT8(save->p); players[i].trickboost = READUINT8(save->p); + players[i].dashRingPullTics = READUINT8(save->p); + players[i].dashRingPushTics = READUINT8(save->p); + players[i].ebrakefor = READUINT32(save->p); players[i].roundscore = READUINT32(save->p); @@ -5665,7 +5671,7 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending) } WRITEUINT8(save->p, encoremode); - + WRITEUINT8(save->p, mapmusrng); WRITEUINT32(save->p, leveltime); @@ -5836,7 +5842,7 @@ static boolean P_NetUnArchiveMisc(savebuffer_t *save, boolean reloading) } encoremode = (boolean)READUINT8(save->p); - + mapmusrng = READUINT8(save->p); if (!P_LoadLevel(true, reloading)) From 255a10494a4caefe0efbcbebac9d4b2752dca7b0 Mon Sep 17 00:00:00 2001 From: Lach Date: Thu, 20 Jul 2023 19:15:20 +1000 Subject: [PATCH 4/8] Expose Dash Ring variables to Lua (and fix roundscore accessibility) --- src/lua_playerlib.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 282279a71..9e7253e97 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -409,8 +409,12 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->trickboostdecay); else if (fastcmp(field,"trickboost")) lua_pushinteger(L, plr->trickboost); + else if (fastcmp(field,"dashRingPullTics")) + lua_pushinteger(L, plr->dashRingPullTics); + else if (fastcmp(field,"dashRingPushTics")) + lua_pushinteger(L, plr->dashRingPushTics); else if (fastcmp(field,"roundscore")) - plr->roundscore = luaL_checkinteger(L, 3); + lua_pushinteger(L, plr->roundscore); else if (fastcmp(field,"emeralds")) lua_pushinteger(L, plr->emeralds); else if (fastcmp(field,"karmadelay")) @@ -730,7 +734,7 @@ static int player_set(lua_State *L) else if (fastcmp(field,"sliptideZipBoost")) plr->sliptideZipBoost = luaL_checkinteger(L, 3); else if (fastcmp(field,"instaShieldCooldown")) - plr->instaShieldCooldown = luaL_checkinteger(L, 3); + plr->instaShieldCooldown = luaL_checkinteger(L, 3); else if (fastcmp(field,"guardCooldown")) plr->guardCooldown = luaL_checkinteger(L, 3); /* @@ -813,8 +817,12 @@ static int player_set(lua_State *L) plr->trickboostdecay = luaL_checkinteger(L, 3); else if (fastcmp(field,"trickboost")) plr->trickboost = luaL_checkinteger(L, 3); + else if (fastcmp(field,"dashRingPullTics")) + plr->dashRingPullTics = luaL_checkinteger(L, 3); + else if (fastcmp(field,"dashRingPushTics")) + plr->dashRingPushTics = luaL_checkinteger(L, 3); else if (fastcmp(field,"roundscore")) - lua_pushinteger(L, plr->roundscore); + plr->roundscore = luaL_checkinteger(L, 3); else if (fastcmp(field,"emeralds")) plr->emeralds = luaL_checkinteger(L, 3); else if (fastcmp(field,"karmadelay")) From 2d7ae88586311b7867e3d289c75baf88cfb68764 Mon Sep 17 00:00:00 2001 From: Lach Date: Fri, 21 Jul 2023 19:19:28 +1000 Subject: [PATCH 5/8] Hardcode MT_BOOSTPAD as MT_SNEAKERPANEL --- src/deh_tables.c | 12 ++-- src/info.c | 18 ++--- src/info.h | 14 ++-- src/k_objects.h | 6 ++ src/objects/CMakeLists.txt | 1 + src/objects/sneaker-panel.c | 129 ++++++++++++++++++++++++++++++++++++ src/p_enemy.c | 3 +- src/p_map.c | 11 +++ src/p_mobj.c | 13 +++- 9 files changed, 182 insertions(+), 25 deletions(-) create mode 100644 src/objects/sneaker-panel.c diff --git a/src/deh_tables.c b/src/deh_tables.c index da72e26ec..89b14223a 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -4251,10 +4251,10 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_DASHRING_VERTICAL_FLASH1", "S_DASHRING_VERTICAL_FLASH2", - // Boost pads - "S_BOOSTPAD", - "S_BOOSTPAD_SMALL", - "S_BOOSTPAD_TINY", + // Sneaker Panels + "S_SNEAKERPANEL", + "S_SNEAKERPANEL_SMALL", + "S_SNEAKERPANEL_TINY", // Various plants "S_SONICBUSH", @@ -5627,8 +5627,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_DASHRING", "MT_RAINBOWDASHRING", - // Boost pads - "MT_BOOSTPAD", + // Sneaker Panels + "MT_SNEAKERPANEL", // Various plants "MT_SONICBUSH", diff --git a/src/info.c b/src/info.c index 8aabe2828..7309a520d 100644 --- a/src/info.c +++ b/src/info.c @@ -720,7 +720,7 @@ char sprnames[NUMSPRITES + 1][5] = // Dash Rings "RAIR", - // Boost pads + // Sneaker Panels "BSTP", "BSTS", "BSTT", @@ -4940,10 +4940,10 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, TICRATE/3 - 2, {NULL}, 0, 0, S_DASHRING_VERTICAL_FLASH2}, // S_DASHRING_VERTICAL_FLASH1 {SPR_RAIR, FF_ADD|3, 2, {NULL}, 0, 0, S_DASHRING_VERTICAL_FLASH1}, // S_DASHRING_VERTICAL_FLASH2 - // Boost pads - {SPR_BSTP, FF_FLOORSPRITE, 1, {A_TextureAnimate}, 5, 2, S_BOOSTPAD}, // S_BOOSTPAD - {SPR_BSTS, FF_FLOORSPRITE, 1, {A_TextureAnimate}, 5, 2, S_BOOSTPAD_SMALL}, // S_BOOSTPAD_SMALL - {SPR_BSTT, FF_FLOORSPRITE, 1, {A_TextureAnimate}, 5, 2, S_BOOSTPAD_TINY}, // S_BOOSTPAD_TINY + // Sneaker Panels + {SPR_BSTP, FF_FLOORSPRITE|FF_FULLBRIGHT, 1, {A_TextureAnimate}, 5, 2, S_SNEAKERPANEL}, // S_SNEAKERPANEL + {SPR_BSTS, FF_FLOORSPRITE|FF_FULLBRIGHT, 1, {A_TextureAnimate}, 5, 2, S_SNEAKERPANEL_SMALL}, // S_SNEAKERPANEL_SMALL + {SPR_BSTT, FF_FLOORSPRITE|FF_FULLBRIGHT, 1, {A_TextureAnimate}, 5, 2, S_SNEAKERPANEL_TINY}, // S_SNEAKERPANEL_TINY // Various plants {SPR_SBUS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SONICBUSH @@ -26807,10 +26807,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_BOOSTPAD + { // MT_SNEAKERPANEL 510, // doomednum - S_BOOSTPAD, // spawnstate - 1, // spawnhealth + S_SNEAKERPANEL, // spawnstate + 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound 0, // reactiontime @@ -26830,7 +26830,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 0, // damage sfx_None, // activesound - MF_ENEMY|MF_SPECIAL, // flags + MF_SPECIAL|MF_ENEMY, // flags -- NOTE: IIRC MF_ENEMY was added by mappers to make conveyor belt setups more convenient S_NULL // raisestate }, diff --git a/src/info.h b/src/info.h index ea8b21b2b..5f816accc 100644 --- a/src/info.h +++ b/src/info.h @@ -1273,7 +1273,7 @@ typedef enum sprite // Dash Rings SPR_RAIR, - // Boost pads + // Sneaker Panels SPR_BSTP, SPR_BSTS, SPR_BSTT, @@ -5390,10 +5390,10 @@ typedef enum state S_DASHRING_VERTICAL_FLASH1, S_DASHRING_VERTICAL_FLASH2, - // Boost pads - S_BOOSTPAD, - S_BOOSTPAD_SMALL, - S_BOOSTPAD_TINY, + // Sneaker Panels + S_SNEAKERPANEL, + S_SNEAKERPANEL_SMALL, + S_SNEAKERPANEL_TINY, // Various plants S_SONICBUSH, @@ -6801,8 +6801,8 @@ typedef enum mobj_type MT_DASHRING, MT_RAINBOWDASHRING, - // Boost pads - MT_BOOSTPAD, + // Sneaker Panels + MT_SNEAKERPANEL, // Various plants MT_SONICBUSH, diff --git a/src/k_objects.h b/src/k_objects.h index ab4d259e6..f72ad1e20 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -193,6 +193,12 @@ void Obj_DashRingTouch(mobj_t *mobj, player_t *player); void Obj_DashRingPlayerThink(player_t *player); boolean Obj_DashRingPlayerHasNoGravity(player_t *player); +/* Sneaker Panels */ +void Obj_SneakerPanelSpawn(mobj_t *mobj); +void Obj_SneakerPanelSetup(mobj_t *mobj, mapthing_t *mthing); +void Obj_SneakerPanelThink(mobj_t *mobj); +void Obj_SneakerPanelCollide(mobj_t *pad, mobj_t *mo); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index 2e0f65913..4eaa1d2f5 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -26,4 +26,5 @@ target_sources(SRB2SDL2 PRIVATE powerup-aura.cpp symbol.c dash-rings.c + sneaker-panel.c ) diff --git a/src/objects/sneaker-panel.c b/src/objects/sneaker-panel.c new file mode 100644 index 000000000..8d27503a8 --- /dev/null +++ b/src/objects/sneaker-panel.c @@ -0,0 +1,129 @@ +#include "../r_main.h" +#include "../p_slopes.h" +#include "../p_local.h" +#include "../k_kart.h" + +#define SNEAKERPANEL_RADIUS (64*FRACUNIT) + +static void SneakerPanelSpriteScale(mobj_t *mobj) +{ + statenum_t newState; + fixed_t spriteScale; + + if (mobj->scale == mobj->movefactor) + return; + + mobj->movefactor = mobj->scale; + + if (mobj->scale > FRACUNIT >> 1) + { + newState = S_SNEAKERPANEL; + spriteScale = FRACUNIT; + } + else if (mobj->scale > FRACUNIT >> 2) + { + newState = S_SNEAKERPANEL_SMALL; + spriteScale = FRACUNIT << 1; + } + else + { + newState = S_SNEAKERPANEL_TINY; + spriteScale = FRACUNIT << 2; + } + + if ((mobj->state - states) != newState) + { + P_SetMobjState(mobj, newState); + mobj->spritexscale = mobj->spriteyscale = spriteScale; + } +} + +void Obj_SneakerPanelSpawn(mobj_t *mobj) +{ + mobj->renderflags |= RF_OBJECTSLOPESPLAT | RF_NOSPLATBILLBOARD; + SneakerPanelSpriteScale(mobj); +} + +void Obj_SneakerPanelSetup(mobj_t *mobj, mapthing_t *mthing) +{ + if (mthing->options & MTF_OBJECTFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + mobj->flags2 |= MF2_OBJECTFLIP; + } + P_TryMove(mobj, mobj->x, mobj->y, true, NULL); // sets standingslope + SneakerPanelSpriteScale(mobj); +} + +void Obj_SneakerPanelThink(mobj_t *mobj) +{ + // ugh, this only has to exist because of the sneaker panel spawners... + // I think, when we hardcode those, it would be good to make a specialized A_TrapShot wrapper to re-scale their spawned panels and remove this thinker + SneakerPanelSpriteScale(mobj); +} + +void Obj_SneakerPanelCollide(mobj_t *panel, mobj_t *mo) +{ + pslope_t *slope = panel->standingslope; + player_t *player = mo->player; + fixed_t playerTop = mo->z + mo->height, playerBottom = mo->z; + fixed_t panelTop, panelBottom, dist, x, y, radius; + angle_t angle; + + // only players can boost! + if (player == NULL) + return; + + // these aren't aerial boosters, so you do need to be on the ground + if (!P_IsObjectOnGround(mo)) + return; + + // player needs to have the same gravflip status as the panel + if ((panel->eflags & MFE_VERTICALFLIP) != (mo->eflags & MFE_VERTICALFLIP)) + return; + + // find the x and y coordinates of the player relative to the booster's angle + dist = R_PointToDist2(panel->x, panel->y, mo->x, mo->y); + angle = R_PointToAngle2(panel->x, panel->y, mo->x, mo->y) - panel->angle; + x = P_ReturnThrustX(NULL, angle, dist); + y = P_ReturnThrustY(NULL, angle, dist); + + // check that these coordinates fall within the square panel + radius = FixedMul(SNEAKERPANEL_RADIUS, panel->scale); + + if (x < -radius || x > radius || y < -radius || y > radius) + return; // out of bounds + + // check that the player is within reasonable vertical bounds + if (slope == NULL) + { + panelTop = panel->z + panel->height; + panelBottom = panel->z; + } + else + { + x = P_ReturnThrustX(NULL, slope->xydirection, panel->radius); + y = P_ReturnThrustY(NULL, slope->xydirection, panel->radius); + panelTop = P_GetSlopeZAt(slope, panel->x + x, panel->y + y); + panelBottom = P_GetSlopeZAt(slope, panel->x - x, panel->y - y); + + if (panelTop < panelBottom) + { + // variable swap + panelTop = panelTop + panelBottom; + panelBottom = panelTop - panelBottom; + panelTop = panelTop - panelBottom; + } + } + + if ((playerBottom > panelTop) || (playerTop < panelBottom)) + return; + + // boost! + if (player->floorboost == 0) + player->floorboost = 3; + else + player->floorboost = 2; + + K_DoSneaker(player, 0); +} diff --git a/src/p_enemy.c b/src/p_enemy.c index bf4165281..01420801f 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -13744,7 +13744,6 @@ void A_TextureAnimate(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; - state_t *state = actor->state; if (LUA_CallAction(A_TEXTUREANIMATE, actor)) { @@ -13754,5 +13753,5 @@ void A_TextureAnimate(mobj_t *actor) if (actor->frame & FF_ANIMATE) // this doesn't work if you're animating on your own as well return; - actor->frame = (actor->frame & ~FF_FRAMEMASK) | ((state->frame & FF_FRAMEMASK) + ((leveltime / state->var2) % (state->var1 + 1))) + actor->frame += ((leveltime / locvar2) % (locvar1 + 1)); } diff --git a/src/p_map.c b/src/p_map.c index 2d00b808e..6c6f47e80 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1152,6 +1152,17 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) return K_FallingRockCollide(thing, tm.thing) ? BMIT_CONTINUE : BMIT_ABORT; } + if (thing->type == MT_SNEAKERPANEL) + { + Obj_SneakerPanelCollide(thing, tm.thing); + return BMIT_CONTINUE; + } + else if (tm.thing->type == MT_SNEAKERPANEL) + { + Obj_SneakerPanelCollide(tm.thing, thing); + return BMIT_CONTINUE; + } + //} if ((thing->type == MT_SPRINGSHELL || thing->type == MT_YELLOWSHELL) && thing->health > 0 diff --git a/src/p_mobj.c b/src/p_mobj.c index acc48e89a..171dbb056 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9608,6 +9608,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) case MT_RAINBOWDASHRING: Obj_RainbowDashRingThink(mobj); break; + case MT_SNEAKERPANEL: + Obj_SneakerPanelThink(mobj); + break; default: // check mobj against possible water content, before movement code P_MobjCheckWater(mobj); @@ -10446,7 +10449,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) case MT_DRIFTCLIP: thing->shadowscale = FRACUNIT/3; break; - case MT_BOOSTPAD: + case MT_SNEAKERPANEL: thing->shadowscale = 0; break; default: @@ -11005,6 +11008,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_RAINBOWDASHRING: Obj_RainbowDashRingSpawn(mobj); break; + case MT_SNEAKERPANEL: + Obj_SneakerPanelSpawn(mobj); + break; default: break; } @@ -13535,6 +13541,11 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj) Obj_DashRingSetup(mobj, mthing); break; } + case MT_SNEAKERPANEL: + { + Obj_SneakerPanelSetup(mobj, mthing); + break; + } default: break; } From bdc77ce9403e4e0cd62e689163a3a73550403115 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 28 Jul 2023 23:39:51 +0100 Subject: [PATCH 6/8] Add "../k_objects.h" to dash-rings.c --- src/objects/dash-rings.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/objects/dash-rings.c b/src/objects/dash-rings.c index 80822d03f..ac24af20e 100644 --- a/src/objects/dash-rings.c +++ b/src/objects/dash-rings.c @@ -1,5 +1,6 @@ #include "../p_local.h" #include "../k_kart.h" +#include "../k_objects.h" #include "../s_sound.h" // Dash Rings are scaled by this much relative to the map scale From fd8ba4236dc2d90a288b04b5505259cd5900f1da Mon Sep 17 00:00:00 2001 From: Lach Date: Sat, 29 Jul 2023 17:51:25 +1000 Subject: [PATCH 7/8] Hardcode MT_SNEAKERPANELSPAWNER & adjust FF_GLOBALANIM behaviour --- src/deh_tables.c | 4 +++- src/info.c | 34 +++++++++++++++++++++++++++++++--- src/info.h | 6 ++++-- src/k_objects.h | 2 +- src/objects/sneaker-panel.c | 13 +++---------- src/p_enemy.c | 36 ++++++++++++++++++++++++++---------- src/p_mobj.c | 12 ++++-------- src/p_tick.c | 4 ++++ src/p_tick.h | 1 + 9 files changed, 77 insertions(+), 35 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 89b14223a..5568518dc 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -301,7 +301,7 @@ actionpointer_t actionpointers[] = {{A_InvincSparkleRotate}, "A_INVINCSPARKLEROTATE"}, {{A_SpawnItemDebrisCloud}, "A_SPAWNITEMDEBRISCLOUD"}, {{A_RingShooterFace}, "A_RINGSHOOTERFACE"}, - {{A_TextureAnimate}, "A_TEXTUREANIMATE"}, + {{A_SpawnSneakerPanel}, "A_SPAWNSNEAKERPANEL"}, {{NULL}, "NONE"}, @@ -4255,6 +4255,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_SNEAKERPANEL", "S_SNEAKERPANEL_SMALL", "S_SNEAKERPANEL_TINY", + "S_SNEAKERPANELSPAWNER", // Various plants "S_SONICBUSH", @@ -5629,6 +5630,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t // Sneaker Panels "MT_SNEAKERPANEL", + "MT_SNEAKERPANELSPAWNER", // Various plants "MT_SONICBUSH", diff --git a/src/info.c b/src/info.c index 7309a520d..4aca66a8d 100644 --- a/src/info.c +++ b/src/info.c @@ -4941,9 +4941,10 @@ state_t states[NUMSTATES] = {SPR_RAIR, FF_ADD|3, 2, {NULL}, 0, 0, S_DASHRING_VERTICAL_FLASH1}, // S_DASHRING_VERTICAL_FLASH2 // Sneaker Panels - {SPR_BSTP, FF_FLOORSPRITE|FF_FULLBRIGHT, 1, {A_TextureAnimate}, 5, 2, S_SNEAKERPANEL}, // S_SNEAKERPANEL - {SPR_BSTS, FF_FLOORSPRITE|FF_FULLBRIGHT, 1, {A_TextureAnimate}, 5, 2, S_SNEAKERPANEL_SMALL}, // S_SNEAKERPANEL_SMALL - {SPR_BSTT, FF_FLOORSPRITE|FF_FULLBRIGHT, 1, {A_TextureAnimate}, 5, 2, S_SNEAKERPANEL_TINY}, // S_SNEAKERPANEL_TINY + {SPR_BSTP, FF_ANIMATE|FF_GLOBALANIM|FF_FLOORSPRITE|FF_FULLBRIGHT, -1, {NULL}, 5, 2, S_SNEAKERPANEL}, // S_SNEAKERPANEL + {SPR_BSTS, FF_ANIMATE|FF_GLOBALANIM|FF_FLOORSPRITE|FF_FULLBRIGHT, -1, {NULL}, 5, 2, S_SNEAKERPANEL_SMALL}, // S_SNEAKERPANEL_SMALL + {SPR_BSTT, FF_ANIMATE|FF_GLOBALANIM|FF_FLOORSPRITE|FF_FULLBRIGHT, -1, {NULL}, 5, 2, S_SNEAKERPANEL_TINY}, // S_SNEAKERPANEL_TINY + {SPR_NULL, 0, 65, {A_SpawnSneakerPanel}, 0, 0, S_SNEAKERPANELSPAWNER}, // S_SNEAKERPANELSPAWNER // Various plants {SPR_SBUS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SONICBUSH @@ -26834,6 +26835,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SNEAKERPANELSPAWNER + 511, // doomednum + S_SNEAKERPANELSPAWNER, // 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 + 32*FRACUNIT, // radius + 60*FRACUNIT, // height + 0, // dispoffset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOBLOCKMAP|MF_SCENERY|MF_NOCLIPTHING, // flags + S_NULL // raisestate + }, + { // MT_SONICBUSH, 715, // doomednum S_SONICBUSH, // spawnstate diff --git a/src/info.h b/src/info.h index 5f816accc..75384566e 100644 --- a/src/info.h +++ b/src/info.h @@ -294,7 +294,7 @@ enum actionnum A_INVINCSPARKLEROTATE, A_SPAWNITEMDEBRISCLOUD, A_RINGSHOOTERFACE, - A_TEXTUREANIMATE, + A_SPAWNSNEAKERPANEL, NUMACTIONS }; @@ -569,7 +569,7 @@ void A_FlameShieldPaper(); void A_InvincSparkleRotate(); void A_SpawnItemDebrisCloud(); void A_RingShooterFace(); -void A_TextureAnimate(); +void A_SpawnSneakerPanel(); extern boolean actionsoverridden[NUMACTIONS]; @@ -5394,6 +5394,7 @@ typedef enum state S_SNEAKERPANEL, S_SNEAKERPANEL_SMALL, S_SNEAKERPANEL_TINY, + S_SNEAKERPANELSPAWNER, // Various plants S_SONICBUSH, @@ -6803,6 +6804,7 @@ typedef enum mobj_type // Sneaker Panels MT_SNEAKERPANEL, + MT_SNEAKERPANELSPAWNER, // Various plants MT_SONICBUSH, diff --git a/src/k_objects.h b/src/k_objects.h index f72ad1e20..26f6d14ac 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -194,9 +194,9 @@ void Obj_DashRingPlayerThink(player_t *player); boolean Obj_DashRingPlayerHasNoGravity(player_t *player); /* Sneaker Panels */ +void Obj_SneakerPanelSpriteScale(mobj_t *mobj); void Obj_SneakerPanelSpawn(mobj_t *mobj); void Obj_SneakerPanelSetup(mobj_t *mobj, mapthing_t *mthing); -void Obj_SneakerPanelThink(mobj_t *mobj); void Obj_SneakerPanelCollide(mobj_t *pad, mobj_t *mo); #ifdef __cplusplus diff --git a/src/objects/sneaker-panel.c b/src/objects/sneaker-panel.c index 8d27503a8..aea6aad7b 100644 --- a/src/objects/sneaker-panel.c +++ b/src/objects/sneaker-panel.c @@ -5,7 +5,7 @@ #define SNEAKERPANEL_RADIUS (64*FRACUNIT) -static void SneakerPanelSpriteScale(mobj_t *mobj) +void Obj_SneakerPanelSpriteScale(mobj_t *mobj) { statenum_t newState; fixed_t spriteScale; @@ -41,7 +41,7 @@ static void SneakerPanelSpriteScale(mobj_t *mobj) void Obj_SneakerPanelSpawn(mobj_t *mobj) { mobj->renderflags |= RF_OBJECTSLOPESPLAT | RF_NOSPLATBILLBOARD; - SneakerPanelSpriteScale(mobj); + Obj_SneakerPanelSpriteScale(mobj); } void Obj_SneakerPanelSetup(mobj_t *mobj, mapthing_t *mthing) @@ -52,14 +52,7 @@ void Obj_SneakerPanelSetup(mobj_t *mobj, mapthing_t *mthing) mobj->flags2 |= MF2_OBJECTFLIP; } P_TryMove(mobj, mobj->x, mobj->y, true, NULL); // sets standingslope - SneakerPanelSpriteScale(mobj); -} - -void Obj_SneakerPanelThink(mobj_t *mobj) -{ - // ugh, this only has to exist because of the sneaker panel spawners... - // I think, when we hardcode those, it would be good to make a specialized A_TrapShot wrapper to re-scale their spawned panels and remove this thinker - SneakerPanelSpriteScale(mobj); + Obj_SneakerPanelSpriteScale(mobj); } void Obj_SneakerPanelCollide(mobj_t *panel, mobj_t *mo) diff --git a/src/p_enemy.c b/src/p_enemy.c index 01420801f..a1624f4cf 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -13662,6 +13662,11 @@ A_SpawnItemDebrisCloud (mobj_t *actor) fixed_t kartspeed; fixed_t fade; + if (LUA_CallAction(A_SPAWNITEMDEBRISCLOUD, (actor))) + { + return; + } + if (target == NULL || target->player == NULL) { return; @@ -13735,23 +13740,34 @@ void A_RingShooterFace(mobj_t *actor) Obj_UpdateRingShooterFace(actor); } -// Syncs the actor's frame with the animated texture ticker in P_UpdateSpecials -// Call continuously to simulate an animated texture -// var1 and var2 act like FF_ANIMATE, i.e.: -// var1 = number of additional frames to cycle through -// var2 = number of tics to display each frame -void A_TextureAnimate(mobj_t *actor) +// Function: A_SpawnSneakerPanel +// +// Description: Spawns a sneaker panel object relative to the location of the actor +// +// var1: +// var1 >> 16 = x offset +// var1 & 65535 = y offset +// var2: +// var2 >> 16 = z +// var2 & 65535 = unused +// +void A_SpawnSneakerPanel(mobj_t *actor) { + INT16 x, y, z; + mobj_t *mo; INT32 locvar1 = var1; INT32 locvar2 = var2; - if (LUA_CallAction(A_TEXTUREANIMATE, actor)) + if (LUA_CallAction(A_SPAWNSNEAKERPANEL, actor)) { return; } - if (actor->frame & FF_ANIMATE) // this doesn't work if you're animating on your own as well - return; + x = (INT16)(locvar1 >> 16); + y = (INT16)(locvar1 & 65535); + z = (INT16)(locvar2 >> 16); - actor->frame += ((leveltime / locvar2) % (locvar1 + 1)); + mo = P_SpawnMobjFromMobj(actor, x << FRACBITS, y << FRACBITS, z << FRACBITS, MT_SNEAKERPANEL); + mo->angle = actor->angle; + Obj_SneakerPanelSpriteScale(mo); } diff --git a/src/p_mobj.c b/src/p_mobj.c index 171dbb056..e5addca93 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -128,11 +128,10 @@ static void P_SetupStateAnimation(mobj_t *mobj, state_t *st) if (st->frame & FF_GLOBALANIM) { - // Attempt to account for the pre-ticker for objects spawned on load - if (!leveltime) return; - - mobj->anim_duration -= (leveltime + 2) % st->var2; // Duration synced to timer - mobj->frame += ((leveltime + 2) / st->var2) % (animlength + 1); // Frame synced to timer (duration taken into account) + mobj->anim_duration -= (leveltime % st->var2); // Duration synced to timer + mobj->frame += (leveltime / st->var2) % (animlength + 1); // Frame synced to timer (duration taken into account) + if (!thinkersCompleted) // objects spawned BEFORE (or during) thinkers will think during this tic... + mobj->anim_duration++; // ...so increase the duration of their current frame by 1 to sync with objects spawned AFTER thinkers } else if (st->frame & FF_RANDOMANIM) { @@ -9608,9 +9607,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj) case MT_RAINBOWDASHRING: Obj_RainbowDashRingThink(mobj); break; - case MT_SNEAKERPANEL: - Obj_SneakerPanelThink(mobj); - break; default: // check mobj against possible water content, before movement code P_MobjCheckWater(mobj); diff --git a/src/p_tick.c b/src/p_tick.c index 1c756a8e5..74250931c 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -48,6 +48,7 @@ #endif tic_t leveltime; +boolean thinkersCompleted; INT32 P_AltFlip(INT32 n, tic_t tics) { @@ -685,6 +686,8 @@ void P_Ticker(boolean run) quake_t *quake = NULL; INT32 i; + thinkersCompleted = false; + // Increment jointime and quittime even if paused for (i = 0; i < MAXPLAYERS; i++) { @@ -794,6 +797,7 @@ void P_Ticker(boolean run) ps_thinkertime = I_GetPreciseTime(); P_RunThinkers(); ps_thinkertime = I_GetPreciseTime() - ps_thinkertime; + thinkersCompleted = true; // Run any "after all the other thinkers" stuff { diff --git a/src/p_tick.h b/src/p_tick.h index a17a5358c..d05813c1c 100644 --- a/src/p_tick.h +++ b/src/p_tick.h @@ -25,6 +25,7 @@ extern "C" { #endif extern tic_t leveltime; +extern boolean thinkersCompleted; // Called by G_Ticker. Carries out all thinking of enemies and players. void Command_Numthinkers_f(void); From 6b86cbb500363b21b8321b0877ab426b332647e3 Mon Sep 17 00:00:00 2001 From: Lach Date: Sat, 29 Jul 2023 18:23:04 +1000 Subject: [PATCH 8/8] Fix compile warnings --- src/objects/sneaker-panel.c | 2 +- src/p_enemy.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objects/sneaker-panel.c b/src/objects/sneaker-panel.c index aea6aad7b..dc5c96c50 100644 --- a/src/objects/sneaker-panel.c +++ b/src/objects/sneaker-panel.c @@ -31,7 +31,7 @@ void Obj_SneakerPanelSpriteScale(mobj_t *mobj) spriteScale = FRACUNIT << 2; } - if ((mobj->state - states) != newState) + if (((statenum_t)(mobj->state - states)) != newState) { P_SetMobjState(mobj, newState); mobj->spritexscale = mobj->spriteyscale = spriteScale; diff --git a/src/p_enemy.c b/src/p_enemy.c index a1624f4cf..2013a19dd 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -330,7 +330,7 @@ void A_FlameShieldPaper(mobj_t *actor); void A_InvincSparkleRotate(mobj_t *actor); void A_SpawnItemDebrisCloud(mobj_t *actor); void A_RingShooterFace(mobj_t *actor); -void A_TextureAnimate(mobj_t *actor); +void A_SpawnSneakerPanel(mobj_t *actor); //for p_enemy.c