- Added ACS GetChar function.

- Added Gez's submission for polyobjects being able to crush corpses but made
  it an explicit MAPINFO option only.


SVN r1585 (trunk)
This commit is contained in:
Christoph Oelckers 2009-05-15 17:21:45 +00:00
parent a732687548
commit eb52c9a90e
8 changed files with 136 additions and 96 deletions

View file

@ -1,4 +1,7 @@
May 15, 2009 (Changes by Graf Zahl)
- Added ACS GetChar function.
- Added Gez's submission for polyobjects being able to crush corpses but made
it an explicit MAPINFO option only.
- Changed APlayerPawn::DamageFade to a PalEntry from 3 floats.
- Removed #pragma warnings from cmdlib.h and fixed the places where they were
still triggered.

View file

@ -598,6 +598,9 @@ public:
// Die. Now.
virtual bool Massacre ();
// Transforms the actor into a finely-ground paste
bool Grind(bool items);
// Is the other actor on my team?
bool IsTeammate (AActor *other);

View file

@ -197,6 +197,7 @@ enum ELevelFlags
LEVEL2_HEXENHACK = 0x00800000, // Level was defined in a Hexen style MAPINFO
LEVEL2_SMOOTHLIGHTING = 0x01000000, // Level uses the smooth lighting feature.
LEVEL2_POLYGRIND = 0x02000000, // Polyobjects grind corpses to gibs.
};

View file

@ -1309,6 +1309,8 @@ MapFlagHandlers[] =
{ "teamplayoff", MITYPE_SCFLAGS2, LEVEL2_FORCETEAMPLAYOFF, ~LEVEL2_FORCETEAMPLAYON },
{ "checkswitchrange", MITYPE_SETFLAG2, LEVEL2_CHECKSWITCHRANGE, 0 },
{ "nocheckswitchrange", MITYPE_CLRFLAG2, LEVEL2_CHECKSWITCHRANGE, 0 },
{ "grinding_polyobj", MITYPE_SETFLAG2, LEVEL2_POLYGRIND, 0 },
{ "no_grinding_polyobj", MITYPE_CLRFLAG2, LEVEL2_POLYGRIND, 0 },
{ "unfreezesingleplayerconversations",MITYPE_SETFLAG2, LEVEL2_CONV_SINGLE_UNFREEZE, 0 },
{ "nobotnodes", MITYPE_IGNORE, 0, 0 }, // Skulltag option: nobotnodes
{ "compat_shorttex", MITYPE_COMPATFLAG, COMPATF_SHORTTEX},

View file

@ -2795,6 +2795,7 @@ enum EACSFunctions
ACSF_SetActivator,
ACSF_SetActivatorToTarget,
ACSF_GetActorViewHeight,
ACSF_GetChar,
};
int DLevelScript::SideFromID(int id, int side)
@ -2893,6 +2894,19 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
}
else return 0;
case ACSF_GetChar:
{
const char *p = FBehavior::StaticLookupString(args[0]);
if (p != NULL && args[1] >= 0 && args[1] < strlen(p))
{
return p[args[1]];
}
else
{
return 0;
}
}
default:
break;

View file

