diff --git a/src/actor.h b/src/actor.h index ab04b176db..7ec6534473 100644 --- a/src/actor.h +++ b/src/actor.h @@ -265,7 +265,7 @@ enum // --- mobj.flags5 --- - /* = 0x00000001, */ + MF5_DONTDRAIN = 0x00000001, // cannot be drained health from. /* = 0x00000002, */ MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances. /* = 0x00000008, */ diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index 07b7c0f561..5c5bb7eba1 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -115,6 +115,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) angle_t slope; player_t *player; AActor *linetarget; + int actualdamage; ACTION_PARAM_START(9); ACTION_PARAM_SOUND(fullsound, 0); @@ -151,7 +152,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) return; } - P_LineAttack (self, angle, Range, slope, damage, NAME_Melee, pufftype, false, &linetarget); + P_LineAttack (self, angle, Range, slope, damage, NAME_Melee, pufftype, false, &linetarget, &actualdamage); if (!linetarget) { @@ -180,8 +181,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) } } - if (LifeSteal) - P_GiveBody (self, (damage * LifeSteal) >> FRACBITS); + if (LifeSteal && !(linetarget->flags5 & MF5_DONTDRAIN)) + P_GiveBody (self, (actualdamage * LifeSteal) >> FRACBITS); S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM); diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index 5e1f0647c4..23ecf1ae59 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -240,6 +240,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack) player_t *player; const PClass *pufftype; AActor *linetarget; + int actualdamage = 0; if (NULL == (player = self->player)) { @@ -273,7 +274,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack) pufftype = PClass::FindClass("GauntletPuff1"); } slope = P_AimLineAttack (self, angle, dist, &linetarget); - P_LineAttack (self, angle, dist, slope, damage, NAME_Melee, pufftype, false, &linetarget); + P_LineAttack (self, angle, dist, slope, damage, NAME_Melee, pufftype, false, &linetarget, &actualdamage); if (!linetarget) { if (pr_gatk() > 64) @@ -298,7 +299,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack) } if (power) { - P_GiveBody (self, damage>>1); + if (!(linetarget->flags5 & MF5_DONTDRAIN)) P_GiveBody (self, actualdamage>>1); S_Sound (self, CHAN_AUTO, "weapons/gauntletspowhit", 1, ATTN_NORM); } else diff --git a/src/gi.cpp b/src/gi.cpp index 2df1fdde0f..75476c8005 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -96,10 +96,10 @@ const char* GameInfoBorders[] = strcpy(gameinfo.key, sc.String); \ } -#define GAMEINFOKEY_STRINGARRAY(key, variable, length) \ +#define GAMEINFOKEY_STRINGARRAY(key, variable, length, clear) \ else if(nextKey.CompareNoCase(variable) == 0) \ { \ - gameinfo.key.Clear(); \ + if (clear) gameinfo.key.Clear(); \ do \ { \ sc.MustGetToken(TK_StringConst); \ @@ -282,8 +282,10 @@ void FMapInfoParser::ParseGameInfo() } // Insert valid keys here. GAMEINFOKEY_CSTRING(titlePage, "titlePage", 8) - GAMEINFOKEY_STRINGARRAY(creditPages, "creditPage", 8) - GAMEINFOKEY_STRINGARRAY(PlayerClasses, "playerclasses", 0) + GAMEINFOKEY_STRINGARRAY(creditPages, "addcreditPage", 8, false) + GAMEINFOKEY_STRINGARRAY(creditPages, "CreditPage", 8, true) + GAMEINFOKEY_STRINGARRAY(PlayerClasses, "addplayerclasses", 0, false) + GAMEINFOKEY_STRINGARRAY(PlayerClasses, "playerclasses", 0, true) GAMEINFOKEY_STRING(titleMusic, "titleMusic") GAMEINFOKEY_FLOAT(titleTime, "titleTime") GAMEINFOKEY_FLOAT(advisoryTime, "advisoryTime") @@ -291,8 +293,9 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_STRING(chatSound, "chatSound") GAMEINFOKEY_STRING(finaleMusic, "finaleMusic") GAMEINFOKEY_CSTRING(finaleFlat, "finaleFlat", 8) - GAMEINFOKEY_STRINGARRAY(finalePages, "finalePage", 8) - GAMEINFOKEY_STRINGARRAY(infoPages, "infoPage", 8) + GAMEINFOKEY_STRINGARRAY(finalePages, "finalePage", 8, true) + GAMEINFOKEY_STRINGARRAY(infoPages, "addinfoPage", 8, false) + GAMEINFOKEY_STRINGARRAY(infoPages, "infoPage", 8, true) GAMEINFOKEY_CSTRING(PauseSign, "pausesign", 8) GAMEINFOKEY_STRING(quitSound, "quitSound") GAMEINFOKEY_CSTRING(borderFlat, "borderFlat", 8) @@ -321,7 +324,8 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_INT(defaultdropstyle, "defaultdropstyle") GAMEINFOKEY_CSTRING(Endoom, "endoom", 8) GAMEINFOKEY_INT(player5start, "player5start") - GAMEINFOKEY_STRINGARRAY(quitmessages, "quitmessages", 0) + GAMEINFOKEY_STRINGARRAY(quitmessages, "addquitmessages", 0, false) + GAMEINFOKEY_STRINGARRAY(quitmessages, "quitmessages", 0, true) GAMEINFOKEY_STRING(mTitleColor, "menufontcolor_title") GAMEINFOKEY_STRING(mFontColor, "menufontcolor_label") GAMEINFOKEY_STRING(mFontColorValue, "menufontcolor_value") diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 96b52e0b74..c46cb40f74 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -657,14 +657,13 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) FState *diestate = NULL; - FName damagetype = (inflictor && inflictor->DeathType != NAME_None) ? inflictor->DeathType : DamageType; - if (damagetype != NAME_None) + if (DamageType != NAME_None) { - diestate = FindState (NAME_Death, damagetype, true); + diestate = FindState (NAME_Death, DamageType, true); if (diestate == NULL) { - if (damagetype == NAME_Ice) + if (DamageType == NAME_Ice) { // If an actor doesn't have an ice death, we can still give them a generic one. if (!deh.NoAutofreeze && !(flags4 & MF4_NOICEDEATH) && (player || (flags3 & MF3_ISMONSTER))) @@ -683,9 +682,9 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) // Don't pass on a damage type this actor cannot handle. // (most importantly, prevent barrels from passing on ice damage.) // Massacre must be preserved though. - if (damagetype != NAME_Massacre) + if (DamageType != NAME_Massacre) { - damagetype = NAME_None; + DamageType = NAME_None; } if ((health < gibhealth || flags4 & MF4_EXTREMEDEATH) && !(flags4 & MF4_NOEXTREMEDEATH)) @@ -1263,7 +1262,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // If the damaging player has the power of drain, give the player 50% of the damage // done in health. - if ( source && source->player && source->player->cheats & CF_DRAIN) + if ( source && source->player && source->player->cheats & CF_DRAIN && !(target->flags5 & MF5_DONTDRAIN)) { if (!target->player || target->player != source->player) { @@ -1278,6 +1277,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, if (target->health <= 0) { // Death target->special1 = damage; + + // use inflictor's death type if it got one. + if (inflictor && inflictor->DeathType != NAME_None) mod = inflictor->DeathType; + // check for special fire damage or ice damage deaths if (mod == NAME_Fire) { diff --git a/src/p_local.h b/src/p_local.h index f5e1f44a0f..a4da0a04b7 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -460,8 +460,8 @@ enum // P_LineAttack flags LAF_NORANDOMPUFFZ = 2 }; -AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, int flags = 0, AActor **victim = NULL); -AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, int flags = 0, AActor **victim = NULL); +AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL); +AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL); void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch); void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch); void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version diff --git a/src/p_map.cpp b/src/p_map.cpp index 1b85961c27..17bb3e1359 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -3496,7 +3496,7 @@ static ETraceStatus CheckForSpectral (FTraceResults &res, void *userdata) //========================================================================== AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, - int pitch, int damage, FName damageType, const PClass *pufftype, int flags, AActor **victim) + int pitch, int damage, FName damageType, const PClass *pufftype, int flags, AActor **victim, int *actualdamage) { fixed_t vx, vy, vz, shootz; FTraceResults trace; @@ -3514,6 +3514,10 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, { *victim = NULL; } + if (actualdamage != NULL) + { + *actualdamage = 0; + } angle >>= ANGLETOFINESHIFT; pitch = (angle_t)(pitch) >> ANGLETOFINESHIFT; @@ -3684,6 +3688,10 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, killPuff = true; } newdam = P_DamageMobj (trace.Actor, puff ? puff : t1, t1, damage, damageType, dmgflags); + if (actualdamage != NULL) + { + *actualdamage = newdam; + } } if (!(puffDefaults != NULL && puffDefaults->flags3&MF3_BLOODLESSIMPACT)) { @@ -3741,7 +3749,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, } AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, - int pitch, int damage, FName damageType, FName pufftype, int flags, AActor **victim) + int pitch, int damage, FName damageType, FName pufftype, int flags, AActor **victim, int *actualdamage) { const PClass * type = PClass::FindClass(pufftype); if (victim != NULL) @@ -3754,7 +3762,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, } else { - return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, flags, victim); + return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, flags, victim, actualdamage); } return NULL; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index aff9909072..41b41aec67 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -270,6 +270,10 @@ void AActor::Serialize (FArchive &arc) << meleethreshold << meleerange << DamageType; + if (SaveVersion >= 4501) + { + arc << DamageTypeReceived; + } if (SaveVersion >= 3237) { arc diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index be91cdf2c8..d35572121a 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1388,6 +1388,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) angle_t angle; int pitch; AActor * linetarget; + int actualdamage; if (!norandom) Damage *= (pr_cwpunch()%8+1); @@ -1404,13 +1405,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch) if (!PuffType) PuffType = PClass::FindClass(NAME_BulletPuff); int puffFlags = LAF_ISMELEEATTACK | (flags & CPF_NORANDOMPUFFZ)? LAF_NORANDOMPUFFZ : 0; - P_LineAttack (self, angle, Range, pitch, Damage, NAME_Melee, PuffType, puffFlags, &linetarget); + P_LineAttack (self, angle, Range, pitch, Damage, NAME_Melee, PuffType, puffFlags, &linetarget, &actualdamage); // turn to face target if (linetarget) { - if (LifeSteal) - P_GiveBody (self, (Damage * LifeSteal) >> FRACBITS); + if (LifeSteal && !(linetarget->flags5 & MF5_DONTDRAIN)) + P_GiveBody (self, (actualdamage * LifeSteal) >> FRACBITS); if (weapon != NULL) { diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 3dbbacac0f..795bcb5cc7 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -182,6 +182,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF4, NOSKIN, AActor, flags4), DEFINE_FLAG(MF4, BOSSDEATH, AActor, flags4), + DEFINE_FLAG(MF5, DONTDRAIN, AActor, flags5), DEFINE_FLAG(MF5, NODROPOFF, AActor, flags5), DEFINE_FLAG(MF5, COUNTSECRET, AActor, flags5), DEFINE_FLAG(MF5, NODAMAGE, AActor, flags5), diff --git a/src/version.h b/src/version.h index e3f8554fec..1038e401b5 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4500 +#define SAVEVER 4501 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)