mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 07:12:16 +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
|
# Libraries ZDoom needs
|
||||||
|
|
||||||
message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" )
|
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}" )
|
include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" )
|
||||||
|
|
||||||
if( SNDFILE_FOUND )
|
if( SNDFILE_FOUND )
|
||||||
|
@ -625,8 +625,6 @@ if( NOT DYN_FLUIDSYNTH )
|
||||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" )
|
set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" )
|
||||||
include_directories( "${FLUIDSYNTH_INCLUDE_DIR}" )
|
include_directories( "${FLUIDSYNTH_INCLUDE_DIR}" )
|
||||||
endif()
|
endif()
|
||||||
else()
|
|
||||||
set( ZDOOM_LIBS ${ZDOOM_LIBS} ${CMAKE_DL_LIBS} )
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Start defining source files for ZDoom
|
# Start defining source files for ZDoom
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
struct subsector_t;
|
struct subsector_t;
|
||||||
struct FBlockNode;
|
struct FBlockNode;
|
||||||
struct FPortalGroupArray;
|
struct FPortalGroupArray;
|
||||||
|
struct visstyle_t;
|
||||||
//
|
//
|
||||||
// NOTES: AActor
|
// NOTES: AActor
|
||||||
//
|
//
|
||||||
|
@ -616,6 +616,8 @@ public:
|
||||||
// Adjusts the angle for deflection/reflection of incoming missiles
|
// Adjusts the angle for deflection/reflection of incoming missiles
|
||||||
// Returns true if the missile should be allowed to explode anyway
|
// Returns true if the missile should be allowed to explode anyway
|
||||||
bool AdjustReflectionAngle (AActor *thing, DAngle &angle);
|
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
|
// Returns true if this actor is within melee range of its target
|
||||||
bool CheckMeleeRange();
|
bool CheckMeleeRange();
|
||||||
|
|
|
@ -229,16 +229,14 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
||||||
// This code is taken and adapted from APowerProtection::ModifyDamage().
|
// This code is taken and adapted from APowerProtection::ModifyDamage().
|
||||||
// The differences include not using a default value, and of course the way
|
// The differences include not using a default value, and of course the way
|
||||||
// the damage factor info is obtained.
|
// the damage factor info is obtained.
|
||||||
|
|
||||||
|
// ApplyDamageFactors(ArmorType, damageType, damage, damage);
|
||||||
DmgFactors *df = PClass::FindActor(ArmorType)->DamageFactors;
|
DmgFactors *df = PClass::FindActor(ArmorType)->DamageFactors;
|
||||||
if (df != NULL)
|
if (df != NULL)
|
||||||
{
|
{
|
||||||
damage = newdamage = df->Apply(damageType, damage);
|
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;
|
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 -------------------------------------------------------------
|
// Speed Powerup -------------------------------------------------------------
|
||||||
|
|
||||||
IMPLEMENT_CLASS(APowerSpeed, false, false)
|
IMPLEMENT_CLASS(APowerSpeed, false, false)
|
||||||
|
|
|
@ -64,45 +64,6 @@ protected:
|
||||||
virtual void InitEffect () override;
|
virtual void InitEffect () override;
|
||||||
virtual void DoEffect () override;
|
virtual void DoEffect () override;
|
||||||
virtual void EndEffect () 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
|
class APowerSpeed : public APowerup
|
||||||
|
|
|
@ -697,12 +697,17 @@ DEFINE_ACTION_FUNCTION(AInventory, BecomePickup)
|
||||||
|
|
||||||
void AInventory::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
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
|
// AInventory :: ModifyDamage
|
||||||
|
@ -778,24 +783,6 @@ bool AInventory::GetNoTeleportFreeze ()
|
||||||
return false;
|
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
|
// AInventory :: Use
|
||||||
|
|
|
@ -133,7 +133,6 @@ public:
|
||||||
|
|
||||||
// visual stuff is for later. Right now the VM has not yet access to the needed functionality.
|
// 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 bool DrawPowerup(int x, int y);
|
||||||
virtual int AlterWeaponSprite(visstyle_t *vis);
|
|
||||||
|
|
||||||
|
|
||||||
// virtual on the script side only.
|
// virtual on the script side only.
|
||||||
|
|
|
@ -297,8 +297,8 @@ static void DrawHealth(player_t *CPlayer, int x, int y)
|
||||||
CR_BLUE;
|
CR_BLUE;
|
||||||
|
|
||||||
const bool haveBerserk = hud_berserk_health
|
const bool haveBerserk = hud_berserk_health
|
||||||
&& NULL != berserkpic
|
&& nullptr != berserkpic
|
||||||
&& NULL != CPlayer->mo->FindInventory< APowerStrength >();
|
&& nullptr != CPlayer->mo->FindInventory(PClass::FindActor(NAME_PowerStrength));
|
||||||
|
|
||||||
DrawImageToBox(haveBerserk ? berserkpic : healthpic, x, y, 31, 17);
|
DrawImageToBox(haveBerserk ? berserkpic : healthpic, x, y, 31, 17);
|
||||||
DrawHudNumber(HudFont, fontcolor, health, x + 33, y + 17);
|
DrawHudNumber(HudFont, fontcolor, health, x + 33, y + 17);
|
||||||
|
|
|
@ -310,21 +310,21 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
|
||||||
|
|
||||||
visstyle_t vis;
|
visstyle_t vis;
|
||||||
|
|
||||||
vis.RenderStyle=playermo->RenderStyle;
|
vis.RenderStyle = STYLE_Count;
|
||||||
vis.Alpha=playermo->Alpha;
|
vis.Alpha = playermo->Alpha;
|
||||||
vis.colormap = NULL;
|
vis.Invert = false;
|
||||||
if (playermo->Inventory)
|
playermo->AlterWeaponSprite(&vis);
|
||||||
|
|
||||||
|
FRenderStyle RenderStyle;
|
||||||
|
if (vis.RenderStyle == STYLE_Count) RenderStyle = playermo->RenderStyle;
|
||||||
|
else RenderStyle = vis.RenderStyle;
|
||||||
|
|
||||||
|
if (vis.Invert)
|
||||||
{
|
{
|
||||||
playermo->Inventory->AlterWeaponSprite(&vis);
|
// this only happens for Strife's inverted weapon sprite
|
||||||
if (vis.colormap >= SpecialColormaps[0].Colormap &&
|
RenderStyle.Flags |= STYLEF_InvertSource;
|
||||||
vis.colormap < SpecialColormaps[SpecialColormaps.Size()].Colormap &&
|
|
||||||
gl_fixedcolormap == CM_DEFAULT)
|
|
||||||
{
|
|
||||||
// this only happens for Strife's inverted weapon sprite
|
|
||||||
vis.RenderStyle.Flags |= STYLEF_InvertSource;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (vis.RenderStyle.AsDWORD == 0)
|
if (RenderStyle.AsDWORD == 0)
|
||||||
{
|
{
|
||||||
// This is RenderStyle None.
|
// This is RenderStyle None.
|
||||||
return;
|
return;
|
||||||
|
@ -334,32 +334,32 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
|
||||||
|
|
||||||
int OverrideShader = -1;
|
int OverrideShader = -1;
|
||||||
float trans = 0.f;
|
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();
|
RenderStyle.CheckFuzz();
|
||||||
if (vis.RenderStyle.BlendOp == STYLEOP_Fuzz)
|
if (RenderStyle.BlendOp == STYLEOP_Fuzz)
|
||||||
{
|
{
|
||||||
if (gl_fuzztype != 0)
|
if (gl_fuzztype != 0)
|
||||||
{
|
{
|
||||||
// Todo: implement shader selection here
|
// Todo: implement shader selection here
|
||||||
vis.RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
RenderStyle = LegacyRenderStyles[STYLE_Translucent];
|
||||||
OverrideShader = gl_fuzztype + 4;
|
OverrideShader = gl_fuzztype + 4;
|
||||||
trans = 0.99f; // trans may not be 1 here
|
trans = 0.99f; // trans may not be 1 here
|
||||||
}
|
}
|
||||||
else
|
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;
|
trans = transsouls;
|
||||||
}
|
}
|
||||||
else if (vis.RenderStyle.Flags & STYLEF_Alpha1)
|
else if (RenderStyle.Flags & STYLEF_Alpha1)
|
||||||
{
|
{
|
||||||
trans = 1.f;
|
trans = 1.f;
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep)
|
||||||
ll = 255;
|
ll = 255;
|
||||||
}
|
}
|
||||||
// set the lighting parameters
|
// 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);
|
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);
|
gl_RenderState.SetObjectColor(0xffffffff);
|
||||||
|
|
|
@ -1305,7 +1305,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da
|
||||||
int newdam = damage;
|
int newdam = damage;
|
||||||
if (damage > 0)
|
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.
|
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)
|
if (!(flags & (DMG_NO_ARMOR|DMG_FORCED)) && target->Inventory != NULL && damage > 0)
|
||||||
{
|
{
|
||||||
int newdam = damage;
|
int newdam = damage;
|
||||||
target->Inventory->AbsorbDamage (damage, mod, newdam);
|
newdam = target->AbsorbDamage(damage, mod);
|
||||||
damage = newdam;
|
damage = newdam;
|
||||||
if (damage <= 0)
|
if (damage <= 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3615,6 +3615,39 @@ bool AActor::AdjustReflectionAngle (AActor *thing, DAngle &angle)
|
||||||
return false;
|
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 ()
|
void AActor::PlayActiveSound ()
|
||||||
{
|
{
|
||||||
if (ActiveSound && !S_IsActorPlayingSomething (this, CHAN_VOICE, -1))
|
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
|
// 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
|
// 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.
|
// 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)
|
for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory)
|
||||||
{
|
{
|
||||||
if (ironfeet->IsKindOf (RUNTIME_CLASS(APowerIronFeet)))
|
if (ironfeet->IsKindOf(pitype))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,9 +579,10 @@ void P_PlayerOnSpecialFlat (player_t *player, int floorType)
|
||||||
|
|
||||||
if (Terrains[floorType].AllowProtection)
|
if (Terrains[floorType].AllowProtection)
|
||||||
{
|
{
|
||||||
|
auto pitype = PClass::FindActor(NAME_PowerIronFeet);
|
||||||
for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory)
|
for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory)
|
||||||
{
|
{
|
||||||
if (ironfeet->IsKindOf (RUNTIME_CLASS(APowerIronFeet)))
|
if (ironfeet->IsKindOf (pitype))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,19 +289,26 @@ void RenderPolyPlayerSprites::RenderSprite(DPSprite *sprite, AActor *owner, floa
|
||||||
{
|
{
|
||||||
visstyle_t visstyle;
|
visstyle_t visstyle;
|
||||||
visstyle.Alpha = Alpha;
|
visstyle.Alpha = Alpha;
|
||||||
visstyle.RenderStyle = RenderStyle;
|
visstyle.RenderStyle = STYLE_Count;
|
||||||
visstyle.colormap = nullptr; // Same as the GL render is doing.
|
visstyle.Invert = false;
|
||||||
|
|
||||||
camera->Inventory->AlterWeaponSprite(&visstyle);
|
camera->Inventory->AlterWeaponSprite(&visstyle);
|
||||||
|
|
||||||
RenderStyle = visstyle.RenderStyle;
|
|
||||||
Alpha = visstyle.Alpha;
|
Alpha = visstyle.Alpha;
|
||||||
|
|
||||||
// Only bother checking for the one type it changes it to until this has been ZScript'ed..
|
if (visstyle.RenderStyle != STYLE_Count)
|
||||||
if (visstyle.colormap == SpecialColormaps[INVERSECOLORMAP].Colormap)
|
{
|
||||||
|
RenderStyle = visstyle.RenderStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visstyle.Invert)
|
||||||
{
|
{
|
||||||
BaseColormap = &SpecialColormaps[INVERSECOLORMAP];
|
BaseColormap = &SpecialColormaps[INVERSECOLORMAP];
|
||||||
ColormapNum = 0;
|
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
|
// This encapsulates the fields of vissprite_t that can be altered by AlterWeaponSprite
|
||||||
struct visstyle_t
|
struct visstyle_t
|
||||||
{
|
{
|
||||||
lighttable_t *colormap;
|
bool Invert;
|
||||||
float Alpha;
|
float Alpha;
|
||||||
FRenderStyle RenderStyle;
|
ERenderStyle RenderStyle;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2127,6 +2127,7 @@ CCMD (soundlist)
|
||||||
{
|
{
|
||||||
Printf ("%3d. %s **not present**\n", i, sfx->name.GetChars());
|
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;
|
Object->ValueType = TypeColorStruct;
|
||||||
}
|
}
|
||||||
|
if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
||||||
else if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer)))
|
|
||||||
{
|
{
|
||||||
auto ptype = static_cast<PPointer *>(Object->ValueType)->PointedType;
|
auto ptype = static_cast<PPointer *>(Object->ValueType)->PointedType;
|
||||||
if (ptype->IsKindOf(RUNTIME_CLASS(PStruct)))
|
if (ptype->IsKindOf(RUNTIME_CLASS(PStruct)))
|
||||||
|
|
|
@ -819,6 +819,68 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau
|
||||||
return true;
|
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
|
// Parses an actor property
|
||||||
|
@ -867,6 +929,17 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag)
|
||||||
}
|
}
|
||||||
else
|
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());
|
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)))
|
else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
|
||||||
{
|
{
|
||||||
auto cls = PClass::FindClass(GetString(exp));
|
auto clsname = GetString(exp);
|
||||||
*(PClass**)addr = cls;
|
auto cls = PClass::FindClass(clsname);
|
||||||
if (!cls->IsDescendantOf(static_cast<PClassPointer*>(f->Type)->ClassRestriction))
|
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
|
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.
|
// 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.
|
// 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);
|
auto think = dyn_cast<DThinker>(obj);
|
||||||
if (think != nullptr)
|
if (think != nullptr)
|
||||||
|
|
|
@ -493,19 +493,26 @@ namespace swrenderer
|
||||||
{
|
{
|
||||||
visstyle_t visstyle;
|
visstyle_t visstyle;
|
||||||
visstyle.Alpha = vis->Alpha;
|
visstyle.Alpha = vis->Alpha;
|
||||||
visstyle.RenderStyle = vis->RenderStyle;
|
visstyle.RenderStyle = STYLE_Count;
|
||||||
visstyle.colormap = nullptr; // Same as the GL render is doing.
|
visstyle.Invert = false;
|
||||||
|
|
||||||
camera->Inventory->AlterWeaponSprite(&visstyle);
|
camera->Inventory->AlterWeaponSprite(&visstyle);
|
||||||
|
|
||||||
vis->RenderStyle = visstyle.RenderStyle;
|
|
||||||
vis->Alpha = visstyle.Alpha;
|
vis->Alpha = visstyle.Alpha;
|
||||||
|
|
||||||
// Only bother checking for the one type it changes it to until this has been ZScript'ed..
|
if (visstyle.RenderStyle != STYLE_Count)
|
||||||
if (visstyle.colormap == SpecialColormaps[INVERSECOLORMAP].Colormap)
|
{
|
||||||
|
vis->RenderStyle = visstyle.RenderStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visstyle.Invert)
|
||||||
{
|
{
|
||||||
vis->BaseColormap = &SpecialColormaps[INVERSECOLORMAP];
|
vis->BaseColormap = &SpecialColormaps[INVERSECOLORMAP];
|
||||||
vis->ColormapNum = 0;
|
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
|
// 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"
|
secretnext = "E4M9"
|
||||||
sky1 = "SKY4"
|
sky1 = "SKY4"
|
||||||
cluster = 4
|
cluster = 4
|
||||||
|
par = 165
|
||||||
music = "$MUSIC_E3M4"
|
music = "$MUSIC_E3M4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,6 +416,7 @@ map E4M2 lookup "HUSTR_E4M2"
|
||||||
secretnext = "E4M9"
|
secretnext = "E4M9"
|
||||||
sky1 = "SKY4"
|
sky1 = "SKY4"
|
||||||
cluster = 4
|
cluster = 4
|
||||||
|
par = 255
|
||||||
music = "$MUSIC_E3M2"
|
music = "$MUSIC_E3M2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,6 +428,7 @@ map E4M3 lookup "HUSTR_E4M3"
|
||||||
secretnext = "E4M9"
|
secretnext = "E4M9"
|
||||||
sky1 = "SKY4"
|
sky1 = "SKY4"
|
||||||
cluster = 4
|
cluster = 4
|
||||||
|
par = 135
|
||||||
music = "$MUSIC_E3M3"
|
music = "$MUSIC_E3M3"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,6 +440,7 @@ map E4M4 lookup "HUSTR_E4M4"
|
||||||
secretnext = "E4M9"
|
secretnext = "E4M9"
|
||||||
sky1 = "SKY4"
|
sky1 = "SKY4"
|
||||||
cluster = 4
|
cluster = 4
|
||||||
|
par = 150
|
||||||
music = "$MUSIC_E1M5"
|
music = "$MUSIC_E1M5"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,6 +452,7 @@ map E4M5 lookup "HUSTR_E4M5"
|
||||||
secretnext = "E4M9"
|
secretnext = "E4M9"
|
||||||
sky1 = "SKY4"
|
sky1 = "SKY4"
|
||||||
cluster = 4
|
cluster = 4
|
||||||
|
par = 180
|
||||||
music = "$MUSIC_E2M7"
|
music = "$MUSIC_E2M7"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,6 +464,7 @@ map E4M6 lookup "HUSTR_E4M6"
|
||||||
secretnext = "E4M9"
|
secretnext = "E4M9"
|
||||||
sky1 = "SKY4"
|
sky1 = "SKY4"
|
||||||
cluster = 4
|
cluster = 4
|
||||||
|
par = 390
|
||||||
cyberdemonspecial
|
cyberdemonspecial
|
||||||
specialaction_opendoor
|
specialaction_opendoor
|
||||||
music = "$MUSIC_E2M4"
|
music = "$MUSIC_E2M4"
|
||||||
|
@ -472,6 +478,7 @@ map E4M7 lookup "HUSTR_E4M7"
|
||||||
secretnext = "E4M9"
|
secretnext = "E4M9"
|
||||||
sky1 = "SKY4"
|
sky1 = "SKY4"
|
||||||
cluster = 4
|
cluster = 4
|
||||||
|
par = 135
|
||||||
music = "$MUSIC_E2M6"
|
music = "$MUSIC_E2M6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,6 +490,7 @@ map E4M8 lookup "HUSTR_E4M8"
|
||||||
secretnext = "E4M9"
|
secretnext = "E4M9"
|
||||||
sky1 = "SKY4"
|
sky1 = "SKY4"
|
||||||
cluster = 4
|
cluster = 4
|
||||||
|
par = 360
|
||||||
nointermission
|
nointermission
|
||||||
nosoundclipping
|
nosoundclipping
|
||||||
spidermastermindspecial
|
spidermastermindspecial
|
||||||
|
@ -498,6 +506,7 @@ map E4M9 lookup "HUSTR_E4M9"
|
||||||
secretnext = "E4M3"
|
secretnext = "E4M3"
|
||||||
sky1 = "SKY4"
|
sky1 = "SKY4"
|
||||||
cluster = 4
|
cluster = 4
|
||||||
|
par = 180
|
||||||
music = "$MUSIC_E1M9"
|
music = "$MUSIC_E1M9"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
struct VisStyle
|
||||||
|
{
|
||||||
|
bool Invert;
|
||||||
|
float Alpha;
|
||||||
|
int RenderStyle;
|
||||||
|
}
|
||||||
|
|
||||||
class Inventory : Actor native
|
class Inventory : Actor native
|
||||||
{
|
{
|
||||||
const BLINKTHRESHOLD = (4*32);
|
const BLINKTHRESHOLD = (4*32);
|
||||||
|
@ -39,6 +46,7 @@ class Inventory : Actor native
|
||||||
virtual native void AttachToOwner(Actor user);
|
virtual native void AttachToOwner(Actor user);
|
||||||
virtual native void DetachFromOwner();
|
virtual native void DetachFromOwner();
|
||||||
virtual native bool DrawPowerup(int x, int y);
|
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 double GetSpeedFactor() { return 1; }
|
||||||
virtual bool GetNoTeleportFreeze() { return false; }
|
virtual bool GetNoTeleportFreeze() { return false; }
|
||||||
virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {}
|
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 bool GoAway();
|
||||||
native void GoAwayAndDie();
|
native void GoAwayAndDie();
|
||||||
|
|
|
@ -32,6 +32,12 @@ class Powerup : Inventory native
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Invulnerable
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
class PowerInvulnerable : Powerup native
|
class PowerInvulnerable : Powerup native
|
||||||
{
|
{
|
||||||
Default
|
Default
|
||||||
|
@ -39,9 +45,26 @@ class PowerInvulnerable : Powerup native
|
||||||
Powerup.Duration -30;
|
Powerup.Duration -30;
|
||||||
inventory.icon "SPSHLD0";
|
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
|
Default
|
||||||
{
|
{
|
||||||
|
@ -49,9 +72,58 @@ class PowerStrength : Powerup native
|
||||||
Powerup.Color "ff 00 00", 0.5;
|
Powerup.Color "ff 00 00", 0.5;
|
||||||
+INVENTORY.HUBPOWER
|
+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);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PowerInvisibility : Powerup native
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Invisibility
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
class PowerInvisibility : Powerup
|
||||||
{
|
{
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
@ -60,6 +132,202 @@ class PowerInvisibility : Powerup native
|
||||||
Powerup.Strength 80;
|
Powerup.Strength 80;
|
||||||
Powerup.Mode "Fuzzy";
|
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
|
class PowerGhost : PowerInvisibility
|
||||||
|
@ -84,16 +352,45 @@ class PowerShadow : PowerInvisibility
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PowerIronFeet : Powerup native
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// IronFeet
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
class PowerIronFeet : Powerup
|
||||||
{
|
{
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
Powerup.Duration -60;
|
Powerup.Duration -60;
|
||||||
Powerup.Color "00 ff 00", 0.125;
|
Powerup.Color "00 ff 00", 0.125;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override void AbsorbDamage (int damage, Name damageType, out int newdamage)
|
||||||
|
{
|
||||||
|
if (damageType == 'Drowning')
|
||||||
|
{
|
||||||
|
newdamage = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override void DoEffect ()
|
||||||
|
{
|
||||||
|
if (Owner.player != NULL)
|
||||||
|
{
|
||||||
|
Owner.player.mo.ResetAirSupply ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PowerMask : PowerIronFeet native
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Mask
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
class PowerMask : PowerIronFeet
|
||||||
{
|
{
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
|
@ -102,6 +399,24 @@ class PowerMask : PowerIronFeet native
|
||||||
+INVENTORY.HUBPOWER
|
+INVENTORY.HUBPOWER
|
||||||
Inventory.Icon "I_MASK";
|
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