Update to ZDoom r1831:

fixed: The Dehacked flags parser fix from May 31 (r1624) was undone by
  yesterday's additions. Changed it so that the parser first checks for 
  the presence of a '-' sign before deciding whether to use strtol or
  strtoul to convert the string into a number.
- Added PinkSilver's A_LookEx fix.
- added resources needed for MBF support.
- removed unused score items from DECORATE file.
- Fixed: Argument count for UsePuzzleItem was wrong.
- Added a few things from Gez's experimental build:
  * MBF Dehacked emulation but removed the COMPATF_MBFDEHACKED flag because
    it wouldn't work and is more or less useless anyway.
  * MBF's dog (definition only, no sprites yet.)
  * User variables. There's an array of 10. They can be set and checked in
    both DECORATE and ACS.
  * Made the tag name changeable but eliminated the redundancy of having
    both the meta property and the individual actor's one. Having one is
	fully sufficient. TO BE FIXED: Names are case insensitive but this
	should better be case sensitive. Unfortunately there's currently nothing
	better than FName to store a string inside an actor without severely
	complicating matters. Also bumped savegame version to avoid problems
	with this change.
  * MBF grenade and bouncing code.
  * several compatibility options.
  * info CCMD to print extended actor information (not fully implemented yet)
  * summonmbf CCMD.
  * Beta BFG code pointer (but not the related missiles yet.)
  * PowerInvisibility enhancements.
  * ScoreItem with one significant change: Added a score variable that can be
    checked through ACS and DECORATE. The engine itself will do nothing with it.
  * Nailgun option for A_Explode.
  * A_PrintBold and A_Log.
  * A_SetSpecial.
  * Beta Lost Soul (added DoomEdNum 9037 to it)
  * A_Mushroom extensions
  * Vavoom compatible MAPINFO keynames.

git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@452 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
Christoph Oelckers 2009-09-15 06:19:39 +00:00
parent 67a7c1b1b7
commit 2352d102e9
152 changed files with 1991 additions and 445 deletions

View file

@ -1,3 +1,42 @@
September 15, 2009 (Changes by Graf Zahl)
- fixed: The Dehacked flags parser fix from May 31 (r1624) was undone by
yesterday's additions. Changed it so that the parser first checks for
the presence of a '-' sign before deciding whether to use strtol or
strtoul to convert the string into a number.
September 14, 2009 (Changes by Graf Zahl)
- Added PinkSilver's A_LookEx fix.
- added resources needed for MBF support.
- removed unused score items from DECORATE file.
- Fixed: Argument count for UsePuzzleItem was wrong.
- Added a few things from Gez's experimental build:
* MBF Dehacked emulation but removed the COMPATF_MBFDEHACKED flag because
it wouldn't work and is more or less useless anyway.
* MBF's dog (definition only, no sprites yet.)
* User variables. There's an array of 10. They can be set and checked in
both DECORATE and ACS.
* Made the tag name changeable but eliminated the redundancy of having
both the meta property and the individual actor's one. Having one is
fully sufficient. TO BE FIXED: Names are case insensitive but this
should better be case sensitive. Unfortunately there's currently nothing
better than FName to store a string inside an actor without severely
complicating matters. Also bumped savegame version to avoid problems
with this change.
* MBF grenade and bouncing code.
* several compatibility options.
* info CCMD to print extended actor information (not fully implemented yet)
* summonmbf CCMD.
* Beta BFG code pointer (but not the related missiles yet.)
* PowerInvisibility enhancements.
* ScoreItem with one significant change: Added a score variable that can be
checked through ACS and DECORATE. The engine itself will do nothing with it.
* Nailgun option for A_Explode.
* A_PrintBold and A_Log.
* A_SetSpecial.
* Beta Lost Soul (added DoomEdNum 9037 to it)
* A_Mushroom extensions
* Vavoom compatible MAPINFO keynames.
September 11, 2009
- Added warning messages when loading maps that have non-zero values in
unused line argument fields, because these maps could potentially break

View file

@ -7,13 +7,13 @@ DEFINE_SPECIAL(Polyobj_ExplicitLine, 5, -1, -1, 5)
DEFINE_SPECIAL(Polyobj_MoveTimes8, 6, 4, 4, 4)
DEFINE_SPECIAL(Polyobj_DoorSwing, 7, 4, 4, 4)
DEFINE_SPECIAL(Polyobj_DoorSlide, 8, 5, 5, 5)
DEFINE_SPECIAL(Line_Horizon, 9, -1, 0, 0) // [RH] draw one-sided wall at horizon
DEFINE_SPECIAL(Line_Horizon, 9, -1, 0, 0) // [RH] draw one-sided wall at horizon
DEFINE_SPECIAL(Door_Close, 10, 2, 3, 3)
DEFINE_SPECIAL(Door_Open, 11, 2, 3, 3)
DEFINE_SPECIAL(Door_Raise, 12, 3, 4, 4)
DEFINE_SPECIAL(Door_LockedRaise, 13, 4, 5, 5)
DEFINE_SPECIAL(Door_Animated, 14, 3, 3, 3)
DEFINE_SPECIAL(Autosave, 15, 0, 0, 0) // [RH] Save the game *now*
DEFINE_SPECIAL(Autosave, 15, 0, 0, 0) // [RH] Save the game *now*
DEFINE_SPECIAL(Transfer_WallLight, 16, -1, -1, 2)
DEFINE_SPECIAL(Thing_Raise, 17, 1, 1, 1)
DEFINE_SPECIAL(StartConversation, 18, 1, 2, 2)
@ -31,13 +31,13 @@ DEFINE_SPECIAL(Pillar_Build, 29, 3, 3, 3)
DEFINE_SPECIAL(Pillar_Open, 30, 4, 4, 4)
DEFINE_SPECIAL(Stairs_BuildDownSync, 31, 4, 4, 4)
DEFINE_SPECIAL(Stairs_BuildUpSync, 32, 4, 4, 4)
DEFINE_SPECIAL(ForceField, 33, 0, 0, 0) // [RH] Strife's forcefield special (148)
DEFINE_SPECIAL(ClearForceField, 34, 1, 1, 1) // [RH] Remove Strife's forcefield from tagged sectors
DEFINE_SPECIAL(ForceField, 33, 0, 0, 0) // [RH] Strife's forcefield special (148)
DEFINE_SPECIAL(ClearForceField, 34, 1, 1, 1) // [RH] Remove Strife's forcefield from tagged sectors
DEFINE_SPECIAL(Floor_RaiseByValueTimes8, 35, 3, 3, 3)
DEFINE_SPECIAL(Floor_LowerByValueTimes8, 36, 3, 3, 3)
DEFINE_SPECIAL(Floor_MoveToValue, 37, 3, 4, 4)
DEFINE_SPECIAL(Ceiling_Waggle, 38, 5, 5, 4) // [RH] Complement of Floor_Waggle
DEFINE_SPECIAL(Teleport_ZombieChanger, 39, 2, 2, 2) // [RH] Needed for Strife
DEFINE_SPECIAL(Ceiling_Waggle, 38, 5, 5, 4) // [RH] Complement of Floor_Waggle
DEFINE_SPECIAL(Teleport_ZombieChanger, 39, 2, 2, 2) // [RH] Needed for Strife
DEFINE_SPECIAL(Ceiling_LowerByValue, 40, 3, 3, 3)
DEFINE_SPECIAL(Ceiling_RaiseByValue, 41, 3, 3, 3)
DEFINE_SPECIAL(Ceiling_CrushAndRaise, 42, 3, 4, 4)
@ -105,9 +105,8 @@ DEFINE_SPECIAL(Light_Strobe, 116, 5, 5, 5)
DEFINE_SPECIAL(Light_Stop, 117, 1, 1, 1)
DEFINE_SPECIAL(Thing_Damage, 119, 2, 3, 3)
DEFINE_SPECIAL(Radius_Quake, 120, 5, 5, 5) // Earthquake
DEFINE_SPECIAL(Radius_Quake, 120, 5, 5, 5) // Earthquake
DEFINE_SPECIAL(Line_SetIdentification, 121, -1, -1, 5)
#if 0 // Skull Tag specials that might be added later
Thing_SetGravity, 122, -1, -1)
Thing_ReverseGravity, 123, -1, -1)
@ -119,7 +118,7 @@ Thing_SetSprite, 126, -1, -1)
#endif
DEFINE_SPECIAL(Thing_SetSpecial, 127, 5, 5, 5)
DEFINE_SPECIAL(ThrustThingZ, 128, 4, 4, 4)
DEFINE_SPECIAL(UsePuzzleItem, 129, 1, 1, 1)
DEFINE_SPECIAL(UsePuzzleItem, 129, 2, 5, 5)
DEFINE_SPECIAL(Thing_Activate, 130, 1, 1, 1)
DEFINE_SPECIAL(Thing_Deactivate, 131, 1, 1, 1)
DEFINE_SPECIAL(Thing_Remove, 132, 1, 1, 1)
@ -140,7 +139,7 @@ DEFINE_SPECIAL(Teleport_NoStop, 154, 2, 3, 3)
DEFINE_SPECIAL(FS_Execute, 158, 1, 4, 4)
DEFINE_SPECIAL(Sector_SetPlaneReflection, 159, 3, 3, 3)
DEFINE_SPECIAL(Sector_Set3DFloor, 160, -1, -1, 5)
DEFINE_SPECIAL(Sector_SetContents, 161, -1, -1, 5) // It probably doesn't use 5 args. Oh well.
DEFINE_SPECIAL(Sector_SetContents, 161, -1, -1, 3)
// [RH] Begin new specials for ZDoom
DEFINE_SPECIAL(Generic_Crusher2, 169, 5, 5, 5)

View file

@ -263,6 +263,8 @@ enum
MF4_FRIGHTENED = 0x40000000, // Monster runs away from player
/* = 0x80000000, */
// --- mobj.flags5 ---
MF5_FASTER = 0x00000001, // moves faster when DF_FAST_MONSTERS or nightmare is on.
MF5_FASTMELEE = 0x00000002, // has a faster melee attack when DF_FAST_MONSTERS or nightmare is on.
MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances.
@ -297,6 +299,8 @@ enum
MF5_PAINLESS = 0x40000000, // Actor always inflicts painless damage.
MF5_MOVEWITHSECTOR = 0x80000000, // P_ChangeSector() will still process this actor if it has MF_NOBLOCKMAP
// --- mobj.flags6 ---
MF6_NOBOSSRIP = 0x00000001, // For rippermissiles: Don't rip through bosses.
MF6_THRUSPECIES = 0x00000002, // Actors passes through other of the same species.
MF6_MTHRUSPECIES = 0x00000004, // Missile passes through actors of its shooter's species.
@ -306,7 +310,13 @@ enum
MF6_DONTHARMSPECIES = 0x00000040, // Don't hurt one's own species with explosions (hitscans, too?)
MF6_STEPMISSILE = 0x00000080, // Missile can "walk" up steps
MF6_NOTELEFRAG = 0x00000100, // [HW] Actor can't be telefragged
MF6_TOUCHY = 0x00000200, // From MBF: killough 11/98: dies when solids touch it
MF6_CANJUMP = 0x00000400, // From MBF: a dedicated flag instead of the BOUNCES+FLOAT+sentient combo
MF6_JUMPDOWN = 0x00000800, // From MBF: generalization of dog behavior wrt. dropoffs.
MF6_VULNERABLE = 0x00001000, // Actor can be damaged (even if not shootable).
MF6_ARMED = 0x00002000, // From MBF: Object is armed (for MF6_TOUCHY objects)
MF6_FALLING = 0x00004000, // From MBF: Object is falling (for pseudotorque simulation)
MF6_LINEDONE = 0x00008000, // From MBF: Object has already run a line effect
// --- mobj.renderflags ---
@ -370,7 +380,7 @@ enum replace_t
ALLOW_REPLACE = 1
};
enum EBounceType
enum EBounceFlags
{
BOUNCE_Walls = 1<<0, // bounces off of walls
BOUNCE_Floors = 1<<1, // bounces off of floors
@ -378,7 +388,7 @@ enum EBounceType
BOUNCE_Actors = 1<<3, // bounces off of some actors
BOUNCE_AllActors = 1<<4, // bounces off of all actors (requires BOUNCE_Actors to be set, too)
BOUNCE_AutoOff = 1<<5, // when bouncing off a floor, if the new Z velocity is below 3.0, disable further bouncing
BOUNCE_HereticType = 1<<6, // only works with floors and ceilings; you probably don't want to use it
BOUNCE_HereticType = 1<<6, // goes into Death state when bouncing on floors or ceilings
BOUNCE_UseSeeSound = 1<<7, // compatibility fallback. This will only be set by
// the compatibility handlers for the old bounce flags.
@ -386,6 +396,9 @@ enum EBounceType
BOUNCE_Quiet = 1<<9, // Strife's grenades don't make a bouncing sound
BOUNCE_ExplodeOnWater = 1<<10, // explodes when hitting a water surface
BOUNCE_CanBounceWater = 1<<11, // can bounce on water
// MBF bouncing is a bit different from other modes as Killough coded many special behavioral cases
// for them that are not present in ZDoom, so it is necessary to identify it properly.
BOUNCE_MBF = 1<<12, // This in itself is not a valid mode, but replaces MBF's MF_BOUNCE flag.
BOUNCE_TypeMask = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff | BOUNCE_HereticType,
@ -399,6 +412,9 @@ enum EBounceType
BOUNCE_Heretic = BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_HereticType,
BOUNCE_Doom = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff,
BOUNCE_Hexen = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors,
BOUNCE_Grenade = BOUNCE_MBF | BOUNCE_Doom, // Bounces on walls and flats like ZDoom bounce.
BOUNCE_Classic = BOUNCE_MBF | BOUNCE_Floors | BOUNCE_Ceilings, // Bounces on flats only, but
// does not die when bouncing.
// combined types
BOUNCE_DoomCompat = BOUNCE_Doom | BOUNCE_UseSeeSound,
@ -412,6 +428,20 @@ enum EBounceType
// being "Doom" or "Hexen" and BOUNCE_AllActors was the separate
// MF5_BOUNCEONACTORS, you must set BOUNCE_Actors for BOUNCE_AllActors to have
// an effect.
};
// Used to affect the logic for MF5_USESPECIAL and MF6_BUMPSPECIAL
// "thing" refers to what has the flag and the special, "trigger" refers to what used or bumped it
enum EThingSpecialActivationType
{
THINGSPEC_Default = 0, // Normal behavior: a player must be the trigger, and is the activator
THINGSPEC_ThingActs = 1, // The thing itself is the activator of the special
THINGSPEC_ThingTargets = 2, // The thing changes its target to the trigger
THINGSPEC_TriggerTargets = 4, // The trigger changes its target to the thing
THINGSPEC_MonsterTrigger = 8, // The thing can be triggered by a monster
THINGSPEC_MissileTrigger = 16, // The thing can be triggered by a projectile
};
// [RH] Like msecnode_t, but for the blockmap
@ -681,6 +711,11 @@ public:
bool CanSeek(AActor *target) const;
fixed_t GetGravity() const;
bool IsSentient() const;
const char *GetTag(const char *def = NULL) const;
// info for drawing
// NOTE: The first member variable *must* be x.
fixed_t x,y,z;
@ -727,7 +762,7 @@ public:
SWORD movecount; // when 0, select a new dir
TObjPtr<AActor> target; // thing being chased/attacked (or NULL)
// also the originator for missiles
TObjPtr<AActor> lastenemy; // Last known enemy -- killogh 2/15/98
TObjPtr<AActor> lastenemy; // Last known enemy -- killough 2/15/98
TObjPtr<AActor> LastHeard; // [RH] Last actor this one heard
SDWORD reactiontime; // if non 0, don't attack yet; used by
// player to freeze a bit after teleporting
@ -739,13 +774,14 @@ public:
WORD SpawnAngle;
int skillrespawncount;
int TIDtoHate; // TID of things to hate (0 if none)
FNameNoInit Species;
FNameNoInit Species; // For monster families
TObjPtr<AActor> tracer; // Thing being chased/attacked for tracers
TObjPtr<AActor> master; // Thing which spawned this one (prevents mutual attacks)
fixed_t floorclip; // value to use for floor clipping
int tid; // thing identifier
int special; // special
int args[5]; // special arguments
int uservar[10]; // user variables, accessible by DECORATE and ACS
AActor *inext, **iprev;// Links to other mobjs in same bucket
TObjPtr<AActor> goal; // Monster's goal if not chasing anything
@ -767,6 +803,9 @@ public:
int FastChaseStrafeCount;
fixed_t pushfactor;
int lastpush;
int activationtype; // How the thing behaves when activated with USESPECIAL or BUMPSPECIAL
int Score; // manipulated by score items, ACS or DECORATE. The engine doesn't use this itself for anything.
FNameNoInit Tag; // Strife's tag name. FIXME: should be case sensitive!
AActor *BlockingMobj; // Actor that blocked the last move
line_t *BlockingLine; // Line that blocked the last move
@ -949,6 +988,8 @@ inline T *Spawn (fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement)
return static_cast<T *>(AActor::StaticSpawn (RUNTIME_CLASS(T), x, y, z, allowreplacement));
}
void PrintMiscActorInfo(AActor * query);
#define S_FREETARGMOBJ 1
#endif // __P_MOBJ_H__

View file

@ -778,10 +778,31 @@ CCMD(linetarget)
linetarget->GetClass()->TypeName.GetChars(),
linetarget->health,
linetarget->SpawnHealth());
PrintMiscActorInfo(linetarget);
}
else Printf("No target found\n");
}
// As linetarget, but also give info about non-shootable actors
CCMD(info)
{
AActor *linetarget;
if (CheckCheatmode () || players[consoleplayer].mo == NULL) return;
P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->angle,MISSILERANGE, &linetarget, 0,
false, false, true);
if (linetarget)
{
Printf("Target=%s, Health=%d, Spawnhealth=%d\n",
linetarget->GetClass()->TypeName.GetChars(),
linetarget->health,
linetarget->SpawnHealth());
PrintMiscActorInfo(linetarget);
}
else Printf("No target found. Info cannot find actors that have\
the NOBLOCKMAP flag or have height/radius of 0.\n");
}
//-----------------------------------------------------------------------------
//
//

View file

@ -78,6 +78,7 @@ static FCompatOption Options[] =
{ "setslopeoverflow", 0, BCOMPATF_SETSLOPEOVERFLOW },
{ "resetplayerspeed", 0, BCOMPATF_RESETPLAYERSPEED },
{ "spechitoverflow", 0, BCOMPATF_SPECHITOVERFLOW },
{ "vileghosts", 0, BCOMPATF_VILEGHOSTS },
// list copied from g_mapinfo.cpp
{ "shorttex", COMPATF_SHORTTEX, 0 },
@ -101,6 +102,9 @@ static FCompatOption Options[] =
{ "wallrun", COMPATF_WALLRUN, 0 }, // [GZ] Added for CC MAP29
{ "anybossdeath", COMPATF_ANYBOSSDEATH, 0}, // [GZ] Added for UAC_DEAD
{ "mushroom", COMPATF_MUSHROOM, 0},
{ "mbfmonstermove", COMPATF_MBFMONSTERMOVE, 0 },
{ "corpsegibs", COMPATF_CORPSEGIBS, 0 },
{ "noblockfriends", COMPATF_NOBLOCKFRIENDS, 0 },
{ NULL, 0, 0 }
};

View file

