Refactor stealing & destroying bumpers

- Prevents being able to farm extra bumpers off of karma players
- Paves the way for bumper destroy animation later
This commit is contained in:
Sally Coolatta 2020-11-15 06:25:38 -05:00
parent 56a20d05df
commit 827a1b5fca
11 changed files with 229 additions and 149 deletions

View file

@ -617,7 +617,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->airtime = (tic_t)LONG(players[i].airtime); rsp->airtime = (tic_t)LONG(players[i].airtime);
rsp->bumpers = SHORT(players[i].bumpers); rsp->bumpers = players[i].bumpers;
rsp->karmadelay = SHORT(players[i].karmadelay); rsp->karmadelay = SHORT(players[i].karmadelay);
rsp->eliminated = players[i].eliminated; rsp->eliminated = players[i].eliminated;
@ -765,7 +765,7 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].airtime = (tic_t)LONG(rsp->airtime); players[i].airtime = (tic_t)LONG(rsp->airtime);
players[i].bumpers = SHORT(rsp->bumpers); players[i].bumpers = rsp->bumpers;
players[i].karmadelay = SHORT(rsp->karmadelay); players[i].karmadelay = SHORT(rsp->karmadelay);
players[i].eliminated = rsp->eliminated; players[i].eliminated = rsp->eliminated;

View file

@ -281,7 +281,7 @@ typedef struct
// SRB2kart // SRB2kart
INT32 kartstuff[NUMKARTSTUFF]; INT32 kartstuff[NUMKARTSTUFF];
tic_t airtime; tic_t airtime;
INT16 bumpers; UINT8 bumpers;
INT16 karmadelay; INT16 karmadelay;
boolean eliminated; boolean eliminated;

View file

@ -524,7 +524,7 @@ typedef struct player_s
waypoint_t *nextwaypoint; waypoint_t *nextwaypoint;
respawnvars_t respawn; // Respawn info respawnvars_t respawn; // Respawn info
tic_t airtime; // Keep track of how long you've been in the air tic_t airtime; // Keep track of how long you've been in the air
INT16 bumpers; UINT8 bumpers;
INT16 karmadelay; INT16 karmadelay;
boolean eliminated; boolean eliminated;

View file

