diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index ab50fc982..52fc483dc 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -141,6 +141,13 @@ DPSprite::DPSprite(player_t *owner, AInventory *caller, int id) if (Next && Next->ID == ID && ID != 0) Next->Destroy(); // Replace it. + + if (ID == ps_weapon || ID == ps_flash || (ID >= NUMPSPRITES && Caller->IsKindOf(RUNTIME_CLASS(AWeapon)))) + { + Flags |= PSPF_ADDBOB; + if (ID != ps_weapon) + Flags |= PSPF_ADDWEAPON; + } } //------------------------------------------------------------------------ @@ -176,26 +183,9 @@ DPSprite *player_t::GetPSprite(psprnum_t layer) { assert(layer > 0 && layer < NUMPSPRITES); - DPSprite *weapon = nullptr; - DPSprite *pspr = psprites; - while (pspr) - { - if (pspr->ID == layer) - return pspr; - - if (pspr->ID == ps_weapon) - weapon = pspr; - - pspr = pspr->Next; - } - - pspr = new DPSprite(this, ReadyWeapon, layer); - - if (layer == ps_flash && weapon) - { - pspr->x = weapon->x; - pspr->y = weapon->y; - } + DPSprite *pspr = FindPSprite(layer); + if (pspr == nullptr) + pspr = new DPSprite(this, ReadyWeapon, layer); return pspr; } @@ -281,13 +271,16 @@ void DPSprite::SetState(FState *newstate, bool pending) Tics = 1; // great for producing decals :) } - if (newstate->GetMisc1()) - { // Set coordinates. - x = newstate->GetMisc1(); - } - if (newstate->GetMisc2()) - { - y = newstate->GetMisc2(); + if (ID != ps_flash) + { // It's still possible to set the flash layer's offsets with the action function. + if (newstate->GetMisc1()) + { // Set coordinates. + x = newstate->GetMisc1(); + } + if (newstate->GetMisc2()) + { + y = newstate->GetMisc2(); + } } if (Owner->mo != nullptr) @@ -986,6 +979,35 @@ DEFINE_ACTION_FUNCTION(AInventory, A_WeaponOffset) return 0; } +//--------------------------------------------------------------------------- +// +// PROC A_OverlayFlags +// +//--------------------------------------------------------------------------- + +DEFINE_ACTION_FUNCTION(AInventory, A_OverlayFlags) +{ + PARAM_ACTION_PROLOGUE; + PARAM_INT(layer); + PARAM_INT(flags); + PARAM_BOOL(set); + + if (self->player == nullptr) + return 0; + + DPSprite *pspr = self->player->FindPSprite(layer); + + if (pspr == nullptr) + return 0; + + if (set) + pspr->Flags |= flags; + else + pspr->Flags &= ~flags; + + return 0; +} + //--------------------------------------------------------------------------- // // PROC A_Lower @@ -1307,11 +1329,6 @@ void player_t::TickPSprites() } else { - if (weapon && flash) - { - flash->x = weapon->x; - flash->y = weapon->y; - } P_CheckWeaponSwitch(this); if (WeaponState & (WF_WEAPONREADY | WF_WEAPONREADYALT)) { @@ -1359,7 +1376,7 @@ void DPSprite::Serialize(FArchive &arc) { Super::Serialize(arc); - arc << Next << Caller << Owner + arc << Next << Caller << Owner << Flags << State << Tics << Sprite << Frame << ID << x << y << oldx << oldy; } diff --git a/src/p_pspr.h b/src/p_pspr.h index b9104d4aa..65293a79c 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -52,6 +52,12 @@ enum psprnum_t // These are all called by the owner's ReadyWeapon. NUMPSPRITES }; +enum PSPFlags +{ + PSPF_ADDWEAPON = 1 << 0, + PSPF_ADDBOB = 1 << 1, +}; + class DPSprite : public DObject { DECLARE_CLASS (DPSprite, DObject) @@ -73,6 +79,7 @@ public: double oldx, oldy; bool firstTic; int Tics; + int Flags; private: DPSprite () {} diff --git a/src/p_user.cpp b/src/p_user.cpp index 9a36fdc46..cbdab0730 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3093,11 +3093,28 @@ void player_t::Serialize (FArchive &arc) pspr = GetPSprite(psprnum_t(i)); pspr->State = state; pspr->Tics = tics; - pspr->x = sx; - pspr->y = sy; pspr->Sprite = sprite; pspr->Frame = frame; pspr->Owner = this; + + if (i == ps_flash) + { + pspr->x = 0; + pspr->y = 0; + } + else + { + pspr->x = sx; + pspr->y = sy; + } + + pspr->Flags = 0; + if (i < ps_targetcenter) + { + pspr->Flags |= PSPF_ADDBOB; + if (i == ps_flash) + pspr->Flags |= PSPF_ADDWEAPON; + } } } } diff --git a/src/r_things.cpp b/src/r_things.cpp index 704b6509c..e194dc6d4 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1279,7 +1279,7 @@ void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) // // R_DrawPSprite // -void R_DrawPSprite(DPSprite *pspr, AActor *owner, double ofsx, double ofsy, double ticfrac) +void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double wx, double wy, double ticfrac) { double tx; int x1; @@ -1331,10 +1331,17 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, double ofsx, double ofsy, doub sx = pspr->oldx + (pspr->x - pspr->oldx) * ticfrac; sy = pspr->oldy + (pspr->y - pspr->oldy) * ticfrac; - if (isweapon) - { // [RH] Don't bob the targeter/non-weapon layers. - sx += ofsx; - sy += ofsy; + + if (pspr->Flags & PSPF_ADDBOB) + { + sx += bobx; + sy += boby; + } + + if (pspr->Flags & PSPF_ADDWEAPON) + { + sx += wx; + sy += wy; } // calculate edges of the shape @@ -1547,6 +1554,7 @@ void R_DrawPlayerSprites () int i; int lightnum; DPSprite* psp; + DPSprite* weapon; sector_t* sec = NULL; static sector_t tempsec; int floorlight, ceilinglight; @@ -1611,11 +1619,32 @@ void R_DrawPlayerSprites () if (camera->player != NULL) { double centerhack = CenterY; - float ofsx, ofsy; + double wx, wy; + float bobx, boby; CenterY = viewheight / 2; - P_BobWeapon (camera->player, &ofsx, &ofsy, r_TicFracF); + P_BobWeapon (camera->player, &bobx, &boby, r_TicFracF); + + // Interpolate the main weapon layer once so as to be able to add it to other layers. + if ((weapon = camera->player->FindPSprite(ps_weapon)) != nullptr) + { + if (weapon->firstTic) + { + wx = weapon->x; + wy = weapon->y; + } + else + { + wx = weapon->oldx + (weapon->x - weapon->oldx) * r_TicFracF; + wy = weapon->oldy + (weapon->y - weapon->oldy) * r_TicFracF; + } + } + else + { + wx = 0; + wy = 0; + } // add all active psprites psp = camera->player->psprites; @@ -1624,7 +1653,7 @@ void R_DrawPlayerSprites () // [RH] Don't draw the targeter's crosshair if the player already has a crosshair set. if (psp->GetID() != ps_targetcenter || CrosshairImage == nullptr) { - R_DrawPSprite(psp, camera, ofsx, ofsy, r_TicFracF); + R_DrawPSprite(psp, camera, bobx, boby, wx, wy, r_TicFracF); } psp = psp->GetNext(); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 911e1036b..8e082cc72 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -568,4 +568,11 @@ enum WOF_KEEPX = 1, WOF_KEEPY = 1 << 1, WOF_ADD = 1 << 2, -}; \ No newline at end of file +}; + +// Flags for psprite layers +enum +{ + PSPF_ADDWEAPON = 1 << 0, + PSPF_ADDBOB = 1 << 1, +}; diff --git a/wadsrc/static/actors/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt index 396274332..0dffc106b 100644 --- a/wadsrc/static/actors/shared/inventory.txt +++ b/wadsrc/static/actors/shared/inventory.txt @@ -51,6 +51,7 @@ ACTOR Inventory native action native A_RestoreSpecialThing2(); action native A_WeaponOffset(float wx = 0, float wy = 32, int flags = 0); action native A_OverlayOffset(int layer = 1, float wx = 0, float wy = 32, int flags = 0); + action native A_OverlayFlags(int layer, int flags, bool set); States {