diff --git a/bzip2/CMakeLists.txt b/bzip2/CMakeLists.txt index 5c125560..f96c97a8 100644 --- a/bzip2/CMakeLists.txt +++ b/bzip2/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required( VERSION 2.4 ) if( CMAKE_COMPILER_IS_GNUC ) - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer -Wshadow -Wfloat-equal -Wcast-qual" ) endif( CMAKE_COMPILER_IS_GNUC ) add_definitions( -DBZ_NO_STDIO ) diff --git a/dumb/CMakeLists.txt b/dumb/CMakeLists.txt index c2cbe8d1..82504e2f 100644 --- a/dumb/CMakeLists.txt +++ b/dumb/CMakeLists.txt @@ -12,7 +12,7 @@ endif( NOT CMAKE_BUILD_TYPE MATCHES "Release" ) set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -DDEBUGMODE=1" ) if( CMAKE_COMPILER_IS_GNUC ) - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-pointer-sign -Wno-uninitialized" ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-pointer-sign -Wno-uninitialized -Wshadow -Wfloat-equal -Wcast-qual" ) endif( CMAKE_COMPILER_IS_GNUC ) CHECK_FUNCTION_EXISTS( itoa ITOA_EXISTS ) diff --git a/game-music-emu/CMakeLists.txt b/game-music-emu/CMakeLists.txt index 7905f847..1f171c49 100644 --- a/game-music-emu/CMakeLists.txt +++ b/game-music-emu/CMakeLists.txt @@ -7,7 +7,7 @@ if( NOT CMAKE_BUILD_TYPE MATCHES "Release" ) endif( NOT CMAKE_BUILD_TYPE MATCHES "Release" ) if( CMAKE_COMPILER_IS_GNUCXX ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wshadow -Wfloat-equal -Wcast-qual" ) if( NOT PROFILE ) set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fomit-frame-pointer" ) endif( NOT PROFILE ) diff --git a/gdtoa/CMakeLists.txt b/gdtoa/CMakeLists.txt index 6fc394d8..bfb60fd1 100644 --- a/gdtoa/CMakeLists.txt +++ b/gdtoa/CMakeLists.txt @@ -9,7 +9,7 @@ if( MSVC ) endif( MSVC ) if( CMAKE_COMPILER_IS_GNUCXX ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wshadow -Wfloat-equal -Wcast-qual" ) endif( CMAKE_COMPILER_IS_GNUCXX ) include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) diff --git a/jpeg-6b/CMakeLists.txt b/jpeg-6b/CMakeLists.txt index c3a5f458..557d7073 100644 --- a/jpeg-6b/CMakeLists.txt +++ b/jpeg-6b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required( VERSION 2.4 ) if( CMAKE_COMPILER_IS_GNUC ) - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wfloat-equal -Wcast-qual -fomit-frame-pointer" ) endif( CMAKE_COMPILER_IS_GNUC ) add_library( jpeg diff --git a/lzma/CMakeLists.txt b/lzma/CMakeLists.txt index 6a2561c6..49bec873 100644 --- a/lzma/CMakeLists.txt +++ b/lzma/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required( VERSION 2.4 ) if( CMAKE_COMPILER_IS_GNUC ) - set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -fomit-frame-pointer" ) + set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wfloat-equal -Wcast-qual -fomit-frame-pointer" ) endif( CMAKE_COMPILER_IS_GNUC ) set( LZMA_FILES diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 62f90b90..669c39e8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -410,7 +410,7 @@ if( CMAKE_COMPILER_IS_GNUCXX ) set( CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} ${REL_CXX_FLAGS}" ) set( CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${REL_CXX_FLAGS}" ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused -Wextra -Wno-missing-field-initializers" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unused -Wextra -Wno-missing-field-initializers -Wshadow -Wfloat-equal -Wcast-qual" ) # Remove extra warnings when using the official DirectX headers. # Also, TDM-GCC 4.4.0 no longer accepts glibc-style printf formats as valid, diff --git a/src/actor.h b/src/actor.h index d23644a2..249560c0 100644 --- a/src/actor.h +++ b/src/actor.h @@ -326,6 +326,8 @@ enum MF6_ADDITIVEPOISONDURATION = 0x00200000, MF6_NOMENU = 0x00400000, // Player class should not appear in the class selection menu. MF6_BOSSCUBE = 0x00800000, // Actor spawned by A_BrainSpit, flagged for timefreeze reasons. + MF6_SEEINVISIBLE = 0x01000000, // Monsters can see invisible player. + MF6_DONTCORPSE = 0x02000000, // [RC] Don't autoset MF_CORPSE upon death and don't force Crash state change. // --- mobj.renderflags --- @@ -905,6 +907,7 @@ public: SWORD PainChance; int PainThreshold; FNameNoInit DamageType; + FNameNoInit DamageTypeReceived; fixed_t DamageFactor; FState *SpawnState; diff --git a/src/actorptrselect.h b/src/actorptrselect.h new file mode 100644 index 00000000..8cc05f2d --- /dev/null +++ b/src/actorptrselect.h @@ -0,0 +1,118 @@ +#pragma once + +#include "p_pspr.h" + +//========================================================================== +// +// Standard pointer acquisition functions +// +// Use COPY_AAPTR(pointer_owner, AActor *assigntovariable, AAPTR selector) +// Use COPY_AAPTR_NOT_NULL to return from a function if the pointer is NULL +// +// Possible effective results at run-time +// assigntovariable = NULL (or a RETURN statement is issued) +// P_BulletSlope(pointer_owner, &temporary), assigntovariable = temporary +// assigntovariable = pointer_owner->target or ...->master or ...->tracer +// +//========================================================================== + + +// Pointer selectors (enum) + +enum AAPTR +{ + AAPTR_DEFAULT = 0, + AAPTR_NULL = 0x1, + AAPTR_TARGET = 0x2, + AAPTR_MASTER = 0x4, + AAPTR_TRACER = 0x8, + + AAPTR_PLAYER_GETTARGET = 0x10, + AAPTR_PLAYER_GETCONVERSATION = 0x20, + + AAPTR_PLAYER1 = 0x40, + AAPTR_PLAYER2 = 0x80, + AAPTR_PLAYER3 = 0x100, + AAPTR_PLAYER4 = 0x200, + AAPTR_PLAYER5 = 0x400, + AAPTR_PLAYER6 = 0x800, + AAPTR_PLAYER7 = 0x1000, + AAPTR_PLAYER8 = 0x2000, + + AAPTR_FRIENDPLAYER = 0x4000, + + AAPTR_PLAYER_SELECTORS = + AAPTR_PLAYER_GETTARGET|AAPTR_PLAYER_GETCONVERSATION, + + AAPTR_GENERAL_SELECTORS = + AAPTR_TARGET|AAPTR_MASTER|AAPTR_TRACER|AAPTR_FRIENDPLAYER, + + AAPTR_STATIC_SELECTORS = + AAPTR_PLAYER1|AAPTR_PLAYER2|AAPTR_PLAYER3|AAPTR_PLAYER4| + AAPTR_PLAYER5|AAPTR_PLAYER6|AAPTR_PLAYER7|AAPTR_PLAYER8| + AAPTR_NULL + +}; + +/* + PROCESS_AAPTR + + Result overview in order of priority: + + 1. Caller is player and a player specific selector is specified: Player specific selector is used. + 2. Caller is non-null and a general actor selector is specified: General actor selector is used. + 3. A static actor selector is specified: Static actor selector is used. + 4. The origin actor is used. + + Only one selector of each type can be used. +*/ + +#define AAPTR_RESOLVE_PLAYERNUM(playernum) (playeringame[playernum] ? players[playernum].mo : NULL) + +static AActor *PROCESS_AAPTR(AActor *origin, int selector) +{ + if (origin) + { + if (origin->player) + { + switch (selector & AAPTR_PLAYER_SELECTORS) + { + case AAPTR_PLAYER_GETTARGET: + { + AActor *gettarget = NULL; + P_BulletSlope(origin, &gettarget); + return gettarget; + } + case AAPTR_PLAYER_GETCONVERSATION: + return origin->player->ConversationNPC; + } + } + + switch (selector & AAPTR_GENERAL_SELECTORS) + { + case AAPTR_TARGET: return origin->target; + case AAPTR_MASTER: return origin->master; + case AAPTR_TRACER: return origin->tracer; + case AAPTR_FRIENDPLAYER: + return origin->FriendPlayer ? AAPTR_RESOLVE_PLAYERNUM(origin->FriendPlayer - 1) : NULL; + } + } + + switch (selector & AAPTR_STATIC_SELECTORS) + { + case AAPTR_PLAYER1: return AAPTR_RESOLVE_PLAYERNUM(0); + case AAPTR_PLAYER2: return AAPTR_RESOLVE_PLAYERNUM(1); + case AAPTR_PLAYER3: return AAPTR_RESOLVE_PLAYERNUM(2); + case AAPTR_PLAYER4: return AAPTR_RESOLVE_PLAYERNUM(3); + case AAPTR_PLAYER5: return AAPTR_RESOLVE_PLAYERNUM(4); + case AAPTR_PLAYER6: return AAPTR_RESOLVE_PLAYERNUM(5); + case AAPTR_PLAYER7: return AAPTR_RESOLVE_PLAYERNUM(6); + case AAPTR_PLAYER8: return AAPTR_RESOLVE_PLAYERNUM(7); + case AAPTR_NULL: return NULL; + } + + return origin; +} + +#define COPY_AAPTR_NOT_NULL(source, destination, selector) { destination = PROCESS_AAPTR(source, selector); if (!destination) return; } +#define COPY_AAPTR(source, destination, selector) { destination = PROCESS_AAPTR(source, selector); } \ No newline at end of file diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 232e91f3..32df6a53 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -336,6 +336,7 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size) info->StateList = NULL; info->DamageFactors = NULL; info->PainChances = NULL; + info->PainFlashes = NULL; info->ColorSets = NULL; m_RuntimeActors.Push (type); } @@ -430,6 +431,7 @@ void PClass::InitializeActorInfo () info->StateList = NULL; info->DamageFactors = NULL; info->PainChances = NULL; + info->PainFlashes = NULL; info->ColorSets = NULL; m_RuntimeActors.Push (this); } diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp index 0f4ec474..55451a89 100644 --- a/src/g_doom/a_painelemental.cpp +++ b/src/g_doom/a_painelemental.cpp @@ -22,11 +22,18 @@ static const PClass *GetSpawnType(DECLARE_PARAMINFO) } +enum PA_Flags +{ + PAF_NOSKULLATTACK = 1, + PAF_AIMFACING = 2, + PAF_NOTARGET = 4, +}; + // // A_PainShootSkull // Spawn a lost soul and launch it at the target // -void A_PainShootSkull (AActor *self, angle_t angle, const PClass *spawntype) +void A_PainShootSkull (AActor *self, angle_t angle, const PClass *spawntype, int flags = 0, int limit = -1) { fixed_t x, y, z; @@ -50,11 +57,14 @@ void A_PainShootSkull (AActor *self, angle_t angle, const PClass *spawntype) } // [RH] make this optional - if (i_compatflags & COMPATF_LIMITPAIN) + if (limit == -1 && (i_compatflags & COMPATF_LIMITPAIN)) + limit = 21; + + if (limit) { // count total number of skulls currently on the level // if there are already 21 skulls on the level, don't spit another one - int count = 21; + int count = limit; FThinkerIterator iterator (spawntype); DThinker *othink; @@ -124,9 +134,10 @@ void A_PainShootSkull (AActor *self, angle_t angle, const PClass *spawntype) } // [RH] Lost souls hate the same things as their pain elementals - other->CopyFriendliness (self, true); + other->CopyFriendliness (self, !(flags & PAF_NOTARGET)); - A_SkullAttack(other, SKULLSPEED); + if (!(flags & PAF_NOSKULLATTACK)) + A_SkullAttack(other, SKULLSPEED); } @@ -139,9 +150,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PainAttack) if (!self->target) return; - const PClass *spawntype = GetSpawnType(PUSH_PARAMINFO); - A_FaceTarget (self); - A_PainShootSkull (self, self->angle, spawntype); + ACTION_PARAM_START(4); + ACTION_PARAM_CLASS(spawntype, 0); + ACTION_PARAM_ANGLE(angle, 1); + ACTION_PARAM_INT(flags, 2); + ACTION_PARAM_INT(limit, 3); + + if (spawntype == NULL) spawntype = PClass::FindClass("LostSoul"); + + if (!(flags & PAF_AIMFACING)) + A_FaceTarget (self); + A_PainShootSkull (self, self->angle+angle, spawntype, flags, limit); } DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DualPainAttack) diff --git a/src/g_shared/a_lightning.cpp b/src/g_shared/a_lightning.cpp index 99de24c2..9e285577 100644 --- a/src/g_shared/a_lightning.cpp +++ b/src/g_shared/a_lightning.cpp @@ -21,7 +21,7 @@ DLightningThinker::DLightningThinker () LightningFlashCount = 0; NextLightningFlash = ((pr_lightning()&15)+5)*35; // don't flash at level start - LightningLightLevels = new BYTE[numsectors + (numsectors+7)/8]; + LightningLightLevels = new short[numsectors + (numsectors+7)/8]; memset (LightningLightLevels, 0, numsectors + (numsectors+7)/8); } @@ -36,7 +36,7 @@ DLightningThinker::~DLightningThinker () void DLightningThinker::Serialize (FArchive &arc) { int i; - BYTE *lights; + short *lights; Super::Serialize (arc); @@ -48,12 +48,21 @@ void DLightningThinker::Serialize (FArchive &arc) { delete[] LightningLightLevels; } - LightningLightLevels = new BYTE[numsectors + (numsectors+7)/8]; + LightningLightLevels = new short[numsectors + (numsectors+7)/8]; } lights = LightningLightLevels; for (i = (numsectors + (numsectors+7)/8); i > 0; ++lights, --i) { - arc << *lights; + if (SaveVersion < 3223) + { + BYTE bytelight; + arc << bytelight; + *lights = bytelight; + } + else + { + arc << *lights; + } } } diff --git a/src/g_shared/a_lightning.h b/src/g_shared/a_lightning.h index 4e3a08eb..990d21fb 100644 --- a/src/g_shared/a_lightning.h +++ b/src/g_shared/a_lightning.h @@ -24,7 +24,7 @@ protected: int NextLightningFlash; int LightningFlashCount; bool Stopped; - BYTE *LightningLightLevels; + short *LightningLightLevels; }; void P_StartLightning (); diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 3091d63e..b1dff41b 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -1546,17 +1546,26 @@ void DBaseStatusBar::BlendView (float blend[4]) BPART(gameinfo.pickupcolor)/255.f, cnt > 128 ? 0.5f : cnt / 255.f, blend); } - if (CPlayer->mo->DamageFade.a != 0) + PainFlashList * pfl = CPlayer->mo->GetClass()->ActorInfo->PainFlashes; + PalEntry painFlash = CPlayer->mo->DamageFade; + + if (pfl) { - cnt = DamageToAlpha[MIN (113, CPlayer->damagecount * CPlayer->mo->DamageFade.a / 255)]; + PalEntry * color = pfl->CheckKey(CPlayer->mo->DamageTypeReceived); + + if (color) painFlash = *color; + } + + if (painFlash.a != 0) + { + cnt = DamageToAlpha[MIN (113, CPlayer->damagecount * painFlash.a / 255)]; if (cnt) { if (cnt > 228) cnt = 228; - APlayerPawn *mo = CPlayer->mo; - AddBlend (mo->DamageFade.r / 255.f, mo->DamageFade.g / 255.f, mo->DamageFade.b / 255.f, cnt / 255.f, blend); + AddBlend (painFlash.r / 255.f, painFlash.g / 255.f, painFlash.b / 255.f, cnt / 255.f, blend); } } diff --git a/src/gl/dynlights/gl_glow.cpp b/src/gl/dynlights/gl_glow.cpp index 10af7782..4543b822 100644 --- a/src/gl/dynlights/gl_glow.cpp +++ b/src/gl/dynlights/gl_glow.cpp @@ -125,7 +125,7 @@ int gl_CheckSpriteGlow(FTextureID floorpic, int lightlevel, fixed_t floordiff) { if (floordiff < tex->gl_info.GlowHeight*FRACUNIT && tex->gl_info.GlowHeight != 0) { - int maxlight=(255+lightlevel)>>1; + int maxlight = (255+lightlevel)>>1; fixed_t lightfrac = floordiff / tex->gl_info.GlowHeight; if (lightfrac<0) lightfrac=0; lightlevel= (lightfrac*lightlevel + maxlight*(FRACUNIT-lightfrac))>>FRACBITS; diff --git a/src/gl/renderer/gl_lightdata.h b/src/gl/renderer/gl_lightdata.h index 756d1f15..ec41872c 100644 --- a/src/gl/renderer/gl_lightdata.h +++ b/src/gl/renderer/gl_lightdata.h @@ -8,6 +8,11 @@ bool gl_BrightmapsActive(); bool gl_GlowActive(); +inline int gl_ClampLight(int lightlevel) +{ + return clamp(lightlevel, 0, 255); +} + void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblending, int *tm, int *sb, int *db, int *be); void gl_SetFogParams(int _fogdensity, PalEntry _outsidefogcolor, int _outsidefogdensity, int _skyfog); diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp index 755a6793..bb4e320c 100644 --- a/src/gl/scene/gl_flats.cpp +++ b/src/gl/scene/gl_flats.cpp @@ -511,8 +511,8 @@ void GLFlat::Process(sector_t * model, int whichplane, bool fog) } else { - gltexture=NULL; - lightlevel=abs(lightlevel); + gltexture = NULL; + lightlevel = abs(lightlevel); } // get height from vplane @@ -599,7 +599,7 @@ void GLFlat::ProcessSector(sector_t * frontsector) srf |= SSRF_RENDERFLOOR; - lightlevel = GetFloorLight(frontsector); + lightlevel = gl_ClampLight(GetFloorLight(frontsector)); Colormap=frontsector->ColorMap; if ((stack = (frontsector->portals[sector_t::floor] != NULL))) { @@ -647,7 +647,7 @@ void GLFlat::ProcessSector(sector_t * frontsector) srf |= SSRF_RENDERCEILING; - lightlevel = GetCeilingLight(frontsector); + lightlevel = gl_ClampLight(GetCeilingLight(frontsector)); Colormap=frontsector->ColorMap; if ((stack = (frontsector->portals[sector_t::ceiling] != NULL))) { @@ -766,7 +766,7 @@ void GLFlat::ProcessSector(sector_t * frontsector) if (rover->flags&FF_FIX) { - lightlevel = rover->model->lightlevel; + lightlevel = gl_ClampLight(rover->model->lightlevel); Colormap = rover->GetColormap(); } diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 71ba989d..ab19e549 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -675,9 +675,9 @@ void GLSprite::Process(AActor* thing,sector_t * sector) (thing->renderflags & RF_FULLBRIGHT) && (!gl_BrightmapsActive() || !gltexture || !gltexture->tex->gl_info.bBrightmapDisablesFullbright); - lightlevel=fullbright? 255 : rendersector->GetTexture(sector_t::ceiling) == skyflatnum ? - GetCeilingLight(rendersector) : GetFloorLight(rendersector); //rendersector->lightlevel; - foglevel = rendersector->lightlevel; + lightlevel=fullbright? 255 : + gl_ClampLight(rendersector->GetTexture(sector_t::ceiling) == skyflatnum ? GetCeilingLight(rendersector) : GetFloorLight(rendersector)); + foglevel = (BYTE)clamp(rendersector->lightlevel, 0, 255); lightlevel = (byte)gl_CheckSpriteGlow(rendersector->GetTexture(sector_t::floor), lightlevel, thingz-thing->floorz); @@ -862,8 +862,7 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s if (particle->trans==0) return; - lightlevel = sector->GetTexture(sector_t::ceiling) == skyflatnum ? - GetCeilingLight(sector) : GetFloorLight(sector); + lightlevel = gl_ClampLight(sector->GetTexture(sector_t::ceiling) == skyflatnum ? GetCeilingLight(sector) : GetFloorLight(sector)); foglevel = sector->lightlevel; if (gl_fixedcolormap) diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index 2d53c677..b4d82e9d 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -508,7 +508,7 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2) { type = RENDERWALL_HORIZON; hi.plane.GetFromSector(fs, true); - hi.lightlevel = GetCeilingLight(fs); + hi.lightlevel = gl_ClampLight(GetCeilingLight(fs)); hi.colormap = fs->ColorMap; if (fs->e->XFloor.ffloors.Size()) @@ -537,7 +537,7 @@ bool GLWall::DoHorizon(seg_t * seg,sector_t * fs, vertex_t * v1,vertex_t * v2) { type = RENDERWALL_HORIZON; hi.plane.GetFromSector(fs, false); - hi.lightlevel = GetFloorLight(fs); + hi.lightlevel = gl_ClampLight(GetFloorLight(fs)); hi.colormap = fs->ColorMap; if (fs->e->XFloor.ffloors.Size()) @@ -1513,7 +1513,7 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector) flags = (!gl_isBlack(Colormap.FadeColor) || level.flags&LEVEL_HASFADETABLE)? GLWF_FOGGY : 0; int rel = 0; - lightlevel = seg->sidedef->GetLightLevel(!!(flags&GLWF_FOGGY), frontsector->lightlevel, &rel); + lightlevel = seg->sidedef->GetLightLevel(!!(flags&GLWF_FOGGY), gl_ClampLight(frontsector->lightlevel), &rel); rellight = rel; alpha=1.0f; @@ -1748,7 +1748,7 @@ void GLWall::ProcessLowerMiniseg(seg_t *seg, sector_t * frontsector, sector_t * flags = (!gl_isBlack(Colormap.FadeColor) || level.flags&LEVEL_HASFADETABLE)? GLWF_FOGGY : 0; // can't do fake contrast without a sidedef - lightlevel = frontsector->lightlevel; + lightlevel = gl_ClampLight(frontsector->lightlevel); rellight = 0; alpha = 1.0f; diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index f5f30551..b12d8a3d 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -216,7 +216,7 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) fakesec = gl_FakeFlat(viewsector, &fs, false); // calculate light level for weapon sprites - lightlevel = fakesec->lightlevel; + lightlevel = gl_ClampLight(fakesec->lightlevel); lightlevel = gl_CheckSpriteGlow(viewsector->GetTexture(sector_t::floor), lightlevel, playermo->z-playermo->floorz); diff --git a/src/info.cpp b/src/info.cpp index 32aa92a9..21e75636 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -313,6 +313,19 @@ void FActorInfo::SetPainChance(FName type, int chance) // //========================================================================== +void FActorInfo::SetPainFlash(FName type, PalEntry color) +{ + if (PainFlashes == NULL) + PainFlashes = new PainFlashList; + + PainFlashes->Insert(type, color); +} + +//========================================================================== +// +// +//========================================================================== + void FActorInfo::SetColorSet(int index, const FPlayerColorSet *set) { if (set != NULL) diff --git a/src/info.h b/src/info.h index 9480f5f5..c2d4f4cc 100644 --- a/src/info.h +++ b/src/info.h @@ -171,6 +171,7 @@ struct FPlayerColorSet typedef TMap DmgFactors; typedef TMap PainChanceList; +typedef TMap PainFlashList; typedef TMap FPlayerColorSetMap; struct FActorInfo @@ -183,6 +184,7 @@ struct FActorInfo void RegisterIDs (); void SetDamageFactor(FName type, fixed_t factor); void SetPainChance(FName type, int chance); + void SetPainFlash(FName type, PalEntry color); void SetColorSet(int index, const FPlayerColorSet *set); FState *FindState (int numnames, FName *names, bool exact=false) const; @@ -206,6 +208,7 @@ struct FActorInfo FStateLabels *StateList; DmgFactors *DamageFactors; PainChanceList *PainChances; + PainFlashList *PainFlashes; FPlayerColorSetMap *ColorSets; }; diff --git a/src/p_3dfloors.h b/src/p_3dfloors.h index 62b35a7b..49df686e 100644 --- a/src/p_3dfloors.h +++ b/src/p_3dfloors.h @@ -83,7 +83,7 @@ struct F3DFloor planeref bottom; planeref top; - unsigned char *toplightlevel; + short *toplightlevel; fixed_t delta; @@ -111,7 +111,7 @@ struct F3DFloor struct lightlist_t { secplane_t plane; - unsigned char * p_lightlevel; + short * p_lightlevel; FDynamicColormap * extra_colormap; PalEntry blend; int flags; diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 0931c4d5..19d32626 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1667,19 +1667,24 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) continue; } - if ((player->mo->flags & MF_SHADOW && !(i_compatflags & COMPATF_INVISIBILITY)) || - player->mo->flags3 & MF3_GHOST) + // [RC] Well, let's let special monsters with this flag active be able to see + // the player then, eh? + if(!(actor->flags & MF6_SEEINVISIBLE)) { - if ((P_AproxDistance (player->mo->x - actor->x, - player->mo->y - actor->y) > 2*MELEERANGE) - && P_AproxDistance (player->mo->velx, player->mo->vely) - < 5*FRACUNIT) - { // Player is sneaking - can't detect - return false; - } - if (pr_lookforplayers() < 225) - { // Player isn't sneaking, but still didn't detect - return false; + if ((player->mo->flags & MF_SHADOW && !(i_compatflags & COMPATF_INVISIBILITY)) || + player->mo->flags3 & MF3_GHOST) + { + if ((P_AproxDistance (player->mo->x - actor->x, + player->mo->y - actor->y) > 2*MELEERANGE) + && P_AproxDistance (player->mo->velx, player->mo->vely) + < 5*FRACUNIT) + { // Player is sneaking - can't detect + return false; + } + if (pr_lookforplayers() < 225) + { // Player isn't sneaking, but still didn't detect + return false; + } } } @@ -2757,7 +2762,7 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn) } // This will never work well if the turn angle is limited. - if (max_turn == 0 && (self->angle == other_angle) && other->flags & MF_SHADOW) + if (max_turn == 0 && (self->angle == other_angle) && other->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE) ) { self->angle += pr_facetarget.Random2() << 21; } @@ -2846,10 +2851,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail) self->target->x - self->target->velx * 3, self->target->y - self->target->vely * 3); - if (self->target->flags & MF_SHADOW) - { + if (self->target->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE)) + { self->angle += pr_railface.Random2() << 21; - } + } P_RailAttack (self, self->GetMissileDamage (0, 1), 0); self->pitch = saved_pitch; diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index b39a4017..0306f866 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -384,7 +384,8 @@ void AActor::Die (AActor *source, AActor *inflictor) { // [RH] Only monsters get to be corpses. // Objects with a raise state should get the flag as well so they can // be revived by an Arch-Vile. Batman Doom needs this. - flags |= MF_CORPSE; + // [RC] And disable this if DONTCORPSE is set, of course. + if(!(flags6 & MF6_DONTCORPSE)) flags |= MF_CORPSE; } flags6 |= MF6_KILLED; @@ -948,7 +949,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage return; } player = target->player; - if (player && damage > 1) + if (player && damage > 1 && damage < TELEFRAG_DAMAGE) { // Take half damage in trainer mode damage = FixedMul(damage, G_SkillProperty(SKILLP_DamageFactor)); @@ -1209,6 +1210,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage // // the damage has been dealt; now deal with the consequences // + target->DamageTypeReceived = mod; // If the damaging player has the power of drain, give the player 50% of the damage // done in health. diff --git a/src/p_lights.cpp b/src/p_lights.cpp index f437f4c7..ba5bdf1a 100644 --- a/src/p_lights.cpp +++ b/src/p_lights.cpp @@ -110,15 +110,15 @@ DFireFlicker::DFireFlicker (sector_t *sector) : DLighting (sector) { m_MaxLight = sector->lightlevel; - m_MinLight = MIN (sector->FindMinSurroundingLight (sector->lightlevel)+16, 255); + m_MinLight = sector_t::ClampLight(sector->FindMinSurroundingLight(sector->lightlevel) + 16); m_Count = 4; } DFireFlicker::DFireFlicker (sector_t *sector, int upper, int lower) : DLighting (sector) { - m_MaxLight = clamp (upper, 0, 255); - m_MinLight = clamp (lower, 0, 255); + m_MaxLight = sector_t::ClampLight(upper); + m_MinLight = sector_t::ClampLight(lower); m_Count = 4; } @@ -260,8 +260,8 @@ DLightFlash::DLightFlash (sector_t *sector, int min, int max) : DLighting (sector) { // Use specified light levels. - m_MaxLight = clamp (max, 0, 255); - m_MinLight = clamp (min, 0, 255); + m_MaxLight = sector_t::ClampLight(max); + m_MinLight = sector_t::ClampLight(min); m_MaxTime = 64; m_MinTime = 7; m_Count = (pr_lightflash() & m_MaxTime) + 1; @@ -320,8 +320,8 @@ DStrobe::DStrobe (sector_t *sector, int upper, int lower, int utics, int ltics) { m_DarkTime = ltics; m_BrightTime = utics; - m_MaxLight = clamp (upper, 0, 255); - m_MinLight = clamp (lower, 0, 255); + m_MaxLight = sector_t::ClampLight(upper); + m_MinLight = sector_t::ClampLight(lower); m_Count = 1; // Hexen-style is always in sync } @@ -513,7 +513,7 @@ void EV_LightTurnOnPartway (int tag, fixed_t frac) // // [RH] New function to adjust tagged sectors' light levels // by a relative amount. Light levels are clipped to -// within the range 0-255 inclusive. +// be within range for sector_t::lightlevel. // //----------------------------------------------------------------------------- @@ -523,8 +523,7 @@ void EV_LightChange (int tag, int value) while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0) { - int newlight = sectors[secnum].lightlevel + value; - sectors[secnum].SetLightLevel(newlight); + sectors[secnum].SetLightLevel(sectors[secnum].lightlevel + value); } } @@ -651,8 +650,8 @@ void DGlow2::Tick () DGlow2::DGlow2 (sector_t *sector, int start, int end, int tics, bool oneshot) : DLighting (sector) { - m_Start = clamp (start, 0, 255); - m_End = clamp (end, 0, 255); + m_Start = sector_t::ClampLight(start); + m_End = sector_t::ClampLight(end); m_MaxTics = tics; m_Tics = -1; m_OneShot = oneshot; diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 187de226..9cd2a34b 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -721,15 +721,12 @@ line_t *FBlockLinesIterator::Next() { line_t *ld = &lines[*list]; + list++; if (ld->validcount != validcount) { ld->validcount = validcount; return ld; } - else - { - list++; - } } } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index bc751e47..eba8ce57 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5071,7 +5071,8 @@ AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, th->velz = (fixed_t)(velocity.Z); // invisible target: rotate velocity vector in 2D - if (dest->flags & MF_SHADOW) + // [RC] Now monsters can aim at invisible player as if they were fully visible. + if (dest->flags & MF_SHADOW && !(source->flags6 & MF6_SEEINVISIBLE)) { angle_t an = pr_spawnmissile.Random2 () << 20; an >>= ANGLETOFINESHIFT; @@ -5484,6 +5485,9 @@ int AActor::GibHealth() void AActor::Crash() { + // [RC] Weird that this forces the Crash state regardless of flag. + if(!(flags6 & MF6_DONTCORPSE)) + { if (((flags & MF_CORPSE) || (flags6 & MF6_KILLED)) && !(flags3 & MF3_CRASHED) && !(flags & MF_ICECORPSE)) @@ -5510,6 +5514,7 @@ void AActor::Crash() // so this code doesn't have to be executed repeatedly. flags3 |= MF3_CRASHED; } + } } void AActor::SetIdle() diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 606acdb2..8b8c5bcd 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -660,10 +660,16 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Raise) // // A_GunFlash // +enum GF_Flags +{ + GFF_NOEXTCHANGE = 1, +}; + DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_GunFlash) { - ACTION_PARAM_START(1) + ACTION_PARAM_START(2) ACTION_PARAM_STATE(flash, 0); + ACTION_PARAM_INT(Flags, 1); player_t *player = self->player; @@ -671,7 +677,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_GunFlash) { return; } - player->mo->PlayAttacking2 (); + if(!(Flags & GFF_NOEXTCHANGE)) player->mo->PlayAttacking2 (); if (flash == NULL) { diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index a8d01acf..42523a32 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -315,9 +315,18 @@ void P_SerializeWorld (FArchive &arc) for (i = 0, sec = sectors; i < numsectors; i++, sec++) { arc << sec->floorplane - << sec->ceilingplane - << sec->lightlevel - << sec->special + << sec->ceilingplane; + if (SaveVersion < 3223) + { + BYTE bytelight; + arc << bytelight; + sec->lightlevel = bytelight; + } + else + { + arc << sec->lightlevel; + } + arc << sec->special << sec->tag << sec->soundtraversed << sec->seqType diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 22d1e4d5..1f4953c1 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1485,7 +1485,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex) ss->ceilingplane.ic = -FRACUNIT; SetTexture(ss, i, sector_t::floor, ms->floorpic, missingtex); SetTexture(ss, i, sector_t::ceiling, ms->ceilingpic, missingtex); - ss->lightlevel = (BYTE)clamp (LittleShort(ms->lightlevel), (short)0, (short)255); + ss->lightlevel = LittleShort(ms->lightlevel); if (map->HasBehavior) ss->special = LittleShort(ms->special); else // [RH] Translate to new sector special diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 91d531a3..f052a2e3 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -695,12 +695,12 @@ public: void Tick (); protected: - static void DoTransfer (BYTE level, int target, bool floor); + static void DoTransfer (int level, int target, bool floor); - BYTE LastLight; sector_t *Source; int TargetTag; bool CopyFloor; + short LastLight; }; IMPLEMENT_CLASS (DLightTransfer) @@ -708,7 +708,17 @@ IMPLEMENT_CLASS (DLightTransfer) void DLightTransfer::Serialize (FArchive &arc) { Super::Serialize (arc); - arc << LastLight << Source << TargetTag << CopyFloor; + if (SaveVersion < 3223) + { + BYTE bytelight; + arc << bytelight; + LastLight = bytelight; + } + else + { + arc << LastLight; + } + arc << Source << TargetTag << CopyFloor; } DLightTransfer::DLightTransfer (sector_t *srcSec, int target, bool copyFloor) @@ -735,7 +745,7 @@ DLightTransfer::DLightTransfer (sector_t *srcSec, int target, bool copyFloor) void DLightTransfer::Tick () { - BYTE light = Source->lightlevel; + int light = Source->lightlevel; if (light != LastLight) { @@ -744,7 +754,7 @@ void DLightTransfer::Tick () } } -void DLightTransfer::DoTransfer (BYTE level, int target, bool floor) +void DLightTransfer::DoTransfer (int level, int target, bool floor) { int secnum; @@ -778,12 +788,12 @@ public: void Tick (); protected: - static void DoTransfer (BYTE level, int target, BYTE flags); + static void DoTransfer (short level, int target, BYTE flags); - BYTE LastLight; - BYTE Flags; sector_t *Source; int TargetID; + short LastLight; + BYTE Flags; }; IMPLEMENT_CLASS (DWallLightTransfer) @@ -791,7 +801,17 @@ IMPLEMENT_CLASS (DWallLightTransfer) void DWallLightTransfer::Serialize (FArchive &arc) { Super::Serialize (arc); - arc << LastLight << Source << TargetID << Flags; + if (SaveVersion < 3223) + { + BYTE bytelight; + arc << bytelight; + LastLight = bytelight; + } + else + { + arc << LastLight; + } + arc << Source << TargetID << Flags; } DWallLightTransfer::DWallLightTransfer (sector_t *srcSec, int target, BYTE flags) @@ -802,10 +822,16 @@ DWallLightTransfer::DWallLightTransfer (sector_t *srcSec, int target, BYTE flags Source = srcSec; TargetID = target; Flags = flags; - DoTransfer (LastLight = srcSec->lightlevel, target, Flags); + DoTransfer (LastLight = srcSec->GetLightLevel(), target, Flags); - if (!(flags&WLF_NOFAKECONTRAST)) wallflags = WALLF_ABSLIGHTING; - else wallflags = WALLF_NOFAKECONTRAST|WALLF_ABSLIGHTING; + if (!(flags & WLF_NOFAKECONTRAST)) + { + wallflags = WALLF_ABSLIGHTING; + } + else + { + wallflags = WALLF_ABSLIGHTING | WALLF_NOFAKECONTRAST; + } for (linenum = -1; (linenum = P_FindLineFromID (target, linenum)) >= 0; ) { @@ -824,7 +850,7 @@ DWallLightTransfer::DWallLightTransfer (sector_t *srcSec, int target, BYTE flags void DWallLightTransfer::Tick () { - BYTE light = Source->lightlevel; + short light = sector_t::ClampLight(Source->lightlevel); if (light != LastLight) { @@ -833,13 +859,13 @@ void DWallLightTransfer::Tick () } } -void DWallLightTransfer::DoTransfer (BYTE lightlevel, int target, BYTE flags) +void DWallLightTransfer::DoTransfer (short lightlevel, int target, BYTE flags) { int linenum; for (linenum = -1; (linenum = P_FindLineFromID (target, linenum)) >= 0; ) { - line_t * line = &lines[linenum]; + line_t *line = &lines[linenum]; if (flags & WLF_SIDE1 && line->sidedef[0] != NULL) { diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index d96695dd..d8a15595 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1122,7 +1122,7 @@ public: continue; case NAME_Lightlevel: - sec->lightlevel = (BYTE)clamp(CheckInt(key), 0, 255); + sec->lightlevel = sector_t::ClampLight(CheckInt(key)); continue; case NAME_Special: diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp index 726986fb..c7d552e4 100644 --- a/src/r_bsp.cpp +++ b/src/r_bsp.cpp @@ -320,7 +320,7 @@ int GetFloorLight (const sector_t *sec) } else { - return clamp (sec->lightlevel + sec->GetPlaneLight(sector_t::floor), 0, 255); + return sector_t::ClampLight(sec->lightlevel + sec->GetPlaneLight(sector_t::floor)); } } @@ -332,7 +332,7 @@ int GetCeilingLight (const sector_t *sec) } else { - return clamp (sec->lightlevel + sec->GetPlaneLight(sector_t::ceiling), 0, 255); + return sector_t::ClampLight(sec->lightlevel + sec->GetPlaneLight(sector_t::ceiling)); } } @@ -1120,7 +1120,7 @@ void R_Subsector (subsector_t *sub) int floorlightlevel; // killough 3/16/98: set floor lightlevel int ceilinglightlevel; // killough 4/11/98 bool outersubsector; - int fll, cll; + int fll, cll, position; // kg3D - fake floor stuff visplane_t *backupfp; @@ -1269,10 +1269,12 @@ void R_Subsector (subsector_t *sub) fake3D = FAKE3D_FAKEFLOOR; tempsec = *fakeFloor->model; tempsec.floorplane = *fakeFloor->top.plane; + tempsec.ceilingplane = *fakeFloor->bottom.plane; if (!(fakeFloor->flags & FF_THISINSIDE) && !(fakeFloor->flags & FF_INVERTSECTOR)) { tempsec.SetTexture(sector_t::floor, tempsec.GetTexture(sector_t::ceiling)); - } + position = sector_t::ceiling; + } else position = sector_t::floor; frontsector = &tempsec; if (fixedlightlev < 0 && sub->sector->e->XFloor.lightlist.Size()) @@ -1288,11 +1290,11 @@ void R_Subsector (subsector_t *sub) floorlightlevel + r_actualextralight, // killough 3/16/98 frontsector->GetAlpha(sector_t::floor), !!(frontsector->GetFlags(sector_t::floor) & PLANEF_ADDITIVE), - frontsector->GetXOffset(sector_t::floor), // killough 3/7/98 - frontsector->GetYOffset(sector_t::floor), // killough 3/7/98 - frontsector->GetXScale(sector_t::floor), - frontsector->GetYScale(sector_t::floor), - frontsector->GetAngle(sector_t::floor), + frontsector->GetXOffset(position), // killough 3/7/98 + frontsector->GetYOffset(position), // killough 3/7/98 + frontsector->GetXScale(position), + frontsector->GetYScale(position), + frontsector->GetAngle(position), frontsector->sky, NULL); @@ -1328,12 +1330,14 @@ void R_Subsector (subsector_t *sub) { fake3D = FAKE3D_FAKECEILING; tempsec = *fakeFloor->model; + tempsec.floorplane = *fakeFloor->top.plane; tempsec.ceilingplane = *fakeFloor->bottom.plane; if ((!(fakeFloor->flags & FF_THISINSIDE) && !(fakeFloor->flags & FF_INVERTSECTOR)) || (fakeFloor->flags & FF_THISINSIDE && fakeFloor->flags & FF_INVERTSECTOR)) { tempsec.SetTexture(sector_t::ceiling, tempsec.GetTexture(sector_t::floor)); - } + position = sector_t::floor; + } else position = sector_t::ceiling; frontsector = &tempsec; tempsec.ceilingplane.ChangeHeight(-1); @@ -1351,11 +1355,11 @@ void R_Subsector (subsector_t *sub) ceilinglightlevel + r_actualextralight, // killough 4/11/98 frontsector->GetAlpha(sector_t::ceiling), !!(frontsector->GetFlags(sector_t::ceiling) & PLANEF_ADDITIVE), - frontsector->GetXOffset(sector_t::ceiling), // killough 3/7/98 - frontsector->GetYOffset(sector_t::ceiling), // killough 3/7/98 - frontsector->GetXScale(sector_t::ceiling), - frontsector->GetYScale(sector_t::ceiling), - frontsector->GetAngle(sector_t::ceiling), + frontsector->GetXOffset(position), // killough 3/7/98 + frontsector->GetYOffset(position), // killough 3/7/98 + frontsector->GetXScale(position), + frontsector->GetYScale(position), + frontsector->GetAngle(position), frontsector->sky, NULL); diff --git a/src/r_defs.h b/src/r_defs.h index c4aac407..0c1c3ab0 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -647,14 +647,19 @@ struct sector_t )? heightsec : NULL; } + static inline short ClampLight(int level) + { + return (short)clamp(level, SHRT_MIN, SHRT_MAX); + } + void ChangeLightLevel(int newval) { - lightlevel = (BYTE)clamp(lightlevel + newval, 0, 255); + lightlevel = ClampLight(lightlevel + newval); } void SetLightLevel(int newval) { - lightlevel = (BYTE)clamp(newval, 0, 255); + lightlevel = ClampLight(newval); } int GetLightLevel() const @@ -680,17 +685,17 @@ struct sector_t // [RH] give floor and ceiling even more properties FDynamicColormap *ColorMap; // [RH] Per-sector colormap - BYTE lightlevel; TObjPtr SoundTarget; - BYTE soundtraversed; // 0 = untraversed, 1,2 = sndlines -1 short special; short tag; + short lightlevel; + short seqType; // this sector's sound sequence + int nexttag,firsttag; // killough 1/30/98: improves searches for tags. int sky; - short seqType; // this sector's sound sequence FNameNoInit SeqName; // Sound sequence name. Setting seqType non-negative will override this. fixed_t soundorg[2]; // origin for any sounds played by the sector @@ -716,6 +721,7 @@ struct sector_t }; TObjPtr interpolations[4]; + BYTE soundtraversed; // 0 = untraversed, 1,2 = sndlines -1 // jff 2/26/98 lockout machinery for stairbuilding SBYTE stairlock; // -2 on first locked -1 after thinker done 0 normally SWORD prevsec; // -1 or number of sector for previous step diff --git a/src/r_main.h b/src/r_main.h index d91450a3..e52f901d 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -98,9 +98,13 @@ extern bool r_dontmaplines; // is necessary in order to best reproduce Doom's original lighting. #define LIGHT2SHADE(l) ((NUMCOLORMAPS*2*FRACUNIT)-(((l)+12)*FRACUNIT*NUMCOLORMAPS/128)) +// MAXLIGHTSCALE from original DOOM, divided by 2. +#define MAXLIGHTVIS (24*FRACUNIT) + // Convert a shade and visibility to a clamped colormap index. // Result is not fixed point. -#define GETPALOOKUP(vis,shade) (clamp (((shade)-(vis))>>FRACBITS, 0, NUMCOLORMAPS-1)) +// Change R_CalcTiltedLighting() when this changes. +#define GETPALOOKUP(vis,shade) (clamp (((shade)-MIN(MAXLIGHTVIS,(vis)))>>FRACBITS, 0, NUMCOLORMAPS-1)) extern fixed_t GlobVis; diff --git a/src/r_plane.cpp b/src/r_plane.cpp index b409bcf5..b7db7082 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -251,64 +251,88 @@ void STACK_ARGS R_CalcTiltedLighting (fixed_t lval, fixed_t lend, int width) BYTE *basecolormapdata = basecolormap->Maps; int i = 0; - lval = planeshade - lval; - lend = planeshade - lend; - if (width == 0 || lval == lend) { // Constant lighting - lightfiller = basecolormapdata + (GETPALOOKUP (-lval, 0) << COLORMAPSHIFT); - } - else if ((lstep = (lend - lval) / width) < 0) - { // Going from dark to light - if (lval < FRACUNIT) - { // All bright - lightfiller = basecolormapdata; - } - else - { - if (lval >= NUMCOLORMAPS*FRACUNIT) - { // Starts beyond the dark end - BYTE *clight = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); - while (lval >= NUMCOLORMAPS*FRACUNIT && i <= width) - { - tiltlighting[i++] = clight; - lval += lstep; - } - if (i > width) - return; - } - while (i <= width && lval >= 0) - { - tiltlighting[i++] = basecolormapdata + ((lval >> FRACBITS) << COLORMAPSHIFT); - lval += lstep; - } - lightfiller = basecolormapdata; - } + lightfiller = basecolormapdata + (GETPALOOKUP(lval, planeshade) << COLORMAPSHIFT); } else - { // Going from light to dark - if (lval >= (NUMCOLORMAPS-1)*FRACUNIT) - { // All dark - lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); + { + lstep = (lend - lval) / width; + if (lval >= MAXLIGHTVIS) + { // lval starts "too bright". + lightfiller = basecolormapdata + (GETPALOOKUP(lval, planeshade) << COLORMAPSHIFT); + for (; i <= width && lval >= MAXLIGHTVIS; ++i) + { + tiltlighting[i] = lightfiller; + lval += lstep; + } } - else + if (lend >= MAXLIGHTVIS) + { // lend ends "too bright". + lightfiller = basecolormapdata + (GETPALOOKUP(lend, planeshade) << COLORMAPSHIFT); + for (; width > i && lend >= MAXLIGHTVIS; --width) + { + tiltlighting[width] = lightfiller; + lend -= lstep; + } + } + if (width > 0) { - while (lval < 0 && i <= width) - { - tiltlighting[i++] = basecolormapdata; - lval += lstep; + lval = planeshade - lval; + lend = planeshade - lend; + lstep = (lend - lval) / width; + if (lstep < 0) + { // Going from dark to light + if (lval < FRACUNIT) + { // All bright + lightfiller = basecolormapdata; + } + else + { + if (lval >= NUMCOLORMAPS*FRACUNIT) + { // Starts beyond the dark end + BYTE *clight = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); + while (lval >= NUMCOLORMAPS*FRACUNIT && i <= width) + { + tiltlighting[i++] = clight; + lval += lstep; + } + if (i > width) + return; + } + while (i <= width && lval >= 0) + { + tiltlighting[i++] = basecolormapdata + ((lval >> FRACBITS) << COLORMAPSHIFT); + lval += lstep; + } + lightfiller = basecolormapdata; + } } - if (i > width) - return; - while (i <= width && lval < (NUMCOLORMAPS-1)*FRACUNIT) - { - tiltlighting[i++] = basecolormapdata + ((lval >> FRACBITS) << COLORMAPSHIFT); - lval += lstep; + else + { // Going from light to dark + if (lval >= (NUMCOLORMAPS-1)*FRACUNIT) + { // All dark + lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); + } + else + { + while (lval < 0 && i <= width) + { + tiltlighting[i++] = basecolormapdata; + lval += lstep; + } + if (i > width) + return; + while (i <= width && lval < (NUMCOLORMAPS-1)*FRACUNIT) + { + tiltlighting[i++] = basecolormapdata + ((lval >> FRACBITS) << COLORMAPSHIFT); + lval += lstep; + } + lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); + } } - lightfiller = basecolormapdata + ((NUMCOLORMAPS-1) << COLORMAPSHIFT); } } - for (; i <= width; i++) { tiltlighting[i] = lightfiller; diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 6edf20d7..053be097 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2056,7 +2056,7 @@ int side_t::GetLightLevel (bool foggy, int baselight, int *pfakecontrast) const { if (Flags & WALLF_ABSLIGHTING) { - baselight = (BYTE)Light; + baselight = Light; } if (pfakecontrast != NULL) @@ -2098,7 +2098,7 @@ int side_t::GetLightLevel (bool foggy, int baselight, int *pfakecontrast) const baselight += this->Light; } } - return clamp(baselight, 0, 255); + return baselight; } diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 4c405389..052d0495 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -2517,6 +2517,21 @@ void S_RestartMusic () } } +//========================================================================== +// +// S_MIDIDeviceChanged +// +//========================================================================== + +void S_MIDIDeviceChanged() +{ + if (mus_playing.handle != NULL && mus_playing.handle->IsMIDI()) + { + mus_playing.handle->Stop(); + mus_playing.handle->Start(mus_playing.loop, -1, mus_playing.baseorder); + } +} + //========================================================================== // // S_GetMusic diff --git a/src/s_sound.h b/src/s_sound.h index 12e7ee3c..d82e273a 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -313,6 +313,8 @@ bool S_ChangeCDMusic (int track, unsigned int id=0, bool looping=true); void S_RestartMusic (); +void S_MIDIDeviceChanged(); + int S_GetMusic (char **name); // Stops the music for sure. diff --git a/src/sound/music_midi_base.cpp b/src/sound/music_midi_base.cpp index 86134c95..e0d67683 100644 --- a/src/sound/music_midi_base.cpp +++ b/src/sound/music_midi_base.cpp @@ -43,13 +43,20 @@ static void MIDIDeviceChanged(int newdev) static int oldmididev = INT_MIN; // If a song is playing, move it to the new device. - if (oldmididev != newdev && currSong != NULL && currSong->IsMIDI()) + if (oldmididev != newdev) { - MusInfo *song = currSong; - if (song->m_Status == MusInfo::STATE_Playing) + if (currSong != NULL && currSong->IsMIDI()) { - song->Stop(); - song->Start(song->m_Looping); + MusInfo *song = currSong; + if (song->m_Status == MusInfo::STATE_Playing) + { + song->Stop(); + song->Start(song->m_Looping); + } + } + else + { + S_MIDIDeviceChanged(); } } oldmididev = newdev; diff --git a/src/textures/bitmap.cpp b/src/textures/bitmap.cpp index b552f979..26ca3b8e 100644 --- a/src/textures/bitmap.cpp +++ b/src/textures/bitmap.cpp @@ -421,7 +421,7 @@ bool FClipRect::Intersect(int ix, int iy, int iw, int ih) } else { - ih -= (x-ih); + ih -= (y-iy); } if (iw < width) width = iw; if (ih < height) height = ih; diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index 41925b71..2043350e 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -26,6 +26,7 @@ struct FFlagDef FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2); void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int index); +bool CheckDeprecatedFlags(AActor *actor, FActorInfo *info, int index); const char *GetFlagName(int flagnum, int flagoffset); #define FLAG_NAME(flagnum, flagvar) GetFlagName(flagnum, myoffsetof(AActor, flagvar)) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index c73a92a2..f0098f10 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -67,6 +67,7 @@ #include "doomstat.h" #include "v_palette.h" #include "g_shared/a_specialspot.h" +#include "actorptrselect.h" static FRandom pr_camissile ("CustomActorfire"); @@ -159,15 +160,14 @@ inline static bool isMissile(AActor * self, bool precise=true) //========================================================================== -enum AAPTR -{ - AAPTR_DEFAULT = 0, - AAPTR_NULL = 0x1, - AAPTR_TARGET = 0x2, - AAPTR_MASTER = 0x4, - AAPTR_TRACER = 0x8 +enum PTROP + { + PTROP_UNSAFETARGET = 1, + PTROP_UNSAFEMASTER = 2, + PTROP_NOSAFEGUARDS = PTROP_UNSAFETARGET|PTROP_UNSAFEMASTER }; + // [FDARI] Exported logic for guarding against loops in Target (for missiles) and Master (for all) chains. // It is called from multiple locations. // The code may be in need of optimisation. @@ -186,8 +186,8 @@ void VerifyTargetChain(AActor *self, bool preciseMissileCheck=true) AActor *compare = self; // every new actor must prove not to be the first actor in the chain, or any subsequent actor // any actor up to and including "origin" has only appeared once - do - { + for (;;) + { if (compare == next) { // if any of the actors from self to (inclusive) origin match the next actor, @@ -197,7 +197,7 @@ void VerifyTargetChain(AActor *self, bool preciseMissileCheck=true) } if (compare == origin) break; // when "compare" = origin, we know that the next actor is, and should be "next" compare = compare->target; - } while (true); // we're never leaving the loop here + } origin = next; next = next->target; @@ -214,7 +214,7 @@ void VerifyMasterChain(AActor *self) while (next) // We always care (See "VerifyTargetChain") { AActor *compare = self; - do + for (;;) { if (compare == next) { @@ -223,21 +223,13 @@ void VerifyMasterChain(AActor *self) } if (compare == origin) break; compare = compare->master; - } while (true); // we're never leaving the loop here + } origin = next; next = next->master; } } -enum PTROP -{ - PTROP_UNSAFETARGET = 1, - PTROP_UNSAFEMASTER = 2, - PTROP_NOSAFEGUARDS = PTROP_UNSAFETARGET|PTROP_UNSAFEMASTER -}; - - //========================================================================== // // A_RearrangePointers @@ -341,35 +333,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TransferPointer) // Exchange pointers with actors to whom you have pointers (or with yourself, if you must) - switch (ptr_source) // pick an actor to provide a pointer - { - case AAPTR_DEFAULT: source = self; break; - case AAPTR_TARGET: source = self->target; break; - case AAPTR_MASTER: source = self->master; break; - case AAPTR_TRACER: source = self->tracer; break; - default: return; - } + COPY_AAPTR(self, source, ptr_source); + COPY_AAPTR_NOT_NULL(self, recepient, ptr_recepient); // pick an actor to store the provided pointer value - if (!source) return; // you must pick somebody. MAYBE we should make a null assignment instead of just returning. - - switch (ptr_recepient) // pick an actor to store the provided pointer value - { - case AAPTR_DEFAULT: recepient = self; break; - case AAPTR_TARGET: recepient = self->target; break; - case AAPTR_MASTER: recepient = self->master; break; - case AAPTR_TRACER: recepient = self->tracer; break; - default: return; - } - - if (!recepient) return; // you must pick somebody. No way we can even make a null assignment here. - - switch (ptr_sourcefield) // convert source from dataprovider to data - { - case AAPTR_TARGET: source = source->target; break; // now we don't care where the data comes from anymore - case AAPTR_MASTER: source = source->master; break; // so we reassign source; it now holds the data itself - case AAPTR_TRACER: source = source->tracer; break; - default: source = NULL; - } + // convert source from dataprovider to data + + COPY_AAPTR(source, source, ptr_sourcefield); if (source == recepient) source = NULL; // The recepient should not acquire a pointer to itself; will write NULL @@ -409,16 +378,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CopyFriendliness) if (self->player) return; AActor *source; - - switch (ptr_source) - { - case AAPTR_TARGET: source = self->target; break; - case AAPTR_MASTER: source = self->master; break; - case AAPTR_TRACER: source = self->tracer; break; - default: return; - } - - if (source) self->CopyFriendliness(source, false, false); // Overriding default behaviour: No modification of health + COPY_AAPTR_NOT_NULL(self, source, ptr_source); + self->CopyFriendliness(source, false, false); // No change in current target or health } //========================================================================== @@ -812,14 +773,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfMasterCloser) //========================================================================== void DoJumpIfInventory(AActor * owner, DECLARE_PARAMINFO) { - ACTION_PARAM_START(3); + ACTION_PARAM_START(4); ACTION_PARAM_CLASS(Type, 0); ACTION_PARAM_INT(ItemAmount, 1); ACTION_PARAM_STATE(JumpOffset, 2); + ACTION_PARAM_INT(setowner, 3); ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! - if (!Type || owner == NULL) return; + if (!Type) return; + COPY_AAPTR_NOT_NULL(owner, owner, setowner); // returns if owner ends up being NULL AInventory *Item = owner->FindInventory(Type); @@ -1669,31 +1632,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun) static void DoGiveInventory(AActor * receiver, DECLARE_PARAMINFO) { - ACTION_PARAM_START(3); // param count up + ACTION_PARAM_START(3); ACTION_PARAM_CLASS(mi, 0); ACTION_PARAM_INT(amount, 1); - - // [FDARI] Modified code: Allow any pointer to be used for receiver ACTION_PARAM_INT(setreceiver, 2); - switch (setreceiver) - { - case AAPTR_TARGET: - if (receiver->target) { receiver = receiver->target; break; } - return; - case AAPTR_MASTER: - if (receiver->master) { receiver = receiver->master; break; } - return; - case AAPTR_TRACER: - if (receiver->tracer) { receiver = receiver->tracer; break; } - return; - } - - // FDARI: End of modified code + COPY_AAPTR_NOT_NULL(receiver, receiver, setreceiver); bool res=true; - if (receiver == NULL) return; - + if (amount==0) amount=1; if (mi) { @@ -1743,30 +1690,14 @@ enum void DoTakeInventory(AActor * receiver, DECLARE_PARAMINFO) { - ACTION_PARAM_START(4); // param count up + ACTION_PARAM_START(4); ACTION_PARAM_CLASS(item, 0); ACTION_PARAM_INT(amount, 1); ACTION_PARAM_INT(flags, 2); - - // [FDARI] Modified code: Allow any pointer to be used for receiver ACTION_PARAM_INT(setreceiver, 3); - - switch (setreceiver) - { - case AAPTR_TARGET: - if (receiver->target) { receiver = receiver->target; break; } - return; - case AAPTR_MASTER: - if (receiver->master) { receiver = receiver->master; break; } - return; - case AAPTR_TRACER: - if (receiver->tracer) { receiver = receiver->tracer; break; } - return; - } - - // FDARI: End of modified code - if (item == NULL || receiver == NULL) return; + if (!item) return; + COPY_AAPTR_NOT_NULL(receiver, receiver, setreceiver); bool res = false; @@ -2917,6 +2848,10 @@ enum JLOS_flags JLOSF_CLOSENOJUMP=16, JLOSF_DEADNOJUMP=32, JLOSF_CHECKMASTER=64, + JLOSF_TARGETLOS=128, + JLOSF_FLIPFOV=256, + JLOSF_ALLYNOJUMP=512, + JLOSF_COMBATANTONLY=1024 }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) @@ -2929,10 +2864,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) ACTION_PARAM_FIXED(dist_close, 4); angle_t an; - AActor *target; + AActor *target, *viewport; ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! + bool doCheckSight; + if (!self->player) { if (flags & JLOSF_CHECKMASTER) @@ -2952,66 +2889,88 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS) } if (!target) return; // [KS] Let's not call P_CheckSight unnecessarily in this case. - + if ((flags & JLOSF_DEADNOJUMP) && (target->health <= 0)) return; - fixed_t distance = P_AproxDistance(target->x - self->x, target->y - self->y); - distance = P_AproxDistance(distance, target->z - self->z); - - if (dist_max && (distance > dist_max)) return; - - bool doCheckSight = !(flags & JLOSF_NOSIGHT); - - if (dist_close && (distance < dist_close)) - { - if (flags & JLOSF_CLOSENOJUMP) - return; - - if (flags & JLOSF_CLOSENOFOV) - fov = 0; - - if (flags & JLOSF_CLOSENOSIGHT) - doCheckSight = false; - } - - if (doCheckSight && !P_CheckSight (self, target, SF_IGNOREVISIBILITY)) - return; - - if (fov && (fov < ANGLE_MAX)) - { - an = R_PointToAngle2 (self->x, - self->y, - target->x, - target->y) - - self->angle; - - if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) - { - - return; // [KS] Outside of FOV - return - } - - } + doCheckSight = !(flags & JLOSF_NOSIGHT); } else { // Does the player aim at something that can be shot? P_BulletSlope(self, &target); - + if (!target) return; - fixed_t distance = P_AproxDistance(target->x - self->x, target->y - self->y); - distance = P_AproxDistance(distance, target->z - self->z); - - if (dist_max && (distance > dist_max)) return; - - if (dist_close && (distance < dist_close)) + switch (flags & (JLOSF_TARGETLOS|JLOSF_FLIPFOV)) { - if (flags & JLOSF_CLOSENOJUMP) - return; + case JLOSF_TARGETLOS|JLOSF_FLIPFOV: + // target makes sight check, player makes fov check; player has verified fov + fov = 0; + // fall-through + case JLOSF_TARGETLOS: + doCheckSight = !(flags & JLOSF_NOSIGHT); // The target is responsible for sight check and fov + break; + default: + // player has verified sight and fov + fov = 0; + // fall-through + case JLOSF_FLIPFOV: // Player has verified sight, but target must verify fov + doCheckSight = false; + break; } } + // [FDARI] If target is not a combatant, don't jump + if ( (flags & JLOSF_COMBATANTONLY) && (!target->player) && !(target->flags3 & MF3_ISMONSTER)) return; + + // [FDARI] If actors share team, don't jump + if ((flags & JLOSF_ALLYNOJUMP) && self->IsFriend(target)) return; + + fixed_t distance = P_AproxDistance(target->x - self->x, target->y - self->y); + distance = P_AproxDistance(distance, target->z - self->z); + + if (dist_max && (distance > dist_max)) return; + + if (dist_close && (distance < dist_close)) + { + if (flags & JLOSF_CLOSENOJUMP) + return; + + if (flags & JLOSF_CLOSENOFOV) + fov = 0; + + if (flags & JLOSF_CLOSENOSIGHT) + doCheckSight = false; + } + + if (flags & JLOSF_TARGETLOS) { viewport = target; target = self; } + else { viewport = self; } + + if (doCheckSight && !P_CheckSight (viewport, target, SF_IGNOREVISIBILITY)) + return; + + if (flags & JLOSF_FLIPFOV) + { + if (viewport == self) { viewport = target; target = self; } + else { target = viewport; viewport = self; } + } + + if (fov && (fov < ANGLE_MAX)) + { + an = R_PointToAngle2 (viewport->x, + viewport->y, + target->x, + target->y) + - viewport->angle; + + if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) + { + + return; // [KS] Outside of FOV - return + } + + } + ACTION_JUMP(jump); } @@ -3352,6 +3311,60 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ChangeFlag) } } +//=========================================================================== +// +// A_CheckFlag +// +//=========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag) +{ + ACTION_PARAM_START(3); + ACTION_PARAM_STRING(flagname, 0); + ACTION_PARAM_STATE(jumpto, 1); + ACTION_PARAM_INT(checkpointer, 2); + + ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! + + AActor *owner; + + COPY_AAPTR_NOT_NULL(self, owner, checkpointer); + + const char *dot = strchr (flagname, '.'); + FFlagDef *fd; + const PClass *cls = owner->GetClass(); + + if (dot != NULL) + { + FString part1(flagname, dot-flagname); + fd = FindFlag (cls, part1, dot+1); + } + else + { + fd = FindFlag (cls, flagname, NULL); + } + + if (fd != NULL) + { + if (fd->structoffset == -1) + { + if (CheckDeprecatedFlags(owner, cls->ActorInfo, fd->flagbit)) { + ACTION_JUMP(jumpto); + } + } + else if ( fd->flagbit & *(DWORD*)(((char*)owner) + fd->structoffset)) + { + ACTION_JUMP(jumpto); + } + } + else + { + Printf("Unknown flag '%s' in '%s'\n", flagname, cls->TypeName.GetChars()); + } + +} + + //=========================================================================== // // A_RemoveMaster diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 5347e6a1..5d0c274b 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -229,6 +229,8 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF6, ADDITIVEPOISONDURATION, AActor, flags6), DEFINE_FLAG(MF6, BLOCKEDBYSOLIDACTORS, AActor, flags6), DEFINE_FLAG(MF6, NOMENU, AActor, flags6), + DEFINE_FLAG(MF6, SEEINVISIBLE, AActor, flags6), + DEFINE_FLAG(MF6, DONTCORPSE, AActor, flags6), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index e7601ba7..b7a352ed 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -159,6 +159,67 @@ void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int ind } } +//=========================================================================== +// +// CheckDeprecatedFlags +// +// Checks properties related to deprecated flags, and returns true only +// if the relevant properties are configured exactly as they would have +// been by setting the flag in HandleDeprecatedFlags. +// +//=========================================================================== + +bool CheckDeprecatedFlags(AActor *actor, FActorInfo *info, int index) +{ + // A deprecated flag is false if + // a) it hasn't been added here + // b) any property of the actor differs from what it would be after setting the flag using HandleDeprecatedFlags + + // Deprecated flags are normally replaced by something more flexible, which means a multitude of related configurations + // will report "false". + + switch (index) + { + case DEPF_FIREDAMAGE: + return actor->DamageType == NAME_Fire; + case DEPF_ICEDAMAGE: + return actor->DamageType == NAME_Ice; + case DEPF_LOWGRAVITY: + return actor->gravity == FRACUNIT/8; + case DEPF_SHORTMISSILERANGE: + return actor->maxtargetrange == 896*FRACUNIT; + case DEPF_LONGMELEERANGE: + return actor->meleethreshold == 196*FRACUNIT; + case DEPF_QUARTERGRAVITY: + return actor->gravity == FRACUNIT/4; + case DEPF_FIRERESIST: + if (info->DamageFactors) + { + fixed_t *df = info->DamageFactors->CheckKey(NAME_Fire); + return df && (*df) == FRACUNIT / 2; + } + return false; + + case DEPF_HERETICBOUNCE: + return (actor->BounceFlags & (BOUNCE_TypeMask|BOUNCE_UseSeeSound)) == BOUNCE_HereticCompat; + + case DEPF_HEXENBOUNCE: + return (actor->BounceFlags & (BOUNCE_TypeMask|BOUNCE_UseSeeSound)) == BOUNCE_HexenCompat; + + case DEPF_DOOMBOUNCE: + return (actor->BounceFlags & (BOUNCE_TypeMask|BOUNCE_UseSeeSound)) == BOUNCE_DoomCompat; + + case DEPF_PICKUPFLASH: + return static_cast(actor)->PickupFlash == PClass::FindClass("PickupFlash"); + // A pure name lookup may or may not be more efficient, but I know no static identifier for PickupFlash. + + case DEPF_INTERHUBSTRIP: + return !(static_cast(actor)->InterHubAmount); + } + + return false; // Any entirely unknown flag is not set +} + //========================================================================== // // @@ -2128,18 +2189,31 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, crouchsprite, S, PlayerPawn) //========================================================================== // //========================================================================== -DEFINE_CLASS_PROPERTY_PREFIX(player, damagescreencolor, Cf, PlayerPawn) +DEFINE_CLASS_PROPERTY_PREFIX(player, damagescreencolor, Cfs, PlayerPawn) { PROP_COLOR_PARM(c, 0); - defaults->DamageFade = c; + + PalEntry color = c; + if (PROP_PARM_COUNT < 3) // Because colors count as 2 parms { - defaults->DamageFade.a = 255; + color.a = 255; + defaults->DamageFade = color; + } + else if (PROP_PARM_COUNT < 4) + { + PROP_FLOAT_PARM(a, 2); + + color.a = BYTE(255 * clamp(a, 0.f, 1.f)); + defaults->DamageFade = color; } else { PROP_FLOAT_PARM(a, 2); - defaults->DamageFade.a = BYTE(255 * clamp(a, 0.f, 1.f)); + PROP_STRING_PARM(type, 3); + + color.a = BYTE(255 * clamp(a, 0.f, 1.f)); + info->SetPainFlash(type, color); } } diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 13dd55e7..720caa85 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -102,7 +102,7 @@ ACTOR Actor native //: Thinker action native A_BspiAttack(); action native A_Hoof(); action native A_CyberAttack(); - action native A_PainAttack(class spawntype = "LostSoul"); + action native A_PainAttack(class spawntype = "LostSoul", float angle = 0, int flags = 0, int limit = -1); action native A_DualPainAttack(class spawntype = "LostSoul"); action native A_PainDie(class spawntype = "LostSoul"); action native A_KeenDie(int doortag = 666); @@ -197,7 +197,7 @@ ACTOR Actor native //: Thinker action native A_JumpIfCloser(float distance, state label); action native A_JumpIfTracerCloser(float distance, state label); action native A_JumpIfMasterCloser(float distance, state label); - action native A_JumpIfInventory(class itemtype, int itemamount, state label); + action native A_JumpIfInventory(class itemtype, int itemamount, state label, int owner = AAPTR_DEFAULT); action native A_JumpIfArmorType(string Type, state label, int amount = 1); action native A_GiveInventory(class itemtype, int amount = 0, int giveto = AAPTR_DEFAULT); action native A_TakeInventory(class itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT); @@ -219,6 +219,7 @@ ACTOR Actor native //: Thinker action native A_DropInventory(class itemtype); action native A_SetBlend(color color1, float alpha, int tics, color color2 = ""); action native A_ChangeFlag(string flagname, bool value); + action native A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT); action native A_JumpIf(bool expression, state label); action native A_RemoveMaster(); action native A_RemoveChildren(bool removeall = false); @@ -238,9 +239,9 @@ ACTOR Actor native //: Thinker action native A_Weave(int xspeed, int yspeed, float xdist, float ydist); action native A_Recoil(float xyvel); - action native A_JumpIfInTargetInventory(class itemtype, int amount, state label); - action native A_GiveToTarget(class itemtype, int amount = 0); - action native A_TakeFromTarget(class itemtype, int amount = 0, int flags = 0); + action native A_JumpIfInTargetInventory(class itemtype, int amount, state label, int forward_ptr = AAPTR_DEFAULT); + action native A_GiveToTarget(class itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT); + action native A_TakeFromTarget(class itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT); action native A_CountdownArg(int argnum, state targstate = ""); action native A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true); action native A_CustomComboAttack(class missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index c5159bbf..de545ed7 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -1,4 +1,9 @@ +// Flags for A_PainAttack +const int PAF_NOSKULLATTACK = 1; +const int PAF_AIMFACING = 2; +const int PAF_NOTARGET = 4; + // Flags for A_Saw const int SF_NORANDOM = 1; const int SF_RANDOMLIGHTMISS = 2; @@ -19,6 +24,9 @@ const int CBAF_NORANDOM = 2; const int CBAF_EXPLICITANGLE = 4; const int CBAF_NOPITCH = 8; +// Flags for A_GunFlash +const int GFF_NOEXTCHANGE = 1; + // Flags for A_FireBullets const int FBF_USEAMMO = 1; const int FBF_NORANDOM = 2; @@ -67,6 +75,10 @@ const int JLOSF_CLOSENOSIGHT = 8; const int JLOSF_CLOSENOJUMP = 16; const int JLOSF_DEADNOJUMP = 32; const int JLOSF_CHECKMASTER = 64; +const int JLOSF_TARGETLOS = 128; +const int JLOSF_FLIPFOV = 256; +const int JLOSF_ALLYNOJUMP = 512; +const int JLOSF_COMBATANTONLY = 1024; // Flags for A_ChangeVelocity const int CVF_RELATIVE = 1; @@ -209,6 +221,20 @@ Const Int AAPTR_TARGET = 2; Const Int AAPTR_MASTER = 4; Const Int AAPTR_TRACER = 8; +Const Int AAPTR_PLAYER_GETTARGET = 16; +Const Int AAPTR_PLAYER_GETCONVERSATION = 32; + +Const Int AAPTR_PLAYER1 = 64; +Const Int AAPTR_PLAYER2 = 128; +Const Int AAPTR_PLAYER3 = 256; +Const Int AAPTR_PLAYER4 = 512; +Const Int AAPTR_PLAYER5 = 1024; +Const Int AAPTR_PLAYER6 = 2048; +Const Int AAPTR_PLAYER7 = 4096; +Const Int AAPTR_PLAYER8 = 8192; + +Const Int AAPTR_FRIENDPLAYER = 16384; + // Pointer operation flags Const Int PTROP_UNSAFETARGET = 1; diff --git a/wadsrc/static/actors/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt index 49b6b39a..3088ffff 100644 --- a/wadsrc/static/actors/shared/inventory.txt +++ b/wadsrc/static/actors/shared/inventory.txt @@ -40,7 +40,7 @@ ACTOR Inventory native action native A_ReFire(state flash = ""); action native A_ClearReFire(); action native A_CheckReload(); - action native A_GunFlash(state flash = ""); + action native A_GunFlash(state flash = "", int flags = 0); action native A_Saw(sound fullsound = "weapons/sawfull", sound hitsound = "weapons/sawhit", int damage = 2, class pufftype = "BulletPuff", int flags = 0, float range = 0, float spread_xy = 2.8125, float spread_z = 0, float lifesteal = 0); action native A_CheckForReload(int counter, state label, bool dontincrement = false); action native A_ResetReloadCounter();