diff --git a/src/k_battle.c b/src/k_battle.c index 15b81f81c..d0bc69c97 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -221,6 +221,29 @@ void K_CheckEmeralds(player_t *player) K_CheckBumpers(); } +UINT16 K_GetChaosEmeraldColor(UINT32 emeraldType) +{ + switch (emeraldType) + { + case EMERALD_CHAOS1: + return SKINCOLOR_CHAOSEMERALD1; + case EMERALD_CHAOS2: + return SKINCOLOR_CHAOSEMERALD2; + case EMERALD_CHAOS3: + return SKINCOLOR_CHAOSEMERALD3; + case EMERALD_CHAOS4: + return SKINCOLOR_CHAOSEMERALD4; + case EMERALD_CHAOS5: + return SKINCOLOR_CHAOSEMERALD5; + case EMERALD_CHAOS6: + return SKINCOLOR_CHAOSEMERALD6; + case EMERALD_CHAOS7: + return SKINCOLOR_CHAOSEMERALD7; + default: + return SKINCOLOR_NONE; + } +} + mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT32 emeraldType) { boolean validEmerald = true; @@ -240,25 +263,13 @@ mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT switch (emeraldType) { case EMERALD_CHAOS1: - emerald->color = SKINCOLOR_CHAOSEMERALD1; - break; case EMERALD_CHAOS2: - emerald->color = SKINCOLOR_CHAOSEMERALD2; - break; case EMERALD_CHAOS3: - emerald->color = SKINCOLOR_CHAOSEMERALD3; - break; case EMERALD_CHAOS4: - emerald->color = SKINCOLOR_CHAOSEMERALD4; - break; case EMERALD_CHAOS5: - emerald->color = SKINCOLOR_CHAOSEMERALD5; - break; case EMERALD_CHAOS6: - emerald->color = SKINCOLOR_CHAOSEMERALD6; - break; case EMERALD_CHAOS7: - emerald->color = SKINCOLOR_CHAOSEMERALD7; + emerald->color = K_GetChaosEmeraldColor(emeraldType); break; default: CONS_Printf("Invalid emerald type %d\n", emeraldType); @@ -336,10 +347,15 @@ UINT8 K_NumEmeralds(player_t *player) return num; } +static inline boolean IsOnInterval(tic_t interval) +{ + return ((leveltime - starttime) % interval) == 0; +} + void K_RunPaperItemSpawners(void) { const boolean overtime = (battleovertime.enabled >= 10*TICRATE); - tic_t interval = 8*TICRATE; + const tic_t interval = BATTLE_SPAWN_INTERVAL; const boolean canmakeemeralds = true; //(!(battlecapsules || bossinfo.boss)); @@ -364,13 +380,7 @@ void K_RunPaperItemSpawners(void) return; } - if (overtime == true) - { - // Double frequency of items - interval /= 2; - } - - if (((leveltime - starttime) % interval) != 0) + if (!IsOnInterval(interval)) { return; } @@ -546,7 +556,7 @@ void K_RunPaperItemSpawners(void) } else { - if (gametyperules & GTR_SPHERES) + if ((gametyperules & GTR_SPHERES) && IsOnInterval(2 * interval)) { drop = K_SpawnSphereBox( spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip), diff --git a/src/k_battle.h b/src/k_battle.h index 42d92cf33..f64cfa967 100644 --- a/src/k_battle.h +++ b/src/k_battle.h @@ -8,6 +8,9 @@ extern "C" { #endif +#define BATTLE_SPAWN_INTERVAL (4*TICRATE) +#define BATTLE_DESPAWN_TIME (15*TICRATE) + extern struct battleovertime { UINT16 enabled; ///< Has this been initalized yet? @@ -25,6 +28,7 @@ boolean K_IsPlayerWanted(player_t *player); void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount); void K_CheckBumpers(void); void K_CheckEmeralds(player_t *player); +UINT16 K_GetChaosEmeraldColor(UINT32 emeraldType); mobj_t *K_SpawnChaosEmerald(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT32 emeraldType); mobj_t *K_SpawnSphereBox(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 amount); void K_DropEmeraldsFromPlayer(player_t *player, UINT32 emeraldType); diff --git a/src/k_kart.c b/src/k_kart.c index f1c0b8be2..660878d4c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6183,17 +6183,48 @@ void K_DropHnextList(player_t *player, boolean keepshields) } } +SINT8 K_GetTotallyRandomResult(UINT8 useodds) +{ + itemroulette_t rouletteData = {0}; + INT32 spawnchance[NUMKARTRESULTS]; + INT32 totalspawnchance = 0; + INT32 i; + + memset(spawnchance, 0, sizeof (spawnchance)); + + K_FillItemRouletteData(NULL, &rouletteData); + + for (i = 1; i < NUMKARTRESULTS; i++) + { + spawnchance[i] = ( + totalspawnchance += K_KartGetItemOdds(NULL, &rouletteData, useodds, i) + ); + } + + if (totalspawnchance > 0) + { + totalspawnchance = P_RandomKey(PR_ITEM_ROULETTE, totalspawnchance); + for (i = 0; i < NUMKARTRESULTS && spawnchance[i] <= totalspawnchance; i++); + } + else + { + i = KITEM_SAD; + } + + return i; +} + mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT8 amount) { mobj_t *drop = P_SpawnMobj(x, y, z, MT_FLOATINGITEM); mobj_t *backdrop = P_SpawnMobjFromMobj(drop, 0, 0, 0, MT_OVERLAY); - + P_SetTarget(&backdrop->target, drop); P_SetMobjState(backdrop, S_ITEMBACKDROP); P_SetScale(drop, drop->scale>>4); drop->destscale = (3*drop->destscale)/2; - + drop->angle = angle; P_Thrust(drop, FixedAngle(P_RandomFixed(PR_ITEM_ROULETTE) * 180) + angle, @@ -6205,62 +6236,31 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 if (type == 0) { - itemroulette_t rouletteData = {0}; - UINT8 useodds = 0; - INT32 spawnchance[NUMKARTRESULTS]; - INT32 totalspawnchance = 0; - INT32 i; + const SINT8 i = K_GetTotallyRandomResult(amount); - memset(spawnchance, 0, sizeof (spawnchance)); + // TODO: this is bad! + // K_KartGetItemResult requires a player + // but item roulette will need rewritten to change this - useodds = amount; + const SINT8 newType = K_ItemResultToType(i); + const UINT8 newAmount = K_ItemResultToAmount(i); - K_FillItemRouletteData(NULL, &rouletteData); - - for (i = 1; i < NUMKARTRESULTS; i++) + if (newAmount > 1) { - spawnchance[i] = ( - totalspawnchance += K_KartGetItemOdds(NULL, &rouletteData, useodds, i) - ); - } + UINT8 j; - if (totalspawnchance > 0) - { - UINT8 newType; - UINT8 newAmount; - - totalspawnchance = P_RandomKey(PR_ITEM_ROULETTE, totalspawnchance); - for (i = 0; i < NUMKARTRESULTS && spawnchance[i] <= totalspawnchance; i++); - - // TODO: this is bad! - // K_KartGetItemResult requires a player - // but item roulette will need rewritten to change this - - newType = K_ItemResultToType(i); - newAmount = K_ItemResultToAmount(i); - - if (newAmount > 1) + for (j = 0; j < newAmount-1; j++) { - UINT8 j; - - for (j = 0; j < newAmount-1; j++) - { - K_CreatePaperItem( - x, y, z, - angle, flip, - newType, 1 - ); - } + K_CreatePaperItem( + x, y, z, + angle, flip, + newType, 1 + ); } + } - drop->threshold = newType; - drop->movecount = 1; - } - else - { - drop->threshold = 1; - drop->movecount = 1; - } + drop->threshold = newType; + drop->movecount = 1; } else { @@ -6273,6 +6273,11 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 P_SetTarget(&backdrop->tracer, drop); backdrop->flags2 |= MF2_LINKDRAW; + if (gametyperules & GTR_BUMPERS) + { + drop->fuse = BATTLE_DESPAWN_TIME; + } + return drop; } @@ -11164,4 +11169,27 @@ void K_HandleDirectionalInfluence(player_t *player) player->mo->momy = FixedMul(speed, finalY); } +void K_UpdateMobjItemOverlay(mobj_t *part, SINT8 itemType, UINT8 itemCount) +{ + switch (itemType) + { + case KITEM_ORBINAUT: + part->sprite = SPR_ITMO; + part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|K_GetOrbinautItemFrame(itemCount); + break; + case KITEM_INVINCIBILITY: + part->sprite = SPR_ITMI; + part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|K_GetInvincibilityItemFrame(); + break; + case KITEM_SAD: + part->sprite = SPR_ITEM; + part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE; + break; + default: + part->sprite = SPR_ITEM; + part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|(itemType); + break; + } +} + //} diff --git a/src/k_kart.h b/src/k_kart.h index f74f14e12..76043919b 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -138,6 +138,7 @@ INT32 K_GetKartDriftSparkValueForStage(player_t *player, UINT8 stage); void K_SpawnDriftBoostExplosion(player_t *player, int stage); void K_SpawnDriftElectricSparks(player_t *player, int color, boolean shockwave); void K_KartUpdatePosition(player_t *player); +SINT8 K_GetTotallyRandomResult(UINT8 useodds); mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT8 amount); void K_DropItems(player_t *player); void K_DropRocketSneaker(player_t *player); @@ -197,6 +198,8 @@ fixed_t K_ItemScaleForPlayer(player_t *player); void K_SetItemOut(player_t *player); void K_UnsetItemOut(player_t *player); +void K_UpdateMobjItemOverlay(mobj_t *part, SINT8 itemType, UINT8 itemCount); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/p_mobj.c b/src/p_mobj.c index 26b38d631..f965d32c8 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4346,25 +4346,7 @@ static void P_RefreshItemCapsuleParts(mobj_t *mobj) part->threshold = mobj->threshold; part->movecount = mobj->movecount; - switch (itemType) - { - case KITEM_ORBINAUT: - part->sprite = SPR_ITMO; - part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|K_GetOrbinautItemFrame(mobj->movecount); - break; - case KITEM_INVINCIBILITY: - part->sprite = SPR_ITMI; - part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|K_GetInvincibilityItemFrame(); - break; - case KITEM_SAD: - part->sprite = SPR_ITEM; - part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE; - break; - default: - part->sprite = SPR_ITEM; - part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|(itemType); - break; - } + K_UpdateMobjItemOverlay(part, itemType, mobj->movecount); // update number frame if (K_GetShieldFromItem(itemType) != KSHIELD_NONE) // shields don't stack, so don't show a number @@ -9528,13 +9510,39 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s P_RemoveMobj(mobj); // make sure they disappear } +static boolean P_CanFlickerFuse(mobj_t *mobj) +{ + switch (mobj->type) + { + case MT_SNAPPER_HEAD: + case MT_SNAPPER_LEG: + case MT_MINECARTSEG: + return true; + + case MT_RANDOMITEM: + case MT_EGGMANITEM: + case MT_FALLINGROCK: + case MT_FLOATINGITEM: + if (mobj->fuse <= TICRATE) + { + return true; + } + break; + + default: + break; + } + + return false; + +} + static boolean P_FuseThink(mobj_t *mobj) { - if (mobj->type == MT_SNAPPER_HEAD || mobj->type == MT_SNAPPER_LEG || mobj->type == MT_MINECARTSEG) - mobj->renderflags ^= RF_DONTDRAW; - - if (mobj->fuse <= TICRATE && (mobj->type == MT_RANDOMITEM || mobj->type == MT_EGGMANITEM || mobj->type == MT_FALLINGROCK)) + if (P_CanFlickerFuse(mobj)) + { mobj->renderflags ^= RF_DONTDRAW; + } mobj->fuse--;