Merge branch 'master' into scripting

Conflicts:
	src/g_shared/a_sharedglobal.h
	src/thingdef/thingdef_codeptr.cpp
	src/thingdef/thingdef_data.cpp
This commit is contained in:
Christoph Oelckers 2015-04-30 12:30:36 +02:00
commit 5f1c4d157c
26 changed files with 327 additions and 120 deletions

View file

@ -1223,10 +1223,17 @@ if( MSVC )
set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /DELAYLOAD:\"openal32.dll\" /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\"") set_target_properties(zdoom PROPERTIES LINK_FLAGS "/MANIFEST:NO /DELAYLOAD:\"fmodex${X64}.dll\" /DELAYLOAD:\"openal32.dll\" /DELAYLOAD:\"libmpg123-0.dll\" /DELAYLOAD:\"libsndfile-1.dll\"")
endif( ZDOOM_GENERATE_MAPFILE ) endif( ZDOOM_GENERATE_MAPFILE )
add_custom_command(TARGET zdoom POST_BUILD if( NO_GENERATOR_EXPRESSIONS )
COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\win32\\zdoom.exe.manifest\" -outputresource:\"$(TargetDir)$(TargetFileName)\"\;\#1 add_custom_command(TARGET zdoom POST_BUILD
COMMENT "Adding manifest..." COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\win32\\zdoom.exe.manifest\" -outputresource:\"$(TargetDir)$(TargetFileName)\"\;\#1
) COMMENT "Adding manifest..."
)
else( NO_GENERATOR_EXPRESSIONS )
add_custom_command(TARGET zdoom POST_BUILD
COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\win32\\zdoom.exe.manifest\" -outputresource:\"$<TARGET_FILE:zdoom>\"\;\#1
COMMENT "Adding manifest..."
)
endif( NO_GENERATOR_EXPRESSIONS )
create_default_target_launcher( zdoom WORKING_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) create_default_target_launcher( zdoom WORKING_DIRECTORY ${ZDOOM_OUTPUT_DIR} )
endif( MSVC ) endif( MSVC )

View file