@ -64,11 +64,14 @@
#include "v_palette.h"
#include "a_sharedglobal.h"
#include "thingdef/thingdef.h"
#include "thingdef/thingdef_exp.h"
#include "vectors.h"
#include "dobject.h"
#include "r_translate.h"
#include "sc_man.h"
#include "i_system.h"
#include "doomerrors.h"
#include "p_effect.h"
// [SO] Just the way Randy said to do it :)
// [RH] Made this CVAR_SERVERINFO
@ -142,6 +145,23 @@ static TArray<StyleName> StyleNames;
static TArray<const PClass *> AmmoNames;
static TArray<const PClass *> WeaponNames;
// DeHackEd trickery to support MBF-style parameters
// List of states that are hacked to use a codepointer
struct MBFParamState
{
FState * state;
int pointer;
};
static TArray<MBFParamState *> MBFParamStates;
// Data on how to correctly modify the codepointers
struct CodePointerAlias
{
char name[20];
char alias[20];
BYTE params;
};
static TArray<CodePointerAlias> MBFCodePointers;
// Miscellaneous info that used to be constant
DehInfo deh =
{
@ -309,7 +329,6 @@ static void PushTouchedActor(PClass *cls)
static int HandleMode (const char *mode, int num)
{
int i = 0;
while (Modes[i].name && stricmp (Modes[i].name, mode))
i++;
@ -575,12 +594,145 @@ static int GetLine (void)
}
}
// This enum must be in sync with the Aliases array in DEHSUPP.
enum MBFCodePointers
{
// Die and Detonate are not in this list because these codepointers have
// no dehacked arguments and therefore do not need special handling.
// NailBomb has no argument but is implemented as new parameters for A_Explode.
MBF_Mushroom, // misc1 = vrange (arg +3), misc2 = hrange (arg+4)
MBF_Spawn, // misc1 = type (arg +0), misc2 = Z-pos (arg +2)
MBF_Turn, // misc1 = angle (in degrees) (arg +0 but factor in current actor angle too)
MBF_Face, // misc1 = angle (in degrees) (arg +0)
MBF_Scratch, // misc1 = damage, misc 2 = sound
MBF_PlaySound, // misc1 = sound, misc2 = attenuation none (true) or normal (false)
MBF_RandomJump, // misc1 = state, misc2 = probability
MBF_LineEffect, // misc1 = Boom linedef type, misc2 = sector tag
SMMU_NailBomb, // No misc, but it's basically A_Explode with an added effect
};
int PrepareStateParameters(FState * state, int numparams, const PClass *cls);// Should probably be in a .h file.
// Hacks the parameter list for the given state so as to convert MBF-args (misc1 and misc2) into real args.
void SetDehParams(FState * state, int codepointer)
{
int value1 = state->GetMisc1();
int value2 = state->GetMisc2();
if (!(value1|value2)) return;
// Fakey fake script position thingamajig. Because NULL cannot be used instead.
// Even if the lump was parsed by an FScanner, there would hardly be a way to
// identify which line is troublesome.
FScriptPosition * pos = new FScriptPosition(FString("DEHACKED"), 0);
// Let's identify the codepointer we're dealing with.
PSymbolActionFunction * sym; PSymbol * s;
s = RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(FName(MBFCodePointers[codepointer].name), true);
if (!s || s->SymbolType != SYM_ActionFunction) return;
sym = static_cast<PSymbolActionFunction*>(s);
// Bleargh! This will all have to be redone once scripting works
// Not sure exactly why the index for a state is greater by one point than the index for a symbol.
DPrintf("SetDehParams: Paramindex is %d, default is %d.\n",
state->ParameterIndex-1, sym->defaultparameterindex);
if (state->ParameterIndex-1 == sym->defaultparameterindex)
{
int a = PrepareStateParameters(state, MBFCodePointers[codepointer].params+1,
FState::StaticFindStateOwner(state)) -1;
int b = sym->defaultparameterindex;
// StateParams.Copy(a, b, MBFParams[codepointer]);
// Meh, function doesn't work. For some reason it resets the paramindex to the default value.
// For instance, a dehacked Commander Keen calling A_Explode would result in a crash as
// ACTION_PARAM_INT(damage, 0) would properly evaluate at paramindex 1377, but then
// ACTION_PARAM_INT(distance, 1) would improperly evaluate at paramindex 148! Now I'm not sure
// whether it's a genuine problem or working as intended and merely not appropriate for the
// task at hand here. So rather than modify it, I use a simple for loop of Set()s and Get()s,
// with a small modification to Set() that I know will have no repercussion anywhere else.
for (int i = 0; i<MBFCodePointers[codepointer].params; i++)
{
StateParams.Set(a+i, StateParams.Get(b+i), true);
}
DPrintf("New paramindex is %d.\n", state->ParameterIndex-1);
}
int ParamIndex = state->ParameterIndex - 1;
switch (codepointer)
{
case MBF_Mushroom:
StateParams.Set(ParamIndex+2, new FxConstant(1, *pos)); // Flag
// NOTE: Do not convert to float here because it will lose precision. It must be double.
if (value1) StateParams.Set(ParamIndex+3, new FxConstant(value1/65536., *pos)); // vrange
if (value2) StateParams.Set(ParamIndex+4, new FxConstant(value2/65536., *pos)); // hrange
break;
case MBF_Spawn:
if (InfoNames[value1-1] == NULL)
{
I_Error("No class found for dehackednum %d!\n", value1+1);
return;
}
StateParams.Set(ParamIndex+0, new FxConstant(InfoNames[value1-1], *pos)); // type
StateParams.Set(ParamIndex+2, new FxConstant(value2, *pos)); // height
break;
case MBF_Turn:
// Intentional fall through. I tried something more complicated by creating an
// FxExpression that corresponded to "variable angle + angle" so as to use A_SetAngle
// as well, but it became an overcomplicated mess that didn't even work as I had to
// create a compile context as well and couldn't get it right.
case MBF_Face:
StateParams.Set(ParamIndex+0, new FxConstant(value1, *pos)); // angle
break;
case MBF_Scratch: // misc1 = damage, misc 2 = sound
StateParams.Set(ParamIndex+0, new FxConstant(value1, *pos)); // damage
if (value2) StateParams.Set(ParamIndex+1, new FxConstant(SoundMap[value2-1], *pos)); // hit sound
break;
case MBF_PlaySound:
StateParams.Set(ParamIndex+0, new FxConstant(SoundMap[value1-1], *pos)); // soundid
StateParams.Set(ParamIndex+4, new FxConstant((value2?ATTN_NONE:ATTN_NORM), *pos)); // attenuation
break;
case MBF_RandomJump:
StateParams.Set(ParamIndex+0, new FxConstant(2, *pos)); // count
StateParams.Set(ParamIndex+1, new FxConstant(value2, *pos)); // maxchance
StateParams.Set(ParamIndex+2, new FxConstant(FindState(value1), *pos)); // jumpto
break;
case MBF_LineEffect:
// This is the second MBF codepointer that couldn't be translated easily.
// Calling P_TranslateLineDef() here was a simple matter, as was adding an
// extra parameter to A_CallSpecial so as to replicate the LINEDONE stuff,
// but unfortunately DEHACKED lumps are processed before the map translation
// arrays are initialized so this didn't work.
StateParams.Set(ParamIndex+0, new FxConstant(value1, *pos)); // special
StateParams.Set(ParamIndex+1, new FxConstant(value2, *pos)); // tag
break;
case SMMU_NailBomb:
// That one does not actually have MBF-style parameters. But since
// we're aliasing it to an extension of A_Explode...
StateParams.Set(ParamIndex+5, new FxConstant(30, *pos)); // nails
StateParams.Set(ParamIndex+6, new FxConstant(10, *pos)); // naildamage
break;
default:
// This simply should not happen.
Printf("Unmanaged dehacked codepointer alias num %i\n", codepointer);
}
}
static int PatchThing (int thingy)
{
enum
{
// Boom flags
MF_TRANSLATION = 0x0c000000, // if 0x4 0x8 or 0xc, use a translation
MF_TRANSSHIFT = 26, // table for player colormaps
// A couple of Boom flags that don't exist in ZDoom
MF_SLIDE = 0x00002000, // Player: keep info about sliding along walls.
MF_TRANSLUCENT = 0x80000000, // Translucent sprite?
// MBF flags: TOUCHY is remapped to flags6, FRIEND is turned into FRIENDLY,
// and finally BOUNCES is replaced by bouncetypes with the BOUNCES_MBF bit.
MF_TOUCHY = 0x10000000, // killough 11/98: dies when solids touch it
MF_BOUNCES = 0x20000000, // killough 7/11/98: for beta BFG fireballs
MF_FRIEND = 0x40000000, // killough 7/18/98: friendly monsters
};
int result;
@ -793,20 +945,30 @@ static int PatchThing (int thingy)
{
DWORD value[4] = { 0, 0, 0 };
bool vchanged[4] = { false, false, false };
// ZDoom used to block the upper range of bits to force use of mnemonics for extra flags.
// MBF also defined extra flags in the same range, but without forcing mnemonics. For MBF
// compatibility, the upper bits are freed, but we have conflicts between the ZDoom bits
// and the MBF bits. The only such flag exposed to DEHSUPP, though, is STEALTH -- the others
// are not available through mnemonics, and aren't available either through their bit value.
// So if we find the STEALTH keyword, it's a ZDoom mod, otherwise assume assume FRIEND.
bool zdoomflags = false;
char *strval;
for (strval = Line2; (strval = strtok (strval, ",+| \t\f\r")); strval = NULL)
{
if (IsNum (strval))
{
// Force the top 4 bits to 0 so that the user is forced
// to use the mnemonics to change them. And MF_SLIDE doesn't
// exist anymore, so 0 that too.
value[0] |= strtoul(strval, NULL, 10) & 0x0fffdfff;
// I have no idea why everyone insists on using strtol here even though it fails
// dismally if a value is parsed where the highest bit it set. Do people really
// use negative values here? Let's better be safe and check both.
if (strchr(strval, '-')) value[0] |= (unsigned long)strtol(strval, NULL, 10);
else value[0] |= (unsigned long)strtoul(strval, NULL, 10);
vchanged[0] = true;
}
else
{
// STEALTH FRIEND HACK!
if (!stricmp(strval, "STEALTH")) zdoomflags = true;
unsigned i;
for(i = 0; i < BitNames.Size(); i++)
{
@ -825,12 +987,104 @@ static int PatchThing (int thingy)
}
if (vchanged[0])
{
if (value[0] & MF_SLIDE)
{
// SLIDE (which occupies in Doom what is the MF_INCHASE slot in ZDoom)
value[0] &= ~MF_SLIDE; // clean the slot
// Nothing else to do, this flag is never actually used.
}
if (value[0] & MF_TRANSLATION)
{
info->Translation = TRANSLATION (TRANSLATION_Standard,
((value[0] & MF_TRANSLATION) >> (MF_TRANSSHIFT))-1);
value[0] &= ~MF_TRANSLATION;
}
if (value[0] & MF_TOUCHY)
{
// TOUCHY (which occupies in MBF what is the MF_UNMORPHED slot in ZDoom)
value[0] &= ~MF_TOUCHY; // clean the slot
info->flags6 |= MF6_TOUCHY; // remap the flag
}
if (value[0] & MF_BOUNCES)
{
// BOUNCES (which occupies in MBF the MF_NOLIFTDROP slot)
// This flag is especially convoluted as what it does depend on what
// other flags the actor also has, and whether it's "sentient" or not.
value[0] &= ~MF_BOUNCES; // clean the slot
// MBF considers that things that bounce can be damaged, even if not shootable.
info->flags6 |= MF6_VULNERABLE;
// MBF also considers that bouncers pass through blocking lines as projectiles.
info->flags3 |= MF3_NOBLOCKMONST;
// MBF also considers that bouncers that explode are grenades, and MBF grenades
// are supposed to hurt everything, except cyberdemons if they're fired by cybies.
// Let's translate that in a more generic way as grenades which hurt everything
// except the class of their shooter. Yes, it does diverge a bit from MBF, as for
// example a dehacked arachnotron that shoots grenade would kill itself quickly
// in MBF and will not here. But class-specific checks are cumbersome and limiting.
info->flags4 |= (MF4_FORCERADIUSDMG | MF4_DONTHARMCLASS);
// MBF bouncing missiles rebound on floors and ceiling, but not on walls.
// This is different from BOUNCE_Heretic behavior as in Heretic the missiles
// die when they bounce, while in MBF they will continue to bounce until they
// collide with a wall or a solid actor.
if (value[0] & MF_MISSILE) info->BounceFlags = BOUNCE_Classic;
// MBF bouncing actors that do not have the missile flag will also rebound on
// walls, and this does correspond roughly to the ZDoom bounce style.
else info->BounceFlags = BOUNCE_Grenade;
// MBF grenades are dehacked rockets that gain the BOUNCES flag but
// lose the MISSILE flag, so they can be identified here easily.
if (!(value[0] & MF_MISSILE) && info->effects & FX_ROCKET)
{
info->effects &= ~FX_ROCKET; // replace rocket trail
info->effects |= FX_GRENADE; // by grenade trail
}
// MBF bounce factors depend on flag combos:
enum
{
MBF_BOUNCE_NOGRAVITY = FRACUNIT, // With NOGRAVITY: full momentum
MBF_BOUNCE_FLOATDROPOFF = (FRACUNIT * 85) / 100,// With FLOAT and DROPOFF: 85%
MBF_BOUNCE_FLOAT = (FRACUNIT * 70) / 100,// With FLOAT alone: 70%
MBF_BOUNCE_DEFAULT = (FRACUNIT * 45) / 100,// Without the above flags: 45%
MBF_BOUNCE_WALL = (FRACUNIT * 50) / 100,// Bouncing off walls: 50%
};
info->bouncefactor = ((value[0] & MF_NOGRAVITY) ? MBF_BOUNCE_NOGRAVITY
: (value[0] & MF_FLOAT) ? (value[0] & MF_DROPOFF) ? MBF_BOUNCE_FLOATDROPOFF
: MBF_BOUNCE_FLOAT : MBF_BOUNCE_DEFAULT);
info->wallbouncefactor = ((value[0] & MF_NOGRAVITY) ? MBF_BOUNCE_NOGRAVITY : MBF_BOUNCE_WALL);
// MBF sentient actors with BOUNCE and FLOAT are able to "jump" by floating up.
if (info->IsSentient())
{
if (value[0] & MF_FLOAT) info->flags6 |= MF6_CANJUMP;
}
// Non sentient actors can be damaged but they shouldn't bleed.
else
{
value[0] |= MF_NOBLOOD;
}
}
if (zdoomflags && (value [0] & MF_STEALTH))
{
// STEALTH FRIEND HACK!
}
else if (value[0] & MF_FRIEND)
{
// FRIEND (which occupies in MBF the MF_STEALTH slot)
value[0] &= ~MF_FRIEND; // clean the slot
value[0] |= MF_FRIENDLY; // remap the flag to its ZDoom equivalent
// MBF friends are not blocked by monster blocking lines:
info->flags3 |= MF3_NOBLOCKMONST;
}
if (value[0] & MF_TRANSLUCENT)
{
// TRANSLUCENT (which occupies in Boom the MF_ICECORPSE slot)
value[0] &= ~MF_TRANSLUCENT; // clean the slot
vchanged[2] = true; value[2] |= 2; // let the TRANSLUCxx code below handle it
}
info->flags = value[0];
}
if (vchanged[1])
@ -1044,25 +1298,11 @@ static int PatchFrame (int frameNum)
}
else if (keylen == 9 && stricmp (Line1, "Unknown 1") == 0)
{
if (val < -128 || val > 127)
{
Printf ("Frame %d: misc1 is out of range\n", frameNum);
}
else
{
misc1 = val;
}
misc1 = val;
}
else if (keylen == 9 && stricmp (Line1, "Unknown 2") == 0)
{
if (val < 0 || val > 255)
{
Printf ("Frame %d: misc2 is out of range\n", frameNum);
}
else
{
info->Misc2 = val;
}
info->Misc2 = val;
}
else if (keylen == 13 && stricmp (Line1, "Sprite number") == 0)
{
@ -1105,11 +1345,7 @@ static int PatchFrame (int frameNum)
if (info != &dummy)
{
if (misc1 != 0 && tics > 254)
{
Printf ("Frame %d: Misc1 must be 0 if tics >254\n", frameNum);
misc1 = 0;
}
info->DefineFlags |= SDF_DEHACKED; // Signals the state has been modified by dehacked
if ((unsigned)(frame & 0x7fff) > 63)
{
Printf ("Frame %d: Subnumber must be in range [0,63]\n", frameNum);
@ -1357,15 +1593,30 @@ static int PatchWeapon (int weapNum)
return result;
}
static void SetPointer(FState *state, PSymbol *sym)
static void SetPointer(FState *state, PSymbol *sym, int frame = 0)
{
if (sym==NULL || sym->SymbolType != SYM_ActionFunction)
{
state->SetAction(NULL);
return;
}
else
{
FString symname = sym->SymbolName;
state->SetAction(static_cast<PSymbolActionFunction*>(sym));
// Note: CompareNoCase() calls stricmp() and therefore returns 0 when they're the same.
for (unsigned int i = 0; i < MBFCodePointers.Size(); i++)
{
if (!symname.CompareNoCase(MBFCodePointers[i].name))
{
MBFParamState * newstate = new MBFParamState;
newstate->state = state;
newstate->pointer = i;
MBFParamStates.Push(newstate);
break; // No need to cycle through the rest of the list.
}
}
}
}
@ -1414,8 +1665,10 @@ static int PatchPointer (int ptrNum)
SetPointer(state, NULL);
else
{
SetPointer(state, Actions[index]);
SetPointer(state, Actions[index], CodePConv[ptrNum]);
}
DPrintf("%s has a hacked state for pointer num %i with index %i\nLine1=%s, Line2=%s\n",
state->StaticFindStateOwner(state)->TypeName.GetChars(), ptrNum, index, Line1, Line2);
}
else
{
@ -1720,6 +1973,16 @@ static int PatchCodePtrs (int dummy)
else
symname.Format("A_%s", Line2);
// Let's consider as aliases some redundant MBF pointer
for (unsigned int i = 0; i < MBFCodePointers.Size(); i++)
{
if (!symname.CompareNoCase(MBFCodePointers[i].alias))
{
symname = MBFCodePointers[i].name;
Printf("%s --> %s\n", MBFCodePointers[i].alias, MBFCodePointers[i].name);
}
}
// This skips the action table and goes directly to the internal symbol table
// DEH compatible functions are easy to recognize.
PSymbol *sym = RUNTIME_CLASS(AInventory)->Symbols.FindSymbol(symname, true);
@ -1736,12 +1999,7 @@ static int PatchCodePtrs (int dummy)
sym = NULL;
}
}
SetPointer(state, sym);
// Hack to trigger compatible mode for A_Mushroom when called from Dehacked mods
if (symname.CompareNoCase("A_Mushroom"))
{
state->Misc1 = 1;
}
SetPointer(state, sym, frame);
}
}
}
@ -2233,6 +2491,15 @@ static void UnloadDehSupp ()
{
if (--DehUseCount <= 0)
{
// Handle MBF params here, before the required arrays are cleared
for (unsigned int i=0; i < MBFParamStates.Size(); i++)
{
SetDehParams(MBFParamStates[i]->state, MBFParamStates[i]->pointer);
}
MBFParamStates.Clear();
MBFParamStates.ShrinkToFit();
MBFCodePointers.Clear();
MBFCodePointers.ShrinkToFit();
// StateMap is not freed here, because if you load a second
// dehacked patch through some means other than including it
// in the first patch, it won't see the state information
@ -2563,6 +2830,27 @@ static bool LoadDehSupp ()
sc.MustGetStringName(",");
}
}
else if (sc.Compare("Aliases"))
{
sc.MustGetStringName("{");
while (!sc.CheckString("}"))
{
CodePointerAlias temp;
sc.MustGetString();
strncpy(temp.alias, sc.String, 19);
temp.alias[19]=0;
sc.MustGetStringName(",");
sc.MustGetString();
strncpy(temp.name, sc.String, 19);
temp.name[19]=0;
sc.MustGetStringName(",");
sc.MustGetNumber();
temp.params = sc.Number;
MBFCodePointers.Push(temp);
if (sc.CheckString("}")) break;
sc.MustGetStringName(",");
}
}
else
{
sc.ScriptError("Unknown section '%s'", sc.String);

View file

@ -499,16 +499,22 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
case 2: // same as 1 but stricter (NO_PASSMOBJ and INVISIBILITY are also set)
v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|
COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_NO_PASSMOBJ|COMPATF_LIMITPAIN|
COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF;
COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF|COMPATF_CORPSEGIBS;
break;
case 3:
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MUSHROOM;
case 3: // Boom compat mode
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL;
break;
case 4:
case 4: // Old ZDoom compat mode
v = COMPATF_SOUNDTARGET;
break;
case 5: // MBF compat mode
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MUSHROOM|
COMPATF_MBFMONSTERMOVE|COMPATF_NOBLOCKFRIENDS;
break;
}
compatflags = v;
}
@ -537,6 +543,9 @@ CVAR (Flag, compat_crossdropoff,compatflags, COMPATF_CROSSDROPOFF);
CVAR (Flag, compat_anybossdeath,compatflags, COMPATF_ANYBOSSDEATH);
CVAR (Flag, compat_minotaur, compatflags, COMPATF_MINOTAUR);
CVAR (Flag, compat_mushroom, compatflags, COMPATF_MUSHROOM);
CVAR (Flag, compat_mbfmonstermove,compatflags, COMPATF_MBFMONSTERMOVE);
CVAR (Flag, compat_corpsegibs, compatflags, COMPATF_CORPSEGIBS);
CVAR (Flag, compat_noblockfriends,compatflags,COMPATF_NOBLOCKFRIENDS);
//==========================================================================
//