@ -38,7 +38,6 @@
#include "p_effect.h"
#include "p_terrain.h"
#include "p_trace.h"
#include "p_enemy.h"
#include "s_sound.h"
#include "decallib.h"
@ -4192,101 +4191,7 @@ void P_FindBelowIntersectors (AActor *actor)
void P_DoCrunch (AActor *thing, FChangePosition *cpos)
{
// crunch bodies to giblets
if ((thing->flags & MF_CORPSE) &&
!(thing->flags3 & MF3_DONTGIB) &&
(thing->health <= 0))
{
FState * state = thing->FindState(NAME_Crush);
if (state != NULL && !(thing->flags & MF_ICECORPSE))
{
if (thing->flags4 & MF4_BOSSDEATH)
{
CALL_ACTION(A_BossDeath, thing);
}
thing->flags &= ~MF_SOLID;
thing->flags3 |= MF3_DONTGIB;
thing->height = thing->radius = 0;
thing->SetState (state);
return;
}
if (!(thing->flags & MF_NOBLOOD))
{
if (thing->flags4 & MF4_BOSSDEATH)
{
CALL_ACTION(A_BossDeath, thing);
}
const PClass *i = PClass::FindClass("RealGibs");
if (i != NULL)
{
i = i->ActorInfo->GetReplacement()->Class;
const AActor *defaults = GetDefaultByType (i);
if (defaults->SpawnState == NULL ||
sprites[defaults->SpawnState->sprite].numframes == 0)
{
i = NULL;
}
}
if (i == NULL)
{
// if there's no gib sprite don't crunch it.
thing->flags &= ~MF_SOLID;
thing->flags3 |= MF3_DONTGIB;
thing->height = thing->radius = 0;
return;
}
AActor *gib = Spawn (i, thing->x, thing->y, thing->z, ALLOW_REPLACE);
if (gib != NULL)
{
gib->RenderStyle = thing->RenderStyle;
gib->alpha = thing->alpha;
gib->height = 0;
gib->radius = 0;
}
S_Sound (thing, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE);
PalEntry bloodcolor = (PalEntry)thing->GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
if (bloodcolor!=0) gib->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
}
if (thing->flags & MF_ICECORPSE)
{
thing->tics = 1;
thing->momx = thing->momy = thing->momz = 0;
}
else if (thing->player)
{
thing->flags |= MF_NOCLIP;
thing->flags3 |= MF3_DONTGIB;
thing->renderflags |= RF_INVISIBLE;
}
else
{
thing->Destroy ();
}
return; // keep checking
}
// crunch dropped items
if (thing->flags & MF_DROPPED)
{
thing->Destroy ();
return; // keep checking
}
if (!(thing->flags & MF_SOLID) || (thing->flags & MF_NOCLIP))
{
return;
}
if (!(thing->flags & MF_SHOOTABLE))
{
return; // assume it is bloody gibs or something
}
if (!(thing && thing->Grind(true) && cpos)) return;
cpos->nofit = true;
if ((cpos->crushchange > 0) && !(level.maptime & 3))

View file

@ -59,6 +59,7 @@
#include "d_event.h"
#include "colormatcher.h"
#include "v_palette.h"
#include "p_enemy.h"
// MACROS ------------------------------------------------------------------
@ -963,6 +964,115 @@ void AActor::Touch (AActor *toucher)
{
}
//============================================================================
//
// AActor :: Grind
//
// Handles the an actor being crushed by a door, crusher or polyobject.
// Originally part of P_DoCrunch(), it has been made into its own actor
// function so that it could be called from a polyobject without hassle.
// Bool items is true if it should destroy() dropped items, false otherwise.
//============================================================================
bool AActor::Grind(bool items)
{
// crunch bodies to giblets
if ((this->flags & MF_CORPSE) &&
!(this->flags3 & MF3_DONTGIB) &&
(this->health <= 0))
{
FState * state = this->FindState(NAME_Crush);
if (state != NULL && !(this->flags & MF_ICECORPSE))
{
if (this->flags4 & MF4_BOSSDEATH)
{
CALL_ACTION(A_BossDeath, this);
}
this->flags &= ~MF_SOLID;
this->flags3 |= MF3_DONTGIB;
this->height = this->radius = 0;
this->SetState (state);
return false;
}
if (!(this->flags & MF_NOBLOOD))
{
if (this->flags4 & MF4_BOSSDEATH)
{
CALL_ACTION(A_BossDeath, this);
}
const PClass *i = PClass::FindClass("RealGibs");
if (i != NULL)
{
i = i->ActorInfo->GetReplacement()->Class;
const AActor *defaults = GetDefaultByType (i);
if (defaults->SpawnState == NULL ||
sprites[defaults->SpawnState->sprite].numframes == 0)
{
i = NULL;
}
}
if (i == NULL)
{
// if there's no gib sprite don't crunch it.
this->flags &= ~MF_SOLID;
this->flags3 |= MF3_DONTGIB;
this->height = this->radius = 0;
return false;
}
AActor *gib = Spawn (i, this->x, this->y, this->z, ALLOW_REPLACE);
if (gib != NULL)
{
gib->RenderStyle = this->RenderStyle;
gib->alpha = this->alpha;
gib->height = 0;
gib->radius = 0;
}
S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE);
PalEntry bloodcolor = (PalEntry)this->GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
if (bloodcolor!=0) gib->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
}
if (this->flags & MF_ICECORPSE)
{
this->tics = 1;
this->momx = this->momy = this->momz = 0;
}
else if (this->player)
{
this->flags |= MF_NOCLIP;
this->flags3 |= MF3_DONTGIB;
this->renderflags |= RF_INVISIBLE;
}
else
{
this->Destroy ();
}
return false; // keep checking
}
// crunch dropped items
if (this->flags & MF_DROPPED)
{
if (items) this->Destroy (); // Only destroy dropped items if wanted
return false; // keep checking
}
if (!(this->flags & MF_SOLID) || (this->flags & MF_NOCLIP))
{
return false;
}
if (!(this->flags & MF_SHOOTABLE))
{
return false; // assume it is bloody gibs or something
}
return true;
}
//============================================================================
//
// AActor :: Massacre

View file

@ -25,6 +25,7 @@
#include "r_main.h"
#include "p_lnspec.h"
#include "r_interpolate.h"
#include "g_level.h"
// MACROS ------------------------------------------------------------------
@ -780,6 +781,7 @@ void ThrustMobj (AActor *actor, seg_t *seg, FPolyObj *po)
P_TraceBleed (po->crush, actor);
}
}
if (level.flags2 & LEVEL2_POLYGRIND) actor->Grind(false); // crush corpses that get caught in a polyobject's way
}
//==========================================================================