- Fixed: The global WeaponSection string was never freed. It has been replaced

with an FString now.
- Fixed: The music strings in the default level info were never freed and
  caused memory leaks when used repeatedly.
- Fixed: The intermusic string in the level info was never freed.
- Fixed: The default fire obituary should only be printed if the damage
  came from the environment. If it comes from a monster the monster specific
  obituary should be used instead.
- Added custom damage types from the floating point test release.
- Changed Pain Elemental's massacre check. Now A_PainDie checks for the damage 
  type and doesn't spawn anything if it is NAME_Massacre. A_PainDie can also 
  be used by other actors so a more generalized approach is needed than hard
  coding it into the Pain Elemental.
- Converted a few of Doom's monsters to DECORATE because I couldn't test the
  first version of the custom state code with the corpses inheriting from them.
- Added custom states from last year's floating point test release and fixed
  some bugs I found in that code. Unfortunately it wasn't all salvageable
  and it was easier to recreate some parts from scratch.



SVN r368 (trunk)
This commit is contained in:
Christoph Oelckers 2006-10-31 14:53:21 +00:00
commit 063c85b157
118 changed files with 2103 additions and 1818 deletions

View file

@ -69,6 +69,10 @@ CVAR (Bool, cl_showsprees, true, CVAR_ARCHIVE)
CVAR (Bool, cl_showmultikills, true, CVAR_ARCHIVE)
EXTERN_CVAR (Bool, show_obituaries)
FName MeansOfDeath;
bool FriendlyFire;
//
// GET STUFF
//
@ -172,11 +176,11 @@ void SexMessage (const char *from, char *to, int gender, const char *victim, con
//
void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
{
int mod;
FName mod;
const char *message;
const char *messagename;
char gendermessage[1024];
INTBOOL friendly;
bool friendly;
int gender;
// No obituaries for non-players, voodoo dolls or when not wanted
@ -187,19 +191,19 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
// Treat voodoo dolls as unknown deaths
if (inflictor && inflictor->player == self->player)
MeansOfDeath = MOD_UNKNOWN;
MeansOfDeath = NAME_None;
if (multiplayer && !deathmatch)
MeansOfDeath |= MOD_FRIENDLY_FIRE;
FriendlyFire = true;
friendly = MeansOfDeath & MOD_FRIENDLY_FIRE;
mod = MeansOfDeath & ~MOD_FRIENDLY_FIRE;
friendly = FriendlyFire;
mod = MeansOfDeath;
message = NULL;
messagename = NULL;
if (attacker == NULL || attacker->player != NULL)
{
if (mod == MOD_TELEFRAG)
if (mod == NAME_Telefrag)
{
if (AnnounceTelefrag (attacker, self))
return;
@ -213,15 +217,13 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
switch (mod)
{
case MOD_SUICIDE: messagename = "OB_SUICIDE"; break;
case MOD_FALLING: messagename = "OB_FALLING"; break;
case MOD_CRUSH: messagename = "OB_CRUSH"; break;
case MOD_EXIT: messagename = "OB_EXIT"; break;
case MOD_WATER: messagename = "OB_WATER"; break;
case MOD_SLIME: messagename = "OB_SLIME"; break;
case MOD_FIRE: messagename = "OB_LAVA"; break;
case MOD_BARREL: messagename = "OB_BARREL"; break;
case MOD_SPLASH: messagename = "OB_SPLASH"; break;
case NAME_Suicide: messagename = "OB_SUICIDE"; break;
case NAME_Falling: messagename = "OB_FALLING"; break;
case NAME_Crush: messagename = "OB_CRUSH"; break;
case NAME_Exit: messagename = "OB_EXIT"; break;
case NAME_Water: messagename = "OB_WATER"; break;
case NAME_Slime: messagename = "OB_SLIME"; break;
case NAME_Fire: if (attacker == NULL) messagename = "OB_LAVA"; break;
}
if (messagename != NULL)
@ -231,21 +233,15 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
{
if (attacker == self)
{
switch (mod)
{
case MOD_R_SPLASH: messagename = "OB_R_SPLASH"; break;
case MOD_ROCKET: messagename = "OB_ROCKET"; break;
default: messagename = "OB_KILLEDSELF"; break;
}
message = GStrings(messagename);
message = GStrings("OB_KILLEDSELF");
}
else if (attacker->player == NULL)
{
if (mod == MOD_TELEFRAG)
if (mod == NAME_Telefrag)
{
message = GStrings("OB_MONTELEFRAG");
}
else if (mod == MOD_HIT)
else if (mod == NAME_Melee)
{
message = attacker->GetClass()->Meta.GetMetaString (AMETA_HitObituary);
if (message == NULL)
@ -273,7 +269,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
}
else
{
if (mod == MOD_TELEFRAG) message = GStrings("OB_MPTELEFRAG");
if (mod == NAME_Telefrag) message = GStrings("OB_MPTELEFRAG");
if (message == NULL)
{
if (inflictor != NULL)
@ -288,9 +284,8 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
{
switch (mod)
{
case MOD_R_SPLASH: messagename = "OB_MPR_SPLASH"; break;
case MOD_BFG_SPLASH: messagename = "OB_MPBFG_SPLASH"; break;
case MOD_RAILGUN: messagename = "OB_RAILGUN"; break;
case NAME_BFGSplash: messagename = "OB_MPBFG_SPLASH"; break;
case NAME_Railgun: messagename = "OB_RAILGUN"; break;
}
if (messagename != NULL)
message = GStrings(messagename);
@ -360,7 +355,7 @@ void AActor::Die (AActor *source, AActor *inflictor)
flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY);
if (!(flags4 & MF4_DONTFALL)) flags&=~MF_NOGRAVITY;
flags |= MF_DROPOFF;
if ((flags3 & MF3_ISMONSTER) || RaiseState != NULL)
if ((flags3 & MF3_ISMONSTER) || FindState(NAME_Raise) != NULL)
{ // [RH] Only monsters get to be corpses.
// Objects with a raise state should get the flag as well so they can
// be revived by an Arch-Vile. Batman Doom needs this.
@ -368,7 +363,7 @@ void AActor::Die (AActor *source, AActor *inflictor)
}
// [RH] Allow the death height to be overridden using metadata.
fixed_t metaheight = 0;
if (DamageType == MOD_FIRE)
if (DamageType == NAME_Fire)
{
metaheight = GetClass()->Meta.GetMetaFixed (AMETA_BurnHeight);
}
@ -612,29 +607,26 @@ void AActor::Die (AActor *source, AActor *inflictor)
return;
}
if (DamageType == MOD_DISINTEGRATE && EDeathState)
{ // Electrocution death
SetState (EDeathState);
}
else if (DamageType == MOD_FIRE && BDeathState)
{ // Burn death
SetState (BDeathState);
}
else if (DamageType == MOD_ICE &&
(IDeathState || (
(!deh.NoAutofreeze && !(flags4 & MF4_NOICEDEATH)) &&
(player || (flags3 & MF3_ISMONSTER)))))
{ // Ice death
if (IDeathState)
FState *diestate=NULL;
if (DamageType != NAME_None)
{
diestate = GetClass()->ActorInfo->FindStateExact (2, NAME_Death, int(DamageType));
if (diestate == NULL)
{
SetState (IDeathState);
}
else
{
SetState (&AActor::States[S_GENERICFREEZEDEATH]);
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)))
{
diestate = &AActor::States[S_GENERICFREEZEDEATH];
}
}
}
}
else
if (diestate == NULL)
{
int flags4 = !inflictor ? 0 : inflictor->player && inflictor->player->ReadyWeapon ?
inflictor->player->ReadyWeapon->flags4 : inflictor->flags4;
@ -642,40 +634,30 @@ void AActor::Die (AActor *source, AActor *inflictor)
int gibhealth = -abs(GetClass()->Meta.GetMetaInt (AMETA_GibHealth,
gameinfo.gametype == GAME_Doom ? -GetDefault()->health : -GetDefault()->health/2));
DamageType = MOD_UNKNOWN; // [RH] "Frozen" barrels shouldn't do freezing damage
if (XDeathState && (health<gibhealth || flags4 & MF4_EXTREMEDEATH) && !(flags4 & MF4_NOEXTREMEDEATH))
DamageType =NAME_None; // Don't pass on a damage type this actor cannot handle
// (most importantly prevent barrels from passing on ice damage)
if ((health<gibhealth || flags4 & MF4_EXTREMEDEATH) && !(flags4 & MF4_NOEXTREMEDEATH))
{ // Extreme death
SetState (XDeathState);
diestate = FindState (2, NAME_Death, NAME_Extreme);
}
else
{ // Normal death
DamageType = MOD_UNKNOWN; // [RH] "Frozen" barrels shouldn't do freezing damage
if (DeathState != NULL) // [RH] DeathState might be NULL, so try others as needed
{
SetState (DeathState);
}
else if (EDeathState != NULL)
{
SetState (EDeathState);
}
else if (BDeathState != NULL)
{
SetState (BDeathState);
}
else if (IDeathState != NULL)
{
SetState (IDeathState);
}
else
{
Destroy();
}
diestate = FindState (NAME_Death);
}
}
tics -= pr_killmobj() & 3;
if (tics < 1)
tics = 1;
if (diestate != NULL)
{
SetState (diestate);
tics -= pr_killmobj() & 3;
if (tics < 1)
tics = 1;
}
else
{
Destroy();
}
}
@ -794,9 +776,8 @@ void P_AutoUseStrifeHealth (player_t *player)
==================
*/
int MeansOfDeath;
void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, int mod, int flags)
void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags)
{
unsigned ang;
player_t *player;
@ -824,7 +805,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
}
if (target->health <= 0)
{
if (inflictor && mod == MOD_ICE)
if (inflictor && mod == NAME_Ice)
{
return;
}
@ -858,6 +839,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
}
MeansOfDeath = mod;
FriendlyFire = false;
// [RH] Andy Baker's Stealth monsters
if (target->flags & MF_STEALTH)
{
@ -898,7 +880,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
return;
}
}
if (mod == MOD_FIRE && target->flags4 & MF4_FIRERESIST)
if (mod == NAME_Fire && target->flags4 & MF4_FIRERESIST)
{
damage /= 2;
}
@ -1000,7 +982,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
// [RH] Avoid friendly fire if enabled
if (source != NULL && player != source->player && target->IsTeammate (source))
{
MeansOfDeath |= MOD_FRIENDLY_FIRE;
FriendlyFire = true;
if (damage < 1000000)
{ // Still allow telefragging :-(
damage = (int)((float)damage * teamdamage);
@ -1066,7 +1048,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
target->target = source;
}
// check for special fire damage or ice damage deaths
if (mod == MOD_FIRE)
if (mod == NAME_Fire)
{
if (player && !player->morphTics)
{ // Check for flame death
@ -1074,12 +1056,12 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
((target->health > -50) && (damage > 25)) ||
!inflictor->IsKindOf (RUNTIME_CLASS(APhoenixFX1)))
{
target->DamageType = MOD_FIRE;
target->DamageType = NAME_Fire;
}
}
else
{
target->DamageType = MOD_FIRE;
target->DamageType = NAME_Fire;
}
}
else
@ -1103,28 +1085,27 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
target->Die (source, inflictor);
return;
}
if (target->WoundState != NULL)
FState * woundstate = target->FindState(2,NAME_Wound, (int)mod);
if (woundstate != NULL)
{
int woundhealth = RUNTIME_TYPE(target)->Meta.GetMetaInt (AMETA_WoundHealth, 6);
if (target->health <= woundhealth)
{
target->SetState (target->WoundState);
target->SetState (woundstate);
return;
}
}
if ((pr_damagemobj() < target->PainChance) && target->PainState != NULL
&& !(target->flags & MF_SKULLFLY))
if ((pr_damagemobj() < target->PainChance) && !(target->flags & MF_SKULLFLY))
{
if (inflictor && inflictor->IsKindOf (RUNTIME_CLASS(ALightning)))
{
if (pr_lightning() < 96)
{
target->flags |= MF_JUSTHIT; // fight back!
if (target->PainState != NULL)
{
target->SetState (target->PainState);
}
FState * painstate = target->FindState(2,NAME_Pain, (int)mod);
if (painstate != NULL) target->SetState (painstate);
}
else
{ // "electrocute" the target
@ -1138,7 +1119,8 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
else
{
target->flags |= MF_JUSTHIT; // fight back!
target->SetState (target->PainState);
FState * painstate = target->FindState(2,NAME_Pain, (int)mod);
if (painstate != NULL) target->SetState (painstate);
if (inflictor && inflictor->IsKindOf (RUNTIME_CLASS(APoisonCloud)))
{
if ((target->flags3 & MF3_ISMONSTER) && pr_poison() < 128)
@ -1317,22 +1299,20 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage,
target->special1 = damage;
if (player && inflictor && !player->morphTics)
{ // Check for flame death
if ((inflictor->DamageType == MOD_FIRE)
if ((inflictor->DamageType == NAME_Fire)
&& (target->health > -50) && (damage > 25))
{
target->DamageType = MOD_FIRE;
}
if (inflictor->DamageType == MOD_ICE)
{
target->DamageType = MOD_ICE;
target->DamageType = NAME_Fire;
}
else target->DamageType = inflictor->DamageType;
}
target->Die (source, source);
return;
}
if (!(level.time&63) && playPainSound && target->PainState != NULL)
if (!(level.time&63) && playPainSound)
{
target->SetState (target->PainState);
FState * painstate = target->FindState(2,NAME_Pain, (int)target->DamageType);
if (painstate != NULL) target->SetState (painstate);
}
/*
if((P_Random() < target->info->painchance)