View file

@ -2094,6 +2094,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_SUMMON:
case DEM_SUMMONFRIEND:
case DEM_SUMMONFOE:
case DEM_SUMMONMBF:
case DEM_SUMMON2:
case DEM_SUMMONFRIEND2:
case DEM_SUMMONFOE2:
@ -2132,7 +2133,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
source->z + 8 * FRACUNIT, ALLOW_REPLACE);
if (spawned != NULL)
{
if (type == DEM_SUMMONFRIEND || type == DEM_SUMMONFRIEND2)
if (type == DEM_SUMMONFRIEND || type == DEM_SUMMONFRIEND2 || type == DEM_SUMMONMBF)
{
if (spawned->CountsAsKill())
{
@ -2142,6 +2143,8 @@ void Net_DoCommand (int type, BYTE **stream, int player)
spawned->flags |= MF_FRIENDLY;
spawned->LastHeard = players[player].mo;
spawned->health = spawned->SpawnHealth();
if (type == DEM_SUMMONMBF)
spawned->flags3 |= MF3_NOBLOCKMONST;
}
else if (type == DEM_SUMMONFOE || type == DEM_SUMMONFOE2)
{
@ -2440,6 +2443,7 @@ void Net_SkipCommand (int type, BYTE **stream)
case DEM_SUMMON:
case DEM_SUMMONFRIEND:
case DEM_SUMMONFOE:
case DEM_SUMMONMBF:
case DEM_SPRAY:
case DEM_MORPHEX:
case DEM_KILLCLASSCHEAT:

View file

@ -839,5 +839,6 @@ CCMD (playerinfo)
Printf ("PlayerClass: %s (%d)\n",
ui->PlayerClass == -1 ? "Random" : PlayerClasses[ui->PlayerClass].Type->Meta.GetMetaString (APMETA_DisplayName),
ui->PlayerClass);
PrintMiscActorInfo(players[i].mo);
}
}

View file

@ -272,7 +272,7 @@ public:
// killough 10/98: used for realistic bobbing (i.e. not simply overall speed)
// mo->velx and mo->vely represent true velocity experienced by player.
// This only represents the thrust that the player applies himself.
// This avoids anomolies with such things as Boom ice and conveyors.
// This avoids anomalies with such things as Boom ice and conveyors.
fixed_t velx, vely; // killough 10/98
bool centering;

View file

@ -154,6 +154,7 @@ enum EDemoCommand
DEM_ADDSLOTDEFAULT, // 55
DEM_ADDSLOT, // 56
DEM_SETSLOT, // 57
DEM_SUMMONMBF,
};
// The following are implemented by cht_DoCheat in m_cheat.cpp

View file

@ -320,7 +320,10 @@ enum
COMPATF_CROSSDROPOFF = 1 << 20, // monsters can't be pushed over dropoffs
COMPATF_ANYBOSSDEATH = 1 << 21, // [GZ] Any monster which calls BOSSDEATH counts for level specials
COMPATF_MINOTAUR = 1 << 22, // Minotaur's floor flame is exploded immediately when feet are clipped
COMPATF_MUSHROOM = 1 << 23, // Force original velocity calculations for A_Mushroom in Dehacked oods.
COMPATF_MUSHROOM = 1 << 23, // Force original velocity calculations for A_Mushroom in Dehacked mods.
COMPATF_MBFMONSTERMOVE = 1 << 24, // Monsters are affected by friction and pushers/pullers.
COMPATF_CORPSEGIBS = 1 << 25, // Crushed monsters are turned into gibs, rather than replaced by gibs.
COMPATF_NOBLOCKFRIENDS = 1 << 26, // Friendly monsters aren't blocked by monster-blocking lines.
};
// Emulate old bugs for select maps. These are not exposed by a cvar
@ -330,6 +333,7 @@ enum
BCOMPATF_SETSLOPEOVERFLOW = 1 << 0, // SetSlope things can overflow
BCOMPATF_RESETPLAYERSPEED = 1 << 1, // Set player speed to 1.0 when changing maps
BCOMPATF_SPECHITOVERFLOW = 1 << 2, // Emulate spechit overflow (e.g. Strain MAP07)
BCOMPATF_VILEGHOSTS = 1 << 3, // Monsters' radius and height aren't restored properly when resurrected.
};
// phares 3/20/98:

View file

@ -21,6 +21,7 @@ static FRandom pr_fireshotgun2 ("FireSG2");
static FRandom pr_fireplasma ("FirePlasma");
static FRandom pr_firerail ("FireRail");
static FRandom pr_bfgspray ("BFGSpray");
static FRandom pr_oldbfg ("OldBFG");
//
// A_Punch
@ -553,3 +554,48 @@ DEFINE_ACTION_FUNCTION(AActor, A_BFGsound)
S_Sound (self, CHAN_WEAPON, "weapons/bfgf", 1, ATTN_NORM);
}
//
// A_FireOldBFG
//
// This function emulates Doom's Pre-Beta BFG
// By Lee Killough 6/6/98, 7/11/98, 7/19/98, 8/20/98
//
// This code may not be used in other mods without appropriate credit given.
// Code leeches will be telefragged.
DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG)
{
const PClass * plasma[] = {PClass::FindClass("PlasmaBall1"), PClass::FindClass("PlasmaBall2")};
AActor * mo = NULL;
player_t *player;
if (NULL == (player = self->player))
{
return;
}
AWeapon *weapon = self->player->ReadyWeapon;
if (weapon != NULL)
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return;
}
self->player->extralight = 2;
// Save values temporarily
angle_t SavedPlayerAngle = self->angle;
fixed_t SavedPlayerPitch = self->pitch;
bool doesautoaim = !(self->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM);
self->player->ReadyWeapon->WeaponFlags |= WIF_NOAUTOAIM; // No autoaiming that gun
for (int i = 0; i < 2; i++) // Spawn two plasma balls in sequence
{
self->angle += ((pr_oldbfg()&127) - 64) * (ANG90/768);
self->pitch += ((pr_oldbfg()&127) - 64) * (ANG90/640);
mo = P_SpawnPlayerMissile (self, plasma[i]);
// Restore saved values
self->angle = SavedPlayerAngle;
self->pitch = SavedPlayerPitch;
}
if (doesautoaim) self->player->ReadyWeapon->WeaponFlags &= ~WIF_NOAUTOAIM; // Restore autoaim setting
}

View file

@ -124,12 +124,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom)
{
int i, j;
ACTION_PARAM_START(3);
ACTION_PARAM_START(5);
ACTION_PARAM_CLASS(spawntype, 0);
ACTION_PARAM_INT(n, 1);
ACTION_PARAM_INT(flags, 2);
ACTION_PARAM_FIXED(vrange, 3);
ACTION_PARAM_FIXED(hrange, 4);
if (n == 0) n = self->GetMissileDamage (0, 1);
if (n == 0) n = self->Damage; // GetMissileDamage (0, 1);
if (spawntype == NULL) spawntype = PClass::FindClass("FatShot");
P_RadiusAttack (self, self->target, 128, 128, self->DamageType, true);
@ -141,15 +143,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom)
// Now launch mushroom cloud
AActor *target = Spawn("Mapspot", 0, 0, 0, NO_REPLACE); // We need something to aim at.
target->height = self->height;
for (i = -n; i <= n; i += 8)
for (i = -n; i <= n; i += 8)
{
for (j = -n; j <= n; j += 8)
for (j = -n; j <= n; j += 8)
{
AActor *mo;
target->x = self->x + (i << FRACBITS); // Aim in many directions from source
target->x = self->x + (i << FRACBITS); // Aim in many directions from source
target->y = self->y + (j << FRACBITS);
target->z = self->z + (P_AproxDistance(i,j) << (FRACBITS+2)); // Aim up fairly high
if (flags == 0 && (self->state->Misc1 == 0 || !(i_compatflags & COMPATF_MUSHROOM)))
target->z = self->z + (P_AproxDistance(i,j) * vrange); // Aim up fairly high
if (flags == 0 && (!(self->state->DefineFlags & SDF_DEHACKED) || !(i_compatflags & COMPATF_MUSHROOM)))
{
mo = P_SpawnMissile (self, target, spawntype); // Launch fireball
}
@ -158,10 +160,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom)
mo = P_OldSpawnMissile (self, target, spawntype); // Launch fireball
}
if (mo != NULL)
{
mo->velx >>= 1;
mo->vely >>= 1; // Slow it down a bit
mo->velz >>= 1;
{ // Slow it down a bit
mo->velx = FixedMul(mo->velx, hrange);
mo->vely = FixedMul(mo->vely, hrange);
mo->velz = FixedMul(mo->velz, hrange);
mo->flags &= ~MF_NOGRAVITY; // Make debris fall under gravity
}
}

View file

@ -13,6 +13,7 @@
*/
FRandom pr_lost ("LostMissileRange");
FRandom pr_oldsoul ("BetaLostSoul");
//
// SkullAttack
@ -54,6 +55,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullAttack)
A_SkullAttack(self, n);
}
DEFINE_ACTION_FUNCTION(AActor, A_BetaSkullAttack)
{
int damage;
if (!self || !self->target || self->target->GetSpecies() == self->GetSpecies())
return;
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
A_FaceTarget(self);
damage = (pr_oldsoul()%8+1)*self->Damage;
P_DamageMobj(self->target, self, self, damage, NAME_None);
}
//==========================================================================
//
// CVAR transsouls

View file

@ -110,6 +110,24 @@ CVAR (Bool, chasedemo, false, 0);
CVAR (Bool, storesavepic, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, longsavemessages, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (String, save_dir, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
EXTERN_CVAR (Float, con_midtime);
//==========================================================================
//
// CVAR displaynametags
//
// Selects whether to display name tags or not when changing weapons
//
//==========================================================================
CUSTOM_CVAR (Bool, displaynametags, 0, CVAR_ARCHIVE)
{
if (self != 0 && self != 1)
{
self = 0;
}
}
gameaction_t gameaction;
gamestate_t gamestate = GS_STARTUP;
@ -335,6 +353,10 @@ CCMD (invnext)
who->InvSel = who->Inventory;
}
}
if (displaynametags && StatusBar && SmallFont
&& gamestate == GS_LEVEL && level.time > con_midtime && who->InvSel)
StatusBar->AttachMessage (new DHUDMessage (SmallFont, who->InvSel->GetTag(),
2.5f, 0.375f, 0, 0, CR_YELLOW, con_midtime), MAKE_ID('S','I','N','V'));
}
who->player->inventorytics = 5*TICRATE;
}
@ -362,6 +384,10 @@ CCMD (invprev)
}
who->InvSel = item;
}
if (displaynametags && StatusBar && SmallFont
&& gamestate == GS_LEVEL && level.time > con_midtime && who->InvSel)
StatusBar->AttachMessage (new DHUDMessage (SmallFont, who->InvSel->GetTag(),
2.5f, 0.375f, 0, 0, CR_YELLOW, con_midtime), MAKE_ID('S','I','N','V'));
}
who->player->inventorytics = 5*TICRATE;
}
@ -385,9 +411,7 @@ CCMD(invquery)
AInventory *inv = players[consoleplayer].mo->InvSel;
if (inv != NULL)
{
const char *description = inv->GetClass()->Meta.GetMetaString(AMETA_StrifeName);
if (description == NULL) description = inv->GetClass()->TypeName;
Printf(PRINT_HIGH, "%s (%dx)\n", description, inv->Amount);
Printf(PRINT_HIGH, "%s (%dx)\n", inv->GetTag(), inv->Amount);
}
}

View file

@ -59,8 +59,9 @@ bool AArtiBlastRadius::Use (bool pickup)
else if (!(mo->flags3 & MF3_ISMONSTER) &&
!(mo->player) &&
!(mo->flags & MF_MISSILE) &&
!(mo->flags3 & MF3_CANBLAST))
{ // Must be monster, player, or missile
!(mo->flags3 & MF3_CANBLAST) &&
!(mo->flags6 & MF6_TOUCHY))
{ // Must be monster, player, missile, or touchy
continue;
}
if (mo->flags2 & MF2_DORMANT)
@ -162,5 +163,10 @@ void AArtiBlastRadius::BlastActor (AActor *victim, fixed_t strength)
{
victim->flags2 |= MF2_BLASTED;
}
if (victim->flags6 & MF6_TOUCHY)
{ // Touchy objects die when blasted
victim->flags6 &= ~MF6_ARMED; // Disarm
P_DamageMobj(victim, Owner, Owner, victim->health, NAME_Melee, DMG_FORCED);
}
}
}

View file

@ -947,6 +947,12 @@ DEFINE_MAP_OPTION(secretnext, true)
parse.ParseNextMap(info->secretmap);
}
DEFINE_MAP_OPTION(secret, true) // Just an alias for secretnext, for Vavoom compatibility
{
parse.ParseAssign();
parse.ParseNextMap(info->secretmap);
}
DEFINE_MAP_OPTION(cluster, true)
{
parse.ParseAssign();
@ -998,6 +1004,14 @@ DEFINE_MAP_OPTION(sky2, true)
}
}
// Vavoom compatibility
DEFINE_MAP_OPTION(skybox, true)
{
parse.ParseAssign();
parse.ParseLumpOrTextureName(info->skypic1);
info->skyspeed1 = 0;
}
DEFINE_MAP_OPTION(fade, true)
{
parse.ParseAssign();
@ -1342,6 +1356,9 @@ MapFlagHandlers[] =
{ "compat_anybossdeath", MITYPE_COMPATFLAG, COMPATF_ANYBOSSDEATH},
{ "compat_minotaur", MITYPE_COMPATFLAG, COMPATF_MINOTAUR},
{ "compat_mushroom", MITYPE_COMPATFLAG, COMPATF_MUSHROOM},
{ "compat_mbfmonstermove", MITYPE_COMPATFLAG, COMPATF_MBFMONSTERMOVE},
{ "compat_corpsegibs", MITYPE_COMPATFLAG, COMPATF_CORPSEGIBS},
{ "compat_noblockfriends", MITYPE_COMPATFLAG, COMPATF_NOBLOCKFRIENDS},
{ "cd_start_track", MITYPE_EATNEXT, 0, 0 },
{ "cd_end1_track", MITYPE_EATNEXT, 0, 0 },
{ "cd_end2_track", MITYPE_EATNEXT, 0, 0 },

View file

@ -91,10 +91,7 @@ void APowerupGiver::Serialize (FArchive &arc)
Super::Serialize (arc);
arc << PowerupType;
arc << EffectTics << BlendColor << Mode;
if (SaveVersion >= 1693)
{
arc << Strength;
}
arc << Strength;
}
// Powerup -------------------------------------------------------------------
@ -128,10 +125,7 @@ void APowerup::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << EffectTics << BlendColor << Mode;
if (SaveVersion >= 1693)
{
arc << Strength;
}
arc << Strength;
}
//===========================================================================
@ -553,7 +547,7 @@ void APowerStrength::Tick ()
PalEntry APowerStrength::GetBlend ()
{
// slowly fade the berzerk out
// slowly fade the berserk out
int cnt = 12 - (EffectTics >> 6);
if (cnt > 0)
@ -570,35 +564,10 @@ PalEntry APowerStrength::GetBlend ()
IMPLEMENT_CLASS (APowerInvisibility)
IMPLEMENT_CLASS (APowerShadow)
//===========================================================================
//
// APowerInvisibility :: CommonInit
//
// stuff that's done for all subclasses
//
//===========================================================================
void APowerInvisibility::CommonInit()
{
if (Owner != NULL)
{
Owner->flags |= MF_SHADOW;
fixed_t ts = MIN(Strength * (special1 + 1), FRACUNIT);
Owner->alpha = clamp<fixed_t>((OPAQUE - ts), 0, OPAQUE);
Owner->RenderStyle = (Mode == NAME_Fuzzy ? STYLE_OptFuzzy : STYLE_Translucent);
// CommonInit() is called every tic by DoEffect, so the flag trick must happen only once!
if (special2 == 0)
{
// transfer seeker missile blocking (but only if the owner does not already have this flag
if (!(Owner->flags5 & MF5_CANTSEEK) && (flags5 & MF5_CANTSEEK)) Owner->flags5 |= MF5_CANTSEEK;
else flags5 &= ~MF5_CANTSEEK;
// transfer ghost flag likewise
if (!(Owner->flags3 & MF3_GHOST) && (flags3 & MF3_GHOST)) Owner->flags3 |= MF3_GHOST;
else flags3 &= ~MF3_GHOST;
special2 = 1;
}
}
}
// Invisibility flag combos
#define INVISIBILITY_FLAGS1 (MF_SHADOW | MF_STEALTH)
#define INVISIBILITY_FLAGS3 (MF3_GHOST)
#define INVISIBILITY_FLAGS5 (MF5_CANTSEEK)
//===========================================================================
//
@ -608,7 +577,39 @@ void APowerInvisibility::CommonInit()
void APowerInvisibility::InitEffect ()
{
CommonInit();
// This used to call CommonInit(), which used to contain all the code that's repeated every
// tic, plus the following code that needs to happen once and only once.
// The CommonInit() code has been moved to DoEffect(), so this now ends with a call to DoEffect(),
// and DoEffect() no longer needs to call InitEffect(). CommonInit() has been removed for being redundant.
if (Owner != NULL)
{
flags &= ~(Owner->flags & INVISIBILITY_FLAGS1);
Owner->flags |= flags & INVISIBILITY_FLAGS1;
flags3 &= ~(Owner->flags3 & INVISIBILITY_FLAGS3);
Owner->flags3 |= flags3 & INVISIBILITY_FLAGS3;
flags5 &= ~(Owner->flags5 & INVISIBILITY_FLAGS5);
Owner->flags5 |= flags5 & INVISIBILITY_FLAGS5;
// Finds out what's the normal alpha and render style for the owner.
// First assume it's what it currently is.
//OwnersNormalStyle = Owner->RenderStyle;
//OwnersNormalAlpha = Owner->alpha;
// Then look if there aren't active invis powerups and look what they're saying.
/*AInventory *item = Owner->Inventory;
while (item != NULL)
{
if (item->IsKindOf(RUNTIME_CLASS(APowerInvisibility)) && item != this)
{
OwnersNormalStyle = static_cast<APowerInvisibility*>(item)->OwnersNormalStyle;
OwnersNormalAlpha = static_cast<APowerInvisibility*>(item)->OwnersNormalAlpha;
item = NULL; // No need to look further
}
else item = item->Inventory;
}
Printf("Owner's normal style is found to be %i, normal alpha is found to be %i.\n",
OwnersNormalStyle, OwnersNormalAlpha>>FRACBITS);*/
DoEffect();
}
}
//===========================================================================
@ -621,7 +622,31 @@ void APowerInvisibility::DoEffect ()
Super::DoEffect();
// Due to potential interference with other PowerInvisibility items
// the effect has to be refreshed each tic.
InitEffect();
fixed_t ts = Strength * (special1 + 1); if (ts > FRACUNIT) ts = FRACUNIT;
Owner->alpha = clamp<fixed_t>((/*OwnersNormalAlpha*/OPAQUE - ts), 0, OPAQUE);
switch (Mode)
{
case (NAME_Fuzzy):
Owner->RenderStyle = STYLE_OptFuzzy;
break;
case (NAME_Opaque):
Owner->RenderStyle = STYLE_Normal;
break;
case (NAME_Additive):
Owner->RenderStyle = STYLE_Add;
break;
case (NAME_Stencil):
Owner->RenderStyle = STYLE_Stencil;
break;
case (NAME_None):
case (NAME_Translucent):
Owner->RenderStyle = STYLE_Translucent;
break;
default: // Something's wrong
Owner->RenderStyle = STYLE_Normal;
Owner->alpha = OPAQUE;
break;
}
}
//===========================================================================
@ -634,11 +659,12 @@ void APowerInvisibility::EndEffect ()
{
if (Owner != NULL)
{
if (flags5 & MF5_CANTSEEK) Owner->flags5 &= ~MF5_CANTSEEK;
if (flags3 & MF3_GHOST) Owner->flags3 &= ~MF3_GHOST;
Owner->flags &= ~MF_SHADOW;
Owner->RenderStyle = STYLE_Normal;
Owner->alpha = OPAQUE;
Owner->flags &= ~(flags & INVISIBILITY_FLAGS1);
Owner->flags3 &= ~(flags3 & INVISIBILITY_FLAGS3);
Owner->flags5 &= ~(flags5 & INVISIBILITY_FLAGS5);
Owner->RenderStyle = STYLE_Normal;//OwnersNormalStyle;
Owner->alpha = OPAQUE;//OwnersNormalAlpha;
// Check whether there are other invisibility items and refresh their effect.
// If this isn't done there will be one incorrectly drawn frame when this
@ -648,7 +674,7 @@ void APowerInvisibility::EndEffect ()
{
if (item->IsKindOf(RUNTIME_CLASS(APowerInvisibility)) && item != this)
{
static_cast<APowerInvisibility*>(item)->InitEffect();
static_cast<APowerInvisibility*>(item)->DoEffect();
}
item = item->Inventory;
}
@ -667,16 +693,36 @@ int APowerInvisibility::AlterWeaponSprite (vissprite_t *vis)
// Blink if the powerup is wearing off
if (changed == 0 && EffectTics < 4*32 && !(EffectTics & 8))
{
vis->RenderStyle = STYLE_Normal;
vis->alpha = OPAQUE;
vis->RenderStyle = STYLE_Normal;//OwnersNormalStyle;
vis->alpha = OPAQUE;//OwnersNormalAlpha;
return 1;
}
else if (changed == 1)
{
// something else set the weapon sprite back to opaque but this item is still active.
fixed_t ts = MIN(Strength * (special1 + 1), FRACUNIT);
vis->alpha = clamp<fixed_t>((OPAQUE - ts), 0, OPAQUE);
vis->RenderStyle = (Mode == NAME_Fuzzy ? STYLE_OptFuzzy : STYLE_Translucent);
fixed_t ts = Strength * (special1 + 1); if (ts > FRACUNIT) ts = FRACUNIT;
vis->alpha = clamp<fixed_t>((/*OwnersNormalAlpha*/OPAQUE - ts), 0, OPAQUE);
switch (Mode)
{
case (NAME_Fuzzy):
vis->RenderStyle = STYLE_OptFuzzy;
break;
case (NAME_Opaque):
vis->RenderStyle = STYLE_Normal;
break;
case (NAME_Additive):
vis->RenderStyle = STYLE_Add;
break;
case (NAME_Stencil):
vis->RenderStyle = STYLE_Stencil;
break;
case (NAME_None):
case (NAME_Cumulative):
case (NAME_Translucent):
default:
vis->RenderStyle = STYLE_Translucent;
break;
}
}
// Handling of Strife-like cumulative invisibility powerups, the weapon itself shouldn't become invisible
if ((vis->alpha < TRANSLUC25 && special1 > 0) || (vis->alpha == 0))

View file

@ -81,11 +81,12 @@ class APowerInvisibility : public APowerup
DECLARE_CLASS (APowerInvisibility, APowerup)
protected:
bool HandlePickup (AInventory *item);
void CommonInit ();
void InitEffect ();
void DoEffect ();
void EndEffect ();
int AlterWeaponSprite (vissprite_t *vis);
// FRenderStyle OwnersNormalStyle;
// fixed_t OwnersNormalAlpha;
};
// Needed only for m_cheat.cpp now

View file

@ -1728,3 +1728,30 @@ bool AMapRevealer::TryPickup (AActor *&toucher)
return true;
}
//===========================================================================
//
// AScoreItem
//
//===========================================================================
IMPLEMENT_CLASS(AScoreItem)
//===========================================================================
//
// AScoreItem :: TryPickup
//
// This function does nothing much. Theoretically, the player could have a
// score property which would be incremented by the score items' own score
// property (probably using the Amount property for that), but that is not
// needed for the moment.
//
//===========================================================================
bool AScoreItem::TryPickup (AActor *&toucher)
{
toucher->Score += Amount;
GoAwayAndDie();
return true;
}