@ -39,6 +39,7 @@
#include "s_sound.h" #include "s_sound.h"
#include "memarena.h" #include "memarena.h"
#include "g_level.h" #include "g_level.h"
#include "tflags.h"
struct subsector_t; struct subsector_t;
class PClassAmmo; class PClassAmmo;
@ -107,10 +108,9 @@ class PClassAmmo;
// Any questions? // Any questions?
// //
enum
{
// --- mobj.flags --- // --- mobj.flags ---
enum ActorFlag
{
MF_SPECIAL = 0x00000001, // call P_SpecialThing when touched MF_SPECIAL = 0x00000001, // call P_SpecialThing when touched
MF_SOLID = 0x00000002, MF_SOLID = 0x00000002,
MF_SHOOTABLE = 0x00000004, MF_SHOOTABLE = 0x00000004,
@ -154,8 +154,13 @@ enum
MF_STEALTH = 0x40000000, // [RH] Andy Baker's stealth monsters MF_STEALTH = 0x40000000, // [RH] Andy Baker's stealth monsters
MF_ICECORPSE = 0x80000000, // a frozen corpse (for blasting) [RH] was 0x800000 MF_ICECORPSE = 0x80000000, // a frozen corpse (for blasting) [RH] was 0x800000
// --- mobj.flags2 --- // --- dummies for unknown/unimplemented Strife flags ---
MF_STRIFEx8000000 = 0, // seems related to MF_SHADOW
};
// --- mobj.flags2 ---
enum ActorFlag2
{
MF2_DONTREFLECT = 0x00000001, // this projectile cannot be reflected MF2_DONTREFLECT = 0x00000001, // this projectile cannot be reflected
MF2_WINDTHRUST = 0x00000002, // gets pushed around by the wind specials MF2_WINDTHRUST = 0x00000002, // gets pushed around by the wind specials
MF2_DONTSEEKINVISIBLE=0x00000004, // For seeker missiles: Don't home in on invisible/shadow targets MF2_DONTSEEKINVISIBLE=0x00000004, // For seeker missiles: Don't home in on invisible/shadow targets
@ -193,9 +198,11 @@ enum
// args should not be taken from the mapthing definition // args should not be taken from the mapthing definition
MF2_SEEKERMISSILE = 0x40000000, // is a seeker (for reflection) MF2_SEEKERMISSILE = 0x40000000, // is a seeker (for reflection)
MF2_REFLECTIVE = 0x80000000, // reflects missiles MF2_REFLECTIVE = 0x80000000, // reflects missiles
};
// --- mobj.flags3 --- // --- mobj.flags3 ---
enum ActorFlag3
{
MF3_FLOORHUGGER = 0x00000001, // Missile stays on floor MF3_FLOORHUGGER = 0x00000001, // Missile stays on floor
MF3_CEILINGHUGGER = 0x00000002, // Missile stays on ceiling MF3_CEILINGHUGGER = 0x00000002, // Missile stays on ceiling
MF3_NORADIUSDMG = 0x00000004, // Actor does not take radius damage MF3_NORADIUSDMG = 0x00000004, // Actor does not take radius damage
@ -228,9 +235,11 @@ enum
MF3_WARNBOT = 0x20000000, // Missile warns bot MF3_WARNBOT = 0x20000000, // Missile warns bot
MF3_PUFFONACTORS = 0x40000000, // Puff appears even when hit bleeding actors MF3_PUFFONACTORS = 0x40000000, // Puff appears even when hit bleeding actors
MF3_HUNTPLAYERS = 0x80000000, // Used with TIDtoHate, means to hate players too MF3_HUNTPLAYERS = 0x80000000, // Used with TIDtoHate, means to hate players too
};
// --- mobj.flags4 --- // --- mobj.flags4 ---
enum ActorFlag4
{
MF4_NOHATEPLAYERS = 0x00000001, // Ignore player attacks MF4_NOHATEPLAYERS = 0x00000001, // Ignore player attacks
MF4_QUICKTORETALIATE= 0x00000002, // Always switch targets when hurt MF4_QUICKTORETALIATE= 0x00000002, // Always switch targets when hurt
MF4_NOICEDEATH = 0x00000004, // Actor never enters an ice death, not even the generic one MF4_NOICEDEATH = 0x00000004, // Actor never enters an ice death, not even the generic one
@ -264,9 +273,12 @@ enum
MF4_EXTREMEDEATH = 0x20000000, // this projectile or weapon always gibs its victim MF4_EXTREMEDEATH = 0x20000000, // this projectile or weapon always gibs its victim
MF4_FRIGHTENED = 0x40000000, // Monster runs away from player MF4_FRIGHTENED = 0x40000000, // Monster runs away from player
MF4_BOSSSPAWNED = 0x80000000, // Spawned by a boss spawn cube MF4_BOSSSPAWNED = 0x80000000, // Spawned by a boss spawn cube
};
// --- mobj.flags5 --- // --- mobj.flags5 ---
enum ActorFlag5
{
MF5_DONTDRAIN = 0x00000001, // cannot be drained health from. MF5_DONTDRAIN = 0x00000001, // cannot be drained health from.
MF5_INSTATECALL = 0x00000002, // This actor is being run through CallStateChain MF5_INSTATECALL = 0x00000002, // This actor is being run through CallStateChain
MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances. MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances.
@ -300,9 +312,11 @@ enum
MF5_INCONVERSATION = 0x20000000, // Actor is having a conversation MF5_INCONVERSATION = 0x20000000, // Actor is having a conversation
MF5_PAINLESS = 0x40000000, // Actor always inflicts painless damage. MF5_PAINLESS = 0x40000000, // Actor always inflicts painless damage.
MF5_MOVEWITHSECTOR = 0x80000000, // P_ChangeSector() will still process this actor if it has MF_NOBLOCKMAP MF5_MOVEWITHSECTOR = 0x80000000, // P_ChangeSector() will still process this actor if it has MF_NOBLOCKMAP
};
// --- mobj.flags6 --- // --- mobj.flags6 ---
enum ActorFlag6
{
MF6_NOBOSSRIP = 0x00000001, // For rippermissiles: Don't rip through bosses. MF6_NOBOSSRIP = 0x00000001, // For rippermissiles: Don't rip through bosses.
MF6_THRUSPECIES = 0x00000002, // Actors passes through other of the same species. MF6_THRUSPECIES = 0x00000002, // Actors passes through other of the same species.
MF6_MTHRUSPECIES = 0x00000004, // Missile passes through actors of its shooter's species. MF6_MTHRUSPECIES = 0x00000004, // Missile passes through actors of its shooter's species.
@ -335,9 +349,11 @@ enum
MF6_NOTAUTOAIMED = 0x20000000, // Do not subject actor to player autoaim. MF6_NOTAUTOAIMED = 0x20000000, // Do not subject actor to player autoaim.
MF6_NOTONAUTOMAP = 0x40000000, // will not be shown on automap with the 'scanner' powerup. MF6_NOTONAUTOMAP = 0x40000000, // will not be shown on automap with the 'scanner' powerup.
MF6_RELATIVETOFLOOR = 0x80000000, // [RC] Make flying actors be affected by lifts. MF6_RELATIVETOFLOOR = 0x80000000, // [RC] Make flying actors be affected by lifts.
};
// --- mobj.flags7 --- // --- mobj.flags7 ---
enum ActorFlag7
{
MF7_NEVERTARGET = 0x00000001, // can not be targetted at all, even if monster friendliness is considered. MF7_NEVERTARGET = 0x00000001, // can not be targetted at all, even if monster friendliness is considered.
MF7_NOTELESTOMP = 0x00000002, // cannot telefrag under any circumstances (even when set by MAPINFO) MF7_NOTELESTOMP = 0x00000002, // cannot telefrag under any circumstances (even when set by MAPINFO)
MF7_ALWAYSTELEFRAG = 0x00000004, // will unconditionally be telefragged when in the way. Overrides all other settings. MF7_ALWAYSTELEFRAG = 0x00000004, // will unconditionally be telefragged when in the way. Overrides all other settings.
@ -356,11 +372,13 @@ enum
MF7_HITMASTER = 0x00008000, // Same as HITTARGET, except it's master instead of target. MF7_HITMASTER = 0x00008000, // Same as HITTARGET, except it's master instead of target.
MF7_HITTRACER = 0x00010000, // Same as HITTARGET, but for tracer. MF7_HITTRACER = 0x00010000, // Same as HITTARGET, but for tracer.
MF7_FLYCHEAT = 0x00020000, // must be part of the actor so that it can be tracked properly MF7_FLYCHEAT = 0x00020000, // must be part of the actor so that it can be tracked properly
MF7_NODECAL = 0x00040000, // [ZK] Forces puff to have no impact decal
MF7_FORCEDECAL = 0x00080000, // [ZK] Forces puff's decal to override the weapon's.
};
// --- mobj.renderflags --- // --- mobj.renderflags ---
enum ActorRenderFlag
{
RF_XFLIP = 0x0001, // Flip sprite horizontally RF_XFLIP = 0x0001, // Flip sprite horizontally
RF_YFLIP = 0x0002, // Flip sprite vertically RF_YFLIP = 0x0002, // Flip sprite vertically
RF_ONESIDED = 0x0004, // Wall/floor sprite is visible from front only RF_ONESIDED = 0x0004, // Wall/floor sprite is visible from front only
@ -389,10 +407,6 @@ enum
RF_FORCEYBILLBOARD = 0x10000, // [BB] OpenGL only: draw with y axis billboard, i.e. anchored to the floor (overrides gl_billboard_mode setting) RF_FORCEYBILLBOARD = 0x10000, // [BB] OpenGL only: draw with y axis billboard, i.e. anchored to the floor (overrides gl_billboard_mode setting)
RF_FORCEXYBILLBOARD = 0x20000, // [BB] OpenGL only: draw with xy axis billboard, i.e. unanchored (overrides gl_billboard_mode setting) RF_FORCEXYBILLBOARD = 0x20000, // [BB] OpenGL only: draw with xy axis billboard, i.e. unanchored (overrides gl_billboard_mode setting)
// --- dummies for unknown/unimplemented Strife flags ---
MF_STRIFEx8000000 = 0, // seems related to MF_SHADOW
}; };
#define TRANSLUC25 (FRACUNIT/4) #define TRANSLUC25 (FRACUNIT/4)
@ -421,7 +435,7 @@ enum replace_t
ALLOW_REPLACE = 1 ALLOW_REPLACE = 1
}; };
enum EBounceFlags enum ActorBounceFlag
{ {
BOUNCE_Walls = 1<<0, // bounces off of walls BOUNCE_Walls = 1<<0, // bounces off of walls
BOUNCE_Floors = 1<<1, // bounces off of floors BOUNCE_Floors = 1<<1, // bounces off of floors
@ -475,6 +489,26 @@ enum EBounceFlags
}; };
// [TP] Flagset definitions
typedef TFlags<ActorFlag> ActorFlags;
typedef TFlags<ActorFlag2> ActorFlags2;
typedef TFlags<ActorFlag3> ActorFlags3;
typedef TFlags<ActorFlag4> ActorFlags4;
typedef TFlags<ActorFlag5> ActorFlags5;
typedef TFlags<ActorFlag6> ActorFlags6;
typedef TFlags<ActorFlag7> ActorFlags7;
typedef TFlags<ActorRenderFlag> ActorRenderFlags;
typedef TFlags<ActorBounceFlag, WORD> ActorBounceFlags;
DEFINE_TFLAGS_OPERATORS (ActorFlags)
DEFINE_TFLAGS_OPERATORS (ActorFlags2)
DEFINE_TFLAGS_OPERATORS (ActorFlags3)
DEFINE_TFLAGS_OPERATORS (ActorFlags4)
DEFINE_TFLAGS_OPERATORS (ActorFlags5)
DEFINE_TFLAGS_OPERATORS (ActorFlags6)
DEFINE_TFLAGS_OPERATORS (ActorFlags7)
DEFINE_TFLAGS_OPERATORS (ActorRenderFlags)
DEFINE_TFLAGS_OPERATORS (ActorBounceFlags)
// Used to affect the logic for thing activation through death, USESPECIAL and BUMPSPECIAL // Used to affect the logic for thing activation through death, USESPECIAL and BUMPSPECIAL
// "thing" refers to what has the flag and the special, "trigger" refers to what used or bumped it // "thing" refers to what has the flag and the special, "trigger" refers to what used or bumped it
enum EThingSpecialActivationType enum EThingSpecialActivationType
@ -813,7 +847,7 @@ public:
BYTE frame; // sprite frame to draw BYTE frame; // sprite frame to draw
fixed_t scaleX, scaleY; // Scaling values; FRACUNIT is normal size fixed_t scaleX, scaleY; // Scaling values; FRACUNIT is normal size
FRenderStyle RenderStyle; // Style to draw this actor with FRenderStyle RenderStyle; // Style to draw this actor with
DWORD renderflags; // Different rendering flags ActorRenderFlags renderflags; // Different rendering flags
FTextureID picnum; // Draw this instead of sprite if valid FTextureID picnum; // Draw this instead of sprite if valid
DWORD effects; // [RH] see p_effect.h DWORD effects; // [RH] see p_effect.h
fixed_t alpha; fixed_t alpha;
@ -839,13 +873,13 @@ public:
FState *state; FState *state;
VMFunction *Damage; // For missiles and monster railgun VMFunction *Damage; // For missiles and monster railgun
int projectileKickback; int projectileKickback;
DWORD flags; ActorFlags flags;
DWORD flags2; // Heretic flags ActorFlags2 flags2; // Heretic flags
DWORD flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable ActorFlags3 flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable
DWORD flags4; // [RH] Even more flags! ActorFlags4 flags4; // [RH] Even more flags!
DWORD flags5; // OMG! We need another one. ActorFlags5 flags5; // OMG! We need another one.
DWORD flags6; // Shit! Where did all the flags go? ActorFlags6 flags6; // Shit! Where did all the flags go?
DWORD flags7; // WHO WANTS TO BET ON 8!? ActorFlags7 flags7; // WHO WANTS TO BET ON 8!?
// [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it. // [BB] If 0, everybody can see the actor, if > 0, only members of team (VisibleToTeam-1) can see it.
DWORD VisibleToTeam; DWORD VisibleToTeam;
@ -891,7 +925,7 @@ public:
BYTE boomwaterlevel; // splash information for non-swimmable water sectors BYTE boomwaterlevel; // splash information for non-swimmable water sectors
BYTE MinMissileChance;// [RH] If a random # is > than this, then missile attack. BYTE MinMissileChance;// [RH] If a random # is > than this, then missile attack.
SBYTE LastLookPlayerNumber;// Player number last looked for (if TIDtoHate == 0) SBYTE LastLookPlayerNumber;// Player number last looked for (if TIDtoHate == 0)
WORD BounceFlags; // which bouncing type? ActorBounceFlags BounceFlags; // which bouncing type?
DWORD SpawnFlags; // Increased to DWORD because of Doom 64 DWORD SpawnFlags; // Increased to DWORD because of Doom 64
fixed_t meleerange; // specifies how far a melee attack reaches. fixed_t meleerange; // specifies how far a melee attack reaches.
fixed_t meleethreshold; // Distance below which a monster doesn't try to shoot missiles anynore fixed_t meleethreshold; // Distance below which a monster doesn't try to shoot missiles anynore

