- Update scripting branch to trunk.

SVN r3758 (scripting)
This commit is contained in:
Randy Heit 2012-07-14 03:04:41 +00:00
commit 562cf04db2
614 changed files with 63691 additions and 31256 deletions

View file

@ -176,7 +176,7 @@ void SexMessage (const char *from, char *to, int gender, const char *victim, con
// [RH]
// ClientObituary: Show a message when a player dies
//
void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgflags)
{
FName mod;
const char *message;
@ -192,7 +192,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
gender = self->player->userinfo.gender;
// Treat voodoo dolls as unknown deaths
if (inflictor && inflictor->player == self->player)
if (inflictor && inflictor->player && inflictor->player->mo != inflictor)
MeansOfDeath = NAME_None;
if (multiplayer && !deathmatch)
@ -228,6 +228,12 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
case NAME_Fire: if (attacker == NULL) messagename = "OB_LAVA"; break;
}
// Check for being killed by a voodoo doll.
if (inflictor && inflictor->player && inflictor->player->mo != inflictor)
{
messagename = "OB_VOODOO";
}
if (messagename != NULL)
message = GStrings(messagename);
@ -274,7 +280,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
{
message = inflictor->GetClass()->Obituary;
}
if (message == NULL && attacker->player->ReadyWeapon != NULL && attacker->player->ReadyWeapon->GetClass()->Obituary.IsNotEmpty())
if (message == NULL && (dmgflags & DMG_PLAYERATTACK) && attacker->player->ReadyWeapon != NULL)
{
message = attacker->player->ReadyWeapon->GetClass()->Obituary;
}
@ -288,6 +294,10 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
if (messagename != NULL)
message = GStrings(messagename);
}
if (message == NULL)
{
message = attacker->GetClass()->Obituary;
}
}
}
}
@ -295,7 +305,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
if (message != NULL && message[0] == '$')
{
message=GStrings[message+1];
message = GStrings[message+1];
}
if (message == NULL)
@ -314,11 +324,10 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
//
EXTERN_CVAR (Int, fraglimit)
void AActor::Die (AActor *source, AActor *inflictor)
void AActor::Die (AActor *source, AActor *inflictor, int dmgflags)
{
// Handle possible unmorph on death
bool wasgibbed = (health < GetGibHealth());
AActor *realthis = NULL;
int realstyle = 0;
int realhealth = 0;
@ -334,7 +343,7 @@ void AActor::Die (AActor *source, AActor *inflictor)
realthis->health = realgibhealth -1; // if morphed was gibbed, so must original be (where allowed)
}
}
realthis->Die(source, inflictor);
realthis->Die(source, inflictor, dmgflags);
}
return;
}
@ -380,7 +389,8 @@ void AActor::Die (AActor *source, AActor *inflictor)
{ // [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.
flags |= MF_CORPSE;
// [RC] And disable this if DONTCORPSE is set, of course.
if(!(flags6 & MF6_DONTCORPSE)) flags |= MF_CORPSE;
}
flags6 |= MF6_KILLED;
@ -507,53 +517,56 @@ void AActor::Die (AActor *source, AActor *inflictor)
}
// [RH] Multikills
source->player->multicount++;
if (source->player->lastkilltime > 0)
if (player != source->player)
{
if (source->player->lastkilltime < level.time - 3*TICRATE)
source->player->multicount++;
if (source->player->lastkilltime > 0)
{
source->player->multicount = 1;
}
if (deathmatch &&
source->CheckLocalView (consoleplayer) &&
cl_showmultikills)
{
const char *multimsg;
switch (source->player->multicount)
if (source->player->lastkilltime < level.time - 3*TICRATE)
{
case 1:
multimsg = NULL;
break;
case 2:
multimsg = GStrings("MULTI2");
break;
case 3:
multimsg = GStrings("MULTI3");
break;
case 4:
multimsg = GStrings("MULTI4");
break;
default:
multimsg = GStrings("MULTI5");
break;
source->player->multicount = 1;
}
if (multimsg != NULL)
{
char buff[256];
if (!AnnounceMultikill (source))
if (deathmatch &&
source->CheckLocalView (consoleplayer) &&
cl_showmultikills)
{
const char *multimsg;
switch (source->player->multicount)
{
SexMessage (multimsg, buff, player->userinfo.gender,
player->userinfo.netname, source->player->userinfo.netname);
StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, buff,
1.5f, 0.8f, 0, 0, CR_RED, 3.f, 0.5f), MAKE_ID('M','K','I','L'));
case 1:
multimsg = NULL;
break;
case 2:
multimsg = GStrings("MULTI2");
break;
case 3:
multimsg = GStrings("MULTI3");
break;
case 4:
multimsg = GStrings("MULTI4");
break;
default:
multimsg = GStrings("MULTI5");
break;
}
if (multimsg != NULL)
{
char buff[256];
if (!AnnounceMultikill (source))
{
SexMessage (multimsg, buff, player->userinfo.gender,
player->userinfo.netname, source->player->userinfo.netname);
StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, buff,
1.5f, 0.8f, 0, 0, CR_RED, 3.f, 0.5f), MAKE_ID('M','K','I','L'));
}
}
}
}
source->player->lastkilltime = level.time;
}
source->player->lastkilltime = level.time;
// [RH] Implement fraglimit
if (deathmatch && fraglimit &&
@ -574,7 +587,7 @@ void AActor::Die (AActor *source, AActor *inflictor)
if (player)
{
// [RH] Death messages
ClientObituary (this, inflictor, source);
ClientObituary (this, inflictor, source, dmgflags);
// Death script execution, care of Skull Tag
FBehavior::StaticStartTypedScripts (SCRIPT_Death, this, true);
@ -636,13 +649,14 @@ void AActor::Die (AActor *source, AActor *inflictor)
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)))
@ -661,9 +675,9 @@ void AActor::Die (AActor *source, AActor *inflictor)
// 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))
@ -860,6 +874,12 @@ void P_AutoUseStrifeHealth (player_t *player)
==================
*/
static inline bool MustForcePain(AActor *target, AActor *inflictor)
{
return (!(target->flags5 & MF5_NOPAIN) && inflictor != NULL &&
(inflictor->flags6 & MF6_FORCEPAIN) && !(inflictor->flags5 & MF5_PAINLESS));
}
void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags)
{
@ -944,7 +964,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
return;
}
player = target->player;
if (player && damage > 1)
if (player && damage > 1 && damage < TELEFRAG_DAMAGE)
{
// Take half damage in trainer mode
damage = FixedMul(damage, G_SkillProperty(SKILLP_DamageFactor));
@ -956,17 +976,17 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
{
if (player != NULL)
{
if (!deathmatch && inflictor->health == -1)
if (!deathmatch && inflictor->FriendPlayer > 0)
return;
}
else if (target->flags4 & MF4_SPECTRAL)
{
if (inflictor->health == -2 && !target->IsHostile(inflictor))
if (inflictor->FriendPlayer == 0 && !target->IsHostile(inflictor))
return;
}
}
damage = inflictor->DoSpecialDamage (target, damage);
damage = inflictor->DoSpecialDamage (target, damage, mod);
if (damage == -1)
{
return;
@ -978,7 +998,13 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
int olddam = damage;
source->Inventory->ModifyDamage(olddam, mod, damage, false);
if (olddam != damage && damage <= 0)
{ // Still allow FORCEPAIN
if (MustForcePain(target, inflictor))
{
goto dopain;
}
return;
}
}
// Handle passive damage modifiers (e.g. PowerProtection)
if (target->Inventory != NULL)
@ -986,29 +1012,30 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
int olddam = damage;
target->Inventory->ModifyDamage(olddam, mod, damage, true);
if (olddam != damage && damage <= 0)
{ // Still allow FORCEPAIN
if (MustForcePain(target, inflictor))
{
goto dopain;
}
return;
}
}
if (!(flags & DMG_NO_FACTOR))
{
DmgFactors *df = target->GetClass()->DamageFactors;
if (df != NULL)
{
fixed_t *pdf = df->CheckKey(mod);
if (pdf== NULL && mod != NAME_None)
{
pdf = df->CheckKey(NAME_None);
}
if (pdf != NULL)
{
damage = FixedMul(damage, *pdf);
if (damage <= 0)
return;
}
}
damage = FixedMul(damage, target->DamageFactor);
if (damage < 0)
if (damage >= 0)
{
damage = DamageTypeDefinition::ApplyMobjDamageFactor(damage, mod, target->GetClass()->DamageFactors);
}
if (damage <= 0)
{ // Still allow FORCEPAIN
if (MustForcePain(target, inflictor))
{
goto dopain;
}
return;
}
}
damage = target->TakeSpecialDamage (inflictor, source, damage, mod);
@ -1027,7 +1054,9 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
{
int kickback;
if (!source || !source->player || !source->player->ReadyWeapon)
if (inflictor && inflictor->projectileKickback)
kickback = inflictor->projectileKickback;
else if (!source || !source->player || !source->player->ReadyWeapon)
kickback = gameinfo.defKickback;
else
kickback = source->player->ReadyWeapon->Kickback;
@ -1086,6 +1115,21 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
}
}
// [RH] Avoid friendly fire if enabled
if (!(flags & DMG_FORCED) && source != NULL &&
((player && player != source->player) || (!player && target != source)) &&
target->IsTeammate (source))
{
if (player)
FriendlyFire = true;
if (damage < TELEFRAG_DAMAGE)
{ // Still allow telefragging :-(
damage = (int)((float)damage * level.teamdamage);
if (damage <= 0)
return;
}
}
//
// player specific
//
@ -1114,17 +1158,6 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
return;
}
// [RH] Avoid friendly fire if enabled
if (source != NULL && player != source->player && target->IsTeammate (source))
{
FriendlyFire = true;
if (damage < TELEFRAG_DAMAGE)
{ // Still allow telefragging :-(
damage = (int)((float)damage * level.teamdamage);
if (damage <= 0)
return;
}
}
if (!(flags & DMG_NO_ARMOR) && player->mo->Inventory != NULL)
{
int newdam = damage;
@ -1133,8 +1166,11 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
if (damage <= 0)
{
// If MF6_FORCEPAIN is set, make the player enter the pain state.
if (inflictor != NULL && (inflictor->flags6 & MF6_FORCEPAIN))
goto dopain;
if (!(target->flags5 & MF5_NOPAIN) && inflictor != NULL &&
(inflictor->flags6 & MF6_FORCEPAIN) && !(inflictor->flags5 & MF5_PAINLESS))
{
goto dopain;
}
return;
}
}
@ -1163,7 +1199,8 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
// but telefragging should still do enough damage to kill the player)
if ((player->cheats & CF_BUDDHA) && damage < TELEFRAG_DAMAGE)
{
target->health = player->health = 1;
// If this is a voodoo doll we need to handle the real player as well.
player->mo->health = target->health = player->health = 1;
}
else
{
@ -1203,6 +1240,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
//
// the damage has been dealt; now deal with the consequences
//
target->DamageTypeReceived = mod;
// If the damaging player has the power of drain, give the player 50% of the damage
// done in health.
@ -1250,7 +1288,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
source = source->tracer;
}
}
target->Die (source, inflictor);
target->Die (source, inflictor, flags);
return;
}
@ -1268,7 +1306,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
if (!(target->flags5 & MF5_NOPAIN) && (inflictor == NULL || !(inflictor->flags5 & MF5_PAINLESS)) &&
!G_SkillProperty(SKILLP_NoPain) && !(target->flags & MF_SKULLFLY))
(target->player != NULL || !G_SkillProperty(SKILLP_NoPain)) && !(target->flags & MF_SKULLFLY))
{
pc = target->GetClass()->PainChances;
painchance = target->PainChance;
@ -1306,7 +1344,7 @@ dopain:
else
{
justhit = true;
FState *painstate = target->FindState(NAME_Pain, mod);
FState *painstate = target->FindState(NAME_Pain, ((inflictor && inflictor->PainType != NAME_None) ? inflictor->PainType : mod));
if (painstate != NULL)
target->SetState(painstate);
if (mod == NAME_PoisonCloud)
@ -1358,12 +1396,30 @@ dopain:
target->flags |= MF_JUSTHIT; // fight back!
}
void P_PoisonMobj (AActor *target, AActor *inflictor, AActor *source, int damage, int duration, int period)
void P_PoisonMobj (AActor *target, AActor *inflictor, AActor *source, int damage, int duration, int period, FName type)
{
int olddamage = target->PoisonDamageReceived;
int oldduration = target->PoisonDurationReceived;
// Check for invulnerability.
if (!(inflictor->flags6 & MF6_POISONALWAYS))
{
if (target->flags2 & MF2_INVULNERABLE)
{ // actor is invulnerable
if (target->player == NULL)
{
if (!(inflictor->flags3 & MF3_FOILINVUL))
{
return;
}
}
else
{
return;
}
}
}
target->Poisoner = source;
target->PoisonDamageTypeReceived = type;
target->PoisonPeriodReceived = period;
if (inflictor->flags6 & MF6_ADDITIVEPOISONDAMAGE)
{
@ -1383,7 +1439,6 @@ void P_PoisonMobj (AActor *target, AActor *inflictor, AActor *source, int damage
target->PoisonDurationReceived = duration;
}
target->PoisonPeriodReceived = period;
}
bool AActor::OkayToSwitchTarget (AActor *other)
@ -1461,6 +1516,15 @@ bool P_PoisonPlayer (player_t *player, AActor *poisoner, AActor *source, int poi
{
player->poisoncount += poison;
player->poisoner = poisoner;
if (poisoner == NULL)
{
player->poisontype = player->poisonpaintype = NAME_None;
}
else
{ // We need to record these in case the poisoner disappears before poisoncount reaches 0.
player->poisontype = poisoner->DamageType;
player->poisonpaintype = poisoner->PainType != NAME_None ? poisoner->PainType : poisoner->DamageType;
}
if(player->poisoncount > 100)
{
player->poisoncount = 100;
@ -1497,16 +1561,31 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage,
// Take half damage in trainer mode
damage = FixedMul(damage, G_SkillProperty(SKILLP_DamageFactor));
}
// Handle passive damage modifiers (e.g. PowerProtection)
if (target->Inventory != NULL)
{
target->Inventory->ModifyDamage(damage, player->poisontype, damage, true);
}
// Modify with damage factors
damage = FixedMul(damage, target->DamageFactor);
if (damage > 0)
{
damage = DamageTypeDefinition::ApplyMobjDamageFactor(damage, player->poisontype, target->GetClass()->DamageFactors);
}
if (damage <= 0)
{ // Damage was reduced to 0, so don't bother further.
return;
}
if (damage >= player->health
&& (G_SkillProperty(SKILLP_AutoUseHealth) || deathmatch)
&& !player->morphTics)
{ // Try to use some inventory health
P_AutoUseHealth (player, damage - player->health+1);
P_AutoUseHealth(player, damage - player->health+1);
}
player->health -= damage; // mirror mobj health here for Dave
if (player->health < 50 && !deathmatch)
{
P_AutoUseStrifeHealth (player);
P_AutoUseStrifeHealth(player);
}
if (player->health < 0)
{
@ -1520,30 +1599,35 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage,
target->health -= damage;
if (target->health <= 0)
{ // Death
if ( player->cheats & CF_BUDDHA )
if (player->cheats & CF_BUDDHA)
{ // [SP] Save the player...
player->health = target->health = 1;
}
else
{
target->special1 = damage;
if (player && inflictor && !player->morphTics)
if (player && !player->morphTics)
{ // Check for flame death
if ((inflictor->DamageType == NAME_Fire)
&& (target->health > -50) && (damage > 25))
if ((player->poisontype == NAME_Fire) && (target->health > -50) && (damage > 25))
{
target->DamageType = NAME_Fire;
}
else target->DamageType = inflictor->DamageType;
else
{
target->DamageType = player->poisontype;
}
}
target->Die (source, source);
target->Die(source, source);
return;
}
}
if (!(level.time&63) && playPainSound)
{
FState * painstate = target->FindState(NAME_Pain, target->DamageType);
if (painstate != NULL) target->SetState (painstate);
FState *painstate = target->FindState(NAME_Pain, player->poisonpaintype);
if (painstate != NULL)
{
target->SetState(painstate);
}
}
/*
if((P_Random() < target->info->painchance)