diff --git a/src/d_player.h b/src/d_player.h index 362d98639..3050dc6cc 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -286,6 +286,8 @@ typedef enum pw_justlaunched, // Launched off a slope this tic (0=none, 1=standard launch, 2=half-pipe launch) + pw_ignorelatch, // Don't grab onto CR_GENERIC, add 32768 (powers[pw_ignorelatch] & 1<<15) to avoid ALL not-NiGHTS CR_ types + NUMPOWERS } powertype_t; diff --git a/src/dehacked.c b/src/dehacked.c index 99f0cacdf..031ddefa7 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9321,7 +9321,9 @@ static const char *const POWERS_LIST[] = { //for dyes "DYE", - "JUSTLAUNCHED" + "JUSTLAUNCHED", + + "IGNORELATCH" }; static const char *const HUDITEMS_LIST[] = { diff --git a/src/p_enemy.c b/src/p_enemy.c index a38496d99..07e36d03b 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -6945,7 +6945,9 @@ void A_RecyclePowers(mobj_t *actor) for (j = 0; j < NUMPOWERS; j++) { if (j == pw_flashing || j == pw_underwater || j == pw_spacetime || j == pw_carry - || j == pw_tailsfly || j == pw_extralife || j == pw_nocontrol || j == pw_super) + || j == pw_tailsfly || j == pw_extralife || j == pw_nocontrol || j == pw_super + || j == pw_pushing || j == pw_justsprung || j == pw_noautobrake || j == pw_justlaunched + || j == pw_ignorelatch) continue; players[recv_pl].powers[j] = powers[send_pl][j]; } @@ -13339,6 +13341,9 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing) if (!player) return true; + if (player->powers[pw_carry] != CR_DUSTDEVIL && (player->powers[pw_ignorelatch] & (1<<15))) + return true; + if (abs(thing->x - dustdevil->x) > dustdevil->radius || abs(thing->y - dustdevil->y) > dustdevil->radius) return true; diff --git a/src/p_inter.c b/src/p_inter.c index b01d40c00..9caed927d 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1468,7 +1468,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_BLACKEGGMAN_GOOPFIRE: - if (!player->powers[pw_flashing]) + if (!player->powers[pw_flashing] && !(player->powers[pw_ignorelatch] & (1<<15))) { toucher->momx = 0; toucher->momy = 0; @@ -1584,44 +1584,53 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_SMALLGRABCHAIN: case MT_BIGGRABCHAIN: - if (P_MobjFlip(toucher)*toucher->momz > 0 - || (player->powers[pw_carry])) - return; - - if (toucher->z > special->z + special->height/2) - return; - - if (toucher->z + toucher->height/2 < special->z) - return; - - if (player->powers[pw_flashing]) - return; - - if (special->movefactor && special->tracer && special->tracer->angle != ANGLE_90 && special->tracer->angle != ANGLE_270) - { // I don't expect you to understand this, Mr Bond... - angle_t ang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->tracer->angle; - if ((special->movefactor > 0) == (special->tracer->angle > ANGLE_90 && special->tracer->angle < ANGLE_270)) - ang += ANGLE_180; - if (ang < ANGLE_180) - return; // I expect you to die. - } - - P_ResetPlayer(player); - P_SetTarget(&toucher->tracer, special); - - if (special->tracer && !(special->tracer->flags2 & MF2_STRONGBOX)) { - player->powers[pw_carry] = CR_MACESPIN; - S_StartSound(toucher, sfx_spin); - P_SetPlayerMobjState(toucher, S_PLAY_ROLL); + boolean macespin = false; + if (P_MobjFlip(toucher)*toucher->momz > 0 + || (player->powers[pw_carry])) + return; + + if (toucher->z > special->z + special->height/2) + return; + + if (toucher->z + toucher->height/2 < special->z) + return; + + if (player->powers[pw_flashing]) + return; + + if (special->tracer && !(special->tracer->flags2 & MF2_STRONGBOX)) + macespin = true; + + if (macespin ? (player->powers[pw_ignorelatch] & (1<<15)) : (player->powers[pw_ignorelatch])) + return; + + if (special->movefactor && special->tracer && special->tracer->angle != ANGLE_90 && special->tracer->angle != ANGLE_270) + { // I don't expect you to understand this, Mr Bond... + angle_t ang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->tracer->angle; + if ((special->movefactor > 0) == (special->tracer->angle > ANGLE_90 && special->tracer->angle < ANGLE_270)) + ang += ANGLE_180; + if (ang < ANGLE_180) + return; // I expect you to die. + } + + P_ResetPlayer(player); + P_SetTarget(&toucher->tracer, special); + + if (macespin) + { + player->powers[pw_carry] = CR_MACESPIN; + S_StartSound(toucher, sfx_spin); + P_SetPlayerMobjState(toucher, S_PLAY_ROLL); + } + else + player->powers[pw_carry] = CR_GENERIC; + + // Can't jump first frame + player->pflags |= PF_JUMPSTASIS; + + return; } - else - player->powers[pw_carry] = CR_GENERIC; - - // Can't jump first frame - player->pflags |= PF_JUMPSTASIS; - - return; case MT_EGGMOBILE2_POGO: // sanity checks if (!special->target || !special->target->health) @@ -1711,7 +1720,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; case MT_MINECARTSPAWNER: - if (!player->bot && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART) + if (!player->bot && special->fuse <= TICRATE && player->powers[pw_carry] != CR_MINECART && !(player->powers[pw_ignorelatch] & (1<<15))) { mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART); P_SetTarget(&mcart->target, toucher); diff --git a/src/p_map.c b/src/p_map.c index 9fff1f693..2a1abffe2 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -527,6 +527,8 @@ static void P_DoPterabyteCarry(player_t *player, mobj_t *ptera) { if (player->powers[pw_carry] && player->powers[pw_carry] != CR_ROLLOUT) return; + if (player->powers[pw_ignorelatch] & (1<<15)) + return; if (ptera->extravalue1 != 1) return; // Not swooping if (ptera->target != player->mo) @@ -611,7 +613,8 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) if (zdist <= sonic->mo->height + sonic->mo->scale // FixedMul(FRACUNIT, sonic->mo->scale), but scale == FRACUNIT by default && zdist > sonic->mo->height*2/3 - && P_MobjFlip(tails->mo)*sonic->mo->momz <= 0) + && P_MobjFlip(tails->mo)*sonic->mo->momz <= 0 + && !(sonic->powers[pw_ignorelatch] & (1<<15))) { if (sonic-players == consoleplayer && botingame) CV_SetValue(&cv_analog[1], false); @@ -1002,6 +1005,7 @@ static boolean PIT_CheckThing(mobj_t *thing) } if ((thing->flags & MF_PUSHABLE) // not carrying a player && (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something + && !(tmthing->player->powers[pw_ignorelatch] & (1<<15)) && ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP)) && (P_MobjFlip(tmthing)*tmthing->momz <= 0) && ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2)) @@ -1291,6 +1295,7 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (tmthing->type == MT_BLACKEGGMAN_MISSILE && thing->player && (thing->player->pflags & PF_JUMPED) && !thing->player->powers[pw_flashing] + && !thing->player->powers[pw_ignorelatch] && thing->tracer != tmthing && tmthing->target != thing) { diff --git a/src/p_spec.c b/src/p_spec.c index 48212f755..b7fdedfd0 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4816,6 +4816,9 @@ DoneSection2: if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) break; + if (player->powers[pw_ignorelatch] & (1<<15)) + break; + // Find line #3 tagged to this sector lineindex = P_FindSpecialLineFromTag(3, sector->tag, -1); @@ -4878,6 +4881,9 @@ DoneSection2: if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) break; + if (player->powers[pw_ignorelatch] & (1<<15)) + break; + // Find line #3 tagged to this sector lineindex = P_FindSpecialLineFromTag(3, sector->tag, -1); @@ -4988,6 +4994,9 @@ DoneSection2: if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG) break; + if (player->powers[pw_ignorelatch] & (1<<15)) + break; + if (player->mo->momz > 0) break; diff --git a/src/p_user.c b/src/p_user.c index bc382a452..8a9823065 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4410,7 +4410,8 @@ void P_DoJump(player_t *player, boolean soundandstate) { player->mo->momz = 9*FRACUNIT; player->powers[pw_carry] = CR_NONE; - P_SetTarget(&player->mo->tracer->target, NULL); + if (!(player->mo->tracer->flags & MF_MISSILE)) // Missiles remember their owner! + P_SetTarget(&player->mo->tracer->target, NULL); P_SetTarget(&player->mo->tracer, NULL); } else if (player->powers[pw_carry] == CR_ROPEHANG) @@ -12094,6 +12095,11 @@ void P_PlayerThink(player_t *player) else player->powers[pw_nocontrol] = 0; + if (player->powers[pw_ignorelatch] & ((1<<15)-1) && player->powers[pw_ignorelatch] < UINT16_MAX) + player->powers[pw_ignorelatch]--; + else + player->powers[pw_ignorelatch] = 0; + //pw_super acts as a timer now if (player->powers[pw_super] && (player->mo->state < &states[S_PLAY_SUPER_TRANS1]