View file

@ -544,7 +544,7 @@ angle_t DBot::FireRox (AActor *enemy, ticcmd_t *cmd)
// creating side-effects during gameplay. // creating side-effects during gameplay.
bool FCajunMaster::SafeCheckPosition (AActor *actor, fixed_t x, fixed_t y, FCheckPosition &tm) bool FCajunMaster::SafeCheckPosition (AActor *actor, fixed_t x, fixed_t y, FCheckPosition &tm)
{ {
int savedFlags = actor->flags; ActorFlags savedFlags = actor->flags;
actor->flags &= ~MF_PICKUP; actor->flags &= ~MF_PICKUP;
bool res = P_CheckPosition (actor, x, y, tm); bool res = P_CheckPosition (actor, x, y, tm);
actor->flags = savedFlags; actor->flags = savedFlags;

View file

@ -1193,31 +1193,31 @@ static int PatchThing (int thingy)
// triggering line effects and can teleport when the missile flag is removed. // triggering line effects and can teleport when the missile flag is removed.
info->flags2 &= ~MF2_NOTELEPORT; info->flags2 &= ~MF2_NOTELEPORT;
} }
info->flags = value[0]; info->flags = ActorFlags::FromInt (value[0]);
} }
if (vchanged[1]) if (vchanged[1])
{ {
info->flags2 = value[1]; info->flags2 = ActorFlags2::FromInt (value[1]);
if (info->flags2 & 0x00000004) // old BOUNCE1 if (info->flags2 & 0x00000004) // old BOUNCE1
{ {
info->flags2 &= ~4; info->flags2 &= ActorFlags2::FromInt (~4);
info->BounceFlags = BOUNCE_DoomCompat; info->BounceFlags = BOUNCE_DoomCompat;
} }
// Damage types that once were flags but now are not // Damage types that once were flags but now are not
if (info->flags2 & 0x20000000) if (info->flags2 & 0x20000000)
{ {
info->DamageType = NAME_Ice; info->DamageType = NAME_Ice;
info->flags2 &= ~0x20000000; info->flags2 &= ActorFlags2::FromInt (~0x20000000);
} }
if (info->flags2 & 0x10000) if (info->flags2 & 0x10000)
{ {
info->DamageType = NAME_Fire; info->DamageType = NAME_Fire;
info->flags2 &= ~0x10000; info->flags2 &= ActorFlags2::FromInt (~0x10000);
} }
if (info->flags2 & 1) if (info->flags2 & 1)
{ {
info->gravity = FRACUNIT/4; info->gravity = FRACUNIT/4;
info->flags2 &= ~1; info->flags2 &= ActorFlags2::FromInt (~1);
} }
} }
if (vchanged[2]) if (vchanged[2])

View file

@ -37,6 +37,7 @@
#include <stdio.h> #include <stdio.h>
#include "dobject.h" #include "dobject.h"
#include "r_state.h" #include "r_state.h"
#include "tflags.h"
class FFile class FFile
{ {
@ -323,4 +324,10 @@ FArchive &operator<< (FArchive &arc, side_t *&side);
template<typename T, typename TT>
FArchive& operator<< (FArchive& arc, TFlags<T, TT>& flag)
{
return flag.Serialize (arc);
}
#endif //__FARCHIVE_H__ #endif //__FARCHIVE_H__

View file

@ -1223,11 +1223,14 @@ void FParser::SF_ObjFlag(void)
if(mo && flagnum<26) // nullptr check if(mo && flagnum<26) // nullptr check
{ {
DWORD tempflags = mo->flags;
// remove old bit // remove old bit
mo->flags &= ~(1 << flagnum); tempflags &= ~(1 << flagnum);
// make the new flag // make the new flag
mo->flags |= (!!intvalue(t_argv[2])) << flagnum; tempflags |= (!!intvalue(t_argv[2])) << flagnum;
mo->flags = ActorFlags::FromInt (tempflags);
} }
} }
t_return.type = svt_int; t_return.type = svt_int;

View file

