diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 50862bbe62..da8b6f2392 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1294,10 +1294,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 d45d60a98b..755ae6f3a0 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; // @@ -105,10 +106,9 @@ struct subsector_t; // Any questions? // -enum -{ // --- mobj.flags --- - +enum ActorFlag +{ MF_SPECIAL = 0x00000001, // call P_SpecialThing when touched MF_SOLID = 0x00000002, MF_SHOOTABLE = 0x00000004, @@ -152,8 +152,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 @@ -191,9 +196,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 @@ -226,9 +233,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 @@ -262,9 +271,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. /* = 0x00000002, reserved for use by scripting branch */ MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances. @@ -298,9 +310,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. @@ -333,9 +347,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. @@ -354,11 +370,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 @@ -387,10 +405,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) @@ -419,7 +433,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 @@ -473,6 +487,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 @@ -843,7 +877,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; @@ -869,13 +903,13 @@ public: FState *state; SDWORD 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; @@ -921,7 +955,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 2800c01c5d..f93625612f 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 4a436c0a88..a994f7603f 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1135,31 +1135,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]) @@ -1180,8 +1180,8 @@ static int PatchThing (int thingy) else info->renderflags &= ~RF_INVISIBLE; } - DPrintf ("Bits: %d,%d (0x%08x,0x%08x)\n", info->flags, info->flags2, - info->flags, info->flags2); + DPrintf ("Bits: %d,%d (0x%08x,0x%08x)\n", info->flags.GetValue(), info->flags2.GetValue(), + info->flags.GetValue(), info->flags2.GetValue()); } else if (stricmp (Line1, "ID #") == 0) { diff --git a/src/farchive.h b/src/farchive.h index 329b448db8..87ebf999b0 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 { @@ -333,4 +334,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 6583d15108..6fcd50341d 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 87491073ec..bc33eb19ca 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 ceffe907a2..4da6eb67bd 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, const PClass *spawntype, i 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, const PClass *spawntype, i 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, const PClass *spawntype, int duration, int s 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); const PClass *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 e86332b3dd..9272901dd2 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 83d0d46954..0f847fa417 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 3d9e4ed10f..2688249ea9 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; const PClass *MorphExitFlash; - DWORD FlagsSave; + ActorFlags FlagsSave; }; class AMapMarker : public AActor diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 519e71c002..5cd5774f49 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 @@ -1390,7 +1391,7 @@ void FBehavior::StaticLoadDefaultModules () } else { - Printf ("Could not find autoloaded ACS library %s\n", sc.String); + Printf (TEXTCOLOR_RED "Could not find autoloaded ACS library %s\n", sc.String); } } } @@ -1408,7 +1409,17 @@ FBehavior *FBehavior::StaticLoadModule (int lumpnum, FileReader *fr, int len) } } - return new FBehavior (lumpnum, fr, len); + FBehavior * behavior = new FBehavior (); + if (behavior->Init(lumpnum, fr, len)) + { + return behavior; + } + else + { + delete behavior; + Printf(TEXTCOLOR_RED "%s: invalid ACS module", Wads.GetLumpFullName(lumpnum)); + return NULL; + } } bool FBehavior::StaticCheckAllGood () @@ -1667,11 +1678,8 @@ static int ParseLocalArrayChunk(void *chunk, ACSLocalArrays *arrays, int offset) return offset; } -FBehavior::FBehavior (int lumpnum, FileReader * fr, int len) +FBehavior::FBehavior() { - BYTE *object; - int i; - NumScripts = 0; NumFunctions = 0; NumArrays = 0; @@ -1683,11 +1691,21 @@ FBehavior::FBehavior (int lumpnum, FileReader * fr, int len) Chunks = NULL; Data = NULL; Format = ACS_Unknown; - LumpNum = lumpnum; + LumpNum = -1; memset (MapVarStore, 0, sizeof(MapVarStore)); ModuleName[0] = 0; FunctionProfileData = NULL; +} + + +bool FBehavior::Init(int lumpnum, FileReader * fr, int len) +{ + BYTE *object; + int i; + + LumpNum = lumpnum; + // Now that everything is set up, record this module as being among the loaded modules. // We need to do this before resolving any imports, because an import might (indirectly) // need to resolve exports in this module. The only things that can be exported are @@ -1698,7 +1716,6 @@ FBehavior::FBehavior (int lumpnum, FileReader * fr, int len) // 1. If not, corrupt modules cause memory leaks // 2. Corrupt modules won't be reported when a level is being loaded if this function quits before // adding it to the list. - LibraryID = StaticModules.Push (this) << LIBRARYID_SHIFT; if (fr == NULL) len = Wads.LumpLength (lumpnum); @@ -1710,7 +1727,7 @@ FBehavior::FBehavior (int lumpnum, FileReader * fr, int len) // has 24 bytes if it is completely empty. An empty SPTR chunk adds 8 bytes.) if (len < 32) { - return; + return false; } object = new BYTE[len]; @@ -1726,7 +1743,7 @@ FBehavior::FBehavior (int lumpnum, FileReader * fr, int len) if (object[0] != 'A' || object[1] != 'C' || object[2] != 'S') { delete[] object; - return; + return false; } switch (object[3]) @@ -1742,8 +1759,9 @@ FBehavior::FBehavior (int lumpnum, FileReader * fr, int len) break; default: delete[] object; - return; + return false; } + LibraryID = StaticModules.Push (this) << LIBRARYID_SHIFT; if (fr == NULL) { @@ -2026,7 +2044,7 @@ FBehavior::FBehavior (int lumpnum, FileReader * fr, int len) int lump = Wads.CheckNumForName (&parse[i], ns_acslibrary); if (lump < 0) { - Printf ("Could not find ACS library %s.\n", &parse[i]); + Printf (TEXTCOLOR_RED "Could not find ACS library %s.\n", &parse[i]); } else { @@ -2067,7 +2085,7 @@ FBehavior::FBehavior (int lumpnum, FileReader * fr, int len) func->ImportNum = i+1; if (realfunc->ArgCount != func->ArgCount) { - Printf ("Function %s in %s has %d arguments. %s expects it to have %d.\n", + Printf (TEXTCOLOR_ORANGE "Function %s in %s has %d arguments. %s expects it to have %d.\n", (char *)(chunk + 2) + chunk[3+j], lib->ModuleName, realfunc->ArgCount, ModuleName, func->ArgCount); Format = ACS_Unknown; @@ -2120,7 +2138,7 @@ FBehavior::FBehavior (int lumpnum, FileReader * fr, int len) if (lib->ArrayStore[impNum].ArraySize != expectedSize) { Format = ACS_Unknown; - Printf ("The array %s in %s has %u elements, but %s expects it to only have %u.\n", + Printf (TEXTCOLOR_ORANGE "The array %s in %s has %u elements, but %s expects it to only have %u.\n", parse, lib->ModuleName, lib->ArrayStore[impNum].ArraySize, ModuleName, expectedSize); } @@ -2134,6 +2152,7 @@ FBehavior::FBehavior (int lumpnum, FileReader * fr, int len) } DPrintf ("Loaded %d scripts, %d functions\n", NumScripts, NumFunctions); + return true; } FBehavior::~FBehavior () @@ -2292,7 +2311,7 @@ void FBehavior::LoadScriptsDirectory () { if (Scripts[i].Number == Scripts[i+1].Number) { - Printf("%s appears more than once.\n", + Printf(TEXTCOLOR_ORANGE "%s appears more than once.\n", ScriptPresentation(Scripts[i].Number).GetChars()); // Make the closed version the first one. if (Scripts[i+1].Type == SCRIPT_Closed) @@ -2489,7 +2508,7 @@ bool FBehavior::IsGood () if (funcdef->Address == 0 && funcdef->ImportNum == 0) { DWORD *chunk = (DWORD *)FindChunk (MAKE_ID('F','N','A','M')); - Printf ("Could not find ACS function %s for use in %s.\n", + Printf (TEXTCOLOR_RED "Could not find ACS function %s for use in %s.\n", (char *)(chunk + 2) + chunk[3+i], ModuleName); bad = true; } @@ -2500,7 +2519,7 @@ bool FBehavior::IsGood () { if (Imports[i] == NULL) { - Printf ("Not all the libraries used by %s could be found.\n", ModuleName); + Printf (TEXTCOLOR_RED "Not all the libraries used by %s could be found.\n", ModuleName); return false; } } @@ -3349,7 +3368,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)) { @@ -5342,7 +5361,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_acs.h b/src/p_acs.h index 88016f0dbf..d5971e3497 100644 --- a/src/p_acs.h +++ b/src/p_acs.h @@ -283,8 +283,9 @@ enum ACSFormat { ACS_Old, ACS_Enhanced, ACS_LittleEnhanced, ACS_Unknown }; class FBehavior { public: - FBehavior (int lumpnum, FileReader * fr=NULL, int len=0); + FBehavior (); ~FBehavior (); + bool Init(int lumpnum, FileReader * fr = NULL, int len = 0); bool IsGood (); BYTE *FindChunk (DWORD id) const; diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index ddfa0e2ec1..46c2b9f4c9 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -894,5 +894,5 @@ void ACustomSprite::BeginPlay () if (cstat & 8) 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 540aa119e0..3e17a85f35 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -2573,7 +2573,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_interaction.cpp b/src/p_interaction.cpp index 36f50a8978..e25dcf7aca 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -660,7 +660,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) FState *diestate = NULL; int gibhealth = GibHealth(); - int iflags4 = inflictor == NULL ? 0 : inflictor->flags4; + ActorFlags4 iflags4 = inflictor == NULL ? ActorFlags4::FromInt(0) : inflictor->flags4; bool extremelydead = ((health < gibhealth || iflags4 & MF4_EXTREMEDEATH) && !(iflags4 & MF4_NOEXTREMEDEATH)); // Special check for 'extreme' damage type to ensure that it gets recorded properly as an extreme death for subsequent checks. diff --git a/src/p_local.h b/src/p_local.h index 682101e7f6..b62836c172 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -461,7 +461,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, const PClass *pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL); diff --git a/src/p_map.cpp b/src/p_map.cpp index 3d878c1f13..b76919a7de 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. @@ -4918,7 +4922,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 3afc89b110..588bc2dccf 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -481,7 +481,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 @@ -2750,10 +2750,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 (); @@ -3991,7 +3991,7 @@ AActor *AActor::StaticSpawn (const PClass *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->Speed = actor->GetClass()->Meta.GetMetaFixed(AMETA_FastSpeed, actor->Speed); @@ -6465,35 +6465,35 @@ void PrintMiscActorInfo(AActor *query) "OptFuzzy", "Stencil", "Translucent", "Add", "Shaded", "TranslucentStencil", "Shadow", "Subtract", "AddStencil", "AddShaded"}; - Printf("%s @ %p has the following flags:\n flags: %x", query->GetTag(), query, query->flags); + Printf("%s @ %p has the following flags:\n flags: %x", query->GetTag(), query, query->flags.GetValue()); for (flagi = 0; flagi <= 31; flagi++) if (query->flags & 1<flags2); + Printf("\n flags2: %x", query->flags2.GetValue()); for (flagi = 0; flagi <= 31; flagi++) if (query->flags2 & 1<flags3); + Printf("\n flags3: %x", query->flags3.GetValue()); for (flagi = 0; flagi <= 31; flagi++) if (query->flags3 & 1<flags4); + Printf("\n flags4: %x", query->flags4.GetValue()); for (flagi = 0; flagi <= 31; flagi++) if (query->flags4 & 1<flags5); + Printf("\n flags5: %x", query->flags5.GetValue()); for (flagi = 0; flagi <= 31; flagi++) if (query->flags5 & 1<flags6); + Printf("\n flags6: %x", query->flags6.GetValue()); for (flagi = 0; flagi <= 31; flagi++) if (query->flags6 & 1<flags7); + Printf("\n flags7: %x", query->flags7.GetValue()); for (flagi = 0; flagi <= 31; flagi++) if (query->flags7 & 1<BounceFlags, FIXED2FLOAT(query->bouncefactor), + query->BounceFlags.GetValue(), FIXED2FLOAT(query->bouncefactor), FIXED2FLOAT(query->wallbouncefactor)); /*for (flagi = 0; flagi < 31; flagi++) if (query->BounceFlags & 1<alpha), query->renderflags); + FIXED2FLOAT(query->alpha), query->renderflags.GetValue()); /*for (flagi = 0; flagi < 31; flagi++) if (query->renderflags & 1<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 dbf4cbeb55..5da0b89926 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 0000000000..6c549a860f --- /dev/null +++ b/src/tflags.h @@ -0,0 +1,111 @@ +/* +** 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)); } + diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index b1da8f546c..21dc930363 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2002,10 +2002,10 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags) mo->RenderStyle = self->RenderStyle; } - if (flags & SIXF_TRANSFERSPRITEFRAME) - { - mo->sprite = self->sprite; - mo->frame = self->frame; + if (flags & SIXF_TRANSFERSPRITEFRAME) + { + mo->sprite = self->sprite; + mo->frame = self->frame; } if (flags & SIXF_TRANSFERROLL) @@ -3056,8 +3056,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()) { @@ -3745,7 +3745,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); @@ -4008,19 +4008,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetPitch) ref->SetPitch(pitch, !!(flags & SPF_INTERPOLATE)); } -//=========================================================================== -// -// [Nash] A_SetRoll -// -// Set actor's roll (in degrees). -// -//=========================================================================== - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRoll) -{ - ACTION_PARAM_START(3); - ACTION_PARAM_ANGLE(roll, 0); - ACTION_PARAM_INT(flags, 1); +//=========================================================================== +// +// [Nash] A_SetRoll +// +// Set actor's roll (in degrees). +// +//=========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRoll) +{ + ACTION_PARAM_START(3); + ACTION_PARAM_ANGLE(roll, 0); + ACTION_PARAM_INT(flags, 1); ACTION_PARAM_INT(ptr, 2); AActor *ref = COPY_AAPTR(self, ptr); @@ -4029,9 +4029,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetRoll) { ACTION_SET_RESULT(false); return; - } - ref->SetRoll(roll, !!(flags & SPF_INTERPOLATE)); -} + } + ref->SetRoll(roll, !!(flags & SPF_INTERPOLATE)); +} //=========================================================================== // @@ -4228,9 +4228,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 @@ -4253,13 +4253,25 @@ enum T_Flags DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) { - ACTION_PARAM_START(6); + ACTION_PARAM_START(7); ACTION_PARAM_STATE(TeleportState, 0); ACTION_PARAM_CLASS(TargetType, 1); ACTION_PARAM_CLASS(FogType, 2); ACTION_PARAM_INT(Flags, 3); ACTION_PARAM_FIXED(MinDist, 4); ACTION_PARAM_FIXED(MaxDist, 5); + ACTION_PARAM_INT(ptr, 6); + + AActor *ref = COPY_AAPTR(self, ptr); + + if (!ref) + { + ACTION_SET_RESULT(false); + return; + } + + if (ref->flags2 & MF2_NOTELEPORT) + return; // Randomly choose not to teleport like A_Srcr2Decide. if (Flags & TF_RANDOMDECIDE) @@ -4269,7 +4281,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)) { @@ -4280,37 +4292,42 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) } DSpotState *state = DSpotState::GetSpotState(); - if (state == NULL) return; + if (state == NULL) + return; - if (!TargetType) TargetType = PClass::FindClass("BossSpot"); + if (!TargetType) + TargetType = PClass::FindClass("BossSpot"); - AActor * spot = state->GetSpotWithMinMaxDistance(TargetType, self->x, self->y, MinDist, MaxDist); - if (spot == NULL) return; + AActor * spot = state->GetSpotWithMinMaxDistance(TargetType, ref->x, ref->y, MinDist, MaxDist); + if (spot == NULL) + return; - 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 teleResult = P_TeleportMove(self, spot->x, spot->y, finalz, Flags & TF_TELEFRAG); + bool teleResult = P_TeleportMove(ref, spot->x, spot->y, finalz, Flags & TF_TELEFRAG); - if (Flags & TF_FORCED) + if (!teleResult && (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, finalz); + ref->SetOrigin(spot->x, spot->y, finalz); teleResult = true; } + AActor *fog1 = NULL, *fog2 = NULL; if (teleResult) { + //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 (FogType || (Flags & TF_USEACTORFOG)) @@ -4318,31 +4335,40 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) 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(FogType, prevX, prevY, prevZ, ALLOW_REPLACE); + { + fog1 = Spawn(FogType, 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(FogType, self->x, self->y, self->z, ALLOW_REPLACE); + { + fog2 = Spawn(FogType, ref->x, ref->y, ref->z, ALLOW_REPLACE); + if (fog2 != NULL) + fog2->target = ref; + } } + } if (Flags & TF_USESPOTZ) - self->z = spot->z; + ref->z = spot->z; else - self->z = self->floorz; + ref->z = ref->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 (TeleportState == NULL) @@ -5818,6 +5844,43 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ResetHealth) } } +//=========================================================================== +// A_JumpIfHigherOrLower +// +// Jumps if a target, master, or tracer is higher or lower than the calling +// actor. Can also specify how much higher/lower the actor needs to be than +// itself. Can also take into account the height of the actor in question, +// depending on which it's checking. This means adding height of the +// calling actor's self if the pointer is higher, or height of the pointer +// if its lower. +//=========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHigherOrLower) +{ + ACTION_PARAM_START(6); + ACTION_PARAM_STATE(high, 0); + ACTION_PARAM_STATE(low, 1); + ACTION_PARAM_FIXED(offsethigh, 2); + ACTION_PARAM_FIXED(offsetlow, 3); + ACTION_PARAM_BOOL(includeHeight, 4); + ACTION_PARAM_INT(ptr, 5); + + AActor *mobj = COPY_AAPTR(self, ptr); + + + if (!mobj || (mobj == self)) //AAPTR_DEFAULT is completely useless in this regard. + { + return; + } + ACTION_SET_RESULT(false); //No inventory jump chains please. + + if ((high) && (mobj->z > ((includeHeight ? self->height : 0) + self->z + offsethigh))) + ACTION_JUMP(high); + else if ((low) && (mobj->z + (includeHeight ? mobj->height : 0)) < (self->z + offsetlow)) + ACTION_JUMP(low); +} + + //=========================================================================== // // A_SetRipperLevel(int level) diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index e91c2ee657..a471e9985a 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -60,7 +60,7 @@ static TArray variables; #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), @@ -253,6 +253,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), @@ -302,7 +306,7 @@ static FFlagDef ActorFlags[]= DEFINE_DUMMY_FLAG(EXPLODEONDEATH), // seems useless }; -static FFlagDef InventoryFlags[] = +static FFlagDef InventoryFlagDefs[] = { // Inventory flags DEFINE_FLAG(IF, QUIET, AInventory, ItemFlags), @@ -329,7 +333,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), @@ -356,7 +360,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), @@ -364,7 +368,7 @@ static FFlagDef PlayerPawnFlags[] = DEFINE_FLAG(PPF, CROUCHABLEMORPH, APlayerPawn, PlayerFlags), }; -static FFlagDef PowerSpeedFlags[] = +static FFlagDef PowerSpeedFlagDefs[] = { // PowerSpeed flags DEFINE_FLAG(PSF, NOTRAIL, APowerSpeed, SpeedFlags), @@ -372,11 +376,11 @@ static FFlagDef PowerSpeedFlags[] = static const struct FFlagList { const PClass *Type; FFlagDef *Defs; int NumDefs; } FlagLists[] = { - { RUNTIME_CLASS(AActor), ActorFlags, countof(ActorFlags) }, - { RUNTIME_CLASS(AInventory), InventoryFlags, countof(InventoryFlags) }, - { RUNTIME_CLASS(AWeapon), WeaponFlags, countof(WeaponFlags) }, - { RUNTIME_CLASS(APlayerPawn), PlayerPawnFlags,countof(PlayerPawnFlags) }, - { RUNTIME_CLASS(APowerSpeed), PowerSpeedFlags,countof(PowerSpeedFlags) }, + { RUNTIME_CLASS(AActor), ActorFlagDefs, countof(ActorFlagDefs) }, + { RUNTIME_CLASS(AInventory), InventoryFlagDefs, countof(InventoryFlagDefs) }, + { RUNTIME_CLASS(AWeapon), WeaponFlagDefs, countof(WeaponFlagDefs) }, + { RUNTIME_CLASS(APlayerPawn), PlayerPawnFlagDefs, countof(PlayerPawnFlagDefs) }, + { RUNTIME_CLASS(APowerSpeed), PowerSpeedFlagDefs, countof(PowerSpeedFlagDefs) }, }; #define NUM_FLAG_LISTS (countof(FlagLists)) @@ -463,11 +467,11 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2) const char *GetFlagName(unsigned int flagnum, int flagoffset) { - for(unsigned i = 0; i < countof(ActorFlags); i++) + for(unsigned 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 88e6084b64..61922feaf9 100644 --- a/src/thingdef/thingdef_parse.cpp +++ b/src/thingdef/thingdef_parse.cpp @@ -526,6 +526,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 27ceeb698e..183cf27091 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -1050,7 +1050,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, }; @@ -1310,13 +1310,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/tools/lemon/lemon.c b/tools/lemon/lemon.c index f4a08f7894..5e8f03a8bc 100644 --- a/tools/lemon/lemon.c +++ b/tools/lemon/lemon.c @@ -437,7 +437,8 @@ struct acttab { #define acttab_yylookahead(X,N) ((X)->aAction[N].lookahead) /* Free all memory associated with the given acttab */ -void acttab_free(acttab *p){ +void acttab_free(acttab **pp){ + acttab *p = *pp; free( p->aAction ); free( p->aLookahead ); free( p ); @@ -2506,12 +2507,14 @@ struct lemon *gp; ErrorMsg(ps.filename,0,"Can't allocate %d of memory to hold this file.", filesize+1); gp->errorcnt++; + fclose(fp); return; } if( fread(filebuf,1,filesize,fp)!=filesize ){ ErrorMsg(ps.filename,0,"Can't read in all %d bytes of this file.", filesize); free(filebuf); + fclose(fp); gp->errorcnt++; return; } @@ -3081,9 +3084,11 @@ struct lemon *lemp; in = fopen(tpltname,"rb"); if( in==0 ){ fprintf(stderr,"Can't open the template file \"%s\".\n",templatename); + free(tpltname); lemp->errorcnt++; return 0; } + free(tpltname); return in; } @@ -3942,6 +3947,7 @@ int mhflag; /* Output in makeheaders format if true */ /* Append any addition code the user desires */ tplt_print(out,lemp,lemp->extracode,lemp->extracodeln,&lineno); + acttab_free(&pActtab); fclose(in); fclose(out); return; diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 8a31b05c0b..b7fea41898 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -248,7 +248,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); @@ -330,6 +330,7 @@ ACTOR Actor native //: Thinker action native A_SetFloatBobPhase(int bob); action native A_SetHealth(int health, int ptr = AAPTR_DEFAULT); action native A_ResetHealth(int ptr = AAPTR_DEFAULT); + action native A_JumpIfHigherOrLower(state high, state low, float offsethigh = 0, float offsetlow = 0, bool includeHeight = true, int ptr = AAPTR_TARGET); action native A_SetRipperLevel(int level); action native A_SetRipMin(int min); action native A_SetRipMax(int max); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index e6434a08ea..2ded98bc77 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;