View file

@ -475,4 +475,16 @@ public:
bool bDepleted;
};
// A score item is picked up without being added to the inventory.
// Contrarily to FakeInventory, it does nothing.
class AScoreItem : public AInventory
{
DECLARE_CLASS (AScoreItem, AInventory)
public:
bool TryPickup(AActor *&toucher);
};
#endif //__A_PICKUPS_H__

View file

@ -58,15 +58,9 @@ void AWeapon::Serialize (FArchive &arc)
<< MoveCombatDist
<< Ammo1 << Ammo2 << SisterWeapon << GivenAsMorphWeapon
<< bAltFire
<< ReloadCounter;
if (SaveVersion >= 1688)
{
arc << FOVScale;
if (SaveVersion >= 1700)
{
arc << Crosshair;
}
}
<< ReloadCounter
<< FOVScale
<< Crosshair;
}
//===========================================================================

View file

@ -636,11 +636,7 @@ private:
continue;
}
label = item->GetClass()->Meta.GetMetaString (AMETA_StrifeName);
if (label == NULL)
{
label = item->GetClass()->TypeName.GetChars();
}
label = item->GetTag();
int colnum = ((i-pos) / 5) & (KeyPopScroll > 0 ? 3 : 1);
int rownum = (i % 5) * 18;

View file

@ -256,6 +256,7 @@ sector_t * GLRendererBase::RenderViewpoint (AActor * camera, GL_IRECT * bounds,
// renders the view
//
//-----------------------------------------------------------------------------
extern unsigned int gl_vbo;
void GLRendererBase::RenderView (player_t* player)
{
@ -269,6 +270,13 @@ void GLRendererBase::RenderView (player_t* player)
LastCamera=player->camera;
}
gl.BindBuffer(GL_ARRAY_BUFFER, gl_vbo);
glVertexPointer(3,GL_FLOAT, 5*sizeof(float), 0);
glTexCoordPointer(2,GL_FLOAT, 5*sizeof(float),(void*)(intptr_t)(3*sizeof(float)));
gl.EnableClientState(GL_VERTEX_ARRAY);
gl.EnableClientState(GL_TEXTURE_COORD_ARRAY);
// reset statistics counters
All.Reset();
All.Clock();

View file

@ -39,6 +39,7 @@
**
*/
#include "gl/gl_include.h"
#include "doomtype.h"
#include "colormatcher.h"
#include "r_translate.h"
@ -686,6 +687,59 @@ static void PrepareSegs()
}
}
//==========================================================================
//
// creates a VBO for flat geometry - just a rough test for now.
//
//==========================================================================
unsigned int gl_vbo;
static void CreateFlatVBO()
{
static TArray<float> data;
for (int h=0;h<2;h++)
{
for(int i=0; i<numsectors;i++)
{
sector_t *sec = &sectors[i];
sec->vboheight[h] = sec->GetPlaneTexZ(h? sector_t::floor:sector_t::ceiling);
for(int j=0; j<sec->subsectorcount; j++)
{
subsector_t *sub = sec->subsectors[j];
sub->vboindex[h] = data.Size()/5;
for(int k=0; k<sub->numvertices; k++)
{
seg_t *seg = &segs[sub->firstline];
vertex_t *vt = seg->v1;
int idx = data.Reserve(5);
data[idx] = vt->fx;
data[idx+2] = vt->fy;
data[idx+3] = vt->fx/64.f;
data[idx+4] = -vt->fy/64.f;
data[idx+1] = float( h==0?
sec->ceilingplane.ZatPoint(vt->fx, vt->fy) :
sec->floorplane.ZatPoint(vt->fx, vt->fy));
}
}
}
}
gl.GenBuffers(1, &gl_vbo);
gl.BindBuffer(GL_ARRAY_BUFFER, gl_vbo);
gl.BufferData(GL_ARRAY_BUFFER, data.Size() * sizeof(float), &data[0], GL_STATIC_DRAW);
glVertexPointer(3,GL_FLOAT, 5*sizeof(float), 0);
glTexCoordPointer(2,GL_FLOAT, 5*sizeof(float),(void*)(intptr_t)(3*sizeof(float)));
gl.EnableClientState(GL_VERTEX_ARRAY);
gl.EnableClientState(GL_TEXTURE_COORD_ARRAY);
}
//==========================================================================
//
// Initialize the level data for the GL renderer
@ -746,6 +800,8 @@ void gl_PreprocessLevel()
}
if (GLRenderer != NULL) GLRenderer->SetupLevel();
if (gl.flags&RFL_GL_21)
CreateFlatVBO();
#if 0
gl_CreateSections();

View file

@ -182,6 +182,7 @@ void GLFlat::DrawSubsector(subsector_t * sub)
//
//
//==========================================================================
CVAR(Bool, gl_testvbo, false, 0)
void GLFlat::DrawSubsectors(bool istrans)
{
@ -193,15 +194,31 @@ void GLFlat::DrawSubsectors(bool istrans)
}
else
{
// Draw the subsectors belonging to this sector
for (int i=0; i<sector->subsectorcount; i++)
if (gl_testvbo && (gl.flags&RFL_GL_21) && !(renderflags&SSRF_RENDER3DPLANES) &&
sector->GetPlaneTexZ(this->ceiling? sector_t::ceiling:sector_t::floor) == sector->vboheight[!ceiling])
{
subsector_t * sub = sector->subsectors[i];
// This is just a quick hack to make translucent 3D floors and portals work.
if (gl_drawinfo->ss_renderflags[sub-subsectors]&renderflags || istrans)
for (int i=0; i<sector->subsectorcount; i++)
{
DrawSubsector(sub);
subsector_t * sub = sector->subsectors[i];
// This is just a quick hack to make translucent 3D floors and portals work.
if (gl_drawinfo->ss_renderflags[sub-subsectors]&renderflags || istrans)
{
gl.DrawArrays(GL_TRIANGLE_FAN, sub->vboindex[!ceiling], sub->numlines);
}
}
}
else
{
// Draw the subsectors belonging to this sector
for (int i=0; i<sector->subsectorcount; i++)
{
subsector_t * sub = sector->subsectors[i];
// This is just a quick hack to make translucent 3D floors and portals work.
if (gl_drawinfo->ss_renderflags[sub-subsectors]&renderflags || istrans)
{
DrawSubsector(sub);
}
}
}

View file

@ -211,7 +211,9 @@ FActorInfo *FActorInfo::GetReplacement (bool lookskill)
FActorInfo *FActorInfo::GetReplacee (bool lookskill)
{
FName skillrepname = AllSkills[gameskill].GetReplacedBy(this->Class->TypeName); if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == NULL) {
FName skillrepname = AllSkills[gameskill].GetReplacedBy(this->Class->TypeName);
if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == NULL)
{
Printf("Warning: incorrect actor name in definition of skill %s: \
inexistent class %s is replaced by class %s\n\
Skill replacement will be ignored for this actor.\n",
@ -229,7 +231,12 @@ FActorInfo *FActorInfo::GetReplacee (bool lookskill)
// potential infinite recursion.
FActorInfo *savedrep = Replacee;
Replacee = NULL;
FActorInfo *rep = savedrep; if (lookskill && (skillrepname != NAME_None) && (PClass::FindClass(skillrepname) != NULL)) { rep = PClass::FindClass(skillrepname)->ActorInfo; } rep = rep->GetReplacee (false); Replacee = savedrep;
FActorInfo *rep = savedrep;
if (lookskill && (skillrepname != NAME_None) && (PClass::FindClass(skillrepname) != NULL))
{
rep = PClass::FindClass(skillrepname)->ActorInfo;
}
rep = rep->GetReplacee (false); Replacee = savedrep;
return rep;
}
@ -445,6 +452,11 @@ CCMD (summonfriend)
SummonActor (DEM_SUMMONFRIEND, DEM_SUMMONFRIEND2, argv);
}
CCMD (summonmbf)
{
SummonActor (DEM_SUMMONMBF, DEM_SUMMONFRIEND2, argv);
}
CCMD (summonfoe)
{
SummonActor (DEM_SUMMONFOE, DEM_SUMMONFOE2, argv);

View file

@ -55,8 +55,8 @@ struct FState
{
WORD sprite;
SWORD Tics;
SBYTE Misc1;
BYTE Misc2;
long Misc1; // Was changed to SBYTE, reverted to long for MBF compat
long Misc2; // Was changed to BYTE, reverted to long for MBF compat
BYTE Frame;
BYTE DefineFlags; // Unused byte so let's use it during state creation.
FState *NextState;

View file

@ -94,6 +94,7 @@ EXTERN_CVAR(Int, showendoom)
EXTERN_CVAR(Bool, hud_althud)
EXTERN_CVAR(Int, compatmode)
EXTERN_CVAR (Bool, vid_vsync)
EXTERN_CVAR(Bool, displaynametags)
static value_t Renderers[] = {
{ 0.0, "Software" },
@ -159,12 +160,13 @@ value_t OffOn[2] = {
{ 1.0, "Off" }
};
value_t CompatModes[5] = {
value_t CompatModes[6] = {
{ 0.0, "Default" },
{ 1.0, "Doom" },
{ 2.0, "Doom (strict)" },
{ 3.0, "Boom" },
{ 4.0, "ZDoom 2.0.63" }
{ 4.0, "ZDoom 2.0.63" },
{ 5.0, "MBF" },
};
menu_t *CurrentMenu;
@ -512,6 +514,7 @@ static menuitem_t VideoItems[] = {
{ discrete, "Rocket Trails", {&cl_rockettrails}, {4.0}, {0.0}, {0.0}, {RocketTrailTypes} },
{ discrete, "Blood Type", {&cl_bloodtype}, {3.0}, {0.0}, {0.0}, {BloodTypes} },
{ discrete, "Bullet Puff Type", {&cl_pufftype}, {2.0}, {0.0}, {0.0}, {PuffTypes} },
{ discrete, "Display nametags", {&displaynametags}, {2.0}, {0.0}, {0.0}, {YesNo} },
};
#define CROSSHAIR_INDEX 10
@ -1094,7 +1097,7 @@ static menu_t DMFlagsMenu =
*=======================================*/
static menuitem_t CompatibilityItems[] = {
{ discrete, "Compatibility mode", {&compatmode}, {5.0}, {1.0}, {0.0}, {CompatModes} },
{ discrete, "Compatibility mode", {&compatmode}, {6.0}, {1.0}, {0.0}, {CompatModes} },
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
{ bitflag, "Find shortest textures like Doom", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SHORTTEX} },
{ bitflag, "Use buggier stair building", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_STAIRINDEX} },
@ -1120,6 +1123,9 @@ static menuitem_t CompatibilityItems[] = {
{ bitflag, "Allow any bossdeath for level special", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_ANYBOSSDEATH} },
{ bitflag, "No Minotaur floor flames in water", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_MINOTAUR} },
{ bitflag, "Original A_Mushroom speed in DEH mods", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_MUSHROOM} },
{ bitflag, "Monster movement is affected by effects", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_MBFMONSTERMOVE} },
{ bitflag, "Crushed monsters can be resurrected", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_CORPSEGIBS} },
{ bitflag, "Friendly monsters aren't blocked", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_NOBLOCKFRIENDS} },
{ discrete, "Interpolate monster movement", {&nomonsterinterpolation}, {2.0}, {0.0}, {0.0}, {NoYes} },
};

View file

@ -25,8 +25,11 @@ xx(Ghost)
xx(Reflective)
// Invisibility types
xx(Additive)
xx(Cumulative)
xx(Fuzzy)
xx(Opaque)
xx(Stencil)
// Healingradius types
xx(Mana)
@ -175,6 +178,7 @@ xx(No)
xx(Greetings)
xx(Idle)
xx(GenericFreezeDeath)
xx(GenericCrush)
// Compatible death names for the decorate parser.
xx(XDeath)

View file

@ -168,13 +168,19 @@ static int P_Set3DFloor(line_t * line, int param,int param2, int alpha)
if (l->args[0])
{
// Yes, Vavoom's 3D-floor definitions suck!
static DWORD vavoomcolors[]={
0, 0x101080, 0x801010, 0x108010, 0x287020, 0xf0f010};
// The content list changed in r1783 of Vavoom to be unified
// among all its supported games, so it has now ten different
// values instead of just five.
static DWORD vavoomcolors[]={VC_EMPTY,
VC_WATER, VC_LAVA, VC_NUKAGE, VC_SLIME, VC_HELLSLIME,
VC_BLOOD, VC_SLUDGE, VC_HAZARD, VC_BOOMWATER};
flags|=FF_SWIMMABLE|FF_BOTHPLANES|FF_ALLSIDES|FF_FLOOD;
l->frontsector->ColorMap = GetSpecialLights (l->frontsector->ColorMap->Color,
vavoomcolors[l->args[0]],
l->frontsector->ColorMap->Desaturate);
l->frontsector->ColorMap =
GetSpecialLights (l->frontsector->ColorMap->Color,
vavoomcolors[l->args[0]]&VC_COLORMASK,
(vavoomcolors[l->args[0]]&VC_ALPHAMASK)>>24);
// l->frontsector->ColorMap->Desaturate);
}
alpha=(alpha*255)/100;
break;

View file

@ -39,7 +39,22 @@ typedef enum
} ffloortype_e;
// This is for the purpose of Sector_SetContents:
enum : unsigned int
{
VC_EMPTY = 0, // Here's the original values of the color shifts in Vavoom, and in ARGB:
VC_WATER = 0x80825032, // 130, 80, 50, 128 -> 80.82.50.32 (was 0x101080)
VC_LAVA = 0x96FF5000, // 255, 80, 0, 150 -> 96.FF.50.00 (was 0xf0f010)
VC_NUKAGE = 0x9632FF32, // 50, 255, 50, 150 -> 96.32.FF.32 (was 0x108010)
VC_SLIME = 0x96001905, // 0, 25, 5, 150 -> 96.00.19.05 (was 0x287020)
VC_HELLSLIME = 0x96FF5000, // 255, 80, 0, 150 -> 96.FF.50.00 (wasn't covered)
VC_BLOOD = 0x96A00A0A, // 160, 16, 16, 150 -> 96.A0.0A.0A (was 0x801010)
VC_SLUDGE = 0x9680A080, // 128, 160, 128, 150 -> 96.80.A0.80 (wasn't covered)
VC_HAZARD = 0x8080A080, // 128, 160, 128, 128 -> 80.80.A0.80 (wasn't covered)
VC_BOOMWATER = 0x80004FA5, // Boom WATERMAP: -> 80.00.4F.A5 (wasn't covered)
VC_ALPHAMASK = 0xFF000000,
VC_COLORMASK = 0x00FFFFFF,
};
#ifdef _3DFLOORS

View file

@ -2426,6 +2426,8 @@ enum
APROP_Dropped = 18,
APROP_Notarget = 19,
APROP_Species = 20,
APROP_NameTag = 21,
APROP_Score = 22,
};
// These are needed for ACS's APROP_RenderStyle
@ -2578,6 +2580,17 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value)
case APROP_Species:
actor->Species = FBehavior::StaticLookupString(value);
break;
case APROP_Score:
actor->Score = value;
case APROP_NameTag:
actor->Tag = FBehavior::StaticLookupString(value);
break;
default:
// do nothing.
break;
}
}
@ -2642,6 +2655,7 @@ int DLevelScript::GetActorProperty (int tid, int property)
{
return 0;
}
case APROP_Score: return actor->Score;
default: return 0;
}
}
@ -2688,6 +2702,7 @@ int DLevelScript::CheckActorProperty (int tid, int property, int value)
case APROP_DeathSound: string = actor->DeathSound; break;
case APROP_ActiveSound: string = actor->ActiveSound; break;
case APROP_Species: string = actor->GetSpecies(); break;
case APROP_NameTag: string = actor->GetTag(); break;
}
if (string == NULL) string = "";
return (!stricmp(string, FBehavior::StaticLookupString(value)));
@ -2874,6 +2889,8 @@ enum EACSFunctions
ACSF_SpawnSpotFacingForced,
ACSF_CheckActorProperty,
ACSF_SetActorVelocity,
ACSF_SetUserVariable,
ACSF_GetUserVariable,
};
int DLevelScript::SideFromID(int id, int side)
@ -3072,6 +3089,42 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
}
return 0;
case ACSF_SetUserVariable:
{
int cnt = 0;
if (args[1] >= 0 && args[1] < 10)
{
if (args[0] == 0)
{
if (activator != NULL)
{
activator->uservar[args[1]] = args[2];
}
cnt++;
}
else
{
TActorIterator<AActor> iterator (args[0]);
while ( (actor = iterator.Next ()) )
{
actor->uservar[args[1]] = args[2];
cnt++;
}
}
}
return cnt;
}
case ACSF_GetUserVariable:
if (args[1] >= 0 && args[1] < 10)
{
activator = SingleActorFromTID(args[0], NULL);
return activator != NULL? activator->uservar[args[1]] : 0;
}
else return 0;
default:
break;
}

View file

@ -875,11 +875,7 @@ static void DrawConversationMenu ()
}
else
{
speakerName = cp->ConversationNPC->GetClass()->Meta.GetMetaString (AMETA_StrifeName);
if (speakerName == NULL)
{
speakerName = "Person";
}
speakerName = cp->mo->GetTag("Person");
}
// Dim the screen behind the dialogue (but only if there is no backdrop).