@ -11313,6 +11313,7 @@ struct {
{"DMG_EXPLODE",DMG_EXPLODE}, {"DMG_EXPLODE",DMG_EXPLODE},
{"DMG_SQUISH",DMG_SQUISH}, {"DMG_SQUISH",DMG_SQUISH},
{"DMG_STING",DMG_STING}, {"DMG_STING",DMG_STING},
{"DMG_KARMA",DMG_KARMA},
//// Death types //// Death types
{"DMG_INSTAKILL",DMG_INSTAKILL}, {"DMG_INSTAKILL",DMG_INSTAKILL},
{"DMG_DEATHPIT",DMG_DEATHPIT}, {"DMG_DEATHPIT",DMG_DEATHPIT},

View file

@ -2461,93 +2461,51 @@ void K_DoInstashield(player_t *player)
P_SetTarget(&layerb->target, player->mo); P_SetTarget(&layerb->target, player->mo);
} }
void K_BattleHitPlayer(player_t *player, player_t *victim, UINT8 points, boolean reducewanted) void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved)
{ {
if (reducewanted == false) UINT8 points = 1;
points = 1; // Force to 1 boolean trapItem = false;
if (player == NULL || victim == NULL)
{
// Invalid player or victim
return;
}
if (player == victim)
{
// You cannot give yourself points
return;
}
if ((inflictor && !P_MobjWasRemoved(inflictor)) && (inflictor->type == MT_BANANA && inflictor->health > 1))
{
trapItem = true;
}
// Only apply score bonuses to non-bananas
if (trapItem == false)
{
if (K_IsPlayerWanted(victim))
{
// +3 points for hitting a wanted player
points = 3;
}
else if (gametyperules & GTR_BUMPERS)
{
if ((victim->bumpers > 0) && (victim->bumpers <= bumpersRemoved))
{
// +2 points for finishing off a player
points = 2;
}
}
}
if (gametyperules & GTR_POINTLIMIT) if (gametyperules & GTR_POINTLIMIT)
{ {
P_AddPlayerScore(player, points); P_AddPlayerScore(player, points);
K_SpawnBattlePoints(player, victim, points); K_SpawnBattlePoints(player, victim, points);
} }
if ((gametyperules & GTR_WANTED) && (reducewanted == true))
{
// Seems a little backwards, but the WANTED system is meant to prevent camping.
// If you don't want people to go after you, then be proactive!
player->kartstuff[k_wanted] -= wantedreduce;
victim->kartstuff[k_wanted] -= (wantedreduce/2);
}
}
void K_RemoveBumper(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 amount, boolean force)
{
UINT8 score = 1;
boolean trapitem = false;
if (amount <= 0)
return;
if (!(gametyperules & GTR_BUMPERS))
return;
if (force == false)
{
if (player->powers[pw_flashing] || P_PlayerInPain(player))
return;
}
if (inflictor && !P_MobjWasRemoved(inflictor))
{
if (inflictor->type == MT_BANANA && inflictor->health <= 1)
{
trapitem = true;
}
}
if (gametyperules & GTR_POINTLIMIT)
{
if (K_IsPlayerWanted(player))
score = 3;
else if ((gametyperules & GTR_BUMPERS) && (player->bumpers <= amount))
score = 2;
}
if (source && source->player && player != source->player)
{
K_BattleHitPlayer(source->player, player, score, trapitem);
}
if (player->bumpers > 0)
{
if (player->bumpers <= amount)
{
mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!!
P_SetTarget(&karmahitbox->target, player->mo);
karmahitbox->destscale = player->mo->scale;
P_SetScale(karmahitbox, player->mo->scale);
CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]);
}
player->bumpers -= amount;
K_CalculateBattleWanted();
}
if (player->bumpers <= 0)
{
player->bumpers = 0;
player->karmadelay = comebacktime;
if (player->kartstuff[k_comebackmode] == 2)
{
mobj_t *poof = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EXPLODE);
S_StartSound(poof, mobjinfo[MT_KARMAHITBOX].seesound);
player->kartstuff[k_comebackmode] = 0;
}
}
K_CheckBumpers();
} }
void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type) void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type)
@ -2660,30 +2618,110 @@ void K_DebtStingPlayer(player_t *player, mobj_t *source)
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
} }
void K_StealBumper(player_t *player, player_t *victim, UINT8 amount) void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers)
{ {
INT32 intendedamount = player->bumpers + amount; if (!(gametyperules & GTR_BUMPERS))
INT32 newbumper; {
angle_t newangle, diff; // Bumpers aren't being used
fixed_t newx, newy;
mobj_t *newmo;
if (amount <= 0)
return; return;
}
// TODO: replace all console text print-outs with a real visual
if (player->bumpers > 0 && prevBumpers == 0)
{
if (player->kartstuff[k_comebackmode] == 2)
{
mobj_t *poof = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EXPLODE);
S_StartSound(poof, mobjinfo[MT_KARMAHITBOX].seesound);
}
player->kartstuff[k_comebackmode] = 0;
if (netgame)
{
CONS_Printf(M_GetText("%s is back in the game!\n"), player_names[player-players]);
}
}
else if (player->bumpers == 0 && prevBumpers > 0)
{
mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX);
P_SetTarget(&karmahitbox->target, player->mo);
karmahitbox->destscale = player->mo->destscale;
P_SetScale(karmahitbox, player->mo->scale);
if (netgame)
{
CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]);
}
}
player->karmadelay = comebacktime;
K_CalculateBattleWanted();
K_CheckBumpers();
}
void K_DestroyBumpers(player_t *player, UINT8 amount)
{
UINT8 oldBumpers = player->bumpers;
if (!(gametyperules & GTR_BUMPERS)) if (!(gametyperules & GTR_BUMPERS))
return;
if (netgame && player->bumpers <= 0)
CONS_Printf(M_GetText("%s is back in the game!\n"), player_names[player-players]);
while (player->bumpers < intendedamount)
{ {
newbumper = player->bumpers; return;
}
amount = min(amount, player->bumpers);
if (amount == 0)
{
return;
}
player->bumpers -= amount;
// TODO: Store a bumperlist on the player mobj,
// that way we can do a bumper destruction animation
K_HandleBumperChanges(player, oldBumpers);
}
void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount)
{
UINT8 oldPlayerBumpers = player->bumpers;
UINT8 oldVictimBumpers = victim->bumpers;
UINT8 tookBumpers = 0;
if (!(gametyperules & GTR_BUMPERS))
{
return;
}
amount = min(amount, victim->bumpers);
if (amount == 0)
{
return;
}
while ((tookBumpers < amount) && (victim->bumpers > 0))
{
UINT8 newbumper = player->bumpers;
angle_t newangle, diff;
fixed_t newx, newy;
mobj_t *newmo;
if (newbumper <= 1) if (newbumper <= 1)
{
diff = 0; diff = 0;
}
else else
{
diff = FixedAngle(360*FRACUNIT/newbumper); diff = FixedAngle(360*FRACUNIT/newbumper);
}
newangle = player->mo->angle; newangle = player->mo->angle;
newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT); newx = player->mo->x + P_ReturnThrustX(player->mo, newangle + ANGLE_180, 64*FRACUNIT);
@ -2691,36 +2729,42 @@ void K_StealBumper(player_t *player, player_t *victim, UINT8 amount)
newmo = P_SpawnMobj(newx, newy, player->mo->z, MT_BATTLEBUMPER); newmo = P_SpawnMobj(newx, newy, player->mo->z, MT_BATTLEBUMPER);
newmo->threshold = newbumper; newmo->threshold = newbumper;
P_SetTarget(&newmo->tracer, victim->mo); P_SetTarget(&newmo->tracer, victim->mo);
P_SetTarget(&newmo->target, player->mo); P_SetTarget(&newmo->target, player->mo);
newmo->angle = (diff * (newbumper-1)); newmo->angle = (diff * (newbumper-1));
newmo->color = victim->skincolor; newmo->color = victim->skincolor;
if (newbumper+1 < 2) if (newbumper+1 < 2)
{
P_SetMobjState(newmo, S_BATTLEBUMPER3); P_SetMobjState(newmo, S_BATTLEBUMPER3);
}
else if (newbumper+1 < 3) else if (newbumper+1 < 3)
{
P_SetMobjState(newmo, S_BATTLEBUMPER2); P_SetMobjState(newmo, S_BATTLEBUMPER2);
}
else else
{
P_SetMobjState(newmo, S_BATTLEBUMPER1); P_SetMobjState(newmo, S_BATTLEBUMPER1);
player->bumpers++;
} }
player->bumpers++;
victim->bumpers--;
tookBumpers++;
}
if (tookBumpers == 0)
{
// No change occured.
return;
}
// Play steal sound
S_StartSound(player->mo, sfx_3db06); S_StartSound(player->mo, sfx_3db06);
player->powers[pw_flashing] = K_GetKartFlashing(player); K_HandleBumperChanges(player, oldPlayerBumpers);
player->karmadelay = comebacktime; K_HandleBumperChanges(victim, oldVictimBumpers);
/*
victim->powers[pw_flashing] = K_GetKartFlashing(victim);
victim->karmadelay = comebacktime;
*/
victim->kartstuff[k_instashield] = 15;
if (cv_kartdebughuddrop.value && !modeattacking)
K_DropItems(victim);
else
K_DropHnextList(victim, false);
} }
// source is the mobj that originally threw the bomb that exploded etc. // source is the mobj that originally threw the bomb that exploded etc.