@ -1923,7 +1923,7 @@ void APowerMorph::EndEffect( )
if (!bNoCallUndoMorph) if (!bNoCallUndoMorph)
{ {
int savedMorphTics = Player->morphTics; int savedMorphTics = Player->morphTics;
P_UndoPlayerMorph (Player, Player); P_UndoPlayerMorph (Player, Player, 0, !!(Player->MorphStyle & MORPH_UNDOALWAYS));
// Abort if unmorph failed; in that case, // Abort if unmorph failed; in that case,
// set the usual retry timer and return. // set the usual retry timer and return.

View file

@ -105,7 +105,7 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp
morphed->flags |= actor->flags & (MF_SHADOW|MF_NOGRAVITY); morphed->flags |= actor->flags & (MF_SHADOW|MF_NOGRAVITY);
morphed->flags2 |= actor->flags2 & MF2_FLY; morphed->flags2 |= actor->flags2 & MF2_FLY;
morphed->flags3 |= actor->flags3 & MF3_GHOST; morphed->flags3 |= actor->flags3 & MF3_GHOST;
Spawn(((enter_flash) ? enter_flash : RUNTIME_CLASS(ATeleportFog)), actor->x, actor->y, actor->z + TELEFOGHEIGHT, ALLOW_REPLACE); AActor *eflash = Spawn(((enter_flash) ? enter_flash : RUNTIME_CLASS(ATeleportFog)), actor->x, actor->y, actor->z + TELEFOGHEIGHT, ALLOW_REPLACE);
actor->player = NULL; actor->player = NULL;
actor->flags &= ~(MF_SOLID|MF_SHOOTABLE); actor->flags &= ~(MF_SOLID|MF_SHOOTABLE);
actor->flags |= MF_UNMORPHED; actor->flags |= MF_UNMORPHED;
@ -151,6 +151,8 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp
p->camera = morphed; p->camera = morphed;
} }
morphed->ScoreIcon = actor->ScoreIcon; // [GRB] morphed->ScoreIcon = actor->ScoreIcon; // [GRB]
if (eflash)
eflash->target = p->mo;
return true; return true;
} }
@ -223,7 +225,7 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
mo->angle = pmo->angle; mo->angle = pmo->angle;
mo->player = player; mo->player = player;
mo->reactiontime = 18; mo->reactiontime = 18;
mo->flags = pmo->special2 & ~MF_JUSTHIT; mo->flags = ActorFlags::FromInt (pmo->special2) & ~MF_JUSTHIT;
mo->velx = 0; mo->velx = 0;
mo->vely = 0; mo->vely = 0;
player->velx = 0; player->velx = 0;
@ -305,9 +307,11 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
} }
angle = mo->angle >> ANGLETOFINESHIFT; angle = mo->angle >> ANGLETOFINESHIFT;
AActor *eflash = NULL;
if (exit_flash != NULL) if (exit_flash != NULL)
{ {
Spawn(exit_flash, pmo->x + 20*finecosine[angle], pmo->y + 20*finesine[angle], pmo->z + TELEFOGHEIGHT, ALLOW_REPLACE); eflash = Spawn(exit_flash, pmo->x + 20*finecosine[angle], pmo->y + 20*finesine[angle], pmo->z + TELEFOGHEIGHT, ALLOW_REPLACE);
if (eflash) eflash->target = mo;
} }
mo->SetupWeaponSlots(); // Use original class's weapon slots. mo->SetupWeaponSlots(); // Use original class's weapon slots.
beastweap = player->ReadyWeapon; beastweap = player->ReadyWeapon;
@ -406,7 +410,9 @@ bool P_MorphMonster (AActor *actor, PClassActor *spawntype, int duration, int st
actor->flags &= ~(MF_SOLID|MF_SHOOTABLE); actor->flags &= ~(MF_SOLID|MF_SHOOTABLE);
actor->flags |= MF_UNMORPHED; actor->flags |= MF_UNMORPHED;
actor->renderflags |= RF_INVISIBLE; actor->renderflags |= RF_INVISIBLE;
Spawn(((enter_flash) ? enter_flash : RUNTIME_CLASS(ATeleportFog)), actor->x, actor->y, actor->z + TELEFOGHEIGHT, ALLOW_REPLACE); AActor *eflash = Spawn(((enter_flash) ? enter_flash : RUNTIME_CLASS(ATeleportFog)), actor->x, actor->y, actor->z + TELEFOGHEIGHT, ALLOW_REPLACE);
if (eflash)
eflash->target = morphed;
return true; return true;
} }
@ -433,7 +439,7 @@ bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force)
actor->SetOrigin (beast->x, beast->y, beast->z); actor->SetOrigin (beast->x, beast->y, beast->z);
actor->flags |= MF_SOLID; actor->flags |= MF_SOLID;
beast->flags &= ~MF_SOLID; beast->flags &= ~MF_SOLID;
int beastflags6 = beast->flags6; ActorFlags6 beastflags6 = beast->flags6;
beast->flags6 &= ~MF6_TOUCHY; beast->flags6 &= ~MF6_TOUCHY;
if (!force && !P_TestMobjLocation (actor)) if (!force && !P_TestMobjLocation (actor))
{ // Didn't fit { // Didn't fit
@ -466,7 +472,9 @@ bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force)
DObject::StaticPointerSubstitution (beast, actor); DObject::StaticPointerSubstitution (beast, actor);
PClassActor *exit_flash = beast->MorphExitFlash; PClassActor *exit_flash = beast->MorphExitFlash;
beast->Destroy (); beast->Destroy ();
Spawn(exit_flash, beast->x, beast->y, beast->z + TELEFOGHEIGHT, ALLOW_REPLACE); AActor *eflash = Spawn(exit_flash, beast->x, beast->y, beast->z + TELEFOGHEIGHT, ALLOW_REPLACE);
if (eflash)
eflash->target = actor;
return true; return true;
} }

View file

@ -24,6 +24,7 @@ enum
MORPH_UNDOBYDEATHFORCED = 0x00000400, // Actor (if unmorphed when killed) forces unmorph (not very useful with UNDOBYDEATHSAVES) MORPH_UNDOBYDEATHFORCED = 0x00000400, // Actor (if unmorphed when killed) forces unmorph (not very useful with UNDOBYDEATHSAVES)
MORPH_UNDOBYDEATHSAVES = 0x00000800, // Actor (if unmorphed when killed) regains their health and doesn't die MORPH_UNDOBYDEATHSAVES = 0x00000800, // Actor (if unmorphed when killed) regains their health and doesn't die
MORPH_UNDOBYTIMEOUT = 0x00001000, // Player unmorphs once countdown expires MORPH_UNDOBYTIMEOUT = 0x00001000, // Player unmorphs once countdown expires
MORPH_UNDOALWAYS = 0x00002000, // Powerups must always unmorph, no matter what.
MORPH_STANDARDUNDOING = MORPH_UNDOBYTOMEOFPOWER | MORPH_UNDOBYCHAOSDEVICE | MORPH_UNDOBYTIMEOUT, MORPH_STANDARDUNDOING = MORPH_UNDOBYTOMEOFPOWER | MORPH_UNDOBYCHAOSDEVICE | MORPH_UNDOBYTIMEOUT,
}; };

View file

@ -603,9 +603,9 @@ void AActorMover::Deactivate (AActor *activator)
if (tracer != NULL) if (tracer != NULL)
{ {
tracer->UnlinkFromWorld (); tracer->UnlinkFromWorld ();
tracer->flags = special1; tracer->flags = ActorFlags::FromInt (special1);
tracer->LinkToWorld (); tracer->LinkToWorld ();
tracer->flags2 = special2; tracer->flags2 = ActorFlags2::FromInt (special2);
} }
} }
} }

View file

@ -202,7 +202,7 @@ public:
TObjPtr<AActor> UnmorphedMe; TObjPtr<AActor> UnmorphedMe;
int UnmorphTime, MorphStyle; int UnmorphTime, MorphStyle;
PClassActor *MorphExitFlash; PClassActor *MorphExitFlash;
DWORD FlagsSave; ActorFlags FlagsSave;
}; };
class AMapMarker : public AActor class AMapMarker : public AActor

View file