View file

@ -371,25 +371,31 @@ bool P_HitFriend(AActor * self)
// Move in the current direction,
// returns false if the move is blocked.
//
bool P_Move (AActor *actor)
{
fixed_t tryx, tryy, deltax, deltay, origx, origy;
bool try_ok;
int speed;
int speed = actor->Speed;
int movefactor = ORIG_FRICTION_FACTOR;
int friction = ORIG_FRICTION;
if (actor->flags2 & MF2_BLASTED)
{
return true;
}
if (actor->movedir == DI_NODIR)
{
return false;
}
// [RH] Instead of yanking non-floating monsters to the ground,
// let gravity drop them down, unless they're moving down a step.
if (!(actor->flags & MF_NOGRAVITY) && actor->z > actor->floorz
&& !(actor->flags2 & MF2_ONMOBJ))
// [GZ] Let jumping actors jump.
if (!((actor->flags & MF_NOGRAVITY) || (actor->flags6 & MF6_CANJUMP))
&& actor->z > actor->floorz && !(actor->flags2 & MF2_ONMOBJ))
{
if (actor->z > actor->floorz + actor->MaxStepHeight)
{
@ -406,21 +412,40 @@ bool P_Move (AActor *actor)
speed = actor->Speed;
#if 0 // [RH] I'm not so sure this is such a good idea
// killough 10/98: make monsters get affected by ice and sludge too:
movefactor = P_GetMoveFactor (actor, &friction);
#if 0 // todo
if (friction < ORIG_FRICTION)
{ // sludge
speed = ((ORIG_FRICTION_FACTOR - (ORIG_FRICTION_FACTOR-movefactor)/2)
* speed) / ORIG_FRICTION_FACTOR;
if (speed == 0)
{ // always give the monster a little bit of speed
speed = ksgn(actor->Speed);
}
// killough 10/98: allow dogs to drop off of taller ledges sometimes.
// dropoff==1 means always allow it, dropoff==2 means only up to 128 high,
// and only if the target is immediately on the other side of the line.
if (actor->flags6 & MF6_JUMPDOWN && target &&
!(target->IsFriend(actor)) &&
P_AproxDistance(actor->x - target->x,
actor->y - target->y) < FRACUNIT*144 &&
P_Random(pr_dropoff) < 235)
{
dropoff = 2;
}
#endif
// [RH] I'm not so sure this is such a good idea
// [GZ] That's why it's compat-optioned.
if (compatflags & COMPATF_MBFMONSTERMOVE)
{
// killough 10/98: make monsters get affected by ice and sludge too:
movefactor = P_GetMoveFactor (actor, &friction);
if (friction < ORIG_FRICTION)
{ // sludge
speed = ((ORIG_FRICTION_FACTOR - (ORIG_FRICTION_FACTOR-movefactor)/2)
* speed) / ORIG_FRICTION_FACTOR;
if (speed == 0)
{ // always give the monster a little bit of speed
speed = ksgn(actor->Speed);
}
}
}
tryx = (origx = actor->x) + (deltax = FixedMul (speed, xspeed[actor->movedir]));
tryy = (origy = actor->y) + (deltay = FixedMul (speed, yspeed[actor->movedir]));
@ -481,7 +506,7 @@ bool P_Move (AActor *actor)
if (!try_ok)
{
if ((actor->flags & MF_FLOAT) && tm.floatok)
if (((actor->flags6 & MF6_CANJUMP)||(actor->flags & MF_FLOAT)) && tm.floatok)
{ // must adjust height
fixed_t savedz = actor->z;
@ -490,6 +515,7 @@ bool P_Move (AActor *actor)
else
actor->z -= actor->FloatSpeed;
// [RH] Check to make sure there's nothing in the way of the float
if (P_TestMobjZ (actor))
{
@ -500,7 +526,9 @@ bool P_Move (AActor *actor)
}
if (!spechit.Size ())
{
return false;
}
// open any specials
actor->movedir = DI_NODIR;
@ -684,7 +712,7 @@ void P_DoNewChaseDir (AActor *actor, fixed_t deltax, fixed_t deltay)
return;
}
actor->movedir = DI_NODIR; // can not move
actor->movedir = DI_NODIR; // cannot move
}
@ -2213,13 +2241,31 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
S_Sound (corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE);
info = corpsehit->GetDefault ();
corpsehit->height = info->height; // [RH] Use real mobj height
corpsehit->radius = info->radius; // [RH] Use real radius
/*
// Make raised corpses look ghostly
if (corpsehit->alpha > TRANSLUC50)
corpsehit->alpha /= 2;
*/
if (ib_compatflags & BCOMPATF_VILEGHOSTS)
{
corpsehit->height <<= 2;
// [GZ] This was a commented-out feature, so let's make use of it,
// but only for ghost monsters so that they are visibly different.
if (corpsehit->height == 0)
{
// Make raised corpses look ghostly
if (corpsehit->alpha > TRANSLUC50)
{
corpsehit->alpha /= 2;
}
// This will only work if the render style is changed as well.
if (corpsehit->RenderStyle == LegacyRenderStyles[STYLE_Normal])
{
corpsehit->RenderStyle = STYLE_Translucent;
}
}
corpsehit->Translation = info->Translation; // Clean up bloodcolor translation from crushed corpses
}
else
{
corpsehit->height = info->height; // [RH] Use real mobj height
corpsehit->radius = info->radius; // [RH] Use real radius
}
corpsehit->flags = info->flags;
corpsehit->flags2 = info->flags2;
corpsehit->flags3 = info->flags3;
@ -2315,7 +2361,7 @@ void A_Chase(AActor *self)
// A_FaceTarget
//
//=============================================================================
void A_FaceTarget(AActor *self)
void A_FaceTarget (AActor *self)
{
if (!self->target)
return;

View file

@ -782,12 +782,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
}
}
}
if (targ && targ->player && (targ->player->cheats & CF_NOTARGET))
{
return;
}
}
}
if (targ && targ->player && (targ->player->cheats & CF_NOTARGET))
{
return;
}
}
// [RH] Andy Baker's stealth monsters
@ -811,36 +811,40 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
}
// Let the self wander around aimlessly looking for a fight
if (self->SeeState != NULL)
{
if (!(self->flags & MF_INCHASE))
{
if (seestate)
{
self->SetState (seestate);
}
else
{
self->SetState (self->SeeState);
}
}
}
else
{
CALL_ACTION(A_Wander, self);
}
if (!(self->flags & MF_INCHASE))
{
if (seestate)
{
self->SetState (seestate);
}
else
{
if (self->SeeState != NULL)
{
self->SetState (self->SeeState);
}
else
{
CALL_ACTION(A_Wander, self);
}
}
}
}
}
else
{
self->target = targ; //We already have a target?
// [KS] The target can become ourselves in rare circumstances (like
// if we committed suicide), so if that's the case, just ignore it.
if (self->target == self) self->target = NULL;
if (targ != NULL)
if (self->target != NULL)
{
if (self->flags & MF_AMBUSH)
{
dist = P_AproxDistance (targ->x - self->x,
targ->y - self->y);
dist = P_AproxDistance (self->target->x - self->x,
self->target->y - self->y);
if (P_CheckSight (self, self->target, 2) &&
(!minseedist || dist > minseedist) &&
(!maxseedist || dist < maxseedist))

View file

@ -883,7 +883,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
FState * woundstate = NULL;
PainChanceList * pc = NULL;
if (target == NULL || !(target->flags & MF_SHOOTABLE))
if (target == NULL || !((target->flags & MF_SHOOTABLE) || (target->flags6 & MF6_VULNERABLE)))
{ // Shouldn't happen
return;
}
@ -1017,13 +1017,12 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
damage = target->TakeSpecialDamage (inflictor, source, damage, mod);
}
if (damage == -1)
{
return;
}
// Push the target unless the source's weapon's kickback is 0.
// (i.e. Guantlets/Chainsaw)
// (i.e. Gauntlets/Chainsaw)
if (inflictor && inflictor != target // [RH] Not if hurting own self
&& !(target->flags & MF_NOCLIP)
&& !(inflictor->flags2 & MF2_NODMGTHRUST)
@ -1047,13 +1046,13 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
// Calculate this as float to avoid overflows so that the
// clamping that had to be done here can be removed.
double fltthrust;
double fltthrust;
fltthrust = mod == NAME_MDK ? 10 : 32;
if (target->Mass > 0)
{
fltthrust = clamp((damage * 0.125 * kickback) / target->Mass, 0., fltthrust);
}
fltthrust = mod == NAME_MDK ? 10 : 32;
if (target->Mass > 0)
{
fltthrust = clamp((damage * 0.125 * kickback) / target->Mass, 0., fltthrust);
}
thrust = FLOAT2FIXED(fltthrust);

View file

@ -380,10 +380,12 @@ void P_FakeZMovement (AActor *mo);
bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, bool dropoff, const secplane_t * onfloor, FCheckPosition &tm);
bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, bool dropoff, const secplane_t * onfloor = NULL);
bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y);
void P_ApplyTorque(AActor *mo);
bool P_TeleportMove (AActor* thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag); // [RH] Added z and telefrag parameters
void P_PlayerStartStomp (AActor *actor); // [RH] Stomp on things for a newly spawned player
void P_SlideMove (AActor* mo, fixed_t tryx, fixed_t tryy, int numsteps);
bool P_BounceWall (AActor *mo);
bool P_BounceActor (AActor *mo, AActor * BlockingMobj);
bool P_CheckSight (const AActor* t1, const AActor* t2, int flags=0);
void P_ResetSightCounters (bool full);
void P_UseLines (player_t* player);
@ -392,7 +394,7 @@ void P_FindFloorCeiling (AActor *actor, bool onlymidtex = false);
bool P_ChangeSector (sector_t* sector, int crunch, int amt, int floorOrCeil, bool isreset);
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget = NULL, fixed_t vrange=0, bool forcenosmart=false, bool check3d = false);
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget = NULL, fixed_t vrange=0, bool forcenosmart=false, bool check3d = false, bool checknonshootable = false);
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, bool ismelee = false);
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, bool ismelee = false);
void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch);
@ -429,10 +431,9 @@ const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymo
// (For ZDoom itself this doesn't make any difference here but for GZDoom it does.)
//
//----------------------------------------------------------------------------------
subsector_t *P_PointInSubsector (fixed_t x, fixed_t y);
inline sector_t *P_PointInSector(fixed_t x, fixed_t y)
{
return P_PointInSubsector(x,y)->sector;
return R_PointInSubsector(x,y)->sector;
}
//

View file

@ -590,17 +590,25 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm)
return false;
}
if (!(tm.thing->flags & MF_MISSILE) || (ld->flags & (ML_BLOCKEVERYTHING|ML_BLOCKPROJECTILE)))
{
// MBF bouncers are treated as missiles here.
bool Projectile = (tm.thing->flags & MF_MISSILE || tm.thing->BounceFlags & BOUNCE_MBF);
// MBF considers that friendly monsters are not blocked by monster-blocking lines.
// This is added here as a compatibility option. Note that monsters that are dehacked
// into being friendly with the MBF flag automatically gain MF3_NOBLOCKMONST, so this
// just optionally generalizes the behavior to other friendly monsters.
bool NotBlocked = ((tm.thing->flags3 & MF3_NOBLOCKMONST)
|| ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY)));
if (!(Projectile) || (ld->flags & (ML_BLOCKEVERYTHING|ML_BLOCKPROJECTILE))) {
if (ld->flags & ML_RAILING)
{
rail = true;
}
else if ((ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING)) || // explicitly blocking everything
(!(tm.thing->flags3 & MF3_NOBLOCKMONST) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only
(tm.thing->player != NULL && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
((tm.thing->flags & MF_MISSILE) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles
((ld->flags & ML_BLOCK_FLOATERS) && (tm.thing->flags & MF_FLOAT))) // block floaters
else if ((ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING)) || // explicitly blocking everything
(!(NotBlocked) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only
(tm.thing->player != NULL && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
((Projectile) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles
((tm.thing->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS))) // block floaters
{
if (tm.thing->flags2 & MF2_BLASTED)
{
@ -754,6 +762,13 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
bool solid;
int damage;
if (!((thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) || thing->flags6 & MF6_TOUCHY))
return true; // can't hit thing
fixed_t blockdist = thing->radius + tm.thing->radius;
if ( abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist)
return true;
// don't clip against self
if (thing == tm.thing)
return true;
@ -764,13 +779,6 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
if ((tm.thing->flags6 & MF6_THRUSPECIES) && (tm.thing->GetSpecies() == thing->GetSpecies()))
return true;
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) )
return true; // can't hit thing
fixed_t blockdist = thing->radius + tm.thing->radius;
if ( abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist)
return true;
tm.thing->BlockingMobj = thing;
topz = thing->z + thing->height;
if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT|MF_MISSILE|MF_SKULLFLY|MF_NOGRAVITY)) &&
@ -806,6 +814,26 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
return true;
}
}
// touchy object is alive, toucher is solid
if (thing->flags6 & MF6_TOUCHY && tm.thing->flags & MF_SOLID && thing->health > 0 &&
// Thing is an armed mine or a sentient thing
(thing->flags6 & MF6_ARMED || thing->IsSentient()) &&
// either different classes or players
(thing->player || thing->GetClass() != tm.thing->GetClass()) &&
// or different species if DONTHARMSPECIES
(!(thing->flags6 & MF6_DONTHARMSPECIES) || thing->GetSpecies() != tm.thing->GetSpecies()) &&
// touches vertically
thing->z + thing->height >= tm.thing->z && tm.thing->z + tm.thing->height >= thing->z &&
// prevents lost souls from exploding when fired by pain elementals
(thing->master != tm.thing && tm.thing->master != thing))
// Difference with MBF: MBF hardcodes the LS/PE check and lets actors of the same species
// but different classes trigger the touchiness, but that seems less straightforwards.
{
thing->flags6 &= ~MF6_ARMED; // Disarm
P_DamageMobj (thing, NULL, NULL, thing->health, NAME_None, DMG_FORCED); // kill object
return true;
}
// Check for skulls slamming into things
if (tm.thing->flags & MF_SKULLFLY)
{
@ -839,8 +867,8 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
LineSpecials[thing->special] (NULL, tm.thing, false, thing->args[0],
thing->args[1], thing->args[2], thing->args[3], thing->args[4]);
}
// Check for missile
if (tm.thing->flags & MF_MISSILE)
// Check for missile or non-solid MBF bouncer
if (tm.thing->flags & MF_MISSILE || ((tm.thing->BounceFlags & BOUNCE_MBF) && !(tm.thing->flags & MF_SOLID)))
{
// Check for a non-shootable mobj
if (thing->flags2 & MF2_NONSHOOTABLE)
@ -891,7 +919,8 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
// [RH] What is the point of this check, again? In Hexen, it is unconditional,
// but here we only do it if the missile's damage is 0.
if ((tm.thing->BounceFlags & BOUNCE_Actors) && tm.thing->Damage == 0)
// MBF bouncer might have a non-0 damage value, but they must not deal damage on impact either.
if ((tm.thing->BounceFlags & BOUNCE_Actors) && (tm.thing->Damage == 0 || !(tm.thing->flags & MF_MISSILE)))
{
return (tm.thing->target == thing || !(thing->flags & MF_SOLID));
}
@ -1314,7 +1343,8 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm)
while ((ld = it.Next()))
{
if (!PIT_CheckLine(ld, box, tm)) return false;
if (!PIT_CheckLine(ld, box, tm))
return false;
}
if (tm.ceilingz - tm.floorz < thing->height)
@ -1594,12 +1624,12 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
#else
// When flying, slide up or down blocking lines until the actor
// is not blocked.
if (thing->z+thing->height > tmceilingz)
if (thing->z+thing->height > tm.ceilingz)
{
thing->velz = -8*FRACUNIT;
goto pushline;
}
else if (thing->z < tmfloorz && tmfloorz-tmdropoffz > thing->MaxDropOffHeight)
else if (thing->z < tm.floorz && tm.floorz-tm.dropoffz > thing->MaxDropOffHeight)
{
thing->velz = 8*FRACUNIT;
goto pushline;
@ -1706,6 +1736,12 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
oldAboveFakeCeiling = eyez > oldsec->heightsec->ceilingplane.ZatPoint (thing->x, thing->y);
}
// Borrowed from MBF:
if (thing->BounceFlags & BOUNCE_MBF && // killough 8/13/98
!(thing->flags & (MF_MISSILE|MF_NOGRAVITY)) &&
!thing->IsSentient() && tm.floorz - thing->z > 16*FRACUNIT)
return false; // too big a step up for MBF bouncers under gravity
// the move is ok, so link the thing into its new position
thing->UnlinkFromWorld ();
@ -1972,8 +2008,6 @@ struct FSlide
bool BounceWall (AActor *mo);
};
//
// P_HitSlideLine
// Adjusts the xmove / ymove
@ -2152,7 +2186,8 @@ void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_
{
goto isblocking;
}
if (li->flags & ML_BLOCKMONSTERS && !(slidemo->flags3 & MF3_NOBLOCKMONST))
if (li->flags & ML_BLOCKMONSTERS && !((slidemo->flags3 & MF3_NOBLOCKMONST)
|| ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (slidemo->flags & MF_FRIENDLY))))
{
goto isblocking;
}
@ -2595,7 +2630,10 @@ bool FSlide::BounceWall (AActor *mo)
// The amount of bounces is limited
if (mo->bouncecount>0 && --mo->bouncecount==0)
{
P_ExplodeMissile(mo, NULL, NULL);
if (mo->flags & MF_MISSILE)
P_ExplodeMissile(mo, NULL, NULL);
else
mo->Die(NULL, NULL);
return true;
}
@ -2636,7 +2674,28 @@ bool P_BounceWall (AActor *mo)
return slide.BounceWall(mo);
}
extern FRandom pr_bounce ("Bounce");
bool P_BounceActor (AActor *mo, AActor * BlockingMobj)
{
if (mo && BlockingMobj && ((mo->BounceFlags & BOUNCE_AllActors)
|| ((mo->flags & MF_MISSILE) && (BlockingMobj->flags2 & MF2_REFLECTIVE)
|| ((!BlockingMobj->player) && (!(BlockingMobj->flags3 & MF3_ISMONSTER))))
))
{
fixed_t speed;
angle_t angle = R_PointToAngle2 (BlockingMobj->x,
BlockingMobj->y, mo->x, mo->y) + ANGLE_1*((pr_bounce()%16)-8);
speed = P_AproxDistance (mo->velx, mo->vely);
speed = FixedMul (speed, mo->wallbouncefactor); // [GZ] was 0.75, using wallbouncefactor seems more consistent
mo->angle = angle;
angle >>= ANGLETOFINESHIFT;
mo->velx = FixedMul (speed, finecosine[angle]);
mo->vely = FixedMul (speed, finesine[angle]);
mo->PlayBounceSound(true);
return true;
}
else return false;
}
//============================================================================
//
@ -2667,7 +2726,7 @@ struct aim_t
bool AimTraverse3DFloors(const divline_t &trace, intercept_t * in);
#endif
void AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy);
void AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, bool checknonshootable = false);
};
@ -2784,7 +2843,7 @@ bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in)
//
//============================================================================
void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy)
void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, bool checknonshootable)
{
FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES|PT_ADDTHINGS);
intercept_t *in;
@ -2839,18 +2898,20 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
if (th == shootthing)
continue; // can't shoot self
if (!(th->flags&MF_SHOOTABLE))
continue; // corpse or something
// check for physical attacks on a ghost
if ((th->flags3 & MF3_GHOST) &&
shootthing->player && // [RH] Be sure shootthing is a player
shootthing->player->ReadyWeapon &&
(shootthing->player->ReadyWeapon->flags2 & MF2_THRUGHOST))
if (!checknonshootable) // For info CCMD, ignore stuff about GHOST and SHOOTABLE flags
{
continue;
if (!(th->flags&MF_SHOOTABLE))
continue; // corpse or something
// check for physical attacks on a ghost
if ((th->flags3 & MF3_GHOST) &&
shootthing->player && // [RH] Be sure shootthing is a player
shootthing->player->ReadyWeapon &&
(shootthing->player->ReadyWeapon->flags2 & MF2_THRUGHOST))
{
continue;
}
}
dist = FixedMul (attackrange, in->frac);
#ifdef _3DFLOORS
@ -2974,6 +3035,11 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
aimpitch=thingpitch;
return;
}
if (checknonshootable)
{
linetarget=th;
aimpitch=thingpitch;
}
}
}
@ -2982,7 +3048,7 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
// P_AimLineAttack
//
//============================================================================
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget, fixed_t vrange, bool forcenosmart, bool check3d)
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget, fixed_t vrange, bool forcenosmart, bool check3d, bool checknonshootable)
{
fixed_t x2;
fixed_t y2;
@ -3051,7 +3117,7 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p
}
#endif
aim.AimTraverse (t1->x, t1->y, x2, y2);
aim.AimTraverse (t1->x, t1->y, x2, y2, checknonshootable);
if (!aim.linetarget)
{
@ -3968,7 +4034,9 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
while ((thing = it.Next()))
{
if (!(thing->flags & MF_SHOOTABLE) )
// Vulnerable actors can be damaged by radius attacks even if not shootable
// Used to emulate MBF's vulnerability of non-missile bouncers to explosions.
if (!((thing->flags & MF_SHOOTABLE) || (thing->flags6 & MF6_VULNERABLE)))
continue;
// Boss spider and cyborg and Heretic's ep >= 2 bosses
@ -4124,7 +4192,6 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
}
}
//
// SECTOR HEIGHT CHANGING
// After modifying a sector's floor or ceiling height,

