diff --git a/src/k_kart.c b/src/k_kart.c index 86d177f90..429ce9046 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -529,6 +529,10 @@ static fixed_t K_PlayerWeight(mobj_t *mobj, mobj_t *against) { weight = 0; // This player does not cause any bump action } + else if (against && against->type == MT_SPECIAL_UFO) + { + weight = 0; + } else { // Applies rubberbanding, to prevent rubberbanding bots diff --git a/src/k_objects.h b/src/k_objects.h index ab7749865..0f2318ee8 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -60,6 +60,7 @@ mobj_t *Obj_SpawnBrolyKi(mobj_t *source, tic_t duration); /* Special Stage UFO */ void Obj_SpecialUFOThinker(mobj_t *bomb); boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UINT8 damageType); +void Obj_PlayerUFOCollide(mobj_t *ufo, mobj_t *other); mobj_t *Obj_CreateSpecialUFO(void); UINT32 K_GetSpecialUFODistance(void); diff --git a/src/objects/ufo.c b/src/objects/ufo.c index f3a1fb803..852eb4bba 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -27,13 +27,14 @@ #define UFO_BASE_SPEED (24 * FRACUNIT) // UFO's slowest speed. #define UFO_SPEEDUP (FRACUNIT >> 1) // Acceleration #define UFO_SLOWDOWN (FRACUNIT >> 1) // Deceleration -#define UFO_SPACING (1024 * FRACUNIT) // How far the UFO wants to stay in front +#define UFO_SPACING (768 * FRACUNIT) // How far the UFO wants to stay in front #define UFO_DEADZONE (2048 * FRACUNIT) // Deadzone where it won't update it's speed as much. -#define UFO_SPEEDFACTOR (FRACUNIT * 9 / 10) // Factor of player's best speed, to make it more fair. +#define UFO_SPEEDFACTOR (FRACUNIT * 3 / 4) // Factor of player's best speed, to make it more fair. #define ufo_waypoint(o) ((o)->extravalue1) #define ufo_distancetofinish(o) ((o)->extravalue2) #define ufo_speed(o) ((o)->watertop) +#define ufo_collectdelay(o) ((o)->threshold) static void UFOMoveTo(mobj_t *ufo, fixed_t destx, fixed_t desty, fixed_t destz) { @@ -131,7 +132,7 @@ static void UFOUpdateSpeed(mobj_t *ufo) // Doesn't matter if a splitscreen player behind is moving faster behind the one most caught up. bestSpeed = R_PointToDist2(0, 0, player->rmomx, player->rmomy); - + bestSpeed = min(bestSpeed, K_GetKartSpeed(player, false, false)); // Don't become unfair with Sneakers. bestSpeed = FixedDiv(bestSpeed, mapobjectscale); // Unscale from mapobjectscale to FRACUNIT bestSpeed = FixedMul(bestSpeed, UFO_SPEEDFACTOR); // Make it a bit more lenient } @@ -160,11 +161,11 @@ static void UFOUpdateSpeed(mobj_t *ufo) if (distDelta > 0) { // Too far behind! Start speeding up! - wantedSpeed = max(bestSpeed << 1, baseSpeed << 2); + wantedSpeed = max(bestSpeed, baseSpeed << 2); } else { - if (abs(distDelta) < deadzone) + if (abs(distDelta) <= deadzone) { // We're in a good spot, try to match the player. wantedSpeed = max(bestSpeed >> 1, baseSpeed); @@ -361,6 +362,11 @@ void Obj_SpecialUFOThinker(mobj_t *ufo) { // Spawn emerald sparkles UFOEmeraldVFX(ufo); + ufo_collectdelay(ufo)--; + } + else + { + ufo_collectdelay(ufo) = TICRATE; } } @@ -379,6 +385,11 @@ static UINT8 GetUFODamage(mobj_t *inflictor) // SPB deals triple damage. return 30; } + case MT_PLAYER: + { + // Players deal damage relative to how many sneakers they used. + return 15 * inflictor->player->numsneakers; + } case MT_ORBINAUT: { // Thrown orbinauts deal double damage. @@ -414,6 +425,13 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN damage = GetUFODamage(inflictor); + if (damage <= 0) + { + return false; + } + + K_SetHitLagForObjects(ufo, inflictor, (damage / 3) + 2, true); + if (damage >= ufo->health - 1) { // Destroy the UFO parts, and make the emerald collectible! @@ -423,10 +441,27 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN } ufo->health -= damage; - K_SetHitLagForObjects(ufo, inflictor, (damage / 3) + 2, true); return true; } +void Obj_PlayerUFOCollide(mobj_t *ufo, mobj_t *other) +{ + if (other->player == NULL) + { + return; + } + + if ((other->player->sneakertimer > 0) + && !P_PlayerInPain(other->player) + && (other->player->flashing == 0)) + { + // Bump and deal damage. + Obj_SpecialUFODamage(ufo, other, other, DMG_STEAL); + K_KartBouncing(other, ufo); + other->player->sneakertimer = 0; + } +} + static mobj_t *InitSpecialUFO(waypoint_t *start) { mobj_t *ufo = NULL; diff --git a/src/p_inter.c b/src/p_inter.c index 7daaff299..f96554c25 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -379,6 +379,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!P_CanPickupItem(player, 0)) return; + if (special->threshold > 0) + return; + + if (toucher->hitlag > 0) + return; + CONS_Printf("You win!\n"); break; /* diff --git a/src/p_map.c b/src/p_map.c index c7047bcde..9816643fe 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1348,6 +1348,14 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing) return BMIT_CONTINUE; } + else if (thing->type == MT_SPECIAL_UFO) + { + if (!(thing->flags & MF_SPECIAL)) + { + Obj_PlayerUFOCollide(thing, tmthing); + return BMIT_CONTINUE; + } + } else if (thing->type == MT_BLUEROBRA_HEAD || thing->type == MT_BLUEROBRA_JOINT) { // see if it went over / under