From 2d2963ead43a8183c5819f977b352014c173b476 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Jan 2017 16:55:45 +0100 Subject: [PATCH 1/6] - fixed: The StripRight fix left some code from a previous fix in that no longer applies. --- src/zstring.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zstring.cpp b/src/zstring.cpp index cef956c90..d17348bd3 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -733,7 +733,7 @@ void FString::StripRight (const char *charset) if (!strchr (charset, Chars[i])) break; } - if (i == max-1) + if (i == max) { // Nothing to strip. return; } From 66cc68606f7c337aaa9c729d70c8f63256bffa29 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Jan 2017 19:23:43 +0100 Subject: [PATCH 2/6] - scriptified the methods of APowerMorph. - made some changes to PowerMorph to better deal with recursive calls from UndoPlayerMorph. The flag hackery was only needed because the 'alternative' pointers were cleared far too late. --- src/g_inventory/a_artifacts.cpp | 75 ----------------------- src/g_inventory/a_artifacts.h | 6 -- src/g_shared/a_morph.cpp | 19 ++++-- wadsrc/static/zscript/shared/player.txt | 1 + wadsrc/static/zscript/shared/powerups.txt | 73 +++++++++++++++++++++- 5 files changed, 88 insertions(+), 86 deletions(-) diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index 00efa0579..f78c6875e 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -1759,7 +1759,6 @@ DEFINE_FIELD(APowerMorph, MorphFlash) DEFINE_FIELD(APowerMorph, UnMorphFlash) DEFINE_FIELD(APowerMorph, MorphStyle) DEFINE_FIELD(APowerMorph, MorphedPlayer) -DEFINE_FIELD(APowerMorph, bInUndoMorph) //=========================================================================== // @@ -1777,77 +1776,3 @@ void APowerMorph::Serialize(FSerializer &arc) ("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; -} - diff --git a/src/g_inventory/a_artifacts.h b/src/g_inventory/a_artifacts.h index f68516de7..90670abb5 100644 --- a/src/g_inventory/a_artifacts.h +++ b/src/g_inventory/a_artifacts.h @@ -228,18 +228,12 @@ class APowerMorph : public APowerup public: virtual void Serialize(FSerializer &arc) override; - void SetNoCallUndoMorph() { bInUndoMorph = true; } // Variables PClassPlayerPawn *PlayerClass; PClassActor *MorphFlash, *UnMorphFlash; int MorphStyle; 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__ diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 7550ff0da..935efa2db 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -154,6 +154,18 @@ bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntyp 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 @@ -204,14 +216,15 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, mo->target = pmo->target; mo->tracer = pmo->tracer; pmo->player = nullptr; + mo->alternative = pmo->alternative = nullptr; // 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) { next = item->Inventory; - if (item->IsKindOf(RUNTIME_CLASS(APowerMorph))) + if (item->IsKindOf(pmtype)) { - static_cast(item)->SetNoCallUndoMorph(); item->Destroy(); } } @@ -348,8 +361,6 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, beastweap->Destroy (); } } - mo->alternative = nullptr; - pmo->alternative = nullptr; pmo->Destroy (); // Restore playerclass armor to its normal amount. AHexenArmor *hxarmor = mo->FindInventory(); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 2f6dc4bc1..953b9d971 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -251,6 +251,7 @@ FWeaponSlots weapons; */ + native bool MorphPlayer(playerinfo p, Class spawntype, int duration, int style, Class enter_flash = null, Class exit_flash = null); native bool UndoPlayerMorph(playerinfo player, int unmorphflag = 0, bool force = false); native bool PoisonPlayer(Actor poisoner, Actor source, int poison); native void PoisonDamage(Actor source, int damage, bool playPainSound); diff --git a/wadsrc/static/zscript/shared/powerups.txt b/wadsrc/static/zscript/shared/powerups.txt index 868951166..c6064d676 100644 --- a/wadsrc/static/zscript/shared/powerups.txt +++ b/wadsrc/static/zscript/shared/powerups.txt @@ -430,11 +430,82 @@ class PowerMorph : Powerup native native Class MorphFlash, UnMorphFlash; native int MorphStyle; native PlayerInfo MorphedPlayer; - native bool bInUndoMorph; Default { 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; + } + + } From 5de3d662cbf238853f0c38e43b57ae4a1efaad97 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Jan 2017 19:36:51 +0100 Subject: [PATCH 3/6] - re-added the glow properties for UDMF which somehow got lost. --- src/p_udmf.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 461feb9c8..51bd780f5 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1576,6 +1576,22 @@ public: sec->reflect[sector_t::ceiling] = (float)CheckFloat(key); 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: // 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. From 1d3afce59be59fb76611e9dbf7626be89475f9dd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Jan 2017 22:52:11 +0100 Subject: [PATCH 4/6] - let SBARINFO treat 'null' as 'untranslated'. Strictly speaking this wasn't a bug but apparently some people tend to use 'null' as a general placeholder for 'nothing', even where not intended. --- src/g_shared/sbarinfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 8ca8d6816..c06abf90d 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -190,7 +190,7 @@ class SBarInfoCommand } EColorRange GetTranslation(FScanner &sc) { - sc.MustGetToken(TK_Identifier); + if (!sc.CheckToken(TK_Null)) sc.MustGetToken(TK_Identifier); EColorRange returnVal = CR_UNTRANSLATED; FString namedTranslation; //we must send in "[translation]" const BYTE *trans_ptr; From 99481891936fdc1d469d527dc3c5094104122435 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 1 Jan 2017 23:11:48 +0100 Subject: [PATCH 5/6] - scriptified PowerProtection and PowerDamage. - made ModifyDamage calls iterative instead of recursive. With going through the VM they'd be too costly otherwise. - small optimization: Detect empty VM functions right when entering the VM and shortcut them. This is to reduce the overhead of virtual placeholders, which in a few cases (e.g. CanCollideWith and ModifyDamage) can be called quite frequently. --- src/g_inventory/a_artifacts.cpp | 134 ------------------- src/g_inventory/a_artifacts.h | 18 --- src/g_inventory/a_pickups.cpp | 5 +- src/g_inventory/a_pickups.h | 2 +- src/p_map.cpp | 6 - src/p_mobj.cpp | 27 +++- src/scripting/vm/vmframe.cpp | 33 +++-- wadsrc/static/zscript/actor.txt | 17 ++- wadsrc/static/zscript/shared/inventory.txt | 1 + wadsrc/static/zscript/shared/powerups.txt | 142 ++++++++++++++++++++- 10 files changed, 206 insertions(+), 179 deletions(-) diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index f78c6875e..335565efd 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -1608,140 +1608,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 ------------------------------------------------------ diff --git a/src/g_inventory/a_artifacts.h b/src/g_inventory/a_artifacts.h index 90670abb5..746d22589 100644 --- a/src/g_inventory/a_artifacts.h +++ b/src/g_inventory/a_artifacts.h @@ -203,24 +203,6 @@ protected: 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 { DECLARE_CLASS( APowerMorph, APowerup ) diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 3c1d32d42..c963fd918 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -724,9 +724,10 @@ void AInventory::AbsorbDamage (int damage, FName damageType, int &newdamage) 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); } } diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 32914e3e5..ea87cfe85 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -128,7 +128,7 @@ public: // still need to be done. 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. virtual bool DrawPowerup(int x, int y); diff --git a/src/p_map.cpp b/src/p_map.cpp index 434db69f1..5bbb9c3f9 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -91,12 +91,6 @@ TArray 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) { static unsigned VIndex = ~0u; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 8d31035a2..0919cfa3b 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -7420,8 +7420,12 @@ DEFINE_ACTION_FUNCTION(AActor, ClearCounters) int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive) { - if (Inventory != nullptr) - Inventory->ModifyDamage(damage, damagetype, damage, passive); + auto inv = Inventory; + while (inv != nullptr) + { + inv->ModifyDamage(damage, damagetype, damage, passive); + inv = inv->Inventory; + } return damage; } @@ -7847,6 +7851,25 @@ DEFINE_ACTION_FUNCTION(AActor, 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 diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index c500c9359..08559445e 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -467,15 +467,30 @@ int VMFrameStack::Call(VMFunction *func, VMValue *params, int numparams, VMRetur } else { - VMCycles[0].Clock(); - VMCalls[0]++; - AllocFrame(static_cast(func)); - allocated = true; - VMFillParams(params, TopFrame(), numparams); - int numret = VMExec(this, static_cast(func)->Code, results, numresults); - PopFrame(); - VMCycles[0].Unclock(); - return numret; + auto code = static_cast(func)->Code; + // handle empty functions consisting of a single return explicitly so that empty virtual callbacks do not need to set up an entire VM frame. + if (code->word == 0x0080804e) + { + return 0; + } + else if (code->word == 0x0004804e) + { + if (numresults == 0) return 0; + results[0].SetInt(static_cast(func)->KonstD[0]); + return 1; + } + else + { + VMCycles[0].Clock(); + VMCalls[0]++; + AllocFrame(static_cast(func)); + allocated = true; + VMFillParams(params, TopFrame(), numparams); + int numret = VMExec(this, code, results, numresults); + PopFrame(); + VMCycles[0].Unclock(); + return numret; + } } } catch (VMException *exception) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2ced709ae..bbd4b3073 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -270,16 +270,22 @@ class Actor : Thinker native virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0); virtual native bool Slam(Actor victim); 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. - // Returns true to continue normal blast processing. - virtual bool SpecialBlastHandling (Actor source, double strength) // this is entirely on the script side with no native part at all. + // Called by PIT_CheckThing to check if two actos actually can collide. + virtual bool CanCollideWith(Actor other, bool passive) { 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; } @@ -288,6 +294,7 @@ class Actor : Thinker native native static int GetSpriteIndex(name sprt); native static double GetDefaultSpeed(class type); native static class GetSpawnableType(int spawnnum); + native static int ApplyDamageFactors(class itemcls, Name damagetype, int damage, int defdamage); native void RemoveFromHash(); native void ChangeTid(int newtid); native static int FindUniqueTid(int start = 0, int limit = 0); diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index 6d034e789..d33b5e112 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -40,6 +40,7 @@ class Inventory : Actor native virtual double GetSpeedFactor() { return 1; } virtual bool GetNoTeleportFreeze() { return false; } + virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {} native void GoAwayAndDie(); native void BecomeItem(); diff --git a/wadsrc/static/zscript/shared/powerups.txt b/wadsrc/static/zscript/shared/powerups.txt index c6064d676..1ef333f60 100644 --- a/wadsrc/static/zscript/shared/powerups.txt +++ b/wadsrc/static/zscript/shared/powerups.txt @@ -236,20 +236,158 @@ class PowerTimeFreezer : Powerup native } } -class PowerDamage : Powerup native +//=========================================================================== +// +// Damage +// +//=========================================================================== + +class PowerDamage : Powerup { Default { 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 { 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); + } + } } //=========================================================================== From 6ab8e90911c310b918421a71d781fa1337b834df Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 2 Jan 2017 00:28:30 +0100 Subject: [PATCH 6/6] - parse GLDEFS and its game-specific variants in lump order instead of both names sequentially. --- src/gl/dynlights/gl_dynlight.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/gl/dynlights/gl_dynlight.cpp b/src/gl/dynlights/gl_dynlight.cpp index de05bb19f..8e3fa34df 100644 --- a/src/gl/dynlights/gl_dynlight.cpp +++ b/src/gl/dynlights/gl_dynlight.cpp @@ -48,6 +48,7 @@ #include "stats.h" #include "zstring.h" #include "d_dehacked.h" +#include "v_text.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; + static const char *gldefsnames[] = { "GLDEFS", defsLump, nullptr }; lastLump = 0; - while ((workingLump = Wads.FindLump(defsLump, &lastLump)) != -1) + while ((workingLump = Wads.FindLumpMulti(gldefsnames, &lastLump)) != -1) { FScanner sc(workingLump); gl_DoParseDefs(sc, workingLump); @@ -1383,8 +1385,7 @@ void gl_ParseDefs() break; } gl_ParseVavoomSkybox(); - if (defsLump != NULL) gl_LoadGLDefs(defsLump); - gl_LoadGLDefs("GLDEFS"); + gl_LoadGLDefs(defsLump); gl_InitializeActorLights(); }