View file

@ -281,36 +281,9 @@ void AActor::Serialize (FArchive &arc)
<< MeleeState
<< MissileState
<< MaxDropOffHeight
<< MaxStepHeight;
if (SaveVersion < 1796)
{
int bouncetype, bounceflags;
arc << bouncetype;
bounceflags = 0;
if (bouncetype & 4)
bounceflags |= BOUNCE_UseSeeSound;
bouncetype &= 3;
if (bouncetype == 1) bounceflags |= BOUNCE_Doom;
else if (bouncetype == 2) bounceflags |= BOUNCE_Heretic;
else if (bouncetype == 3) bounceflags |= BOUNCE_Hexen;
if (flags3 & 0x00800000)
flags3 &= ~0x00800000, bounceflags |= BOUNCE_CanBounceWater;
if (flags3 & 0x01000000)
flags3 &= ~0x01000000, bounceflags |= BOUNCE_NoWallSound;
if (flags4 & 0x80000000)
flags4 &= ~0x80000000, bounceflags |= BOUNCE_Quiet;
if (flags5 & 0x00000008)
flags5 &= ~0x00000008, bounceflags |= BOUNCE_AllActors;
if (flags5 & 0x00000010)
flags5 &= ~0x00000010, bounceflags |= BOUNCE_ExplodeOnWater;
BounceFlags = bounceflags;
}
else
{
arc << BounceFlags;
}
arc << bouncefactor
<< MaxStepHeight
<< BounceFlags
<< bouncefactor
<< wallbouncefactor
<< bouncecount
<< maxtargetrange
@ -324,7 +297,11 @@ void AActor::Serialize (FArchive &arc)
<< BlockingMobj
<< BlockingLine
<< pushfactor
<< Species;
<< Species
<< Score
<< Tag;
for(int i=0; i<10; i++) arc << uservar[i];
if (arc.IsStoring ())
{
@ -1013,24 +990,42 @@ void AActor::Touch (AActor *toucher)
bool AActor::Grind(bool items)
{
// crunch bodies to giblets
if ((this->flags & MF_CORPSE) &&
!(this->flags3 & MF3_DONTGIB) &&
(this->health <= 0))
if ((flags & MF_CORPSE) && !(flags3 & MF3_DONTGIB) && (health <= 0))
{
FState * state = this->FindState(NAME_Crush);
if (state != NULL && !(this->flags & MF_ICECORPSE))
FState * state = FindState(NAME_Crush);
bool isgeneric = false;
// ZDoom behavior differs from standard as crushed corpses cannot be raised.
// The reason for the change was originally because of a problem with players,
// see rh_log entry for February 21, 1999. Don't know if it is still relevant.
if (state == NULL // Only use the default crushed state if:
&& !(flags & MF_NOBLOOD) // 1. the monster bleeeds,
&& (i_compatflags & COMPATF_CORPSEGIBS) // 2. the compat setting is on,
&& player != NULL) // 3. and the thing isn't a player.
{
isgeneric = true;
state = FindState(NAME_GenericCrush);
if (state != NULL && (sprites[state->sprite].numframes <= 0))
state = NULL; // If one of these tests fails, do not use that state.
}
if (state != NULL && !(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);
flags &= ~MF_SOLID;
flags3 |= MF3_DONTGIB;
height = radius = 0;
SetState (state);
if (isgeneric) // Not a custom crush state, so colorize it appropriately.
{
S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE);
PalEntry bloodcolor = PalEntry(GetClass()->Meta.GetMetaInt(AMETA_BloodColor));
if (bloodcolor!=0) Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
}
return false;
}
if (!(this->flags & MF_NOBLOOD))
if (!(flags & MF_NOBLOOD))
{
if (this->flags4 & MF4_BOSSDEATH)
{
@ -1053,17 +1048,17 @@ bool AActor::Grind(bool items)
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;
flags &= ~MF_SOLID;
flags3 |= MF3_DONTGIB;
height = radius = 0;
return false;
}
AActor *gib = Spawn (i, this->x, this->y, this->z, ALLOW_REPLACE);
AActor *gib = Spawn (i, x, y, z, ALLOW_REPLACE);
if (gib != NULL)
{
gib->RenderStyle = this->RenderStyle;
gib->alpha = this->alpha;
gib->RenderStyle = RenderStyle;
gib->alpha = alpha;
gib->height = 0;
gib->radius = 0;
}
@ -1072,37 +1067,45 @@ bool AActor::Grind(bool items)
PalEntry bloodcolor = (PalEntry)this->GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
if (bloodcolor!=0) gib->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
}
if (this->flags & MF_ICECORPSE)
if (flags & MF_ICECORPSE)
{
this->tics = 1;
this->velx = this->vely = this->velz = 0;
tics = 1;
velx = vely = velz = 0;
}
else if (this->player)
else if (player)
{
this->flags |= MF_NOCLIP;
this->flags3 |= MF3_DONTGIB;
this->renderflags |= RF_INVISIBLE;
flags |= MF_NOCLIP;
flags3 |= MF3_DONTGIB;
renderflags |= RF_INVISIBLE;
}
else
{
this->Destroy ();
Destroy ();
}
return false; // keep checking
}
// crunch dropped items
if (this->flags & MF_DROPPED)
if (flags & MF_DROPPED)
{
if (items) this->Destroy (); // Only destroy dropped items if wanted
if (items) Destroy (); // Only destroy dropped items if wanted
return false; // keep checking
}
if (!(this->flags & MF_SOLID) || (this->flags & MF_NOCLIP))
// killough 11/98: kill touchy things immediately
if (flags6 & MF6_TOUCHY && (flags6 & MF6_ARMED || IsSentient()))
{
flags6 &= ~MF6_ARMED; // Disarm
P_DamageMobj (this, NULL, NULL, health, NAME_Crush, DMG_FORCED); // kill object
return true; // keep checking
}
if (!(flags & MF_SOLID) || (flags & MF_NOCLIP))
{
return false;
}
if (!(this->flags & MF_SHOOTABLE))
if (!(flags & MF_SHOOTABLE))
{
return false; // assume it is bloody gibs or something
}
@ -1324,7 +1327,10 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
// Landed in some sort of liquid
if (BounceFlags & BOUNCE_ExplodeOnWater)
{
P_ExplodeMissile(this, NULL, NULL);
if (flags & MF_MISSILE)
P_ExplodeMissile(this, NULL, NULL);
else
Die(NULL, NULL);
return true;
}
if (!(BounceFlags & BOUNCE_CanBounceWater))
@ -1348,37 +1354,49 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
// The amount of bounces is limited
if (bouncecount>0 && --bouncecount==0)
{
P_ExplodeMissile(this, NULL, NULL);
if (flags & MF_MISSILE)
P_ExplodeMissile(this, NULL, NULL);
else
Die(NULL, NULL);
return true;
}
fixed_t dot = TMulScale16 (velx, plane.a, vely, plane.b, velz, plane.c);
if (BounceFlags & BOUNCE_HereticType)
if (BounceFlags & (BOUNCE_HereticType | BOUNCE_MBF))
{
velx -= MulScale15 (plane.a, dot);
vely -= MulScale15 (plane.b, dot);
velz -= MulScale15 (plane.c, dot);
angle = R_PointToAngle2 (0, 0, velx, vely);
flags |= MF_INBOUNCE;
SetState (FindState(NAME_Death));
flags &= ~MF_INBOUNCE;
return false;
if (!(BounceFlags & BOUNCE_MBF)) // Heretic projectiles die, MBF projectiles don't.
{
flags |= MF_INBOUNCE;
SetState (FindState(NAME_Death));
flags &= ~MF_INBOUNCE;
return false;
}
else velz = FixedMul(velz, bouncefactor);
}
else // Don't run through this for MBF-style bounces
{
// The reflected velocity keeps only about 70% of its original speed
velx = FixedMul (velx - MulScale15 (plane.a, dot), bouncefactor);
vely = FixedMul (vely - MulScale15 (plane.b, dot), bouncefactor);
velz = FixedMul (velz - MulScale15 (plane.c, dot), bouncefactor);
angle = R_PointToAngle2 (0, 0, velx, vely);
}
// The reflected velocity keeps only about 70% of its original speed
velx = FixedMul (velx - MulScale15 (plane.a, dot), bouncefactor);
vely = FixedMul (vely - MulScale15 (plane.b, dot), bouncefactor);
velz = FixedMul (velz - MulScale15 (plane.c, dot), bouncefactor);
angle = R_PointToAngle2 (0, 0, velx, vely);
PlayBounceSound(true);
if (BounceFlags & BOUNCE_AutoOff)
if (BounceFlags & BOUNCE_MBF) // Bring it to rest below a certain speed
{
if (abs(velz) < (fixed_t)(Mass * GetGravity() / 64))
velz = 0;
}
else if (BounceFlags & BOUNCE_AutoOff)
{
if (!(flags & MF_NOGRAVITY) && (velz < 3*FRACUNIT))
{
BounceFlags &= ~BOUNCE_TypeMask;
}
}
return false;
}
@ -1723,13 +1741,20 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
if (!P_TryMove (mo, ptryx, ptryy, true, walkplane, tm))
{
// blocked move
AActor *BlockingMobj = mo->BlockingMobj;
line_t *BlockingLine = mo->BlockingLine;
if ((mo->flags2 & (MF2_SLIDE|MF2_BLASTED) || bForceSlide) && !(mo->flags&MF_MISSILE))
if (!(mo->flags & MF_MISSILE) && (mo->BounceFlags & BOUNCE_MBF)
&& (BlockingMobj != NULL ? P_BounceActor(mo, BlockingMobj) : P_BounceWall(mo)))
{
// try to slide along it
if (mo->BlockingMobj == NULL)
// Do nothing, relevant actions already done in the condition.
// This allows to avoid setting velocities to 0 in the final else of this series.
}
else if ((mo->flags2 & (MF2_SLIDE|MF2_BLASTED) || bForceSlide) && !(mo->flags&MF_MISSILE))
{ // try to slide along it
if (BlockingMobj == NULL)
{ // slide against wall
if (mo->BlockingLine != NULL &&
if (BlockingLine != NULL &&
mo->player && mo->waterlevel && mo->waterlevel < 3 &&
(mo->player->cmd.ucmd.forwardmove | mo->player->cmd.ucmd.sidemove) &&
mo->BlockingLine->sidedef[1] != NULL)
@ -1800,36 +1825,17 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
}
else if (mo->flags & MF_MISSILE)
{
AActor *BlockingMobj = mo->BlockingMobj;
steps = 0;
if (BlockingMobj)
{
if (mo->BounceFlags & BOUNCE_Actors)
{
if ((mo->BounceFlags & BOUNCE_AllActors) ||
(BlockingMobj->flags2 & MF2_REFLECTIVE) ||
((!BlockingMobj->player) &&
(!(BlockingMobj->flags3 & MF3_ISMONSTER))))
{
fixed_t speed;
angle = R_PointToAngle2 (BlockingMobj->x,
BlockingMobj->y, mo->x, mo->y)
+ANGLE_1*((pr_bounce()%16)-8);
speed = P_AproxDistance (mo->velx, mo->vely);
speed = FixedMul (speed, (fixed_t)(0.75*FRACUNIT));
mo->angle = angle;
angle >>= ANGLETOFINESHIFT;
mo->velx = FixedMul (speed, finecosine[angle]);
mo->vely = FixedMul (speed, finesine[angle]);
mo->PlayBounceSound(true);
return oldfloorz;
}
else
{ // Struck a player/creature
// Bounce test and code moved to P_BounceActor
if (!P_BounceActor(mo, BlockingMobj))
{ // Struck a player/creature
P_ExplodeMissile (mo, NULL, BlockingMobj);
return oldfloorz;
}
return oldfloorz;
}
}
else
@ -1841,14 +1847,11 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
return oldfloorz;
}
}
if (BlockingMobj &&
(BlockingMobj->flags2 & MF2_REFLECTIVE))
if (BlockingMobj && (BlockingMobj->flags2 & MF2_REFLECTIVE))
{
angle = R_PointToAngle2(BlockingMobj->x,
BlockingMobj->y,
mo->x, mo->y);
angle = R_PointToAngle2(BlockingMobj->x, BlockingMobj->y, mo->x, mo->y);
// Change angle for deflection/reflection
// Change angle for deflection/reflection
if (mo->AdjustReflectionAngle (BlockingMobj, angle))
{
goto explode;
@ -1947,10 +1950,12 @@ explode:
return oldfloorz;
}
if (mo->flags & MF_CORPSE)
// killough 8/11/98: add bouncers
// killough 9/15/98: add objects falling off ledges
// killough 11/98: only include bouncers hanging off ledges
if ((mo->flags & MF_CORPSE) || (mo->BounceFlags & BOUNCE_MBF && mo->z > mo->dropoffz) || (mo->flags6 & MF6_FALLING))
{ // Don't stop sliding if halfway off a step with some velocity
if (mo->velx > FRACUNIT/4 || mo->velx < -FRACUNIT/4
|| mo->vely > FRACUNIT/4 || mo->vely < -FRACUNIT/4)
if (mo->velx > FRACUNIT/4 || mo->velx < -FRACUNIT/4 || mo->vely > FRACUNIT/4 || mo->vely < -FRACUNIT/4)
{
if (mo->floorz > mo->Sector->floorplane.ZatPoint (mo->x, mo->y))
{
@ -2057,12 +2062,13 @@ void P_MonsterFallingDamage (AActor *mo)
//
// P_ZMovement
//
void P_ZMovement (AActor *mo, fixed_t oldfloorz)
{
fixed_t dist;
fixed_t delta;
fixed_t oldz = mo->z;
fixed_t oldz = mo->z;
//
// check for smooth step up
//
@ -2087,8 +2093,7 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
if (!mo->waterlevel || mo->flags & MF_CORPSE || (mo->player &&
!(mo->player->cmd.ucmd.forwardmove | mo->player->cmd.ucmd.sidemove)))
{
fixed_t grav = (fixed_t)(level.gravity * mo->Sector->gravity *
FIXED2FLOAT(mo->gravity) * 81.92);
fixed_t grav = mo->GetGravity();
// [RH] Double gravity only if running off a ledge. Coming down from
// an upward thrust (e.g. a jump) should not double it.
@ -2127,7 +2132,7 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
//
if ((mo->flags & MF_FLOAT) && !(mo->flags2 & MF2_DORMANT) && mo->target)
{ // float down towards target if too close
if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT))
if (!(mo->flags & (MF_SKULLFLY | MF_INFLOAT)))
{
dist = P_AproxDistance (mo->x - mo->target->x, mo->y - mo->target->y);
delta = (mo->target->z + (mo->height>>1)) - mo->z;
@ -2170,12 +2175,12 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
if (mo->BounceFlags & BOUNCE_Floors)
{
mo->FloorBounceMissile (mo->floorsector->floorplane);
return;
/* if (!(mo->flags6 & MF6_CANJUMP)) */ return;
}
else if (mo->flags3 & MF3_NOEXPLODEFLOOR)
{
mo->velz = 0;
P_HitFloor (mo);
mo->velz = 0;
return;
}
else if (mo->flags3 & MF3_FLOORHUGGER)
@ -2196,6 +2201,10 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
return;
}
}
else if (mo->BounceFlags & BOUNCE_MBF && mo->velz) // check for MBF-like bounce on non-missiles
{
mo->FloorBounceMissile(mo->floorsector->floorplane);
}
if (mo->flags3 & MF3_ISMONSTER) // Blasted mobj falling
{
if (mo->velz < -(23*FRACUNIT))
@ -2263,14 +2272,14 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
if (mo->BounceFlags & BOUNCE_Ceilings)
{ // ceiling bounce
mo->FloorBounceMissile (mo->ceilingsector->ceilingplane);
return;
/*if (!(mo->flags6 & MF6_CANJUMP))*/ return;
}
if (mo->velz > 0)
mo->velz = 0;
if (mo->flags & MF_SKULLFLY)
{ // the skull slammed into something
mo->velz = -mo->velz;
}
if (mo->velz > 0)
mo->velz = 0;
if (mo->flags & MF_MISSILE &&
(!(gameinfo.gametype & GAME_DoomChex) || !(mo->flags & MF_NOCLIP)))
{
@ -3157,11 +3166,18 @@ void AActor::Tick ()
{ // actor was destroyed
return;
}
if ((velx | vely) == 0 && (flags2 & MF2_BLASTED))
{ // Reset to not blasted when velocitiess are gone
flags2 &= ~MF2_BLASTED;
}
if ((velx | vely) == 0) // Actors at rest
{
if (flags2 & MF2_BLASTED)
{ // Reset to not blasted when velocities are gone
flags2 &= ~MF2_BLASTED;
}
if ((flags6 & MF6_TOUCHY) && !IsSentient())
{ // Arm a mine which has come to rest
flags6 |= MF6_ARMED;
}
}
if (flags2 & MF2_FLOATBOB)
{ // Floating item bobbing motion
z += FloatBobDiffs[(FloatBobPhase + level.maptime) & 63];
@ -3407,7 +3423,7 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t
AActor *actor;
actor = static_cast<AActor *>(const_cast<PClass *>(type)->CreateNew ());
actor->x = actor->PrevX = ix;
@ -4698,6 +4714,15 @@ bool P_HitFloor (AActor *thing)
{
const msecnode_t *m;
// killough 11/98: touchy objects explode on impact
// Allow very short drops to be safe, so that a touchy can be summoned without exploding.
if (thing->flags6 & MF6_TOUCHY && ((thing->flags6 & MF6_ARMED) || thing->IsSentient()) && ((thing->velz) < (-5 * FRACUNIT)))
{
thing->flags6 &= ~MF6_ARMED; // Disarm
P_DamageMobj (thing, NULL, NULL, thing->health, NAME_Crush, DMG_FORCED); // kill object
return true;
}
if (thing->flags2 & MF2_FLOATBOB || thing->flags3 & MF3_DONTSPLASH)
return false;
@ -4783,9 +4808,26 @@ bool P_CheckMissileSpawn (AActor* th)
th->y += th->vely >> shift;
th->z += th->velz >> shift;
// killough 3/15/98: no dropoff (really = don't care for missiles)
// killough 8/12/98: for non-missile objects (e.g. grenades)
//
// [GZ] MBF excludes non-missile objects from the P_TryMove test
// and subsequent potential P_ExplodeMissile call. That is because
// in MBF, a projectile is not an actor with the MF_MISSILE flag
// but an actor with either or both the MF_MISSILE and MF_BOUNCES
// flags, and a grenade is identified by not having MF_MISSILE.
// Killough wanted grenades not to explode directly when spawned,
// therefore they can be fired safely even when humping a wall as
// they will then just drop on the floor at their shooter's feet.
//
// However, ZDoom does allow non-missiles to be shot as well, so
// Killough's check for non-missiles is inadequate here. So let's
// replace it by a check for non-missile and MBF bounce type.
// This should allow MBF behavior where relevant without altering
// established ZDoom behavior for crazy stuff like a cacodemon cannon.
bool MBFGrenade = (!(th->flags & MF_MISSILE) || (th->BounceFlags & BOUNCE_MBF));
if (!P_TryMove (th, th->x, th->y, false, false, tm))
// killough 3/15/98: no dropoff (really = don't care for missiles)
if (!(P_TryMove (th, th->x, th->y, false, false, tm)))
{
// [RH] Don't explode ripping missiles that spawn inside something
if (th->BlockingMobj == NULL || !(th->flags2 & MF2_RIP) || (th->BlockingMobj->flags5 & MF5_DONTRIP))
@ -4801,6 +4843,10 @@ bool P_CheckMissileSpawn (AActor* th)
{
th->Destroy ();
}
else if (MBFGrenade && th->BlockingLine != NULL )
{
P_BounceWall(th);
}
else
{
P_ExplodeMissile (th, NULL, th->BlockingMobj);
@ -4958,6 +5004,7 @@ AActor * P_OldSpawnMissile(AActor * source, AActor * dest, const PClass *type)
P_CheckMissileSpawn(th);
return th;
}
//---------------------------------------------------------------------------
//
// FUNC P_SpawnMissileAngle
@ -5362,6 +5409,7 @@ int AActor::SpawnHealth()
return (adj <= 0) ? 1 : adj;
}
}
FDropItem *AActor::GetDropItems()
{
unsigned int index = GetClass()->Meta.GetMetaInt (ACMETA_DropItems) - 1;
@ -5373,6 +5421,29 @@ FDropItem *AActor::GetDropItems()
return NULL;
}
fixed_t AActor::GetGravity() const
{
if (flags & MF_NOGRAVITY) return 0;
return fixed_t(level.gravity * Sector->gravity * FIXED2FLOAT(gravity) * 81.92);
}
// killough 11/98:
// Whether an object is "sentient" or not. Used for environmental influences.
// (left precisely the same as MBF even though it doesn't make much sense.)
bool AActor::IsSentient() const
{
return health > 0 || SeeState != NULL;
}
const char *AActor::GetTag(const char *def) const
{
if (Tag != NAME_None) return Tag.GetChars();
else if (def) return def;
else return GetClass()->TypeName.GetChars();
}
//----------------------------------------------------------------------------
//
// DropItem handling
@ -5403,3 +5474,68 @@ int StoreDropItemChain(FDropItem *chain)
return DropItemList.Push (chain) + 1;
}
void PrintMiscActorInfo(AActor * query)
{
if (query)
{
int flagi;
int querystyle = STYLE_Count;
for (int style = STYLE_None; style < STYLE_Count; ++style)
{ // Check for a legacy render style that matches.
if (LegacyRenderStyles[style] == query->RenderStyle)
{
querystyle = style;
break;
}
}
static const char * renderstyles[]= {"None", "Normal", "Fuzzy", "SoulTrans",
"OptFuzzy", "Stencil", "Translucent", "Add", "Shaded", "TranslucentStencil"};
/*
Printf("%s %x has the following flags:\n\tflags1: %x",
query->GetNameTag().GetChars(), query, query->flags);
*/
for (flagi = 0; flagi < 31; flagi++)
if (query->flags & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags));
Printf("\n\tflags2: %x", query->flags2);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags2 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags2));
Printf("\n\tflags3: %x", query->flags3);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags3 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags3));
Printf("\n\tflags4: %x", query->flags4);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags4 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags4));
Printf("\n\tflags5: %x", query->flags5);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags5 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags5));
Printf("\n\tflags6: %x", query->flags6);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags6 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags6));
/*
Printf("\nIts bounce style and factors are %s and f:%f, w:%f; its bounce flags are:\n\tflagsb: %x",
bouncestyles[bt], FIXED2FLOAT(query->bouncefactor),
FIXED2FLOAT(query->wallbouncefactor), query->BounceFlags);
for (flagi = 0; flagi < 31; flagi++)
if (query->BounceFlags & 1<<flagi) Printf(" %s", flagnamesb[flagi]);
*/
Printf("\nIts render style is %i:%s with alpha %f and the following render flags:\n\tflagsr: %x",
querystyle, (querystyle < STYLE_Count ? renderstyles[querystyle] : "Unknown"),
FIXED2FLOAT(query->alpha), query->renderflags);
/*
for (flagi = 0; flagi < 31; flagi++)
if (query->renderflags & 1<<flagi) Printf(" %s", flagnamesr[flagi]);
*/
Printf("\nIts thing special and arguments are %s(%i, %i, %i, %i, %i), and its specials are %i and %i.",
LineSpecialsInfo[query->special]->name, query->args[0], query->args[1],
query->args[2], query->args[3], query->args[4],
query->special1, query->special2);
Printf("\nIts coordinates are x: %f, y: %f, z:%f, floor:%f, ceiling:%f.",
FIXED2FLOAT(query->x), FIXED2FLOAT(query->y), FIXED2FLOAT(query->z),
FIXED2FLOAT(query->floorz), FIXED2FLOAT(query->ceilingz));
Printf("\nIts speed is %f and velocity is x:%f, y:%f, z:%f, combined:%f.\n",
FIXED2FLOAT(query->Speed), FIXED2FLOAT(query->velx), FIXED2FLOAT(query->vely), FIXED2FLOAT(query->velz),
sqrt(pow(FIXED2FLOAT(query->velx), 2) + pow(FIXED2FLOAT(query->vely), 2) + pow(FIXED2FLOAT(query->velz), 2)));
}
}

