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
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
51
src/actor.h
|
@ -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__
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 = §ors[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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
16
src/info.cpp
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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} },
|
||||
};
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
149
src/p_map.cpp
|
@ -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,
|
||||
|
|
392
src/p_mobj.cpp
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
//
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
45
wadsrc/static/actors/doom/dog.txt
Normal 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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 -----------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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.";
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
|
|
BIN
wadsrc/static/sounds/DSDGACT.flac
Normal file
BIN
wadsrc/static/sounds/DSDGATK.flac
Normal file
BIN
wadsrc/static/sounds/DSDGDTH.flac
Normal file
BIN
wadsrc/static/sounds/DSDGPAIN.flac
Normal file
BIN
wadsrc/static/sounds/DSDGSIT.flac
Normal file
BIN
wadsrc/static/sprites/PLS1A0.png
Normal file
After Width: | Height: | Size: 329 B |
BIN
wadsrc/static/sprites/PLS1B0.png
Normal file
After Width: | Height: | Size: 332 B |
BIN
wadsrc/static/sprites/PLS1C0.png
Normal file
After Width: | Height: | Size: 329 B |
BIN
wadsrc/static/sprites/PLS1D0.png
Normal file
After Width: | Height: | Size: 331 B |
BIN
wadsrc/static/sprites/PLS1E0.png
Normal file
After Width: | Height: | Size: 843 B |
BIN
wadsrc/static/sprites/PLS1F0.png
Normal file
After Width: | Height: | Size: 844 B |
BIN
wadsrc/static/sprites/PLS1G0.png
Normal file
After Width: | Height: | Size: 581 B |
BIN
wadsrc/static/sprites/PLS2A0.png
Normal file
After Width: | Height: | Size: 273 B |
BIN
wadsrc/static/sprites/PLS2B0.png
Normal file
After Width: | Height: | Size: 261 B |
BIN
wadsrc/static/sprites/PLS2C0.png
Normal file
After Width: | Height: | Size: 297 B |
BIN
wadsrc/static/sprites/PLS2D0.png
Normal file
After Width: | Height: | Size: 253 B |
BIN
wadsrc/static/sprites/PLS2E0.png
Normal file
After Width: | Height: | Size: 267 B |
BIN
wadsrc/static/sprites/dogs/DOGSA1.png
Normal file
After Width: | Height: | Size: 416 B |
BIN
wadsrc/static/sprites/dogs/DOGSA2A8.png
Normal file
After Width: | Height: | Size: 466 B |
BIN
wadsrc/static/sprites/dogs/DOGSA3A7.png
Normal file
After Width: | Height: | Size: 479 B |
BIN
wadsrc/static/sprites/dogs/DOGSA4A6.png
Normal file
After Width: | Height: | Size: 451 B |
BIN
wadsrc/static/sprites/dogs/DOGSA5.png
Normal file
After Width: | Height: | Size: 387 B |
BIN
wadsrc/static/sprites/dogs/DOGSB1.png
Normal file
After Width: | Height: | Size: 408 B |
BIN
wadsrc/static/sprites/dogs/DOGSB2B8.png
Normal file
After Width: | Height: | Size: 475 B |
BIN
wadsrc/static/sprites/dogs/DOGSB3B7.png
Normal file
After Width: | Height: | Size: 484 B |
BIN
wadsrc/static/sprites/dogs/DOGSB4B6.png
Normal file
After Width: | Height: | Size: 445 B |
BIN
wadsrc/static/sprites/dogs/DOGSB5.png
Normal file
After Width: | Height: | Size: 405 B |