View file

@ -42,13 +42,14 @@ void K_KartPlayerAfterThink(player_t *player);
angle_t K_MomentumAngle(mobj_t *mo); angle_t K_MomentumAngle(mobj_t *mo);
void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics); void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics);
void K_DoInstashield(player_t *player); void K_DoInstashield(player_t *player);
void K_BattleHitPlayer(player_t *player, player_t *victim, UINT8 points, boolean reducewanted); void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved);
void K_RemoveBumper(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 amount, boolean force);
void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type); void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type);
void K_SquishPlayer(player_t *player, mobj_t *inflictor, mobj_t *source); void K_SquishPlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source); void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
void K_DebtStingPlayer(player_t *player, mobj_t *source); void K_DebtStingPlayer(player_t *player, mobj_t *source);
void K_StealBumper(player_t *player, player_t *victim, UINT8 amount); void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers);
void K_DestroyBumpers(player_t *player, UINT8 amount);
void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount);
void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source); void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source);
void K_SpawnMineExplosion(mobj_t *source, UINT8 color); void K_SpawnMineExplosion(mobj_t *source, UINT8 color);
UINT16 K_DriftSparkColor(player_t *player, INT32 charge); UINT16 K_DriftSparkColor(player_t *player, INT32 charge);

View file

