diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 12218f997..a8f92959e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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\"") endif( ZDOOM_GENERATE_MAPFILE ) - add_custom_command(TARGET zdoom POST_BUILD - COMMAND "mt.exe" -manifest \"${CMAKE_CURRENT_SOURCE_DIR}\\win32\\zdoom.exe.manifest\" -outputresource:\"$(TargetDir)$(TargetFileName)\"\;\#1 - COMMENT "Adding manifest..." - ) + if( NO_GENERATOR_EXPRESSIONS ) + add_custom_command(TARGET zdoom POST_BUILD + 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:\"$\"\;\#1 + COMMENT "Adding manifest..." + ) + endif( NO_GENERATOR_EXPRESSIONS ) create_default_target_launcher( zdoom WORKING_DIRECTORY ${ZDOOM_OUTPUT_DIR} ) endif( MSVC ) diff --git a/src/actor.h b/src/actor.h index 03266f9bb..cedc28e00 100644 --- a/src/actor.h +++ b/src/actor.h @@ -39,6 +39,7 @@ #include "s_sound.h" #include "memarena.h" #include "g_level.h" +#include "tflags.h" struct subsector_t; class PClassAmmo; @@ -107,10 +108,9 @@ class PClassAmmo; // Any questions? // -enum -{ // --- mobj.flags --- - +enum ActorFlag +{ MF_SPECIAL = 0x00000001, // call P_SpecialThing when touched MF_SOLID = 0x00000002, MF_SHOOTABLE = 0x00000004, @@ -154,8 +154,13 @@ enum MF_STEALTH = 0x40000000, // [RH] Andy Baker's stealth monsters 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_WINDTHRUST = 0x00000002, // gets pushed around by the wind specials 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 MF2_SEEKERMISSILE = 0x40000000, // is a seeker (for reflection) MF2_REFLECTIVE = 0x80000000, // reflects missiles +}; // --- mobj.flags3 --- - +enum ActorFlag3 +{ MF3_FLOORHUGGER = 0x00000001, // Missile stays on floor MF3_CEILINGHUGGER = 0x00000002, // Missile stays on ceiling MF3_NORADIUSDMG = 0x00000004, // Actor does not take radius damage @@ -228,9 +235,11 @@ enum MF3_WARNBOT = 0x20000000, // Missile warns bot MF3_PUFFONACTORS = 0x40000000, // Puff appears even when hit bleeding actors MF3_HUNTPLAYERS = 0x80000000, // Used with TIDtoHate, means to hate players too +}; // --- mobj.flags4 --- - +enum ActorFlag4 +{ MF4_NOHATEPLAYERS = 0x00000001, // Ignore player attacks MF4_QUICKTORETALIATE= 0x00000002, // Always switch targets when hurt 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_FRIGHTENED = 0x40000000, // Monster runs away from player MF4_BOSSSPAWNED = 0x80000000, // Spawned by a boss spawn cube - +}; + // --- mobj.flags5 --- +enum ActorFlag5 +{ MF5_DONTDRAIN = 0x00000001, // cannot be drained health from. MF5_INSTATECALL = 0x00000002, // This actor is being run through CallStateChain MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances. @@ -300,9 +312,11 @@ enum MF5_INCONVERSATION = 0x20000000, // Actor is having a conversation 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 --- - +enum ActorFlag6 +{ 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. @@ -335,9 +349,11 @@ enum MF6_NOTAUTOAIMED = 0x20000000, // Do not subject actor to player autoaim. MF6_NOTONAUTOMAP = 0x40000000, // will not be shown on automap with the 'scanner' powerup. MF6_RELATIVETOFLOOR = 0x80000000, // [RC] Make flying actors be affected by lifts. +}; // --- mobj.flags7 --- - +enum ActorFlag7 +{ 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_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_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_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 --- - +enum ActorRenderFlag +{ RF_XFLIP = 0x0001, // Flip sprite horizontally RF_YFLIP = 0x0002, // Flip sprite vertically 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_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) @@ -421,7 +435,7 @@ enum replace_t ALLOW_REPLACE = 1 }; -enum EBounceFlags +enum ActorBounceFlag { BOUNCE_Walls = 1<<0, // bounces off of walls BOUNCE_Floors = 1<<1, // bounces off of floors @@ -475,6 +489,26 @@ enum EBounceFlags }; +// [TP] Flagset definitions +typedef TFlags ActorFlags; +typedef TFlags ActorFlags2; +typedef TFlags ActorFlags3; +typedef TFlags ActorFlags4; +typedef TFlags ActorFlags5; +typedef TFlags ActorFlags6; +typedef TFlags ActorFlags7; +typedef TFlags ActorRenderFlags; +typedef TFlags 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 // "thing" refers to what has the flag and the special, "trigger" refers to what used or bumped it enum EThingSpecialActivationType @@ -813,7 +847,7 @@ public: BYTE frame; // sprite frame to draw fixed_t scaleX, scaleY; // Scaling values; FRACUNIT is normal size 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 DWORD effects; // [RH] see p_effect.h fixed_t alpha; @@ -839,13 +873,13 @@ public: FState *state; VMFunction *Damage; // For missiles and monster railgun int projectileKickback; - DWORD flags; - DWORD flags2; // Heretic flags - DWORD flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable - DWORD flags4; // [RH] Even more flags! - DWORD flags5; // OMG! We need another one. - DWORD flags6; // Shit! Where did all the flags go? - DWORD flags7; // WHO WANTS TO BET ON 8!? + ActorFlags flags; + ActorFlags2 flags2; // Heretic flags + ActorFlags3 flags3; // [RH] Hexen/Heretic actor-dependant behavior made flaggable + ActorFlags4 flags4; // [RH] Even more flags! + ActorFlags5 flags5; // OMG! We need another one. + ActorFlags6 flags6; // Shit! Where did all the flags go? + 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. DWORD VisibleToTeam; @@ -891,7 +925,7 @@ public: BYTE boomwaterlevel; // splash information for non-swimmable water sectors BYTE MinMissileChance;// [RH] If a random # is > than this, then missile attack. 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 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 diff --git a/src/b_func.cpp b/src/b_func.cpp index 2800c01c5..f93625612 100644 --- a/src/b_func.cpp +++ b/src/b_func.cpp @@ -544,7 +544,7 @@ angle_t DBot::FireRox (AActor *enemy, ticcmd_t *cmd) // creating side-effects during gameplay. 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; bool res = P_CheckPosition (actor, x, y, tm); actor->flags = savedFlags; diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 1f346d526..b602e5c44 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1193,31 +1193,31 @@ static int PatchThing (int thingy) // triggering line effects and can teleport when the missile flag is removed. info->flags2 &= ~MF2_NOTELEPORT; } - info->flags = value[0]; + info->flags = ActorFlags::FromInt (value[0]); } if (vchanged[1]) { - info->flags2 = value[1]; + info->flags2 = ActorFlags2::FromInt (value[1]); if (info->flags2 & 0x00000004) // old BOUNCE1 { - info->flags2 &= ~4; + info->flags2 &= ActorFlags2::FromInt (~4); info->BounceFlags = BOUNCE_DoomCompat; } // Damage types that once were flags but now are not if (info->flags2 & 0x20000000) { info->DamageType = NAME_Ice; - info->flags2 &= ~0x20000000; + info->flags2 &= ActorFlags2::FromInt (~0x20000000); } if (info->flags2 & 0x10000) { info->DamageType = NAME_Fire; - info->flags2 &= ~0x10000; + info->flags2 &= ActorFlags2::FromInt (~0x10000); } if (info->flags2 & 1) { info->gravity = FRACUNIT/4; - info->flags2 &= ~1; + info->flags2 &= ActorFlags2::FromInt (~1); } } if (vchanged[2]) diff --git a/src/farchive.h b/src/farchive.h index 7b9327d59..64c7cc9fe 100644 --- a/src/farchive.h +++ b/src/farchive.h @@ -37,6 +37,7 @@ #include #include "dobject.h" #include "r_state.h" +#include "tflags.h" class FFile { @@ -323,4 +324,10 @@ FArchive &operator<< (FArchive &arc, side_t *&side); +template +FArchive& operator<< (FArchive& arc, TFlags& flag) +{ + return flag.Serialize (arc); +} + #endif //__FARCHIVE_H__ diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 56cb0e5ce..f57c0b95b 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -1223,11 +1223,14 @@ void FParser::SF_ObjFlag(void) if(mo && flagnum<26) // nullptr check { + DWORD tempflags = mo->flags; + // remove old bit - mo->flags &= ~(1 << flagnum); + tempflags &= ~(1 << flagnum); // 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; diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index e0bddc9aa..0dfde2b4e 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -1923,7 +1923,7 @@ void APowerMorph::EndEffect( ) if (!bNoCallUndoMorph) { int savedMorphTics = Player->morphTics; - P_UndoPlayerMorph (Player, Player); + P_UndoPlayerMorph (Player, Player, 0, !!(Player->MorphStyle & MORPH_UNDOALWAYS)); // Abort if unmorph failed; in that case, // set the usual retry timer and return. diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 14bc49007..679f5ad0d 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -105,7 +105,7 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp morphed->flags |= actor->flags & (MF_SHADOW|MF_NOGRAVITY); morphed->flags2 |= actor->flags2 & MF2_FLY; 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->flags &= ~(MF_SOLID|MF_SHOOTABLE); actor->flags |= MF_UNMORPHED; @@ -151,6 +151,8 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp p->camera = morphed; } morphed->ScoreIcon = actor->ScoreIcon; // [GRB] + if (eflash) + eflash->target = p->mo; return true; } @@ -223,7 +225,7 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, mo->angle = pmo->angle; mo->player = player; mo->reactiontime = 18; - mo->flags = pmo->special2 & ~MF_JUSTHIT; + mo->flags = ActorFlags::FromInt (pmo->special2) & ~MF_JUSTHIT; mo->velx = 0; mo->vely = 0; player->velx = 0; @@ -305,9 +307,11 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, } angle = mo->angle >> ANGLETOFINESHIFT; + AActor *eflash = 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. 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_UNMORPHED; 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; } @@ -433,7 +439,7 @@ bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force) actor->SetOrigin (beast->x, beast->y, beast->z); actor->flags |= MF_SOLID; beast->flags &= ~MF_SOLID; - int beastflags6 = beast->flags6; + ActorFlags6 beastflags6 = beast->flags6; beast->flags6 &= ~MF6_TOUCHY; if (!force && !P_TestMobjLocation (actor)) { // Didn't fit @@ -466,7 +472,9 @@ bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force) DObject::StaticPointerSubstitution (beast, actor); PClassActor *exit_flash = beast->MorphExitFlash; 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; } diff --git a/src/g_shared/a_morph.h b/src/g_shared/a_morph.h index fb0e4c65d..467b7e800 100644 --- a/src/g_shared/a_morph.h +++ b/src/g_shared/a_morph.h @@ -24,6 +24,7 @@ enum 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_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, }; diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp index 83d0d4695..0f847fa41 100644 --- a/src/g_shared/a_movingcamera.cpp +++ b/src/g_shared/a_movingcamera.cpp @@ -603,9 +603,9 @@ void AActorMover::Deactivate (AActor *activator) if (tracer != NULL) { tracer->UnlinkFromWorld (); - tracer->flags = special1; + tracer->flags = ActorFlags::FromInt (special1); tracer->LinkToWorld (); - tracer->flags2 = special2; + tracer->flags2 = ActorFlags2::FromInt (special2); } } } diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 45394b7f2..d23b8291c 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -202,7 +202,7 @@ public: TObjPtr UnmorphedMe; int UnmorphTime, MorphStyle; PClassActor *MorphExitFlash; - DWORD FlagsSave; + ActorFlags FlagsSave; }; class AMapMarker : public AActor diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 2b3923d34..de484a5dd 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -113,8 +113,9 @@ FRandom pr_acs ("ACS"); #define NOT_FLOOR 8 #define NOT_CEILING 16 -// LineAtack flags +// LineAttack flags #define FHF_NORANDOMPUFFZ 1 +#define FHF_NOIMPACTDECAL 2 // SpawnDecal flags #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); if (actor != NULL) { - DWORD oldFlags2 = actor->flags2; + ActorFlags2 oldFlags2 = actor->flags2; actor->flags2 |= MF2_PASSMOBJ; 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; 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) { diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index 73cd11f23..fa5af987f 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -895,5 +895,5 @@ void ACustomSprite::BeginPlay () renderflags |= RF_YFLIP; // set face/wall/floor flags - renderflags |= ((cstat >> 4) & 3) << 12; + renderflags |= ActorRenderFlags::FromInt (((cstat >> 4) & 3) << 12); } diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 640fef3fa..bb5e19ee1 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2585,7 +2585,7 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates) fixed_t oldheight = corpsehit->height; fixed_t oldradius = corpsehit->radius; - int oldflags = corpsehit->flags; + ActorFlags oldflags = corpsehit->flags; corpsehit->flags |= MF_SOLID; corpsehit->height = corpsehit->GetDefault()->height; diff --git a/src/p_local.h b/src/p_local.h index a029bf02f..3a4a0b633 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -465,7 +465,8 @@ enum // P_AimLineAttack flags enum // P_LineAttack flags { 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); diff --git a/src/p_map.cpp b/src/p_map.cpp index 0fb2bbff8..8949e1974 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1592,7 +1592,7 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, bool actorsonly) bool P_TestMobjLocation(AActor *mobj) { - int flags; + ActorFlags flags; flags = mobj->flags; mobj->flags &= ~MF_PICKUP; @@ -3726,13 +3726,17 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance, } // [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. if (t1->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. @@ -4921,7 +4925,7 @@ EXTERN_CVAR(Int, cl_bloodtype) bool P_AdjustFloorCeil(AActor *thing, FChangePosition *cpos) { - int flags2 = thing->flags2 & MF2_PASSMOBJ; + ActorFlags2 flags2 = thing->flags2 & MF2_PASSMOBJ; FCheckPosition tm; if ((thing->flags2 & MF2_PASSMOBJ) && (thing->flags3 & MF3_ISMONSTER)) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a16b9a47d..36d38dbd4 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -566,7 +566,7 @@ bool AActor::SetState (FState *newstate, bool nofunction) } state = newstate; tics = GetTics(newstate); - renderflags = (renderflags & ~RF_FULLBRIGHT) | newstate->GetFullbright(); + renderflags = (renderflags & ~RF_FULLBRIGHT) | ActorRenderFlags::FromInt (newstate->GetFullbright()); newsprite = newstate->sprite; if (newsprite != SPR_FIXED) { // 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. // 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 - P_SpawnTeleportFog(mobj, x, y, z + TELEFOGHEIGHT, false); + P_SpawnTeleportFog(mobj, x, y, z + TELEFOGHEIGHT, false, true); // remove the old monster mobj->Destroy (); @@ -4096,7 +4096,7 @@ AActor *AActor::StaticSpawn (PClassActor *type, fixed_t ix, fixed_t iy, fixed_t actor->sprite = st->sprite; 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 if (G_SkillProperty(SKILLP_FastMonsters) && actor->GetClass()->FastSpeed >= 0) actor->Speed = actor->GetClass()->FastSpeed; diff --git a/src/p_things.cpp b/src/p_things.cpp index 0b51b9c18..9caa76d7d 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -86,7 +86,7 @@ bool P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog, if (mobj != NULL) { - DWORD oldFlags2 = mobj->flags2; + ActorFlags2 oldFlags2 = mobj->flags2; mobj->flags2 |= MF2_PASSMOBJ; 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); 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) 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) { - P_SpawnTeleportFog(source, x, y, z); - P_SpawnTeleportFog(source, oldx, oldy, oldz, false); + P_SpawnTeleportFog(source, x, y, z, false, true); + P_SpawnTeleportFog(source, oldx, oldy, oldz, true, true); } source->PrevX = x; source->PrevY = y; @@ -429,7 +429,7 @@ bool P_Thing_Raise(AActor *thing, AActor *raiser) // [RH] Check against real height and radius fixed_t oldheight = thing->height; fixed_t oldradius = thing->radius; - int oldflags = thing->flags; + ActorFlags oldflags = thing->flags; thing->flags |= MF_SOLID; thing->height = info->height; // [RH] Use real height @@ -468,7 +468,7 @@ bool P_Thing_CanRaise(AActor *thing) AActor *info = thing->GetDefault(); // Check against real height and radius - int oldflags = thing->flags; + ActorFlags oldflags = thing->flags; fixed_t oldheight = thing->height; fixed_t oldradius = thing->radius; diff --git a/src/r_main.cpp b/src/r_main.cpp index dbf4cbeb5..5da0b8992 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -790,7 +790,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines) P_FindParticleSubsectors (); WallCycles.Clock(); - DWORD savedflags = camera->renderflags; + ActorRenderFlags savedflags = camera->renderflags; // Never draw the player unless in chasecam mode if (!r_showviewer) { diff --git a/src/tflags.h b/src/tflags.h new file mode 100644 index 000000000..20caba227 --- /dev/null +++ b/src/tflags.h @@ -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 +class TFlags +{ + struct ZeroDummy {}; + +public: + typedef TFlags Self; + typedef T EnumType; + typedef TT IntType; + + TFlags(){} + TFlags (const Self& other) : Value (other.GetValue()) {} + TFlags (T value) : Value (static_cast (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 (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)); } \ No newline at end of file diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 302d22f68..0370545e4 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -3352,8 +3352,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn) if (flags & RSF_FOG) { - P_SpawnTeleportFog(self, oldx, oldy, oldz, true); - P_SpawnTeleportFog(self, self->x, self->y, self->z, false); + P_SpawnTeleportFog(self, oldx, oldy, oldz, true, true); + P_SpawnTeleportFog(self, self->x, self->y, self->z, false, true); } if (self->CountsAsKill()) { @@ -4072,7 +4072,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) } 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. 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, -// optional class fogtype, optional int flags, optional fixed mindist, -// optional fixed maxdist) +// A_Teleport([state teleportstate, [class targettype, +// [class fogtype, [int flags, [fixed mindist, +// [fixed maxdist]]]]]]) // // 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 @@ -4589,8 +4589,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) PARAM_INT_OPT (flags) { flags = 0; } PARAM_FIXED_OPT (mindist) { mindist = 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. if (flags & TF_RANDOMDECIDE) @@ -4600,7 +4610,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) 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)) { @@ -4624,65 +4634,78 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) 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) { return numret; } - fixed_t prevX = self->x; - fixed_t prevY = self->y; - fixed_t prevZ = self->z; + fixed_t prevX = ref->x; + fixed_t prevY = ref->y; + fixed_t prevZ = ref->z; fixed_t aboveFloor = spot->z - spot->floorz; fixed_t finalz = spot->floorz + aboveFloor; - if (spot->z + self->height > spot->ceilingz) - finalz = spot->ceilingz - self->height; + if (spot->z + ref->height > spot->ceilingz) + finalz = spot->ceilingz - ref->height; else if (spot->z < spot->floorz) finalz = spot->floorz; //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. - self->SetOrigin(spot->x, spot->y, spot->z); + ref->SetOrigin(spot->x, spot->y, finalz); tele_result = true; } + AActor *fog1 = NULL, *fog2 = NULL; if (tele_result) { - // If a fog type is defined in the parameter, or the user wants to use - // the actor's predefined fogs, and if there's no desire to be fogless, - // spawn a fog based upon settings. + //If a fog type is defined in the parameter, or the user wants to use the actor's predefined fogs, + //and if there's no desire to be fogless, spawn a fog based upon settings. if (fog_type || (flags & TF_USEACTORFOG)) - { + { if (!(flags & TF_NOSRCFOG)) { if (flags & TF_USEACTORFOG) - P_SpawnTeleportFog(self, prevX, prevY, prevZ, true); + P_SpawnTeleportFog(ref, prevX, prevY, prevZ, true, true); 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_USEACTORFOG) - P_SpawnTeleportFog(self, self->x, self->y, self->z, false); + P_SpawnTeleportFog(ref, ref->x, ref->y, ref->z, false, true); 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; if (!(flags & TF_KEEPANGLE)) - self->angle = spot->angle; + ref->angle = spot->angle; 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! if (teleport_state == NULL) diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index ca4c9b487..4ae103f86 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -59,7 +59,7 @@ static TArray AFTable; #define DEFINE_DEPRECATED_FLAG(name) { DEPF_##name, #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, SPECIAL, APlayerPawn, flags), @@ -252,6 +252,10 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF7, HITTARGET, AActor, flags7), DEFINE_FLAG(MF7, HITMASTER, 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 DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), @@ -301,7 +305,7 @@ static FFlagDef ActorFlags[]= DEFINE_DUMMY_FLAG(EXPLODEONDEATH), // seems useless }; -static FFlagDef InventoryFlags[] = +static FFlagDef InventoryFlagDefs[] = { // Inventory flags DEFINE_FLAG(IF, QUIET, AInventory, ItemFlags), @@ -328,7 +332,7 @@ static FFlagDef InventoryFlags[] = DEFINE_DEPRECATED_FLAG(PICKUPFLASH), DEFINE_DEPRECATED_FLAG(INTERHUBSTRIP),}; -static FFlagDef WeaponFlags[] = +static FFlagDef WeaponFlagDefs[] = { // Weapon flags DEFINE_FLAG(WIF, NOAUTOFIRE, AWeapon, WeaponFlags), @@ -355,7 +359,7 @@ static FFlagDef WeaponFlags[] = DEFINE_DUMMY_FLAG(ALLOW_WITH_RESPAWN_INVUL), }; -static FFlagDef PlayerPawnFlags[] = +static FFlagDef PlayerPawnFlagDefs[] = { // PlayerPawn flags DEFINE_FLAG(PPF, NOTHRUSTWHENINVUL, APlayerPawn, PlayerFlags), @@ -363,7 +367,7 @@ static FFlagDef PlayerPawnFlags[] = DEFINE_FLAG(PPF, CROUCHABLEMORPH, APlayerPawn, PlayerFlags), }; -static FFlagDef PowerSpeedFlags[] = +static FFlagDef PowerSpeedFlagDefs[] = { // PowerSpeed flags 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[] = { - { &RUNTIME_CLASS_CASTLESS(AActor), ActorFlags, countof(ActorFlags) }, - { &RUNTIME_CLASS_CASTLESS(AInventory), InventoryFlags, countof(InventoryFlags) }, - { &RUNTIME_CLASS_CASTLESS(AWeapon), WeaponFlags, countof(WeaponFlags) }, - { &RUNTIME_CLASS_CASTLESS(APlayerPawn), PlayerPawnFlags,countof(PlayerPawnFlags) }, - { &RUNTIME_CLASS_CASTLESS(APowerSpeed), PowerSpeedFlags,countof(PowerSpeedFlags) }, + { &RUNTIME_CLASS_CASTLESS(AActor), ActorFlagDefs, countof(ActorFlagDefs) }, + { &RUNTIME_CLASS_CASTLESS(AInventory), InventoryFlagDefs, countof(InventoryFlagDefs) }, + { &RUNTIME_CLASS_CASTLESS(AWeapon), WeaponFlagDefs, countof(WeaponFlagDefs) }, + { &RUNTIME_CLASS_CASTLESS(APlayerPawn), PlayerPawnFlagDefs, countof(PlayerPawnFlagDefs) }, + { &RUNTIME_CLASS_CASTLESS(APowerSpeed), PowerSpeedFlagDefs, countof(PowerSpeedFlagDefs) }, }; #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) { - 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 diff --git a/src/thingdef/thingdef_parse.cpp b/src/thingdef/thingdef_parse.cpp index 064d5a107..1db878bfa 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -680,6 +680,7 @@ static int ParseMorphStyle (FScanner &sc) { "MRF_UNDOBYDEATH", MORPH_UNDOBYDEATH}, { "MRF_UNDOBYDEATHFORCED", MORPH_UNDOBYDEATHFORCED}, { "MRF_UNDOBYDEATHSAVES", MORPH_UNDOBYDEATHSAVES}, + { "MRF_UNDOALWAYS", MORPH_UNDOALWAYS }, { NULL, 0 } }; diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index c60977b27..aec05adcd 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1085,7 +1085,7 @@ DEFINE_PROPERTY(bloodtype, Sss, Actor) DEFINE_PROPERTY(bouncetype, S, Actor) { 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_DoomCompat, BOUNCE_HereticCompat, BOUNCE_HexenCompat, BOUNCE_Grenade, BOUNCE_Classic, }; @@ -1348,13 +1348,13 @@ DEFINE_PROPERTY(species, S, Actor) //========================================================================== DEFINE_PROPERTY(clearflags, 0, Actor) { - defaults->flags = - defaults->flags3 = - defaults->flags4 = - defaults->flags5 = - defaults->flags6 = - defaults->flags7 = 0; + defaults->flags = 0; 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; } //========================================================================== diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index d993a4de7..ee07b270a 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -216,7 +216,7 @@ ACTOR Actor native //: Thinker action native A_CheckCeiling(state label); action native A_PlayerSkinCheck(state label); action native A_BasicAttack(int meleedamage, sound meleesound, class missiletype, float missileheight); - action native A_Teleport(state teleportstate = "", class targettype = "BossSpot", class fogtype = "TeleportFog", int flags = 0, float mindist = 0, float maxdist = 0); + action native A_Teleport(state teleportstate = "", class targettype = "BossSpot", class 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_ThrowGrenade(class 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); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 2f8f22344..f0b2233dd 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -140,6 +140,7 @@ const int MRF_NEWTIDBEHAVIOUR = 256; const int MRF_UNDOBYDEATH = 512; const int MRF_UNDOBYDEATHFORCED = 1024; const int MRF_UNDOBYDEATHSAVES = 2048; +const int MRF_UNDOALWAYS = 4096; // Flags for A_RailAttack and A_CustomRailgun const int RGF_SILENT = 1;