View file

@ -419,11 +419,8 @@ void extsector_t::Serialize(FArchive &arc)
FArchive &operator<< (FArchive &arc, side_t::part &p)
{
arc << p.xoffset << p.yoffset << p.interpolation << p.texture;// << p.Light;
if (SaveVersion >= 1645)
{
arc << p.xscale << p.yscale;
}
arc << p.xoffset << p.yoffset << p.interpolation << p.texture
<< p.xscale << p.yscale;// << p.Light;
return arc;
}

View file

@ -1737,7 +1737,17 @@ void DPusher::Tick ()
while ((thing = it.Next()))
{
if ((thing->flags2 & MF2_WINDTHRUST) && !(thing->flags & MF_NOCLIP))
// Normal ZDoom is based only on the WINDTHRUST flag, with the noclip cheat as an exemption.
bool pusharound = ((thing->flags2 & MF2_WINDTHRUST) && !(thing->flags & MF_NOCLIP));
// MBF allows any sentient or shootable thing to be affected, but players with a fly cheat aren't.
if (compatflags & COMPATF_MBFMONSTERMOVE)
{
pusharound = ((pusharound || (thing->IsSentient()) || (thing->flags & MF_SHOOTABLE)) // Add categories here
&& (!(thing->player && (thing->flags & (MF_NOGRAVITY))))); // Exclude flying players here
}
if ((pusharound) )
{
int sx = m_X;
int sy = m_Y;

View file

@ -424,11 +424,8 @@ void APlayerPawn::Serialize (FArchive &arc)
<< InvFirst
<< InvSel
<< MorphWeapon
<< DamageFade;
if (SaveVersion >= 1695)
{
arc << PlayerFlags;
}
<< DamageFade
<< PlayerFlags;
}
//===========================================================================
@ -1653,7 +1650,7 @@ void P_MovePlayer (player_t *player)
mo->angle += cmd->ucmd.yaw << 16;
}
onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ);
onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF);
// killough 10/98:
//

View file

@ -746,6 +746,7 @@ struct sector_t
fixed_t transdoorheight; // for transparent door hacks
int subsectorcount; // list of subsectors
subsector_t ** subsectors;
fixed_t vboheight[2];
float GetFloorReflect() { return gl_plane_reflection_i? floor_reflect : 0; }
float GetCeilingReflect() { return gl_plane_reflection_i? ceiling_reflect : 0; }
@ -1015,6 +1016,7 @@ struct subsector_t
bool degenerate;
char hacked; // 1: is part of a render hack
// 2: has one-sided walls
int vboindex[2];
};
//

View file

@ -3,5 +3,5 @@
// This file was automatically generated by the
// updaterevision tool. Do not edit by hand.
#define ZD_SVN_REVISION_STRING "1814"
#define ZD_SVN_REVISION_NUMBER 1814
#define ZD_SVN_REVISION_STRING "1831"
#define ZD_SVN_REVISION_NUMBER 1831

View file

@ -5,6 +5,7 @@
#include "info.h"
#include "s_sound.h"
#include "sc_man.h"
#include "cmdlib.h"
class FScanner;
@ -25,6 +26,9 @@ struct FFlagDef
FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2);
void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int index);
const char *GetFlagName(int flagnum, int flagoffset);
#define FLAG_NAME(flagnum, flagvar) GetFlagName(flagnum, myoffsetof(AActor, flagvar))
//==========================================================================
@ -44,6 +48,8 @@ enum EStateDefineFlags
SDF_WAIT = 3,
SDF_LABEL = 4,
SDF_INDEX = 5,
SDF_MASK = 7,
SDF_DEHACKED = 8, // Identify a state as having been modified by a dehacked lump
};
struct FStateDefine
@ -120,7 +126,7 @@ public:
~FStateExpressions();
int Add(FxExpression *x, const PClass *o, bool c);
int Reserve(int num, const PClass *cls);
void Set(int num, FxExpression *x);
void Set(int num, FxExpression *x, bool cloned = false);
void Copy(int dest, int src, int cnt);
int ResolveAll();
FxExpression *Get(int no);

View file

@ -560,12 +560,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfArmorType)
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
{
ACTION_PARAM_START(5);
ACTION_PARAM_START(7);
ACTION_PARAM_INT(damage, 0);
ACTION_PARAM_INT(distance, 1);
ACTION_PARAM_BOOL(hurtSource, 2);
ACTION_PARAM_BOOL(alert, 3);
ACTION_PARAM_INT(fulldmgdistance, 4);
ACTION_PARAM_INT(nails, 5);
ACTION_PARAM_INT(naildamage, 6);
if (damage < 0) // get parameters from metadata
{
@ -578,6 +580,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
{
if (distance <= 0) distance = damage;
}
// NailBomb effect, from SMMU but not from its source code: instead it was implemented and
// generalized from the documentation at http://www.doomworld.com/eternity/engine/codeptrs.html
if (nails)
{
angle_t ang;
for (int i = 0; i < nails; i++)
{
ang = i*(ANGLE_MAX/nails);
// Comparing the results of a test wad with Eternity, it seems A_NailBomb does not aim
P_LineAttack (self, ang, MISSILERANGE, 0,
//P_AimLineAttack (self, ang, MISSILERANGE),
naildamage, NAME_None, NAME_BulletPuff);
}
}
P_RadiusAttack (self, self->target, damage, distance, self->DamageType, hurtSource, true, fulldmgdistance);
if (self->z <= self->floorz + (distance<<FRACBITS))
@ -1675,6 +1692,47 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Print)
}
}
//===========================================================================
//
// A_PrintBold
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PrintBold)
{
ACTION_PARAM_START(3);
ACTION_PARAM_STRING(text, 0);
ACTION_PARAM_FLOAT(time, 1);
ACTION_PARAM_NAME(fontname, 2);
float saved = con_midtime;
FFont *font = NULL;
if (fontname != NAME_None)
{
font = V_GetFont(fontname);
}
if (time > 0)
{
con_midtime = time;
}
C_MidPrintBold(font != NULL ? font : SmallFont, text);
con_midtime = saved;
}
//===========================================================================
//
// A_Log
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Log)
{
ACTION_PARAM_START(1);
ACTION_PARAM_STRING(text, 0);
Printf("%s\n", text);
}
//===========================================================================
//
@ -2081,6 +2139,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn)
{
AActor *defs = self->GetDefault();
self->health = defs->health;
// [KS] Don't keep target, because it could be self if the monster committed suicide
self->target = NULL;
self->LastHeard = NULL;
self->flags = (defs->flags & ~MF_FRIENDLY) | (self->flags & MF_FRIENDLY);
self->flags2 = defs->flags2;
@ -2769,3 +2831,92 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetArg)
self->args[pos] = value;
}
}
//===========================================================================
//
// A_SetSpecial
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpecial)
{
ACTION_PARAM_START(6);
ACTION_PARAM_INT(spec, 0);
ACTION_PARAM_INT(arg0, 1);
ACTION_PARAM_INT(arg1, 2);
ACTION_PARAM_INT(arg2, 3);
ACTION_PARAM_INT(arg3, 4);
ACTION_PARAM_INT(arg4, 5);
self->special = spec;
self->args[0] = arg0;
self->args[1] = arg1;
self->args[2] = arg2;
self->args[3] = arg3;
self->args[4] = arg4;
}
//===========================================================================
//
// A_SetVar
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserVar)
{
ACTION_PARAM_START(2);
ACTION_PARAM_INT(pos, 0);
ACTION_PARAM_INT(value, 1);
if (pos < 0 || pos > 9)
return;
// Set the value of the specified arg
self->uservar[pos] = value;
}
//===========================================================================
//
// A_Turn
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Turn)
{
ACTION_PARAM_START(1);
ACTION_PARAM_ANGLE(angle, 0);
self->angle += angle;
}
//===========================================================================
//
// A_LineEffect
//
// This allows linedef effects to be activated inside deh frames.
//
//===========================================================================
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld);
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LineEffect)
{
ACTION_PARAM_START(2);
ACTION_PARAM_INT(special, 0);
ACTION_PARAM_INT(tag, 1);
line_t junk; maplinedef_t oldjunk;
bool res = false;
if (!(self->flags6 & MF6_LINEDONE)) // Unless already used up
{
if ((oldjunk.special = special)) // Linedef type
{
oldjunk.tag = tag; // Sector tag for linedef
P_TranslateLineDef(&junk, &oldjunk); // Turn into native type
res = !!LineSpecials[junk.special](NULL, self, false, junk.args[0],
junk.args[1], junk.args[2], junk.args[3], junk.args[4]);
if (res && !(junk.flags & ML_REPEAT_SPECIAL)) // If only once,
self->flags6 |= MF6_LINEDONE; // no more for this thing
}
}
ACTION_SET_RESULT(res);
}

View file

@ -214,6 +214,10 @@ static FFlagDef ActorFlags[]=
DEFINE_FLAG(MF6, DONTHARMSPECIES, AActor, flags6),
DEFINE_FLAG(MF6, STEPMISSILE, AActor, flags6),
DEFINE_FLAG(MF6, NOTELEFRAG, AActor, flags6),
DEFINE_FLAG(MF6, TOUCHY, AActor, flags6),
DEFINE_FLAG(MF6, CANJUMP, AActor, flags6),
DEFINE_FLAG(MF6, JUMPDOWN, AActor, flags6),
DEFINE_FLAG(MF6, VULNERABLE, AActor, flags6),
// Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
@ -391,6 +395,24 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2)
}
//==========================================================================
//
// Gets the name of an actor flag
//
//==========================================================================
const char *GetFlagName(int flagnum, int flagoffset)
{
for(int i=0; i<countof(ActorFlags); i++)
{
if (ActorFlags[i].flagbit == flagnum && ActorFlags[i].structoffset == flagoffset)
{
return ActorFlags[i].name;
}
}
return "(unknown)"; // return something printable
}
//==========================================================================
//
// Find a property by name using a binary search
@ -534,7 +556,6 @@ static int STACK_ARGS varcmp(const void * a, const void * b)
return stricmp(A->name, B->name);
}
//==========================================================================
//
// Initialization

View file

@ -62,6 +62,8 @@ DEFINE_MEMBER_VARIABLE(floorz, AActor)
DEFINE_MEMBER_VARIABLE(health, AActor)
DEFINE_MEMBER_VARIABLE(pitch, AActor)
DEFINE_MEMBER_VARIABLE(special, AActor)
DEFINE_MEMBER_VARIABLE(special1, AActor)
DEFINE_MEMBER_VARIABLE(special2, AActor)
DEFINE_MEMBER_VARIABLE(tid, AActor)
DEFINE_MEMBER_VARIABLE(TIDtoHate, AActor)
DEFINE_MEMBER_VARIABLE(waterlevel, AActor)
@ -75,6 +77,8 @@ DEFINE_MEMBER_VARIABLE_ALIAS(momx, velx, AActor)
DEFINE_MEMBER_VARIABLE_ALIAS(momy, vely, AActor)
DEFINE_MEMBER_VARIABLE_ALIAS(momz, velz, AActor)
DEFINE_MEMBER_VARIABLE(Damage, AActor)
DEFINE_MEMBER_VARIABLE(Score, AActor)
DEFINE_MEMBER_VARIABLE(uservar, AActor)
//==========================================================================
//
@ -2812,13 +2816,13 @@ int FStateExpressions::Reserve(int num, const PClass *cls)
//
//==========================================================================
void FStateExpressions::Set(int num, FxExpression *x)
void FStateExpressions::Set(int num, FxExpression *x, bool cloned)
{
if (num >= 0 && num < int(Size()))
{
assert(expressions[num].expr == NULL || expressions[num].cloned);
expressions[num].expr = x;
expressions[num].cloned = false;
expressions[num].cloned = cloned;
}
}

View file

@ -302,7 +302,7 @@ DEFINE_PROPERTY(skip_super, 0, Actor)
DEFINE_PROPERTY(tag, S, Actor)
{
PROP_STRING_PARM(str, 0);
info->Class->Meta.SetMetaString(AMETA_StrifeName, str);
defaults->Tag = str;
}
//==========================================================================
@ -849,10 +849,11 @@ DEFINE_PROPERTY(bloodtype, Sss, Actor)
//==========================================================================
DEFINE_PROPERTY(bouncetype, S, Actor)
{
static const char *names[] = { "None", "Doom", "Heretic", "Hexen", "DoomCompat", "HereticCompat", "HexenCompat", NULL };
static const BYTE flags[] = { BOUNCE_None,
static const char *names[] = { "None", "Doom", "Heretic", "Hexen", "DoomCompat", "HereticCompat", "HexenCompat", "Grenade", "Classic", NULL };
static const int flags[] = { BOUNCE_None,
BOUNCE_Doom, BOUNCE_Heretic, BOUNCE_Hexen,
BOUNCE_DoomCompat, BOUNCE_HereticCompat, BOUNCE_HexenCompat };
BOUNCE_DoomCompat, BOUNCE_HereticCompat, BOUNCE_HexenCompat,
BOUNCE_Grenade, BOUNCE_Classic, };
PROP_STRING_PARM(id, 0);
int match = MatchString(id, names);
if (match < 0)
@ -1294,7 +1295,6 @@ DEFINE_CLASS_PROPERTY(pickupsound, S, Inventory)
//==========================================================================
DEFINE_CLASS_PROPERTY(pickupannouncerentry, S, Inventory)
{
PROP_STRING_PARM(str, 0);
}
//==========================================================================

View file

@ -66,7 +66,7 @@
// Protocol version used in demos.
// Bump it if you change existing DEM_ commands or add new ones.
// Otherwise, it should be safe to leave it alone.
#define DEMOGAMEVERSION 0x211
#define DEMOGAMEVERSION 0x212
// Minimum demo version we can play.
// Bump it whenever you change or remove existing DEM_ commands.
@ -77,7 +77,7 @@
// SAVESIG should match SAVEVER.
// MINSAVEVER is the minimum level snapshot version that can be loaded.
#define MINSAVEVER 1643
#define MINSAVEVER 1823
#if ZD_SVN_REVISION_NUMBER < MINSAVEVER
// Never write a savegame with a version lower than what we need

View file

@ -26,6 +26,7 @@ ACTOR Actor native //: Thinker
native fixed_t alpha;
native angle_t angle;
native int args[5];
native int uservar[10];
native fixed_t ceilingz;
native fixed_t floorz;
native int health;
@ -44,6 +45,11 @@ ACTOR Actor native //: Thinker
native fixed_t momx; // alias for velx
native fixed_t momy; // alias for vely
native fixed_t momz; // alias for velz
native int score;
// Meh, MBF redundant functions. Only for DeHackEd support.
action native A_Turn(float angle = 0);
action native A_LineEffect(int boomspecial = 0, int tag = 0);
// End of MBF redundant functions.
action native A_MonsterRail();
action native A_BFGSpray(class<Actor> spraytype = "BFGExtra", int numrays = 40, int damagecount = 15);
@ -80,6 +86,7 @@ ACTOR Actor native //: Thinker
action native A_HeadAttack();
action native A_BruisAttack();
action native A_SkullAttack(float speed = 20);
action native A_BetaSkullAttack();
action native A_Metal();
action native A_SpidRefire();
action native A_BabyMetal();
@ -100,7 +107,7 @@ ACTOR Actor native //: Thinker
action native A_BrainExplode();
action native A_Die(name damagetype = "none");
action native A_Detonate();
action native A_Mushroom(class<Actor> spawntype = "FatShot", int numspawns = 0, int flags = 0);
action native A_Mushroom(class<Actor> spawntype = "FatShot", int numspawns = 0, int flags = 0, float vrange = 4.0, float hrange = 0.5);
action native A_CallSpecial(int special, int arg1=0, int arg2=0, int arg3=0, int arg4=0, int arg5=0);
action native A_SetFloorClip();
@ -164,7 +171,7 @@ ACTOR Actor native //: Thinker
action native A_MeleeAttack();
action native A_ComboAttack();
action native A_BulletAttack();
action native A_PlaySound(sound whattoplay, int slot = CHAN_BODY, float volume = 1.0, bool looping = false, float attenuation = ATTN_NORM);
action native A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, float volume = 1.0, bool looping = false, float attenuation = ATTN_NORM);
action native A_PlayWeaponSound(sound whattoplay);
action native A_FLoopActiveSound();
action native A_LoopActiveSound();
@ -172,7 +179,7 @@ ACTOR Actor native //: Thinker
action native A_PlaySoundEx(sound whattoplay, coerce name slot, bool looping = false, int attenuation = 0);
action native A_StopSoundEx(coerce name slot);
action native A_SeekerMissile(int threshold, int turnmax);
action native A_Jump(int chance, state label, ...);
action native A_Jump(int chance = 256, state label, ...);
action native A_CustomMissile(class<Actor> missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0);
action native A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, bool aimfacing = false);
action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, bool aim = false, float maxdiff = 0, class<Actor> pufftype = "BulletPuff");
@ -182,9 +189,11 @@ ACTOR Actor native //: Thinker
action native A_JumpIfArmorType(string Type, state label, int amount = 1);
action native A_GiveInventory(class<Inventory> itemtype, int amount = 0);
action native A_TakeInventory(class<Inventory> itemtype, int amount = 0);
action native A_SpawnItem(class<Actor> itemtype, float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false);
action native A_SpawnItem(class<Actor> itemtype = "Unknown", float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false);
action native A_SpawnItemEx(class<Actor> itemtype, float xofs = 0, float yofs = 0, float zofs = 0, float xvel = 0, float yvel = 0, float zvel = 0, float angle = 0, int flags = 0, int failchance = 0);
action native A_Print(string whattoprint, float time = 0, string fontname = "");
action native A_PrintBold(string whattoprint, float time = 0, string fontname = "");
action native A_Log(string whattoprint);
action native A_SetTranslucent(float alpha, int style = 0);
action native A_FadeIn(float reduce = 0.1);
action native A_FadeOut(float reduce = 0.1, bool remove = true);
@ -215,11 +224,11 @@ ACTOR Actor native //: Thinker
action native A_GiveToTarget(class<Inventory> itemtype, int amount = 0);
action native A_TakeFromTarget(class<Inventory> itemtype, int amount = 0);
action native A_CountdownArg(int argnum);
action native A_CustomMeleeAttack(int damage, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true);
action native A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true);
action native A_CustomComboAttack(class<Actor> missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true);
action native A_Burst(class<Actor> chunktype);
action native A_RadiusThrust(int force = 128, int distance = -1, bool affectsource = true);
action native A_Explode(int damage = -1, int distance = -1, bool hurtsource = true, bool alert = false, int fulldamagedistance = 0);
action native A_Explode(int damage = -1, int distance = -1, bool hurtsource = true, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10);
action native A_Stop();
action native A_Respawn(bool fog = true);
action native A_BarrelDestroy();
@ -245,11 +254,13 @@ ACTOR Actor native //: Thinker
action native A_DropWeaponPieces(class<Actor> p1, class<Actor> p2, class<Actor> p3);
action native A_PigPain ();
action native A_MonsterRefire(int chance, state label);
action native A_SetAngle(float angle);
action native A_SetAngle(float angle = 0);
action native A_SetPitch(float pitch);
action native A_ScaleVelocity(float scale);
action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0);
action native A_SetArg(int pos, int value);
action native A_SetUserVar(int pos, int value);
action native A_SetSpecial(int spec, int arg0, int arg1, int arg2, int arg3, int arg4);
States
{
@ -264,6 +275,9 @@ ACTOR Actor native //: Thinker
"----" A 5 A_GenericFreezeDeath
"----" A 1 A_FreezeDeathChunks
Wait
GenericCrush:
POL5 A -1
Stop
}
}

