diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aa5697997..24b59ae08 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -146,6 +146,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 k_serverstats.c k_zvote.c k_mapuser.c + k_powerup.cpp ) if(SRB2_CONFIG_ENABLE_WEBM_MOVIES) diff --git a/src/info.c b/src/info.c index 61da58f39..c0e95fa73 100644 --- a/src/info.c +++ b/src/info.c @@ -648,6 +648,7 @@ char sprnames[NUMSPRITES + 1][5] = "ITMO", "ITMI", "ITMN", + "PWRB", "WANT", "PBOM", // player bomb diff --git a/src/info.h b/src/info.h index ea4df4be3..50486d2b3 100644 --- a/src/info.h +++ b/src/info.h @@ -1201,6 +1201,7 @@ typedef enum sprite SPR_ITMO, SPR_ITMI, SPR_ITMN, + SPR_PWRB, SPR_WANT, SPR_PBOM, // player bomb diff --git a/src/k_battle.h b/src/k_battle.h index 4e1dda2c8..bd15f8b55 100644 --- a/src/k_battle.h +++ b/src/k_battle.h @@ -10,6 +10,7 @@ extern "C" { #define BATTLE_SPAWN_INTERVAL (4*TICRATE) #define BATTLE_DESPAWN_TIME (15*TICRATE) +#define BATTLE_POWERUP_TIME (20*TICRATE) extern struct battleovertime { diff --git a/src/k_collide.cpp b/src/k_collide.cpp index 41f029bbe..cc3dd492d 100644 --- a/src/k_collide.cpp +++ b/src/k_collide.cpp @@ -16,6 +16,7 @@ #include "k_objects.h" #include "k_roulette.h" #include "k_podium.h" +#include "k_powerup.h" angle_t K_GetCollideAngle(mobj_t *t1, mobj_t *t2) { @@ -888,6 +889,8 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim) P_PlayerRingBurst(victimPlayer, 5); P_DamageMobj(victim, shield, attacker, 1, DMG_STUMBLE); // There's a special exception in P_DamageMobj for type==MT_INSTAWHIP + K_DropPowerUps(victimPlayer); + angle_t thrangle = ANGLE_180 + R_PointToAngle2(victim->x, victim->y, shield->x, shield->y); P_Thrust(victim, thrangle, FRACUNIT*10); diff --git a/src/k_kart.c b/src/k_kart.c index 122b80964..40527d844 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6532,13 +6532,26 @@ SINT8 K_GetTotallyRandomResult(UINT8 useodds) 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 *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT16 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); + // FIXME: due to linkdraw sucking major ass, I was unable + // to make a backdrop render behind dropped power-ups + // (which use a smaller sprite than normal items). So + // dropped power-ups have the backdrop baked into the + // sprite for now. + if (type < FIRSTPOWERUP) + { + mobj_t *backdrop = P_SpawnMobjFromMobj(drop, 0, 0, 0, MT_OVERLAY); + + P_SetTarget(&backdrop->target, drop); + P_SetMobjState(backdrop, S_ITEMBACKDROP); + + backdrop->dispoffset = 1; + P_SetTarget(&backdrop->tracer, drop); + backdrop->flags2 |= MF2_LINKDRAW; + } P_SetScale(drop, drop->scale>>4); drop->destscale = (3*drop->destscale)/2; @@ -6587,9 +6600,6 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 } drop->flags |= MF_NOCLIPTHING; - backdrop->dispoffset = 1; - P_SetTarget(&backdrop->tracer, drop); - backdrop->flags2 |= MF2_LINKDRAW; if (gametyperules & GTR_CLOSERPLAYERS) { @@ -12004,8 +12014,17 @@ void K_UpdateMobjItemOverlay(mobj_t *part, SINT8 itemType, UINT8 itemCount) part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE; break; default: - part->sprite = SPR_ITEM; - part->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|(itemType); + if (itemType >= FIRSTPOWERUP) + { + part->sprite = SPR_PWRB; + // Not a papersprite. See K_CreatePaperItem for why. + part->frame = FF_FULLBRIGHT|(itemType - FIRSTPOWERUP); + } + else + { + 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 3235d539a..9c9d876d8 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -150,7 +150,7 @@ void K_SpawnDriftElectricSparks(player_t *player, int color, boolean shockwave); void K_KartUpdatePosition(player_t *player); void K_UpdateAllPlayerPositions(void); 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); +mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 flip, UINT8 type, UINT16 amount); void K_DropPaperItem(player_t *player, UINT8 itemtype, UINT16 itemamount); void K_PopPlayerShield(player_t *player); void K_DropItems(player_t *player); diff --git a/src/k_powerup.cpp b/src/k_powerup.cpp new file mode 100644 index 000000000..f646ec4f7 --- /dev/null +++ b/src/k_powerup.cpp @@ -0,0 +1,50 @@ +/// \brief Battle mode power-up code + +#include "k_kart.h" +#include "k_objects.h" +#include "k_powerup.h" + +tic_t K_PowerUpRemaining(const player_t* player, kartitems_t powerup) +{ + switch (powerup) + { + case POWERUP_SUPERFLICKY: + return Obj_SuperFlickySwarmTime(player->powerup.flickyController); + + default: + return 0u; + } +} + +void K_GivePowerUp(player_t* player, kartitems_t powerup, tic_t time) +{ + switch (powerup) + { + case POWERUP_SUPERFLICKY: + if (K_PowerUpRemaining(player, POWERUP_SUPERFLICKY)) + { + Obj_ExtendSuperFlickySwarm(player->powerup.flickyController, time); + } + else + { + Obj_SpawnSuperFlickySwarm(player, time); + } + break; + + default: + break; + } +} + +void K_DropPowerUps(player_t* player) +{ + if (K_PowerUpRemaining(player, POWERUP_SUPERFLICKY)) + { + mobj_t* swarm = player->powerup.flickyController; + + // Be sure to measure the remaining time before ending the power-up + K_DropPaperItem(player, POWERUP_SUPERFLICKY, Obj_SuperFlickySwarmTime(swarm)); + + Obj_EndSuperFlickySwarm(swarm); + } +} diff --git a/src/k_powerup.h b/src/k_powerup.h new file mode 100644 index 000000000..736ce68fe --- /dev/null +++ b/src/k_powerup.h @@ -0,0 +1,19 @@ +#ifndef __K_POWERUP__ +#define __K_POWERUP__ + +#include "doomtype.h" +#include "d_player.h" + +#ifdef __cplusplus +extern "C" { +#endif + +tic_t K_PowerUpRemaining(const player_t *player, kartitems_t powerup); +void K_GivePowerUp(player_t *player, kartitems_t powerup, tic_t timer); +void K_DropPowerUps(player_t *player); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __K_POWERUP__ diff --git a/src/p_inter.c b/src/p_inter.c index 6a6aabde9..0a659f255 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -41,6 +41,7 @@ #include "k_roulette.h" #include "k_boss.h" #include "acs/interface.h" +#include "k_powerup.h" // CTF player names #define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : "" @@ -276,14 +277,21 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_InstaThrust(player->mo, player->mo->angle, 20<itemamount && player->itemtype != special->threshold)) - return; - - player->itemtype = special->threshold; - if ((UINT16)(player->itemamount) + special->movecount > 255) - player->itemamount = 255; + if (special->threshold >= FIRSTPOWERUP) + { + K_GivePowerUp(player, special->threshold, special->movecount); + } else - player->itemamount += special->movecount; + { + if (!P_CanPickupItem(player, 3) || (player->itemamount && player->itemtype != special->threshold)) + return; + + player->itemtype = special->threshold; + if ((UINT16)(player->itemamount) + special->movecount > 255) + player->itemamount = 255; + else + player->itemamount += special->movecount; + } S_StartSound(special, special->info->deathsound);