@ -113,8 +113,9 @@ FRandom pr_acs ("ACS");
#define NOT_FLOOR 8 #define NOT_FLOOR 8
#define NOT_CEILING 16 #define NOT_CEILING 16
// LineAtack flags // LineAttack flags
#define FHF_NORANDOMPUFFZ 1 #define FHF_NORANDOMPUFFZ 1
#define FHF_NOIMPACTDECAL 2
// SpawnDecal flags // SpawnDecal flags
#define SDF_ABSANGLE 1 #define SDF_ABSANGLE 1
@ -3348,7 +3349,7 @@ int DLevelScript::DoSpawn (int type, fixed_t x, fixed_t y, fixed_t z, int tid, i
actor = Spawn (info, x, y, z, ALLOW_REPLACE); actor = Spawn (info, x, y, z, ALLOW_REPLACE);
if (actor != NULL) if (actor != NULL)
{ {
DWORD oldFlags2 = actor->flags2; ActorFlags2 oldFlags2 = actor->flags2;
actor->flags2 |= MF2_PASSMOBJ; actor->flags2 |= MF2_PASSMOBJ;
if (force || P_TestMobjLocation (actor)) if (force || P_TestMobjLocation (actor))
{ {
@ -5334,7 +5335,9 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args, const
fixed_t range = argCount > 6 && args[6]? args[6] : MISSILERANGE; fixed_t range = argCount > 6 && args[6]? args[6] : MISSILERANGE;
int flags = argCount > 7 && args[7]? args[7] : 0; int flags = argCount > 7 && args[7]? args[7] : 0;
int fhflags = (flags & FHF_NORANDOMPUFFZ)? LAF_NORANDOMPUFFZ : 0; int fhflags = 0;
if (flags & FHF_NORANDOMPUFFZ) fhflags |= LAF_NORANDOMPUFFZ;
if (flags & FHF_NOIMPACTDECAL) fhflags |= LAF_NOIMPACTDECAL;
if (args[0] == 0) if (args[0] == 0)
{ {

View file

@ -895,5 +895,5 @@ void ACustomSprite::BeginPlay ()
renderflags |= RF_YFLIP; renderflags |= RF_YFLIP;
// set face/wall/floor flags // set face/wall/floor flags
renderflags |= ((cstat >> 4) & 3) << 12; renderflags |= ActorRenderFlags::FromInt (((cstat >> 4) & 3) << 12);
} }

View file

@ -2585,7 +2585,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
fixed_t oldheight = corpsehit->height; fixed_t oldheight = corpsehit->height;
fixed_t oldradius = corpsehit->radius; fixed_t oldradius = corpsehit->radius;
int oldflags = corpsehit->flags; ActorFlags oldflags = corpsehit->flags;
corpsehit->flags |= MF_SOLID; corpsehit->flags |= MF_SOLID;
corpsehit->height = corpsehit->GetDefault()->height; corpsehit->height = corpsehit->GetDefault()->height;

View file

@ -465,7 +465,8 @@ enum // P_AimLineAttack flags
enum // P_LineAttack flags enum // P_LineAttack flags
{ {
LAF_ISMELEEATTACK = 1, LAF_ISMELEEATTACK = 1,
LAF_NORANDOMPUFFZ = 2 LAF_NORANDOMPUFFZ = 2,
LAF_NOIMPACTDECAL = 4
}; };
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL); AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL);

View file

@ -1592,7 +1592,7 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, bool actorsonly)
bool P_TestMobjLocation(AActor *mobj) bool P_TestMobjLocation(AActor *mobj)
{ {
int flags; ActorFlags flags;
flags = mobj->flags; flags = mobj->flags;
mobj->flags &= ~MF_PICKUP; mobj->flags &= ~MF_PICKUP;
@ -3726,13 +3726,17 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
} }
// [RH] Spawn a decal // [RH] Spawn a decal
if (trace.HitType == TRACE_HitWall && trace.Line->special != Line_Horizon) if (trace.HitType == TRACE_HitWall && trace.Line->special != Line_Horizon && !(flags & LAF_NOIMPACTDECAL) && !(puffDefaults->flags7 & MF7_NODECAL))
{ {
// [TN] If the actor or weapon has a decal defined, use that one. // [TN] If the actor or weapon has a decal defined, use that one.
if (t1->DecalGenerator != NULL || if (t1->DecalGenerator != NULL ||
(t1->player != NULL && t1->player->ReadyWeapon != NULL && t1->player->ReadyWeapon->DecalGenerator != NULL)) (t1->player != NULL && t1->player->ReadyWeapon != NULL && t1->player->ReadyWeapon->DecalGenerator != NULL))
{ {
SpawnShootDecal(t1, trace); // [ZK] If puff has FORCEDECAL set, do not use the weapon's decal
if (puffDefaults->flags7 & MF7_FORCEDECAL && puff != NULL && puff->DecalGenerator)
SpawnShootDecal(puff, trace);
else
SpawnShootDecal(t1, trace);
} }
// Else, look if the bulletpuff has a decal defined. // Else, look if the bulletpuff has a decal defined.
@ -4921,7 +4925,7 @@ EXTERN_CVAR(Int, cl_bloodtype)
bool P_AdjustFloorCeil(AActor *thing, FChangePosition *cpos) bool P_AdjustFloorCeil(AActor *thing, FChangePosition *cpos)
{ {
int flags2 = thing->flags2 & MF2_PASSMOBJ; ActorFlags2 flags2 = thing->flags2 & MF2_PASSMOBJ;
FCheckPosition tm; FCheckPosition tm;
if ((thing->flags2 & MF2_PASSMOBJ) && (thing->flags3 & MF3_ISMONSTER)) if ((thing->flags2 & MF2_PASSMOBJ) && (thing->flags3 & MF3_ISMONSTER))

View file

@ -566,7 +566,7 @@ bool AActor::SetState (FState *newstate, bool nofunction)
} }
state = newstate; state = newstate;
tics = GetTics(newstate); tics = GetTics(newstate);
renderflags = (renderflags & ~RF_FULLBRIGHT) | newstate->GetFullbright(); renderflags = (renderflags & ~RF_FULLBRIGHT) | ActorRenderFlags::FromInt (newstate->GetFullbright());
newsprite = newstate->sprite; newsprite = newstate->sprite;
if (newsprite != SPR_FIXED) if (newsprite != SPR_FIXED)
{ // okay to change sprite and/or frame { // okay to change sprite and/or frame
@ -2845,10 +2845,10 @@ void P_NightmareRespawn (AActor *mobj)
mo->PrevZ = z; // Do not interpolate Z position if we changed it since spawning. mo->PrevZ = z; // Do not interpolate Z position if we changed it since spawning.
// spawn a teleport fog at old spot because of removal of the body? // spawn a teleport fog at old spot because of removal of the body?
P_SpawnTeleportFog(mobj, mobj->x, mobj->y, mobj->z + TELEFOGHEIGHT, true); P_SpawnTeleportFog(mobj, mobj->x, mobj->y, mobj->z + TELEFOGHEIGHT, true, true);
// spawn a teleport fog at the new spot // spawn a teleport fog at the new spot
P_SpawnTeleportFog(mobj, x, y, z + TELEFOGHEIGHT, false); P_SpawnTeleportFog(mobj, x, y, z + TELEFOGHEIGHT, false, true);
// remove the old monster // remove the old monster
mobj->Destroy (); mobj->Destroy ();
@ -4096,7 +4096,7 @@ AActor *AActor::StaticSpawn (PClassActor *type, fixed_t ix, fixed_t iy, fixed_t
actor->sprite = st->sprite; actor->sprite = st->sprite;
actor->frame = st->GetFrame(); actor->frame = st->GetFrame();
actor->renderflags = (actor->renderflags & ~RF_FULLBRIGHT) | st->GetFullbright(); actor->renderflags = (actor->renderflags & ~RF_FULLBRIGHT) | ActorRenderFlags::FromInt (st->GetFullbright());
actor->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98 actor->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98
if (G_SkillProperty(SKILLP_FastMonsters) && actor->GetClass()->FastSpeed >= 0) if (G_SkillProperty(SKILLP_FastMonsters) && actor->GetClass()->FastSpeed >= 0)
actor->Speed = actor->GetClass()->FastSpeed; actor->Speed = actor->GetClass()->FastSpeed;

View file

@ -86,7 +86,7 @@ bool P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog,
if (mobj != NULL) if (mobj != NULL)
{ {
DWORD oldFlags2 = mobj->flags2; ActorFlags2 oldFlags2 = mobj->flags2;
mobj->flags2 |= MF2_PASSMOBJ; mobj->flags2 |= MF2_PASSMOBJ;
if (P_TestMobjLocation (mobj)) if (P_TestMobjLocation (mobj))
{ {
@ -94,7 +94,7 @@ bool P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog,
mobj->angle = (angle != ANGLE_MAX ? angle : spot->angle); mobj->angle = (angle != ANGLE_MAX ? angle : spot->angle);
if (fog) if (fog)
{ {
P_SpawnTeleportFog(mobj, spot->x, spot->y, spot->z + TELEFOGHEIGHT, false); P_SpawnTeleportFog(mobj, spot->x, spot->y, spot->z + TELEFOGHEIGHT, false, true);
} }
if (mobj->flags & MF_SPECIAL) if (mobj->flags & MF_SPECIAL)
mobj->flags |= MF_DROPPED; // Don't respawn mobj->flags |= MF_DROPPED; // Don't respawn
@ -132,8 +132,8 @@ bool P_MoveThing(AActor *source, fixed_t x, fixed_t y, fixed_t z, bool fog)
{ {
if (fog) if (fog)
{ {
P_SpawnTeleportFog(source, x, y, z); P_SpawnTeleportFog(source, x, y, z, false, true);
P_SpawnTeleportFog(source, oldx, oldy, oldz, false); P_SpawnTeleportFog(source, oldx, oldy, oldz, true, true);
} }
source->PrevX = x; source->PrevX = x;
source->PrevY = y; source->PrevY = y;
@ -429,7 +429,7 @@ bool P_Thing_Raise(AActor *thing, AActor *raiser)
// [RH] Check against real height and radius // [RH] Check against real height and radius
fixed_t oldheight = thing->height; fixed_t oldheight = thing->height;
fixed_t oldradius = thing->radius; fixed_t oldradius = thing->radius;
int oldflags = thing->flags; ActorFlags oldflags = thing->flags;
thing->flags |= MF_SOLID; thing->flags |= MF_SOLID;
thing->height = info->height; // [RH] Use real height thing->height = info->height; // [RH] Use real height
@ -468,7 +468,7 @@ bool P_Thing_CanRaise(AActor *thing)
AActor *info = thing->GetDefault(); AActor *info = thing->GetDefault();
// Check against real height and radius // Check against real height and radius
int oldflags = thing->flags; ActorFlags oldflags = thing->flags;
fixed_t oldheight = thing->height; fixed_t oldheight = thing->height;
fixed_t oldradius = thing->radius; fixed_t oldradius = thing->radius;

View file

@ -790,7 +790,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
P_FindParticleSubsectors (); P_FindParticleSubsectors ();
WallCycles.Clock(); WallCycles.Clock();
DWORD savedflags = camera->renderflags; ActorRenderFlags savedflags = camera->renderflags;
// Never draw the player unless in chasecam mode // Never draw the player unless in chasecam mode
if (!r_showviewer) if (!r_showviewer)
{ {

110
src/tflags.h Normal file
View file

@ -0,0 +1,110 @@
/*
** tflags.h
**
**---------------------------------------------------------------------------
** Copyright 2015 Teemu Piippo
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#pragma once
#include "doomtype.h"
/*
* TFlags
*
* A Qt-inspired type-safe flagset type.
*
* T is the enum type of individual flags,
* TT is the underlying integer type used (defaults to DWORD)
*/
template<typename T, typename TT = DWORD>
class TFlags
{
struct ZeroDummy {};
public:
typedef TFlags<T, TT> Self;
typedef T EnumType;
typedef TT IntType;
TFlags(){}
TFlags (const Self& other) : Value (other.GetValue()) {}
TFlags (T value) : Value (static_cast<TT> (value)) {}
// This allows initializing the flagset with 0, as 0 implicitly converts into a null pointer.
TFlags (ZeroDummy*) : Value (0) {}
// Relation operators
Self operator| (Self other) const { return Self::FromInt (Value | other.GetValue()); }
Self operator& (Self other) const { return Self::FromInt (Value & other.GetValue()); }
Self operator^ (Self other) const { return Self::FromInt (Value ^ other.GetValue()); }
Self operator| (T value) const { return Self::FromInt (Value | value); }
Self operator& (T value) const { return Self::FromInt (Value & value); }
Self operator^ (T value) const { return Self::FromInt (Value ^ value); }
Self operator~() const { return Self::FromInt (~Value); }
// Assignment operators
Self& operator= (Self other) { Value = other.GetValue(); return *this; }
Self& operator|= (Self other) { Value |= other.GetValue(); return *this; }
Self& operator&= (Self other) { Value &= other.GetValue(); return *this; }
Self& operator^= (Self other) { Value ^= other.GetValue(); return *this; }
Self& operator= (T value) { Value = value; return *this; }
Self& operator|= (T value) { Value |= value; return *this; }
Self& operator&= (T value) { Value &= value; return *this; }
Self& operator^= (T value) { Value ^= value; return *this; }
// Access the value of the flagset
TT GetValue() const { return Value; }
operator TT() const { return Value; }
// Serialize to FArchive
FArchive& Serialize (FArchive& arc)
{
arc << Value;
return arc;
}
// Set the value of the flagset manually with an integer.
// Please think twice before using this.
static Self FromInt (TT value) { return Self (static_cast<T> (value)); }
private:
TT Value;
};
/*
* Additional operators for TFlags types.
*/
#define DEFINE_TFLAGS_OPERATORS(T) \
inline T operator| (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) | T::IntType (b)); } \
inline T operator& (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) & T::IntType (b)); } \
inline T operator^ (T::EnumType a, T::EnumType b) { return T::FromInt (T::IntType (a) ^ T::IntType (b)); } \
inline T operator| (T::EnumType a, T b) { return T::FromInt (T::IntType (a) | T::IntType (b)); } \
inline T operator& (T::EnumType a, T b) { return T::FromInt (T::IntType (a) & T::IntType (b)); } \
inline T operator^ (T::EnumType a, T b) { return T::FromInt (T::IntType (a) ^ T::IntType (b)); } \
inline T operator~ (T::EnumType a) { return T::FromInt (~T::IntType (a)); }

View file

@ -3352,8 +3352,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn)
if (flags & RSF_FOG) if (flags & RSF_FOG)
{ {
P_SpawnTeleportFog(self, oldx, oldy, oldz, true); P_SpawnTeleportFog(self, oldx, oldy, oldz, true, true);
P_SpawnTeleportFog(self, self->x, self->y, self->z, false); P_SpawnTeleportFog(self, self->x, self->y, self->z, false, true);
} }
if (self->CountsAsKill()) if (self->CountsAsKill())
{ {
@ -4072,7 +4072,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag)
} }
else else
{ {
DWORD *flagp = (DWORD*) (((char*)self) + fd->structoffset); ActorFlags *flagp = (ActorFlags*) (((char*)self) + fd->structoffset);
// If these 2 flags get changed we need to update the blockmap and sector links. // If these 2 flags get changed we need to update the blockmap and sector links.
bool linkchange = flagp == &self->flags && (fd->flagbit == MF_NOBLOCKMAP || fd->flagbit == MF_NOSECTOR); bool linkchange = flagp == &self->flags && (fd->flagbit == MF_NOBLOCKMAP || fd->flagbit == MF_NOSECTOR);
@ -4557,9 +4557,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetUserArray)
//=========================================================================== //===========================================================================
// //
// A_Teleport(optional state teleportstate, optional class targettype, // A_Teleport([state teleportstate, [class targettype,
// optional class fogtype, optional int flags, optional fixed mindist, // [class fogtype, [int flags, [fixed mindist,
// optional fixed maxdist) // [fixed maxdist]]]]]])
// //
// Attempts to teleport to a targettype at least mindist away and at most // Attempts to teleport to a targettype at least mindist away and at most
// maxdist away (0 means unlimited). If successful, spawn a fogtype at old // maxdist away (0 means unlimited). If successful, spawn a fogtype at old
@ -4589,8 +4589,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
PARAM_INT_OPT (flags) { flags = 0; } PARAM_INT_OPT (flags) { flags = 0; }
PARAM_FIXED_OPT (mindist) { mindist = 128 << FRACBITS; } PARAM_FIXED_OPT (mindist) { mindist = 128 << FRACBITS; }
PARAM_FIXED_OPT (maxdist) { maxdist = 128 << FRACBITS; } PARAM_FIXED_OPT (maxdist) { maxdist = 128 << FRACBITS; }
PARAM_INT_OPT (ptr) { ptr = AAPTR_DEFAULT; }
ACTION_SET_RESULT(true); AActor *ref = COPY_AAPTR(self, ptr);
if (!ref)
{
ACTION_SET_RESULT(false);
return 0;
}
if (ref->flags2 & MF2_NOTELEPORT)
return 0;
// Randomly choose not to teleport like A_Srcr2Decide. // Randomly choose not to teleport like A_Srcr2Decide.
if (flags & TF_RANDOMDECIDE) if (flags & TF_RANDOMDECIDE)
@ -4600,7 +4610,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
192, 120, 120, 120, 64, 64, 32, 16, 0 192, 120, 120, 120, 64, 64, 32, 16, 0
}; };
unsigned int chanceindex = self->health / ((self->SpawnHealth()/8 == 0) ? 1 : self->SpawnHealth()/8); unsigned int chanceindex = ref->health / ((ref->SpawnHealth()/8 == 0) ? 1 : ref->SpawnHealth()/8);
if (chanceindex >= countof(chance)) if (chanceindex >= countof(chance))
{ {
@ -4624,65 +4634,78 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport)
target_type = PClass::FindActor("BossSpot"); target_type = PClass::FindActor("BossSpot");
} }
AActor *spot = state->GetSpotWithMinMaxDistance(target_type, self->x, self->y, mindist, maxdist); AActor * spot = state->GetSpotWithMinMaxDistance(target_type, ref->x, ref->y, mindist, maxdist);
if (spot == NULL) if (spot == NULL)
{ {
return numret; return numret;
} }
fixed_t prevX = self->x; fixed_t prevX = ref->x;
fixed_t prevY = self->y; fixed_t prevY = ref->y;
fixed_t prevZ = self->z; fixed_t prevZ = ref->z;
fixed_t aboveFloor = spot->z - spot->floorz; fixed_t aboveFloor = spot->z - spot->floorz;
fixed_t finalz = spot->floorz + aboveFloor; fixed_t finalz = spot->floorz + aboveFloor;
if (spot->z + self->height > spot->ceilingz) if (spot->z + ref->height > spot->ceilingz)
finalz = spot->ceilingz - self->height; finalz = spot->ceilingz - ref->height;
else if (spot->z < spot->floorz) else if (spot->z < spot->floorz)
finalz = spot->floorz; finalz = spot->floorz;
//Take precedence and cooperate with telefragging first. //Take precedence and cooperate with telefragging first.
bool tele_result = P_TeleportMove(self, spot->x, spot->y, spot->z, flags & TF_TELEFRAG); bool tele_result = P_TeleportMove(ref, spot->x, spot->y, finalz, flags & TF_TELEFRAG);
if (flags & TF_FORCED) if (!tele_result && (flags & TF_FORCED))
{ {
//If for some reason the original move didn't work, regardless of telefrag, force it to move. //If for some reason the original move didn't work, regardless of telefrag, force it to move.
self->SetOrigin(spot->x, spot->y, spot->z); ref->SetOrigin(spot->x, spot->y, finalz);
tele_result = true; tele_result = true;
} }
AActor *fog1 = NULL, *fog2 = NULL;
if (tele_result) if (tele_result)
{ {
// If a fog type is defined in the parameter, or the user wants to use //If a fog type is defined in the parameter, or the user wants to use the actor's predefined fogs,
// the actor's predefined fogs, and if there's no desire to be fogless, //and if there's no desire to be fogless, spawn a fog based upon settings.
// spawn a fog based upon settings.
if (fog_type || (flags & TF_USEACTORFOG)) if (fog_type || (flags & TF_USEACTORFOG))
{ {
if (!(flags & TF_NOSRCFOG)) if (!(flags & TF_NOSRCFOG))
{ {
if (flags & TF_USEACTORFOG) if (flags & TF_USEACTORFOG)
P_SpawnTeleportFog(self, prevX, prevY, prevZ, true); P_SpawnTeleportFog(ref, prevX, prevY, prevZ, true, true);
else else
Spawn(fog_type, prevX, prevY, prevZ, ALLOW_REPLACE); {
} fog1 = Spawn(fog_type, prevX, prevY, prevZ, ALLOW_REPLACE);
if (fog1 != NULL)
fog1->target = ref;
}
}
if (!(flags & TF_NODESTFOG)) if (!(flags & TF_NODESTFOG))
{ {
if (flags & TF_USEACTORFOG) if (flags & TF_USEACTORFOG)
P_SpawnTeleportFog(self, self->x, self->y, self->z, false); P_SpawnTeleportFog(ref, ref->x, ref->y, ref->z, false, true);
else else
Spawn(fog_type, self->x, self->y, self->z, ALLOW_REPLACE); {
fog2 = Spawn(fog_type, prevX, prevY, prevZ, ALLOW_REPLACE);
if (fog2 != NULL)
fog2->target = ref;
}
} }
} }
if (flags & TF_USESPOTZ)
ref->z = spot->z;
else
ref->z = ref->floorz;
self->z = (flags & TF_USESPOTZ) ? spot->z : self->floorz; self->z = (flags & TF_USESPOTZ) ? spot->z : self->floorz;
if (!(flags & TF_KEEPANGLE)) if (!(flags & TF_KEEPANGLE))
self->angle = spot->angle; ref->angle = spot->angle;
if (!(flags & TF_KEEPVELOCITY)) if (!(flags & TF_KEEPVELOCITY))
self->velx = self->vely = self->velz = 0; ref->velx = ref->vely = ref->velz = 0;
if (!(flags & TF_NOJUMP)) if (!(flags & TF_NOJUMP)) //The state jump should only happen with the calling actor.
{ {
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
if (teleport_state == NULL) if (teleport_state == NULL)

View file

@ -59,7 +59,7 @@ static TArray<AFuncDesc> AFTable;
#define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #name, -1, 0 } #define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #name, -1, 0 }
#define DEFINE_DUMMY_FLAG(name) { DEPF_UNUSED, #name, -1, 0 } #define DEFINE_DUMMY_FLAG(name) { DEPF_UNUSED, #name, -1, 0 }
static FFlagDef ActorFlags[]= static FFlagDef ActorFlagDefs[]=
{ {
DEFINE_FLAG(MF, PICKUP, APlayerPawn, flags), DEFINE_FLAG(MF, PICKUP, APlayerPawn, flags),
DEFINE_FLAG(MF, SPECIAL, APlayerPawn, flags), DEFINE_FLAG(MF, SPECIAL, APlayerPawn, flags),
@ -252,6 +252,10 @@ static FFlagDef ActorFlags[]=
DEFINE_FLAG(MF7, HITTARGET, AActor, flags7), DEFINE_FLAG(MF7, HITTARGET, AActor, flags7),
DEFINE_FLAG(MF7, HITMASTER, AActor, flags7), DEFINE_FLAG(MF7, HITMASTER, AActor, flags7),
DEFINE_FLAG(MF7, HITTRACER, AActor, flags7), DEFINE_FLAG(MF7, HITTRACER, AActor, flags7),
// [ZK] Decal flags
DEFINE_FLAG(MF7, NODECAL, AActor, flags7),
DEFINE_FLAG(MF7, FORCEDECAL, AActor, flags7),
// Effect flags // Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
@ -301,7 +305,7 @@ static FFlagDef ActorFlags[]=
DEFINE_DUMMY_FLAG(EXPLODEONDEATH), // seems useless DEFINE_DUMMY_FLAG(EXPLODEONDEATH), // seems useless
}; };
static FFlagDef InventoryFlags[] = static FFlagDef InventoryFlagDefs[] =
{ {
// Inventory flags // Inventory flags
DEFINE_FLAG(IF, QUIET, AInventory, ItemFlags), DEFINE_FLAG(IF, QUIET, AInventory, ItemFlags),
@ -328,7 +332,7 @@ static FFlagDef InventoryFlags[] =
DEFINE_DEPRECATED_FLAG(PICKUPFLASH), DEFINE_DEPRECATED_FLAG(PICKUPFLASH),
DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),}; DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),};
static FFlagDef WeaponFlags[] = static FFlagDef WeaponFlagDefs[] =
{ {
// Weapon flags // Weapon flags
DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags),
@ -355,7 +359,7 @@ static FFlagDef WeaponFlags[] =
DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL), DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL),
}; };
static FFlagDef PlayerPawnFlags[] = static FFlagDef PlayerPawnFlagDefs[] =
{ {
// PlayerPawn flags // PlayerPawn flags
DEFINE_FLAG(PPF, NOTHRUSTWHENINVUL, APlayerPawn, PlayerFlags), DEFINE_FLAG(PPF, NOTHRUSTWHENINVUL, APlayerPawn, PlayerFlags),
@ -363,7 +367,7 @@ static FFlagDef PlayerPawnFlags[] =
DEFINE_FLAG(PPF, CROUCHABLEMORPH, APlayerPawn, PlayerFlags), DEFINE_FLAG(PPF, CROUCHABLEMORPH, APlayerPawn, PlayerFlags),
}; };
static FFlagDef PowerSpeedFlags[] = static FFlagDef PowerSpeedFlagDefs[] =
{ {
// PowerSpeed flags // PowerSpeed flags
DEFINE_FLAG(PSF, NOTRAIL, APowerSpeed, SpeedFlags), DEFINE_FLAG(PSF, NOTRAIL, APowerSpeed, SpeedFlags),
@ -371,11 +375,11 @@ static FFlagDef PowerSpeedFlags[] =
static const struct FFlagList { const PClass * const *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] = static const struct FFlagList { const PClass * const *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] =
{ {
{ &RUNTIME_CLASS_CASTLESS(AActor), ActorFlags, countof(ActorFlags) }, { &RUNTIME_CLASS_CASTLESS(AActor), ActorFlagDefs, countof(ActorFlagDefs) },
{ &RUNTIME_CLASS_CASTLESS(AInventory), InventoryFlags, countof(InventoryFlags) }, { &RUNTIME_CLASS_CASTLESS(AInventory), InventoryFlagDefs, countof(InventoryFlagDefs) },
{ &RUNTIME_CLASS_CASTLESS(AWeapon), WeaponFlags, countof(WeaponFlags) }, { &RUNTIME_CLASS_CASTLESS(AWeapon), WeaponFlagDefs, countof(WeaponFlagDefs) },
{ &RUNTIME_CLASS_CASTLESS(APlayerPawn), PlayerPawnFlags,countof(PlayerPawnFlags) }, { &RUNTIME_CLASS_CASTLESS(APlayerPawn), PlayerPawnFlagDefs, countof(PlayerPawnFlagDefs) },
{ &RUNTIME_CLASS_CASTLESS(APowerSpeed), PowerSpeedFlags,countof(PowerSpeedFlags) }, { &RUNTIME_CLASS_CASTLESS(APowerSpeed), PowerSpeedFlagDefs, countof(PowerSpeedFlagDefs) },
}; };
#define NUM_FLAG_LISTS (countof(FlagLists)) #define NUM_FLAG_LISTS (countof(FlagLists))
@ -462,11 +466,11 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2)
const char *GetFlagName(unsigned int flagnum, int flagoffset) const char *GetFlagName(unsigned int flagnum, int flagoffset)
{ {
for(size_t i = 0; i < countof(ActorFlags); i++) for(size_t i = 0; i < countof(ActorFlagDefs); i++)
{ {
if (ActorFlags[i].flagbit == flagnum && ActorFlags[i].structoffset == flagoffset) if (ActorFlagDefs[i].flagbit == flagnum && ActorFlagDefs[i].structoffset == flagoffset)
{ {
return ActorFlags[i].name; return ActorFlagDefs[i].name;
} }
} }
return "(unknown)"; // return something printable return "(unknown)"; // return something printable

View file

@ -680,6 +680,7 @@ static int ParseMorphStyle (FScanner &sc)
{ "MRF_UNDOBYDEATH", MORPH_UNDOBYDEATH}, { "MRF_UNDOBYDEATH", MORPH_UNDOBYDEATH},
{ "MRF_UNDOBYDEATHFORCED", MORPH_UNDOBYDEATHFORCED}, { "MRF_UNDOBYDEATHFORCED", MORPH_UNDOBYDEATHFORCED},
{ "MRF_UNDOBYDEATHSAVES", MORPH_UNDOBYDEATHSAVES}, { "MRF_UNDOBYDEATHSAVES", MORPH_UNDOBYDEATHSAVES},
{ "MRF_UNDOALWAYS", MORPH_UNDOALWAYS },
{ NULL, 0 } { NULL, 0 }
}; };

View file

@ -1085,7 +1085,7 @@ DEFINE_PROPERTY(bloodtype, Sss, Actor)
DEFINE_PROPERTY(bouncetype, S, Actor) DEFINE_PROPERTY(bouncetype, S, Actor)
{ {
static const char *names[] = { "None", "Doom", "Heretic", "Hexen", "DoomCompat", "HereticCompat", "HexenCompat", "Grenade", "Classic", NULL }; static const char *names[] = { "None", "Doom", "Heretic", "Hexen", "DoomCompat", "HereticCompat", "HexenCompat", "Grenade", "Classic", NULL };
static const int flags[] = { BOUNCE_None, static const ActorBounceFlag flags[] = { BOUNCE_None,
BOUNCE_Doom, BOUNCE_Heretic, BOUNCE_Hexen, BOUNCE_Doom, BOUNCE_Heretic, BOUNCE_Hexen,
BOUNCE_DoomCompat, BOUNCE_HereticCompat, BOUNCE_HexenCompat, BOUNCE_DoomCompat, BOUNCE_HereticCompat, BOUNCE_HexenCompat,
BOUNCE_Grenade, BOUNCE_Classic, }; BOUNCE_Grenade, BOUNCE_Classic, };
@ -1348,13 +1348,13 @@ DEFINE_PROPERTY(species, S, Actor)
//========================================================================== //==========================================================================
DEFINE_PROPERTY(clearflags, 0, Actor) DEFINE_PROPERTY(clearflags, 0, Actor)
{ {
defaults->flags = defaults->flags = 0;
defaults->flags3 =
defaults->flags4 =
defaults->flags5 =
defaults->flags6 =
defaults->flags7 = 0;
defaults->flags2 &= MF2_ARGSDEFINED; // this flag must not be cleared defaults->flags2 &= MF2_ARGSDEFINED; // this flag must not be cleared
defaults->flags3 = 0;
defaults->flags4 = 0;
defaults->flags5 = 0;
defaults->flags6 = 0;
defaults->flags7 = 0;
} }
//========================================================================== //==========================================================================

View file

@ -216,7 +216,7 @@ ACTOR Actor native //: Thinker
action native A_CheckCeiling(state label); action native A_CheckCeiling(state label);
action native A_PlayerSkinCheck(state label); action native A_PlayerSkinCheck(state label);
action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight); action native A_BasicAttack(int meleedamage, sound meleesound, class<actor> missiletype, float missileheight);
action native A_Teleport(state teleportstate = "", class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0); action native A_Teleport(state teleportstate = "", class<SpecialSpot> targettype = "BossSpot", class<Actor> fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0, int ptr = AAPTR_DEFAULT);
action native A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = ""); action native A_Warp(int ptr_destination, float xofs = 0, float yofs = 0, float zofs = 0, float angle = 0, int flags = 0, state success_state = "");
action native A_ThrowGrenade(class<Actor> itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true); action native A_ThrowGrenade(class<Actor> itemtype, float zheight = 0, float xyvel = 0, float zvel = 0, bool useammo = true);
action native A_Weave(int xspeed, int yspeed, float xdist, float ydist); action native A_Weave(int xspeed, int yspeed, float xdist, float ydist);

View file

@ -140,6 +140,7 @@ const int MRF_NEWTIDBEHAVIOUR = 256;
const int MRF_UNDOBYDEATH = 512; const int MRF_UNDOBYDEATH = 512;
const int MRF_UNDOBYDEATHFORCED = 1024; const int MRF_UNDOBYDEATHFORCED = 1024;
const int MRF_UNDOBYDEATHSAVES = 2048; const int MRF_UNDOBYDEATHSAVES = 2048;
const int MRF_UNDOALWAYS = 4096;
// Flags for A_RailAttack and A_CustomRailgun // Flags for A_RailAttack and A_CustomRailgun
const int RGF_SILENT = 1; const int RGF_SILENT = 1;