mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
Merge remote-tracking branch 'gzdoom/master' into qzdoom
# Conflicts: # src/r_things.cpp # src/r_things.h
This commit is contained in:
commit
2848ca53dc
23 changed files with 531 additions and 494 deletions
|
@ -609,7 +609,7 @@ endif()
|
|||
# Libraries ZDoom needs
|
||||
|
||||
message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" )
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" "${CMAKE_DL_LIBS}" )
|
||||
include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" )
|
||||
|
||||
if( SNDFILE_FOUND )
|
||||
|
@ -625,8 +625,6 @@ if( NOT DYN_FLUIDSYNTH )
|
|||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" )
|
||||
include_directories( "${FLUIDSYNTH_INCLUDE_DIR}" )
|
||||
endif()
|
||||
else()
|
||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${CMAKE_DL_LIBS} )
|
||||
endif()
|
||||
|
||||
# Start defining source files for ZDoom
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
struct subsector_t;
|
||||
struct FBlockNode;
|
||||
struct FPortalGroupArray;
|
||||
|
||||
struct visstyle_t;
|
||||
//
|
||||
// NOTES: AActor
|
||||
//
|
||||
|
@ -616,6 +616,8 @@ public:
|
|||
// Adjusts the angle for deflection/reflection of incoming missiles
|
||||
// Returns true if the missile should be allowed to explode anyway
|
||||
bool AdjustReflectionAngle (AActor *thing, DAngle &angle);
|
||||
int AbsorbDamage(int damage, FName dmgtype);
|
||||
void AlterWeaponSprite(visstyle_t *vis);
|
||||
|
||||
// Returns true if this actor is within melee range of its target
|
||||
bool CheckMeleeRange();
|
||||
|
|
|
@ -229,16 +229,14 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
|||
// This code is taken and adapted from APowerProtection::ModifyDamage().
|
||||
// The differences include not using a default value, and of course the way
|
||||
// the damage factor info is obtained.
|
||||
|
||||
// ApplyDamageFactors(ArmorType, damageType, damage, damage);
|
||||
DmgFactors *df = PClass::FindActor(ArmorType)->DamageFactors;
|
||||
if (df != NULL)
|
||||
{
|
||||
damage = newdamage = df->Apply(damageType, damage);
|
||||
}
|
||||
}
|
||||
if (Inventory != NULL)
|
||||
{
|
||||
Inventory->AbsorbDamage (damage, damageType, newdamage);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -629,10 +627,6 @@ void AHexenArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
|||
damage = newdamage;
|
||||
}
|
||||
}
|
||||
if (Inventory != NULL)
|
||||
{
|
||||
Inventory->AbsorbDamage (damage, damageType, newdamage);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -540,370 +540,6 @@ void APowerInvulnerable::EndEffect ()
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerInvulnerable :: AlterWeaponSprite
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
int APowerInvulnerable::AlterWeaponSprite (visstyle_t *vis)
|
||||
{
|
||||
int changed = Inventory == NULL ? false : Inventory->AlterWeaponSprite(vis);
|
||||
if (Owner != NULL)
|
||||
{
|
||||
if (Mode == NAME_Ghost && !(Owner->flags & MF_SHADOW))
|
||||
{
|
||||
vis->Alpha = MIN<float>(0.25f + (float)Owner->Alpha*0.75f, 1.f);
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
// Strength (aka Berserk) Powerup --------------------------------------------
|
||||
|
||||
IMPLEMENT_CLASS(APowerStrength, false, false)
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerStrength :: HandlePickup
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool APowerStrength::HandlePickup (AInventory *item)
|
||||
{
|
||||
if (item->GetClass() == GetClass())
|
||||
{ // Setting EffectTics to 0 will force Powerup's HandlePickup()
|
||||
// method to reset the tic count so you get the red flash again.
|
||||
EffectTics = 0;
|
||||
}
|
||||
return Super::HandlePickup (item);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerStrength :: InitEffect
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void APowerStrength::InitEffect ()
|
||||
{
|
||||
Super::InitEffect();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerStrength :: DoEffect
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void APowerStrength::Tick ()
|
||||
{
|
||||
// Strength counts up to diminish the fade.
|
||||
assert(EffectTics < (INT_MAX - 1)); // I can't see a game lasting nearly two years, but...
|
||||
EffectTics += 2;
|
||||
Super::Tick();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerStrength :: GetBlend
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
PalEntry APowerStrength::GetBlend ()
|
||||
{
|
||||
// slowly fade the berserk out
|
||||
int cnt = 12 - (EffectTics >> 6);
|
||||
|
||||
if (cnt > 0)
|
||||
{
|
||||
cnt = (cnt + 7) >> 3;
|
||||
return PalEntry (BlendColor.a*cnt*255/9,
|
||||
BlendColor.r, BlendColor.g, BlendColor.b);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Invisibility Powerup ------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CLASS(APowerInvisibility, false, false)
|
||||
|
||||
// Invisibility flag combos
|
||||
#define INVISIBILITY_FLAGS1 (MF_SHADOW)
|
||||
#define INVISIBILITY_FLAGS3 (MF3_GHOST)
|
||||
#define INVISIBILITY_FLAGS5 (MF5_CANTSEEK)
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerInvisibility :: InitEffect
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void APowerInvisibility::InitEffect ()
|
||||
{
|
||||
Super::InitEffect();
|
||||
// This used to call CommonInit(), which used to contain all the code that's repeated every
|
||||
// tic, plus the following code that needs to happen once and only once.
|
||||
// The CommonInit() code has been moved to DoEffect(), so this now ends with a call to DoEffect(),
|
||||
// and DoEffect() no longer needs to call InitEffect(). CommonInit() has been removed for being redundant.
|
||||
if (Owner != NULL)
|
||||
{
|
||||
flags &= ~(Owner->flags & INVISIBILITY_FLAGS1);
|
||||
Owner->flags |= flags & INVISIBILITY_FLAGS1;
|
||||
flags3 &= ~(Owner->flags3 & INVISIBILITY_FLAGS3);
|
||||
Owner->flags3 |= flags3 & INVISIBILITY_FLAGS3;
|
||||
flags5 &= ~(Owner->flags5 & INVISIBILITY_FLAGS5);
|
||||
Owner->flags5 |= flags5 & INVISIBILITY_FLAGS5;
|
||||
|
||||
CallDoEffect();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerInvisibility :: DoEffect
|
||||
//
|
||||
//===========================================================================
|
||||
void APowerInvisibility::DoEffect ()
|
||||
{
|
||||
Super::DoEffect();
|
||||
// Due to potential interference with other PowerInvisibility items
|
||||
// the effect has to be refreshed each tic.
|
||||
double ts = (Strength / 100) * (special1 + 1);
|
||||
|
||||
if (ts > 1.) ts = 1.;
|
||||
Owner->Alpha = clamp((1. - ts), 0., 1.);
|
||||
switch (Mode)
|
||||
{
|
||||
case (NAME_Fuzzy):
|
||||
Owner->RenderStyle = STYLE_OptFuzzy;
|
||||
break;
|
||||
case (NAME_Opaque):
|
||||
Owner->RenderStyle = STYLE_Normal;
|
||||
break;
|
||||
case (NAME_Additive):
|
||||
Owner->RenderStyle = STYLE_Add;
|
||||
break;
|
||||
case (NAME_Stencil):
|
||||
Owner->RenderStyle = STYLE_Stencil;
|
||||
break;
|
||||
case (NAME_AddStencil) :
|
||||
Owner->RenderStyle = STYLE_AddStencil;
|
||||
break;
|
||||
case (NAME_TranslucentStencil) :
|
||||
Owner->RenderStyle = STYLE_TranslucentStencil;
|
||||
break;
|
||||
case (NAME_None) :
|
||||
case (NAME_Cumulative):
|
||||
case (NAME_Translucent):
|
||||
Owner->RenderStyle = STYLE_Translucent;
|
||||
break;
|
||||
default: // Something's wrong
|
||||
Owner->RenderStyle = STYLE_Normal;
|
||||
Owner->Alpha = 1.;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerInvisibility :: EndEffect
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void APowerInvisibility::EndEffect ()
|
||||
{
|
||||
Super::EndEffect();
|
||||
if (Owner != NULL)
|
||||
{
|
||||
Owner->flags &= ~(flags & INVISIBILITY_FLAGS1);
|
||||
Owner->flags3 &= ~(flags3 & INVISIBILITY_FLAGS3);
|
||||
Owner->flags5 &= ~(flags5 & INVISIBILITY_FLAGS5);
|
||||
|
||||
Owner->RenderStyle = STYLE_Normal;
|
||||
Owner->Alpha = 1.;
|
||||
|
||||
// Check whether there are other invisibility items and refresh their effect.
|
||||
// If this isn't done there will be one incorrectly drawn frame when this
|
||||
// item expires.
|
||||
AInventory *item = Owner->Inventory;
|
||||
while (item != NULL)
|
||||
{
|
||||
if (item->IsKindOf(RUNTIME_CLASS(APowerInvisibility)) && item != this)
|
||||
{
|
||||
static_cast<APowerInvisibility*>(item)->DoEffect();
|
||||
}
|
||||
item = item->Inventory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerInvisibility :: AlterWeaponSprite
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
int APowerInvisibility::AlterWeaponSprite (visstyle_t *vis)
|
||||
{
|
||||
int changed = Inventory == NULL ? false : Inventory->AlterWeaponSprite(vis);
|
||||
// Blink if the powerup is wearing off
|
||||
if (changed == 0 && EffectTics < 4*32 && !(EffectTics & 8))
|
||||
{
|
||||
vis->RenderStyle = STYLE_Normal;
|
||||
vis->Alpha = 1.f;
|
||||
return 1;
|
||||
}
|
||||
else if (changed == 1)
|
||||
{
|
||||
// something else set the weapon sprite back to opaque but this item is still active.
|
||||
float ts = float((Strength / 100) * (special1 + 1));
|
||||
vis->Alpha = clamp<>((1.f - ts), 0.f, 1.f);
|
||||
switch (Mode)
|
||||
{
|
||||
case (NAME_Fuzzy):
|
||||
vis->RenderStyle = STYLE_OptFuzzy;
|
||||
break;
|
||||
case (NAME_Opaque):
|
||||
vis->RenderStyle = STYLE_Normal;
|
||||
break;
|
||||
case (NAME_Additive):
|
||||
vis->RenderStyle = STYLE_Add;
|
||||
break;
|
||||
case (NAME_Stencil):
|
||||
vis->RenderStyle = STYLE_Stencil;
|
||||
break;
|
||||
case (NAME_TranslucentStencil) :
|
||||
vis->RenderStyle = STYLE_TranslucentStencil;
|
||||
break;
|
||||
case (NAME_AddStencil) :
|
||||
vis->RenderStyle = STYLE_AddStencil;
|
||||
break;
|
||||
case (NAME_None) :
|
||||
case (NAME_Cumulative):
|
||||
case (NAME_Translucent):
|
||||
default:
|
||||
vis->RenderStyle = STYLE_Translucent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Handling of Strife-like cumulative invisibility powerups, the weapon itself shouldn't become invisible
|
||||
if ((vis->Alpha < 0.25f && special1 > 0) || (vis->Alpha == 0))
|
||||
{
|
||||
vis->Alpha = clamp((1.f - float(Strength/100)), 0.f, 1.f);
|
||||
vis->colormap = SpecialColormaps[INVERSECOLORMAP].Colormap;
|
||||
}
|
||||
return -1; // This item is valid so another one shouldn't reset the translucency
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerInvisibility :: HandlePickup
|
||||
//
|
||||
// If the player already has the first stage of a cumulative powerup, getting
|
||||
// it again increases the player's alpha. (But shouldn't this be in Use()?)
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool APowerInvisibility::HandlePickup (AInventory *item)
|
||||
{
|
||||
if (Mode == NAME_Cumulative && ((Strength * special1) < 1.) && item->GetClass() == GetClass())
|
||||
{
|
||||
APowerup *power = static_cast<APowerup *>(item);
|
||||
if (power->EffectTics == 0)
|
||||
{
|
||||
power->ItemFlags |= IF_PICKUPGOOD;
|
||||
return true;
|
||||
}
|
||||
// Only increase the EffectTics, not decrease it.
|
||||
// Color also gets transferred only when the new item has an effect.
|
||||
if (power->EffectTics > EffectTics)
|
||||
{
|
||||
EffectTics = power->EffectTics;
|
||||
BlendColor = power->BlendColor;
|
||||
}
|
||||
special1++; // increases power
|
||||
power->ItemFlags |= IF_PICKUPGOOD;
|
||||
return true;
|
||||
}
|
||||
return Super::HandlePickup (item);
|
||||
}
|
||||
|
||||
// Ironfeet Powerup ----------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CLASS(APowerIronFeet, false, false)
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerIronFeet :: AbsorbDamage
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void APowerIronFeet::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
||||
{
|
||||
if (damageType == NAME_Drowning)
|
||||
{
|
||||
newdamage = 0;
|
||||
}
|
||||
else if (Inventory != NULL)
|
||||
{
|
||||
Inventory->AbsorbDamage (damage, damageType, newdamage);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerIronFeet :: DoEffect
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void APowerIronFeet::DoEffect ()
|
||||
{
|
||||
if (Owner->player != NULL)
|
||||
{
|
||||
Owner->player->mo->ResetAirSupply ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Strife Environment Suit Powerup -------------------------------------------
|
||||
|
||||
IMPLEMENT_CLASS(APowerMask, false, false)
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerMask :: AbsorbDamage
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void APowerMask::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
||||
{
|
||||
if (damageType == NAME_Fire)
|
||||
{
|
||||
newdamage = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Super::AbsorbDamage (damage, damageType, newdamage);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerMask :: DoEffect
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void APowerMask::DoEffect ()
|
||||
{
|
||||
Super::DoEffect ();
|
||||
if (!(level.time & 0x3f))
|
||||
{
|
||||
S_Sound (Owner, CHAN_AUTO, "misc/mask", 1, ATTN_STATIC);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Speed Powerup -------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CLASS(APowerSpeed, false, false)
|
||||
|
|
|
@ -64,45 +64,6 @@ protected:
|
|||
virtual void InitEffect () override;
|
||||
virtual void DoEffect () override;
|
||||
virtual void EndEffect () override;
|
||||
virtual int AlterWeaponSprite (visstyle_t *vis) override;
|
||||
};
|
||||
|
||||
class APowerStrength : public APowerup
|
||||
{
|
||||
DECLARE_CLASS (APowerStrength, APowerup)
|
||||
public:
|
||||
PalEntry GetBlend ();
|
||||
protected:
|
||||
virtual void InitEffect () override;
|
||||
virtual void Tick () override;
|
||||
virtual bool HandlePickup (AInventory *item) override;
|
||||
};
|
||||
|
||||
class APowerInvisibility : public APowerup
|
||||
{
|
||||
DECLARE_CLASS (APowerInvisibility, APowerup)
|
||||
protected:
|
||||
virtual bool HandlePickup (AInventory *item) override;
|
||||
virtual void InitEffect () override;
|
||||
virtual void DoEffect () override;
|
||||
virtual void EndEffect () override;
|
||||
virtual int AlterWeaponSprite (visstyle_t *vis) override;
|
||||
};
|
||||
|
||||
class APowerIronFeet : public APowerup
|
||||
{
|
||||
DECLARE_CLASS (APowerIronFeet, APowerup)
|
||||
public:
|
||||
virtual void AbsorbDamage (int damage, FName damageType, int &newdamage) override;
|
||||
virtual void DoEffect () override;
|
||||
};
|
||||
|
||||
class APowerMask : public APowerIronFeet
|
||||
{
|
||||
DECLARE_CLASS (APowerMask, APowerIronFeet)
|
||||
public:
|
||||
virtual void AbsorbDamage (int damage, FName damageType, int &newdamage) override;
|
||||
virtual void DoEffect () override;
|
||||
};
|
||||
|
||||
class APowerSpeed : public APowerup
|
||||
|
|
|
@ -697,12 +697,17 @@ DEFINE_ACTION_FUNCTION(AInventory, BecomePickup)
|
|||
|
||||
void AInventory::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
||||
{
|
||||
if (Inventory != NULL)
|
||||
{
|
||||
Inventory->AbsorbDamage (damage, damageType, newdamage);
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AInventory, AbsorbDamage)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AInventory);
|
||||
PARAM_INT(damage);
|
||||
PARAM_NAME(type);
|
||||
PARAM_POINTER(newdmg, int);
|
||||
self->AbsorbDamage(damage, type, *newdmg);
|
||||
return 0;
|
||||
}
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: ModifyDamage
|
||||
|
@ -778,24 +783,6 @@ bool AInventory::GetNoTeleportFreeze ()
|
|||
return false;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: AlterWeaponSprite
|
||||
//
|
||||
// Allows inventory items to alter a player's weapon sprite just before it
|
||||
// is drawn.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
int AInventory::AlterWeaponSprite (visstyle_t *vis)
|
||||
{
|
||||
if (Inventory != NULL)
|
||||
{
|
||||
return Inventory->AlterWeaponSprite (vis);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AInventory :: Use
|
||||
|
|
|
@ -133,7 +133,6 @@ public:
|
|||
|
||||
// visual stuff is for later. Right now the VM has not yet access to the needed functionality.
|
||||
virtual bool DrawPowerup(int x, int y);
|
||||
virtual int AlterWeaponSprite(visstyle_t *vis);
|
||||
|
||||
|
||||
// virtual on the script side only.
|
||||
|
|
|
@ -297,8 +297,8 @@ static void DrawHealth(player_t *CPlayer, int x, int y)
|
|||
CR_BLUE;
|
||||
|
||||
const bool haveBerserk = hud_berserk_health
|
||||
&& NULL != berserkpic
|
||||
&& NULL != CPlayer->mo->FindInventory< APowerStrength >();
|
||||
&& nullptr != berserkpic
|
||||
&& nullptr != CPlayer->mo->FindInventory(PClass::FindActor(NAME_PowerStrength));
|
||||
|
||||
DrawImageToBox(haveBerserk ? berserkpic : healthpic, x, y, 31, 17);
|
||||
DrawHudNumber(HudFont, fontcolor, health, x + 33, y + 17);
|
||||
|
|
|
@ -310,21 +310,21 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
|
|||
|
||||
visstyle_t vis;
|
||||
|
||||
vis.RenderStyle=playermo->RenderStyle;
|
||||
vis.RenderStyle = STYLE_Count;
|
||||
vis.Alpha = playermo->Alpha;
|
||||
vis.colormap = NULL;
|
||||
if (playermo->Inventory)
|
||||
{
|
||||
playermo->Inventory->AlterWeaponSprite(&vis);
|
||||
if (vis.colormap >= SpecialColormaps[0].Colormap &&
|
||||
vis.colormap < SpecialColormaps[SpecialColormaps.Size()].Colormap &&
|
||||
gl_fixedcolormap == CM_DEFAULT)
|
||||
vis.Invert = false;
|
||||
playermo->AlterWeaponSprite(&vis);
|
||||
|
||||
FRenderStyle RenderStyle;
|
||||
if (vis.RenderStyle == STYLE_Count) RenderStyle = playermo->RenderStyle;
|
||||
else RenderStyle = vis.RenderStyle;
|
||||
|
||||
if (vis.Invert)
|
||||
{
|
||||
// this only happens for Strife's inverted weapon sprite
|
||||
vis.RenderStyle.Flags |= STYLEF_InvertSource;
|
||||
RenderStyle.Flags |= STYLEF_InvertSource;
|
||||
}
|
||||
}
|
||||
if (vis.RenderStyle.AsDWORD == 0)
|
||||
if (RenderStyle.AsDWORD == 0)
|
||||
{
|
||||
// This is RenderStyle None.
|
||||
return;
|
||||
|
@ -334,32 +334,32 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
|
|||
|
||||
int OverrideShader = -1;
|
||||
float trans = 0.f;
|
||||
if (vis.RenderStyle.BlendOp >= STYLEOP_Fuzz && vis.RenderStyle.BlendOp <= STYLEOP_FuzzOrRevSub)
|
||||
if (RenderStyle.BlendOp >= STYLEOP_Fuzz && RenderStyle.BlendOp <= STYLEOP_FuzzOrRevSub)
|
||||
{
|
||||
vis.RenderStyle.CheckFuzz();
|
||||
if (vis.RenderStyle.BlendOp == STYLEOP_Fuzz)
|
||||
RenderStyle.CheckFuzz();
|
||||
if (RenderStyle.BlendOp == STYLEOP_Fuzz)
|
||||
{
|
||||
if (gl_fuzztype != 0)
|
||||
{
|
||||
// Todo: implement shader selection here
|
||||
vis.RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
||||
RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
||||
OverrideShader = gl_fuzztype + 4;
|
||||
trans = 0.99f; // trans may not be 1 here
|
||||
}
|
||||
else
|
||||
{
|
||||
vis.RenderStyle.BlendOp = STYLEOP_Shadow;
|
||||
RenderStyle.BlendOp = STYLEOP_Shadow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gl_SetRenderStyle(vis.RenderStyle, false, false);
|
||||
gl_SetRenderStyle(RenderStyle, false, false);
|
||||
|
||||
if (vis.RenderStyle.Flags & STYLEF_TransSoulsAlpha)
|
||||
if (RenderStyle.Flags & STYLEF_TransSoulsAlpha)
|
||||
{
|
||||
trans = transsouls;
|
||||
}
|
||||
else if (vis.RenderStyle.Flags & STYLEF_Alpha1)
|
||||
else if (RenderStyle.Flags & STYLEF_Alpha1)
|
||||
{
|
||||
trans = 1.f;
|
||||
}
|
||||
|
@ -402,7 +402,7 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
|
|||
ll = 255;
|
||||
}
|
||||
// set the lighting parameters
|
||||
if (vis.RenderStyle.BlendOp == STYLEOP_Shadow)
|
||||
if (RenderStyle.BlendOp == STYLEOP_Shadow)
|
||||
{
|
||||
gl_RenderState.SetColor(0.2f, 0.2f, 0.2f, 0.33f, cmc.desaturation);
|
||||
}
|
||||
|
@ -438,7 +438,7 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
|
|||
}
|
||||
|
||||
|
||||
DrawPSprite(player, psp, sx, sy, hudModelStep, OverrideShader, !!(vis.RenderStyle.Flags & STYLEF_RedIsAlpha));
|
||||
DrawPSprite(player, psp, sx, sy, hudModelStep, OverrideShader, !!(RenderStyle.Flags & STYLEF_RedIsAlpha));
|
||||
}
|
||||
}
|
||||
gl_RenderState.SetObjectColor(0xffffffff);
|
||||
|
|
|
@ -1305,7 +1305,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
|
|||
int newdam = damage;
|
||||
if (damage > 0)
|
||||
{
|
||||
player->mo->Inventory->AbsorbDamage(damage, mod, newdam);
|
||||
newdam = player->mo->AbsorbDamage(damage, mod);
|
||||
}
|
||||
if (!telefragDamage || (player->mo->flags7 & MF7_LAXTELEFRAGDMG)) //rawdamage is never modified.
|
||||
{
|
||||
|
@ -1385,7 +1385,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
|
|||
if (!(flags & (DMG_NO_ARMOR|DMG_FORCED)) && target->Inventory != NULL && damage > 0)
|
||||
{
|
||||
int newdam = damage;
|
||||
target->Inventory->AbsorbDamage (damage, mod, newdam);
|
||||
newdam = target->AbsorbDamage(damage, mod);
|
||||
damage = newdam;
|
||||
if (damage <= 0)
|
||||
{
|
||||
|
|
|
@ -3615,6 +3615,39 @@ bool AActor::AdjustReflectionAngle (AActor *thing, DAngle &angle)
|
|||
return false;
|
||||
}
|
||||
|
||||
int AActor::AbsorbDamage(int damage, FName dmgtype)
|
||||
{
|
||||
for (AInventory *item = Inventory; item != nullptr; item = item->Inventory)
|
||||
{
|
||||
IFVIRTUALPTR(item, AInventory, AbsorbDamage)
|
||||
{
|
||||
VMValue params[4] = { item, damage, dmgtype.GetIndex(), &damage };
|
||||
GlobalVMStack.Call(func, params, 4, nullptr, 0, nullptr);
|
||||
}
|
||||
else item->AbsorbDamage(damage, dmgtype, damage);
|
||||
}
|
||||
return damage;
|
||||
}
|
||||
|
||||
void AActor::AlterWeaponSprite(visstyle_t *vis)
|
||||
{
|
||||
int changed = 0;
|
||||
TArray<AInventory *> items;
|
||||
// This needs to go backwards through the items but the list has no backlinks.
|
||||
for (AInventory *item = Inventory; item != nullptr; item = item->Inventory)
|
||||
{
|
||||
items.Push(item);
|
||||
}
|
||||
for(int i=items.Size()-1;i>=0;i--)
|
||||
{
|
||||
IFVIRTUALPTR(items[i], AInventory, AlterWeaponSprite)
|
||||
{
|
||||
VMValue params[3] = { items[i], vis, &changed };
|
||||
GlobalVMStack.Call(func, params, 3, nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AActor::PlayActiveSound ()
|
||||
{
|
||||
if (ActiveSound && !S_IsActorPlayingSomething (this, CHAN_VOICE, -1))
|
||||
|
|
|
@ -394,9 +394,10 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
|
|||
// Allow subclasses. Better would be to implement it as armor and let that reduce
|
||||
// the damage as part of the normal damage procedure. Unfortunately, I don't have
|
||||
// different damage types yet, so that's not happening for now.
|
||||
auto pitype = PClass::FindActor(NAME_PowerIronFeet);
|
||||
for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory)
|
||||
{
|
||||
if (ironfeet->IsKindOf (RUNTIME_CLASS(APowerIronFeet)))
|
||||
if (ironfeet->IsKindOf(pitype))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -578,9 +579,10 @@ void P_PlayerOnSpecialFlat (player_t *player, int floorType)
|
|||
|
||||
if (Terrains[floorType].AllowProtection)
|
||||
{
|
||||
auto pitype = PClass::FindActor(NAME_PowerIronFeet);
|
||||
for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory)
|
||||
{
|
||||
if (ironfeet->IsKindOf (RUNTIME_CLASS(APowerIronFeet)))
|
||||
if (ironfeet->IsKindOf (pitype))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -289,19 +289,26 @@ void RenderPolyPlayerSprites::RenderSprite(DPSprite *sprite, AActor *owner, floa
|
|||
{
|
||||
visstyle_t visstyle;
|
||||
visstyle.Alpha = Alpha;
|
||||
visstyle.RenderStyle = RenderStyle;
|
||||
visstyle.colormap = nullptr; // Same as the GL render is doing.
|
||||
visstyle.RenderStyle = STYLE_Count;
|
||||
visstyle.Invert = false;
|
||||
|
||||
camera->Inventory->AlterWeaponSprite(&visstyle);
|
||||
|
||||
RenderStyle = visstyle.RenderStyle;
|
||||
Alpha = visstyle.Alpha;
|
||||
|
||||
// Only bother checking for the one type it changes it to until this has been ZScript'ed..
|
||||
if (visstyle.colormap == SpecialColormaps[INVERSECOLORMAP].Colormap)
|
||||
if (visstyle.RenderStyle != STYLE_Count)
|
||||
{
|
||||
RenderStyle = visstyle.RenderStyle;
|
||||
}
|
||||
|
||||
if (visstyle.Invert)
|
||||
{
|
||||
BaseColormap = &SpecialColormaps[INVERSECOLORMAP];
|
||||
ColormapNum = 0;
|
||||
if (BaseColormap->Maps < mybasecolormap->Maps || BaseColormap->Maps >= mybasecolormap->Maps + NUMCOLORMAPS * 256)
|
||||
{
|
||||
noaccel = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1488,9 +1488,9 @@ typedef BYTE lighttable_t; // This could be wider for >8 bit display.
|
|||
// This encapsulates the fields of vissprite_t that can be altered by AlterWeaponSprite
|
||||
struct visstyle_t
|
||||
{
|
||||
lighttable_t *colormap;
|
||||
bool Invert;
|
||||
float Alpha;
|
||||
FRenderStyle RenderStyle;
|
||||
ERenderStyle RenderStyle;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -2127,6 +2127,7 @@ CCMD (soundlist)
|
|||
{
|
||||
Printf ("%3d. %s **not present**\n", i, sfx->name.GetChars());
|
||||
}
|
||||
Printf(" PitchMask = %d\n", sfx->PitchMask);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5921,8 +5921,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx)
|
|||
{
|
||||
Object->ValueType = TypeColorStruct;
|
||||
}
|
||||
|
||||
else if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||
if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||
{
|
||||
auto ptype = static_cast<PPointer *>(Object->ValueType)->PointedType;
|
||||
if (ptype->IsKindOf(RUNTIME_CLASS(PStruct)))
|
||||
|
|
|
@ -819,6 +819,68 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau
|
|||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Parses an actor property's parameters and calls the handler
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaults, Baggage &bag)
|
||||
{
|
||||
for (unsigned i=0; i<prop->Variables.Size();i++)
|
||||
{
|
||||
auto f = prop->Variables[i];
|
||||
void *addr;
|
||||
|
||||
if (i > 0) sc.MustGetStringName(",");
|
||||
if (f->Flags & VARF_Meta)
|
||||
{
|
||||
addr = ((char*)bag.Info) + f->Offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = ((char*)defaults) + f->Offset;
|
||||
}
|
||||
|
||||
if (f->Type->IsKindOf(RUNTIME_CLASS(PInt)))
|
||||
{
|
||||
sc.MustGetNumber();
|
||||
static_cast<PInt*>(f->Type)->SetValue(addr, sc.Number);
|
||||
}
|
||||
else if (f->Type->IsKindOf(RUNTIME_CLASS(PFloat)))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
static_cast<PFloat*>(f->Type)->SetValue(addr, sc.Float);
|
||||
}
|
||||
else if (f->Type->IsKindOf(RUNTIME_CLASS(PString)))
|
||||
{
|
||||
sc.MustGetString();
|
||||
*(FString*)addr = sc.String;
|
||||
}
|
||||
else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
{
|
||||
sc.MustGetString();
|
||||
auto cls = PClass::FindClass(sc.String);
|
||||
*(PClass**)addr = cls;
|
||||
if (cls == nullptr)
|
||||
{
|
||||
cls = static_cast<PClassPointer*>(f->Type)->ClassRestriction->FindClassTentative(sc.String);
|
||||
}
|
||||
else if (!cls->IsDescendantOf(static_cast<PClassPointer*>(f->Type)->ClassRestriction))
|
||||
{
|
||||
sc.ScriptMessage("class %s is not compatible with property type %s", sc.String, static_cast<PClassPointer*>(f->Type)->ClassRestriction->TypeName.GetChars());
|
||||
FScriptPosition::ErrorCounter++;
|
||||
}
|
||||
*(PClass**)addr = cls;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptMessage("unhandled property type %s", f->Type->DescriptiveName());
|
||||
FScriptPosition::ErrorCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Parses an actor property
|
||||
|
@ -867,6 +929,17 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag)
|
|||
}
|
||||
else
|
||||
{
|
||||
propname.Insert(0, "@property@");
|
||||
FName name(propname, true);
|
||||
if (name != NAME_None)
|
||||
{
|
||||
auto propp = dyn_cast<PProperty>(bag.Info->Symbols.FindSymbol(name, true));
|
||||
if (propp != nullptr)
|
||||
{
|
||||
DispatchScriptProperty(sc, propp, (AActor *)bag.Info->Defaults, bag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
sc.ScriptError("'%s' is an unknown actor property\n", propname.GetChars());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1960,12 +1960,17 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop
|
|||
}
|
||||
else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||
{
|
||||
auto cls = PClass::FindClass(GetString(exp));
|
||||
*(PClass**)addr = cls;
|
||||
if (!cls->IsDescendantOf(static_cast<PClassPointer*>(f->Type)->ClassRestriction))
|
||||
auto clsname = GetString(exp);
|
||||
auto cls = PClass::FindClass(clsname);
|
||||
if (cls == nullptr)
|
||||
{
|
||||
Error(property, "class %s is not compatible with property type %s", cls->TypeName.GetChars(), static_cast<PClassPointer*>(f->Type)->ClassRestriction->TypeName.GetChars());
|
||||
cls = static_cast<PClassPointer*>(f->Type)->ClassRestriction->FindClassTentative(clsname);
|
||||
}
|
||||
else if (!cls->IsDescendantOf(static_cast<PClassPointer*>(f->Type)->ClassRestriction))
|
||||
{
|
||||
Error(property, "class %s is not compatible with property type %s", clsname, static_cast<PClassPointer*>(f->Type)->ClassRestriction->TypeName.GetChars());
|
||||
}
|
||||
*(PClass**)addr = cls;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -495,7 +495,7 @@ void FSerializer::Close()
|
|||
{
|
||||
// we must explicitly delete all thinkers in the array which did not get linked into the thinker lists.
|
||||
// Otherwise these objects may survive a level deletion and point to incorrect data.
|
||||
for (auto &obj : r->mDObjects)
|
||||
for (auto obj : r->mDObjects)
|
||||
{
|
||||
auto think = dyn_cast<DThinker>(obj);
|
||||
if (think != nullptr)
|
||||
|
|
|
@ -493,19 +493,26 @@ namespace swrenderer
|
|||
{
|
||||
visstyle_t visstyle;
|
||||
visstyle.Alpha = vis->Alpha;
|
||||
visstyle.RenderStyle = vis->RenderStyle;
|
||||
visstyle.colormap = nullptr; // Same as the GL render is doing.
|
||||
visstyle.RenderStyle = STYLE_Count;
|
||||
visstyle.Invert = false;
|
||||
|
||||
camera->Inventory->AlterWeaponSprite(&visstyle);
|
||||
|
||||
vis->RenderStyle = visstyle.RenderStyle;
|
||||
vis->Alpha = visstyle.Alpha;
|
||||
|
||||
// Only bother checking for the one type it changes it to until this has been ZScript'ed..
|
||||
if (visstyle.colormap == SpecialColormaps[INVERSECOLORMAP].Colormap)
|
||||
if (visstyle.RenderStyle != STYLE_Count)
|
||||
{
|
||||
vis->RenderStyle = visstyle.RenderStyle;
|
||||
}
|
||||
|
||||
if (visstyle.Invert)
|
||||
{
|
||||
vis->BaseColormap = &SpecialColormaps[INVERSECOLORMAP];
|
||||
vis->ColormapNum = 0;
|
||||
if (vis->BaseColormap->Maps < mybasecolormap->Maps || vis->BaseColormap->Maps >= mybasecolormap->Maps + NUMCOLORMAPS * 256)
|
||||
{
|
||||
noaccel = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we're drawing with a special colormap, but shaders for them are disabled, do
|
||||
|
|
|
@ -404,6 +404,7 @@ map E4M1 lookup "HUSTR_E4M1"
|
|||
secretnext = "E4M9"
|
||||
sky1 = "SKY4"
|
||||
cluster = 4
|
||||
par = 165
|
||||
music = "$MUSIC_E3M4"
|
||||
}
|
||||
|
||||
|
@ -415,6 +416,7 @@ map E4M2 lookup "HUSTR_E4M2"
|
|||
secretnext = "E4M9"
|
||||
sky1 = "SKY4"
|
||||
cluster = 4
|
||||
par = 255
|
||||
music = "$MUSIC_E3M2"
|
||||
}
|
||||
|
||||
|
@ -426,6 +428,7 @@ map E4M3 lookup "HUSTR_E4M3"
|
|||
secretnext = "E4M9"
|
||||
sky1 = "SKY4"
|
||||
cluster = 4
|
||||
par = 135
|
||||
music = "$MUSIC_E3M3"
|
||||
}
|
||||
|
||||
|
@ -437,6 +440,7 @@ map E4M4 lookup "HUSTR_E4M4"
|
|||
secretnext = "E4M9"
|
||||
sky1 = "SKY4"
|
||||
cluster = 4
|
||||
par = 150
|
||||
music = "$MUSIC_E1M5"
|
||||
}
|
||||
|
||||
|
@ -448,6 +452,7 @@ map E4M5 lookup "HUSTR_E4M5"
|
|||
secretnext = "E4M9"
|
||||
sky1 = "SKY4"
|
||||
cluster = 4
|
||||
par = 180
|
||||
music = "$MUSIC_E2M7"
|
||||
}
|
||||
|
||||
|
@ -459,6 +464,7 @@ map E4M6 lookup "HUSTR_E4M6"
|
|||
secretnext = "E4M9"
|
||||
sky1 = "SKY4"
|
||||
cluster = 4
|
||||
par = 390
|
||||
cyberdemonspecial
|
||||
specialaction_opendoor
|
||||
music = "$MUSIC_E2M4"
|
||||
|
@ -472,6 +478,7 @@ map E4M7 lookup "HUSTR_E4M7"
|
|||
secretnext = "E4M9"
|
||||
sky1 = "SKY4"
|
||||
cluster = 4
|
||||
par = 135
|
||||
music = "$MUSIC_E2M6"
|
||||
}
|
||||
|
||||
|
@ -483,6 +490,7 @@ map E4M8 lookup "HUSTR_E4M8"
|
|||
secretnext = "E4M9"
|
||||
sky1 = "SKY4"
|
||||
cluster = 4
|
||||
par = 360
|
||||
nointermission
|
||||
nosoundclipping
|
||||
spidermastermindspecial
|
||||
|
@ -498,6 +506,7 @@ map E4M9 lookup "HUSTR_E4M9"
|
|||
secretnext = "E4M3"
|
||||
sky1 = "SKY4"
|
||||
cluster = 4
|
||||
par = 180
|
||||
music = "$MUSIC_E1M9"
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
struct VisStyle
|
||||
{
|
||||
bool Invert;
|
||||
float Alpha;
|
||||
int RenderStyle;
|
||||
}
|
||||
|
||||
class Inventory : Actor native
|
||||
{
|
||||
const BLINKTHRESHOLD = (4*32);
|
||||
|
@ -39,6 +46,7 @@ class Inventory : Actor native
|
|||
virtual native void AttachToOwner(Actor user);
|
||||
virtual native void DetachFromOwner();
|
||||
virtual native bool DrawPowerup(int x, int y);
|
||||
virtual native void AbsorbDamage (int damage, Name damageType, out int newdamage);
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
|
@ -55,6 +63,7 @@ class Inventory : Actor native
|
|||
virtual double GetSpeedFactor() { return 1; }
|
||||
virtual bool GetNoTeleportFreeze() { return false; }
|
||||
virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {}
|
||||
virtual void AlterWeaponSprite(VisStyle vis, in out int changed) {}
|
||||
|
||||
native bool GoAway();
|
||||
native void GoAwayAndDie();
|
||||
|
|
|
@ -32,6 +32,12 @@ class Powerup : Inventory native
|
|||
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Invulnerable
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
class PowerInvulnerable : Powerup native
|
||||
{
|
||||
Default
|
||||
|
@ -39,9 +45,26 @@ class PowerInvulnerable : Powerup native
|
|||
Powerup.Duration -30;
|
||||
inventory.icon "SPSHLD0";
|
||||
}
|
||||
|
||||
override void AlterWeaponSprite (VisStyle vis, in out int changed)
|
||||
{
|
||||
if (Owner != NULL)
|
||||
{
|
||||
if (Mode == 'Ghost' && !(Owner.bShadow))
|
||||
{
|
||||
vis.Alpha = min(0.25 + Owner.Alpha * 0.75, 1.);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PowerStrength : Powerup native
|
||||
//===========================================================================
|
||||
//
|
||||
// Strength
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
class PowerStrength : Powerup
|
||||
{
|
||||
Default
|
||||
{
|
||||
|
@ -49,9 +72,58 @@ class PowerStrength : Powerup native
|
|||
Powerup.Color "ff 00 00", 0.5;
|
||||
+INVENTORY.HUBPOWER
|
||||
}
|
||||
|
||||
override bool HandlePickup (Inventory item)
|
||||
{
|
||||
if (item.GetClass() == GetClass())
|
||||
{ // Setting EffectTics to 0 will force Powerup's HandlePickup()
|
||||
// method to reset the tic count so you get the red flash again.
|
||||
EffectTics = 0;
|
||||
}
|
||||
return Super.HandlePickup (item);
|
||||
}
|
||||
|
||||
class PowerInvisibility : Powerup native
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerStrength :: DoEffect
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override void Tick ()
|
||||
{
|
||||
// Strength counts up to diminish the fade.
|
||||
EffectTics += 2;
|
||||
Super.Tick();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerStrength :: GetBlend
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override color GetBlend ()
|
||||
{
|
||||
// slowly fade the berserk out
|
||||
int cnt = 128 - (EffectTics>>3);
|
||||
|
||||
if (cnt > 0)
|
||||
{
|
||||
return Color(BlendColor.a*cnt/256,
|
||||
BlendColor.r, BlendColor.g, BlendColor.b);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Invisibility
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
class PowerInvisibility : Powerup
|
||||
{
|
||||
Default
|
||||
{
|
||||
|
@ -60,6 +132,202 @@ class PowerInvisibility : Powerup native
|
|||
Powerup.Strength 80;
|
||||
Powerup.Mode "Fuzzy";
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerInvisibility :: InitEffect
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override void InitEffect ()
|
||||
{
|
||||
Super.InitEffect();
|
||||
|
||||
let Owner = self.Owner;
|
||||
if (Owner != NULL)
|
||||
{
|
||||
let savedShadow = Owner.bShadow;
|
||||
let savedGhost = Owner.bGhost;
|
||||
let savedCantSeek = Owner.bCantSeek;
|
||||
Owner.bShadow = bShadow;
|
||||
Owner.bGhost = bGhost;
|
||||
Owner.bCantSeek = bCantSeek;
|
||||
bShadow = savedShadow;
|
||||
bGhost = savedGhost;
|
||||
bCantSeek = savedCantSeek;
|
||||
DoEffect();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerInvisibility :: DoEffect
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override void DoEffect ()
|
||||
{
|
||||
Super.DoEffect();
|
||||
// Due to potential interference with other PowerInvisibility items
|
||||
// the effect has to be refreshed each tic.
|
||||
double ts = (Strength / 100) * (special1 + 1);
|
||||
|
||||
if (ts > 1.) ts = 1.;
|
||||
let newAlpha = clamp((1. - ts), 0., 1.);
|
||||
int newStyle;
|
||||
switch (Mode)
|
||||
{
|
||||
case 'Fuzzy':
|
||||
newStyle = STYLE_OptFuzzy;
|
||||
break;
|
||||
case 'Opaque':
|
||||
newStyle = STYLE_Normal;
|
||||
break;
|
||||
case 'Additive':
|
||||
newStyle = STYLE_Add;
|
||||
break;
|
||||
case 'Stencil':
|
||||
newStyle = STYLE_Stencil;
|
||||
break;
|
||||
case 'AddStencil' :
|
||||
newStyle = STYLE_AddStencil;
|
||||
break;
|
||||
case 'TranslucentStencil':
|
||||
newStyle = STYLE_TranslucentStencil;
|
||||
break;
|
||||
case 'None' :
|
||||
case 'Cumulative':
|
||||
case 'Translucent':
|
||||
newStyle = STYLE_Translucent;
|
||||
break;
|
||||
default: // Something's wrong
|
||||
newStyle = STYLE_Normal;
|
||||
newAlpha = 1.;
|
||||
break;
|
||||
}
|
||||
Owner.A_SetRenderStyle(newAlpha, newStyle);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerInvisibility :: EndEffect
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override void EndEffect ()
|
||||
{
|
||||
Super.EndEffect();
|
||||
if (Owner != NULL)
|
||||
{
|
||||
Owner.bShadow = bShadow;
|
||||
Owner.bGhost = bGhost;
|
||||
Owner.bCantSeek = bCantSeek;
|
||||
|
||||
Owner.A_SetRenderStyle(1, STYLE_Normal);
|
||||
|
||||
// Check whether there are other invisibility items and refresh their effect.
|
||||
// If this isn't done there will be one incorrectly drawn frame when this
|
||||
// item expires.
|
||||
for(let item = Owner.Inv; item != null; item = item.Inv)
|
||||
{
|
||||
if (item != self && item is 'PowerInvisibility')
|
||||
{
|
||||
item.DoEffect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerInvisibility :: AlterWeaponSprite
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override void AlterWeaponSprite (VisStyle vis, in out int changed)
|
||||
{
|
||||
// Blink if the powerup is wearing off
|
||||
if (changed == 0 && EffectTics < 4*32 && !(EffectTics & 8))
|
||||
{
|
||||
vis.RenderStyle = STYLE_Normal;
|
||||
vis.Alpha = 1.f;
|
||||
changed = 1;
|
||||
return;
|
||||
}
|
||||
else if (changed == 1)
|
||||
{
|
||||
// something else set the weapon sprite back to opaque but this item is still active.
|
||||
float ts = float((Strength / 100) * (special1 + 1));
|
||||
vis.Alpha = clamp((1. - ts), 0., 1.);
|
||||
switch (Mode)
|
||||
{
|
||||
case 'Fuzzy':
|
||||
vis.RenderStyle = STYLE_OptFuzzy;
|
||||
break;
|
||||
case 'Opaque':
|
||||
vis.RenderStyle = STYLE_Normal;
|
||||
break;
|
||||
case 'Additive':
|
||||
vis.RenderStyle = STYLE_Add;
|
||||
break;
|
||||
case 'Stencil':
|
||||
vis.RenderStyle = STYLE_Stencil;
|
||||
break;
|
||||
case 'TranslucentStencil':
|
||||
vis.RenderStyle = STYLE_TranslucentStencil;
|
||||
break;
|
||||
case 'AddStencil':
|
||||
vis.RenderStyle = STYLE_AddStencil;
|
||||
break;
|
||||
case 'None':
|
||||
case 'Cumulative':
|
||||
case 'Translucent':
|
||||
default:
|
||||
vis.RenderStyle = STYLE_Translucent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Handling of Strife-like cumulative invisibility powerups, the weapon itself shouldn't become invisible
|
||||
if ((vis.Alpha < 0.25f && special1 > 0) || (vis.Alpha == 0))
|
||||
{
|
||||
vis.Alpha = clamp((1. - Strength/100.), 0., 1.);
|
||||
vis.invert = true;
|
||||
}
|
||||
changed = -1; // This item is valid so another one shouldn't reset the translucency
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APowerInvisibility :: HandlePickup
|
||||
//
|
||||
// If the player already has the first stage of a cumulative powerup, getting
|
||||
// it again increases the player's alpha. (But shouldn't this be in Use()?)
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override bool HandlePickup (Inventory item)
|
||||
{
|
||||
if (Mode == 'Cumulative' && ((Strength * special1) < 1.) && item.GetClass() == GetClass())
|
||||
{
|
||||
let power = Powerup(item);
|
||||
if (power.EffectTics == 0)
|
||||
{
|
||||
power.bPickupGood = true;
|
||||
return true;
|
||||
}
|
||||
// Only increase the EffectTics, not decrease it.
|
||||
// Color also gets transferred only when the new item has an effect.
|
||||
if (power.EffectTics > EffectTics)
|
||||
{
|
||||
EffectTics = power.EffectTics;
|
||||
BlendColor = power.BlendColor;
|
||||
}
|
||||
special1++; // increases power
|
||||
power.bPickupGood = true;
|
||||
return true;
|
||||
}
|
||||
return Super.HandlePickup (item);
|
||||
}
|
||||
}
|
||||
|
||||
class PowerGhost : PowerInvisibility
|
||||
|
@ -84,16 +352,45 @@ class PowerShadow : PowerInvisibility
|
|||
}
|
||||
}
|
||||
|
||||
class PowerIronFeet : Powerup native
|
||||
//===========================================================================
|
||||
//
|
||||
// IronFeet
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
class PowerIronFeet : Powerup
|
||||
{
|
||||
Default
|
||||
{
|
||||
Powerup.Duration -60;
|
||||
Powerup.Color "00 ff 00", 0.125;
|
||||
}
|
||||
|
||||
override void AbsorbDamage (int damage, Name damageType, out int newdamage)
|
||||
{
|
||||
if (damageType == 'Drowning')
|
||||
{
|
||||
newdamage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
class PowerMask : PowerIronFeet native
|
||||
override void DoEffect ()
|
||||
{
|
||||
if (Owner.player != NULL)
|
||||
{
|
||||
Owner.player.mo.ResetAirSupply ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Mask
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
class PowerMask : PowerIronFeet
|
||||
{
|
||||
Default
|
||||
{
|
||||
|
@ -102,6 +399,24 @@ class PowerMask : PowerIronFeet native
|
|||
+INVENTORY.HUBPOWER
|
||||
Inventory.Icon "I_MASK";
|
||||
}
|
||||
|
||||
override void AbsorbDamage (int damage, Name damageType, out int newdamage)
|
||||
{
|
||||
if (damageType == 'Fire' || damageType == 'Drowning')
|
||||
{
|
||||
newdamage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
override void DoEffect ()
|
||||
{
|
||||
Super.DoEffect ();
|
||||
if (!(level.time & 0x3f))
|
||||
{
|
||||
Owner.A_PlaySound ("misc/mask", CHAN_AUTO);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
Loading…
Reference in a new issue