From ae7b95fc52a7a77d49eeaefba551c9415ec5faff Mon Sep 17 00:00:00 2001 From: Braden Obrzut Date: Mon, 16 Jan 2017 02:19:03 -0500 Subject: [PATCH 1/9] - There are more DYN options than just fluidsynth so unconditionally use CMAKE_DL_LIBS. --- src/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 60ee44f18..7909ec5dd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -595,7 +595,7 @@ add_custom_target( revision_check ALL # Libraries ZDoom needs message( STATUS "Fluid synth libs: ${FLUIDSYNTH_LIBRARIES}" ) -set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" ) +set( ZDOOM_LIBS ${ZDOOM_LIBS} "${ZLIB_LIBRARIES}" "${JPEG_LIBRARIES}" "${BZIP2_LIBRARIES}" "${GME_LIBRARIES}" "${CMAKE_DL_LIBS}" ) include_directories( "${ZLIB_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GME_INCLUDE_DIR}" ) if( SNDFILE_FOUND ) @@ -611,8 +611,6 @@ if( NOT DYN_FLUIDSYNTH ) set( ZDOOM_LIBS ${ZDOOM_LIBS} "${FLUIDSYNTH_LIBRARIES}" ) include_directories( "${FLUIDSYNTH_INCLUDE_DIR}" ) endif() -else() - set( ZDOOM_LIBS ${ZDOOM_LIBS} ${CMAKE_DL_LIBS} ) endif() # Start defining source files for ZDoom From cd0d17dbd5c389f778c9339ff826a0d0e33645fb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 16 Jan 2017 01:16:11 +0100 Subject: [PATCH 2/9] - made AbsorbDamage work iteratively to avoid large stack use in the VM. --- src/actor.h | 1 + src/g_inventory/a_armor.cpp | 8 -------- src/g_inventory/a_artifacts.cpp | 4 ---- src/g_inventory/a_pickups.cpp | 4 ---- src/p_interaction.cpp | 4 ++-- src/p_mobj.cpp | 14 ++++++++++++++ 6 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/actor.h b/src/actor.h index 6b4ce4ae7..09c1b9918 100644 --- a/src/actor.h +++ b/src/actor.h @@ -616,6 +616,7 @@ public: // Adjusts the angle for deflection/reflection of incoming missiles // Returns true if the missile should be allowed to explode anyway bool AdjustReflectionAngle (AActor *thing, DAngle &angle); + int AbsorbDamage(int damage, FName dmgtype); // Returns true if this actor is within melee range of its target bool CheckMeleeRange(); diff --git a/src/g_inventory/a_armor.cpp b/src/g_inventory/a_armor.cpp index ebe8f49f6..e19b50259 100644 --- a/src/g_inventory/a_armor.cpp +++ b/src/g_inventory/a_armor.cpp @@ -235,10 +235,6 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage) damage = newdamage = df->Apply(damageType, damage); } } - if (Inventory != NULL) - { - Inventory->AbsorbDamage (damage, damageType, newdamage); - } } //=========================================================================== @@ -629,10 +625,6 @@ void AHexenArmor::AbsorbDamage (int damage, FName damageType, int &newdamage) damage = newdamage; } } - if (Inventory != NULL) - { - Inventory->AbsorbDamage (damage, damageType, newdamage); - } } //=========================================================================== diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index f8e34c9a7..2ab8ca51a 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -845,10 +845,6 @@ void APowerIronFeet::AbsorbDamage (int damage, FName damageType, int &newdamage) { newdamage = 0; } - else if (Inventory != NULL) - { - Inventory->AbsorbDamage (damage, damageType, newdamage); - } } //=========================================================================== diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 72e51b0c9..c82c146d2 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -697,10 +697,6 @@ DEFINE_ACTION_FUNCTION(AInventory, BecomePickup) void AInventory::AbsorbDamage (int damage, FName damageType, int &newdamage) { - if (Inventory != NULL) - { - Inventory->AbsorbDamage (damage, damageType, newdamage); - } } //=========================================================================== diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 97787fd9c..d3dbe0232 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1305,7 +1305,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da int newdam = damage; if (damage > 0) { - player->mo->Inventory->AbsorbDamage(damage, mod, newdam); + newdam = player->mo->AbsorbDamage(damage, mod); } if (!telefragDamage || (player->mo->flags7 & MF7_LAXTELEFRAGDMG)) //rawdamage is never modified. { @@ -1385,7 +1385,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da if (!(flags & (DMG_NO_ARMOR|DMG_FORCED)) && target->Inventory != NULL && damage > 0) { int newdam = damage; - target->Inventory->AbsorbDamage (damage, mod, newdam); + newdam = target->AbsorbDamage damage, mod); damage = newdam; if (damage <= 0) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index b40b8baa3..4985454ae 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3615,6 +3615,20 @@ bool AActor::AdjustReflectionAngle (AActor *thing, DAngle &angle) return false; } +int AActor::AbsorbDamage(int damage, FName dmgtype) +{ + for (AInventory *item = Inventory; item != nullptr; item = item->Inventory) + { + IFVIRTUALPTR(item, AInventory, AbsorbDamage) + { + VMValue params[4] = { (item, damage, dmgtype.GetIndex(), &damage }; + GlobalVMStack.Call(func, params, 4, nullptr, 0, nullptr); + } + else item->AbsorbDamage(damage, dmgtype, damage); + } + return damage; +} + void AActor::PlayActiveSound () { if (ActiveSound && !S_IsActorPlayingSomething (this, CHAN_VOICE, -1)) From cd1d96b83a47558e3410655da86ac20ee347081d Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 16 Jan 2017 10:23:26 +0100 Subject: [PATCH 3/9] - fixed compilation. --- src/g_inventory/a_pickups.cpp | 9 +++++++++ src/p_interaction.cpp | 2 +- src/p_mobj.cpp | 2 +- wadsrc/static/zscript/inventory/inventory.txt | 1 + 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index c82c146d2..4a7783ae4 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -699,6 +699,15 @@ void AInventory::AbsorbDamage (int damage, FName damageType, int &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 diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index d3dbe0232..a73e3d8b3 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1385,7 +1385,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da if (!(flags & (DMG_NO_ARMOR|DMG_FORCED)) && target->Inventory != NULL && damage > 0) { int newdam = damage; - newdam = target->AbsorbDamage damage, mod); + newdam = target->AbsorbDamage(damage, mod); damage = newdam; if (damage <= 0) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 4985454ae..5d86e78ff 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3621,7 +3621,7 @@ int AActor::AbsorbDamage(int damage, FName dmgtype) { IFVIRTUALPTR(item, AInventory, AbsorbDamage) { - VMValue params[4] = { (item, damage, dmgtype.GetIndex(), &damage }; + VMValue params[4] = { item, damage, dmgtype.GetIndex(), &damage }; GlobalVMStack.Call(func, params, 4, nullptr, 0, nullptr); } else item->AbsorbDamage(damage, dmgtype, damage); diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index d3f6bfef5..7db3ba212 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -39,6 +39,7 @@ class Inventory : Actor native virtual native void AttachToOwner(Actor user); virtual native void DetachFromOwner(); virtual native bool DrawPowerup(int x, int y); + virtual native void AbsorbDamage (int damage, Name damageType, out int newdamage); //=========================================================================== // From 65b7e344f7b9bdc054e0a910a8d3ddb19762dd72 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 16 Jan 2017 10:36:23 +0100 Subject: [PATCH 4/9] - added custom property parsing to DECORATE as well. --- src/scripting/decorate/thingdef_parse.cpp | 68 +++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index f53b97006..2eee0f01d 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -819,6 +819,63 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau return true; } +//========================================================================== +// +// Parses an actor property's parameters and calls the handler +// +//========================================================================== + +static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaults, Baggage &bag) +{ + for (unsigned i=0; iVariables.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(f->Type)->SetValue(addr, sc.Number); + } + else if (f->Type->IsKindOf(RUNTIME_CLASS(PFloat))) + { + sc.MustGetFloat(); + static_cast(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->IsDescendantOf(static_cast(f->Type)->ClassRestriction)) + { + sc.ScriptMessage("class %s is not compatible with property type %s", cls->TypeName.GetChars(), static_cast(f->Type)->ClassRestriction->TypeName.GetChars()); + FScriptPosition::ErrorCounter++; + } + } + else + { + sc.ScriptMessage("unhandled property type %s", f->Type->DescriptiveName()); + FScriptPosition::ErrorCounter++; + } + } +} + //========================================================================== // // Parses an actor property @@ -867,6 +924,17 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag) } else { + propname.Insert(0, "@property@"); + FName name(propname, true); + if (name != NAME_None) + { + auto propp = dyn_cast(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()); } } From 616f954153b130d8b8047ac4ae7fd5ecb44fb908 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 16 Jan 2017 19:04:03 +0100 Subject: [PATCH 5/9] - scriptified PowerIronFeet and PowerMask. --- src/g_inventory/a_armor.cpp | 2 + src/g_inventory/a_artifacts.cpp | 71 -------------------- src/g_inventory/a_artifacts.h | 16 ----- src/p_spec.cpp | 6 +- src/serializer.cpp | 2 +- wadsrc/static/zscript/inventory/powerups.txt | 51 +++++++++++++- 6 files changed, 56 insertions(+), 92 deletions(-) diff --git a/src/g_inventory/a_armor.cpp b/src/g_inventory/a_armor.cpp index e19b50259..8bb32c921 100644 --- a/src/g_inventory/a_armor.cpp +++ b/src/g_inventory/a_armor.cpp @@ -229,6 +229,8 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage) // This code is taken and adapted from APowerProtection::ModifyDamage(). // The differences include not using a default value, and of course the way // the damage factor info is obtained. + + // ApplyDamageFactors(ArmorType, damageType, damage, damage); DmgFactors *df = PClass::FindActor(ArmorType)->DamageFactors; if (df != NULL) { diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index 2ab8ca51a..51aedd809 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -829,77 +829,6 @@ bool APowerInvisibility::HandlePickup (AInventory *item) 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; - } -} - -//=========================================================================== -// -// APowerIronFeet :: DoEffect -// -//=========================================================================== - -void APowerIronFeet::DoEffect () -{ - if (Owner->player != NULL) - { - Owner->player->mo->ResetAirSupply (); - } -} - - -// Strife Environment Suit Powerup ------------------------------------------- - -IMPLEMENT_CLASS(APowerMask, false, false) - -//=========================================================================== -// -// APowerMask :: AbsorbDamage -// -//=========================================================================== - -void APowerMask::AbsorbDamage (int damage, FName damageType, int &newdamage) -{ - if (damageType == NAME_Fire) - { - newdamage = 0; - } - else - { - Super::AbsorbDamage (damage, damageType, newdamage); - } -} - -//=========================================================================== -// -// APowerMask :: DoEffect -// -//=========================================================================== - -void APowerMask::DoEffect () -{ - Super::DoEffect (); - if (!(level.time & 0x3f)) - { - S_Sound (Owner, CHAN_AUTO, "misc/mask", 1, ATTN_STATIC); - } -} - - // Speed Powerup ------------------------------------------------------------- IMPLEMENT_CLASS(APowerSpeed, false, false) diff --git a/src/g_inventory/a_artifacts.h b/src/g_inventory/a_artifacts.h index d72ed42c3..5149bd2d9 100644 --- a/src/g_inventory/a_artifacts.h +++ b/src/g_inventory/a_artifacts.h @@ -89,22 +89,6 @@ protected: 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 { DECLARE_CLASS (APowerSpeed, APowerup) diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 0909da70f..e5a1178d8 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -394,9 +394,10 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector) // Allow subclasses. Better would be to implement it as armor and let that reduce // the damage as part of the normal damage procedure. Unfortunately, I don't have // different damage types yet, so that's not happening for now. + auto pitype = PClass::FindActor(NAME_PowerIronFeet); for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory) { - if (ironfeet->IsKindOf (RUNTIME_CLASS(APowerIronFeet))) + if (ironfeet->IsKindOf(pitype)) break; } @@ -578,9 +579,10 @@ void P_PlayerOnSpecialFlat (player_t *player, int floorType) if (Terrains[floorType].AllowProtection) { + auto pitype = PClass::FindActor(NAME_PowerIronFeet); for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory) { - if (ironfeet->IsKindOf (RUNTIME_CLASS(APowerIronFeet))) + if (ironfeet->IsKindOf (pitype)) break; } } diff --git a/src/serializer.cpp b/src/serializer.cpp index 5154b0700..6d7a6ef7c 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -495,7 +495,7 @@ void FSerializer::Close() { // we must explicitly delete all thinkers in the array which did not get linked into the thinker lists. // Otherwise these objects may survive a level deletion and point to incorrect data. - for (auto &obj : r->mDObjects) + for (auto obj : r->mDObjects) { auto think = dyn_cast(obj); if (think != nullptr) diff --git a/wadsrc/static/zscript/inventory/powerups.txt b/wadsrc/static/zscript/inventory/powerups.txt index db838b904..8a3e81d2e 100644 --- a/wadsrc/static/zscript/inventory/powerups.txt +++ b/wadsrc/static/zscript/inventory/powerups.txt @@ -84,16 +84,45 @@ class PowerShadow : PowerInvisibility } } -class PowerIronFeet : Powerup native +//=========================================================================== +// +// IronFeet +// +//=========================================================================== + +class PowerIronFeet : Powerup { Default { Powerup.Duration -60; Powerup.Color "00 ff 00", 0.125; } + + override void AbsorbDamage (int damage, Name damageType, out int newdamage) + { + if (damageType == 'Drowning') + { + newdamage = 0; + } + } + + override void DoEffect () + { + if (Owner.player != NULL) + { + Owner.player.mo.ResetAirSupply (); + } + } + } -class PowerMask : PowerIronFeet native +//=========================================================================== +// +// Mask +// +//=========================================================================== + +class PowerMask : PowerIronFeet { Default { @@ -102,6 +131,24 @@ class PowerMask : PowerIronFeet native +INVENTORY.HUBPOWER Inventory.Icon "I_MASK"; } + + override void AbsorbDamage (int damage, Name damageType, out int newdamage) + { + if (damageType == 'Fire' || damageType == 'Drowning') + { + newdamage = 0; + } + } + + override void DoEffect () + { + Super.DoEffect (); + if (!(level.time & 0x3f)) + { + Owner.A_PlaySound ("misc/mask", CHAN_AUTO); + } + } + } //=========================================================================== From a5edd421bd0bb7ecdb7e9a497897e3243b51a5b1 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 16 Jan 2017 13:13:47 -0500 Subject: [PATCH 6/9] - Added Deejay's par times for Thy Flesh Consumed --- wadsrc/static/mapinfo/doom1.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/wadsrc/static/mapinfo/doom1.txt b/wadsrc/static/mapinfo/doom1.txt index 2baba9a5d..f767e1c38 100644 --- a/wadsrc/static/mapinfo/doom1.txt +++ b/wadsrc/static/mapinfo/doom1.txt @@ -404,6 +404,7 @@ map E4M1 lookup "HUSTR_E4M1" secretnext = "E4M9" sky1 = "SKY4" cluster = 4 + par = 165 music = "$MUSIC_E3M4" } @@ -415,6 +416,7 @@ map E4M2 lookup "HUSTR_E4M2" secretnext = "E4M9" sky1 = "SKY4" cluster = 4 + par = 255 music = "$MUSIC_E3M2" } @@ -426,6 +428,7 @@ map E4M3 lookup "HUSTR_E4M3" secretnext = "E4M9" sky1 = "SKY4" cluster = 4 + par = 135 music = "$MUSIC_E3M3" } @@ -437,6 +440,7 @@ map E4M4 lookup "HUSTR_E4M4" secretnext = "E4M9" sky1 = "SKY4" cluster = 4 + par = 150 music = "$MUSIC_E1M5" } @@ -448,6 +452,7 @@ map E4M5 lookup "HUSTR_E4M5" secretnext = "E4M9" sky1 = "SKY4" cluster = 4 + par = 180 music = "$MUSIC_E2M7" } @@ -459,6 +464,7 @@ map E4M6 lookup "HUSTR_E4M6" secretnext = "E4M9" sky1 = "SKY4" cluster = 4 + par = 390 cyberdemonspecial specialaction_opendoor music = "$MUSIC_E2M4" @@ -472,6 +478,7 @@ map E4M7 lookup "HUSTR_E4M7" secretnext = "E4M9" sky1 = "SKY4" cluster = 4 + par = 135 music = "$MUSIC_E2M6" } @@ -483,6 +490,7 @@ map E4M8 lookup "HUSTR_E4M8" secretnext = "E4M9" sky1 = "SKY4" cluster = 4 + par = 360 nointermission nosoundclipping spidermastermindspecial @@ -498,6 +506,7 @@ map E4M9 lookup "HUSTR_E4M9" secretnext = "E4M3" sky1 = "SKY4" cluster = 4 + par = 180 music = "$MUSIC_E1M9" } From d3ab691afbe5723b5756cd40b5c97d6291b78ea0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 16 Jan 2017 20:33:41 +0100 Subject: [PATCH 7/9] - scriptified APowerInvisibility. - changed AlterWeaponSprite so that it doesn't expose renderer internals to the script code. --- src/actor.h | 3 +- src/g_inventory/a_artifacts.cpp | 224 ------------------ src/g_inventory/a_artifacts.h | 12 - src/g_inventory/a_pickups.cpp | 18 -- src/g_inventory/a_pickups.h | 1 - src/gl/scene/gl_weapon.cpp | 46 ++-- src/p_mobj.cpp | 19 ++ src/r_defs.h | 4 +- src/r_things.cpp | 130 +++++----- src/r_things.h | 2 + wadsrc/static/zscript/inventory/inventory.txt | 8 + wadsrc/static/zscript/inventory/powerups.txt | 221 ++++++++++++++++- 12 files changed, 339 insertions(+), 349 deletions(-) diff --git a/src/actor.h b/src/actor.h index 09c1b9918..e1cc56290 100644 --- a/src/actor.h +++ b/src/actor.h @@ -46,7 +46,7 @@ struct subsector_t; struct FBlockNode; struct FPortalGroupArray; - +struct visstyle_t; // // NOTES: AActor // @@ -617,6 +617,7 @@ public: // Returns true if the missile should be allowed to explode anyway bool AdjustReflectionAngle (AActor *thing, DAngle &angle); int AbsorbDamage(int damage, FName dmgtype); + void AlterWeaponSprite(visstyle_t *vis); // Returns true if this actor is within melee range of its target bool CheckMeleeRange(); diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index 51aedd809..bb6d76fc3 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -540,25 +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(0.25f + (float)Owner->Alpha*0.75f, 1.f); - } - } - return changed; -} - // Strength (aka Berserk) Powerup -------------------------------------------- IMPLEMENT_CLASS(APowerStrength, false, false) @@ -624,211 +605,6 @@ PalEntry APowerStrength::GetBlend () 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(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(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); -} - // Speed Powerup ------------------------------------------------------------- IMPLEMENT_CLASS(APowerSpeed, false, false) diff --git a/src/g_inventory/a_artifacts.h b/src/g_inventory/a_artifacts.h index 5149bd2d9..fb0a29a0f 100644 --- a/src/g_inventory/a_artifacts.h +++ b/src/g_inventory/a_artifacts.h @@ -64,7 +64,6 @@ protected: virtual void InitEffect () override; virtual void DoEffect () override; virtual void EndEffect () override; - virtual int AlterWeaponSprite (visstyle_t *vis) override; }; class APowerStrength : public APowerup @@ -78,17 +77,6 @@ protected: 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 APowerSpeed : public APowerup { DECLARE_CLASS (APowerSpeed, APowerup) diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 4a7783ae4..13842d359 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -783,24 +783,6 @@ bool AInventory::GetNoTeleportFreeze () return false; } -//=========================================================================== -// -// AInventory :: AlterWeaponSprite -// -// Allows inventory items to alter a player's weapon sprite just before it -// is drawn. -// -//=========================================================================== - -int AInventory::AlterWeaponSprite (visstyle_t *vis) -{ - if (Inventory != NULL) - { - return Inventory->AlterWeaponSprite (vis); - } - return 0; -} - //=========================================================================== // // AInventory :: Use diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 9cd49bbaf..9f85e482b 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -133,7 +133,6 @@ public: // visual stuff is for later. Right now the VM has not yet access to the needed functionality. virtual bool DrawPowerup(int x, int y); - virtual int AlterWeaponSprite(visstyle_t *vis); // virtual on the script side only. diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index 953509495..d53e252e3 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -310,21 +310,21 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) visstyle_t vis; - vis.RenderStyle=playermo->RenderStyle; - vis.Alpha=playermo->Alpha; - vis.colormap = NULL; - if (playermo->Inventory) + vis.RenderStyle = STYLE_Count; + vis.Alpha = playermo->Alpha; + vis.Invert = false; + playermo->AlterWeaponSprite(&vis); + + FRenderStyle RenderStyle; + if (vis.RenderStyle == STYLE_Count) RenderStyle = playermo->RenderStyle; + else RenderStyle = vis.RenderStyle; + + if (vis.Invert) { - playermo->Inventory->AlterWeaponSprite(&vis); - if (vis.colormap >= SpecialColormaps[0].Colormap && - vis.colormap < SpecialColormaps[SpecialColormaps.Size()].Colormap && - gl_fixedcolormap == CM_DEFAULT) - { - // this only happens for Strife's inverted weapon sprite - vis.RenderStyle.Flags |= STYLEF_InvertSource; - } + // this only happens for Strife's inverted weapon sprite + RenderStyle.Flags |= STYLEF_InvertSource; } - if (vis.RenderStyle.AsDWORD == 0) + if (RenderStyle.AsDWORD == 0) { // This is RenderStyle None. return; @@ -334,32 +334,32 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) int OverrideShader = -1; float trans = 0.f; - if (vis.RenderStyle.BlendOp >= STYLEOP_Fuzz && vis.RenderStyle.BlendOp <= STYLEOP_FuzzOrRevSub) + if (RenderStyle.BlendOp >= STYLEOP_Fuzz && RenderStyle.BlendOp <= STYLEOP_FuzzOrRevSub) { - vis.RenderStyle.CheckFuzz(); - if (vis.RenderStyle.BlendOp == STYLEOP_Fuzz) + RenderStyle.CheckFuzz(); + if (RenderStyle.BlendOp == STYLEOP_Fuzz) { if (gl_fuzztype != 0) { // Todo: implement shader selection here - vis.RenderStyle = LegacyRenderStyles[STYLE_Translucent]; + RenderStyle = LegacyRenderStyles[STYLE_Translucent]; OverrideShader = gl_fuzztype + 4; trans = 0.99f; // trans may not be 1 here } else { - vis.RenderStyle.BlendOp = STYLEOP_Shadow; + RenderStyle.BlendOp = STYLEOP_Shadow; } } } - gl_SetRenderStyle(vis.RenderStyle, false, false); + gl_SetRenderStyle(RenderStyle, false, false); - if (vis.RenderStyle.Flags & STYLEF_TransSoulsAlpha) + if (RenderStyle.Flags & STYLEF_TransSoulsAlpha) { trans = transsouls; } - else if (vis.RenderStyle.Flags & STYLEF_Alpha1) + else if (RenderStyle.Flags & STYLEF_Alpha1) { trans = 1.f; } @@ -402,7 +402,7 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) ll = 255; } // set the lighting parameters - if (vis.RenderStyle.BlendOp == STYLEOP_Shadow) + if (RenderStyle.BlendOp == STYLEOP_Shadow) { gl_RenderState.SetColor(0.2f, 0.2f, 0.2f, 0.33f, cmc.desaturation); } @@ -438,7 +438,7 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) } - DrawPSprite(player, psp, sx, sy, hudModelStep, OverrideShader, !!(vis.RenderStyle.Flags & STYLEF_RedIsAlpha)); + DrawPSprite(player, psp, sx, sy, hudModelStep, OverrideShader, !!(RenderStyle.Flags & STYLEF_RedIsAlpha)); } } gl_RenderState.SetObjectColor(0xffffffff); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 5d86e78ff..9c18ea638 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3629,6 +3629,25 @@ int AActor::AbsorbDamage(int damage, FName dmgtype) return damage; } +void AActor::AlterWeaponSprite(visstyle_t *vis) +{ + int changed = 0; + TArray items; + // This needs to go backwards through the items but the list has no backlinks. + for (AInventory *item = Inventory; item != nullptr; item = item->Inventory) + { + items.Push(item); + } + for(int i=items.Size()-1;i>=0;i--) + { + IFVIRTUALPTR(items[i], AInventory, AlterWeaponSprite) + { + VMValue params[3] = { items[i], vis, &changed }; + GlobalVMStack.Call(func, params, 3, nullptr, 0, nullptr); + } + } +} + void AActor::PlayActiveSound () { if (ActiveSound && !S_IsActorPlayingSomething (this, CHAN_VOICE, -1)) diff --git a/src/r_defs.h b/src/r_defs.h index 9551778b0..a6e8358ee 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -1489,9 +1489,9 @@ typedef BYTE lighttable_t; // This could be wider for >8 bit display. // This encapsulates the fields of vissprite_t that can be altered by AlterWeaponSprite struct visstyle_t { - lighttable_t *colormap; + bool Invert; float Alpha; - FRenderStyle RenderStyle; + ERenderStyle RenderStyle; }; diff --git a/src/r_things.cpp b/src/r_things.cpp index 62b424327..3ddd3110a 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -406,11 +406,11 @@ void R_DrawVisSprite (vissprite_t *vis) } fixed_t centeryfrac = FLOAT2FIXED(CenterY); - R_SetColorMapLight(vis->Style.colormap, 0.0f, 0); + R_SetColorMapLight(vis->colormap, 0.0f, 0); - mode = R_SetPatchStyle (vis->Style.RenderStyle, vis->Style.Alpha, vis->Translation, vis->FillColor); + mode = R_SetPatchStyle (vis->RenderStyle, vis->Style.Alpha, vis->Translation, vis->FillColor); - if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Shaded]) + if (vis->RenderStyle == LegacyRenderStyles[STYLE_Shaded]) { // For shaded sprites, R_SetPatchStyle sets a dc_colormap to an alpha table, but // it is the brightest one. We need to get back to the proper light level for // this sprite. @@ -521,7 +521,7 @@ void R_DrawWallSprite(vissprite_t *spr) bool rereadcolormap = true; // Decals that are added to the scene must fade to black. - if (spr->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0) + if (spr->RenderStyle == LegacyRenderStyles[STYLE_Add] && usecolormap->Fade != 0) { usecolormap = GetSpecialLights(usecolormap->Color, 0, usecolormap->Desaturate); rereadcolormap = false; @@ -559,7 +559,7 @@ void R_DrawWallSprite(vissprite_t *spr) dc_x = x1; ESPSResult mode; - mode = R_SetPatchStyle (spr->Style.RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor); + mode = R_SetPatchStyle (spr->RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor); // R_SetPatchStyle can modify basecolormap. if (rereadcolormap) @@ -646,8 +646,8 @@ void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop int flags = 0; // Do setup for blending. - R_SetColorMapLight(spr->Style.colormap, 0.0f, 0); - mode = R_SetPatchStyle(spr->Style.RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor); + R_SetColorMapLight(spr->colormap, 0.0f, 0); + mode = R_SetPatchStyle(spr->RenderStyle, spr->Style.Alpha, spr->Translation, spr->FillColor); if (mode == DontDraw) { @@ -672,7 +672,7 @@ void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop // Render the voxel, either directly to the screen or offscreen. R_DrawVoxel(spr->pa.vpos, spr->pa.vang, spr->gpos, spr->Angle, - spr->xscale, FLOAT2FIXED(spr->yscale), spr->voxel, spr->Style.colormap, cliptop, clipbot, + spr->xscale, FLOAT2FIXED(spr->yscale), spr->voxel, spr->colormap, cliptop, clipbot, minslabz, maxslabz, flags); // Blend the voxel, if that's what we need to do. @@ -1051,7 +1051,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor vis->renderflags = renderflags; if(thing->flags5 & MF5_BRIGHT) vis->renderflags |= RF_FULLBRIGHT; // kg3D - vis->Style.RenderStyle = thing->RenderStyle; + vis->RenderStyle = thing->RenderStyle; vis->FillColor = thing->fillcolor; vis->Translation = thing->Translation; // [RH] thing translation table vis->FakeFlatStat = fakeside; @@ -1079,9 +1079,9 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor // The software renderer cannot invert the source without inverting the overlay // too. That means if the source is inverted, we need to do the reverse of what // the invert overlay flag says to do. - INTBOOL invertcolormap = (vis->Style.RenderStyle.Flags & STYLEF_InvertOverlay); + INTBOOL invertcolormap = (vis->RenderStyle.Flags & STYLEF_InvertOverlay); - if (vis->Style.RenderStyle.Flags & STYLEF_InvertSource) + if (vis->RenderStyle.Flags & STYLEF_InvertSource) { invertcolormap = !invertcolormap; } @@ -1093,12 +1093,12 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor } // Sprites that are added to the scene must fade to black. - if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] && mybasecolormap->Fade != 0) + if (vis->RenderStyle == LegacyRenderStyles[STYLE_Add] && mybasecolormap->Fade != 0) { mybasecolormap = GetSpecialLights(mybasecolormap->Color, 0, mybasecolormap->Desaturate); } - if (vis->Style.RenderStyle.Flags & STYLEF_FadeToBlack) + if (vis->RenderStyle.Flags & STYLEF_FadeToBlack) { if (invertcolormap) { // Fade to white @@ -1114,7 +1114,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor // get light level if (fixedcolormap != NULL) { // fixed map - vis->Style.colormap = fixedcolormap; + vis->colormap = fixedcolormap; } else { @@ -1124,17 +1124,17 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor } if (fixedlightlev >= 0) { - vis->Style.colormap = mybasecolormap->Maps + fixedlightlev; + vis->colormap = mybasecolormap->Maps + fixedlightlev; } else if (!foggy && ((renderflags & RF_FULLBRIGHT) || (thing->flags5 & MF5_BRIGHT))) { // full bright - vis->Style.colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps; + vis->colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps; } else { // diminished light vis->ColormapNum = GETPALOOKUP( r_SpriteVisibility / MAX(tz, MINZ), spriteshade); - vis->Style.colormap = mybasecolormap->Maps + (vis->ColormapNum << COLORMAPSHIFT); + vis->colormap = mybasecolormap->Maps + (vis->ColormapNum << COLORMAPSHIFT); } } } @@ -1196,7 +1196,7 @@ static void R_ProjectWallSprite(AActor *thing, const DVector3 &pos, FTextureID p vis->deltay = float(pos.Y - ViewPos.Y); vis->renderflags = renderflags; if(thing->flags5 & MF5_BRIGHT) vis->renderflags |= RF_FULLBRIGHT; // kg3D - vis->Style.RenderStyle = thing->RenderStyle; + vis->RenderStyle = thing->RenderStyle; vis->FillColor = thing->fillcolor; vis->Translation = thing->Translation; vis->FakeFlatStat = 0; @@ -1210,7 +1210,7 @@ static void R_ProjectWallSprite(AActor *thing, const DVector3 &pos, FTextureID p vis->bWallSprite = true; vis->ColormapNum = GETPALOOKUP( r_SpriteVisibility / MAX(tz, MINZ), spriteshade); - vis->Style.colormap = basecolormap->Maps + (vis->ColormapNum << COLORMAPSHIFT); + vis->colormap = basecolormap->Maps + (vis->ColormapNum << COLORMAPSHIFT); vis->wallc = wallc; } @@ -1414,21 +1414,21 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double if (pspr->GetID() < PSP_TARGETCENTER) { vis->Style.Alpha = float(owner->Alpha); - vis->Style.RenderStyle = owner->RenderStyle; + vis->RenderStyle = owner->RenderStyle; // The software renderer cannot invert the source without inverting the overlay // too. That means if the source is inverted, we need to do the reverse of what // the invert overlay flag says to do. - INTBOOL invertcolormap = (vis->Style.RenderStyle.Flags & STYLEF_InvertOverlay); + INTBOOL invertcolormap = (vis->RenderStyle.Flags & STYLEF_InvertOverlay); - if (vis->Style.RenderStyle.Flags & STYLEF_InvertSource) + if (vis->RenderStyle.Flags & STYLEF_InvertSource) { invertcolormap = !invertcolormap; } FDynamicColormap *mybasecolormap = basecolormap; - if (vis->Style.RenderStyle.Flags & STYLEF_FadeToBlack) + if (vis->RenderStyle.Flags & STYLEF_FadeToBlack) { if (invertcolormap) { // Fade to white @@ -1443,7 +1443,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double if (realfixedcolormap != nullptr) { // fixed color - vis->Style.colormap = realfixedcolormap->Colormap; + vis->colormap = realfixedcolormap->Colormap; } else { @@ -1453,44 +1453,40 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double } if (fixedlightlev >= 0) { - vis->Style.colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (mybasecolormap->Maps + fixedlightlev); + vis->colormap = (r_fullbrightignoresectorcolor) ? (FullNormalLight.Maps + fixedlightlev) : (mybasecolormap->Maps + fixedlightlev); } else if (!foggy && pspr->GetState()->GetFullbright()) { // full bright - vis->Style.colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps; // [RH] use basecolormap + vis->colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps; // [RH] use basecolormap } else { // local light - vis->Style.colormap = mybasecolormap->Maps + (GETPALOOKUP(0, spriteshade) << COLORMAPSHIFT); + vis->colormap = mybasecolormap->Maps + (GETPALOOKUP(0, spriteshade) << COLORMAPSHIFT); } } if (camera->Inventory != nullptr) { - lighttable_t *oldcolormap = vis->Style.colormap; - camera->Inventory->AlterWeaponSprite(&vis->Style); - if (vis->Style.colormap != oldcolormap) + vis->Style.RenderStyle = STYLE_Count; + vis->Style.Invert = false; + camera->AlterWeaponSprite(&vis->Style); + if (vis->Style.Invert) { - // The colormap has changed. Is it one we can easily identify? - // If not, then don't bother trying to identify it for - // hardware accelerated drawing. - if (vis->Style.colormap < SpecialColormaps[0].Colormap || - vis->Style.colormap > SpecialColormaps.Last().Colormap) - { - noaccel = true; - } + vis->colormap = SpecialColormaps[0].Colormap; + // Has the basecolormap changed? If so, we can't hardware accelerate it, // since we don't know what it is anymore. - else if (vis->Style.colormap < mybasecolormap->Maps || - vis->Style.colormap >= mybasecolormap->Maps + NUMCOLORMAPS * 256) + if (vis->colormap < mybasecolormap->Maps || + vis->colormap >= mybasecolormap->Maps + NUMCOLORMAPS * 256) { noaccel = true; } } + if (vis->Style.RenderStyle != STYLE_Count) vis->RenderStyle = vis->Style.RenderStyle; } // If we're drawing with a special colormap, but shaders for them are disabled, do // not accelerate. - if (!r_shadercolormaps && (vis->Style.colormap >= SpecialColormaps[0].Colormap && - vis->Style.colormap <= SpecialColormaps.Last().Colormap)) + if (!r_shadercolormaps && (vis->colormap >= SpecialColormaps[0].Colormap && + vis->colormap <= SpecialColormaps.Last().Colormap)) { noaccel = true; } @@ -1517,15 +1513,15 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double else { colormap_to_use = basecolormap; - vis->Style.colormap = basecolormap->Maps; - vis->Style.RenderStyle = STYLE_Normal; + vis->colormap = basecolormap->Maps; + vis->RenderStyle = STYLE_Normal; } // Check for hardware-assisted 2D. If it's available, and this sprite is not // fuzzy, don't draw it until after the switch to 2D mode. if (!noaccel && RenderTarget == screen && (DFrameBuffer *)screen->Accel2D) { - FRenderStyle style = vis->Style.RenderStyle; + FRenderStyle style = vis->RenderStyle; style.CheckFuzz(); if (style.BlendOp != STYLEOP_Fuzz) { @@ -1688,18 +1684,18 @@ void R_DrawRemainingPlayerSprites() FColormapStyle colormapstyle; bool usecolormapstyle = false; - if (vis->Style.colormap >= SpecialColormaps[0].Colormap && - vis->Style.colormap < SpecialColormaps[SpecialColormaps.Size()].Colormap) + if (vis->colormap >= SpecialColormaps[0].Colormap && + vis->colormap < SpecialColormaps[SpecialColormaps.Size()].Colormap) { // Yuck! There needs to be a better way to store colormaps in the vissprite... :( - ptrdiff_t specialmap = (vis->Style.colormap - SpecialColormaps[0].Colormap) / sizeof(FSpecialColormap); + ptrdiff_t specialmap = (vis->colormap - SpecialColormaps[0].Colormap) / sizeof(FSpecialColormap); special = &SpecialColormaps[specialmap]; } else if (colormap->Color == PalEntry(255,255,255) && colormap->Desaturate == 0) { overlay = colormap->Fade; - overlay.a = BYTE(((vis->Style.colormap - colormap->Maps) >> 8) * 255 / NUMCOLORMAPS); + overlay.a = BYTE(((vis->colormap - colormap->Maps) >> 8) * 255 / NUMCOLORMAPS); } else { @@ -1707,7 +1703,7 @@ void R_DrawRemainingPlayerSprites() colormapstyle.Color = colormap->Color; colormapstyle.Fade = colormap->Fade; colormapstyle.Desaturate = colormap->Desaturate; - colormapstyle.FadeLevel = ((vis->Style.colormap - colormap->Maps) >> 8) / float(NUMCOLORMAPS); + colormapstyle.FadeLevel = ((vis->colormap - colormap->Maps) >> 8) / float(NUMCOLORMAPS); } screen->DrawTexture(vis->pic, viewwindowx + vispsprites[i].x1, @@ -1723,7 +1719,7 @@ void R_DrawRemainingPlayerSprites() DTA_ClipRight, viewwindowx + viewwidth, DTA_ClipBottom, viewwindowy + viewheight, DTA_AlphaF, vis->Style.Alpha, - DTA_RenderStyle, vis->Style.RenderStyle, + DTA_RenderStyle, vis->RenderStyle, DTA_FillColor, vis->FillColor, DTA_SpecialColormap, special, DTA_ColorOverlay, overlay.d, @@ -1950,7 +1946,7 @@ void R_DrawSprite (vissprite_t *spr) int r1, r2; short topclip, botclip; short *clip1, *clip2; - lighttable_t *colormap = spr->Style.colormap; + lighttable_t *colormap = spr->colormap; F3DFloor *rover; FDynamicColormap *mybasecolormap; @@ -2014,20 +2010,20 @@ void R_DrawSprite (vissprite_t *spr) // found new values, recalculate if (sec) { - INTBOOL invertcolormap = (spr->Style.RenderStyle.Flags & STYLEF_InvertOverlay); + INTBOOL invertcolormap = (spr->RenderStyle.Flags & STYLEF_InvertOverlay); - if (spr->Style.RenderStyle.Flags & STYLEF_InvertSource) + if (spr->RenderStyle.Flags & STYLEF_InvertSource) { invertcolormap = !invertcolormap; } // Sprites that are added to the scene must fade to black. - if (spr->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] && mybasecolormap->Fade != 0) + if (spr->RenderStyle == LegacyRenderStyles[STYLE_Add] && mybasecolormap->Fade != 0) { mybasecolormap = GetSpecialLights(mybasecolormap->Color, 0, mybasecolormap->Desaturate); } - if (spr->Style.RenderStyle.Flags & STYLEF_FadeToBlack) + if (spr->RenderStyle.Flags & STYLEF_FadeToBlack) { if (invertcolormap) { // Fade to white @@ -2047,16 +2043,16 @@ void R_DrawSprite (vissprite_t *spr) } if (fixedlightlev >= 0) { - spr->Style.colormap = mybasecolormap->Maps + fixedlightlev; + spr->colormap = mybasecolormap->Maps + fixedlightlev; } else if (!foggy && (spr->renderflags & RF_FULLBRIGHT)) { // full bright - spr->Style.colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps; + spr->colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : mybasecolormap->Maps; } else { // diminished light spriteshade = LIGHT2SHADE(sec->lightlevel + r_actualextralight); - spr->Style.colormap = mybasecolormap->Maps + (GETPALOOKUP( + spr->colormap = mybasecolormap->Maps + (GETPALOOKUP( r_SpriteVisibility / MAX(MINZ, (double)spr->depth), spriteshade) << COLORMAPSHIFT); } } @@ -2205,7 +2201,7 @@ void R_DrawSprite (vissprite_t *spr) if (topclip >= botclip) { - spr->Style.colormap = colormap; + spr->colormap = colormap; return; } @@ -2335,7 +2331,7 @@ void R_DrawSprite (vissprite_t *spr) } if (i == x2) { - spr->Style.colormap = colormap; + spr->colormap = colormap; return; } } @@ -2353,7 +2349,7 @@ void R_DrawSprite (vissprite_t *spr) int maxvoxely = spr->gzb > hzb ? INT_MAX : xs_RoundToInt((spr->gzt - hzb) / spr->yscale); R_DrawVisVoxel(spr, minvoxely, maxvoxely, cliptop, clipbot); } - spr->Style.colormap = colormap; + spr->colormap = colormap; } // kg3D: @@ -2601,21 +2597,21 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade, if (fixedlightlev >= 0) { - vis->Style.colormap = map + fixedlightlev; + vis->colormap = map + fixedlightlev; } else if (fixedcolormap) { - vis->Style.colormap = fixedcolormap; + vis->colormap = fixedcolormap; } else if (particle->bright) { - vis->Style.colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : map; + vis->colormap = (r_fullbrightignoresectorcolor) ? FullNormalLight.Maps : map; } else { // Particles are slightly more visible than regular sprites. vis->ColormapNum = GETPALOOKUP(tiz * r_SpriteVisibility * 0.5, shade); - vis->Style.colormap = map + (vis->ColormapNum << COLORMAPSHIFT); + vis->colormap = map + (vis->ColormapNum << COLORMAPSHIFT); } } @@ -2650,7 +2646,7 @@ void R_DrawParticle_C (vissprite_t *vis) int spacing; BYTE *dest; DWORD fg; - BYTE color = vis->Style.colormap[vis->startfrac]; + BYTE color = vis->colormap[vis->startfrac]; int yl = vis->y1; int ycount = vis->y2 - yl + 1; int x1 = vis->x1; diff --git a/src/r_things.h b/src/r_things.h index 6d694b8fd..07676dc44 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -95,6 +95,8 @@ struct vissprite_t BYTE ColormapNum; // Which colormap is rendered (needed for shaded drawer) short renderflags; DWORD Translation; // [RH] for color translation + lighttable_t *colormap; + FRenderStyle RenderStyle; visstyle_t Style; int CurrentPortalUniq; // [ZZ] to identify the portal that this thing is in. used for clipping. diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index 7db3ba212..90ed458d0 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -1,3 +1,10 @@ +struct VisStyle +{ + bool Invert; + float Alpha; + int RenderStyle; +} + class Inventory : Actor native { const BLINKTHRESHOLD = (4*32); @@ -56,6 +63,7 @@ class Inventory : Actor native virtual double GetSpeedFactor() { return 1; } virtual bool GetNoTeleportFreeze() { return false; } virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {} + virtual void AlterWeaponSprite(VisStyle vis, in out int changed) {} native bool GoAway(); native void GoAwayAndDie(); diff --git a/wadsrc/static/zscript/inventory/powerups.txt b/wadsrc/static/zscript/inventory/powerups.txt index 8a3e81d2e..f31c88f77 100644 --- a/wadsrc/static/zscript/inventory/powerups.txt +++ b/wadsrc/static/zscript/inventory/powerups.txt @@ -32,6 +32,12 @@ class Powerup : Inventory native } +//=========================================================================== +// +// Invulnerable +// +//=========================================================================== + class PowerInvulnerable : Powerup native { Default @@ -39,6 +45,17 @@ class PowerInvulnerable : Powerup native Powerup.Duration -30; inventory.icon "SPSHLD0"; } + + override void AlterWeaponSprite (VisStyle vis, in out int changed) + { + if (Owner != NULL) + { + if (Mode == 'Ghost' && !(Owner.bShadow)) + { + vis.Alpha = min(0.25 + Owner.Alpha * 0.75, 1.); + } + } + } } class PowerStrength : Powerup native @@ -51,7 +68,13 @@ class PowerStrength : Powerup native } } -class PowerInvisibility : Powerup native +//=========================================================================== +// +// Invisibility +// +//=========================================================================== + +class PowerInvisibility : Powerup { Default { @@ -60,6 +83,202 @@ class PowerInvisibility : Powerup native Powerup.Strength 80; Powerup.Mode "Fuzzy"; } + + //=========================================================================== + // + // APowerInvisibility :: InitEffect + // + //=========================================================================== + + override void InitEffect () + { + Super.InitEffect(); + + let Owner = self.Owner; + if (Owner != NULL) + { + let savedShadow = Owner.bShadow; + let savedGhost = Owner.bGhost; + let savedCantSeek = Owner.bCantSeek; + Owner.bShadow = bShadow; + Owner.bGhost = bGhost; + Owner.bCantSeek = bCantSeek; + bShadow = savedShadow; + bGhost = savedGhost; + bCantSeek = savedCantSeek; + DoEffect(); + } + } + + //=========================================================================== + // + // APowerInvisibility :: DoEffect + // + //=========================================================================== + + override void DoEffect () + { + Super.DoEffect(); + // Due to potential interference with other PowerInvisibility items + // the effect has to be refreshed each tic. + double ts = (Strength / 100) * (special1 + 1); + + if (ts > 1.) ts = 1.; + let newAlpha = clamp((1. - ts), 0., 1.); + int newStyle; + switch (Mode) + { + case 'Fuzzy': + newStyle = STYLE_OptFuzzy; + break; + case 'Opaque': + newStyle = STYLE_Normal; + break; + case 'Additive': + newStyle = STYLE_Add; + break; + case 'Stencil': + newStyle = STYLE_Stencil; + break; + case 'AddStencil' : + newStyle = STYLE_AddStencil; + break; + case 'TranslucentStencil': + newStyle = STYLE_TranslucentStencil; + break; + case 'None' : + case 'Cumulative': + case 'Translucent': + newStyle = STYLE_Translucent; + break; + default: // Something's wrong + newStyle = STYLE_Normal; + newAlpha = 1.; + break; + } + Owner.A_SetRenderStyle(newAlpha, newStyle); + } + + //=========================================================================== + // + // APowerInvisibility :: EndEffect + // + //=========================================================================== + + override void EndEffect () + { + Super.EndEffect(); + if (Owner != NULL) + { + Owner.bShadow = bShadow; + Owner.bGhost = bGhost; + Owner.bCantSeek = bCantSeek; + + Owner.A_SetRenderStyle(1, STYLE_Normal); + + // Check whether there are other invisibility items and refresh their effect. + // If this isn't done there will be one incorrectly drawn frame when this + // item expires. + for(let item = Owner.Inv; item != null; item = item.Inv) + { + if (item != self && item is 'PowerInvisibility') + { + item.DoEffect(); + } + } + } + } + + //=========================================================================== + // + // APowerInvisibility :: AlterWeaponSprite + // + //=========================================================================== + + override void AlterWeaponSprite (VisStyle vis, in out int changed) + { + // Blink if the powerup is wearing off + if (changed == 0 && EffectTics < 4*32 && !(EffectTics & 8)) + { + vis.RenderStyle = STYLE_Normal; + vis.Alpha = 1.f; + changed = 1; + return; + } + else if (changed == 1) + { + // something else set the weapon sprite back to opaque but this item is still active. + float ts = float((Strength / 100) * (special1 + 1)); + vis.Alpha = clamp((1. - ts), 0., 1.); + switch (Mode) + { + case 'Fuzzy': + vis.RenderStyle = STYLE_OptFuzzy; + break; + case 'Opaque': + vis.RenderStyle = STYLE_Normal; + break; + case 'Additive': + vis.RenderStyle = STYLE_Add; + break; + case 'Stencil': + vis.RenderStyle = STYLE_Stencil; + break; + case 'TranslucentStencil': + vis.RenderStyle = STYLE_TranslucentStencil; + break; + case 'AddStencil': + vis.RenderStyle = STYLE_AddStencil; + break; + case 'None': + case 'Cumulative': + case 'Translucent': + default: + vis.RenderStyle = STYLE_Translucent; + break; + } + } + // Handling of Strife-like cumulative invisibility powerups, the weapon itself shouldn't become invisible + if ((vis.Alpha < 0.25f && special1 > 0) || (vis.Alpha == 0)) + { + vis.Alpha = clamp((1. - Strength/100.), 0., 1.); + vis.invert = true; + } + changed = -1; // This item is valid so another one shouldn't reset the translucency + } + + //=========================================================================== + // + // APowerInvisibility :: HandlePickup + // + // If the player already has the first stage of a cumulative powerup, getting + // it again increases the player's alpha. (But shouldn't this be in Use()?) + // + //=========================================================================== + + override bool HandlePickup (Inventory item) + { + if (Mode == 'Cumulative' && ((Strength * special1) < 1.) && item.GetClass() == GetClass()) + { + let power = Powerup(item); + if (power.EffectTics == 0) + { + power.bPickupGood = true; + return true; + } + // Only increase the EffectTics, not decrease it. + // Color also gets transferred only when the new item has an effect. + if (power.EffectTics > EffectTics) + { + EffectTics = power.EffectTics; + BlendColor = power.BlendColor; + } + special1++; // increases power + power.bPickupGood = true; + return true; + } + return Super.HandlePickup (item); + } } class PowerGhost : PowerInvisibility From c5f100a61d44631950054b06b9802caba9924262 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 16 Jan 2017 20:44:52 +0100 Subject: [PATCH 8/9] - fixed class name checks for custom properties. --- src/scripting/decorate/thingdef_parse.cpp | 9 +++++++-- src/scripting/zscript/zcc_compile.cpp | 13 +++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 2eee0f01d..c839a2dc0 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -862,11 +862,16 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul sc.MustGetString(); auto cls = PClass::FindClass(sc.String); *(PClass**)addr = cls; - if (!cls->IsDescendantOf(static_cast(f->Type)->ClassRestriction)) + if (cls == nullptr) { - sc.ScriptMessage("class %s is not compatible with property type %s", cls->TypeName.GetChars(), static_cast(f->Type)->ClassRestriction->TypeName.GetChars()); + cls = static_cast(f->Type)->ClassRestriction->FindClassTentative(sc.String); + } + else if (!cls->IsDescendantOf(static_cast(f->Type)->ClassRestriction)) + { + sc.ScriptMessage("class %s is not compatible with property type %s", sc.String, static_cast(f->Type)->ClassRestriction->TypeName.GetChars()); FScriptPosition::ErrorCounter++; } + *(PClass**)addr = cls; } else { diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 281f707d2..1687983f2 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1960,12 +1960,17 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop } else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer))) { - auto cls = PClass::FindClass(GetString(exp)); - *(PClass**)addr = cls; - if (!cls->IsDescendantOf(static_cast(f->Type)->ClassRestriction)) + auto clsname = GetString(exp); + auto cls = PClass::FindClass(clsname); + if (cls == nullptr) { - Error(property, "class %s is not compatible with property type %s", cls->TypeName.GetChars(), static_cast(f->Type)->ClassRestriction->TypeName.GetChars()); + cls = static_cast(f->Type)->ClassRestriction->FindClassTentative(clsname); } + else if (!cls->IsDescendantOf(static_cast(f->Type)->ClassRestriction)) + { + Error(property, "class %s is not compatible with property type %s", clsname, static_cast(f->Type)->ClassRestriction->TypeName.GetChars()); + } + *(PClass**)addr = cls; } else { From 6990a46dafde9feb76e231cf14c3e4af5ad9839a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 16 Jan 2017 22:27:49 +0100 Subject: [PATCH 9/9] - scriptified PowerStrength. This revealed an interesting bug: When the berserk fadout formula was changed in 2005 the result was essentially broken, resulting in values around 7000 - it only worked by happenstance because the lower 8 bits of the resulting values just happened to work to some degree and never overflowed. But the resulting fade was far too weak and a slightly different handling of the color composition code for the VM made it break down entirely. This restores the pre-2005 formula but weakened intensity which now comes a lot closer to how it is supposed to look. --- src/g_inventory/a_artifacts.cpp | 65 -------------------- src/g_inventory/a_artifacts.h | 11 ---- src/g_shared/shared_hud.cpp | 4 +- src/s_advsound.cpp | 1 + src/scripting/codegeneration/codegen.cpp | 3 +- wadsrc/static/zscript/inventory/powerups.txt | 51 ++++++++++++++- 6 files changed, 54 insertions(+), 81 deletions(-) diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index bb6d76fc3..0cd4828b1 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -540,71 +540,6 @@ void APowerInvulnerable::EndEffect () } } -// 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; -} - // Speed Powerup ------------------------------------------------------------- IMPLEMENT_CLASS(APowerSpeed, false, false) diff --git a/src/g_inventory/a_artifacts.h b/src/g_inventory/a_artifacts.h index fb0a29a0f..f947e18d5 100644 --- a/src/g_inventory/a_artifacts.h +++ b/src/g_inventory/a_artifacts.h @@ -66,17 +66,6 @@ protected: virtual void EndEffect () 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 APowerSpeed : public APowerup { DECLARE_CLASS (APowerSpeed, APowerup) diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index b645ac511..839582d34 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -297,8 +297,8 @@ static void DrawHealth(player_t *CPlayer, int x, int y) CR_BLUE; const bool haveBerserk = hud_berserk_health - && NULL != berserkpic - && NULL != CPlayer->mo->FindInventory< APowerStrength >(); + && nullptr != berserkpic + && nullptr != CPlayer->mo->FindInventory(PClass::FindActor(NAME_PowerStrength)); DrawImageToBox(haveBerserk ? berserkpic : healthpic, x, y, 31, 17); DrawHudNumber(HudFont, fontcolor, health, x + 33, y + 17); diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index 085f1869e..952a40d09 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -2127,6 +2127,7 @@ CCMD (soundlist) { Printf ("%3d. %s **not present**\n", i, sfx->name.GetChars()); } + Printf(" PitchMask = %d\n", sfx->PitchMask); } } diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 1eefba216..47a10f95d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5921,8 +5921,7 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) { Object->ValueType = TypeColorStruct; } - - else if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) + if (Object->ValueType->IsKindOf(RUNTIME_CLASS(PPointer))) { auto ptype = static_cast(Object->ValueType)->PointedType; if (ptype->IsKindOf(RUNTIME_CLASS(PStruct))) diff --git a/wadsrc/static/zscript/inventory/powerups.txt b/wadsrc/static/zscript/inventory/powerups.txt index f31c88f77..b744bfc97 100644 --- a/wadsrc/static/zscript/inventory/powerups.txt +++ b/wadsrc/static/zscript/inventory/powerups.txt @@ -58,7 +58,13 @@ class PowerInvulnerable : Powerup native } } -class PowerStrength : Powerup native +//=========================================================================== +// +// Strength +// +//=========================================================================== + +class PowerStrength : Powerup { Default { @@ -66,6 +72,49 @@ class PowerStrength : Powerup native Powerup.Color "ff 00 00", 0.5; +INVENTORY.HUBPOWER } + + override bool HandlePickup (Inventory item) + { + if (item.GetClass() == GetClass()) + { // Setting EffectTics to 0 will force Powerup's HandlePickup() + // method to reset the tic count so you get the red flash again. + EffectTics = 0; + } + return Super.HandlePickup (item); + } + + //=========================================================================== + // + // 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; + } + } //===========================================================================