diff --git a/src/dehacked.c b/src/dehacked.c index b6bd59501..b028b9c53 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7400,6 +7400,7 @@ struct { {"DMG_CRUSHED",DMG_CRUSHED}, {"DMG_SPECTATOR",DMG_SPECTATOR}, //// Masks + {"DMG_CANHURTSELF",DMG_CANHURTSELF}, {"DMG_DEATHMASK",DMG_DEATHMASK}, // Gametypes, for use with global var "gametype" diff --git a/src/info.c b/src/info.c index e744be054..91b8a2025 100644 --- a/src/info.c +++ b/src/info.c @@ -5422,7 +5422,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16*FRACUNIT, // radius 48*FRACUNIT, // height 0, // display offset - sfx_s3k5a, // mass + 0, // mass 3, // damage sfx_mswarp, // activesound MF_NOGRAVITY|MF_BOSS|MF_SLIDEME, // flags diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 0cb530b53..c1fd87af3 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1356,11 +1356,12 @@ static int lib_pRadiusAttack(lua_State *L) mobj_t *spot = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); fixed_t damagedist = luaL_checkfixed(L, 3); + UINT8 damagetype = luaL_optinteger(L, 4, 0); NOHUD INLEVEL if (!spot || !source) return LUA_ErrInvalid(L, "mobj_t"); - P_RadiusAttack(spot, source, damagedist); + P_RadiusAttack(spot, source, damagedist, damagetype); return 0; } diff --git a/src/p_enemy.c b/src/p_enemy.c index 1ecf8cd3a..5cf045454 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2824,16 +2824,17 @@ void A_GoldMonitorSparkle(mobj_t *actor) // // Description: Explodes an object, doing damage to any objects nearby. The target is used as the cause of the explosion. Damage value is used as explosion range. // -// var1 = unused +// var1 = damagetype // var2 = unused // void A_Explode(mobj_t *actor) { + INT32 locvar1 = var1; #ifdef HAVE_BLUA if (LUA_CallAction("A_Explode", actor)) return; #endif - P_RadiusAttack(actor, actor->target, actor->info->damage); + P_RadiusAttack(actor, actor->target, actor->info->damage, locvar1); } // Function: A_BossDeath @@ -9580,7 +9581,7 @@ void A_VileAttack(mobj_t *actor) actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), fire->z); - P_RadiusAttack(fire, actor, 70*FRACUNIT); + P_RadiusAttack(fire, actor, 70*FRACUNIT, 0); } else { @@ -9625,7 +9626,7 @@ void A_VileAttack(mobj_t *actor) actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), fire->z); - P_RadiusAttack(fire, actor, 70*FRACUNIT); + P_RadiusAttack(fire, actor, 70*FRACUNIT, 0); } } @@ -10709,7 +10710,7 @@ void A_MineExplode(mobj_t *actor) quake.intensity = 8*FRACUNIT; quake.time = TICRATE/3; - P_RadiusAttack(actor, actor->tracer, 192*FRACUNIT); + P_RadiusAttack(actor, actor->tracer, 192*FRACUNIT, DMG_CANHURTSELF); P_MobjCheckWater(actor); { diff --git a/src/p_inter.c b/src/p_inter.c index f50191ec1..7f712c84a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2670,7 +2670,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) } } -static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) +static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { player_t *player = target->player; (void)damage; //unused parm @@ -2680,7 +2680,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou return false; // Ignore IT players shooting each other, unless friendlyfire is on. - if ((player->pflags & PF_TAGIT && !(cv_friendlyfire.value && + if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) && source && source->player && source->player->pflags & PF_TAGIT))) return false; @@ -2690,7 +2690,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou // Don't allow players on the same team to hurt one another, // unless cv_friendlyfire is on. - if (!cv_friendlyfire.value && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT)) + if (!(cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT)) { if (!(inflictor->flags & MF_FIRE)) P_GivePlayerRings(player, 1); @@ -2745,21 +2745,26 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou return true; } -static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) +static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { player_t *player = target->player; - // You can't kill yourself, idiot... - if (source == target) - return false; + if (!(damagetype & DMG_CANHURTSELF)) + { + // You can't kill yourself, idiot... + if (source == target) + return false; - // In COOP/RACE/CHAOS, you can't hurt other players unless cv_friendlyfire is on - if (!cv_friendlyfire.value && (G_PlatformGametype())) - return false; + // In COOP/RACE, you can't hurt other players unless cv_friendlyfire is on + if (!cv_friendlyfire.value && (G_PlatformGametype())) + return false; + } // Tag handling if (G_TagGametype()) - return P_TagDamage(target, inflictor, source, damage); + return P_TagDamage(target, inflictor, source, damage, damagetype); + else if (damagetype & DMG_CANHURTSELF) + return true; else if (G_GametypeHasTeams()) // CTF + Team Match { // Don't allow players on the same team to hurt one another, @@ -3177,7 +3182,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da // Player hits another player if (!force && source && source->player) { - if (!P_PlayerHitsPlayer(target, inflictor, source, damage)) + if (!P_PlayerHitsPlayer(target, inflictor, source, damage, damagetype)) return false; } diff --git a/src/p_local.h b/src/p_local.h index 1958e6559..da4c70b0f 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -363,7 +363,7 @@ void P_DelPrecipSeclist(mprecipsecnode_t *node); void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y); void P_Initsecnode(void); -void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist); +void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype); fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height); boolean PIT_PushableMoved(mobj_t *thing); @@ -413,6 +413,8 @@ typedef struct BasicFF_s #define DMG_DEATHPIT 0x80+3 #define DMG_CRUSHED 0x80+4 #define DMG_SPECTATOR 0x80+5 +// Masks +#define DMG_CANHURTSELF 0x40 // Flag - can hurt self/team indirectly, such as through mines #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); diff --git a/src/p_map.c b/src/p_map.c index a219d3b97..a9d49a7e1 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -674,14 +674,14 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - if (thing->flags & MF_PAIN) + if (thing->flags & MF_PAIN && tmthing->player) { // Player touches painful thing sitting on the floor // see if it went over / under if (thing->z > tmthing->z + tmthing->height) return true; // overhead if (thing->z + thing->height < tmthing->z) return true; // underneath - if (tmthing->player && tmthing->flags & MF_SHOOTABLE && thing->health > 0) + if (tmthing->flags & MF_SHOOTABLE && thing->health > 0) { UINT8 damagetype = thing->info->mass; if (!damagetype && thing->flags & MF_FIRE) // BURN! @@ -691,14 +691,14 @@ static boolean PIT_CheckThing(mobj_t *thing) } return true; } - else if (tmthing->flags & MF_PAIN) + else if (tmthing->flags & MF_PAIN && thing->player) { // Painful thing splats player in the face // see if it went over / under if (tmthing->z > thing->z + thing->height) return true; // overhead if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (thing->player && thing->flags & MF_SHOOTABLE && tmthing->health > 0) + if (thing->flags & MF_SHOOTABLE && tmthing->health > 0) { UINT8 damagetype = tmthing->info->mass; if (!damagetype && tmthing->flags & MF_FIRE) // BURN! @@ -751,6 +751,7 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (tmz > thzh - sprarea && tmz < thzh) // Don't damage people springing up / down return true; } + // missiles can hit other things if (tmthing->flags & MF_MISSILE || tmthing->type == MT_SHELL) { @@ -805,30 +806,11 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->type == MT_EGGSHIELD) { - fixed_t touchx, touchy; - angle_t angle; + angle_t angle = (R_PointToAngle2(thing->x, thing->y, tmthing->x - tmthing->momx, tmthing->y - tmthing->momy) - thing->angle) - ANGLE_90; - if (P_AproxDistance(tmthing->x-thing->x, tmthing->y-thing->y) > - P_AproxDistance((tmthing->x-tmthing->momx)-thing->x, (tmthing->y-tmthing->momy)-thing->y)) - { - touchx = tmthing->x + tmthing->momx; - touchy = tmthing->y + tmthing->momy; - } - else - { - touchx = tmthing->x; - touchy = tmthing->y; - } - - angle = R_PointToAngle2(thing->x, thing->y, touchx, touchy) - thing->angle; - - if (!(angle > ANGLE_90 && angle < ANGLE_270)) // hit front of shield, didn't destroy it - return false; - else // hit shield from behind, shield is destroyed! - { + if (angle < ANGLE_180) // hit shield from behind, shield is destroyed! P_KillMobj(thing, tmthing, tmthing, 0); - return false; - } + return false; } // damage / explode @@ -1086,6 +1068,14 @@ static boolean PIT_CheckThing(mobj_t *thing) } } + // thanks to sal for solidenemies dot lua + if (thing->flags & (MF_ENEMY|MF_BOSS) && tmthing->flags & (MF_ENEMY|MF_BOSS)) + { + if ((thing->z + thing->height >= tmthing->z) + && (tmthing->z + tmthing->height >= thing->z)) + return false; + } + // Damage other players when invincible if (tmthing->player && thing->player // Make sure they aren't able to damage you ANYWHERE along the Z axis, you have to be TOUCHING the person. @@ -1150,7 +1140,7 @@ static boolean PIT_CheckThing(mobj_t *thing) { // Objects kill you if it falls from above. if (thing != tmthing->target) - P_DamageMobj(thing, tmthing, tmthing->target, 1, DMG_INSTAKILL); + P_DamageMobj(thing, tmthing, tmthing->target, 1, DMG_CRUSHED); tmthing->momz = -tmthing->momz/2; // Bounce, just for fun! // The tmthing->target allows the pusher of the object @@ -1185,7 +1175,8 @@ static boolean PIT_CheckThing(mobj_t *thing) UINT8 elementalpierce = (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY) ? (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2) : 0); - if (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING) + if (!(thing->flags & MF_SOLID) + || tmthing->player->pflags & (PF_SPINNING|PF_GLIDING) || ((tmthing->player->pflags & PF_JUMPED) && (!(tmthing->player->pflags & PF_NOJUMPDAMAGE) || (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) @@ -1194,8 +1185,8 @@ static boolean PIT_CheckThing(mobj_t *thing) && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0)) || elementalpierce) { - if (thing->z - FixedMul(FRACUNIT, thing->scale) <= tmthing->z + tmthing->height - && thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) >= tmthing->z) + if (thing->z - thing->scale <= tmthing->z + tmthing->height + && thing->z + thing->height + thing->scale >= tmthing->z) { player_t *player = tmthing->player; SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed. @@ -3527,6 +3518,7 @@ bounceback: static fixed_t bombdamage; static mobj_t *bombsource; static mobj_t *bombspot; +static UINT8 bombdamagetype; // // PIT_RadiusAttack @@ -3537,17 +3529,13 @@ static boolean PIT_RadiusAttack(mobj_t *thing) { fixed_t dx, dy, dz, dist; - if (thing == bombspot // ignore the bomb itself (Deton fix) - || (bombsource && thing->type == bombsource->type)) // ignore the type of guys who dropped the bomb (Jetty-Syn Bomber or Skim can bomb eachother, but not themselves.) + if (thing == bombspot) // ignore the bomb itself (Deton fix) return true; - if (!(thing->flags & MF_SHOOTABLE)) + if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) != MF_SHOOTABLE) return true; - if (thing->flags & MF_BOSS) - return true; - - if (thing->flags & MF_MONITOR) + if (bombsource && thing->type == bombsource->type && !(bombdamagetype & DMG_CANHURTSELF)) // ignore the type of guys who dropped the bomb (Jetty-Syn Bomber or Skim can bomb eachother, but not themselves.) return true; dx = abs(thing->x - bombspot->x); @@ -3571,7 +3559,7 @@ static boolean PIT_RadiusAttack(mobj_t *thing) if (P_CheckSight(thing, bombspot)) { // must be in direct path - P_DamageMobj(thing, bombspot, bombsource, 1, 0); // Tails 01-11-2001 + P_DamageMobj(thing, bombspot, bombsource, 1, bombdamagetype); // Tails 01-11-2001 } return true; @@ -3581,7 +3569,7 @@ static boolean PIT_RadiusAttack(mobj_t *thing) // P_RadiusAttack // Source is the creature that caused the explosion at spot. // -void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist) +void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype) { INT32 x, y; INT32 xl, xh, yl, yh; @@ -3598,6 +3586,7 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist) bombspot = spot; bombsource = source; bombdamage = FixedMul(damagedist, spot->scale); + bombdamagetype = damagetype; for (y = yl; y <= yh; y++) for (x = xl; x <= xh; x++) diff --git a/src/p_mobj.c b/src/p_mobj.c index f0dcaf872..8e9f39a33 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -877,7 +877,7 @@ void P_ExplodeMissile(mobj_t *mo) if (mo->type == MT_DETON) { - P_RadiusAttack(mo, mo, 96*FRACUNIT); + P_RadiusAttack(mo, mo, 96*FRACUNIT, 0); explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); P_SetScale(explodemo, mo->scale);