From eb52c9a90eb84b897d6996483ab2e08d75cfe0c4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 15 May 2009 17:21:45 +0000 Subject: [PATCH] - 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) --- docs/rh-log.txt | 3 ++ src/actor.h | 3 ++ src/g_level.h | 1 + src/g_mapinfo.cpp | 2 + src/p_acs.cpp | 14 ++++++ src/p_map.cpp | 97 +--------------------------------------- src/p_mobj.cpp | 110 ++++++++++++++++++++++++++++++++++++++++++++++ src/po_man.cpp | 2 + 8 files changed, 136 insertions(+), 96 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 5cf630cb7..4156eba49 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -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. diff --git a/src/actor.h b/src/actor.h index 8bd5edc13..35e51de6f 100644 --- a/src/actor.h +++ b/src/actor.h @@ -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); diff --git a/src/g_level.h b/src/g_level.h index 8e475719a..6bb7260d1 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -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. }; diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index 6f01aa73f..e95d59a38 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -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}, diff --git a/src/p_acs.cpp b/src/p_acs.cpp index de71852f7..9643c50b8 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -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; diff --git a/src/p_map.cpp b/src/p_map.cpp index 30c3b4946..a303f2975 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -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)) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index eb4036925..030764440 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -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 diff --git a/src/po_man.cpp b/src/po_man.cpp index 5277fc8bd..68908ece1 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -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 } //==========================================================================