Partial damage system overhaul: P_DamageMobj, P_KillMobj, P_HitDeathMessages and P_RingDamage now all take a "damagetype" variable that determines what type of damage was dealt. Does not replace the "damage" variable, we'll have to see if that is worth keeping another time?

Currently the main benefit of these changes is that a number of non-Object-related hazards/deaths no long rely on dummy MT_NULL objects or other hacks to tell the game how you were hurt/killed, yay

git-svn-id: https://code.orospakr.ca/svn/srb2/trunk@9039 6de4a73c-47e2-0310-b8c1-93d6ecd3f8cd
This commit is contained in:
MonsterIestyn 2015-02-13 16:15:58 +00:00 committed by Ronald Kinard
parent ff8c09922d
commit e83fa3dc43
13 changed files with 226 additions and 188 deletions

View File

@ -1911,7 +1911,7 @@ static void Got_Suicide(UINT8 **cp, INT32 playernum)
} }
if (players[suicideplayer].mo) if (players[suicideplayer].mo)
P_DamageMobj(players[suicideplayer].mo, NULL, NULL, 10000); P_DamageMobj(players[suicideplayer].mo, NULL, NULL, 1, DMG_INSTAKILL);
} }
/** Deals with an ::XD_RANDOMSEED message in a netgame. /** Deals with an ::XD_RANDOMSEED message in a netgame.
@ -2442,7 +2442,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
if (players[playernum].mo) if (players[playernum].mo)
{ {
if (!players[playernum].spectator) if (!players[playernum].spectator)
P_DamageMobj(players[playernum].mo, NULL, NULL, 10000); P_DamageMobj(players[playernum].mo, NULL, NULL, 1, DMG_INSTAKILL);
else else
{ {
P_RemoveMobj(players[playernum].mo); P_RemoveMobj(players[playernum].mo);

View File

@ -4134,7 +4134,7 @@ void G_ConsGhostTic(void)
if (demosynced) if (demosynced)
CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
demosynced = false; demosynced = false;
P_DamageMobj(mobj, players[0].mo, players[0].mo, 1); P_DamageMobj(mobj, players[0].mo, players[0].mo, 1, 0);
} }
} }
} }

View File

@ -1037,6 +1037,7 @@ static int lib_pDamageMobj(lua_State *L)
{ {
mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL; mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL;
INT32 damage; INT32 damage;
UINT8 damagetype;
NOHUD NOHUD
if (!target) if (!target)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
@ -1045,13 +1046,15 @@ static int lib_pDamageMobj(lua_State *L)
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
damage = (INT32)luaL_optinteger(L, 4, 1); damage = (INT32)luaL_optinteger(L, 4, 1);
lua_pushboolean(L, P_DamageMobj(target, inflictor, source, damage)); damagetype = (UINT8)luaL_optinteger(L, 5, 0);
lua_pushboolean(L, P_DamageMobj(target, inflictor, source, damage, damagetype));
return 1; return 1;
} }
static int lib_pKillMobj(lua_State *L) static int lib_pKillMobj(lua_State *L)
{ {
mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL; mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL;
UINT8 damagetype;
NOHUD NOHUD
if (!target) if (!target)
return LUA_ErrInvalid(L, "mobj_t"); return LUA_ErrInvalid(L, "mobj_t");
@ -1059,7 +1062,8 @@ static int lib_pKillMobj(lua_State *L)
inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
P_KillMobj(target, inflictor, source); damagetype = (UINT8)luaL_optinteger(L, 4, 0);
P_KillMobj(target, inflictor, source, damagetype);
return 0; return 0;
} }

View File

@ -372,7 +372,7 @@ void Command_Hurtme_f(void)
return; return;
} }
P_DamageMobj(players[consoleplayer].mo, NULL, NULL, atoi(COM_Argv(1))); P_DamageMobj(players[consoleplayer].mo, NULL, NULL, atoi(COM_Argv(1)), 0);
} }
// Moves the NiGHTS player to another axis within the current mare // Moves the NiGHTS player to another axis within the current mare

View File

@ -4813,7 +4813,7 @@ void A_UnidusBall(mobj_t *actor)
boolean skull = (actor->target->flags2 & MF2_SKULLFLY) == MF2_SKULLFLY; boolean skull = (actor->target->flags2 & MF2_SKULLFLY) == MF2_SKULLFLY;
if (actor->target->state == &states[actor->target->info->painstate]) if (actor->target->state == &states[actor->target->info->painstate])
{ {
P_KillMobj(actor, NULL, NULL); P_KillMobj(actor, NULL, NULL, 0);
return; return;
} }
switch(actor->extravalue2) switch(actor->extravalue2)
@ -5278,7 +5278,7 @@ void A_RingExplode(mobj_t *actor)
if (mo2->flags & MF_SHOOTABLE) if (mo2->flags & MF_SHOOTABLE)
{ {
actor->flags2 |= MF2_DEBRIS; actor->flags2 |= MF2_DEBRIS;
P_DamageMobj(mo2, actor, actor->target, 1); P_DamageMobj(mo2, actor, actor->target, 1, 0);
continue; continue;
} }
} }
@ -6383,7 +6383,7 @@ void A_EggmanBox(mobj_t *actor)
return; return;
} }
P_DamageMobj(actor->target, actor, actor, 1); // Ow! P_DamageMobj(actor->target, actor, actor, 1, 0); // Ow!
} }
// Function: A_TurretFire // Function: A_TurretFire
@ -9368,9 +9368,9 @@ void A_RemoteDamage(mobj_t *actor)
if (locvar2 == 1) // Kill mobj! if (locvar2 == 1) // Kill mobj!
{ {
if (target->player) // players die using P_DamageMobj instead for some reason if (target->player) // players die using P_DamageMobj instead for some reason
P_DamageMobj(target, source, source, 10000); P_DamageMobj(target, source, source, 1, DMG_INSTAKILL);
else else
P_KillMobj(target, source, source); P_KillMobj(target, source, source, 0);
} }
else if (locvar2 == 2) // Remove mobj! else if (locvar2 == 2) // Remove mobj!
{ {
@ -9380,7 +9380,7 @@ void A_RemoteDamage(mobj_t *actor)
P_RemoveMobj(target); P_RemoveMobj(target);
} }
else // default: Damage mobj! else // default: Damage mobj!
P_DamageMobj(target, source, source, 1); P_DamageMobj(target, source, source, 1, 0);
} }
// Function: A_HomingChase // Function: A_HomingChase
@ -9615,7 +9615,7 @@ void A_VileAttack(mobj_t *actor)
return; return;
S_StartSound(actor, soundtoplay); S_StartSound(actor, soundtoplay);
P_DamageMobj(actor->target, actor, actor, 1); P_DamageMobj(actor->target, actor, actor, 1, 0);
//actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it //actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it
actor->target->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(actor->target); // How we're doing it actor->target->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(actor->target); // How we're doing it
if (explosionType != MT_NULL) if (explosionType != MT_NULL)
@ -9656,7 +9656,7 @@ void A_VileAttack(mobj_t *actor)
continue; continue;
S_StartSound(actor, soundtoplay); S_StartSound(actor, soundtoplay);
P_DamageMobj(players[i].mo, actor, actor, 1); P_DamageMobj(players[i].mo, actor, actor, 1, 0);
//actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it //actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it
players[i].mo->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(players[i].mo); // How we're doing it players[i].mo->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(players[i].mo); // How we're doing it
if (explosionType != MT_NULL) if (explosionType != MT_NULL)

View File

@ -1215,9 +1215,7 @@ void T_SpikeSector(levelspecthink_t *spikes)
if (dothepain) if (dothepain)
{ {
mobj_t *killer = P_SpawnMobj(thing->x, thing->y, thing->z, MT_NULL); P_DamageMobj(thing, NULL, NULL, 1, DMG_SPIKE);
killer->threshold = 43; // Special flag that it was spikes which hurt you.
P_DamageMobj(thing, killer, killer, 1);
break; break;
} }
} }
@ -3125,7 +3123,7 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob
thing->momz = FixedMul(6*FRACUNIT, thing->scale); thing->momz = FixedMul(6*FRACUNIT, thing->scale);
P_SetThingPosition(thing); P_SetThingPosition(thing);
if (thing->flags & MF_SHOOTABLE) if (thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, puncher, puncher, 1); P_DamageMobj(thing, puncher, puncher, 1, 0);
else if (thing->type == MT_RING || thing->type == MT_COIN) else if (thing->type == MT_RING || thing->type == MT_COIN)
{ {
thing->momz = FixedMul(3*FRACUNIT, thing->scale); thing->momz = FixedMul(3*FRACUNIT, thing->scale);

View File

@ -291,7 +291,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{ {
if (special->type == MT_BLACKEGGMAN) if (special->type == MT_BLACKEGGMAN)
{ {
P_DamageMobj(toucher, special, special, 1); // ouch P_DamageMobj(toucher, special, special, 1, 0); // ouch
return; return;
} }
@ -303,7 +303,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
toucher->momz = -toucher->momz; toucher->momz = -toucher->momz;
toucher->momx = -toucher->momx; toucher->momx = -toucher->momx;
toucher->momy = -toucher->momy; toucher->momy = -toucher->momy;
P_DamageMobj(special, toucher, toucher, 1); P_DamageMobj(special, toucher, toucher, 1, 0);
} }
else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP)) else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP))
|| (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP))) || (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP)))
@ -313,10 +313,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{ {
toucher->momz = -toucher->momz/2; toucher->momz = -toucher->momz/2;
P_DamageMobj(special, toucher, toucher, 1); P_DamageMobj(special, toucher, toucher, 1, 0);
} }
else else
P_DamageMobj(toucher, special, special, 1); P_DamageMobj(toucher, special, special, 1, 0);
return; return;
} }
@ -330,13 +330,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
&& toucher->z < special->z + special->height && toucher->z + toucher->height > special->z) && toucher->z < special->z + special->height && toucher->z + toucher->height > special->z)
{ {
// Can only hit snapper from above // Can only hit snapper from above
P_DamageMobj(toucher, special, special, 1); P_DamageMobj(toucher, special, special, 1, 0);
} }
else if (special->type == MT_SHARP else if (special->type == MT_SHARP
&& ((special->state == &states[special->info->xdeathstate]) || (toucher->z > special->z + special->height/2))) && ((special->state == &states[special->info->xdeathstate]) || (toucher->z > special->z + special->height/2)))
{ {
// Cannot hit sharp from above or when red and angry // Cannot hit sharp from above or when red and angry
P_DamageMobj(toucher, special, special, 1); P_DamageMobj(toucher, special, special, 1, 0);
} }
else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING))
|| (player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING)) || (player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING))
@ -345,7 +345,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (P_MobjFlip(toucher)*toucher->momz < 0) if (P_MobjFlip(toucher)*toucher->momz < 0)
toucher->momz = -toucher->momz; toucher->momz = -toucher->momz;
P_DamageMobj(special, toucher, toucher, 1); P_DamageMobj(special, toucher, toucher, 1, 0);
} }
else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP)) else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP))
|| (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP))) // Flame is bad at logic - JTE || (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP))) // Flame is bad at logic - JTE
@ -356,16 +356,16 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (P_MobjFlip(toucher)*toucher->momz < 0) if (P_MobjFlip(toucher)*toucher->momz < 0)
toucher->momz = -toucher->momz/2; toucher->momz = -toucher->momz/2;
P_DamageMobj(special, toucher, toucher, 1); P_DamageMobj(special, toucher, toucher, 1, 0);
} }
else else
P_DamageMobj(toucher, special, special, 1); P_DamageMobj(toucher, special, special, 1, 0);
return; return;
} }
else if (special->flags & MF_FIRE) else if (special->flags & MF_FIRE)
{ {
P_DamageMobj(toucher, special, special, 1); P_DamageMobj(toucher, special, special, 1, DMG_FIRE);
return; return;
} }
else else
@ -743,7 +743,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (mo2->flags & MF_SHOOTABLE) if (mo2->flags & MF_SHOOTABLE)
{ {
P_DamageMobj(mo2, toucher, toucher, 1); P_DamageMobj(mo2, toucher, toucher, 1, 0);
continue; continue;
} }
@ -1351,7 +1351,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
case MT_SPECIALSPIKEBALL: case MT_SPECIALSPIKEBALL:
if (!(!useNightsSS && G_IsSpecialStage(gamemap))) // Only for old special stages if (!(!useNightsSS && G_IsSpecialStage(gamemap))) // Only for old special stages
{ {
P_DamageMobj(toucher, special, special, 1); P_DamageMobj(toucher, special, special, 1, 0);
return; return;
} }
@ -1382,7 +1382,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Goomba Stomp'd! // Goomba Stomp'd!
if (special->target->momz < 0) if (special->target->momz < 0)
{ {
P_DamageMobj(toucher, special, special->target, 1); P_DamageMobj(toucher, special, special->target, 1, 0);
//special->target->momz = -special->target->momz; //special->target->momz = -special->target->momz;
special->target->momx = special->target->momy = 0; special->target->momx = special->target->momy = 0;
special->target->momz = 0; special->target->momz = 0;
@ -1446,7 +1446,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
S_StartSound(toucher, special->info->deathsound); // was NULL, but changed to player so you could hear others pick up rings S_StartSound(toucher, special->info->deathsound); // was NULL, but changed to player so you could hear others pick up rings
P_KillMobj(special, NULL, toucher); P_KillMobj(special, NULL, toucher, 0);
} }
#define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : "" #define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""
@ -1457,8 +1457,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
* \param player Affected player. * \param player Affected player.
* \param inflictor The attack weapon used, can be NULL. * \param inflictor The attack weapon used, can be NULL.
* \param source The attacker, can be NULL. * \param source The attacker, can be NULL.
* \param damagetype The type of damage dealt to the player. If bit 7 (0x80) is set, this was an instant-kill.
*/ */
static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *source) static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype)
{ {
const char *str = NULL; const char *str = NULL;
boolean deathonly = false; boolean deathonly = false;
@ -1567,22 +1568,6 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
} }
else switch (source->type) else switch (source->type)
{ {
case MT_NULL:
switch(source->threshold)
{
case 42:
deathonly = true;
str = M_GetText("%s drowned.\n");
break;
case 43:
str = M_GetText("%s was %s by spikes.\n");
break;
case 44:
deathonly = true;
str = M_GetText("%s was crushed.\n");
break;
}
break;
case MT_EGGMANICO: case MT_EGGMANICO:
case MT_EGGMANBOX: case MT_EGGMANBOX:
str = M_GetText("%s was %s by Eggman's nefarious TV magic.\n"); str = M_GetText("%s was %s by Eggman's nefarious TV magic.\n");
@ -1598,30 +1583,52 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
else else
{ {
// null source, environment kills // null source, environment kills
// TERRIBLE HACK for hit damage because P_DoPlayerPain moves the player... switch (damagetype)
// I'll put it back, I promise!
player->mo->z -= player->mo->momz+1;
if (P_PlayerTouchingSectorSpecial(player, 1, 2))
str = M_GetText("%s was %s by chemical water.\n");
else if (P_PlayerTouchingSectorSpecial(player, 1, 3))
str = M_GetText("%s was %s by molten lava.\n");
else if (P_PlayerTouchingSectorSpecial(player, 1, 4))
str = M_GetText("%s was %s by electricity.\n");
else if (deadtarget)
{ {
deathonly = true; case DMG_WATER:
if (P_PlayerTouchingSectorSpecial(player, 1, 6) str = M_GetText("%s was %s by chemical water.\n");
|| P_PlayerTouchingSectorSpecial(player, 1, 7)) break;
str = M_GetText("%s fell into a bottomless pit.\n"); case DMG_FIRE:
else if (P_PlayerTouchingSectorSpecial(player, 1, 12)) str = M_GetText("%s was %s by molten lava.\n");
str = M_GetText("%s asphyxiated in space.\n"); break;
else case DMG_ELECTRIC:
str = M_GetText("%s died.\n"); str = M_GetText("%s was %s by electricity.\n");
break;
case DMG_SPIKE:
str = M_GetText("%s was %s by spikes.\n");
break;
case DMG_DROWNED:
deathonly = true;
str = M_GetText("%s drowned.\n");
break;
case DMG_CRUSHED:
deathonly = true;
str = M_GetText("%s was crushed.\n");
break;
case DMG_DEATHPIT:
if (deadtarget)
{
deathonly = true;
str = M_GetText("%s fell into a bottomless pit.\n");
}
break;
case DMG_SPACEDROWN:
if (deadtarget)
{
deathonly = true;
str = M_GetText("%s asphyxiated in space.\n");
}
break;
default:
if (deadtarget)
{
deathonly = true;
str = M_GetText("%s died.\n");
}
break;
} }
if (!str) if (!str)
str = M_GetText("%s was %s by an environmental hazard.\n"); str = M_GetText("%s was %s by an environmental hazard.\n");
player->mo->z += player->mo->momz+1;
} }
if (!str) // Should not happen! Unless we missed catching something above. if (!str) // Should not happen! Unless we missed catching something above.
@ -1799,10 +1806,11 @@ boolean P_CheckRacers(void)
* \param target The victim. * \param target The victim.
* \param inflictor The attack weapon. May be NULL (environmental damage). * \param inflictor The attack weapon. May be NULL (environmental damage).
* \param source The attacker. May be NULL. * \param source The attacker. May be NULL.
* \param damagetype The type of damage dealt that killed the target. If bit 7 (0x80) was set, this was an instant-death.
* \todo Cleanup, refactor, split up. * \todo Cleanup, refactor, split up.
* \sa P_DamageMobj * \sa P_DamageMobj
*/ */
void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype)
{ {
mobjtype_t item; mobjtype_t item;
mobj_t *mo; mobj_t *mo;
@ -2126,15 +2134,19 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
case MT_PLAYER: case MT_PLAYER:
target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player) target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player)
target->momx = target->momy = target->momz = 0; target->momx = target->momy = target->momz = 0;
if (!(source && source->type == MT_NULL && source->threshold == 42)) // Don't jump up when drowning if (damagetype == DMG_DROWNED) // drowned
P_SetObjectMomZ(target, 14*FRACUNIT, false); {
if (source && source->type == MT_NULL && source->threshold == 42) // drowned
S_StartSound(target, sfx_drown); S_StartSound(target, sfx_drown);
else if (source && (source->type == MT_SPIKE || (source->type == MT_NULL && source->threshold == 43))) // Spikes // Don't jump up when drowning
S_StartSound(target, sfx_spkdth); }
else else
P_PlayDeathSound(target); {
P_SetObjectMomZ(target, 14*FRACUNIT, false);
if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // Spikes
S_StartSound(target, sfx_spkdth);
else
P_PlayDeathSound(target);
}
break; break;
default: default:
break; break;
@ -2384,7 +2396,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
if (source->player->pflags & PF_TAGIT && !(player->pflags & PF_TAGIT)) if (source->player->pflags & PF_TAGIT && !(player->pflags & PF_TAGIT))
{ {
P_AddPlayerScore(source->player, 100); //award points to tagger. P_AddPlayerScore(source->player, 100); //award points to tagger.
P_HitDeathMessages(player, inflictor, source); P_HitDeathMessages(player, inflictor, source, 0);
if (gametype == GT_TAG) //survivor if (gametype == GT_TAG) //survivor
{ {
@ -2640,7 +2652,7 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source,
} }
} }
static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage) static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
{ {
if (!(inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) if (!(inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])))
{ {
@ -2648,7 +2660,7 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if (source && (source->type == MT_SPIKE || (source->type == MT_NULL && source->threshold == 43))) // spikes if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // spikes
S_StartSound(player->mo, sfx_spkdth); S_StartSound(player->mo, sfx_spkdth);
} }
@ -2677,21 +2689,21 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
/** Damages an object, which may or may not be a player. /** Damages an object, which may or may not be a player.
* For melee attacks, source and inflictor are the same. * For melee attacks, source and inflictor are the same.
* *
* \param target The object being damaged. * \param target The object being damaged.
* \param inflictor The thing that caused the damage: creature, missile, * \param inflictor The thing that caused the damage: creature, missile,
* gargoyle, and so forth. Can be NULL in the case of * gargoyle, and so forth. Can be NULL in the case of
* environmental damage, such as slime or crushing. * environmental damage, such as slime or crushing.
* \param source The creature or person responsible. For example, if a * \param source The creature or person responsible. For example, if a
* player is hit by a ring, the player who shot it. In some * player is hit by a ring, the player who shot it. In some
* cases, the target will go after this object after * cases, the target will go after this object after
* receiving damage. This can be NULL. * receiving damage. This can be NULL.
* \param damage Amount of damage to be dealt. 10000 is instant death. * \param damage Amount of damage to be dealt.
* \param damagetype Type of damage to be dealt. If bit 7 (0x80) is set, this is an instant-kill.
* \return True if the target sustained damage, otherwise false. * \return True if the target sustained damage, otherwise false.
* \todo Clean up this mess, split into multiple functions. * \todo Clean up this mess, split into multiple functions.
* \todo Get rid of the magic number 10000.
* \sa P_KillMobj * \sa P_KillMobj
*/ */
boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
{ {
player_t *player; player_t *player;
#ifdef HAVE_BLUA #ifdef HAVE_BLUA
@ -2709,9 +2721,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
// Spectator handling // Spectator handling
if (netgame) if (netgame)
{ {
if (damage == 42000 && target->player && target->player->spectator) if (damagetype != DMG_SPECTATOR && target->player && target->player->spectator)
damage = 10000;
else if (target->player && target->player->spectator)
return false; return false;
if (source && source->player && source->player->spectator) if (source && source->player && source->player->spectator)
@ -2819,6 +2829,21 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (!(target->player->pflags & (PF_NIGHTSMODE|PF_NIGHTSFALL)) && (maptol & TOL_NIGHTS)) if (!(target->player->pflags & (PF_NIGHTSMODE|PF_NIGHTSFALL)) && (maptol & TOL_NIGHTS))
return false; return false;
switch (damagetype)
{
case DMG_WATER:
case DMG_FIRE:
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)
return false; // Invincible to water/fire damage
break;
case DMG_ELECTRIC:
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT)
return false; // Invincible to electric damage
break;
default:
break;
}
} }
if (player->pflags & PF_NIGHTSMODE) // NiGHTS damage handling if (player->pflags & PF_NIGHTSMODE) // NiGHTS damage handling
@ -2840,12 +2865,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
return true; return true;
} }
if (!force && inflictor && (inflictor->flags & MF_FIRE)) if (!force && inflictor && inflictor->flags & MF_FIRE)
{ {
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)
return false; // Invincible to fire objects return false; // Invincible to fire objects
if (G_PlatformGametype() && source && source->player) if (G_PlatformGametype() && inflictor && source && source->player)
return false; // Don't get hurt by fire generated from friends. return false; // Don't get hurt by fire generated from friends.
} }
@ -2854,7 +2879,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
{ {
if ((gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF) && cv_suddendeath.value if ((gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF) && cv_suddendeath.value
&& !player->powers[pw_flashing] && !player->powers[pw_invulnerability]) && !player->powers[pw_flashing] && !player->powers[pw_invulnerability])
damage = 10000; damagetype = DMG_INSTAKILL;
} }
// Player hits another player // Player hits another player
@ -2868,7 +2893,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
return false; return false;
// Instant-Death // Instant-Death
if (damage == 10000) if (damagetype & DMG_DEATHMASK)
P_KillPlayer(player, source, damage); P_KillPlayer(player, source, damage);
else if (metalrecording) else if (metalrecording)
{ {
@ -2876,7 +2901,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
inflictor = source; inflictor = source;
if (inflictor && inflictor->flags & MF_ENEMY) if (inflictor && inflictor->flags & MF_ENEMY)
{ // Metal Sonic destroy enemy !! { // Metal Sonic destroy enemy !!
P_KillMobj(inflictor, NULL, target); P_KillMobj(inflictor, NULL, target, damagetype);
return false; return false;
} }
else if (inflictor && inflictor->flags & MF_MISSILE) else if (inflictor && inflictor->flags & MF_MISSILE)
@ -2915,7 +2940,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
else if (player->mo->health > 1) // No shield but have rings. else if (player->mo->health > 1) // No shield but have rings.
{ {
damage = player->mo->health - 1; damage = player->mo->health - 1;
P_RingDamage(player, inflictor, source, damage); P_RingDamage(player, inflictor, source, damage, damagetype);
} }
else // No shield, no rings, no invincibility. else // No shield, no rings, no invincibility.
{ {
@ -2952,21 +2977,20 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
P_PlayerFlagBurst(player, false); P_PlayerFlagBurst(player, false);
} }
else if (damagetype & DMG_DEATHMASK)
player->health = 0;
else else
{ {
player->health -= damage; // mirror mobj health here player->health -= damage; // mirror mobj health here
if (damage < 10000) target->player->powers[pw_flashing] = flashingtics;
{ if (damage > 0) // don't spill emeralds/ammo/panels for shield damage
target->player->powers[pw_flashing] = flashingtics; P_PlayerRingBurst(player, damage);
if (damage > 0) // don't spill emeralds/ammo/panels for shield damage
P_PlayerRingBurst(player, damage);
}
} }
if (player->health < 0) if (player->health < 0)
player->health = 0; player->health = 0;
P_HitDeathMessages(player, inflictor, source); P_HitDeathMessages(player, inflictor, source, damagetype);
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
} }
@ -2974,7 +2998,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
// Killing dead. Just for kicks. // Killing dead. Just for kicks.
// Require source and inflictor be player. Don't hurt for firing rings. // Require source and inflictor be player. Don't hurt for firing rings.
if (cv_killingdead.value && (source && source->player) && (inflictor && inflictor->player) && P_Random() < 80) if (cv_killingdead.value && (source && source->player) && (inflictor && inflictor->player) && P_Random() < 80)
P_DamageMobj(source, target, target, 1); P_DamageMobj(source, target, target, 1, 0);
// do the damage // do the damage
if (player && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]) && inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player)) if (player && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]) && inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player))
@ -2983,6 +3007,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (target->health < 2) if (target->health < 2)
target->health = 2; target->health = 2;
} }
else if (damagetype & DMG_DEATHMASK)
target->health = 0;
else else
target->health -= damage; target->health -= damage;
@ -2991,7 +3017,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (target->health <= 0) if (target->health <= 0)
{ {
P_KillMobj(target, inflictor, source); P_KillMobj(target, inflictor, source, damagetype);
return true; return true;
} }

View File

@ -342,12 +342,29 @@ typedef struct BasicFF_s
INT32 Magnitude; ///< Magnitude of the effect, in the range from 0 through 10,000. INT32 Magnitude; ///< Magnitude of the effect, in the range from 0 through 10,000.
} BasicFF_t; } BasicFF_t;
/* Damage/death types, for P_DamageMobj and related */
//// Damage types
//#define DMG_NORMAL 0 (unneeded?)
#define DMG_WATER 1
#define DMG_FIRE 2
#define DMG_ELECTRIC 3
#define DMG_SPIKE 4
//#define DMG_SPECIALSTAGE 5
//// Death types - cannot be combined with damage types
#define DMG_INSTAKILL 0x80
#define DMG_DROWNED 0x80+1
#define DMG_SPACEDROWN 0x80+2
#define DMG_DEATHPIT 0x80+3
#define DMG_CRUSHED 0x80+4
#define DMG_SPECTATOR 0x80+5
#define DMG_DEATHMASK DMG_INSTAKILL // if bit 7 is set, this is a death type instead of a damage type
void P_ForceFeed(const player_t *player, INT32 attack, INT32 fade, tic_t duration, INT32 period); void P_ForceFeed(const player_t *player, INT32 attack, INT32 fade, tic_t duration, INT32 period);
void P_ForceConstant(const BasicFF_t *FFInfo); void P_ForceConstant(const BasicFF_t *FFInfo);
void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End); void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End);
void P_RemoveShield(player_t *player); void P_RemoveShield(player_t *player);
boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype);
void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source); void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype);
void P_PlayerRingBurst(player_t *player, INT32 num_rings); /// \todo better fit in p_user.c void P_PlayerRingBurst(player_t *player, INT32 num_rings); /// \todo better fit in p_user.c
void P_PlayerWeaponPanelBurst(player_t *player); void P_PlayerWeaponPanelBurst(player_t *player);
void P_PlayerWeaponAmmoBurst(player_t *player); void P_PlayerWeaponAmmoBurst(player_t *player);

View File

@ -426,12 +426,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
S_StartSound(tmthing, thing->info->deathsound); S_StartSound(tmthing, thing->info->deathsound);
for (thing = thing->subsector->sector->thinglist; thing; thing = thing->snext) for (thing = thing->subsector->sector->thinglist; thing; thing = thing->snext)
if (thing->type == MT_SPIKE && thing->health > 0 && thing->flags & MF_SOLID && P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < FixedMul(56*FRACUNIT, thing->scale)) if (thing->type == MT_SPIKE && thing->health > 0 && thing->flags & MF_SOLID && P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < FixedMul(56*FRACUNIT, thing->scale))
P_KillMobj(thing, tmthing, tmthing); P_KillMobj(thing, tmthing, tmthing, 0);
} }
else else
{ {
thing->health = 0; thing->health = 0;
P_KillMobj(thing, tmthing, tmthing); P_KillMobj(thing, tmthing, tmthing, 0);
} }
return true; return true;
} }
@ -483,7 +483,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
else else
thing->z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale); thing->z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale);
if (thing->flags & MF_SHOOTABLE) if (thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, tmthing, tmthing, 1); P_DamageMobj(thing, tmthing, tmthing, 1, 0);
return true; return true;
} }
@ -495,7 +495,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->z + thing->height < tmthing->z) if (thing->z + thing->height < tmthing->z)
return true; // underneath return true; // underneath
if (tmthing->player && tmthing->flags & MF_SHOOTABLE) if (tmthing->player && tmthing->flags & MF_SHOOTABLE)
P_DamageMobj(tmthing, thing, thing, 1); {
UINT8 damagetype = 0;
if (thing->flags & MF_FIRE) // BURN!
damagetype = DMG_FIRE;
P_DamageMobj(tmthing, thing, thing, 1, damagetype);
}
return true; return true;
} }
else if (tmthing->flags & MF_PAIN) else if (tmthing->flags & MF_PAIN)
@ -506,7 +511,12 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (tmthing->z + tmthing->height < thing->z) if (tmthing->z + tmthing->height < thing->z)
return true; // underneath return true; // underneath
if (thing->player && thing->flags & MF_SHOOTABLE) if (thing->player && thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, tmthing, tmthing, 1); {
UINT8 damagetype = 0;
if (tmthing->flags & MF_FIRE) // BURN!
damagetype = DMG_FIRE;
P_DamageMobj(thing, tmthing, tmthing, 1, damagetype);
}
return true; return true;
} }
@ -627,7 +637,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
return false; return false;
else // hit shield from behind, shield is destroyed! else // hit shield from behind, shield is destroyed!
{ {
P_KillMobj(thing, tmthing, tmthing); P_KillMobj(thing, tmthing, tmthing, 0);
return false; return false;
} }
} }
@ -636,7 +646,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true; return true;
// damage / explode // damage / explode
if (tmthing->flags & MF_ENEMY) // An actual ENEMY! (Like the deton, for example) if (tmthing->flags & MF_ENEMY) // An actual ENEMY! (Like the deton, for example)
P_DamageMobj(thing, tmthing, tmthing, 1); P_DamageMobj(thing, tmthing, tmthing, 1, 0);
else if (tmthing->type == MT_BLACKEGGMAN_MISSILE && thing->player else if (tmthing->type == MT_BLACKEGGMAN_MISSILE && thing->player
&& (thing->player->pflags & PF_JUMPED) && (thing->player->pflags & PF_JUMPED)
&& !thing->player->powers[pw_flashing] && !thing->player->powers[pw_flashing]
@ -672,7 +682,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
P_SetThingPosition(tmthing); P_SetThingPosition(tmthing);
} }
else else
P_DamageMobj(thing, tmthing, tmthing->target, 1); P_DamageMobj(thing, tmthing, tmthing->target, 1, 0);
// don't traverse any more // don't traverse any more
@ -786,11 +796,11 @@ static boolean PIT_CheckThing(mobj_t *thing)
{ {
if (thing->z + thing->height <= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) if (thing->z + thing->height <= tmthing->z + FixedMul(FRACUNIT, tmthing->scale)
&& thing->z + thing->height + thing->momz >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz) && thing->z + thing->height + thing->momz >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz)
P_DamageMobj(thing, tmthing, tmthing, 1); P_DamageMobj(thing, tmthing, tmthing, 1, 0);
} }
else if (thing->z >= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) else if (thing->z >= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale)
&& thing->z + thing->momz <= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz) && thing->z + thing->momz <= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz)
P_DamageMobj(thing, tmthing, tmthing, 1); P_DamageMobj(thing, tmthing, tmthing, 1, 0);
} }
else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tmthing->player) // unfortunate player falls into spike?! else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tmthing->player) // unfortunate player falls into spike?!
{ {
@ -798,11 +808,11 @@ static boolean PIT_CheckThing(mobj_t *thing)
{ {
if (tmthing->z + tmthing->height <= thing->z - FixedMul(FRACUNIT, thing->scale) if (tmthing->z + tmthing->height <= thing->z - FixedMul(FRACUNIT, thing->scale)
&& tmthing->z + tmthing->height + tmthing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)) && tmthing->z + tmthing->height + tmthing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale))
P_DamageMobj(tmthing, thing, thing, 1); P_DamageMobj(tmthing, thing, thing, 1, 0);
} }
else if (tmthing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) else if (tmthing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)
&& tmthing->z + tmthing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)) && tmthing->z + tmthing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale))
P_DamageMobj(tmthing, thing, thing, 1); P_DamageMobj(tmthing, thing, thing, 1, 0);
} }
if (thing->flags & MF_PUSHABLE) if (thing->flags & MF_PUSHABLE)
@ -832,10 +842,10 @@ static boolean PIT_CheckThing(mobj_t *thing)
{ {
if ((tmthing->player->powers[pw_invulnerability] || tmthing->player->powers[pw_super]) if ((tmthing->player->powers[pw_invulnerability] || tmthing->player->powers[pw_super])
&& !thing->player->powers[pw_super]) && !thing->player->powers[pw_super])
P_DamageMobj(thing, tmthing, tmthing, 1); P_DamageMobj(thing, tmthing, tmthing, 1, 0);
else if ((thing->player->powers[pw_invulnerability] || thing->player->powers[pw_super]) else if ((thing->player->powers[pw_invulnerability] || thing->player->powers[pw_super])
&& !tmthing->player->powers[pw_super]) && !tmthing->player->powers[pw_super])
P_DamageMobj(tmthing, thing, thing, 1); P_DamageMobj(tmthing, thing, thing, 1, 0);
} }
// If players are using touch tag, seekers damage hiders. // If players are using touch tag, seekers damage hiders.
@ -843,9 +853,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
((thing->player->pflags & PF_TAGIT) != (tmthing->player->pflags & PF_TAGIT))) ((thing->player->pflags & PF_TAGIT) != (tmthing->player->pflags & PF_TAGIT)))
{ {
if ((tmthing->player->pflags & PF_TAGIT) && !(thing->player->pflags & PF_TAGIT)) if ((tmthing->player->pflags & PF_TAGIT) && !(thing->player->pflags & PF_TAGIT))
P_DamageMobj(thing, tmthing, tmthing, 1); P_DamageMobj(thing, tmthing, tmthing, 1, 0);
else if ((thing->player->pflags & PF_TAGIT) && !(tmthing->player->pflags & PF_TAGIT)) else if ((thing->player->pflags & PF_TAGIT) && !(tmthing->player->pflags & PF_TAGIT))
P_DamageMobj(tmthing, thing, tmthing, 1); P_DamageMobj(tmthing, thing, tmthing, 1, 0);
} }
} }
@ -883,7 +893,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
{ {
// Objects kill you if it falls from above. // Objects kill you if it falls from above.
if (thing != tmthing->target) if (thing != tmthing->target)
P_DamageMobj(thing, tmthing, tmthing->target, 10000); P_DamageMobj(thing, tmthing, tmthing->target, 1, DMG_INSTAKILL);
tmthing->momz = -tmthing->momz/2; // Bounce, just for fun! tmthing->momz = -tmthing->momz/2; // Bounce, just for fun!
// The tmthing->target allows the pusher of the object // The tmthing->target allows the pusher of the object
@ -917,7 +927,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
{ {
SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed. SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed.
fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;; fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;;
P_DamageMobj(thing, tmthing, tmthing, 1); // break the monitor P_DamageMobj(thing, tmthing, tmthing, 1, 0); // break the monitor
// Going down? Then bounce back up. // Going down? Then bounce back up.
if ((P_MobjWasRemoved(thing) // Monitor was removed if ((P_MobjWasRemoved(thing) // Monitor was removed
|| !thing->health) // or otherwise popped || !thing->health) // or otherwise popped
@ -3007,7 +3017,7 @@ static boolean PIT_RadiusAttack(mobj_t *thing)
if (P_CheckSight(thing, bombspot)) if (P_CheckSight(thing, bombspot))
{ // must be in direct path { // must be in direct path
P_DamageMobj(thing, bombspot, bombsource, 1); // Tails 01-11-2001 P_DamageMobj(thing, bombspot, bombsource, 1, 0); // Tails 01-11-2001
} }
return true; return true;
@ -3140,22 +3150,15 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
{ {
// Crush the object // Crush the object
if (netgame && thing->player && thing->player->spectator) if (netgame && thing->player && thing->player->spectator)
P_DamageMobj(thing, NULL, NULL, 42000); // Respawn crushed spectators P_DamageMobj(thing, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators
else else
{ P_DamageMobj(thing, killer, killer, 1, DMG_CRUSHED);
if (!killer) return true;
{
//Nobody is responsible for crushing the object, so give a generic crush message
killer = P_SpawnMobj(thing->x, thing->y, thing->z, MT_NULL);
killer->threshold = 44; // Special flag for crushing
}
P_DamageMobj(thing, killer, killer, 10000);
}
} }
} }
if (realcrush && crushchange) if (realcrush && crushchange)
P_DamageMobj(thing, NULL, NULL, 1); P_DamageMobj(thing, NULL, NULL, 1, 0);
// keep checking (crush other things) // keep checking (crush other things)
return true; return true;

View File

@ -712,7 +712,7 @@ void P_ExplodeMissile(mobj_t *mo)
S_StartSound(explodemo, sfx_cybdth); S_StartSound(explodemo, sfx_cybdth);
// Hack: Release an animal. // Hack: Release an animal.
P_DamageMobj(mo, NULL, NULL, 10000); P_DamageMobj(mo, NULL, NULL, 1, DMG_INSTAKILL);
} }
mo->flags &= ~MF_MISSILE; mo->flags &= ~MF_MISSILE;
@ -1744,7 +1744,7 @@ static boolean P_ZMovement(mobj_t *mo)
// Kill enemies and bosses that fall into death pits. // Kill enemies and bosses that fall into death pits.
if (mo->health) if (mo->health)
{ {
P_KillMobj(mo, NULL, NULL); P_KillMobj(mo, NULL, NULL, 0);
return false; return false;
} }
} }
@ -2800,7 +2800,7 @@ void P_DestroyRobots(void)
continue; continue;
// Found a target enemy // Found a target enemy
P_KillMobj(mo, players[consoleplayer].mo, players[consoleplayer].mo); P_KillMobj(mo, players[consoleplayer].mo, players[consoleplayer].mo, 0);
} }
} }
@ -3481,7 +3481,7 @@ static void P_Boss3Thinker(mobj_t *mobj)
continue; continue;
if (players[i].mo->eflags & MFE_UNDERWATER) if (players[i].mo->eflags & MFE_UNDERWATER)
P_DamageMobj(players[i].mo, mobj, mobj, 1); P_DamageMobj(players[i].mo, mobj, mobj, 1, 0);
} }
// Make the water flash // Make the water flash
@ -3822,7 +3822,7 @@ static void P_Boss4PopSpikeballs(mobj_t *mobj)
P_SetTarget(&base->tracer, NULL); P_SetTarget(&base->tracer, NULL);
for (seg = base; seg; seg = seg->hnext) for (seg = base; seg; seg = seg->hnext)
if (seg->health) if (seg->health)
P_KillMobj(seg, NULL, NULL); P_KillMobj(seg, NULL, NULL, 0);
base = next; base = next;
} }
} }
@ -4122,7 +4122,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
{ {
INT32 i; INT32 i;
P_KillMobj(mobj, NULL, NULL); P_KillMobj(mobj, NULL, NULL, 0);
// It was a team effort // It was a team effort
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
@ -4173,7 +4173,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
&& players[i].mo->z < mobj->z + mobj->height + 128*FRACUNIT) // You can't be in the vicinity, either... && players[i].mo->z < mobj->z + mobj->height + 128*FRACUNIT) // You can't be in the vicinity, either...
{ {
// Punch him! // Punch him!
P_DamageMobj(players[i].mo, mobj, mobj, 1); P_DamageMobj(players[i].mo, mobj, mobj, 1, 0);
mobj->state->nextstate = mobj->info->spawnstate; mobj->state->nextstate = mobj->info->spawnstate;
// Laugh // Laugh
@ -4396,7 +4396,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
if (players[i].mo->z < mobj->z - 64*FRACUNIT) if (players[i].mo->z < mobj->z - 64*FRACUNIT)
continue; continue;
P_DamageMobj(players[i].mo, mobj, mobj, 1); P_DamageMobj(players[i].mo, mobj, mobj, 1, 0);
// Laugh // Laugh
S_StartSound(0, sfx_bewar1 + P_RandomKey(4)); S_StartSound(0, sfx_bewar1 + P_RandomKey(4));
@ -5818,7 +5818,7 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL
&& (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)))
{ {
P_KillMobj(mobj, NULL, NULL); P_KillMobj(mobj, NULL, NULL, 0);
return; return;
} }
} }
@ -6450,7 +6450,7 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL
&& (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)))
{ {
P_KillMobj(mobj, NULL, NULL); P_KillMobj(mobj, NULL, NULL, 0);
return; return;
} }
break; break;
@ -6699,7 +6699,7 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
if (mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->health if (mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->health
&& P_CheckDeathPitCollide(mobj)) // extra pit check in case these didn't have momz && P_CheckDeathPitCollide(mobj)) // extra pit check in case these didn't have momz
{ {
P_KillMobj(mobj, NULL, NULL); P_KillMobj(mobj, NULL, NULL, DMG_DEATHPIT);
return; return;
} }
@ -6713,7 +6713,7 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
&& !(mobj->flags & MF_NOCLIPHEIGHT) && !(mobj->flags & MF_NOCLIPHEIGHT)
&& mobj->health > 0) && mobj->health > 0)
{ {
P_KillMobj(mobj, NULL, NULL); P_KillMobj(mobj, NULL, NULL, DMG_CRUSHED);
return; return;
} }
} }

View File

@ -3472,19 +3472,19 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
{ {
case 1: // Damage (Generic) case 1: // Damage (Generic)
if (roversector || P_MobjReadyToTrigger(player->mo, sector)) if (roversector || P_MobjReadyToTrigger(player->mo, sector))
P_DamageMobj(player->mo, NULL, NULL, 1); P_DamageMobj(player->mo, NULL, NULL, 1, 0);
break; break;
case 2: // Damage (Water) case 2: // Damage (Water)
if ((roversector || P_MobjReadyToTrigger(player->mo, sector)) && (player->powers[pw_underwater] || player->pflags & PF_NIGHTSMODE) && (player->powers[pw_shield] & SH_NOSTACK) != SH_ELEMENTAL) if ((roversector || P_MobjReadyToTrigger(player->mo, sector)) && (player->powers[pw_underwater] || player->pflags & PF_NIGHTSMODE))
P_DamageMobj(player->mo, NULL, NULL, 1); P_DamageMobj(player->mo, NULL, NULL, 1, DMG_WATER);
break; break;
case 3: // Damage (Fire) case 3: // Damage (Fire)
if ((roversector || P_MobjReadyToTrigger(player->mo, sector)) && (player->powers[pw_shield] & SH_NOSTACK) != SH_ELEMENTAL) if (roversector || P_MobjReadyToTrigger(player->mo, sector))
P_DamageMobj(player->mo, NULL, NULL, 1); P_DamageMobj(player->mo, NULL, NULL, 1, DMG_FIRE);
break; break;
case 4: // Damage (Electrical) case 4: // Damage (Electrical)
if ((roversector || P_MobjReadyToTrigger(player->mo, sector)) && (player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT) if (roversector || P_MobjReadyToTrigger(player->mo, sector))
P_DamageMobj(player->mo, NULL, NULL, 1); P_DamageMobj(player->mo, NULL, NULL, 1, DMG_ELECTRIC);
break; break;
case 5: // Spikes case 5: // Spikes
// Don't do anything. In Soviet Russia, spikes find you. // Don't do anything. In Soviet Russia, spikes find you.
@ -3492,10 +3492,10 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
case 6: // Death Pit (Camera Mod) case 6: // Death Pit (Camera Mod)
case 7: // Death Pit (No Camera Mod) case 7: // Death Pit (No Camera Mod)
if (roversector || P_MobjReadyToTrigger(player->mo, sector)) if (roversector || P_MobjReadyToTrigger(player->mo, sector))
P_DamageMobj(player->mo, NULL, NULL, 10000); P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT);
break; break;
case 8: // Instant Kill case 8: // Instant Kill
P_DamageMobj(player->mo, NULL, NULL, 10000); P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL);
break; break;
case 9: // Ring Drainer (Floor Touch) case 9: // Ring Drainer (Floor Touch)
case 10: // Ring Drainer (No Floor Touch) case 10: // Ring Drainer (No Floor Touch)
@ -3599,7 +3599,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_EGGTRAP) if (mo2->type == MT_EGGTRAP)
P_KillMobj(mo2, NULL, player->mo); P_KillMobj(mo2, NULL, player->mo, 0);
} }
// clear the special so you can't push the button twice. // clear the special so you can't push the button twice.
@ -5355,9 +5355,9 @@ void T_LaserFlash(laserthink_t *flash)
continue; continue;
if (thing->flags & MF_SHOOTABLE) if (thing->flags & MF_SHOOTABLE)
P_DamageMobj(thing, NULL, NULL, 1); P_DamageMobj(thing, NULL, NULL, 1, 0);
else if (thing->type == MT_EGGSHIELD) else if (thing->type == MT_EGGSHIELD)
P_KillMobj(thing, NULL, NULL); P_KillMobj(thing, NULL, NULL, 0);
} }
} }

View File

@ -662,7 +662,7 @@ void P_Ticker(boolean run)
if (!players[i].mo) if (!players[i].mo)
continue; continue;
P_DamageMobj(players[i].mo, NULL, NULL, 10000); P_DamageMobj(players[i].mo, NULL, NULL, 1, DMG_INSTAKILL);
} }
} }

View File

@ -632,7 +632,7 @@ static void P_DeNightserizePlayer(player_t *player)
continue; continue;
if (mo2->flags & MF_AMBUSH) if (mo2->flags & MF_AMBUSH)
P_DamageMobj(player->mo, NULL, NULL, 10000); P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL);
break; break;
} }
@ -1998,21 +1998,15 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player)
// Underwater timer runs out // Underwater timer runs out
else if (player->powers[pw_underwater] == 1) else if (player->powers[pw_underwater] == 1)
{ {
mobj_t *killer;
if ((netgame || multiplayer) && P_IsLocalPlayer(player)) if ((netgame || multiplayer) && P_IsLocalPlayer(player))
S_ChangeMusic(mapmusic, true); S_ChangeMusic(mapmusic, true);
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DROWNED);
killer = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_NULL);
killer->threshold = 42; // Special flag that it was drowning which killed you.
P_DamageMobj(player->mo, killer, killer, 10000);
} }
else if (player->powers[pw_spacetime] == 1) else if (player->powers[pw_spacetime] == 1)
{ {
if ((netgame || multiplayer) && P_IsLocalPlayer(player)) if ((netgame || multiplayer) && P_IsLocalPlayer(player))
S_ChangeMusic(mapmusic, true); S_ChangeMusic(mapmusic, true);
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPACEDROWN);
P_DamageMobj(player->mo, NULL, NULL, 10000);
} }
if (numbermobj) if (numbermobj)
@ -6016,7 +6010,7 @@ static void P_NiGHTSMovement(player_t *player)
if (player->powers[pw_flashing] == 1) if (player->powers[pw_flashing] == 1)
player->powers[pw_flashing] = 3; player->powers[pw_flashing] = 3;
else else
P_DamageMobj(player->mo, NULL, NULL, 1); P_DamageMobj(player->mo, NULL, NULL, 1, 0);
} }
if (movingangle >= ANGLE_90 && movingangle <= ANGLE_180) if (movingangle >= ANGLE_90 && movingangle <= ANGLE_180)
@ -6378,7 +6372,7 @@ static void P_MovePlayer(player_t *player)
players[i].exiting = (14*TICRATE)/5 + 1; players[i].exiting = (14*TICRATE)/5 + 1;
} }
else if (player->health > 1) else if (player->health > 1)
P_DamageMobj(player->mo, NULL, NULL, 1); P_DamageMobj(player->mo, NULL, NULL, 1, 0);
player->pflags &= ~PF_NIGHTSFALL; player->pflags &= ~PF_NIGHTSFALL;
} }
} }
@ -6906,13 +6900,9 @@ static void P_MovePlayer(player_t *player)
else if (player->mo->ceilingz - player->mo->floorz < player->mo->height) else if (player->mo->ceilingz - player->mo->floorz < player->mo->height)
{ {
if ((netgame || multiplayer) && player->spectator) if ((netgame || multiplayer) && player->spectator)
P_DamageMobj(player->mo, NULL, NULL, 42000); // Respawn crushed spectators P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators
else else
{ P_DamageMobj(player->mo, NULL, NULL, 1, DMG_CRUSHED);
mobj_t *killer = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_NULL);
killer->threshold = 44; // Special flag that it was crushing which killed you.
P_DamageMobj(player->mo, killer, killer, 10000);
}
if (player->playerstate == PST_DEAD) if (player->playerstate == PST_DEAD)
return; return;
@ -7343,7 +7333,7 @@ static void P_NukeAllPlayers(player_t *player)
if (mo == player->mo) if (mo == player->mo)
continue; continue;
P_DamageMobj(mo, player->mo, player->mo, 1); P_DamageMobj(mo, player->mo, player->mo, 1, 0);
} }
CONS_Printf(M_GetText("%s caused a world of pain.\n"), player_names[player-players]); CONS_Printf(M_GetText("%s caused a world of pain.\n"), player_names[player-players]);
@ -7401,12 +7391,12 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
mo->flags |= MF_SPECIAL|MF_SHOOTABLE; mo->flags |= MF_SPECIAL|MF_SHOOTABLE;
if (mo->type == MT_EGGGUARD && mo->tracer) //nuke Egg Guard's shield! if (mo->type == MT_EGGGUARD && mo->tracer) //nuke Egg Guard's shield!
P_KillMobj(mo->tracer, inflictor, source); P_KillMobj(mo->tracer, inflictor, source, 0);
if (mo->flags & MF_BOSS || mo->type == MT_PLAYER) //don't OHKO bosses nor players! if (mo->flags & MF_BOSS || mo->type == MT_PLAYER) //don't OHKO bosses nor players!
P_DamageMobj(mo, inflictor, source, 1); P_DamageMobj(mo, inflictor, source, 1, 0);
else else
P_DamageMobj(mo, inflictor, source, 1000); P_DamageMobj(mo, inflictor, source, 1000, 0);
} }
} }
@ -8679,7 +8669,7 @@ void P_PlayerThink(player_t *player)
} }
player->lives = 2; // Don't start the game over music! player->lives = 2; // Don't start the game over music!
P_DamageMobj(player->mo, NULL, NULL, 10000); P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL);
player->lives = 0; player->lives = 0;
if (player->playerstate == PST_DEAD) if (player->playerstate == PST_DEAD)