mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-11 15:22:16 +00:00
Merge branch 'master' of https://github.com/raa-eruanna/qzdoom into qzdoom
This commit is contained in:
commit
c0e91086ce
16 changed files with 317 additions and 271 deletions
|
@ -1609,140 +1609,6 @@ void APowerTimeFreezer::EndEffect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Damage powerup ------------------------------------------------------
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(APowerDamage, false, false)
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// APowerDamage :: InitEffect
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void APowerDamage::InitEffect( )
|
|
||||||
{
|
|
||||||
Super::InitEffect();
|
|
||||||
|
|
||||||
// Use sound channel 5 to avoid interference with other actions.
|
|
||||||
if (Owner != NULL) S_Sound(Owner, 5, SeeSound, 1.0f, ATTN_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// APowerDamage :: EndEffect
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void APowerDamage::EndEffect( )
|
|
||||||
{
|
|
||||||
Super::EndEffect();
|
|
||||||
// Use sound channel 5 to avoid interference with other actions.
|
|
||||||
if (Owner != NULL) S_Sound(Owner, 5, DeathSound, 1.0f, ATTN_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// APowerDamage :: ModifyDamage
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void APowerDamage::ModifyDamage(int damage, FName damageType, int &newdamage, bool passive)
|
|
||||||
{
|
|
||||||
if (!passive && damage > 0)
|
|
||||||
{
|
|
||||||
int newdam;
|
|
||||||
DmgFactors *df = GetClass()->DamageFactors;
|
|
||||||
if (df != NULL && df->CountUsed() != 0)
|
|
||||||
{
|
|
||||||
newdam = MAX(1, df->Apply(damageType, damage));// don't allow zero damage as result of an underflow
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newdam = damage * 4;
|
|
||||||
}
|
|
||||||
if (Owner != NULL && newdam > damage) S_Sound(Owner, 5, ActiveSound, 1.0f, ATTN_NONE);
|
|
||||||
newdamage = damage = newdam;
|
|
||||||
}
|
|
||||||
if (Inventory != NULL) Inventory->ModifyDamage(damage, damageType, newdamage, passive);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Quarter damage powerup ------------------------------------------------------
|
|
||||||
|
|
||||||
IMPLEMENT_CLASS(APowerProtection, false, false)
|
|
||||||
|
|
||||||
#define PROTECTION_FLAGS3 (MF3_NORADIUSDMG | MF3_DONTMORPH | MF3_DONTSQUASH | MF3_DONTBLAST | MF3_NOTELEOTHER)
|
|
||||||
#define PROTECTION_FLAGS5 (MF5_NOPAIN | MF5_DONTRIP)
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// APowerProtection :: InitEffect
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void APowerProtection::InitEffect( )
|
|
||||||
{
|
|
||||||
Super::InitEffect();
|
|
||||||
|
|
||||||
if (Owner != NULL)
|
|
||||||
{
|
|
||||||
S_Sound(Owner, CHAN_AUTO, SeeSound, 1.0f, ATTN_NONE);
|
|
||||||
|
|
||||||
// Transfer various protection flags if owner does not already have them.
|
|
||||||
// If the owner already has the flag, clear it from the powerup.
|
|
||||||
// If the powerup still has a flag set, add it to the owner.
|
|
||||||
flags3 &= ~(Owner->flags3 & PROTECTION_FLAGS3);
|
|
||||||
Owner->flags3 |= flags3 & PROTECTION_FLAGS3;
|
|
||||||
|
|
||||||
flags5 &= ~(Owner->flags5 & PROTECTION_FLAGS5);
|
|
||||||
Owner->flags5 |= flags5 & PROTECTION_FLAGS5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// APowerProtection :: EndEffect
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void APowerProtection::EndEffect( )
|
|
||||||
{
|
|
||||||
Super::EndEffect();
|
|
||||||
if (Owner != NULL)
|
|
||||||
{
|
|
||||||
S_Sound(Owner, CHAN_AUTO, DeathSound, 1.0f, ATTN_NONE);
|
|
||||||
Owner->flags3 &= ~(flags3 & PROTECTION_FLAGS3);
|
|
||||||
Owner->flags5 &= ~(flags5 & PROTECTION_FLAGS5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// APowerProtection :: AbsorbDamage
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void APowerProtection::ModifyDamage(int damage, FName damageType, int &newdamage, bool passive)
|
|
||||||
{
|
|
||||||
if (passive && damage > 0)
|
|
||||||
{
|
|
||||||
int newdam;
|
|
||||||
DmgFactors *df = GetClass()->DamageFactors;
|
|
||||||
if (df != NULL && df->CountUsed() != 0)
|
|
||||||
{
|
|
||||||
newdam = MAX(0, df->Apply(damageType, damage));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newdam = damage / 4;
|
|
||||||
}
|
|
||||||
if (Owner != NULL && newdam < damage) S_Sound(Owner, CHAN_AUTO, ActiveSound, 1.0f, ATTN_NONE);
|
|
||||||
newdamage = damage = newdam;
|
|
||||||
}
|
|
||||||
if (Inventory != NULL)
|
|
||||||
{
|
|
||||||
Inventory->ModifyDamage(damage, damageType, newdamage, passive);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Morph powerup ------------------------------------------------------
|
// Morph powerup ------------------------------------------------------
|
||||||
|
|
||||||
|
@ -1760,7 +1626,6 @@ DEFINE_FIELD(APowerMorph, MorphFlash)
|
||||||
DEFINE_FIELD(APowerMorph, UnMorphFlash)
|
DEFINE_FIELD(APowerMorph, UnMorphFlash)
|
||||||
DEFINE_FIELD(APowerMorph, MorphStyle)
|
DEFINE_FIELD(APowerMorph, MorphStyle)
|
||||||
DEFINE_FIELD(APowerMorph, MorphedPlayer)
|
DEFINE_FIELD(APowerMorph, MorphedPlayer)
|
||||||
DEFINE_FIELD(APowerMorph, bInUndoMorph)
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
|
@ -1778,77 +1643,3 @@ void APowerMorph::Serialize(FSerializer &arc)
|
||||||
("morphedplayer", MorphedPlayer);
|
("morphedplayer", MorphedPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// APowerMorph :: InitEffect
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void APowerMorph::InitEffect( )
|
|
||||||
{
|
|
||||||
Super::InitEffect();
|
|
||||||
|
|
||||||
if (Owner != nullptr && Owner->player != nullptr && PlayerClass != nullptr)
|
|
||||||
{
|
|
||||||
player_t *realplayer = Owner->player; // Remember the identity of the player
|
|
||||||
if (P_MorphPlayer(realplayer, realplayer, PlayerClass, INT_MAX/*INDEFINITELY*/, MorphStyle, MorphFlash, UnMorphFlash))
|
|
||||||
{
|
|
||||||
Owner = realplayer->mo; // Replace the new owner in our owner; safe because we are not attached to anything yet
|
|
||||||
ItemFlags |= IF_CREATECOPYMOVED; // Let the caller know the "real" owner has changed (to the morphed actor)
|
|
||||||
MorphedPlayer = realplayer; // Store the player identity (morphing clears the unmorphed actor's "player" field)
|
|
||||||
}
|
|
||||||
else // morph failed - give the caller an opportunity to fail the pickup completely
|
|
||||||
{
|
|
||||||
ItemFlags |= IF_INITEFFECTFAILED; // Let the caller know that the activation failed (can fail the pickup if appropriate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
//
|
|
||||||
// APowerMorph :: EndEffect
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void APowerMorph::EndEffect( )
|
|
||||||
{
|
|
||||||
Super::EndEffect();
|
|
||||||
|
|
||||||
// Abort if owner already destroyed or unmorphed
|
|
||||||
if (Owner == nullptr || MorphedPlayer == nullptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Abort if owner is dead; their Die() method will
|
|
||||||
// take care of any required unmorphing on death.
|
|
||||||
if (MorphedPlayer->health <= 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmorph if possible
|
|
||||||
if (!bInUndoMorph)
|
|
||||||
{
|
|
||||||
int savedMorphTics = MorphedPlayer->morphTics;
|
|
||||||
P_UndoPlayerMorph (MorphedPlayer, MorphedPlayer, 0, !!(MorphedPlayer->MorphStyle & MORPH_UNDOALWAYS));
|
|
||||||
|
|
||||||
// Abort if unmorph failed; in that case,
|
|
||||||
// set the usual retry timer and return.
|
|
||||||
if (MorphedPlayer != NULL && MorphedPlayer->morphTics)
|
|
||||||
{
|
|
||||||
// Transfer retry timeout
|
|
||||||
// to the powerup's timer.
|
|
||||||
EffectTics = MorphedPlayer->morphTics;
|
|
||||||
// Reload negative morph tics;
|
|
||||||
// use actual value; it may
|
|
||||||
// be in use for animation.
|
|
||||||
MorphedPlayer->morphTics = savedMorphTics;
|
|
||||||
// Try again some time later
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Unmorph suceeded
|
|
||||||
MorphedPlayer = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -203,24 +203,6 @@ protected:
|
||||||
virtual void EndEffect() override;
|
virtual void EndEffect() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class APowerDamage : public APowerup
|
|
||||||
{
|
|
||||||
DECLARE_CLASS( APowerDamage, APowerup )
|
|
||||||
protected:
|
|
||||||
virtual void InitEffect () override;
|
|
||||||
virtual void EndEffect () override;
|
|
||||||
virtual void ModifyDamage (int damage, FName damageType, int &newdamage, bool passive) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class APowerProtection : public APowerup
|
|
||||||
{
|
|
||||||
DECLARE_CLASS( APowerProtection, APowerup )
|
|
||||||
protected:
|
|
||||||
virtual void InitEffect () override;
|
|
||||||
virtual void EndEffect () override;
|
|
||||||
virtual void ModifyDamage (int damage, FName damageType, int &newdamage, bool passive) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
class APowerMorph : public APowerup
|
class APowerMorph : public APowerup
|
||||||
{
|
{
|
||||||
DECLARE_CLASS( APowerMorph, APowerup )
|
DECLARE_CLASS( APowerMorph, APowerup )
|
||||||
|
@ -228,18 +210,12 @@ class APowerMorph : public APowerup
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual void Serialize(FSerializer &arc) override;
|
virtual void Serialize(FSerializer &arc) override;
|
||||||
void SetNoCallUndoMorph() { bInUndoMorph = true; }
|
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
PClassPlayerPawn *PlayerClass;
|
PClassPlayerPawn *PlayerClass;
|
||||||
PClassActor *MorphFlash, *UnMorphFlash;
|
PClassActor *MorphFlash, *UnMorphFlash;
|
||||||
int MorphStyle;
|
int MorphStyle;
|
||||||
player_t *MorphedPlayer;
|
player_t *MorphedPlayer;
|
||||||
bool bInUndoMorph; // Because P_UndoPlayerMorph() can call EndEffect recursively
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void InitEffect () override;
|
|
||||||
virtual void EndEffect () override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //__A_ARTIFACTS_H__
|
#endif //__A_ARTIFACTS_H__
|
||||||
|
|
|
@ -724,9 +724,10 @@ void AInventory::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
||||||
|
|
||||||
void AInventory::ModifyDamage (int damage, FName damageType, int &newdamage, bool passive)
|
void AInventory::ModifyDamage (int damage, FName damageType, int &newdamage, bool passive)
|
||||||
{
|
{
|
||||||
if (Inventory != NULL)
|
IFVIRTUAL(AInventory, ModifyDamage)
|
||||||
{
|
{
|
||||||
Inventory->ModifyDamage (damage, damageType, newdamage, passive);
|
VMValue params[5] = { (DObject*)this, damage, int(damageType), &newdamage, passive };
|
||||||
|
GlobalVMStack.Call(func, params, 5, nullptr, 0, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ public:
|
||||||
|
|
||||||
// still need to be done.
|
// still need to be done.
|
||||||
virtual void AbsorbDamage(int damage, FName damageType, int &newdamage);
|
virtual void AbsorbDamage(int damage, FName damageType, int &newdamage);
|
||||||
virtual void ModifyDamage(int damage, FName damageType, int &newdamage, bool passive);
|
void ModifyDamage(int damage, FName damageType, int &newdamage, bool passive);
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
|
@ -154,6 +154,18 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_PlayerInfo, MorphPlayer)
|
||||||
|
{
|
||||||
|
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||||
|
PARAM_POINTER(victim, player_t);
|
||||||
|
PARAM_CLASS(spawntype, APlayerPawn);
|
||||||
|
PARAM_INT(duration);
|
||||||
|
PARAM_INT(style);
|
||||||
|
PARAM_CLASS_DEF(enter_flash, AActor);
|
||||||
|
PARAM_CLASS_DEF(exit_flash, AActor);
|
||||||
|
ACTION_RETURN_BOOL(P_MorphPlayer(self, victim, spawntype, duration, style, enter_flash, exit_flash));
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNC P_UndoPlayerMorph
|
// FUNC P_UndoPlayerMorph
|
||||||
|
@ -204,14 +216,15 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
|
||||||
mo->target = pmo->target;
|
mo->target = pmo->target;
|
||||||
mo->tracer = pmo->tracer;
|
mo->tracer = pmo->tracer;
|
||||||
pmo->player = nullptr;
|
pmo->player = nullptr;
|
||||||
|
mo->alternative = pmo->alternative = nullptr;
|
||||||
|
|
||||||
// Remove the morph power if the morph is being undone prematurely.
|
// Remove the morph power if the morph is being undone prematurely.
|
||||||
|
auto pmtype = PClass::FindActor("PowerMorph");
|
||||||
for (AInventory *item = pmo->Inventory, *next = nullptr; item != nullptr; item = next)
|
for (AInventory *item = pmo->Inventory, *next = nullptr; item != nullptr; item = next)
|
||||||
{
|
{
|
||||||
next = item->Inventory;
|
next = item->Inventory;
|
||||||
if (item->IsKindOf(RUNTIME_CLASS(APowerMorph)))
|
if (item->IsKindOf(pmtype))
|
||||||
{
|
{
|
||||||
static_cast<APowerMorph *>(item)->SetNoCallUndoMorph();
|
|
||||||
item->Destroy();
|
item->Destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -348,8 +361,6 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
|
||||||
beastweap->Destroy ();
|
beastweap->Destroy ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mo->alternative = nullptr;
|
|
||||||
pmo->alternative = nullptr;
|
|
||||||
pmo->Destroy ();
|
pmo->Destroy ();
|
||||||
// Restore playerclass armor to its normal amount.
|
// Restore playerclass armor to its normal amount.
|
||||||
AHexenArmor *hxarmor = mo->FindInventory<AHexenArmor>();
|
AHexenArmor *hxarmor = mo->FindInventory<AHexenArmor>();
|
||||||
|
|
|
@ -190,7 +190,7 @@ class SBarInfoCommand
|
||||||
}
|
}
|
||||||
EColorRange GetTranslation(FScanner &sc)
|
EColorRange GetTranslation(FScanner &sc)
|
||||||
{
|
{
|
||||||
sc.MustGetToken(TK_Identifier);
|
if (!sc.CheckToken(TK_Null)) sc.MustGetToken(TK_Identifier);
|
||||||
EColorRange returnVal = CR_UNTRANSLATED;
|
EColorRange returnVal = CR_UNTRANSLATED;
|
||||||
FString namedTranslation; //we must send in "[translation]"
|
FString namedTranslation; //we must send in "[translation]"
|
||||||
const BYTE *trans_ptr;
|
const BYTE *trans_ptr;
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "stats.h"
|
#include "stats.h"
|
||||||
#include "zstring.h"
|
#include "zstring.h"
|
||||||
#include "d_dehacked.h"
|
#include "d_dehacked.h"
|
||||||
|
#include "v_text.h"
|
||||||
|
|
||||||
|
|
||||||
#include "gl/dynlights/gl_dynlight.h"
|
#include "gl/dynlights/gl_dynlight.h"
|
||||||
|
@ -1336,12 +1337,13 @@ void gl_DoParseDefs(FScanner &sc, int workingLump)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void gl_LoadGLDefs(const char * defsLump)
|
void gl_LoadGLDefs(const char *defsLump)
|
||||||
{
|
{
|
||||||
int workingLump, lastLump;
|
int workingLump, lastLump;
|
||||||
|
static const char *gldefsnames[] = { "GLDEFS", defsLump, nullptr };
|
||||||
|
|
||||||
lastLump = 0;
|
lastLump = 0;
|
||||||
while ((workingLump = Wads.FindLump(defsLump, &lastLump)) != -1)
|
while ((workingLump = Wads.FindLumpMulti(gldefsnames, &lastLump)) != -1)
|
||||||
{
|
{
|
||||||
FScanner sc(workingLump);
|
FScanner sc(workingLump);
|
||||||
gl_DoParseDefs(sc, workingLump);
|
gl_DoParseDefs(sc, workingLump);
|
||||||
|
@ -1383,8 +1385,7 @@ void gl_ParseDefs()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gl_ParseVavoomSkybox();
|
gl_ParseVavoomSkybox();
|
||||||
if (defsLump != NULL) gl_LoadGLDefs(defsLump);
|
gl_LoadGLDefs(defsLump);
|
||||||
gl_LoadGLDefs("GLDEFS");
|
|
||||||
gl_InitializeActorLights();
|
gl_InitializeActorLights();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,12 +91,6 @@ TArray<spechit_t> portalhit;
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, CanCollideWith)
|
|
||||||
{
|
|
||||||
// No need to check the parameters, as they are not even used.
|
|
||||||
ACTION_RETURN_BOOL(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool P_CanCollideWith(AActor *tmthing, AActor *thing)
|
bool P_CanCollideWith(AActor *tmthing, AActor *thing)
|
||||||
{
|
{
|
||||||
static unsigned VIndex = ~0u;
|
static unsigned VIndex = ~0u;
|
||||||
|
|
|
@ -7420,8 +7420,12 @@ DEFINE_ACTION_FUNCTION(AActor, ClearCounters)
|
||||||
|
|
||||||
int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive)
|
int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive)
|
||||||
{
|
{
|
||||||
if (Inventory != nullptr)
|
auto inv = Inventory;
|
||||||
Inventory->ModifyDamage(damage, damagetype, damage, passive);
|
while (inv != nullptr)
|
||||||
|
{
|
||||||
|
inv->ModifyDamage(damage, damagetype, damage, passive);
|
||||||
|
inv = inv->Inventory;
|
||||||
|
}
|
||||||
|
|
||||||
return damage;
|
return damage;
|
||||||
}
|
}
|
||||||
|
@ -7847,6 +7851,25 @@ DEFINE_ACTION_FUNCTION(AActor, CountsAsKill)
|
||||||
ACTION_RETURN_FLOAT(self->CountsAsKill());
|
ACTION_RETURN_FLOAT(self->CountsAsKill());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(AActor, ApplyDamageFactors)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_CLASS(itemcls, AInventory);
|
||||||
|
PARAM_NAME(damagetype);
|
||||||
|
PARAM_INT(damage);
|
||||||
|
PARAM_INT(defdamage);
|
||||||
|
|
||||||
|
DmgFactors *df = itemcls->DamageFactors;
|
||||||
|
if (df != nullptr && df->CountUsed() != 0)
|
||||||
|
{
|
||||||
|
ACTION_RETURN_INT(df->Apply(damagetype, damage));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ACTION_RETURN_INT(defdamage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// DropItem handling
|
// DropItem handling
|
||||||
|
|
|
@ -1576,6 +1576,22 @@ public:
|
||||||
sec->reflect[sector_t::ceiling] = (float)CheckFloat(key);
|
sec->reflect[sector_t::ceiling] = (float)CheckFloat(key);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NAME_floorglowcolor:
|
||||||
|
sec->planes[sector_t::floor].GlowColor = CheckInt(key);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAME_floorglowheight:
|
||||||
|
sec->planes[sector_t::floor].GlowHeight = (float)CheckFloat(key);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAME_ceilingglowcolor:
|
||||||
|
sec->planes[sector_t::ceiling].GlowColor = CheckInt(key);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NAME_ceilingglowheight:
|
||||||
|
sec->planes[sector_t::ceiling].GlowHeight = (float)CheckFloat(key);
|
||||||
|
break;
|
||||||
|
|
||||||
case NAME_MoreIds:
|
case NAME_MoreIds:
|
||||||
// delay parsing of the tag string until parsing of the sector is complete
|
// delay parsing of the tag string until parsing of the sector is complete
|
||||||
// This ensures that the ID is always the first tag in the list.
|
// This ensures that the ID is always the first tag in the list.
|
||||||
|
|
|
@ -467,15 +467,30 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VMCycles[0].Clock();
|
auto code = static_cast<VMScriptFunction *>(func)->Code;
|
||||||
VMCalls[0]++;
|
// handle empty functions consisting of a single return explicitly so that empty virtual callbacks do not need to set up an entire VM frame.
|
||||||
AllocFrame(static_cast<VMScriptFunction *>(func));
|
if (code->word == 0x0080804e)
|
||||||
allocated = true;
|
{
|
||||||
VMFillParams(params, TopFrame(), numparams);
|
return 0;
|
||||||
int numret = VMExec(this, static_cast<VMScriptFunction *>(func)->Code, results, numresults);
|
}
|
||||||
PopFrame();
|
else if (code->word == 0x0004804e)
|
||||||
VMCycles[0].Unclock();
|
{
|
||||||
return numret;
|
if (numresults == 0) return 0;
|
||||||
|
results[0].SetInt(static_cast<VMScriptFunction *>(func)->KonstD[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VMCycles[0].Clock();
|
||||||
|
VMCalls[0]++;
|
||||||
|
AllocFrame(static_cast<VMScriptFunction *>(func));
|
||||||
|
allocated = true;
|
||||||
|
VMFillParams(params, TopFrame(), numparams);
|
||||||
|
int numret = VMExec(this, code, results, numresults);
|
||||||
|
PopFrame();
|
||||||
|
VMCycles[0].Unclock();
|
||||||
|
return numret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (VMException *exception)
|
catch (VMException *exception)
|
||||||
|
|
|
@ -733,7 +733,7 @@ void FString::StripRight (const char *charset)
|
||||||
if (!strchr (charset, Chars[i]))
|
if (!strchr (charset, Chars[i]))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (i == max-1)
|
if (i == max)
|
||||||
{ // Nothing to strip.
|
{ // Nothing to strip.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,16 +270,22 @@ class Actor : Thinker native
|
||||||
virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0);
|
virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0);
|
||||||
virtual native bool Slam(Actor victim);
|
virtual native bool Slam(Actor victim);
|
||||||
virtual native void Touch(Actor toucher);
|
virtual native void Touch(Actor toucher);
|
||||||
virtual native bool CanCollideWith(Actor other, bool passive); // This is an empty native function, it's native for the sole reason of performance as this is in a performance critical spot.
|
|
||||||
|
|
||||||
// Called when an actor is to be reflected by a disc of repulsion.
|
// Called by PIT_CheckThing to check if two actos actually can collide.
|
||||||
// Returns true to continue normal blast processing.
|
virtual bool CanCollideWith(Actor other, bool passive)
|
||||||
virtual bool SpecialBlastHandling (Actor source, double strength) // this is entirely on the script side with no native part at all.
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int SpecialMissileHit (Actor victim) // for this no native version exists
|
// Called when an actor is to be reflected by a disc of repulsion.
|
||||||
|
// Returns true to continue normal blast processing.
|
||||||
|
virtual bool SpecialBlastHandling (Actor source, double strength)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is called before a missile gets exploded.
|
||||||
|
virtual int SpecialMissileHit (Actor victim)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -288,6 +294,7 @@ class Actor : Thinker native
|
||||||
native static int GetSpriteIndex(name sprt);
|
native static int GetSpriteIndex(name sprt);
|
||||||
native static double GetDefaultSpeed(class<Actor> type);
|
native static double GetDefaultSpeed(class<Actor> type);
|
||||||
native static class<Actor> GetSpawnableType(int spawnnum);
|
native static class<Actor> GetSpawnableType(int spawnnum);
|
||||||
|
native static int ApplyDamageFactors(class<Inventory> itemcls, Name damagetype, int damage, int defdamage);
|
||||||
native void RemoveFromHash();
|
native void RemoveFromHash();
|
||||||
native void ChangeTid(int newtid);
|
native void ChangeTid(int newtid);
|
||||||
native static int FindUniqueTid(int start = 0, int limit = 0);
|
native static int FindUniqueTid(int start = 0, int limit = 0);
|
||||||
|
|
|
@ -40,6 +40,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) {}
|
||||||
|
|
||||||
native void GoAwayAndDie();
|
native void GoAwayAndDie();
|
||||||
native void BecomeItem();
|
native void BecomeItem();
|
||||||
|
|
|
@ -253,6 +253,7 @@ FWeaponSlots weapons;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
native bool MorphPlayer(playerinfo p, Class<PlayerPawn> spawntype, int duration, int style, Class<Actor> enter_flash = null, Class<Actor> exit_flash = null);
|
||||||
native bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false);
|
native bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false);
|
||||||
native bool PoisonPlayer(Actor poisoner, Actor source, int poison);
|
native bool PoisonPlayer(Actor poisoner, Actor source, int poison);
|
||||||
native void PoisonDamage(Actor source, int damage, bool playPainSound);
|
native void PoisonDamage(Actor source, int damage, bool playPainSound);
|
||||||
|
|
|
@ -236,20 +236,158 @@ class PowerTimeFreezer : Powerup native
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PowerDamage : Powerup native
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Damage
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
class PowerDamage : Powerup
|
||||||
{
|
{
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
Powerup.Duration -25;
|
Powerup.Duration -25;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// InitEffect
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void InitEffect()
|
||||||
|
{
|
||||||
|
Super.InitEffect();
|
||||||
|
|
||||||
|
if (Owner != null)
|
||||||
|
{
|
||||||
|
Owner.A_PlaySound(SeeSound, CHAN_5, 1.0, false, ATTN_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// EndEffect
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void EndEffect()
|
||||||
|
{
|
||||||
|
Super.EndEffect();
|
||||||
|
if (Owner != null)
|
||||||
|
{
|
||||||
|
Owner.A_PlaySound(DeathSound, CHAN_5, 1.0, false, ATTN_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// ModifyDamage
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive)
|
||||||
|
{
|
||||||
|
if (!passive && damage > 0)
|
||||||
|
{
|
||||||
|
newdamage = max(1, ApplyDamageFactors(GetClass(), damageType, damage, damage * 4));
|
||||||
|
if (Owner != null && newdamage > damage) Owner.A_PlaySound(ActiveSound, CHAN_AUTO, 1.0, false, ATTN_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PowerProtection : Powerup native
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// Protection
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
class PowerProtection : Powerup
|
||||||
{
|
{
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
Powerup.Duration -25;
|
Powerup.Duration -25;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// InitEffect
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void InitEffect()
|
||||||
|
{
|
||||||
|
Super.InitEffect();
|
||||||
|
|
||||||
|
let o = Owner; // copy to a local variable for quicker access.
|
||||||
|
if (o != null)
|
||||||
|
{
|
||||||
|
o.A_PlaySound(SeeSound, CHAN_AUTO, 1.0, false, ATTN_NONE);
|
||||||
|
|
||||||
|
// Transfer various protection flags if owner does not already have them.
|
||||||
|
// If the owner already has the flag, clear it from the powerup.
|
||||||
|
// If the powerup still has a flag set, add it to the owner.
|
||||||
|
bNoRadiusDmg &= !o.bNoRadiusDmg;
|
||||||
|
o.bNoRadiusDmg |= bNoRadiusDmg;
|
||||||
|
|
||||||
|
bDontMorph &= !o.bDontMorph;
|
||||||
|
o.bDontMorph |= bDontMorph;
|
||||||
|
|
||||||
|
bDontSquash &= !o.bDontSquash;
|
||||||
|
o.bDontSquash |= bDontSquash;
|
||||||
|
|
||||||
|
bDontBlast &= !o.bDontBlast;
|
||||||
|
o.bDontBlast |= bDontBlast;
|
||||||
|
|
||||||
|
bNoTeleOther &= !o.bNoTeleOther;
|
||||||
|
o.bNoTeleOther |= bNoTeleOther;
|
||||||
|
|
||||||
|
bNoPain &= !o.bNoPain;
|
||||||
|
o.bNoPain |= bNoPain;
|
||||||
|
|
||||||
|
bDontRip &= !o.bDontRip;
|
||||||
|
o.bDontRip |= bDontRip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// EndEffect
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void EndEffect()
|
||||||
|
{
|
||||||
|
Super.EndEffect();
|
||||||
|
let o = Owner; // copy to a local variable for quicker access.
|
||||||
|
if (o != null)
|
||||||
|
{
|
||||||
|
o.A_PlaySound(DeathSound, CHAN_AUTO, 1.0, false, ATTN_NONE);
|
||||||
|
|
||||||
|
o.bNoRadiusDmg &= !bNoRadiusDmg;
|
||||||
|
o.bDontMorph &= !bDontMorph;
|
||||||
|
o.bDontSquash &= !bDontSquash;
|
||||||
|
o.bDontBlast &= !bDontBlast;
|
||||||
|
o.bNoTeleOther &= !bNoTeleOther;
|
||||||
|
o.bNoPain &= !bNoPain;
|
||||||
|
o.bDontRip &= !bDontRip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// AbsorbDamage
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive)
|
||||||
|
{
|
||||||
|
if (passive && damage > 0)
|
||||||
|
{
|
||||||
|
newdamage = max(1, ApplyDamageFactors(GetClass(), damageType, damage, damage / 4));
|
||||||
|
if (Owner != null && newdamage < damage) Owner.A_PlaySound(ActiveSound, CHAN_AUTO, 1.0, false, ATTN_NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
@ -430,11 +568,82 @@ class PowerMorph : Powerup native
|
||||||
native Class<Actor> MorphFlash, UnMorphFlash;
|
native Class<Actor> MorphFlash, UnMorphFlash;
|
||||||
native int MorphStyle;
|
native int MorphStyle;
|
||||||
native PlayerInfo MorphedPlayer;
|
native PlayerInfo MorphedPlayer;
|
||||||
native bool bInUndoMorph;
|
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
Powerup.Duration -40;
|
Powerup.Duration -40;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// InitEffect
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void InitEffect()
|
||||||
|
{
|
||||||
|
Super.InitEffect();
|
||||||
|
|
||||||
|
if (Owner != null && Owner.player != null && PlayerClass != null)
|
||||||
|
{
|
||||||
|
let realplayer = Owner.player; // Remember the identity of the player
|
||||||
|
if (realplayer.MorphPlayer(realplayer, PlayerClass, 0x7fffffff/*INDEFINITELY*/, MorphStyle, MorphFlash, UnMorphFlash))
|
||||||
|
{
|
||||||
|
Owner = realplayer.mo; // Replace the new owner in our owner; safe because we are not attached to anything yet
|
||||||
|
bCreateCopyMoved = true; // Let the caller know the "real" owner has changed (to the morphed actor)
|
||||||
|
MorphedPlayer = realplayer; // Store the player identity (morphing clears the unmorphed actor's "player" field)
|
||||||
|
}
|
||||||
|
else // morph failed - give the caller an opportunity to fail the pickup completely
|
||||||
|
{
|
||||||
|
bInitEffectFailed = true; // Let the caller know that the activation failed (can fail the pickup if appropriate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// EndEffect
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
override void EndEffect()
|
||||||
|
{
|
||||||
|
Super.EndEffect();
|
||||||
|
|
||||||
|
// Abort if owner already destroyed or unmorphed
|
||||||
|
if (Owner == null || MorphedPlayer == null || Owner.alternative == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abort if owner is dead; their Die() method will
|
||||||
|
// take care of any required unmorphing on death.
|
||||||
|
if (MorphedPlayer.health <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int savedMorphTics = MorphedPlayer.morphTics;
|
||||||
|
MorphedPlayer.UndoPlayerMorph (MorphedPlayer, 0, !!(MorphedPlayer.MorphStyle & MRF_UNDOALWAYS));
|
||||||
|
|
||||||
|
// Abort if unmorph failed; in that case,
|
||||||
|
// set the usual retry timer and return.
|
||||||
|
if (MorphedPlayer != null && MorphedPlayer.morphTics)
|
||||||
|
{
|
||||||
|
// Transfer retry timeout
|
||||||
|
// to the powerup's timer.
|
||||||
|
EffectTics = MorphedPlayer.morphTics;
|
||||||
|
// Reload negative morph tics;
|
||||||
|
// use actual value; it may
|
||||||
|
// be in use for animation.
|
||||||
|
MorphedPlayer.morphTics = savedMorphTics;
|
||||||
|
// Try again some time later
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Unmorph suceeded
|
||||||
|
MorphedPlayer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue