diff --git a/src/d_player.h b/src/d_player.h index 95d703ef..9a3ba707 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -321,6 +321,7 @@ typedef enum k_eggmanheld, // Eggman monitor held, separate from k_itemheld so it doesn't stop you from getting items k_eggmanexplode, // Fake item recieved, explode in a few seconds k_eggmanblame, // Fake item recieved, who set this fake + k_lastjawztarget, // Last person you target with jawz, for playing the target switch sfx k_bananadrag, // After a second of holding a banana behind you, you start to slow down k_spinouttimer, // Spin-out from a banana peel or oil slick (was "pw_bananacam") k_wipeoutslow, // Timer before you slowdown when getting wiped out diff --git a/src/dehacked.c b/src/dehacked.c index 28f20332..be17998c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6362,6 +6362,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_JAWZ_DEAD2", //} + "S_PLAYERRETICULE", // Player reticule + // Special Stage Mine "S_SSMINE1", "S_SSMINE2", @@ -7226,6 +7228,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_JAWZ_DUD", "MT_JAWZ_SHIELD", + "MT_PLAYERRETICULE", // Jawz reticule + "MT_SSMINE_SHIELD", // Special Stage Mine stuff "MT_SSMINE", "MT_MINEEXPLOSION", @@ -7683,7 +7687,6 @@ static const char *const KARTSTUFF_LIST[] = { "ITEMAMOUNT", "ITEMHELD", - //"THUNDERANIM", "CURSHIELD", "HYUDOROTIMER", "STEALINGTIMER", @@ -7697,6 +7700,7 @@ static const char *const KARTSTUFF_LIST[] = { "EGGMANHELD", "EGGMANEXPLODE", "EGGMANBLAME", + "LASTJAWZTARGET", "BANANADRAG", "SPINOUTTIMER", "WIPEOUTSLOW", diff --git a/src/info.c b/src/info.c index 281fe10f..76c535d7 100644 --- a/src/info.c +++ b/src/info.c @@ -60,7 +60,7 @@ char sprnames[NUMSPRITES + 1][5] = "THNS","SINK","SITR","KBLN","DEZL","POKE","AUDI","DECO","DOOD","SNES", "GBAS","SPRS","BUZB","CHOM","SACO","CRAB","SHAD","BRNG","BUMP","FLEN", "CLAS","PSHW","ISTA","ISTB","ARRO","ITEM","ITMO","ITMI","ITMN","WANT", - "PBOM","VIEW" + "PBOM","RETI","VIEW" }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) @@ -2684,6 +2684,8 @@ state_t states[NUMSTATES] = {SPR_JAWZ, 5, 175, {NULL}, 0, 0, S_JAWZ_DEAD2}, // S_JAWZ_DEAD1 {SPR_NULL, 0, 1, {A_JawzExplode}, 0, 0, S_NULL}, // S_JAWZ_DEAD2 + {SPR_RETI, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_PLAYERRETICULE + {SPR_SSMN, 0, 30, {NULL}, 0, 0, S_SSMINE2}, // S_SSMINE1 {SPR_SSMN, 3, 3, {NULL}, 0, 0, S_SSMINE3}, // S_SSMINE2 {SPR_SSMN, 2, 3, {NULL}, 0, 0, S_SSMINE4}, // S_SSMINE3 @@ -2894,7 +2896,6 @@ state_t states[NUMSTATES] = {SPR_BRNG, 10, 2, {NULL}, 0, 0, S_BIGRING12}, // S_BIGRING11 {SPR_BRNG, 11, 2, {NULL}, 0, 0, S_BIGRING01}, // S_BIGRING12 - {SPR_SNES, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNES_DONUTBUSH1 {SPR_SNES, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SNES_DONUTBUSH2 {SPR_SNES, 2, -1, {NULL}, 0, 0, S_NULL}, // S_SNES_DONUTBUSH3 @@ -2991,7 +2992,6 @@ state_t states[NUMSTATES] = {SPR_WANT, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_PLAYERARROW_WANTED6}, // S_PLAYERARROW_WANTED5 {SPR_WANT, FF_FULLBRIGHT|5, 1, {NULL}, 0, 0, S_PLAYERARROW_WANTED7}, // S_PLAYERARROW_WANTED6 {SPR_WANT, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_PLAYERARROW_WANTED1}, // S_PLAYERARROW_WANTED7 - {SPR_PBOM, FF_ANIMATE, -1, {NULL}, 3, 3, S_NULL}, // S_PLAYERBOMB {SPR_RNDM, FF_ANIMATE, -1, {NULL}, 23, 3, S_NULL}, // S_PLAYERITEM @@ -14794,6 +14794,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_PLAYERRETICULE + -1, // doomednum + S_PLAYERRETICULE, // 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 + 8, // speed + 16*FRACUNIT, // radius + 56*FRACUNIT, // height + 2, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_SSMINE -1, // doomednum S_SSMINE_AIR1, // spawnstate diff --git a/src/info.h b/src/info.h index 98d628b3..20209416 100644 --- a/src/info.h +++ b/src/info.h @@ -637,6 +637,7 @@ typedef enum sprite SPR_WANT, SPR_PBOM, // player bomb + SPR_RETI, // player reticule SPR_VIEW, // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw! @@ -3206,6 +3207,8 @@ typedef enum state S_JAWZ_DEAD2, //} + S_PLAYERRETICULE, // Player reticule + // Special Stage Mine S_SSMINE1, S_SSMINE2, @@ -4087,6 +4090,8 @@ typedef enum mobj_type MT_JAWZ_DUD, MT_JAWZ_SHIELD, + MT_PLAYERRETICULE, // Jawz reticule + MT_SSMINE, // Mine stuff MT_SSMINE_SHIELD, MT_MINEEXPLOSION, diff --git a/src/k_kart.c b/src/k_kart.c index 86ab61f9..9dce3dee 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3069,6 +3069,87 @@ static void K_MoveHeldObjects(player_t *player) } } +player_t *K_FindJawzTarget(mobj_t *actor, player_t *source) +{ + fixed_t best = -1; + player_t *wtarg = NULL; + INT32 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + angle_t thisang; + player_t *player; + + if (!playeringame[i]) + continue; + + player = &players[i]; + + if (player->spectator) + continue; // spectator + + if (!player->mo) + continue; + + if (player->mo->health <= 0) + continue; // dead + + // Don't target yourself, stupid. + if (player == source) + continue; + + // Don't home in on teammates. + if (G_GametypeHasTeams() && source->ctfteam == player->ctfteam) + continue; + + // Find the angle, see who's got the best. + thisang = actor->angle - R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y); + if (thisang > ANGLE_180) + thisang = InvAngle(thisang); + + if (thisang > ANGLE_45) // Don't go for people who are behind you + continue; + + // Jawz only go after the person directly ahead of you in race... sort of literally now! + if (G_RaceGametype()) + { + if (player->kartstuff[k_position] >= source->kartstuff[k_position]) // Don't pay attention to people behind you + continue; + if ((best == -1) || (player->kartstuff[k_position] > best)) + { + wtarg = player; + best = player->kartstuff[k_position]; + } + } + else + { + fixed_t thisdist; + fixed_t thisavg; + + if (player->kartstuff[k_bumper] <= 0) + continue; + + thisdist = P_AproxDistance(P_AproxDistance(player->mo->x - (actor->x + actor->momx), + player->mo->y - (actor->y + actor->momy)), player->mo->z - (actor->z + actor->momz)); + + if (thisdist > RING_DIST) // Don't go for people who are too far away + continue; + + thisavg = (AngleFixed(thisang) + thisdist) / 2; + + //CONS_Printf("got avg %d from player # %d\n", thisavg>>FRACBITS, i); + + if ((best == -1) || (thisavg < best)) + { + wtarg = player; + best = thisavg; + } + } + } + + return wtarg; +} + /** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c \param player player object passed from P_PlayerThink @@ -3362,6 +3443,39 @@ void K_KartPlayerAfterThink(player_t *player) // Move held objects (Bananas, Orbinaut, etc) K_MoveHeldObjects(player); + + // Jawz reticule (seeking) + if (player->kartstuff[k_itemtype] == KITEM_JAWZ && player->kartstuff[k_itemheld]) + { + player_t *targ = K_FindJawzTarget(player->mo, player); + mobj_t *ret; + + if (!targ) + { + player->kartstuff[k_lastjawztarget] = -1; + return; + } + + ret = P_SpawnMobj(targ->mo->x, targ->mo->y, targ->mo->z, MT_PLAYERRETICULE); + P_SetTarget(&ret->target, targ->mo); + ret->frame |= ((leveltime % 10) / 2); + ret->tics = 1; + ret->color = player->skincolor; + + if (targ-players != player->kartstuff[k_lastjawztarget]) + { + if (P_IsLocalPlayer(player) || P_IsLocalPlayer(targ)) + S_StartSound(NULL, sfx_s3k89); + else + S_StartSound(targ->mo, sfx_s3k89); + + player->kartstuff[k_lastjawztarget] = targ-players; + } + } + else + { + player->kartstuff[k_lastjawztarget] = -1; + } } // Returns false if this player being placed here causes them to collide with any other player diff --git a/src/k_kart.h b/src/k_kart.h index 89f1ea7e..58f2cc17 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -42,6 +42,7 @@ void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source); void K_CleanHnextList(mobj_t *work); void K_UpdateHnextList(player_t *player); void K_RepairOrbitChain(mobj_t *orbit); +player_t *K_FindJawzTarget(mobj_t *actor, player_t *source); boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue); fixed_t K_GetKartDriftSparkValue(player_t *player); diff --git a/src/p_enemy.c b/src/p_enemy.c index f5f83405..83011674 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8164,8 +8164,6 @@ void A_ItemPop(mobj_t *actor) void A_JawzChase(mobj_t *actor) { - fixed_t best = -1; - SINT8 wtarg = -1; player_t *player; #ifdef HAVE_BLUA if (LUA_CallAction("A_JawzChase", actor)) @@ -8179,6 +8177,13 @@ void A_JawzChase(mobj_t *actor) if (actor->tracer && actor->tracer->health) { + mobj_t *ret; + + ret = P_SpawnMobj(actor->tracer->x, actor->tracer->y, actor->tracer->z, MT_PLAYERRETICULE); + P_SetTarget(&ret->target, actor->tracer); + ret->frame |= ((leveltime % 10) / 2) + 5; + ret->color = actor->target->player->skincolor; + P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), actor->info->speed); return; } @@ -8187,84 +8192,9 @@ void A_JawzChase(mobj_t *actor) if (actor->extravalue1) // Disable looking by setting this return; - for (actor->lastlook = 0; actor->lastlook < MAXPLAYERS; actor->lastlook++) - { - if (!playeringame[actor->lastlook]) - continue; - - player = &players[actor->lastlook]; - - if (player->spectator) - continue; // spectator - - if (!player->mo) - continue; - - if (player->mo->health <= 0) - continue; // dead - - if (actor->target && actor->target->player) - { - angle_t thisang; - - if (player->mo == actor->target) - continue; - - // Don't home in on teammates. - if (G_GametypeHasTeams() && actor->target->player->ctfteam == player->ctfteam) - continue; - - // Find the angle, see who's got the best. - thisang = actor->angle - R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y); - if (thisang > ANGLE_180) - thisang = InvAngle(thisang); - - if (thisang > ANGLE_45) // Don't go for people who are behind you - continue; - - // Jawz only go after the person directly ahead of you in race... sort of literally now! - if (G_RaceGametype()) - { - if (player->kartstuff[k_position] >= actor->target->player->kartstuff[k_position]) // Don't pay attention to people behind you - continue; - if ((best == -1) || (player->kartstuff[k_position] > best)) - { - wtarg = actor->lastlook; - best = player->kartstuff[k_position]; - } - } - else - { - fixed_t thisdist; - fixed_t thisavg; - - if (player->kartstuff[k_bumper] <= 0) - continue; - - thisdist = P_AproxDistance(P_AproxDistance(player->mo->x - (actor->x + actor->momx), - player->mo->y - (actor->y + actor->momy)), player->mo->z - (actor->z + actor->momz)); - - if (thisdist > RING_DIST) // Don't go for people who are too far away - continue; - - thisavg = (AngleFixed(thisang) + thisdist) / 2; - - //CONS_Printf("got avg %d from player # %d\n", thisavg>>FRACBITS, actor->lastlook); - - if ((best == -1) || (thisavg < best)) - { - wtarg = actor->lastlook; - best = thisavg; - } - } - } - } - - if (wtarg != -1) - { - //CONS_Printf("best: %d, final target: %d\n", best, wtarg); - P_SetTarget(&actor->tracer, players[wtarg].mo); - } + player = K_FindJawzTarget(actor, actor->target->player); + if (player) + P_SetTarget(&actor->tracer, player->mo); if (G_RaceGametype()) // Stop looking after first tic in race actor->extravalue1 = 1; diff --git a/src/p_mobj.c b/src/p_mobj.c index b6ebcd69..e1db00cc 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8242,6 +8242,14 @@ void P_MobjThinker(mobj_t *mobj) } P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); break; + case MT_PLAYERRETICULE: + if (!mobj->target || !mobj->target->health) + { + P_RemoveMobj(mobj); + return; + } + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + break; case MT_INSTASHIELDB: if (leveltime & 1) mobj->flags2 |= MF2_DONTDRAW; diff --git a/src/sounds.c b/src/sounds.c index a7e674ab..6e956260 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -483,7 +483,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k86", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k87", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k88", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k89", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3k89", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Jawz target {"s3k8a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k8b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, {"s3k8c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR},