Player death uses damage types

- Fixed last place elimination not working (again)
- Replaces squishing from level geometry with good old fashioned crush death
This commit is contained in:
Sally Coolatta 2020-09-25 16:31:10 -04:00
parent f31923d2d6
commit 285ec3e08c
15 changed files with 173 additions and 194 deletions

View file

@ -3028,7 +3028,7 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum)
if (!P_IsObjectOnGround(players[respawnplayer].mo))
return;
K_DoIngameRespawn(&players[respawnplayer]);
K_DoIngameRespawn(&players[respawnplayer], false);
demo_extradata[playernum] |= DXD_RESPAWN;
}
}

View file

@ -11267,6 +11267,7 @@ struct {
{"DMG_DEATHPIT",DMG_DEATHPIT},
{"DMG_CRUSHED",DMG_CRUSHED},
{"DMG_SPECTATOR",DMG_SPECTATOR},
{"DMG_TIMEOVER",DMG_TIMEOVER},
//// Masks
{"DMG_STEAL",DMG_CANTHURTSELF},
{"DMG_CANTHURTSELF",DMG_CANTHURTSELF},

View file

@ -500,7 +500,7 @@ void DRPC_UpdatePresence(void)
// This way, we can use the invite feature in-dev, but not have snoopers seeing any potential secrets! :P
discordPresence.largeImageKey = "miscdevelop";
discordPresence.largeImageText = "No peeking!";
discordPresence.state = "Testing the game";
discordPresence.state = "Development EXE";
DRPC_EmptyRequests();
Discord_UpdatePresence(&discordPresence);

View file

@ -243,7 +243,7 @@ void G_ReadDemoExtraData(void)
if (players[p].mo)
{
// Is this how this should work..?
K_DoIngameRespawn(&players[p]);
K_DoIngameRespawn(&players[p], false);
}
}
if (extradata & DXD_SKIN)

View file

@ -2310,7 +2310,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
if (leveltime > (starttime + (TICRATE/2)) && !p->spectator)
{
K_DoIngameRespawn(p);
K_DoIngameRespawn(p, true);
}
}
@ -2373,7 +2373,7 @@ void G_SpawnPlayer(INT32 playernum)
void G_MovePlayerToSpawnOrStarpost(INT32 playernum)
{
if (players[playernum].starpostnum)
if (leveltime > starttime)
P_MovePlayerToStarpost(playernum);
else
P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum));

View file

@ -86,11 +86,11 @@ static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint)
}
/*--------------------------------------------------
void K_DoIngameRespawn(player_t *player)
void K_DoIngameRespawn(player_t *player, boolean fromTheDead)
See header file for description.
--------------------------------------------------*/
void K_DoIngameRespawn(player_t *player)
void K_DoIngameRespawn(player_t *player, boolean fromTheDead)
{
if (!player->mo || P_MobjWasRemoved(player->mo))
{
@ -125,7 +125,10 @@ void K_DoIngameRespawn(player_t *player)
if (player->respawn.wp != NULL && leveltime >= starttime)
{
const UINT32 dist = RESPAWN_DIST + (player->airtime * 48);
player->respawn.distanceleft = (dist * mapobjectscale) / FRACUNIT;
if (fromTheDead == true)
player->respawn.distanceleft = 0;
else
player->respawn.distanceleft = (dist * mapobjectscale) / FRACUNIT;
K_RespawnAtWaypoint(player, player->respawn.wp);
}
else
@ -674,37 +677,6 @@ static void K_HandleDropDash(player_t *player)
//P_PlayRinglossSound(player->mo);
P_PlayerRingBurst(player, 3);
if (gametype == GT_BATTLE)
{
if (player->kartstuff[k_bumper] > 0)
{
if (player->kartstuff[k_bumper] == 1)
{
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->kartstuff[k_bumper]--;
if (K_IsPlayerWanted(player))
K_CalculateBattleWanted();
}
if (!player->kartstuff[k_bumper])
{
player->kartstuff[k_comebacktimer] = 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();
}
player->respawn.state = RESPAWNST_NONE;
}
}

View file

@ -39,19 +39,20 @@ fixed_t K_RespawnOffset(player_t *player, boolean flip);
/*--------------------------------------------------
void K_DoIngameRespawn(player_t *player);
void K_DoIngameRespawn(player_t *player, boolean fromTheDead);
Starts the respawning animation for the specified player,
updating their respawn variables in preparation.
Input Arguments:-
player - Player to preform this for.
fromTheDead - Doesn't set the distance variable. If respawning from dying, then this should be true.
Return:-
None
--------------------------------------------------*/
void K_DoIngameRespawn(player_t *player);
void K_DoIngameRespawn(player_t *player, boolean fromTheDead);
/*--------------------------------------------------

View file

@ -11174,7 +11174,7 @@ void A_RemoteDamage(mobj_t *actor)
if (locvar2 == 1) // Kill mobj!
{
if (target->player)
K_DoIngameRespawn(target->player);
K_DoIngameRespawn(target->player, false);
else
P_KillMobj(target, source, source, DMG_NORMAL);
}

View file

@ -34,6 +34,7 @@
#include "k_battle.h"
#include "k_pwrlv.h"
#include "k_grandprix.h"
#include "k_respawn.h"
#include "p_spec.h"
// CTF player names
@ -953,14 +954,14 @@ boolean P_CheckRacers(void)
}
}
if (eliminatelast == true && (numplayersingame <= numexiting-1))
if (eliminatelast == true && (numexiting >= numplayersingame-1))
{
// Everyone's done playing but one guy apparently.
// Just kill everyone who is still playing.
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || players[i].lives <= 0) // Not playing
if (!playeringame[i] || players[i].spectator || players[i].lives <= 0)
{
// Y'all aren't even playing
continue;
@ -1645,58 +1646,59 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
return true;
}
static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
static boolean P_KillPlayer(player_t *player, UINT8 type)
{
(void)source;
if (player->exiting)
{
player->mo->destscale = 1;
return false;
}
K_RemoveBumper(player, NULL, NULL);
switch (type)
{
case DMG_DEATHPIT:
// Respawn kill types
K_DoIngameRespawn(player, false);
return false;
default:
// Everything else REALLY kills
break;
}
player->pflags &= ~PF_SLIDING;
player->powers[pw_carry] = CR_NONE;
// Get rid of shield
player->powers[pw_shield] = SH_NONE;
player->mo->color = player->skincolor;
player->mo->colorized = false;
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
P_ResetPlayer(player);
if (!player->spectator)
if (player->spectator == false)
{
player->mo->drawflags &= ~MFD_DONTDRAW;
}
P_SetPlayerMobjState(player->mo, player->mo->info->deathstate);
if (player->pflags & PF_GAMETYPEOVER)
if (type == DMG_TIMEOVER)
{
mobj_t *boom;
player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP);
player->mo->drawflags |= MFD_DONTDRAW;
boom = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FZEROBOOM);
boom->scale = player->mo->scale;
boom->angle = player->mo->angle;
P_SetTarget(&boom->target, player->mo);
}
if ((gametyperules & GTR_BUMPERS))
{
if (player->kartstuff[k_bumper] > 0)
{
if (player->kartstuff[k_bumper] == 1)
{
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->kartstuff[k_bumper]--;
if (K_IsPlayerWanted(player))
K_CalculateBattleWanted();
}
K_CheckBumpers();
}
return true;
}
void P_RemoveShield(player_t *player)
@ -1828,122 +1830,129 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
}
// Instant-Death
if (damagetype & DMG_DEATHMASK)
P_KillPlayer(player, source, damage);
if ((damagetype & DMG_DEATHMASK))
{
P_KillPlayer(player, damagetype);
}
else if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype))
{
return true;
// Check if the player is allowed to be damaged!
// If not, then spawn the instashield effect instead.
if (!force)
{
if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0)
{
// Full invulnerability
K_DoInstashield(player);
return false;
}
if (combo == false)
{
if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2))
{
// Post-hit invincibility
K_DoInstashield(player);
return false;
}
}
if (gametyperules & GTR_BUMPERS)
{
if ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1)
{
// No bumpers, can't be hurt
K_DoInstashield(player);
return false;
}
}
else
{
if (damagetype & DMG_STEAL)
{
// Gametype does not have bumpers, steal damage is intended to not do anything
// (No instashield is intentional)
return false;
}
}
}
// We successfully hit 'em!
if (type != DMG_STING)
{
if (source && source != player->mo && source->player)
{
K_PlayHitEmSound(source);
if (damagetype & DMG_STEAL)
{
K_StealBumper(source->player, player);
}
}
K_RemoveBumper(player, inflictor, source);
}
player->kartstuff[k_sneakertimer] = player->kartstuff[k_numsneakers] = 0;
player->kartstuff[k_driftboost] = 0;
player->kartstuff[k_ringboost] = 0;
player->kartstuff[k_drift] = player->kartstuff[k_driftcharge] = 0;
player->kartstuff[k_pogospring] = 0;
switch (type)
{
case DMG_STING:
K_DebtStingPlayer(player, source);
K_KartPainEnergyFling(player);
ringburst = 0;
break;
case DMG_EXPLODE:
K_ExplodePlayer(player, inflictor, source);
break;
case DMG_WIPEOUT:
if (P_IsDisplayPlayer(player))
P_StartQuake(32<<FRACBITS, 5);
K_SpinPlayer(player, inflictor, source, 1);
K_KartPainEnergyFling(player);
break;
case DMG_NORMAL:
default:
K_SpinPlayer(player, inflictor, source, 0);
break;
}
if (type != DMG_STING)
player->powers[pw_flashing] = K_GetKartFlashing(player);
P_PlayRinglossSound(player->mo);
P_PlayerRingBurst(player, ringburst);
K_PlayPainSound(player->mo);
if ((type == DMG_EXPLODE) || (cv_kartdebughuddrop.value && !modeattacking))
{
K_DropItems(player);
}
else
{
K_DropHnextList(player, false);
// Check if the player is allowed to be damaged!
// If not, then spawn the instashield effect instead.
if (!force)
{
if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0)
{
// Full invulnerability
K_DoInstashield(player);
return false;
}
if (combo == false)
{
if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2))
{
// Post-hit invincibility
K_DoInstashield(player);
return false;
}
}
if (gametyperules & GTR_BUMPERS)
{
if ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1)
{
// No bumpers, can't be hurt
K_DoInstashield(player);
return false;
}
}
else
{
if (damagetype & DMG_STEAL)
{
// Gametype does not have bumpers, steal damage is intended to not do anything
// (No instashield is intentional)
return false;
}
}
}
// We successfully hit 'em!
if (type != DMG_STING)
{
if (source && source != player->mo && source->player)
{
K_PlayHitEmSound(source);
if (damagetype & DMG_STEAL)
{
K_StealBumper(source->player, player);
}
}
K_RemoveBumper(player, inflictor, source);
}
player->kartstuff[k_sneakertimer] = player->kartstuff[k_numsneakers] = 0;
player->kartstuff[k_driftboost] = 0;
player->kartstuff[k_ringboost] = 0;
switch (type)
{
case DMG_STING:
K_DebtStingPlayer(player, source);
K_KartPainEnergyFling(player);
ringburst = 0;
break;
case DMG_EXPLODE:
K_ExplodePlayer(player, inflictor, source);
break;
case DMG_WIPEOUT:
if (P_IsDisplayPlayer(player))
P_StartQuake(32<<FRACBITS, 5);
K_SpinPlayer(player, inflictor, source, 1);
K_KartPainEnergyFling(player);
break;
case DMG_NORMAL:
default:
K_SpinPlayer(player, inflictor, source, 0);
break;
}
if (type != DMG_STING)
player->powers[pw_flashing] = K_GetKartFlashing(player);
P_PlayRinglossSound(player->mo);
if (ringburst > 0)
P_PlayerRingBurst(player, ringburst);
K_PlayPainSound(player->mo);
if ((type == DMG_EXPLODE) || (cv_kartdebughuddrop.value && !modeattacking))
{
K_DropItems(player);
}
else
{
K_DropHnextList(player, false);
}
player->kartstuff[k_instashield] = 15;
return true;
}
player->kartstuff[k_instashield] = 15;
return true;
}
if (damagetype & DMG_STEAL)
else
{
// Not a player, steal damage is intended to not do anything
return false;
if (damagetype & DMG_STEAL)
{
// Not a player, steal damage is intended to not do anything
return false;
}
}
// do the damage
@ -2030,7 +2039,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType);
mo->threshold = 10;
mo->fuse = 120*TICRATE;
mo->fuse = 60*TICRATE;
P_SetTarget(&mo->target, player->mo);
mo->destscale = player->mo->scale;

View file

@ -469,6 +469,7 @@ typedef struct BasicFF_s
#define DMG_DEATHPIT 0x81
#define DMG_CRUSHED 0x82
#define DMG_SPECTATOR 0x83
#define DMG_TIMEOVER 0x84
// Masks
#define DMG_STEAL 0x20 // Flag - can steal bumpers, will only deal damage to players, and will not deal damage outside Battle Mode.
#define DMG_CANTHURTSELF 0x40 // Flag - cannot hurt your self or your team

View file

@ -1232,7 +1232,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->player)
{
// Doesn't matter what gravity player's following! Just do your stuff in YOUR direction only
/*
if (tmthing->eflags & MFE_VERTICALFLIP
&& (tmthing->z + tmthing->height + tmthing->momz < thing->z
|| tmthing->z + tmthing->height + tmthing->momz >= thing->z + thing->height))
@ -1256,7 +1255,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
// to get the point if he topples it on an opponent.
}
}
*/
if (tmthing->type == MT_FAN || tmthing->type == MT_STEAM)
P_DoFanAndGasJet(tmthing, thing);

View file

@ -10314,7 +10314,7 @@ void P_MovePlayerToStarpost(INT32 playernum)
mobj_t *mobj = p->mo;
I_Assert(mobj != NULL);
K_DoIngameRespawn(p);
K_DoIngameRespawn(p, true);
P_UnsetThingPosition(mobj);
mobj->x = p->respawn.pointx;

View file

@ -1992,7 +1992,7 @@ static void K_HandleLapIncrement(player_t *player)
if (leveltime < starttime)
{
// Will fault the player
K_DoIngameRespawn(player);
K_DoIngameRespawn(player, false);
}
else if ((player->starpostnum == numstarposts) || (player->laps == 0))
{
@ -4449,10 +4449,10 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
case 6: // Death Pit (Camera Mod)
case 7: // Death Pit (No Camera Mod)
if (roversector || P_MobjReadyToTrigger(player->mo, sector))
K_DoIngameRespawn(player); // DMG_DEATHPIT eventually
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT);
break;
case 8: // Instant Kill
K_DoIngameRespawn(player); // DMG_INSTAKILL eventually
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL);
break;
case 9: // Ring Drainer (Floor Touch)
case 10: // Ring Drainer (No Floor Touch)

View file

@ -480,8 +480,12 @@ boolean P_PlayerInPain(player_t *player)
void P_ResetPlayer(player_t *player)
{
//player->pflags &= ~(PF_);
player->powers[pw_carry] = CR_NONE;
player->onconveyor = 0;
player->kartstuff[k_drift] = player->kartstuff[k_driftcharge] = 0;
player->kartstuff[k_pogospring] = 0;
}
//
@ -2352,10 +2356,7 @@ void P_MovePlayer(player_t *player)
if ((netgame || multiplayer) && player->spectator)
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators
else
{
K_SquishPlayer(player, NULL, NULL); // SRB2kart - we don't kill when squished, we squish when squished.
// P_DamageMobj(player->mo, NULL, NULL, 1, DMG_CRUSHED);
}
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_CRUSHED);
if (player->playerstate == PST_DEAD)
return;
@ -3778,7 +3779,7 @@ void P_DoTimeOver(player_t *player)
if (player->mo)
{
S_StopSound(player->mo);
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL);
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_TIMEOVER);
}
P_EndingMusic(player);

View file

@ -229,10 +229,6 @@ void SplitScreen_OnChange(void)
}
static void Fov_OnChange(void)
{
// Shouldn't be needed with render parity?
//if ((netgame || multiplayer) && !cv_debug && cv_fov.value != 90*FRACUNIT)
// CV_Set(&cv_fov, cv_fov.defaultvalue);
R_SetViewSize();
}