- Update to ZDoom r3224:

Emulate the size limit of Doom's lightscale table by capping the value of vis passed to GETPALOOKUP. The end result is that there is a minimum distance around you where light amplification stops and it gets no brighter. Should this scale with visibility? I can't say. So, yeah, it turns out all these years ago, I made this out to be harder than it really is.
    Fixed: Light levels outside the range [0,255] really do matter.
    Added FDARI's latest actor pointer submission.
    Added kgsws's 3D floor textute rotation fix.
    Added DavidPH's damage type specific damage color submission.
    Added DavidPH's A_PainAttack extension submission.
    Fixed: Telefrag damage should not be affected by skill damage factors.
    Added A_GunFlash extension submission.
    Added DONTCORPSE submission.
    Added SEEINVISIBLE submission.
    Added submission for disabling some new and rather pointless GCC warnings.
    Fixed: Selecting TiMidity++ as a MIDI device without a working timidity.exe, then switching to a different MIDI device would leave music silent until a new song was started. (The discrepancy between mus_playing.handle and currSong is one which should probably be handled properly at some point.)
    Fixed: Typo in FClipRect::Intersect() could case bad clipping.

git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@1216 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
Christoph Oelckers 2011-06-12 09:08:10 +00:00
parent e150d13413
commit dbd6c3d6b5
49 changed files with 740 additions and 332 deletions

View file

@ -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 )

View file

@ -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 )

View file

@ -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 )

View file

@ -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} )

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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;

118
src/actorptrselect.h Normal file
View file

@ -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); }

View file

@ -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);
}

View file

@ -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)

View file

@ -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;
}
}
}

View file

@ -24,7 +24,7 @@ protected:
int NextLightningFlash;
int LightningFlashCount;
bool Stopped;
BYTE *LightningLightLevels;
short *LightningLightLevels;
};
void P_StartLightning ();

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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);

View file

@ -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();
}

View file

@ -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<short>(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)

View file

@ -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;

View file

@ -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);

View file

@ -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)

View file

@ -171,6 +171,7 @@ struct FPlayerColorSet
typedef TMap<FName, fixed_t> DmgFactors;
typedef TMap<FName, int> PainChanceList;
typedef TMap<FName, PalEntry> PainFlashList;
typedef TMap<int, FPlayerColorSet> 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;
};

View file

@ -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;

View file

@ -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;

View file

@ -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.

View file

@ -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;

View file

@ -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++;
}
}
}

View file

@ -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()

View file

@ -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)
{

View file

@ -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

View file

@ -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

View file

@ -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)
{

View file

@ -1122,7 +1122,7 @@ public:
continue;
case NAME_Lightlevel:
sec->lightlevel = (BYTE)clamp<int>(CheckInt(key), 0, 255);
sec->lightlevel = sector_t::ClampLight(CheckInt(key));
continue;
case NAME_Special:

View file

@ -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);

View file

@ -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<AActor> 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<DInterpolation> 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

View file

@ -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<int> (((shade)-(vis))>>FRACBITS, 0, NUMCOLORMAPS-1))
// Change R_CalcTiltedLighting() when this changes.
#define GETPALOOKUP(vis,shade) (clamp<int> (((shade)-MIN(MAXLIGHTVIS,(vis)))>>FRACBITS, 0, NUMCOLORMAPS-1))
extern fixed_t GlobVis;

View file

@ -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;

View file

@ -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;
}

View file

@ -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

View file

@ -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.

View file

@ -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;

View file

@ -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;

View file

@ -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))

View file

@ -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

View file

@ -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),

View file

@ -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<AInventory*>(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<AInventory*>(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);
}
}

View file

@ -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<Actor> spawntype = "LostSoul");
action native A_PainAttack(class<Actor> spawntype = "LostSoul", float angle = 0, int flags = 0, int limit = -1);
action native A_DualPainAttack(class<Actor> spawntype = "LostSoul");
action native A_PainDie(class<Actor> 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<Inventory> itemtype, int itemamount, state label);
action native A_JumpIfInventory(class<Inventory> 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<Inventory> itemtype, int amount = 0, int giveto = AAPTR_DEFAULT);
action native A_TakeInventory(class<Inventory> itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT);
@ -219,6 +219,7 @@ ACTOR Actor native //: Thinker
action native A_DropInventory(class<Inventory> 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<Inventory> itemtype, int amount, state label);
action native A_GiveToTarget(class<Inventory> itemtype, int amount = 0);
action native A_TakeFromTarget(class<Inventory> itemtype, int amount = 0, int flags = 0);
action native A_JumpIfInTargetInventory(class<Inventory> itemtype, int amount, state label, int forward_ptr = AAPTR_DEFAULT);
action native A_GiveToTarget(class<Inventory> itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT);
action native A_TakeFromTarget(class<Inventory> 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<Actor> missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true);

View file

@ -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;

View file

@ -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<Actor> 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();