@ -3432,7 +3432,7 @@ static int lib_kExplodePlayer(lua_State *L)
return 0; return 0;
} }
static int lib_kStealBumper(lua_State *L) static int lib_kTakeBumpersFromPlayer(lua_State *L)
{ {
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
player_t *victim = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); player_t *victim = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
@ -3442,7 +3442,7 @@ static int lib_kStealBumper(lua_State *L)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
if (!victim) if (!victim)
return LUA_ErrInvalid(L, "player_t"); return LUA_ErrInvalid(L, "player_t");
K_StealBumper(player, victim, amount); K_TakeBumpersFromPlayer(player, victim, amount);
return 0; return 0;
} }
@ -3919,7 +3919,7 @@ static luaL_Reg lib[] = {
{"K_SpinPlayer",lib_kSpinPlayer}, {"K_SpinPlayer",lib_kSpinPlayer},
{"K_SquishPlayer",lib_kSquishPlayer}, {"K_SquishPlayer",lib_kSquishPlayer},
{"K_ExplodePlayer",lib_kExplodePlayer}, {"K_ExplodePlayer",lib_kExplodePlayer},
{"K_StealBumper",lib_kStealBumper}, {"K_TakeBumpersFromPlayer",lib_kTakeBumpersFromPlayer},
{"K_SpawnKartExplosion",lib_kSpawnKartExplosion}, {"K_SpawnKartExplosion",lib_kSpawnKartExplosion},
{"K_SpawnMineExplosion",lib_kSpawnMineExplosion}, {"K_SpawnMineExplosion",lib_kSpawnMineExplosion},
{"K_SpawnBoostTrail",lib_kSpawnBoostTrail}, {"K_SpawnBoostTrail",lib_kSpawnBoostTrail},

View file

@ -305,7 +305,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{ {
mobj_t *boom; mobj_t *boom;
if (P_DamageMobj(toucher, special, special->target, 1, DMG_EXPLODE) == false) if (P_DamageMobj(toucher, special, special->target, 1, DMG_KARMA) == false)
{ {
return; return;
} }
@ -323,9 +323,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
S_StartSound(boom, special->info->attacksound); S_StartSound(boom, special->info->attacksound);
K_StealBumper(special->target->player, player, max(1, player->bumpers-1)); // bumpers-1 to slowly remove bumpers from the economy
K_RemoveBumper(player, special->target, special->target, player->bumpers, true);
special->target->player->karthud[khud_yougotem] = 2*TICRATE; special->target->player->karthud[khud_yougotem] = 2*TICRATE;
special->target->player->karmadelay = comebacktime; special->target->player->karmadelay = comebacktime;
} }
@ -1692,7 +1689,7 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
{ {
case DMG_DEATHPIT: case DMG_DEATHPIT:
// Respawn kill types // Respawn kill types
K_RemoveBumper(player, NULL, NULL, 1, true); K_DestroyBumpers(player, 1);
K_DoIngameRespawn(player); K_DoIngameRespawn(player);
return false; return false;
default: default:
@ -1733,7 +1730,7 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
P_SetTarget(&boom->target, player->mo); P_SetTarget(&boom->target, player->mo);
} }
K_RemoveBumper(player, NULL, NULL, player->bumpers, true); K_DestroyBumpers(player, player->bumpers);
player->eliminated = true; player->eliminated = true;
} }
@ -1923,31 +1920,54 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
} }
} }
// We successfully hit 'em! // We successfully damaged them! Give 'em some bumpers!
if (type != DMG_STING) if (type != DMG_STING)
{ {
UINT8 bumpadd = 1; UINT8 takeBumpers = 1;
if (damagetype & DMG_STEAL) if (damagetype & DMG_STEAL)
{ {
bumpadd = 2; takeBumpers = 2;
if (type == DMG_KARMA)
{
takeBumpers = player->bumpers;
}
}
else
{
if (type == DMG_KARMA)
{
// Take half of their bumpers for karma comeback damage
takeBumpers = max(1, player->bumpers / 2);
}
} }
if (source && source != player->mo && source->player) if (source && source != player->mo && source->player)
{ {
K_PlayHitEmSound(source); K_PlayHitEmSound(source);
K_StealBumper(source->player, player, bumpadd);
K_BattleAwardHit(source->player, player, inflictor, takeBumpers);
K_TakeBumpersFromPlayer(source->player, player, takeBumpers);
if (type == DMG_KARMA)
{
// Destroy any remainder bumpers from the player for karma comeback damage
K_DestroyBumpers(player, player->bumpers);
}
if (damagetype & DMG_STEAL) if (damagetype & DMG_STEAL)
{ {
// Give them ALL of your emeralds :) // Give them ALL of your emeralds instantly :)
source->player->powers[pw_emeralds] |= player->powers[pw_emeralds]; source->player->powers[pw_emeralds] |= player->powers[pw_emeralds];
player->powers[pw_emeralds] = 0; player->powers[pw_emeralds] = 0;
K_CheckEmeralds(source->player); K_CheckEmeralds(source->player);
} }
} }
else
K_RemoveBumper(player, inflictor, source, bumpadd, false); {
K_DestroyBumpers(player, takeBumpers);
}
if (!(damagetype & DMG_STEAL)) if (!(damagetype & DMG_STEAL))
{ {
@ -1968,6 +1988,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
ringburst = 0; ringburst = 0;
break; break;
case DMG_EXPLODE: case DMG_EXPLODE:
case DMG_KARMA:
K_ExplodePlayer(player, inflictor, source); K_ExplodePlayer(player, inflictor, source);
break; break;
case DMG_WIPEOUT: case DMG_WIPEOUT:
@ -1997,7 +2018,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
K_PlayPainSound(player->mo); K_PlayPainSound(player->mo);
if ((type == DMG_EXPLODE) || (cv_kartdebughuddrop.value && !modeattacking)) if ((type == DMG_EXPLODE || type == DMG_KARMA) || (cv_kartdebughuddrop.value && !modeattacking))
{ {
K_DropItems(player); K_DropItems(player);
} }

View file

@ -467,6 +467,7 @@ typedef struct BasicFF_s
#define DMG_EXPLODE 0x02 #define DMG_EXPLODE 0x02
#define DMG_SQUISH 0x03 #define DMG_SQUISH 0x03
#define DMG_STING 0x04 #define DMG_STING 0x04
#define DMG_KARMA 0x05 // Karma Bomb explosion -- works like DMG_EXPLODE, but steals half of their bumpers & deletes the rest
//// Death types - cannot be combined with damage types //// Death types - cannot be combined with damage types
#define DMG_INSTAKILL 0x80 #define DMG_INSTAKILL 0x80
#define DMG_DEATHPIT 0x81 #define DMG_DEATHPIT 0x81

View file

@ -5278,15 +5278,23 @@ static void P_MobjSceneryThink(mobj_t *mobj)
} }
break; break;
case MT_BATTLEBUMPER: case MT_BATTLEBUMPER:
if (mobj->health > 0 && mobj->target && mobj->target->player if (mobj->health <= 0)
&& mobj->target->health > 0 && !mobj->target->player->spectator)
{ {
// DO EXPLODE ANIMATION HERE
//CONS_Printf("bumper explosion\n");
P_RemoveMobj(mobj);
return;
}
else if (mobj->target && mobj->target->player && mobj->target->health > 0 && !mobj->target->player->spectator)
{
// Following a player
fixed_t rad = 32*mobj->target->scale; fixed_t rad = 32*mobj->target->scale;
fixed_t offz; fixed_t offz;
angle_t ang, diff; angle_t ang, diff;
if (!((mobj->target->player-players) & 1)) if (!((mobj->target->player-players) & 1))
ang = (FixedAngle(mobj->info->speed) * -1); ang = -FixedAngle(mobj->info->speed);
else else
ang = FixedAngle(mobj->info->speed); ang = FixedAngle(mobj->info->speed);
@ -5341,21 +5349,20 @@ static void P_MobjSceneryThink(mobj_t *mobj)
P_SetThingPosition(mobj); P_SetThingPosition(mobj);
} }
// Was this so hard?
if (mobj->target->player->bumpers <= mobj->threshold) if (mobj->target->player->bumpers <= mobj->threshold)
{ {
// Sliently remove
P_RemoveMobj(mobj); P_RemoveMobj(mobj);
return; return;
} }
} }
else if ((mobj->health > 0 else
&& (!mobj->target || !mobj->target->player || !mobj->target->player->mo || mobj->target->health <= 0 || mobj->target->player->spectator))
|| (mobj->health <= 0 && P_IsObjectOnGround(mobj))
|| P_CheckDeathPitCollide(mobj)) // When in death state
{ {
// Sliently remove
P_RemoveMobj(mobj); P_RemoveMobj(mobj);
return; return;
} }
break; break;
case MT_PLAYERARROW: case MT_PLAYERARROW:
if (mobj->target && mobj->target->health if (mobj->target && mobj->target->health
@ -10167,20 +10174,25 @@ void P_SpawnPlayer(INT32 playernum)
P_SetScale(mobj, mobj->destscale); P_SetScale(mobj, mobj->destscale);
P_FlashPal(p, 0, 0); // Resets P_FlashPal(p, 0, 0); // Resets
if ((gametyperules & GTR_BUMPERS)) // SRB2kart if (gametyperules & GTR_BUMPERS)
{ {
mobj_t *overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + mobj->height + 16*FRACUNIT, MT_PLAYERARROW); mobj_t *overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + mobj->height + 16*FRACUNIT, MT_PLAYERARROW);
P_SetTarget(&overheadarrow->target, mobj); P_SetTarget(&overheadarrow->target, mobj);
overheadarrow->drawflags |= MFD_DONTDRAW; overheadarrow->drawflags |= MFD_DONTDRAW;
P_SetScale(overheadarrow, mobj->destscale); P_SetScale(overheadarrow, mobj->destscale);
if (p->spectator && pcount > 1) // HEY! No being cheap... if (p->spectator)
p->bumpers = 0;
else if (p->bumpers > 0 || leveltime < 1
|| (p->jointime <= 1 && pcount <= 1))
{ {
if (leveltime < 1 || (p->jointime <= 1 && pcount <= 1)) // Start of the map? // HEY! No being cheap...
p->bumpers = K_StartingBumperCount(); // Reset those bumpers! p->bumpers = 0;
}
else if ((p->bumpers > 0) || (leveltime < starttime) || (pcount <= 1))
{
if ((leveltime < starttime) || (pcount <= 1)) // Start of the map?
{
// Reset those bumpers!
p->bumpers = K_StartingBumperCount();
}
if (p->bumpers) if (p->bumpers)
{ {

View file

@ -257,7 +257,7 @@ static void P_NetArchivePlayers(void)
WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].nextwaypoint)); WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].nextwaypoint));
WRITEUINT32(save_p, players[i].airtime); WRITEUINT32(save_p, players[i].airtime);
WRITEINT16(save_p, players[i].bumpers); WRITEUINT8(save_p, players[i].bumpers);
WRITEINT16(save_p, players[i].karmadelay); WRITEINT16(save_p, players[i].karmadelay);
WRITEUINT8(save_p, players[i].eliminated); WRITEUINT8(save_p, players[i].eliminated);
@ -447,7 +447,7 @@ static void P_NetUnArchivePlayers(void)
players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save_p); players[i].nextwaypoint = (waypoint_t *)(size_t)READUINT32(save_p);
players[i].airtime = READUINT32(save_p); players[i].airtime = READUINT32(save_p);
players[i].bumpers = READINT16(save_p); players[i].bumpers = READUINT8(save_p);
players[i].karmadelay = READINT16(save_p); players[i].karmadelay = READINT16(save_p);
players[i].eliminated = (boolean)READUINT8(save_p); players[i].eliminated = (boolean)READUINT8(save_p);