diff --git a/src/info.c b/src/info.c index 3faf15dd0..a80f67a78 100644 --- a/src/info.c +++ b/src/info.c @@ -29014,7 +29014,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16, // mass 0, // damage sfx_None, // activesound - MF_SOLID|MF_SHOOTABLE|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags + MF_SHOOTABLE|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, }; diff --git a/src/k_kart.c b/src/k_kart.c index ca030f88a..e3d0dd9ef 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -651,6 +651,24 @@ void K_RunItemCooldowns(void) } } +boolean K_ItemEnabled(SINT8 item) +{ + if (item < 1 || item >= NUMKARTRESULTS) + { + // Not a real item. + return false; + } + + if (K_CanChangeRules(true) == false) + { + // Force all items to be enabled. + return true; + } + + // Allow the user preference. + return KartItemCVars[item - 1]->value; +} + /** \brief Item Roulette for Kart @@ -760,7 +778,7 @@ INT32 K_KartGetItemOdds( I_Assert(item > KITEM_NONE); // too many off by one scenarioes. I_Assert(KartItemCVars[NUMKARTRESULTS-2] != NULL); // Make sure this exists - if (!KartItemCVars[item-1]->value && !modeattacking) + if (K_ItemEnabled(item) == false) { return 0; } @@ -837,32 +855,38 @@ INT32 K_KartGetItemOdds( } } - if (players[i].position == 1) + if (specialStage.active == false) { - first = &players[i]; - } + if (players[i].position == 1) + { + first = &players[i]; + } - if (players[i].position == 2) - { - second = &players[i]; + if (players[i].position == 2) + { + second = &players[i]; + } } } - if (first != NULL) // calculate 2nd's distance from 1st, for SPB + if (specialStage.active == false) { - firstDist = first->distancetofinish; - isFirst = (ourDist <= firstDist); - } + if (first != NULL) // calculate 2nd's distance from 1st, for SPB + { + firstDist = first->distancetofinish; + isFirst = (ourDist <= firstDist); + } - if (second != NULL) - { - secondDist = second->distancetofinish; - } + if (second != NULL) + { + secondDist = second->distancetofinish; + } - if (first != NULL && second != NULL) - { - secondToFirst = secondDist - firstDist; - secondToFirst = K_ScaleItemDistance(secondToFirst, 16 - pingame); // Reversed scaling, so 16P is like 1v1, and 1v1 is like 16P + if (first != NULL && second != NULL) + { + secondToFirst = secondDist - firstDist; + secondToFirst = K_ScaleItemDistance(secondToFirst, 16 - pingame); // Reversed scaling, so 16P is like 1v1, and 1v1 is like 16P + } } switch (item) @@ -1050,7 +1074,7 @@ UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbum } #define SETUPDISTTABLE(odds, num) \ - totalsize++;\ + totalsize += num;\ if (oddsvalid[odds]) \ for (i = num; i; --i) \ disttable[distlen++] = odds; @@ -1075,11 +1099,9 @@ UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbum } else { - UINT32 itotaldis = 0; - if (specialStage.active == true) // Special Stages { - SETUPDISTTABLE(0,1); + SETUPDISTTABLE(0,2); SETUPDISTTABLE(1,2); SETUPDISTTABLE(2,3); SETUPDISTTABLE(3,1); @@ -1096,25 +1118,26 @@ UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbum SETUPDISTTABLE(7,1); } - itotaldis = DISTVAR * (((totalsize - 2) * distlen) / totalsize); + for (i = 0; i < totalsize; i++) + { + fixed_t pos = 0; + fixed_t dist = 0; + UINT8 index = 0; - if (pdis == 0) - { - useodds = disttable[0]; - } - else if (pdis > itotaldis) - { - useodds = disttable[distlen-1]; - } - else - { - for (i = 1; i < totalsize-1; i++) + if (i == totalsize-1) { - if (pdis <= DISTVAR * ((i * distlen) / totalsize)) - { - useodds = disttable[((i * distlen) / totalsize)]; - break; - } + useodds = disttable[distlen-1]; + break; + } + + pos = ((i << FRACBITS) * distlen) / totalsize; + dist = FixedMul(DISTVAR << FRACBITS, pos) >> FRACBITS; + index = FixedInt(FixedRound(pos)); + + if (pdis <= (unsigned)dist) + { + useodds = disttable[index]; + break; } } } diff --git a/src/k_kart.h b/src/k_kart.h index 8f43a6f37..167572260 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -62,6 +62,7 @@ UINT8 K_ItemResultToAmount(SINT8 getitem); tic_t K_GetItemCooldown(SINT8 itemResult); void K_SetItemCooldown(SINT8 itemResult, tic_t time); void K_RunItemCooldowns(void); +boolean K_ItemEnabled(SINT8 item); fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against); boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2); boolean K_KartSolidBounce(mobj_t *bounceMobj, mobj_t *solidMobj); diff --git a/src/objects/ufo.c b/src/objects/ufo.c index fa26ef51d..eba92c525 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -24,12 +24,12 @@ #include "../k_waypoint.h" #include "../k_specialstage.h" -#define UFO_BASE_SPEED (16 * FRACUNIT) // UFO's slowest speed. -#define UFO_SPEEDUP (FRACUNIT >> 3) -#define UFO_SLOWDOWN (FRACUNIT >> 2) -#define UFO_SPACING (1024 * FRACUNIT) -#define UFO_DEADZONE (768 * FRACUNIT) -#define UFO_SPEEDFACTOR (FRACUNIT * 9 / 10) +#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_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_waypoint(o) ((o)->extravalue1) #define ufo_distancetofinish(o) ((o)->extravalue2) @@ -157,17 +157,17 @@ static void UFOUpdateSpeed(mobj_t *ufo) distDelta = ufo_distancetofinish(ufo) - wantedDist; - if (abs(distDelta) <= deadzone) + if (distDelta > 0) { - // We're in a good spot, try to match the player. - wantedSpeed = max(bestSpeed >> 1, baseSpeed); + // Too far behind! Start speeding up! + wantedSpeed = max(bestSpeed << 1, baseSpeed << 2); } else { - if (distDelta > 0) + if (abs(distDelta) < deadzone) { - // Too far behind! Start speeding up! - wantedSpeed = max(bestSpeed << 1, baseSpeed << 2); + // We're in a good spot, try to match the player. + wantedSpeed = max(bestSpeed >> 1, baseSpeed); } else { @@ -354,14 +354,29 @@ static UINT8 GetUFODamage(mobj_t *inflictor) { if (inflictor == NULL || P_MobjWasRemoved(inflictor) == true) { - return 1; + // Default damage value. + return 10; } switch (inflictor->type) { + case MT_SPB: + { + // SPB deals triple damage. + return 30; + } + case MT_ORBINAUT: + case MT_ORBINAUT_SHIELD: + { + // Orbinauts deal double damage. + return 20; + } + case MT_JAWZ: + case MT_JAWZ_SHIELD: default: { - return 1; + // Jawz deal minimal damage. + return 10; } } } @@ -373,6 +388,9 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN (void)source; (void)damageType; + // Speed up on damage! + ufo_speed(ufo) += FixedMul(UFO_BASE_SPEED, K_GetKartGameSpeedScalar(gamespeed)); + if (UFOEmeraldChase(ufo) == true) { // Damaged fully already, no need for any more. @@ -384,14 +402,14 @@ boolean Obj_SpecialUFODamage(mobj_t *ufo, mobj_t *inflictor, mobj_t *source, UIN if (damage >= ufo->health - 1) { - // Turn into just an emerald, and make it collectible! + // Destroy the UFO parts, and make the emerald collectible! ufo->health = 1; ufo->flags = (ufo->flags & ~MF_SHOOTABLE) | (MF_SPECIAL|MF_PICKUPFROMBELOW); return true; } ufo->health -= damage; - K_SetHitLagForObjects(ufo, inflictor, damage * 6, true); + K_SetHitLagForObjects(ufo, inflictor, (damage / 3) + 2, true); return true; } @@ -415,15 +433,18 @@ static mobj_t *InitSpecialUFO(waypoint_t *start) UFOUpdateDistanceToFinish(ufo); } - ufo_speed(ufo) = UFO_BASE_SPEED; + ufo_speed(ufo) = FixedMul(UFO_BASE_SPEED << 2, K_GetKartGameSpeedScalar(gamespeed)); + // TODO: Adjustable Special Stage emerald color ufo->color = SKINCOLOR_CHAOSEMERALD1; underlay = P_SpawnMobjFromMobj(ufo, 0, 0, 0, MT_OVERLAY); P_SetTarget(&underlay->target, ufo); - P_SetMobjState(underlay, S_CHAOSEMERALD_UNDER); underlay->color = ufo->color; + // TODO: Super Emeralds / Chaos Rings + P_SetMobjState(underlay, S_CHAOSEMERALD_UNDER); + return ufo; }