View file

@ -0,0 +1,45 @@
ACTOR Dog 888
{
Game Doom
Health 500
Speed 10
PainChance 180
Radius 12
Height 28
Mass 100
Monster
+JUMPDOWN
ActiveSound "dog/active"
AttackSound "dog/attack"
DeathSound "dog/death"
PainSound "dog/pain"
SeeSound "dog/sight"
Obituary "$OB_DOG"
States
{
Spawn:
DOGS AB 10 A_Look
Loop
See:
DOGS AABBCCDD 2 A_Chase
Loop
Melee:
DOGS EF 8 A_FaceTarget
DOGS G 8 A_SargAttack
Goto See
Pain:
DOGS H 2
DOGS H 2 A_Pain
Goto See
Death:
DOGS I 8
DOGS J 8 A_Scream
DOGS K 4
DOGS L 4 A_Fall
DOGS M 4
DOGS N -1
Raise:
DOGS NMLKJI 5
Goto See
}
}

View file

@ -77,5 +77,34 @@ ACTOR DoomUnusedStates
stop
PLAY S -1
stop
TNT: // MBF compatibility
TNT1 A -1
Loop
}
}
// MBF Beta emulation items
Actor EvilSceptre : ScoreItem 2016
{
Game Doom
Inventory.PickupMessage "$BETA_BONUS3"
States
{
Spawn:
BON3 A 6
Loop
}
}
Actor UnholyBible : ScoreItem 2017
{
Game Doom
Inventory.PickupMessage "$BETA_BONUS4"
States
{
Spawn:
BON4 A 6
Loop
}
}

View file

@ -342,12 +342,13 @@ ACTOR Rocket
// --------------------------------------------------------------------------
//
// Grenade -- Taken and adapted from Skulltag
// Grenade -- Taken and adapted from Skulltag, with MBF stuff added to it
//
// --------------------------------------------------------------------------
ACTOR Grenade
{
Game Doom
SpawnID 216
Radius 8
Height 8
@ -376,6 +377,17 @@ ACTOR Grenade
MISL C 6 Bright
MISL D 4 Bright
Stop
Grenade:
MISL A 1000 A_Die
Wait
Detonate:
MISL B 4 A_Scream
MISL C 6 A_Detonate
MISL D 10
Stop
Mushroom:
MISL B 8 A_Mushroom
Goto Death+1
}
}
@ -445,8 +457,42 @@ ACTOR PlasmaBall
Stop
}
}
// --------------------------------------------------------------------------
//
// BFG 2704
//
// --------------------------------------------------------------------------
ACTOR PlasmaBall1 : PlasmaBall
{
Damage 4
BounceType "Classic"
BounceFactor 1.0
Obituary "$OB_MPBFG_MBF"
States
{
Spawn:
PLS1 AB 6 Bright
Loop
Death:
PLS1 CDEFG 4 Bright
Stop
}
}
ACTOR PlasmaBall2 : PlasmaBall1
{
States
{
Spawn:
PLS2 AB 6 Bright
Loop
Death:
PLS2 CDE 4 Bright
Stop
}
}
// --------------------------------------------------------------------------
//
@ -489,6 +535,12 @@ ACTOR BFG9000 : DoomWeapon 2006
Spawn:
BFUG A -1
Stop
OldFire:
BFGG A 10 A_BFGsound
BFGG BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB 1 A_FireOldBFG
BFGG B 0 A_Light0
BFGG B 20 A_ReFire
Goto Ready
}
}

View file

@ -49,3 +49,33 @@ ACTOR LostSoul 3006
Stop
}
}
Actor BetaSkull : LostSoul 9037
{
States
{
Spawn:
SKUL A 10 A_Look
Loop
See:
SKUL BCDA 5 A_Chase
Loop
Missile:
SKUL E 4 A_FaceTarget
SKUL F 5 A_BetaSkullAttack
SKUL F 4
Goto See
Pain:
SKUL G 4
SKUL H 2 A_Pain
SKUL I 4
Goto See
Death:
SKUL JKLM 5
SKUL N 5 A_Scream
SKUL O 5
SKUL P 5 A_Fall
SKUL Q 5 A_Stop
Wait
}
}

View file

@ -35,6 +35,7 @@ ACTOR Inventory native
action native A_RailWait();
action native A_BFGsound();
action native A_FireBFG();
action native A_FireOldBFG();
action native A_ReFire();
action native A_ClearReFire();
action native A_CheckReload();
@ -70,6 +71,14 @@ ACTOR Inventory native
}
}
Actor ScoreItem : Inventory native
{
Height 10
+COUNTITEM
Inventory.Amount 1
+Inventory.ALWAYSPICKUP
}
Actor Ammo : Inventory native
{
+INVENTORY.KEEPDEPLETED
@ -161,6 +170,7 @@ ACTOR PowerStrength : Powerup native
ACTOR PowerInvisibility : Powerup native
{
+SHADOW
Powerup.Duration -60
Powerup.Strength 80
Powerup.Mode "Fuzzy"

View file

@ -87,8 +87,7 @@ ACTOR RealGibs
States
{
Spawn:
POL5 A -1
Stop
goto GenericCrush
}
}
@ -137,6 +136,7 @@ ACTOR RandomSpawner native
+NOBLOCKMAP
+NOSECTOR
+NOGRAVITY
+THRUACTORS
}
// Fast projectiles -----------------------------------------------------------

View file

@ -78,3 +78,15 @@ F84AB4557464A383E93F37CD3A82AC48 // MM2 map03
{
anybossdeath
}
// Arch-Vile ghost monster effect is used by the following maps
145C4DFCF843F2B92C73036BA0E1D98A // Hell Revealed map26
5379C080299EB961792B50AD96821543 // Hell to Pay map14
7837B5334A277F107515D649BCEFB682 // Hell to Pay map22
2EEB1E12FA9F9545DE9D99990A4A78E5 // Icarus map24
65A53A09A09525AE42EA210BF879CD37 // Plutonia 2 map32
2499CF9A9351BE9BC4E9C66FC9F291A7 // Requiem map23
{
corpsegibs
vileghosts
}

View file

@ -522,6 +522,78 @@ decal RevenantScorch
randomflipy
}
/***** MBF OldBFG plasma scorches ******************************************/
decal GreenPlasmaScorch1
{
pic PLS1A0
add 1.0
fullbright
animator GoAway
lowerdecal DoomImpScorch
}
decal GreenPlasmaScorch2
{
pic PLS1B0
add 1.0
fullbright
animator GoAway
lowerdecal DoomImpScorch
}
decal GreenPlasmaScorch3
{
pic PLS1C0
add 1.0
fullbright
animator GoAway
lowerdecal DoomImpScorch
}
decal GreenPlasmaScorch4
{
pic PLS1D0
add 1.0
fullbright
animator GoAway
lowerdecal DoomImpScorch
}
decalgroup GreenPlasmaScorch
{
GreenPlasmaScorch1 1
GreenPlasmaScorch2 1
GreenPlasmaScorch3 1
GreenPlasmaScorch4 1
}
decal RedPlasmaScorch1
{
pic PLS2A0
add 1.0
fullbright
animator GoAway
lowerdecal PlasmaScorchLower1
}
decal RedPlasmaScorch2
{
pic PLS2B0
add 1.0
fullbright
animator GoAway
lowerdecal PlasmaScorchLower2
}
decalgroup RedPlasmaScorch
{
RedPlasmaScorch1 1
RedPlasmaScorch2 1
}
// Graf Zahl provided definitions for the other games.
/***** Crossbow ************************************************************/
@ -975,6 +1047,8 @@ generator Chaingun BulletChip
generator PlasmaBall PlasmaScorch
generator Rocket Scorch
generator BFGBall BFGLightning
generator PlasmaBall1 GreenPlasmaScorch
generator PlasmaBall2 RedPlasmaScorch
generator MarinePistol BulletChip
generator MarineShotgun BulletChip

View file

@ -45,6 +45,7 @@
#include "actors/doom/spidermaster.txt"
#include "actors/doom/keen.txt"
#include "actors/doom/bossbrain.txt"
#include "actors/doom/dog.txt"
#include "actors/doom/deadthings.txt"
#include "actors/doom/doomammo.txt"

View file

@ -172,15 +172,15 @@ ActionList
Chase, Chase, Chase, Chase, Chase, Chase, Chase, Chase,
FaceTarget, FaceTarget, SargAttack, NULL, Pain, NULL, Scream,
NULL, Fall, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, BFGsound,
NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/,
NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/,
NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/,
NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/,
NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/, NULL/*FireOldBFG*/,
FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG,
FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG,
FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG,
FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG,
FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG, FireOldBFG,
Light0, ReFire, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
Look, Chase, Chase, Chase, CHase, FaceTarget,
NULL/*BetaSkullAttack*/, NULL, NULL, Pain, NULL,
Look, Chase, Chase, Chase, Chase, FaceTarget,
BetaSkullAttack, NULL, NULL, Pain, NULL,
NULL, NULL, NULL, NULL, Scream, NULL, Fall, Stop,
Mushroom
};
@ -239,7 +239,17 @@ CodePConv
733, 734, 735, 736, 737, 738, 739, 740, 741, 743,
745, 746, 750, 751, 766, 774, 777, 779, 780, 783,
784, 785, 786, 787, 788, 789, 790, 791, 792, 793,
794, 795, 796, 797, 798, 801, 809, 811
794, 795, 796, 797, 798, 801, 809, 811, // 448th
// Now for the 74 MBF states with code pointers
968, 969, 970, 972, 973, 974, 975, 976, 977, 978,
979, 980, 981, 982, 983, 984, 986, 988, 990, 999,
1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007,
1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015,
1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023,
1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031,
1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039,
1040, 1041, 1056, 1057, 1058, 1059, 1060, 1061,
1062, 1065, 1071, 1073, 1074, 1075 // Total: 522
};
// Sprite names in the order Doom originally had them.
@ -258,7 +268,8 @@ OrgSprNames
POL3,POL1,POL6,GOR2,GOR3,GOR4,GOR5,SMIT,COL1,COL2,
COL3,COL4,CAND,CBRA,COL6,TRE1,TRE2,ELEC,CEYE,FSKU,
COL5,TBLU,TGRN,TRED,SMBT,SMGT,SMRT,HDB1,HDB2,HDB3,
HDB4,HDB5,HDB6,POB1,POB2,BRS1,TLMP,TLP2
HDB4,HDB5,HDB6,POB1,POB2,BRS1,TLMP,TLP2,
TNT1,DOGS,PLS1,PLS2,BON3,BON4 // Added by MBF
};
StateMap
@ -360,7 +371,7 @@ StateMap
BloodyTwitch, Spawn, 4, // S_BLOODYTWITCH - S_BLOODYTWITCH4
DoomUnusedStates, Label2, 2, // S_DEADTORSO - S_DEADBOTTOM
HeadsOnAStick, Spawn, 1, // S_HEADSONSTICK
RealGibs, Spawn, 1, // S_GIBS
Actor, GenericCrush, 1, // S_GIBS
HeadOnAStick, Spawn, 1, // S_HEADONASTICK
HeadCandles, Spawn, 2, // S_HEADCANDLES - S_HEADCANDLES2
DeadStick, Spawn, 1, // S_DEADSTICK
@ -399,7 +410,18 @@ StateMap
SmallBloodPool, Spawn, 1, // S_SMALLPOOL
BrainStem, Spawn, 1, // S_BRAINSTEM
TechLamp, Spawn, 4, // S_TECHLAMP - S_TECHLAMP4
TechLamp2, Spawn, 4 // S_TECH2LAMP - S_TECH2LAMP4
TechLamp2, Spawn, 4, // S_TECH2LAMP - S_TECH2LAMP4
DoomUnusedStates, TNT, 1, // [MBF] S_TNT1 967
Grenade, Grenade, 1, // [MBF] S_GRENADE 968
Grenade, Detonate, 3, // [MBF] S_DETONATE - S_DETONATE3 969-971
Dog, Spawn, 27, // [MBF] S_DOGS_STND - S_DOGS_RAISE6 972-998
BFG9000, OldFire, 43, // [MBF] S_OLDBFG1 - S_OLDBFG43 999-1041
PlasmaBall1, Spawn, 7, // [MBF] S_PLS1BALL - S_PLS1EXP5 1042-1048
PlasmaBall2, Spawn, 5, // [MBF] S_PLS2BALL - S_PLS2BALLX3 1049-1053
EvilSceptre, Spawn, 1, // [MBF] S_BON3 1054
UnholyBible, Spawn, 1, // [MBF] S_BON4 1055
BetaSkull, Spawn, 19, // [MBF] S_BSKUL_STND - S_BSKUL_DIE8 1056-1074
Grenade, Mushroom, 1, // [MBF] S_MUSHROOM 1075
};
// Sound equivalences. When a patch tries to change a sound, use these sound names.
@ -654,7 +676,16 @@ InfoNames
HangTNoBrain,
ColonGibs,
SmallBloodPool,
BrainStem
BrainStem,
// Boom additional actors:
PointPusher,
PointPuller,
// MBF additional actors:
Dog,
PlasmaBall1,
PlasmaBall2,
EvilSceptre,
UnholyBible
};
ThingBits
@ -672,6 +703,7 @@ ThingBits
10, 0, DROPOFF,
11, 0, PICKUP,
12, 0, NOCLIP,
13, 0, SLIDE,
14, 0, FLOAT,
15, 0, TELEPORT,
16, 0, MISSILE,
@ -691,7 +723,10 @@ ThingBits
28, 0, UNUSED2, // BOOM compatibility
29, 0, UNUSED3, // BOOM compatibility
30, 0, UNUSED4, // BOOM compatibility
2, 2, TRANSLUCENT, // BOOM compatibility?
28, 0, TOUCHY, // MBF compatibility
29, 0, BOUNCES, // MBF compatibility
30, 0, FRIEND, // MBF compatibility
31, 0, TRANSLUCENT, // BOOM compatibility
30, 0, STEALTH,
1, 2, TRANSLUC25,
2, 2, TRANSLUC50,
@ -773,3 +808,22 @@ WeaponNames
Chainsaw,
SuperShotgun
};
// Codepointer aliases
// The idea is that, rather than add redundant codepointers for compatibility,
// or codepointers that would require to transform ZDoom's underlying architecture
// because they refer to things, sounds or states by their DeHackEd numbers,
// we can translate their parameters and transform them into standard functions
// when parsing a DEHACKED lump.
Aliases
{
A_Mushroom, A_Mushroom, 5,
A_Spawn, A_SpawnItem, 5,
A_Turn, A_Turn, 1,
A_Face, A_SetAngle, 1,
A_Scratch, A_CustomMeleeAttack, 5, // 19 characters for "A_CustomMeleeAttack"!
A_PlaySound, A_PlaySound, 5, // A function name any longer and the definition
A_RandomJump, A_Jump, 3, // for CodePointerAlias would need to be updated.
A_LineEffect, A_LineEffect, 2,
A_NailBomb, A_Explode, 7,
};

View file

@ -115,6 +115,10 @@ PD_YELLOWSO = "You need a yellow skull to activate this object";
GGSAVED = "game saved.";
HUSTR_MSGU = "[Message unsent]";
PICKUP_PISTOL_DROPPED = "Picked up a pistol.";
BETA_BONUS1 = "You pick up a demonic dagger.";
BETA_BONUS2 = "You pick up a skullchest.";
BETA_BONUS3 = "You pick up an evil sceptre.";
BETA_BONUS4 = "You pick up an unholy bible.";
// Level names
HUSTR_E1M1 = "E1M1: Hangar";
@ -634,6 +638,7 @@ OB_SPIDER = "%o stood in awe of the spider demon.";
OB_BABY = "%o let an arachnotron get %h.";
OB_CYBORG = "%o was splattered by a cyberdemon.";
OB_WOLFSS = "%o met a Nazi.";
OB_DOG = "%o was mauled by a dog.";
OB_CHICKEN = "%o was pecked to death.";
OB_BEAST = "%o was charred by a weredragon.";
@ -707,6 +712,7 @@ OB_MPBFG_BOOM = "%o was splintered by %k's BFG.";
OB_MPBFG_SPLASH = "%o couldn't hide from %k's BFG.";
OB_MPTELEFRAG = "%o was telefragged by %k.";
OB_RAILGUN = "%o was railed by %k.";
OB_MPBFG_MBF = "%o was burned by %k's BFG.";
// Same as OB_MPTELEFRAG, but shown when a monster telefrags you
OB_MONTELEFRAG = "%o was telefragged.";

View file

@ -425,6 +425,13 @@ brain/cube dsboscub
brain/cubeboom dsfirxpl
$alias brain/spawn misc/teleport
// Marine's Best Friend
dog/active dsdgact
dog/attack dsdgatk
dog/death dsdgdth
dog/pain dsdgpain
dog/sight dsdgsit
//============================================================================
//

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 332 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 844 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Some files were not shown because too many files have changed in this diff Show more