From cc331d90da1ddd223de1145c16ae4824af7d279b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 25 Sep 2022 09:55:49 -0400 Subject: [PATCH 1/7] Add orbinaut.c + new backwards behavior --- src/k_collide.c | 98 ----------- src/k_collide.h | 2 - src/k_kart.c | 124 ++++---------- src/k_kart.h | 2 + src/k_objects.h | 6 + src/objects/Sourcefile | 1 + src/objects/orbinaut.c | 377 +++++++++++++++++++++++++++++++++++++++++ src/p_map.c | 4 +- src/p_mobj.c | 72 +------- 9 files changed, 420 insertions(+), 266 deletions(-) create mode 100644 src/objects/orbinaut.c diff --git a/src/k_collide.c b/src/k_collide.c index a373af5c2..a95f77dc3 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -37,104 +37,6 @@ angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2) return R_PointToAngle2(0, 0, momux, momuy); } -boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) -{ - boolean damageitem = false; - boolean sprung = false; - - if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0)) - return true; - - if (((t1->target == t2) || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (t1->target == t2->target))) && ((t1->threshold > 0 && t2->type == MT_PLAYER) || (t2->type != MT_PLAYER && t2->threshold > 0))) - return true; - - if (t1->health <= 0 || t2->health <= 0) - return true; - - if ((t1->type == MT_ORBINAUT_SHIELD || t1->type == MT_JAWZ_SHIELD) && t1->lastlook - && (t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD) && t2->lastlook - && (t1->target == t2->target)) // Don't hit each other if you have the same target - return true; - - if (t2->player) - { - if ((t2->player->flashing > 0 && t2->hitlag == 0) - && !(t1->type == MT_ORBINAUT || t1->type == MT_JAWZ || t1->type == MT_JAWZ_DUD)) - return true; - - if (t2->player->hyudorotimer) - return true; // no interaction - - if (t2->player->flamedash && t2->player->itemtype == KITEM_FLAMESHIELD) - { - // Melt item - S_StartSound(t2, sfx_s3k43); - } - else - { - // Player Damage - P_DamageMobj(t2, t1, t1->target, 1, DMG_WIPEOUT|DMG_WOMBO); - K_KartBouncing(t2, t1); - S_StartSound(t2, sfx_s3k7b); - } - - damageitem = true; - } - else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD - || t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD - || t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD - || t2->type == MT_BALLHOG) - { - // Other Item Damage - angle_t bounceangle = K_GetCollideAngle(t1, t2); - - S_StartSound(t2, t2->info->deathsound); - P_KillMobj(t2, t1, t1, DMG_NORMAL); - - P_SetObjectMomZ(t2, 8*FRACUNIT, false); - P_InstaThrust(t2, bounceangle, 16*FRACUNIT); - - P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH); - - damageitem = true; - } - else if (t2->type == MT_SSMINE_SHIELD || t2->type == MT_SSMINE || t2->type == MT_LANDMINE) - { - damageitem = true; - // Bomb death - P_KillMobj(t2, t1, t1, DMG_NORMAL); - } - else if (t2->flags & MF_SPRING && (t1->type != MT_ORBINAUT_SHIELD && t1->type != MT_JAWZ_SHIELD)) - { - // Let thrown items hit springs! - sprung = P_DoSpring(t2, t1); - } - else if (t2->flags & MF_SHOOTABLE) - { - // Shootable damage - P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL); - damageitem = true; - } - - if (damageitem) - { - // This Item Damage - angle_t bounceangle = K_GetCollideAngle(t2, t1); - S_StartSound(t1, t1->info->deathsound); - P_KillMobj(t1, t2, t2, DMG_NORMAL); - - P_SetObjectMomZ(t1, 8*FRACUNIT, false); - P_InstaThrust(t1, bounceangle, 16*FRACUNIT); - } - - if (sprung) - { - return false; - } - - return true; -} - boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2) { boolean damageitem = false; diff --git a/src/k_collide.h b/src/k_collide.h index cf1ee5dc7..a498241ca 100644 --- a/src/k_collide.h +++ b/src/k_collide.h @@ -6,8 +6,6 @@ angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2); -boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2); - boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2); boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2); diff --git a/src/k_kart.c b/src/k_kart.c index ad93fdb75..54309a9c4 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4674,7 +4674,7 @@ fixed_t K_ItemScaleForPlayer(player_t *player) } } -static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, INT32 flags2, fixed_t speed) +static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, INT32 flags2, fixed_t speed, SINT8 dir) { mobj_t *th; fixed_t x, y, z; @@ -4688,20 +4688,20 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I if (source->player->itemscale == ITEMSCALE_SHRINK) { // Nerf the base item speed a bit. - finalspeed = FixedMul(finalspeed, SHRINK_PHYSICS_SCALE); + speed = finalspeed = FixedMul(speed, SHRINK_PHYSICS_SCALE); } if (source->player->speed > topspeed) { - angle_t input = source->angle - an; - boolean invert = (input > ANGLE_180); - if (invert) - input = InvAngle(input); + angle_t delta = AngleDelta(source->angle, an); - finalspeed = max(speed, FixedMul(speed, FixedMul( - FixedDiv(source->player->speed, topspeed), // Multiply speed to be proportional to your own, boosted maxspeed. - (((180<player->speed, topspeed), // Multiply speed to be proportional to your own, boosted maxspeed. + FixedDiv((ANGLE_180 - delta), ANGLE_180) // multiply speed based on angle diff... i.e: don't do this for firing backward :V + ) + )); } finalscale = K_ItemScaleForPlayer(source->player); @@ -4763,11 +4763,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I switch (type) { case MT_ORBINAUT: - if (source && source->player) - th->color = source->player->skincolor; - else - th->color = SKINCOLOR_GREY; - th->movefactor = finalspeed; + Obj_OrbinautThrown(th, finalspeed, dir); break; case MT_JAWZ: if (source && source->player) @@ -4784,10 +4780,10 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I } else th->cvmem = SKINCOLOR_KETCHUP; - /* FALLTHRU */ - case MT_JAWZ_DUD: + S_StartSound(th, th->info->activesound); - /* FALLTHRU */ + th->movefactor = finalspeed; + break; case MT_SPB: th->movefactor = finalspeed; break; @@ -5626,12 +5622,12 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, if (dir == -1 && mapthing != MT_SPB) { // Shoot backward - mo = K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) + angleOffset, 0, PROJSPEED/8); + mo = K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) + angleOffset, 0, PROJSPEED / 8, dir); } else { // Shoot forward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + angleOffset, 0, PROJSPEED); + mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + angleOffset, 0, PROJSPEED, dir); } if (mapthing == MT_DROPTARGET && mo) @@ -6402,6 +6398,12 @@ void K_DropHnextList(player_t *player, boolean keepshields) dropwork->health = work->health; // will never be set to 0 as long as above guard exists dropwork->hitlag = work->hitlag; + if (orbit == true) + { + // Projectile item; set fuse + dropwork->fuse = RR_PROJECTILE_FUSE; + } + // Copy interp data dropwork->old_angle = work->old_angle; dropwork->old_x = work->old_x; @@ -6851,8 +6853,11 @@ static void K_MoveHeldObjects(player_t *player) if (!player->mo->hnext) { player->bananadrag = 0; + if (player->pflags & PF_EGGMANOUT) + { player->pflags &= ~PF_EGGMANOUT; + } else if (player->pflags & PF_ITEMOUT) { player->itemamount = 0; @@ -6867,14 +6872,18 @@ static void K_MoveHeldObjects(player_t *player) // we need this here too because this is done in afterthink - pointers are cleaned up at the START of each tic... P_SetTarget(&player->mo->hnext, NULL); player->bananadrag = 0; + if (player->pflags & PF_EGGMANOUT) + { player->pflags &= ~PF_EGGMANOUT; + } else if (player->pflags & PF_ITEMOUT) { player->itemamount = 0; K_UnsetItemOut(player); player->itemtype = KITEM_NONE; } + return; } @@ -6885,80 +6894,9 @@ static void K_MoveHeldObjects(player_t *player) case MT_ORBINAUT_SHIELD: // Kart orbit items case MT_JAWZ_SHIELD: { - mobj_t *cur = player->mo->hnext; - fixed_t speed = ((8 - min(4, player->itemamount)) * cur->info->speed) / 7; - - player->bananadrag = 0; // Just to make sure - - while (cur && !P_MobjWasRemoved(cur)) - { - const fixed_t radius = FixedHypot(player->mo->radius, player->mo->radius) + FixedHypot(cur->radius, cur->radius); // mobj's distance from its Target, or Radius. - fixed_t z; - - if (!cur->health) - { - cur = cur->hnext; - continue; - } - - cur->color = player->skincolor; - - cur->angle -= ANGLE_90; - cur->angle += FixedAngle(speed); - - if (cur->extravalue1 < radius) - cur->extravalue1 += P_AproxDistance(cur->extravalue1, radius) / 12; - if (cur->extravalue1 > radius) - cur->extravalue1 = radius; - - // If the player is on the ceiling, then flip your items as well. - if (player && player->mo->eflags & MFE_VERTICALFLIP) - cur->eflags |= MFE_VERTICALFLIP; - else - cur->eflags &= ~MFE_VERTICALFLIP; - - // Shrink your items if the player shrunk too. - P_SetScale(cur, (cur->destscale = FixedMul(FixedDiv(cur->extravalue1, radius), finalscale))); - - if (P_MobjFlip(cur) > 0) - z = player->mo->z; - else - z = player->mo->z + player->mo->height - cur->height; - - cur->flags |= MF_NOCLIPTHING; // temporarily make them noclip other objects so they can't hit anyone while in the player - P_MoveOrigin(cur, player->mo->x, player->mo->y, z); - cur->momx = FixedMul(FINECOSINE(cur->angle>>ANGLETOFINESHIFT), cur->extravalue1); - cur->momy = FixedMul(FINESINE(cur->angle>>ANGLETOFINESHIFT), cur->extravalue1); - cur->flags &= ~MF_NOCLIPTHING; - - if (!P_TryMove(cur, player->mo->x + cur->momx, player->mo->y + cur->momy, true)) - P_SlideMove(cur); - - if (P_IsObjectOnGround(player->mo)) - { - if (P_MobjFlip(cur) > 0) - { - if (cur->floorz > player->mo->z - cur->height) - z = cur->floorz; - } - else - { - if (cur->ceilingz < player->mo->z + player->mo->height + cur->height) - z = cur->ceilingz - cur->height; - } - } - - // Center it during the scale up animation - z += (FixedMul(mobjinfo[cur->type].height, finalscale - cur->scale)>>1) * P_MobjFlip(cur); - - cur->z = z; - cur->momx = cur->momy = 0; - cur->angle += ANGLE_90; - - cur = cur->hnext; - } + Obj_OrbinautMoveHeld(player); + break; } - break; case MT_BANANA_SHIELD: // Kart trailing items case MT_SSMINE_SHIELD: case MT_DROPTARGET_SHIELD: diff --git a/src/k_kart.h b/src/k_kart.h index b120f0b6c..e501781a2 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -28,6 +28,8 @@ Make sure this matches the actual number of states #define GROW_PHYSICS_SCALE (3*FRACUNIT/2) #define SHRINK_PHYSICS_SCALE (3*FRACUNIT/4) +#define RR_PROJECTILE_FUSE (8*TICRATE) + #define STUMBLE_STEEP_VAL ANG60 #define STUMBLE_STEEP_VAL_AIR (ANG30 + ANG10) diff --git a/src/k_objects.h b/src/k_objects.h index d39da4247..fb674b304 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -29,4 +29,10 @@ void Obj_SPBTouch(mobj_t *spb, mobj_t *toucher); void Obj_MantaRingThink(mobj_t *manta); mobj_t *Obj_MantaRingCreate(mobj_t *spb, mobj_t *owner, mobj_t *chase); +/* Orbinaut */ +void Obj_OrbinautThink(mobj_t *th); +boolean Obj_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2); +void Obj_OrbinautThrown(mobj_t *th, fixed_t finalSpeed, SINT8 dir); +void Obj_OrbinautMoveHeld(player_t *player); + #endif/*k_objects_H*/ diff --git a/src/objects/Sourcefile b/src/objects/Sourcefile index 84e263f29..05555d906 100644 --- a/src/objects/Sourcefile +++ b/src/objects/Sourcefile @@ -3,3 +3,4 @@ shrink.c item-debris.c spb.c manta-ring.c +orbinaut.c diff --git a/src/objects/orbinaut.c b/src/objects/orbinaut.c new file mode 100644 index 000000000..16798aea3 --- /dev/null +++ b/src/objects/orbinaut.c @@ -0,0 +1,377 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2022 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file orbinaut.c +/// \brief Orbinaut item code. + +#include "../doomdef.h" +#include "../doomstat.h" +#include "../info.h" +#include "../k_kart.h" +#include "../k_objects.h" +#include "../m_random.h" +#include "../p_local.h" +#include "../r_main.h" +#include "../s_sound.h" +#include "../g_game.h" +#include "../z_zone.h" +#include "../k_waypoint.h" +#include "../k_respawn.h" +#include "../k_collide.h" + +#define ORBINAUT_MAXTURN (ANGLE_67h) +#define ORBINAUT_TURNLERP (16) + +#define orbinaut_speed(o) ((o)->movefactor) +#define orbinaut_selfdelay(o) ((o)->threshold) +#define orbinaut_dropped(o) ((o)->flags2 & MF2_AMBUSH) +#define orbinaut_droptime(o) ((o)->movecount) + +#define orbinaut_turn(o) ((o)->extravalue1) + +#define orbinaut_owner(o) ((o)->target) +#define orbinaut_center(o) ((o)->tracer) + +#define orbinaut_shield_dist(o) ((o)->extravalue1) + +void Obj_OrbinautThink(mobj_t *th) +{ + boolean grounded = P_IsObjectOnGround(th); + mobj_t *ghost = NULL; + + if (th->fuse <= TICRATE) + { + th->renderflags ^= RF_DONTDRAW; + } + + if (orbinaut_dropped(th)) + { + if (grounded && (th->flags & MF_NOCLIPTHING)) + { + th->momx = 1; + th->momy = 0; + th->frame = 3; + S_StartSound(th, th->info->activesound); + th->flags &= ~MF_NOCLIPTHING; + } + else if (orbinaut_droptime(th)) + { + orbinaut_droptime(th)--; + } + else if (th->frame < 3) + { + orbinaut_droptime(th) = 2; + th->frame++; + } + + return; + } + + ghost = P_SpawnGhostMobj(th); + ghost->colorized = true; // already has color! + + th->angle = K_MomentumAngle(th); + if (orbinaut_turn(th) != 0) + { + th->angle += orbinaut_turn(th); + + if (abs(orbinaut_turn(th)) < ORBINAUT_MAXTURN) + { + if (orbinaut_turn(th) < 0) + { + orbinaut_turn(th) -= ORBINAUT_MAXTURN / ORBINAUT_TURNLERP; + } + else + { + orbinaut_turn(th) += ORBINAUT_MAXTURN / ORBINAUT_TURNLERP; + } + } + } + + if (grounded == true) + { + fixed_t finalspeed = orbinaut_speed(th); + const fixed_t currentspeed = R_PointToDist2(0, 0, th->momx, th->momy); + fixed_t thrustamount = 0; + fixed_t frictionsafety = (th->friction == 0) ? 1 : th->friction; + + if (th->health <= 5) + { + INT32 i; + for (i = 5; i >= th->health; i--) + { + finalspeed = FixedMul(finalspeed, FRACUNIT-FRACUNIT/4); + } + } + + if (currentspeed >= finalspeed) + { + // Thrust as if you were at top speed, slow down naturally + thrustamount = FixedDiv(finalspeed, frictionsafety) - finalspeed; + } + else + { + const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; + // Thrust to immediately get to top speed + thrustamount = beatfriction + FixedDiv(finalspeed - currentspeed, frictionsafety); + } + + P_Thrust(th, th->angle, thrustamount); + } + + if (P_MobjTouchingSectorSpecial(th, 3, 1, true)) + { + K_DoPogoSpring(th, 0, 1); + } + + if (orbinaut_selfdelay(th) > 0) + { + orbinaut_selfdelay(th)--; + } + + if (leveltime % 6 == 0) + { + S_StartSound(th, th->info->activesound); + } +} + +boolean Obj_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) +{ + boolean damageitem = false; + boolean sprung = false; + + if ((orbinaut_selfdelay(t1) > 0 && t2->hitlag > 0) + || (orbinaut_selfdelay(t2) > 0 && t1->hitlag > 0)) + { + return true; + } + + if (t1->health <= 0 || t2->health <= 0) + { + return true; + } + + if ((orbinaut_owner(t1) == t2) + || (!(t2->flags & (MF_ENEMY|MF_BOSS)) && (orbinaut_owner(t1) == t2->target))) + { + if ((orbinaut_selfdelay(t1) > 0 && t2->type == MT_PLAYER) + || (orbinaut_selfdelay(t2) > 0 && t2->type != MT_PLAYER)) + { + return true; + } + } + + if ((t1->type == MT_ORBINAUT_SHIELD || t1->type == MT_JAWZ_SHIELD) && t1->lastlook + && (t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD) && t2->lastlook + && (orbinaut_owner(t1) == t2->target)) // Don't hit each other if you have the same target + { + return true; + } + + if (t2->player) + { + if ((t2->player->flashing > 0 && t2->hitlag == 0) + && !(t1->type == MT_ORBINAUT || t1->type == MT_JAWZ || t1->type == MT_JAWZ_DUD)) + return true; + + if (t2->player->hyudorotimer) + return true; // no interaction + + if (t2->player->flamedash && t2->player->itemtype == KITEM_FLAMESHIELD) + { + // Melt item + S_StartSound(t2, sfx_s3k43); + } + else + { + // Player Damage + P_DamageMobj(t2, t1, t1->target, 1, DMG_WIPEOUT|DMG_WOMBO); + K_KartBouncing(t2, t1); + S_StartSound(t2, sfx_s3k7b); + } + + damageitem = true; + } + else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD + || t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD + || t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD + || t2->type == MT_BALLHOG) + { + // Other Item Damage + angle_t bounceangle = K_GetCollideAngle(t1, t2); + + S_StartSound(t2, t2->info->deathsound); + P_KillMobj(t2, t1, t1, DMG_NORMAL); + + P_SetObjectMomZ(t2, 8*FRACUNIT, false); + P_InstaThrust(t2, bounceangle, 16*FRACUNIT); + + P_SpawnMobj(t2->x/2 + t1->x/2, t2->y/2 + t1->y/2, t2->z/2 + t1->z/2, MT_ITEMCLASH); + + damageitem = true; + } + else if (t2->type == MT_SSMINE_SHIELD || t2->type == MT_SSMINE || t2->type == MT_LANDMINE) + { + damageitem = true; + // Bomb death + P_KillMobj(t2, t1, t1, DMG_NORMAL); + } + else if (t2->flags & MF_SPRING && (t1->type != MT_ORBINAUT_SHIELD && t1->type != MT_JAWZ_SHIELD)) + { + // Let thrown items hit springs! + sprung = P_DoSpring(t2, t1); + } + else if (t2->flags & MF_SHOOTABLE) + { + // Shootable damage + P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL); + damageitem = true; + } + + if (damageitem) + { + // This Item Damage + angle_t bounceangle = K_GetCollideAngle(t2, t1); + S_StartSound(t1, t1->info->deathsound); + P_KillMobj(t1, t2, t2, DMG_NORMAL); + + P_SetObjectMomZ(t1, 8*FRACUNIT, false); + P_InstaThrust(t1, bounceangle, 16*FRACUNIT); + } + + if (sprung) + { + return false; + } + + return true; +} + +void Obj_OrbinautThrown(mobj_t *th, fixed_t finalSpeed, SINT8 dir) +{ + if (orbinaut_owner(th) != NULL && P_MobjWasRemoved(orbinaut_owner(th)) == false + && orbinaut_owner(th)->player != NULL) + { + th->color = orbinaut_owner(th)->player->skincolor; + } + else + { + th->color = SKINCOLOR_GREY; + } + + th->fuse = RR_PROJECTILE_FUSE; + orbinaut_speed(th) = finalSpeed; + + if (dir == -1) + { + // Thrown backwards, init orbiting in place + orbinaut_turn(th) = ORBINAUT_MAXTURN / ORBINAUT_TURNLERP; + + th->angle -= ANGLE_45; + th->momx = FixedMul(finalSpeed, FINECOSINE(th->angle >> ANGLETOFINESHIFT)); + th->momy = FixedMul(finalSpeed, FINESINE(th->angle >> ANGLETOFINESHIFT)); + } +} + +void Obj_OrbinautMoveHeld(player_t *player) +{ + fixed_t finalscale = K_ItemScaleForPlayer(player); + mobj_t *cur = player->mo->hnext; + fixed_t speed = ((8 - min(4, player->itemamount)) * cur->info->speed) / 7; + + player->bananadrag = 0; // Just to make sure + + while (cur && !P_MobjWasRemoved(cur)) + { + const fixed_t radius = FixedHypot(player->mo->radius, player->mo->radius) + FixedHypot(cur->radius, cur->radius); // mobj's distance from its Target, or Radius. + fixed_t z; + + if (!cur->health) + { + cur = cur->hnext; + continue; + } + + cur->color = player->skincolor; + + cur->angle -= ANGLE_90; + cur->angle += FixedAngle(speed); + + if (orbinaut_shield_dist(cur) < radius) + { + orbinaut_shield_dist(cur) += P_AproxDistance(orbinaut_shield_dist(cur), radius) / 12; + } + + if (orbinaut_shield_dist(cur) > radius) + { + orbinaut_shield_dist(cur) = radius; + } + + // If the player is on the ceiling, then flip your items as well. + if (player && player->mo->eflags & MFE_VERTICALFLIP) + { + cur->eflags |= MFE_VERTICALFLIP; + } + else + { + cur->eflags &= ~MFE_VERTICALFLIP; + } + + // Shrink your items if the player shrunk too. + cur->destscale = FixedMul(FixedDiv(orbinaut_shield_dist(cur), radius), finalscale); + P_SetScale(cur, cur->destscale); + + if (P_MobjFlip(cur) > 0) + { + z = player->mo->z; + } + else + { + z = player->mo->z + player->mo->height - cur->height; + } + + cur->flags |= MF_NOCLIPTHING; // temporarily make them noclip other objects so they can't hit anyone while in the player + P_MoveOrigin(cur, player->mo->x, player->mo->y, z); + cur->momx = FixedMul(FINECOSINE(cur->angle >> ANGLETOFINESHIFT), orbinaut_shield_dist(cur)); + cur->momy = FixedMul(FINESINE(cur->angle >> ANGLETOFINESHIFT), orbinaut_shield_dist(cur)); + cur->flags &= ~MF_NOCLIPTHING; + + if (!P_TryMove(cur, player->mo->x + cur->momx, player->mo->y + cur->momy, true)) + { + P_SlideMove(cur); + } + + if (P_IsObjectOnGround(player->mo)) + { + if (P_MobjFlip(cur) > 0) + { + if (cur->floorz > player->mo->z - cur->height) + { + z = cur->floorz; + } + } + else + { + if (cur->ceilingz < player->mo->z + player->mo->height + cur->height) + { + z = cur->ceilingz - cur->height; + } + } + } + + // Center it during the scale up animation + z += (FixedMul(cur->info->height, finalscale - cur->scale) >> 1) * P_MobjFlip(cur); + + cur->z = z; + cur->momx = cur->momy = 0; + cur->angle += ANGLE_90; + + cur = cur->hnext; + } +} diff --git a/src/p_map.c b/src/p_map.c index 619f8698a..e5882d47f 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -940,7 +940,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_OrbinautJawzCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; + return Obj_OrbinautJawzCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD || thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD) @@ -951,7 +951,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return BMIT_CONTINUE; // underneath - return K_OrbinautJawzCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; + return Obj_OrbinautJawzCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; } if (tmthing->type == MT_BANANA || tmthing->type == MT_BANANA_SHIELD || tmthing->type == MT_BALLHOG) diff --git a/src/p_mobj.c b/src/p_mobj.c index 034d9c6e0..e39ab6aaa 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6712,77 +6712,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) break; case MT_ORBINAUT: { - boolean grounded = P_IsObjectOnGround(mobj); - - if (mobj->flags2 & MF2_AMBUSH) - { - if (grounded && (mobj->flags & MF_NOCLIPTHING)) - { - mobj->momx = 1; - mobj->momy = 0; - mobj->frame = 3; - S_StartSound(mobj, mobj->info->activesound); - mobj->flags &= ~MF_NOCLIPTHING; - } - else if (mobj->movecount) - mobj->movecount--; - else if (mobj->frame < 3) - { - mobj->movecount = 2; - mobj->frame++; - } - } - else - { - mobj_t *ghost = P_SpawnGhostMobj(mobj); - ghost->colorized = true; // already has color! - - mobj->angle = K_MomentumAngle(mobj); - - if (P_IsObjectOnGround(mobj)) - { - fixed_t finalspeed = mobj->movefactor; - const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); - fixed_t thrustamount = 0; - fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; - - if (!grounded) - { - // No friction in the air - frictionsafety = FRACUNIT; - } - - if (mobj->health <= 5) - { - INT32 i; - for (i = 5; i >= mobj->health; i--) - finalspeed = FixedMul(finalspeed, FRACUNIT-FRACUNIT/4); - } - - if (currentspeed >= finalspeed) - { - // Thrust as if you were at top speed, slow down naturally - thrustamount = FixedDiv(finalspeed, frictionsafety) - finalspeed; - } - else - { - const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; - // Thrust to immediately get to top speed - thrustamount = beatfriction + FixedDiv(finalspeed - currentspeed, frictionsafety); - } - - P_Thrust(mobj, mobj->angle, thrustamount); - } - - if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true)) - K_DoPogoSpring(mobj, 0, 1); - - if (mobj->threshold > 0) - mobj->threshold--; - - if (leveltime % 6 == 0) - S_StartSound(mobj, mobj->info->activesound); - } + Obj_OrbinautThink(mobj); break; } case MT_JAWZ: From b0e38405500b766bc28585419d5f03f79dc697ac Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 25 Sep 2022 11:27:07 -0400 Subject: [PATCH 2/7] Add jawz.c + new backwards behavior --- src/deh_tables.c | 10 -- src/info.c | 52 ++------ src/info.h | 11 -- src/k_botsearch.c | 1 - src/k_collide.c | 6 +- src/k_kart.c | 166 ++++++++++++------------- src/k_kart.h | 2 +- src/k_objects.h | 6 +- src/lua_baselib.c | 2 +- src/objects/Sourcefile | 1 + src/objects/jawz.c | 269 +++++++++++++++++++++++++++++++++++++++++ src/objects/orbinaut.c | 9 +- src/p_enemy.c | 127 ------------------- src/p_inter.c | 4 +- src/p_map.c | 12 +- src/p_mobj.c | 94 +------------- 16 files changed, 388 insertions(+), 384 deletions(-) create mode 100644 src/objects/jawz.c diff --git a/src/deh_tables.c b/src/deh_tables.c index 5f1c88826..a22b2f50a 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -320,7 +320,6 @@ actionpointer_t actionpointers[] = // SRB2Kart {{A_ItemPop}, "A_ITEMPOP"}, - {{A_JawzChase}, "A_JAWZCHASE"}, {{A_JawzExplode}, "A_JAWZEXPLODE"}, {{A_SSMineSearch}, "A_SSMINESEARCH"}, {{A_SSMineExplode}, "A_SSMINEEXPLODE"}, @@ -3523,14 +3522,6 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_JAWZ6", "S_JAWZ7", "S_JAWZ8", - "S_JAWZ_DUD1", - "S_JAWZ_DUD2", - "S_JAWZ_DUD3", - "S_JAWZ_DUD4", - "S_JAWZ_DUD5", - "S_JAWZ_DUD6", - "S_JAWZ_DUD7", - "S_JAWZ_DUD8", "S_JAWZ_SHIELD1", "S_JAWZ_SHIELD2", "S_JAWZ_SHIELD3", @@ -5337,7 +5328,6 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_ORBINAUT_SHIELD", "MT_JAWZ", // Jawz stuff - "MT_JAWZ_DUD", "MT_JAWZ_SHIELD", "MT_PLAYERRETICULE", // Jawz reticule diff --git a/src/info.c b/src/info.c index 947b06701..794b147d7 100644 --- a/src/info.c +++ b/src/info.c @@ -4091,23 +4091,14 @@ state_t states[NUMSTATES] = {SPR_ORBN, 11, 3, {NULL}, 0, 0, S_ORBINAUT_SHIELD1}, // S_ORBINAUT_SHIELD6 {SPR_ORBN, 6, 175, {NULL}, 0, 0, S_NULL}, // S_ORBINAUT_SHIELDDEAD - {SPR_JAWZ, 0, 1, {A_JawzChase}, 0, 0, S_JAWZ2}, // S_JAWZ1 - {SPR_JAWZ, 4, 1, {A_JawzChase}, 0, 0, S_JAWZ3}, // S_JAWZ2 - {SPR_JAWZ, 1, 1, {A_JawzChase}, 0, 0, S_JAWZ4}, // S_JAWZ3 - {SPR_JAWZ, 4, 1, {A_JawzChase}, 0, 0, S_JAWZ5}, // S_JAWZ4 - {SPR_JAWZ, 2, 1, {A_JawzChase}, 0, 0, S_JAWZ6}, // S_JAWZ5 - {SPR_JAWZ, 4, 1, {A_JawzChase}, 0, 0, S_JAWZ7}, // S_JAWZ6 - {SPR_JAWZ, 3, 1, {A_JawzChase}, 0, 0, S_JAWZ8}, // S_JAWZ7 - {SPR_JAWZ, 4, 1, {A_JawzChase}, 0, 0, S_JAWZ1}, // S_JAWZ8 - - {SPR_JAWZ, 0, 1, {NULL}, 0, 0, S_JAWZ_DUD2}, // S_JAWZ_DUD1 - {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_DUD3}, // S_JAWZ_DUD2 - {SPR_JAWZ, 1, 1, {NULL}, 0, 0, S_JAWZ_DUD4}, // S_JAWZ_DUD3 - {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_DUD5}, // S_JAWZ_DUD4 - {SPR_JAWZ, 2, 1, {NULL}, 0, 0, S_JAWZ_DUD6}, // S_JAWZ_DUD5 - {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_DUD7}, // S_JAWZ_DUD6 - {SPR_JAWZ, 3, 1, {NULL}, 0, 0, S_JAWZ_DUD8}, // S_JAWZ_DUD7 - {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_DUD1}, // S_JAWZ_DUD8 + {SPR_JAWZ, 0, 1, {NULL}, 0, 0, S_JAWZ2}, // S_JAWZ1 + {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ3}, // S_JAWZ2 + {SPR_JAWZ, 1, 1, {NULL}, 0, 0, S_JAWZ4}, // S_JAWZ3 + {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ5}, // S_JAWZ4 + {SPR_JAWZ, 2, 1, {NULL}, 0, 0, S_JAWZ6}, // S_JAWZ5 + {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ7}, // S_JAWZ6 + {SPR_JAWZ, 3, 1, {NULL}, 0, 0, S_JAWZ8}, // S_JAWZ7 + {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ1}, // S_JAWZ8 {SPR_JAWZ, 0, 1, {NULL}, 0, 0, S_JAWZ_SHIELD2}, // S_JAWZ_SHIELD1 {SPR_JAWZ, 4, 1, {NULL}, 0, 0, S_JAWZ_SHIELD3}, // S_JAWZ_SHIELD2 @@ -23506,33 +23497,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_JAWZ_DUD - -1, // doomednum - S_JAWZ_DUD1, // spawnstate - 1, // spawnhealth - S_NULL, // seestate - sfx_tossed, // seesound - 8, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate - S_JAWZ_DEAD1, // deathstate - S_JAWZ_DEAD2, // xdeathstate - sfx_s3k5d, // deathsound - 64*FRACUNIT, // speed - 16*FRACUNIT, // radius - 32*FRACUNIT, // height - 0, // display offset - 100, // mass - 1, // damage - sfx_s3kc0s, // activesound - MF_SHOOTABLE|MF_DONTENCOREMAP, // flags - S_NULL // raisestate - }, - { // MT_JAWZ_SHIELD -1, // doomednum S_JAWZ_SHIELD1, // spawnstate diff --git a/src/info.h b/src/info.h index 426963709..b05a7034b 100644 --- a/src/info.h +++ b/src/info.h @@ -273,7 +273,6 @@ enum actionnum A_DRAGONSEGMENT, A_CHANGEHEIGHT, A_ITEMPOP, - A_JAWZCHASE, A_JAWZEXPLODE, A_SSMINESEARCH, A_SSMINEEXPLODE, @@ -545,7 +544,6 @@ void A_ChangeHeight(); // SRB2Kart // void A_ItemPop(); -void A_JawzChase(); void A_JawzExplode(); void A_SSMineSearch(); void A_SSMineExplode(); @@ -4522,14 +4520,6 @@ typedef enum state S_JAWZ6, S_JAWZ7, S_JAWZ8, - S_JAWZ_DUD1, - S_JAWZ_DUD2, - S_JAWZ_DUD3, - S_JAWZ_DUD4, - S_JAWZ_DUD5, - S_JAWZ_DUD6, - S_JAWZ_DUD7, - S_JAWZ_DUD8, S_JAWZ_SHIELD1, S_JAWZ_SHIELD2, S_JAWZ_SHIELD3, @@ -6372,7 +6362,6 @@ typedef enum mobj_type MT_ORBINAUT_SHIELD, MT_JAWZ, // Jawz stuff - MT_JAWZ_DUD, MT_JAWZ_SHIELD, MT_PLAYERRETICULE, // Jawz reticule diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 26fc9f73d..5b6f1ccca 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -413,7 +413,6 @@ static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing) case MT_ORBINAUT: case MT_ORBINAUT_SHIELD: case MT_JAWZ: - case MT_JAWZ_DUD: case MT_JAWZ_SHIELD: case MT_SSMINE: case MT_SSMINE_SHIELD: diff --git a/src/k_collide.c b/src/k_collide.c index a95f77dc3..e4a536403 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -80,7 +80,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2) } else if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD || t2->type == MT_ORBINAUT || t2->type == MT_ORBINAUT_SHIELD - || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD || t2->type == MT_JAWZ_SHIELD + || t2->type == MT_JAWZ || t2->type == MT_JAWZ_SHIELD || t2->type == MT_BALLHOG) { // Other Item Damage @@ -334,7 +334,7 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2) K_PuntMine(t1, t2); } } - else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD + else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD) { // Bomb death @@ -395,7 +395,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2) } else if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD || t2->type == MT_ORBINAUT || t2->type == MT_ORBINAUT_SHIELD - || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD || t2->type == MT_JAWZ_SHIELD + || t2->type == MT_JAWZ || t2->type == MT_JAWZ_SHIELD || t2->type == MT_BALLHOG) { // Other Item Damage diff --git a/src/k_kart.c b/src/k_kart.c index 54309a9c4..04752dcb7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1421,7 +1421,6 @@ fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) weight = K_PlayerWeight(against, NULL); break; case MT_JAWZ: - case MT_JAWZ_DUD: case MT_JAWZ_SHIELD: if (against->player) weight = K_PlayerWeight(against, NULL) + (3*FRACUNIT); @@ -4712,6 +4711,12 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I finalscale = source->scale; } + if (dir == -1 && (type == MT_ORBINAUT || type == MT_BALLHOG)) + { + // Backwards nerfs + finalspeed /= 8; + } + x = source->x + source->momx + FixedMul(finalspeed, FINECOSINE(an>>ANGLETOFINESHIFT)); y = source->y + source->momy + FixedMul(finalspeed, FINESINE(an>>ANGLETOFINESHIFT)); z = source->z; // spawn on the ground please @@ -4766,23 +4771,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I Obj_OrbinautThrown(th, finalspeed, dir); break; case MT_JAWZ: - if (source && source->player) - { - INT32 lasttarg = source->player->lastjawztarget; - th->cvmem = source->player->skincolor; - if ((lasttarg >= 0 && lasttarg < MAXPLAYERS) - && playeringame[lasttarg] - && !players[lasttarg].spectator - && players[lasttarg].mo) - { - P_SetTarget(&th->tracer, players[lasttarg].mo); - } - } - else - th->cvmem = SKINCOLOR_KETCHUP; - - S_StartSound(th, th->info->activesound); - th->movefactor = finalspeed; + Obj_JawzThrown(th, finalspeed, dir); break; case MT_SPB: th->movefactor = finalspeed; @@ -5622,12 +5611,12 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, if (dir == -1 && mapthing != MT_SPB) { // Shoot backward - mo = K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) + angleOffset, 0, PROJSPEED / 8, dir); + mo = K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) + angleOffset, 0, PROJSPEED, -1); } else { // Shoot forward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + angleOffset, 0, PROJSPEED, dir); + mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + angleOffset, 0, PROJSPEED, 1); } if (mapthing == MT_DROPTARGET && mo) @@ -6341,7 +6330,7 @@ void K_DropHnextList(player_t *player, boolean keepshields) break; case MT_JAWZ_SHIELD: orbit = true; - type = MT_JAWZ_DUD; + type = MT_JAWZ; break; // Kart trailing items case MT_BANANA_SHIELD: @@ -6465,7 +6454,7 @@ void K_DropHnextList(player_t *player, boolean keepshields) dropwork->tics = -1; - if (type == MT_JAWZ_DUD) + if (type == MT_JAWZ) { dropwork->z += 20*flip*dropwork->scale; } @@ -6894,7 +6883,7 @@ static void K_MoveHeldObjects(player_t *player) case MT_ORBINAUT_SHIELD: // Kart orbit items case MT_JAWZ_SHIELD: { - Obj_OrbinautMoveHeld(player); + Obj_OrbinautJawzMoveHeld(player); break; } case MT_BANANA_SHIELD: // Kart trailing items @@ -7106,95 +7095,111 @@ static void K_MoveHeldObjects(player_t *player) } } -player_t *K_FindJawzTarget(mobj_t *actor, player_t *source) +player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range) { - fixed_t best = -1; + fixed_t best = INT32_MAX; player_t *wtarg = NULL; INT32 i; for (i = 0; i < MAXPLAYERS; i++) { - angle_t thisang; - player_t *player; + angle_t thisang = ANGLE_MAX; + fixed_t thisdist = INT32_MAX; + fixed_t thisScore = INT32_MAX; + player_t *player = NULL; - if (!playeringame[i]) + if (playeringame[i] == false) + { 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) + if (player->spectator) + { + // Spectators continue; + } - // Invisible, don't bother - if (player->hyudorotimer) + if (player->mo == NULL || P_MobjWasRemoved(player->mo) == true) + { + // Invalid mobj 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 (player->mo->health <= 0) + { + // dead + continue; + } + + if (G_GametypeHasTeams() && source != NULL && source->ctfteam == player->ctfteam) + { + // Don't home in on teammates. + continue; + } + + if (player->hyudorotimer > 0) + { + // Invisible player + continue; + } - // Jawz only go after the person directly ahead of you in race... sort of literally now! if (gametyperules & GTR_CIRCUIT) { - // Don't go for people who are behind you - if (thisang > ANGLE_67h) - continue; - // Don't pay attention to people who aren't above your position - if (player->position >= source->position) - continue; - if ((best == -1) || (player->position > best)) + if (player->position > source->position) { - wtarg = player; - best = player->position; + // Don't pay attention to people who aren't above your position + continue; } } else { - fixed_t thisdist; - fixed_t thisavg; - - // Don't go for people who are behind you - if (thisang > ANGLE_45) - continue; - - // Don't pay attention to dead players if (player->bumpers <= 0) + { + // Don't pay attention to dead players continue; + } // Z pos too high/low if (abs(player->mo->z - (actor->z + actor->momz)) > RING_DIST/8) - continue; - - thisdist = P_AproxDistance(player->mo->x - (actor->x + actor->momx), player->mo->y - (actor->y + actor->momy)); - - if (thisdist > 2*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; + continue; } } + + // Find the angle, see who's got the best. + thisang = AngleDelta(actor->angle, R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y)); + + // Don't go for people who are behind you + if (thisang > range) + { + continue; + } + + thisdist = P_AproxDistance(player->mo->x - (actor->x + actor->momx), player->mo->y - (actor->y + actor->momy)); + + // Don't go for people who are too far away + if (thisdist > 2*RING_DIST) + { + continue; + } + + thisScore = (AngleFixed(thisang) * 2) + (thisdist / 2); + + //CONS_Printf("got score %f from player # %d\n", FixedToFloat(thisScore), i); + + if (thisScore < best) + { + wtarg = player; + best = thisScore; + } } return wtarg; @@ -8274,7 +8279,7 @@ void K_KartPlayerAfterThink(player_t *player) player->jawztargetdelay--; } else - targ = K_FindJawzTarget(player->mo, player); + targ = K_FindJawzTarget(player->mo, player, ANGLE_45); if (!targ || !targ->mo || P_MobjWasRemoved(targ->mo)) { @@ -10295,10 +10300,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } else if (ATTACK_IS_DOWN && HOLDING_ITEM && (player->pflags & PF_ITEMOUT)) // Jawz thrown { - if (player->throwdir == 1 || player->throwdir == 0) - K_ThrowKartItem(player, true, MT_JAWZ, 1, 0, 0); - else if (player->throwdir == -1) // Throwing backward gives you a dud that doesn't home in - K_ThrowKartItem(player, true, MT_JAWZ_DUD, -1, 0, 0); + K_ThrowKartItem(player, true, MT_JAWZ, 1, 0, 0); K_PlayAttackTaunt(player->mo); player->itemamount--; K_UpdateHnextList(player, false); diff --git a/src/k_kart.h b/src/k_kart.h index e501781a2..1c75288e5 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -118,7 +118,7 @@ void K_UpdateHnextList(player_t *player, boolean clean); void K_DropHnextList(player_t *player, boolean keepshields); void K_RepairOrbitChain(mobj_t *orbit); void K_CalculateBananaSlope(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player); -player_t *K_FindJawzTarget(mobj_t *actor, player_t *source); +player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range); INT32 K_GetKartRingPower(player_t *player, boolean boosted); void K_UpdateDistanceFromFinishLine(player_t *const player); boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); diff --git a/src/k_objects.h b/src/k_objects.h index fb674b304..7679db658 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -33,6 +33,10 @@ mobj_t *Obj_MantaRingCreate(mobj_t *spb, mobj_t *owner, mobj_t *chase); void Obj_OrbinautThink(mobj_t *th); boolean Obj_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2); void Obj_OrbinautThrown(mobj_t *th, fixed_t finalSpeed, SINT8 dir); -void Obj_OrbinautMoveHeld(player_t *player); +void Obj_OrbinautJawzMoveHeld(player_t *player); + +/* Jawz */ +void Obj_JawzThink(mobj_t *th); +void Obj_JawzThrown(mobj_t *th, fixed_t finalSpeed, SINT8 dir); #endif/*k_objects_H*/ diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 190a7f701..f63bb85ef 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3651,7 +3651,7 @@ static int lib_kFindJawzTarget(lua_State *L) return LUA_ErrInvalid(L, "mobj_t"); if (!source) return LUA_ErrInvalid(L, "player_t"); - LUA_PushUserdata(L, K_FindJawzTarget(actor, source), META_PLAYER); + LUA_PushUserdata(L, K_FindJawzTarget(actor, source, ANGLE_45), META_PLAYER); return 1; } diff --git a/src/objects/Sourcefile b/src/objects/Sourcefile index 05555d906..339175b0c 100644 --- a/src/objects/Sourcefile +++ b/src/objects/Sourcefile @@ -4,3 +4,4 @@ item-debris.c spb.c manta-ring.c orbinaut.c +jawz.c diff --git a/src/objects/jawz.c b/src/objects/jawz.c new file mode 100644 index 000000000..0ab8b6c67 --- /dev/null +++ b/src/objects/jawz.c @@ -0,0 +1,269 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2022 by Kart Krew +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file jawz.c +/// \brief Jawz item code. + +#include "../doomdef.h" +#include "../doomstat.h" +#include "../info.h" +#include "../k_kart.h" +#include "../k_objects.h" +#include "../m_random.h" +#include "../p_local.h" +#include "../r_main.h" +#include "../s_sound.h" +#include "../g_game.h" +#include "../z_zone.h" +#include "../k_waypoint.h" +#include "../k_respawn.h" +#include "../k_collide.h" + +#define MAX_JAWZ_TURN (ANGLE_90 / 15) // We can turn a maximum of 6 degrees per frame at regular max speed + +#define jawz_speed(o) ((o)->movefactor) +#define jawz_selfdelay(o) ((o)->threshold) +#define jawz_dropped(o) ((o)->flags2 & MF2_AMBUSH) +#define jawz_droptime(o) ((o)->movecount) + +#define jawz_retcolor(o) ((o)->cvmem) + +#define jawz_owner(o) ((o)->target) +#define jawz_chase(o) ((o)->tracer) + +#define jawz_shield_dist(o) ((o)->extravalue1) + +static void JawzChase(mobj_t *th, boolean grounded) +{ + fixed_t thrustamount = 0; + fixed_t frictionsafety = (th->friction == 0) ? 1 : th->friction; + fixed_t topspeed = jawz_speed(th); + + if (jawz_chase(th) != NULL && P_MobjWasRemoved(jawz_chase(th)) == false) + { + if (jawz_chase(th)->health > 0) + { + const angle_t targetangle = R_PointToAngle2( + th->x, th->y, + jawz_chase(th)->x, jawz_chase(th)->y + ); + angle_t angledelta = th->angle - targetangle; + mobj_t *ret = NULL; + + if (gametyperules & GTR_CIRCUIT) + { + const fixed_t distbarrier = FixedMul( + 512 * mapobjectscale, + FRACUNIT + ((gamespeed-1) * (FRACUNIT/4)) + ); + + const fixed_t distaway = P_AproxDistance( + jawz_chase(th)->x - th->x, + jawz_chase(th)->y - th->y + ); + + if (distaway < distbarrier) + { + if (jawz_chase(th)->player != NULL) + { + fixed_t speeddifference = abs( + topspeed - min( + jawz_chase(th)->player->speed, + K_GetKartSpeed(jawz_chase(th)->player, false, false) + ) + ); + + topspeed = topspeed - FixedMul(speeddifference, FRACUNIT - FixedDiv(distaway, distbarrier)); + } + } + } + + if (angledelta != 0) + { + angle_t turnSpeed = MAX_JAWZ_TURN; + boolean turnclockwise = true; + + // MAX_JAWZ_TURN gets stronger the slower the top speed of jawz + if (topspeed < jawz_speed(th)) + { + if (topspeed == 0) + { + turnSpeed = ANGLE_180; + } + else + { + fixed_t anglemultiplier = FixedDiv(jawz_speed(th), topspeed); + turnSpeed += FixedAngle(FixedMul(AngleFixed(turnSpeed), anglemultiplier)); + } + } + + if (angledelta > ANGLE_180) + { + angledelta = InvAngle(angledelta); + turnclockwise = false; + } + + if (angledelta > turnSpeed) + { + angledelta = turnSpeed; + } + + if (turnclockwise == true) + { + th->angle -= angledelta; + } + else + { + th->angle += angledelta; + } + } + + ret = P_SpawnMobjFromMobj(jawz_chase(th), 0, 0, 0, MT_PLAYERRETICULE); + ret->old_x = jawz_chase(th)->old_x; + ret->old_y = jawz_chase(th)->old_y; + ret->old_z = jawz_chase(th)->old_z; + P_SetTarget(&ret->target, jawz_chase(th)); + ret->frame |= ((leveltime % 10) / 2) + 5; + ret->color = jawz_retcolor(th); + } + else + { + P_SetTarget(&jawz_chase(th), NULL); + } + } + + if (jawz_chase(th) == NULL || P_MobjWasRemoved(jawz_chase(th)) == true) + { + th->angle = K_MomentumAngle(th); + + if (jawz_owner(th) != NULL && P_MobjWasRemoved(jawz_owner(th)) == false + && jawz_owner(th)->player != NULL) + { + player_t *newPlayer = K_FindJawzTarget(th, jawz_owner(th)->player, ANGLE_90); + + if (newPlayer != NULL) + { + P_SetTarget(&jawz_chase(th), newPlayer->mo); + } + } + } + + if (grounded == true) + { + const fixed_t currentspeed = R_PointToDist2(0, 0, th->momx, th->momy); + + if (currentspeed >= topspeed) + { + // Thrust as if you were at top speed, slow down naturally + thrustamount = FixedDiv(topspeed, frictionsafety) - topspeed; + } + else + { + const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; + // Thrust to immediately get to top speed + thrustamount = beatfriction + FixedDiv(topspeed - currentspeed, frictionsafety); + } + + P_Thrust(th, th->angle, thrustamount); + } +} + +void Obj_JawzThink(mobj_t *th) +{ + mobj_t *ghost = P_SpawnGhostMobj(th); + boolean grounded = P_IsObjectOnGround(th); + + if (th->fuse > 0 && th->fuse <= TICRATE) + { + th->renderflags ^= RF_DONTDRAW; + } + + if (jawz_dropped(th)) + { + if (grounded && (th->flags & MF_NOCLIPTHING)) + { + th->momx = 1; + th->momy = 0; + S_StartSound(th, th->info->deathsound); + th->flags &= ~MF_NOCLIPTHING; + } + + return; + } + + if (jawz_owner(th) != NULL && P_MobjWasRemoved(jawz_owner(th)) == false + && jawz_owner(th)->player != NULL) + { + ghost->color = jawz_owner(th)->player->skincolor; + ghost->colorized = true; + } + + if (!(gametyperules & GTR_CIRCUIT)) + { + th->friction = max(0, 3 * th->friction / 4); + } + + JawzChase(th, grounded); + K_DriftDustHandling(th); + + if (P_MobjTouchingSectorSpecial(th, 3, 1, true)) + { + K_DoPogoSpring(th, 0, 1); + } + + if (jawz_selfdelay(th) > 0) + { + jawz_selfdelay(th)--; + } + + if (leveltime % TICRATE == 0) + { + S_StartSound(th, th->info->activesound); + } +} + +void Obj_JawzThrown(mobj_t *th, fixed_t finalSpeed, SINT8 dir) +{ + INT32 lastTarg = -1; + + if (jawz_owner(th) != NULL && P_MobjWasRemoved(jawz_owner(th)) == false + && jawz_owner(th)->player != NULL) + { + lastTarg = jawz_owner(th)->player->lastjawztarget; + jawz_retcolor(th) = jawz_owner(th)->player->skincolor; + } + else + { + jawz_retcolor(th) = SKINCOLOR_KETCHUP; + } + + if (dir == -1) + { + // Thrown backwards, init self-chase + P_SetTarget(&jawz_chase(th), jawz_owner(th)); + th->fuse = RR_PROJECTILE_FUSE; + finalSpeed = FixedMul(finalSpeed, 4*FRACUNIT/5); + } + else + { + if ((lastTarg >= 0 && lastTarg < MAXPLAYERS) + && playeringame[lastTarg] == true) + { + player_t *tryPlayer = &players[lastTarg]; + + if (tryPlayer->spectator == false) + { + P_SetTarget(&jawz_chase(th), tryPlayer->mo); + } + } + } + + S_StartSound(th, th->info->activesound); + jawz_speed(th) = finalSpeed; +} diff --git a/src/objects/orbinaut.c b/src/objects/orbinaut.c index 16798aea3..240e01496 100644 --- a/src/objects/orbinaut.c +++ b/src/objects/orbinaut.c @@ -36,7 +36,6 @@ #define orbinaut_turn(o) ((o)->extravalue1) #define orbinaut_owner(o) ((o)->target) -#define orbinaut_center(o) ((o)->tracer) #define orbinaut_shield_dist(o) ((o)->extravalue1) @@ -45,7 +44,7 @@ void Obj_OrbinautThink(mobj_t *th) boolean grounded = P_IsObjectOnGround(th); mobj_t *ghost = NULL; - if (th->fuse <= TICRATE) + if (th->fuse > 0 && th->fuse <= TICRATE) { th->renderflags ^= RF_DONTDRAW; } @@ -177,7 +176,7 @@ boolean Obj_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) if (t2->player) { if ((t2->player->flashing > 0 && t2->hitlag == 0) - && !(t1->type == MT_ORBINAUT || t1->type == MT_JAWZ || t1->type == MT_JAWZ_DUD)) + && !(t1->type == MT_ORBINAUT || t1->type == MT_JAWZ)) return true; if (t2->player->hyudorotimer) @@ -198,7 +197,7 @@ boolean Obj_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) damageitem = true; } - else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD + else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD || t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD || t2->type == MT_BALLHOG) @@ -279,7 +278,7 @@ void Obj_OrbinautThrown(mobj_t *th, fixed_t finalSpeed, SINT8 dir) } } -void Obj_OrbinautMoveHeld(player_t *player) +void Obj_OrbinautJawzMoveHeld(player_t *player) { fixed_t finalscale = K_ItemScaleForPlayer(player); mobj_t *cur = player->mo->hnext; diff --git a/src/p_enemy.c b/src/p_enemy.c index 74170980c..86403fa28 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -310,7 +310,6 @@ void A_ChangeHeight(mobj_t *actor); // SRB2Kart // void A_ItemPop(mobj_t *actor); -void A_JawzChase(mobj_t *actor); void A_JawzExplode(mobj_t *actor); void A_SSMineSearch(mobj_t *actor); void A_SSMineExplode(mobj_t *actor); @@ -13207,132 +13206,6 @@ void A_ItemPop(mobj_t *actor) } } -void A_JawzChase(mobj_t *actor) -{ - player_t *player; - fixed_t thrustamount = 0; - fixed_t frictionsafety = (actor->friction == 0) ? 1 : actor->friction; - fixed_t topspeed = actor->movefactor; - - if (LUA_CallAction(A_JAWZCHASE, actor)) - return; - - if (actor->tracer) - { - /*if ((gametyperules & GTR_CIRCUIT)) // Stop looking after first target in race - actor->extravalue1 = 1;*/ - - if (actor->tracer->health) - { - const angle_t targetangle = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); - mobj_t *ret; - angle_t angledelta = actor->angle - targetangle; - boolean turnclockwise = true; - - if (gametyperules & GTR_CIRCUIT) - { - const fixed_t distbarrier = FixedMul(512*mapobjectscale, FRACUNIT + ((gamespeed-1) * (FRACUNIT/4))); - const fixed_t distaway = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); - if (distaway < distbarrier) - { - if (actor->tracer->player) - { - fixed_t speeddifference = abs(topspeed - min(actor->tracer->player->speed, K_GetKartSpeed(actor->tracer->player, false, false))); - topspeed = topspeed - FixedMul(speeddifference, FRACUNIT-FixedDiv(distaway, distbarrier)); - } - } - } - - if (angledelta != 0) - { - angle_t MAX_JAWZ_TURN = ANGLE_90/15; // We can turn a maximum of 6 degrees per frame at regular max speed - // MAX_JAWZ_TURN gets stronger the slower the top speed of jawz - if (topspeed < actor->movefactor) - { - if (topspeed == 0) - { - MAX_JAWZ_TURN = ANGLE_180; - } - else - { - fixed_t anglemultiplier = FixedDiv(actor->movefactor, topspeed); - MAX_JAWZ_TURN += FixedAngle(FixedMul(AngleFixed(MAX_JAWZ_TURN), anglemultiplier)); - } - } - - if (angledelta > ANGLE_180) - { - angledelta = InvAngle(angledelta); - turnclockwise = false; - } - - if (angledelta > MAX_JAWZ_TURN) - { - angledelta = MAX_JAWZ_TURN; - } - - if (turnclockwise) - { - actor->angle -= angledelta; - } - else - { - actor->angle += angledelta; - } - } - - ret = P_SpawnMobj(actor->tracer->x, actor->tracer->y, actor->tracer->z, MT_PLAYERRETICULE); - ret->old_x = actor->tracer->old_x; - ret->old_y = actor->tracer->old_y; - ret->old_z = actor->tracer->old_z; - P_SetTarget(&ret->target, actor->tracer); - ret->frame |= ((leveltime % 10) / 2) + 5; - ret->color = actor->cvmem; - } - else - P_SetTarget(&actor->tracer, NULL); - } - - if (!actor->tracer) - { - actor->angle = K_MomentumAngle(actor); - } - - if (P_IsObjectOnGround(actor)) - { - const fixed_t currentspeed = R_PointToDist2(0, 0, actor->momx, actor->momy); - - if (currentspeed >= topspeed) - { - // Thrust as if you were at top speed, slow down naturally - thrustamount = FixedDiv(topspeed, frictionsafety) - topspeed; - } - else - { - const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; - // Thrust to immediately get to top speed - thrustamount = beatfriction + FixedDiv(topspeed - currentspeed, frictionsafety); - } - - P_Thrust(actor, actor->angle, thrustamount); - } - - if ((actor->tracer != NULL) && (actor->tracer->health > 0)) - return; - - if (actor->extravalue1) // Disable looking by setting this - return; - - if (!actor->target || P_MobjWasRemoved(actor->target)) // No source! - return; - - player = K_FindJawzTarget(actor, actor->target->player); - if (player) - P_SetTarget(&actor->tracer, player->mo); - - return; -} - void A_JawzExplode(mobj_t *actor) { INT32 shrapnel = 2; diff --git a/src/p_inter.c b/src/p_inter.c index 4974338bb..0f185ea6f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -916,7 +916,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget // SRB2kart if (target->type != MT_PLAYER && !(target->flags & MF_MONITOR) && !(target->type == MT_ORBINAUT || target->type == MT_ORBINAUT_SHIELD - || target->type == MT_JAWZ || target->type == MT_JAWZ_DUD || target->type == MT_JAWZ_SHIELD + || target->type == MT_JAWZ || target->type == MT_JAWZ_SHIELD || target->type == MT_BANANA || target->type == MT_BANANA_SHIELD || target->type == MT_DROPTARGET || target->type == MT_DROPTARGET_SHIELD || target->type == MT_EGGMANITEM || target->type == MT_EGGMANITEM_SHIELD @@ -1497,7 +1497,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget break; } - if ((target->type == MT_JAWZ || target->type == MT_JAWZ_DUD || target->type == MT_JAWZ_SHIELD) && !(target->flags2 & MF2_AMBUSH)) + if ((target->type == MT_JAWZ || target->type == MT_JAWZ_SHIELD) && !(target->flags2 & MF2_AMBUSH)) { target->z += P_MobjFlip(target)*20*target->scale; } diff --git a/src/p_map.c b/src/p_map.c index e5882d47f..07d610fb8 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -863,7 +863,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) // Bubble Shield reflect if (((thing->type == MT_BUBBLESHIELD && thing->target->player && thing->target->player->bubbleblowup) || (thing->player && thing->player->bubbleblowup)) - && (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD + && (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_BANANA || tmthing->type == MT_EGGMANITEM || tmthing->type == MT_BALLHOG || tmthing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || tmthing->type == MT_SINK || (tmthing->type == MT_PLAYER && thing->target != tmthing))) @@ -878,7 +878,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) } else if (((tmthing->type == MT_BUBBLESHIELD && tmthing->target->player && tmthing->target->player->bubbleblowup) || (tmthing->player && tmthing->player->bubbleblowup)) - && (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD + && (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG || thing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || thing->type == MT_SINK || (thing->type == MT_PLAYER && tmthing->target != thing))) @@ -898,7 +898,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) // Droptarget reflect if ((thing->type == MT_DROPTARGET || thing->type == MT_DROPTARGET_SHIELD) - && (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD + && (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_BANANA || tmthing->type == MT_EGGMANITEM || tmthing->type == MT_BALLHOG || tmthing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || tmthing->type == MT_SINK || (tmthing->type == MT_PLAYER))) @@ -912,7 +912,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) return K_DropTargetCollide(thing, tmthing) ? BMIT_CONTINUE : BMIT_ABORT; } else if ((tmthing->type == MT_DROPTARGET || tmthing->type == MT_DROPTARGET_SHIELD) - && (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD + && (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_BANANA || thing->type == MT_EGGMANITEM || thing->type == MT_BALLHOG || thing->type == MT_SSMINE || tmthing->type == MT_LANDMINE || thing->type == MT_SINK || (thing->type == MT_PLAYER))) @@ -931,7 +931,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) || thing->type == MT_DROPTARGET_SHIELD || tmthing->type == MT_DROPTARGET_SHIELD) return BMIT_CONTINUE; - if (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_JAWZ_DUD + if (tmthing->type == MT_ORBINAUT || tmthing->type == MT_JAWZ || tmthing->type == MT_ORBINAUT_SHIELD || tmthing->type == MT_JAWZ_SHIELD) { // see if it went over / under @@ -942,7 +942,7 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) return Obj_OrbinautJawzCollide(tmthing, thing) ? BMIT_CONTINUE : BMIT_ABORT; } - else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_JAWZ_DUD + else if (thing->type == MT_ORBINAUT || thing->type == MT_JAWZ || thing->type == MT_ORBINAUT_SHIELD || thing->type == MT_JAWZ_SHIELD) { // see if it went over / under diff --git a/src/p_mobj.c b/src/p_mobj.c index e39ab6aaa..e8178b2dd 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1743,7 +1743,6 @@ void P_XYMovement(mobj_t *mo) /*FALLTHRU*/ case MT_JAWZ: - case MT_JAWZ_DUD: if (mo->health == 1) { // This Item Damage @@ -2181,7 +2180,6 @@ boolean P_ZMovement(mobj_t *mo) case MT_BANANA: case MT_ORBINAUT: case MT_JAWZ: - case MT_JAWZ_DUD: case MT_BALLHOG: case MT_SSMINE: case MT_LANDMINE: @@ -4993,7 +4991,7 @@ boolean P_IsKartItem(INT32 type) type == MT_BANANA || type == MT_BANANA_SHIELD || type == MT_DROPTARGET || type == MT_DROPTARGET_SHIELD || type == MT_ORBINAUT || type == MT_ORBINAUT_SHIELD || - type == MT_JAWZ || type == MT_JAWZ_DUD || type == MT_JAWZ_SHIELD || + type == MT_JAWZ || type == MT_JAWZ_SHIELD || type == MT_SSMINE || type == MT_SSMINE_SHIELD || type == MT_SINK || type == MT_SINK_SHIELD || type == MT_SPB || type == MT_BALLHOG || type == MT_BUBBLESHIELDTRAP || @@ -6328,7 +6326,6 @@ static boolean P_MobjDeadThink(mobj_t *mobj) mobj->renderflags ^= RF_DONTDRAW; break; case MT_JAWZ: - case MT_JAWZ_DUD: if (P_IsObjectOnGround(mobj)) P_SetMobjState(mobj, mobj->info->xdeathstate); /* FALLTHRU */ @@ -6717,89 +6714,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) } case MT_JAWZ: { - mobj_t *ghost = P_SpawnGhostMobj(mobj); - - if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) - { - ghost->color = mobj->target->player->skincolor; - ghost->colorized = true; - } - - if (mobj->threshold > 0) - mobj->threshold--; - if (leveltime % TICRATE == 0) - S_StartSound(mobj, mobj->info->activesound); - - // Movement handling has ALL been moved to A_JawzChase - - K_DriftDustHandling(mobj); - - if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true)) - K_DoPogoSpring(mobj, 0, 1); - - if (!(gametyperules & GTR_CIRCUIT)) - mobj->friction = max(0, 3 * mobj->friction / 4); - - break; - } - case MT_JAWZ_DUD: - { - boolean grounded = P_IsObjectOnGround(mobj); - - if (mobj->flags2 & MF2_AMBUSH) - { - if (grounded && (mobj->flags & MF_NOCLIPTHING)) - { - mobj->momx = 1; - mobj->momy = 0; - S_StartSound(mobj, mobj->info->deathsound); - mobj->flags &= ~MF_NOCLIPTHING; - } - } - else - { - mobj_t *ghost = P_SpawnGhostMobj(mobj); - const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); - fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; - fixed_t thrustamount = 0; - - if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) - { - ghost->color = mobj->target->player->skincolor; - ghost->colorized = true; - } - - if (!grounded) - { - // No friction in the air - frictionsafety = FRACUNIT; - } - - if (currentspeed >= mobj->movefactor) - { - // Thrust as if you were at top speed, slow down naturally - thrustamount = FixedDiv(mobj->movefactor, frictionsafety) - mobj->movefactor; - } - else - { - const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; - // Thrust to immediately get to top speed - thrustamount = beatfriction + FixedDiv(mobj->movefactor - currentspeed, frictionsafety); - } - - mobj->angle = K_MomentumAngle(mobj); - P_Thrust(mobj, mobj->angle, thrustamount); - - if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true)) - K_DoPogoSpring(mobj, 0, 1); - - if (mobj->threshold > 0) - mobj->threshold--; - - if (leveltime % TICRATE == 0) - S_StartSound(mobj, mobj->info->activesound); - } - + Obj_JawzThink(mobj); break; } case MT_EGGMANITEM: @@ -9380,7 +9295,7 @@ void P_MobjThinker(mobj_t *mobj) // Destroy items sector special if (mobj->type == MT_BANANA || mobj->type == MT_EGGMANITEM || mobj->type == MT_ORBINAUT || mobj->type == MT_BALLHOG - || mobj->type == MT_JAWZ || mobj->type == MT_JAWZ_DUD + || mobj->type == MT_JAWZ || mobj->type == MT_SSMINE || mobj->type == MT_BUBBLESHIELDTRAP || mobj->type == MT_LANDMINE) { @@ -9469,7 +9384,7 @@ void P_MobjThinker(mobj_t *mobj) || mobj->type == MT_CANNONBALLDECOR || mobj->type == MT_FALLINGROCK || mobj->type == MT_ORBINAUT - || mobj->type == MT_JAWZ || mobj->type == MT_JAWZ_DUD + || mobj->type == MT_JAWZ || (mobj->type == MT_DROPTARGET && mobj->reactiontime)) { P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly @@ -9771,7 +9686,6 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) case MT_ORBINAUT: case MT_ORBINAUT_SHIELD: case MT_JAWZ: - case MT_JAWZ_DUD: case MT_JAWZ_SHIELD: case MT_SSMINE: case MT_SSMINE_SHIELD: From bbec083d4e8f56f3d3509f6b8948ced7cadd2e2f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 25 Sep 2022 12:04:08 -0400 Subject: [PATCH 3/7] Polish backwards behavior --- src/k_kart.c | 21 ++++++++++++++------- src/objects/jawz.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 04752dcb7..b644350ff 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4698,7 +4698,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I speed, FixedMul( FixedDiv(source->player->speed, topspeed), // Multiply speed to be proportional to your own, boosted maxspeed. - FixedDiv((ANGLE_180 - delta), ANGLE_180) // multiply speed based on angle diff... i.e: don't do this for firing backward :V + FixedDiv(AngleFixed(ANGLE_180 - delta), 180 * FRACUNIT) // multiply speed based on angle diff... i.e: don't do this for firing backward :V ) )); } @@ -5608,15 +5608,15 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing, if (missile) // Shootables { - if (dir == -1 && mapthing != MT_SPB) + if (dir < 0 && mapthing != MT_SPB) { // Shoot backward - mo = K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) + angleOffset, 0, PROJSPEED, -1); + mo = K_SpawnKartMissile(player->mo, mapthing, (player->mo->angle + ANGLE_180) + angleOffset, 0, PROJSPEED, dir); } else { // Shoot forward - mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + angleOffset, 0, PROJSPEED, 1); + mo = K_SpawnKartMissile(player->mo, mapthing, player->mo->angle + angleOffset, 0, PROJSPEED, dir); } if (mapthing == MT_DROPTARGET && mo) @@ -8273,13 +8273,20 @@ void K_KartPlayerAfterThink(player_t *player) player_t *targ; mobj_t *ret; - if (player->jawztargetdelay && playeringame[lasttarg] && !players[lasttarg].spectator) + if (player->throwdir == -1) + { + targ = player; + player->jawztargetdelay = 0; + } + else if (player->jawztargetdelay && playeringame[lasttarg] && !players[lasttarg].spectator) { targ = &players[lasttarg]; player->jawztargetdelay--; } else + { targ = K_FindJawzTarget(player->mo, player, ANGLE_45); + } if (!targ || !targ->mo || P_MobjWasRemoved(targ->mo)) { @@ -8297,14 +8304,14 @@ void K_KartPlayerAfterThink(player_t *player) ret->tics = 1; ret->color = player->skincolor; - if (targ-players != lasttarg) + if (targ - players != lasttarg) { if (P_IsDisplayPlayer(player) || P_IsDisplayPlayer(targ)) S_StartSound(NULL, sfx_s3k89); else S_StartSound(targ->mo, sfx_s3k89); - player->lastjawztarget = targ-players; + player->lastjawztarget = targ - players; player->jawztargetdelay = 5; } } diff --git a/src/objects/jawz.c b/src/objects/jawz.c index 0ab8b6c67..b5bc71058 100644 --- a/src/objects/jawz.c +++ b/src/objects/jawz.c @@ -33,12 +33,11 @@ #define jawz_droptime(o) ((o)->movecount) #define jawz_retcolor(o) ((o)->cvmem) +#define jawz_stillturn(o) ((o)->cusval) #define jawz_owner(o) ((o)->target) #define jawz_chase(o) ((o)->tracer) -#define jawz_shield_dist(o) ((o)->extravalue1) - static void JawzChase(mobj_t *th, boolean grounded) { fixed_t thrustamount = 0; @@ -131,6 +130,7 @@ static void JawzChase(mobj_t *th, boolean grounded) P_SetTarget(&ret->target, jawz_chase(th)); ret->frame |= ((leveltime % 10) / 2) + 5; ret->color = jawz_retcolor(th); + ret->renderflags = (ret->renderflags & ~RF_DONTDRAW) | (th->renderflags & RF_DONTDRAW); } else { @@ -154,6 +154,13 @@ static void JawzChase(mobj_t *th, boolean grounded) } } + if (jawz_stillturn(th) > 0) + { + // When beginning to chase your own owner, + // we should turn but not thrust quite yet. + return; + } + if (grounded == true) { const fixed_t currentspeed = R_PointToDist2(0, 0, th->momx, th->momy); @@ -222,6 +229,11 @@ void Obj_JawzThink(mobj_t *th) jawz_selfdelay(th)--; } + if (jawz_stillturn(th) > 0) + { + jawz_stillturn(th)--; + } + if (leveltime % TICRATE == 0) { S_StartSound(th, th->info->activesound); @@ -247,8 +259,19 @@ void Obj_JawzThrown(mobj_t *th, fixed_t finalSpeed, SINT8 dir) { // Thrown backwards, init self-chase P_SetTarget(&jawz_chase(th), jawz_owner(th)); - th->fuse = RR_PROJECTILE_FUSE; + + // Stop it here. + th->momx = 0; + th->momy = 0; + + // Slow down the top speed. finalSpeed = FixedMul(finalSpeed, 4*FRACUNIT/5); + + // Set a fuse. + th->fuse = RR_PROJECTILE_FUSE; + + // Stay still while you turn towards the player + jawz_stillturn(th) = ANGLE_180 / MAX_JAWZ_TURN; } else { From 13e94dfee06998460f2f041dc3c68d84190cc135 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 25 Sep 2022 12:14:21 -0400 Subject: [PATCH 4/7] Polish up Jawz target conditions slightly --- src/k_kart.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index b644350ff..d8a908db3 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7151,6 +7151,8 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range) continue; } + thisdist = P_AproxDistance(player->mo->x - (actor->x + actor->momx), player->mo->y - (actor->y + actor->momy)); + if (gametyperules & GTR_CIRCUIT) { if (player->position > source->position) @@ -7168,7 +7170,13 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range) } // Z pos too high/low - if (abs(player->mo->z - (actor->z + actor->momz)) > RING_DIST/8) + if (abs(player->mo->z - (actor->z + actor->momz)) > FixedMul(RING_DIST/8, mapobjectscale)) + { + continue; + } + + // Distance too far away + if (thisdist > FixedMul(RING_DIST*2, mapobjectscale)) { continue; } @@ -7183,14 +7191,6 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range) continue; } - thisdist = P_AproxDistance(player->mo->x - (actor->x + actor->momx), player->mo->y - (actor->y + actor->momy)); - - // Don't go for people who are too far away - if (thisdist > 2*RING_DIST) - { - continue; - } - thisScore = (AngleFixed(thisang) * 2) + (thisdist / 2); //CONS_Printf("got score %f from player # %d\n", FixedToFloat(thisScore), i); From 13e6dfb79eb9dcc6705350988a0c9ed65fe6f6af Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 25 Sep 2022 12:29:18 -0400 Subject: [PATCH 5/7] New Jawz swap prevention Instead of a static 5 tic delay each time the reticule changes, its a timer that increments the longer your target is on someone, up to 10 tics. When trying to swap targets, it will reduce this timer, and only swap when it reaches 0. --- src/k_kart.c | 74 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index d8a908db3..c3badeacd 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7191,7 +7191,7 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range) continue; } - thisScore = (AngleFixed(thisang) * 2) + (thisdist / 2); + thisScore = (AngleFixed(thisang) * 2) + (thisdist / 4); //CONS_Printf("got score %f from player # %d\n", FixedToFloat(thisScore), i); @@ -8269,26 +8269,69 @@ void K_KartPlayerAfterThink(player_t *player) // Jawz reticule (seeking) if (player->itemtype == KITEM_JAWZ && (player->pflags & PF_ITEMOUT)) { - INT32 lasttarg = player->lastjawztarget; - player_t *targ; - mobj_t *ret; + INT32 lastTargID = player->lastjawztarget; + player_t *lastTarg = NULL; + player_t *targ = NULL; + mobj_t *ret = NULL; + + if ((lastTargID >= 0 && lastTargID <= MAXPLAYERS) + && playeringame[lastTargID] == true) + { + if (players[lastTargID].spectator == false) + { + lastTarg = &players[lastTargID]; + } + } if (player->throwdir == -1) { + // Backwards Jawz targets yourself. targ = player; player->jawztargetdelay = 0; } - else if (player->jawztargetdelay && playeringame[lasttarg] && !players[lasttarg].spectator) - { - targ = &players[lasttarg]; - player->jawztargetdelay--; - } else { + // Find a new target. targ = K_FindJawzTarget(player->mo, player, ANGLE_45); } - if (!targ || !targ->mo || P_MobjWasRemoved(targ->mo)) + if (targ != NULL && targ->mo != NULL && P_MobjWasRemoved(targ->mo) == false) + { + if (targ - players == lastTargID) + { + // Increment delay. + if (player->jawztargetdelay < 10) + { + player->jawztargetdelay++; + } + } + else + { + if (player->jawztargetdelay > 0) + { + // Wait a bit before swapping... + player->jawztargetdelay--; + targ = lastTarg; + } + else + { + // Allow a swap. + if (P_IsDisplayPlayer(player) || P_IsDisplayPlayer(targ)) + { + S_StartSound(NULL, sfx_s3k89); + } + else + { + S_StartSound(targ->mo, sfx_s3k89); + } + + player->lastjawztarget = targ - players; + player->jawztargetdelay = 5; + } + } + } + + if (targ == NULL || targ->mo == NULL || P_MobjWasRemoved(targ->mo) == true) { player->lastjawztarget = -1; player->jawztargetdelay = 0; @@ -8303,17 +8346,6 @@ void K_KartPlayerAfterThink(player_t *player) ret->frame |= ((leveltime % 10) / 2); ret->tics = 1; ret->color = player->skincolor; - - if (targ - players != lasttarg) - { - if (P_IsDisplayPlayer(player) || P_IsDisplayPlayer(targ)) - S_StartSound(NULL, sfx_s3k89); - else - S_StartSound(targ->mo, sfx_s3k89); - - player->lastjawztarget = targ - players; - player->jawztargetdelay = 5; - } } else { From ead1c59d58ef3032944589bc0008f04d93a893f2 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 25 Sep 2022 12:41:23 -0400 Subject: [PATCH 6/7] Weight dist even less heavily --- src/k_kart.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index c3badeacd..df01b4e6a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7155,7 +7155,7 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range) if (gametyperules & GTR_CIRCUIT) { - if (player->position > source->position) + if (player->position >= source->position) { // Don't pay attention to people who aren't above your position continue; @@ -7191,7 +7191,7 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source, angle_t range) continue; } - thisScore = (AngleFixed(thisang) * 2) + (thisdist / 4); + thisScore = (AngleFixed(thisang) * 8) + (thisdist / 32); //CONS_Printf("got score %f from player # %d\n", FixedToFloat(thisScore), i); From 232b7d356135f5fef770670c03422902220d667a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 25 Sep 2022 13:00:34 -0400 Subject: [PATCH 7/7] Slowed down orbiting item rotation drastically --- src/objects/orbinaut.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/objects/orbinaut.c b/src/objects/orbinaut.c index 240e01496..0c04c4b67 100644 --- a/src/objects/orbinaut.c +++ b/src/objects/orbinaut.c @@ -281,12 +281,15 @@ void Obj_OrbinautThrown(mobj_t *th, fixed_t finalSpeed, SINT8 dir) void Obj_OrbinautJawzMoveHeld(player_t *player) { fixed_t finalscale = K_ItemScaleForPlayer(player); - mobj_t *cur = player->mo->hnext; - fixed_t speed = ((8 - min(4, player->itemamount)) * cur->info->speed) / 7; + fixed_t speed = 0; + mobj_t *cur = NULL; player->bananadrag = 0; // Just to make sure - while (cur && !P_MobjWasRemoved(cur)) + cur = player->mo->hnext; + speed = ((8 - min(4, player->itemamount)) * cur->info->speed) / 7; + + while (cur != NULL && P_MobjWasRemoved(cur) == false) { const fixed_t radius = FixedHypot(player->mo->radius, player->mo->radius) + FixedHypot(cur->radius, cur->radius); // mobj's distance from its Target, or Radius. fixed_t z; @@ -300,7 +303,7 @@ void Obj_OrbinautJawzMoveHeld(player_t *player) cur->color = player->skincolor; cur->angle -= ANGLE_90; - cur->angle += FixedAngle(speed); + cur->angle += FixedAngle(speed) / 3; if (orbinaut_shield_dist(cur) < radius) {