From 1966b61b8fd83621406c62dbc7e42aa80bafec29 Mon Sep 17 00:00:00 2001 From: Leonard2 Date: Mon, 9 May 2016 20:03:47 +0200 Subject: [PATCH] Generalized the psprites implementation --- src/d_player.h | 8 +- src/g_doom/a_doomweaps.cpp | 38 +-- src/g_game.cpp | 2 + src/g_heretic/a_chicken.cpp | 14 +- src/g_heretic/a_hereticweaps.cpp | 24 +- src/g_hexen/a_clericstaff.cpp | 12 +- src/g_hexen/a_fighteraxe.cpp | 32 +- src/g_hexen/a_fighterplayer.cpp | 4 +- src/g_hexen/a_pig.cpp | 4 +- src/g_shared/a_artifacts.cpp | 52 ++-- src/g_shared/a_weapons.cpp | 9 +- src/g_strife/a_strifestuff.cpp | 27 +- src/g_strife/a_strifeweapons.cpp | 46 +-- src/m_cheat.cpp | 12 +- src/p_local.h | 1 - src/p_mobj.cpp | 8 +- src/p_pspr.cpp | 477 ++++++++++++++++++++---------- src/p_pspr.h | 75 +++-- src/p_saveg.cpp | 17 +- src/p_tick.cpp | 2 +- src/p_user.cpp | 69 ++++- src/r_things.cpp | 271 +++++++++-------- src/r_things.h | 1 - src/thingdef/thingdef_codeptr.cpp | 13 +- src/version.h | 2 +- 25 files changed, 743 insertions(+), 477 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 40178dac1..ee9e64f0c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -380,6 +380,7 @@ class player_t { public: player_t(); + ~player_t(); player_t &operator= (const player_t &p); void Serialize (FArchive &arc); @@ -454,7 +455,6 @@ public: int extralight; // so gun flashes light up areas short fixedcolormap; // can be set to REDCOLORMAP, etc. short fixedlightlevel; - pspdef_t psprites[NUMPSPRITES]; // view sprites (gun, etc) int morphTics; // player is a chicken/pig if > 0 PClassPlayerPawn *MorphedPlayerClass; // [MH] (for SBARINFO) class # for this player instance when morphed int MorphStyle; // which effects to apply for this player instance when morphed @@ -526,6 +526,12 @@ public: } int GetSpawnClass(); + + // PSprite layers + DPSprite *psprites; // view sprites (gun, etc) + void TickPSprites(); + void DestroyPSprites(); + DPSprite *GetPSprite(psprnum_t layer); // Used ONLY for compatibility with the old hardcoded layers. }; // Bookkeeping on players - state. diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index 21119f8a0..a96fab8fc 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -73,16 +73,15 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePistol) bool accurate; - if (self->player != NULL) + if (self->player != nullptr) { AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) + if (weapon != nullptr && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return 0; - P_SetPsprite (self->player, ps_flash, weapon->FindState(NAME_Flash)); - self->player->psprites[ps_flash].processPending = true; + self->player->GetPSprite(ps_flash)->SetState(weapon->FindState(NAME_Flash), true); } self->player->mo->PlayAttacking2 (); @@ -263,19 +262,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun) int i; player_t *player; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } S_Sound (self, CHAN_WEAPON, "weapons/shotgf", 1, ATTN_NORM); AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) + if (weapon != nullptr && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return 0; - P_SetPsprite (player, ps_flash, weapon->FindState(NAME_Flash)); - self->player->psprites[ps_flash].processPending = true; + player->GetPSprite(ps_flash)->SetState(weapon->FindState(NAME_Flash), true); } player->mo->PlayAttacking2 (); @@ -300,19 +298,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2) int damage; player_t *player; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } S_Sound (self, CHAN_WEAPON, "weapons/sshotf", 1, ATTN_NORM); AWeapon *weapon = self->player->ReadyWeapon; - if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) + if (weapon != nullptr && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 2)) return 0; - P_SetPsprite (player, ps_flash, weapon->FindState(NAME_Flash)); - self->player->psprites[ps_flash].processPending = true; + player->GetPSprite(ps_flash)->SetState(weapon->FindState(NAME_Flash), true); } player->mo->PlayAttacking2 (); @@ -384,15 +381,13 @@ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int i if (flashstate + index < cls->OwnedStates + cls->NumOwnedStates) { // we're ok so set the state - P_SetPsprite (player, ps_flash, flashstate + index); - player->psprites[ps_flash].processPending = true; + player->GetPSprite(ps_flash)->SetState(flashstate + index, true); return; } else { // oh, no! The state is beyond the end of the state table so use the original flash state. - P_SetPsprite (player, ps_flash, flashstate); - player->psprites[ps_flash].processPending = true; + player->GetPSprite(ps_flash)->SetState(flashstate, true); return; } } @@ -408,8 +403,7 @@ void P_SetSafeFlash(AWeapon *weapon, player_t *player, FState *flashstate, int i { // Invalid state. With no index offset, it should at least be valid. index = 0; } - P_SetPsprite (player, ps_flash, flashstate + index); - player->psprites[ps_flash].processPending = true; + player->GetPSprite(ps_flash)->SetState(flashstate + index, true); } // @@ -421,13 +415,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCGun) player_t *player; - if (self == NULL || NULL == (player = self->player)) + if (self == nullptr || nullptr == (player = self->player)) { return 0; } AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL && ACTION_CALL_FROM_WEAPON()) + if (weapon != nullptr && ACTION_CALL_FROM_WEAPON()) { if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1)) return 0; @@ -435,12 +429,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCGun) S_Sound (self, CHAN_WEAPON, "weapons/chngun", 1, ATTN_NORM); FState *flash = weapon->FindState(NAME_Flash); - if (flash != NULL) + if (flash != nullptr) { // [RH] Fix for Sparky's messed-up Dehacked patch! Blargh! FState * atk = weapon->FindState(NAME_Fire); - int theflash = clamp (int(player->psprites[ps_weapon].state - atk), 0, 1); + int theflash = clamp (int(player->GetPSprite(ps_weapon)->GetState() - atk), 0, 1); if (flash[theflash].sprite != flash->sprite) { diff --git a/src/g_game.cpp b/src/g_game.cpp index 7c31e09c0..3c9d274c8 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1750,6 +1750,8 @@ void G_DoPlayerPop(int playernum) players[playernum].mo = NULL; players[playernum].camera = NULL; } + + players[playernum].DestroyPSprites(); } void G_ScreenShot (char *filename) diff --git a/src/g_heretic/a_chicken.cpp b/src/g_heretic/a_chicken.cpp index 3251e3812..cb8bc7fc9 100644 --- a/src/g_heretic/a_chicken.cpp +++ b/src/g_heretic/a_chicken.cpp @@ -123,9 +123,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Feathers) void P_UpdateBeak (AActor *self) { - if (self->player != NULL) + if (self->player != nullptr) { - self->player->psprites[ps_weapon].sy = WEAPONTOP + self->player->chickenPeck / 2; + self->player->GetPSprite(ps_weapon)->y = WEAPONTOP + self->player->chickenPeck / 2; } } @@ -141,12 +141,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakRaise) player_t *player; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } - player->psprites[ps_weapon].sy = WEAPONTOP; - P_SetPsprite (player, ps_weapon, player->ReadyWeapon->GetReadyState()); + player->GetPSprite(ps_weapon)->y = WEAPONTOP; + player->GetPSprite(ps_weapon)->SetState(player->ReadyWeapon->GetReadyState()); return 0; } @@ -192,7 +192,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1) } P_PlayPeck (player->mo); player->chickenPeck = 12; - player->psprites[ps_weapon].tics -= pr_beakatkpl1() & 7; + player->GetPSprite(ps_weapon)->Tics -= pr_beakatkpl1() & 7; return 0; } @@ -227,6 +227,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL2) } P_PlayPeck (player->mo); player->chickenPeck = 12; - player->psprites[ps_weapon].tics -= pr_beakatkpl2()&3; + player->GetPSprite(ps_weapon)->Tics -= pr_beakatkpl2()&3; return 0; } diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index 504321061..8b5409f5b 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -259,7 +259,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack) FTranslatedLineTarget t; int actualdamage = 0; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } @@ -267,13 +267,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack) PARAM_INT(power); AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) + if (weapon != nullptr) { if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; } - player->psprites[ps_weapon].sx = ((pr_gatk()&3)-2); - player->psprites[ps_weapon].sy = WEAPONTOP + (pr_gatk()&3); + player->GetPSprite(ps_weapon)->x = ((pr_gatk()&3)-2); + player->GetPSprite(ps_weapon)->y = WEAPONTOP + (pr_gatk()&3); Angle = self->Angles.Yaw; if (power) { @@ -425,7 +425,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL1) AActor *ball; player_t *player; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } @@ -436,13 +436,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL1) return 0; } AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) + if (weapon != nullptr) { if (!weapon->DepleteAmmo(weapon->bAltFire)) return 0; } - player->psprites[ps_weapon].sx = ((pr_maceatk() & 3) - 2); - player->psprites[ps_weapon].sy = WEAPONTOP + (pr_maceatk() & 3); + player->GetPSprite(ps_weapon)->x = ((pr_maceatk() & 3) - 2); + player->GetPSprite(ps_weapon)->y = WEAPONTOP + (pr_maceatk() & 3); ball = P_SpawnPlayerMissile(self, PClass::FindActor("MaceFX1"), self->Angles.Yaw + (((pr_maceatk() & 7) - 4) * (360. / 256))); if (ball) { @@ -1158,7 +1158,7 @@ IMPLEMENT_CLASS (APhoenixRodPowered) void APhoenixRodPowered::EndPowerup () { - P_SetPsprite (Owner->player, ps_weapon, SisterWeapon->GetReadyState()); + Owner->player->GetPSprite(ps_weapon)->SetState(SisterWeapon->GetReadyState()); DepleteAmmo (bAltFire); Owner->player->refire = 0; S_StopSound (Owner, CHAN_WEAPON); @@ -1298,7 +1298,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL2) player_t *player; APhoenixRod *flamethrower; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } @@ -1306,9 +1306,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL2) soundid = "weapons/phoenixpowshoot"; flamethrower = static_cast (player->ReadyWeapon); - if (flamethrower == NULL || --flamethrower->FlameCount == 0) + if (flamethrower == nullptr || --flamethrower->FlameCount == 0) { // Out of flame - P_SetPsprite (player, ps_weapon, flamethrower->FindState("Powerdown")); + player->GetPSprite(ps_weapon)->SetState(flamethrower->FindState("Powerdown")); player->refire = 0; S_StopSound (self, CHAN_WEAPON); return 0; diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp index d936e8d1d..898ff9b0e 100644 --- a/src/g_hexen/a_clericstaff.cpp +++ b/src/g_hexen/a_clericstaff.cpp @@ -58,7 +58,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) FTranslatedLineTarget t; PClassActor *puff; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } @@ -77,7 +77,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) if (t.linetarget) { P_LineAttack(pmo, angle, 1.5 * MELEERANGE, slope, damage, NAME_Melee, puff, false, &t); - if (t.linetarget != NULL) + if (t.linetarget != nullptr) { pmo->Angles.Yaw = t.angleFromSource; if (((t.linetarget->player && (!t.linetarget->IsTeammate(pmo) || level.teamdamage != 0)) || t.linetarget->flags3&MF3_ISMONSTER) @@ -89,13 +89,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) { pmo->health = player->health = newLife; } - if (weapon != NULL) + if (weapon != nullptr) { FState * newstate = weapon->FindState("Drain"); - if (newstate != NULL) P_SetPsprite(player, ps_weapon, newstate); + if (newstate != nullptr) player->GetPSprite(ps_weapon)->SetState(newstate); } } - if (weapon != NULL) + if (weapon != nullptr) { weapon->DepleteAmmo(weapon->bAltFire, false); } @@ -187,7 +187,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheckBlink) { if (!--self->weaponspecial) { - P_SetPsprite (self->player, ps_weapon, self->player->ReadyWeapon->FindState ("Blink")); + self->player->GetPSprite(ps_weapon)->SetState(self->player->ReadyWeapon->FindState ("Blink")); self->weaponspecial = (pr_blink()+50)>>2; } else diff --git a/src/g_hexen/a_fighteraxe.cpp b/src/g_hexen/a_fighteraxe.cpp index c83726b44..7fe867697 100644 --- a/src/g_hexen/a_fighteraxe.cpp +++ b/src/g_hexen/a_fighteraxe.cpp @@ -70,13 +70,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReady) player_t *player; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } if (player->ReadyWeapon->Ammo1->Amount) { - P_SetPsprite (player, ps_weapon, player->ReadyWeapon->FindState ("ReadyGlow")); + player->GetPSprite(ps_weapon)->SetState(player->ReadyWeapon->FindState ("ReadyGlow")); } else { @@ -97,13 +97,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckReadyG) player_t *player; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } if (player->ReadyWeapon->Ammo1->Amount <= 0) { - P_SetPsprite (player, ps_weapon, player->ReadyWeapon->FindState ("Ready")); + player->GetPSprite(ps_weapon)->SetState(player->ReadyWeapon->FindState ("Ready")); } else { @@ -124,13 +124,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUp) player_t *player; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } if (player->ReadyWeapon->Ammo1->Amount) { - P_SetPsprite (player, ps_weapon, player->ReadyWeapon->FindState ("SelectGlow")); + player->GetPSprite(ps_weapon)->SetState(player->ReadyWeapon->FindState ("SelectGlow")); } else { @@ -151,13 +151,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckUpG) player_t *player; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } if (player->ReadyWeapon->Ammo1->Amount <= 0) { - P_SetPsprite (player, ps_weapon, player->ReadyWeapon->FindState ("Select")); + player->GetPSprite(ps_weapon)->SetState(player->ReadyWeapon->FindState ("Select")); } else { @@ -178,13 +178,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeCheckAtk) player_t *player; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } if (player->ReadyWeapon->Ammo1->Amount) { - P_SetPsprite (player, ps_weapon, player->ReadyWeapon->FindState ("FireGlow")); + player->GetPSprite(ps_weapon)->SetState(player->ReadyWeapon->FindState ("FireGlow")); } return 0; } @@ -210,7 +210,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeAttack) PClassActor *pufftype; FTranslatedLineTarget t; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } @@ -241,7 +241,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeAttack) if (t.linetarget) { P_LineAttack(pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype, true, &t); - if (t.linetarget != NULL) + if (t.linetarget != nullptr) { if (t.linetarget->flags3&MF3_ISMONSTER || t.linetarget->player) { @@ -265,15 +265,15 @@ axedone: if (useMana == 2) { AWeapon *weapon = player->ReadyWeapon; - if (weapon != NULL) + if (weapon != nullptr) { weapon->DepleteAmmo (weapon->bAltFire, false); - if ((weapon->Ammo1 == NULL || weapon->Ammo1->Amount == 0) && + if ((weapon->Ammo1 == nullptr || weapon->Ammo1->Amount == 0) && (!(weapon->WeaponFlags & WIF_PRIMARY_USES_BOTH) || - weapon->Ammo2 == NULL || weapon->Ammo2->Amount == 0)) + weapon->Ammo2 == nullptr || weapon->Ammo2->Amount == 0)) { - P_SetPsprite (player, ps_weapon, player->ReadyWeapon->FindState ("Fire") + 5); + player->GetPSprite(ps_weapon)->SetState(player->ReadyWeapon->FindState ("Fire") + 5); } } } diff --git a/src/g_hexen/a_fighterplayer.cpp b/src/g_hexen/a_fighterplayer.cpp index c8f3aa19f..35b08f860 100644 --- a/src/g_hexen/a_fighterplayer.cpp +++ b/src/g_hexen/a_fighterplayer.cpp @@ -105,7 +105,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FPunchAttack) int i; player_t *player; - if (NULL == (player = self->player)) + if (nullptr == (player = self->player)) { return 0; } @@ -120,7 +120,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FPunchAttack) if (pmo->weaponspecial >= 3) { pmo->weaponspecial = 0; - P_SetPsprite (player, ps_weapon, player->ReadyWeapon->FindState("Fire2")); + player->GetPSprite(ps_weapon)->SetState(player->ReadyWeapon->FindState("Fire2")); S_Sound (pmo, CHAN_VOICE, "*fistgrunt", 1, ATTN_NORM); } return 0; diff --git a/src/g_hexen/a_pig.cpp b/src/g_hexen/a_pig.cpp index b53442c14..58db7dfc6 100644 --- a/src/g_hexen/a_pig.cpp +++ b/src/g_hexen/a_pig.cpp @@ -37,9 +37,9 @@ void APigPlayer::MorphPlayerThink () } if(Vel.X == 0 && Vel.Y == 0 && pr_pigplayerthink() < 64) { // Snout sniff - if (player->ReadyWeapon != NULL) + if (player->ReadyWeapon != nullptr) { - P_SetPsprite(player, ps_weapon, player->ReadyWeapon->FindState("Grunt")); + player->GetPSprite(ps_weapon)->SetState(player->ReadyWeapon->FindState("Grunt")); } S_Sound (this, CHAN_VOICE, "PigActive1", 1, ATTN_NORM); // snort return; diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index d36cdfe65..1b48678ab 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -1109,17 +1109,17 @@ void APowerWeaponLevel2::InitEffect () Super::InitEffect(); - if (Owner->player == NULL) + if (Owner->player == nullptr) return; weapon = Owner->player->ReadyWeapon; - if (weapon == NULL) + if (weapon == nullptr) return; sister = weapon->SisterWeapon; - if (sister == NULL) + if (sister == nullptr) return; if (!(sister->WeaponFlags & WIF_POWERED_UP)) @@ -1131,7 +1131,7 @@ void APowerWeaponLevel2::InitEffect () if (weapon->GetReadyState() != sister->GetReadyState()) { - P_SetPsprite (Owner->player, ps_weapon, sister->GetReadyState()); + Owner->player->GetPSprite(ps_weapon)->SetState(sister->GetReadyState()); } } @@ -1298,22 +1298,22 @@ void APowerTargeter::InitEffect () Super::InitEffect(); - if ((player = Owner->player) == NULL) + if ((player = Owner->player) == nullptr) return; FState *state = FindState("Targeter"); - if (state != NULL) + if (state != nullptr) { - P_SetPsprite (player, ps_targetcenter, state + 0); - P_SetPsprite (player, ps_targetleft, state + 1); - P_SetPsprite (player, ps_targetright, state + 2); + player->GetPSprite(ps_targetcenter)->SetState(state + 0); + player->GetPSprite(ps_targetleft)->SetState(state + 1); + player->GetPSprite(ps_targetright)->SetState(state + 2); } - player->psprites[ps_targetcenter].sx = (160-3); - player->psprites[ps_targetcenter].sy = - player->psprites[ps_targetleft].sy = - player->psprites[ps_targetright].sy = (100-3); + player->GetPSprite(ps_targetcenter)->x = (160-3); + player->GetPSprite(ps_targetcenter)->y = + player->GetPSprite(ps_targetleft)->y = + player->GetPSprite(ps_targetright)->y = (100-3); PositionAccuracy (); } @@ -1333,7 +1333,7 @@ void APowerTargeter::DoEffect () { Super::DoEffect (); - if (Owner != NULL && Owner->player != NULL) + if (Owner != nullptr && Owner->player != nullptr) { player_t *player = Owner->player; @@ -1342,17 +1342,17 @@ void APowerTargeter::DoEffect () { FState *state = FindState("Targeter"); - if (state != NULL) + if (state != nullptr) { if (EffectTics & 32) { - P_SetPsprite (player, ps_targetright, NULL); - P_SetPsprite (player, ps_targetleft, state+1); + player->GetPSprite(ps_targetright)->SetState(nullptr); + player->GetPSprite(ps_targetleft)->SetState(state + 1); } else if (EffectTics & 16) { - P_SetPsprite (player, ps_targetright, state+2); - P_SetPsprite (player, ps_targetleft, NULL); + player->GetPSprite(ps_targetright)->SetState(state + 2); + player->GetPSprite(ps_targetleft)->SetState(nullptr); } } } @@ -1362,11 +1362,11 @@ void APowerTargeter::DoEffect () void APowerTargeter::EndEffect () { Super::EndEffect(); - if (Owner != NULL && Owner->player != NULL) + if (Owner != nullptr && Owner->player != nullptr) { - P_SetPsprite (Owner->player, ps_targetcenter, NULL); - P_SetPsprite (Owner->player, ps_targetleft, NULL); - P_SetPsprite (Owner->player, ps_targetright, NULL); + Owner->player->GetPSprite(ps_targetcenter)->SetState(nullptr); + Owner->player->GetPSprite(ps_targetleft)->SetState(nullptr); + Owner->player->GetPSprite(ps_targetright)->SetState(nullptr); } } @@ -1374,10 +1374,10 @@ void APowerTargeter::PositionAccuracy () { player_t *player = Owner->player; - if (player != NULL) + if (player != nullptr) { - player->psprites[ps_targetleft].sx = (160-3) - ((100 - player->mo->accuracy)); - player->psprites[ps_targetright].sx = (160-3)+ ((100 - player->mo->accuracy)); + player->GetPSprite(ps_targetleft)->x = (160-3) - ((100 - player->mo->accuracy)); + player->GetPSprite(ps_targetright)->x = (160-3)+ ((100 - player->mo->accuracy)); } } diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index adb010d0c..f561a26de 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -608,15 +608,18 @@ bool AWeapon::DepleteAmmo (bool altFire, bool checkEnough, int ammouse) void AWeapon::PostMorphWeapon () { - if (Owner == NULL) + DPSprite *pspr; + if (Owner == nullptr) { return; } Owner->player->PendingWeapon = WP_NOCHANGE; Owner->player->ReadyWeapon = this; - Owner->player->psprites[ps_weapon].sy = WEAPONBOTTOM; Owner->player->refire = 0; - P_SetPsprite (Owner->player, ps_weapon, GetUpState()); + + pspr = Owner->player->GetPSprite(ps_weapon); + pspr->y = WEAPONBOTTOM; + pspr->SetState(GetUpState()); } //=========================================================================== diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 097965e34..98ffa0f96 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -350,11 +350,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_ItBurnsItBurns) S_Sound (self, CHAN_VOICE, "human/imonfire", 1, ATTN_NORM); - if (self->player != NULL && self->player->mo == self) + if (self->player != nullptr && self->player->mo == self) { - P_SetPsprite (self->player, ps_weapon, self->FindState("FireHands")); - P_SetPsprite (self->player, ps_flash, NULL); - self->player->ReadyWeapon = NULL; + self->player->GetPSprite(ps_weapon)->SetState(self->FindState("FireHands")); + self->player->GetPSprite(ps_flash)->SetState(nullptr); + self->player->ReadyWeapon = nullptr; self->player->PendingWeapon = WP_NOCHANGE; self->player->playerstate = PST_LIVE; self->player->extralight = 3; @@ -376,12 +376,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrispyPlayer) { PARAM_ACTION_PROLOGUE; - if (self->player != NULL && self->player->mo == self) + if (self->player != nullptr && self->player->mo == self) { self->player->playerstate = PST_DEAD; - P_SetPsprite (self->player, ps_weapon, - self->player->psprites[ps_weapon].state + - (self->FindState("FireHandsLower") - self->FindState("FireHands"))); + + DPSprite *psp; + psp = self->player->GetPSprite(ps_weapon); + psp->SetState(psp->GetState() + (self->FindState("FireHandsLower") - self->FindState("FireHands"))); } return 0; } @@ -390,13 +391,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_HandLower) { PARAM_ACTION_PROLOGUE; - if (self->player != NULL) + if (self->player != nullptr) { - pspdef_t *psp = &self->player->psprites[ps_weapon]; - psp->sy += 9; - if (psp->sy > WEAPONBOTTOM*2) + DPSprite *psp = self->player->GetPSprite(ps_weapon); + psp->y += 9; + if (psp->y > WEAPONBOTTOM*2) { - P_SetPsprite (self->player, ps_weapon, NULL); + psp->SetState(nullptr); } if (self->player->extralight > 0) self->player->extralight--; } diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index 96d53d431..32ae96366 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -216,10 +216,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_ClearFlash) player_t *player = self->player; - if (player == NULL) + if (player == nullptr) return 0; - P_SetPsprite (player, ps_flash, NULL); + player->GetPSprite(ps_flash)->SetState(nullptr); return 0; } @@ -233,9 +233,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_ShowElectricFlash) { PARAM_ACTION_PROLOGUE; - if (self->player != NULL) + if (self->player != nullptr) { - P_SetPsprite (self->player, ps_flash, self->player->ReadyWeapon->FindState(NAME_Flash)); + self->player->GetPSprite(ps_flash)->SetState(self->player->ReadyWeapon->FindState(NAME_Flash)); } return 0; } @@ -498,10 +498,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMauler2Pre) S_Sound (self, CHAN_WEAPON, "weapons/mauler2charge", 1, ATTN_NORM); - if (self->player != NULL) + if (self->player != nullptr) { - self->player->psprites[ps_weapon].sx += pr_mauler2.Random2() / 64.; - self->player->psprites[ps_weapon].sy += pr_mauler2.Random2() / 64.; + self->player->GetPSprite(ps_weapon)->x += pr_mauler2.Random2() / 64.; + self->player->GetPSprite(ps_weapon)->y += pr_mauler2.Random2() / 64.; } return 0; } @@ -698,24 +698,23 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireGrenade) DAngle an; AWeapon *weapon; - if (player == NULL || grenadetype == NULL) + if (player == nullptr || grenadetype == nullptr) return 0; - if ((weapon = player->ReadyWeapon) == NULL) + if ((weapon = player->ReadyWeapon) == nullptr) return 0; if (!weapon->DepleteAmmo (weapon->bAltFire)) return 0; - P_SetPsprite (player, ps_flash, flash); - self->player->psprites[ps_flash].processPending = true; + player->GetPSprite(ps_flash)->SetState(flash, true); - if (grenadetype != NULL) + if (grenadetype != nullptr) { self->AddZ(32); grenade = P_SpawnSubMissile (self, grenadetype, self); self->AddZ(-32); - if (grenade == NULL) + if (grenade == nullptr) return 0; if (grenade->SeeSound != 0) @@ -849,15 +848,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilView) { PARAM_ACTION_PROLOGUE; + DPSprite *pspr; int pieces; - if (self->player == NULL) + if (self->player == nullptr) { return 0; } pieces = static_cast(self->player->ReadyWeapon)->NumPieces; - P_SetPsprite (self->player, ps_weapon, - self->player->psprites[ps_weapon].state + pieces); + pspr = self->player->GetPSprite(ps_weapon); + pspr->SetState(pspr->GetState() + pieces); return 0; } @@ -875,9 +875,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilDown) { PARAM_ACTION_PROLOGUE; + DPSprite *pspr; int pieces; - if (self->player == NULL) + if (self->player == nullptr) { return 0; } @@ -887,8 +888,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilDown) { pieces = static_cast(self->player->ReadyWeapon)->NumPieces; } - P_SetPsprite (self->player, ps_weapon, - self->player->psprites[ps_weapon].state + pieces); + pspr = self->player->GetPSprite(ps_weapon); + pspr->SetState(pspr->GetState() + pieces); return 0; } @@ -904,15 +905,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_SelectSigilAttack) { PARAM_ACTION_PROLOGUE; + DPSprite *pspr; int pieces; - if (self->player == NULL) + if (self->player == nullptr) { return 0; } pieces = static_cast(self->player->ReadyWeapon)->NumPieces; - P_SetPsprite (self->player, ps_weapon, - self->player->psprites[ps_weapon].state + 4*pieces - 3); + pspr = self->player->GetPSprite(ps_weapon); + pspr->SetState(pspr->GetState() + 4*pieces - 3); return 0; } diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index ff9e2ac9a..bb9d41d55 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -314,7 +314,7 @@ void cht_DoCheat (player_t *player, int cheat) // [GRB] case CHT_RESSURECT: - if (player->playerstate != PST_LIVE && player->mo != NULL) + if (player->playerstate != PST_LIVE && player->mo != nullptr) { if (player->mo->IsKindOf(RUNTIME_CLASS(APlayerChunk))) { @@ -343,9 +343,9 @@ void cht_DoCheat (player_t *player, int cheat) player->mo->Translation = TRANSLATION(TRANSLATION_Players, BYTE(player-players)); } player->mo->DamageType = NAME_None; - if (player->ReadyWeapon != NULL) + if (player->ReadyWeapon != nullptr) { - P_SetPsprite(player, ps_weapon, player->ReadyWeapon->GetUpState()); + player->GetPSprite(ps_weapon)->SetState(player->ReadyWeapon->GetUpState()); } if (player->morphTics > 0) @@ -932,10 +932,10 @@ void cht_Take (player_t *player, const char *name, int amount) if (weapon) weapon->Destroy (); - player->ReadyWeapon = NULL; + player->ReadyWeapon = nullptr; player->PendingWeapon = WP_NOCHANGE; - player->psprites[ps_weapon].state = NULL; - player->psprites[ps_flash].state = NULL; + player->GetPSprite(ps_weapon)->SetState(nullptr); + player->GetPSprite(ps_flash)->SetState(nullptr); } } diff --git a/src/p_local.h b/src/p_local.h index 8e64c3414..14d7e9152 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -75,7 +75,6 @@ extern int bmapnegy; // P_PSPR // void P_SetupPsprites (player_t* curplayer, bool startweaponup); -void P_MovePsprites (player_t* curplayer); void P_DropWeapon (player_t* player); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index fe049bdb4..94f8c57c3 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -997,12 +997,12 @@ void AActor::ClearInventory() invp = &inv->Inventory; } } - if (player != NULL) + if (player != nullptr) { - player->ReadyWeapon = NULL; + player->ReadyWeapon = nullptr; player->PendingWeapon = WP_NOCHANGE; - player->psprites[ps_weapon].state = NULL; - player->psprites[ps_flash].state = NULL; + player->GetPSprite(ps_weapon)->SetState(nullptr); + player->GetPSprite(ps_flash)->SetState(nullptr); } } diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index fad782b41..656ee4c38 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -93,25 +93,92 @@ static const FGenericButtons ButtonChecks[] = // CODE -------------------------------------------------------------------- +//------------------------------------------------------------------------ +// +// +// +//------------------------------------------------------------------------ + +IMPLEMENT_POINTY_CLASS(DPSprite) + DECLARE_POINTER(Caller) + DECLARE_POINTER(Next) +END_POINTERS + +//------------------------------------------------------------------------ +// +// +// +//------------------------------------------------------------------------ + +DPSprite::DPSprite(player_t *owner, AInventory *caller, int id) +: processPending(true), firstTic(true), Owner(owner), Caller(caller), ID(id) +{ + DPSprite **prev = &Owner->psprites; + while (*prev && (*prev)->ID < ID) + prev = &(*prev)->Next; + + Next = *prev; + *prev = this; + + if (Next && Next->ID == ID && ID != 0) + Next->Destroy(); // Replace it. +} + +//------------------------------------------------------------------------ +// +// +// +//------------------------------------------------------------------------ + +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; + } + + return pspr; +} + //--------------------------------------------------------------------------- // // PROC P_NewPspriteTick // //--------------------------------------------------------------------------- -void P_NewPspriteTick() +void DPSprite::NewTick() { // This function should be called after the beginning of a tick, before any possible // prprite-event, or near the end, after any possible psprite event. // Because data is reset for every tick (which it must be) this has no impact on savegames. - for (int i = 0; iprocessPending = true; + + pspr = pspr->Next; } } } @@ -123,79 +190,85 @@ void P_NewPspriteTick() // //--------------------------------------------------------------------------- -void P_SetPsprite (player_t *player, int position, FState *state, bool nofunction) +void DPSprite::SetState(FState *newstate, bool pending) { - pspdef_t *psp; - - if (position == ps_weapon && !nofunction) + if (ID == ps_weapon) { // A_WeaponReady will re-set these as needed - player->WeaponState &= ~(WF_WEAPONREADY | WF_WEAPONREADYALT | WF_WEAPONBOBBING | WF_WEAPONSWITCHOK | WF_WEAPONRELOADOK | WF_WEAPONZOOMOK | + Owner->WeaponState &= ~(WF_WEAPONREADY | WF_WEAPONREADYALT | WF_WEAPONBOBBING | WF_WEAPONSWITCHOK | WF_WEAPONRELOADOK | WF_WEAPONZOOMOK | WF_USER1OK | WF_USER2OK | WF_USER3OK | WF_USER4OK); } - psp = &player->psprites[position]; - psp->processPending = false; // Do not subsequently perform periodic processing within the same tick. + // Special handling for the old hardcoded layers. + if (ID > 0 && ID < NUMPSPRITES) + Caller = Owner->ReadyWeapon; + + processPending = pending; do { - if (state == NULL) + if (newstate == nullptr) { // Object removed itself. - psp->state = NULL; - break; + Destroy(); + return; } - psp->state = state; + State = newstate; - if (state->sprite != SPR_FIXED) + if (newstate->sprite != SPR_FIXED) { // okay to change sprite and/or frame - if (!state->GetSameFrame()) + if (!newstate->GetSameFrame()) { // okay to change frame - psp->frame = state->GetFrame(); + Frame = newstate->GetFrame(); } - if (state->sprite != SPR_NOCHANGE) + if (newstate->sprite != SPR_NOCHANGE) { // okay to change sprite - psp->sprite = state->sprite; + Sprite = newstate->sprite; } } + Tics = newstate->GetTics(); // could be 0 - if (sv_fastweapons == 2 && position == ps_weapon) - psp->tics = state->ActionFunc == NULL ? 0 : 1; - else if (sv_fastweapons == 3) - psp->tics = (state->GetTics() != 0); - else if (sv_fastweapons) - psp->tics = 1; // great for producing decals :) - else - psp->tics = state->GetTics(); // could be 0 + if ((ID > 0 && ID < NUMPSPRITES) || Caller->IsKindOf(RUNTIME_CLASS(AWeapon))) + { // The targeter layers are affected by this too. + if (sv_fastweapons == 2 && ID == ps_weapon) + Tics = newstate->ActionFunc == nullptr ? 0 : 1; + else if (sv_fastweapons == 3) + Tics = (newstate->GetTics() != 0); + else if (sv_fastweapons) + Tics = 1; // great for producing decals :) + } - if (state->GetMisc1()) + if (newstate->GetMisc1()) { // Set coordinates. - psp->sx = state->GetMisc1(); + x = newstate->GetMisc1(); } - if (state->GetMisc2()) + if (newstate->GetMisc2()) { - psp->sy = state->GetMisc2(); + y = newstate->GetMisc2(); } - if (!nofunction && player->mo != NULL) + if (Owner->mo != nullptr) { - FState *newstate; - if (state->CallAction(player->mo, player->ReadyWeapon, &newstate)) + FState *nextstate; + if (newstate->CallAction(Owner->mo, Caller, &nextstate)) { - if (newstate != NULL) + if (nextstate != nullptr) { - state = newstate; - psp->tics = 0; + newstate = nextstate; + Tics = 0; continue; } - if (psp->state == NULL) + if (State == nullptr) { - break; + Destroy(); + return; } } } - state = psp->state->GetNextState(); - } while (!psp->tics); // An initial state of 0 could cycle through. + newstate = State->GetNextState(); + } while (!Tics); // An initial state of 0 could cycle through. + + return; } //--------------------------------------------------------------------------- @@ -211,13 +284,14 @@ void P_BringUpWeapon (player_t *player) { FState *newstate; AWeapon *weapon; + DPSprite *psweapon = player->GetPSprite(ps_weapon); if (player->PendingWeapon == WP_NOCHANGE) { - if (player->ReadyWeapon != NULL) + if (player->ReadyWeapon != nullptr) { - player->psprites[ps_weapon].sy = WEAPONTOP; - P_SetPsprite (player, ps_weapon, player->ReadyWeapon->GetReadyState()); + psweapon->y = WEAPONTOP; + psweapon->SetState(player->ReadyWeapon->GetReadyState()); } return; } @@ -226,7 +300,7 @@ void P_BringUpWeapon (player_t *player) // If the player has a tome of power, use this weapon's powered up // version, if one is available. - if (weapon != NULL && + if (weapon != nullptr && weapon->SisterWeapon && weapon->SisterWeapon->WeaponFlags & WIF_POWERED_UP && player->mo->FindInventory (RUNTIME_CLASS(APowerWeaponLevel2), true)) @@ -234,7 +308,7 @@ void P_BringUpWeapon (player_t *player) weapon = weapon->SisterWeapon; } - if (weapon != NULL) + if (weapon != nullptr) { if (weapon->UpSound) { @@ -245,20 +319,19 @@ void P_BringUpWeapon (player_t *player) } else { - newstate = NULL; + newstate = nullptr; } player->PendingWeapon = WP_NOCHANGE; player->ReadyWeapon = weapon; - player->psprites[ps_weapon].sy = player->cheats & CF_INSTANTWEAPSWITCH + psweapon->y = player->cheats & CF_INSTANTWEAPSWITCH ? WEAPONTOP : WEAPONBOTTOM; + psweapon->SetState(newstate); // make sure that the previous weapon's flash state is terminated. // When coming here from a weapon drop it may still be active. - P_SetPsprite(player, ps_flash, NULL); - P_SetPsprite (player, ps_weapon, newstate); + player->GetPSprite(ps_flash)->SetState(nullptr); player->mo->weaponspecial = 0; } - //--------------------------------------------------------------------------- // // PROC P_FireWeapon @@ -271,24 +344,24 @@ void P_FireWeapon (player_t *player, FState *state) // [SO] 9/2/02: People were able to do an awful lot of damage // when they were observers... - if (player->Bot == NULL && bot_observer) + if (player->Bot == nullptr && bot_observer) { return; } weapon = player->ReadyWeapon; - if (weapon == NULL || !weapon->CheckAmmo (AWeapon::PrimaryFire, true)) + if (weapon == nullptr || !weapon->CheckAmmo (AWeapon::PrimaryFire, true)) { return; } player->mo->PlayAttacking (); weapon->bAltFire = false; - if (state == NULL) + if (state == nullptr) { state = weapon->GetAtkState(!!player->refire); } - P_SetPsprite (player, ps_weapon, state); + player->GetPSprite(ps_weapon)->SetState(state); if (!(weapon->WeaponFlags & WIF_NOALERT)) { P_NoiseAlert (player->mo, player->mo, false); @@ -307,13 +380,13 @@ void P_FireWeaponAlt (player_t *player, FState *state) // [SO] 9/2/02: People were able to do an awful lot of damage // when they were observers... - if (player->Bot == NULL && bot_observer) + if (player->Bot == nullptr && bot_observer) { return; } weapon = player->ReadyWeapon; - if (weapon == NULL || weapon->FindState(NAME_AltFire) == NULL || !weapon->CheckAmmo (AWeapon::AltFire, true)) + if (weapon == nullptr || weapon->FindState(NAME_AltFire) == nullptr || !weapon->CheckAmmo (AWeapon::AltFire, true)) { return; } @@ -321,12 +394,12 @@ void P_FireWeaponAlt (player_t *player, FState *state) player->mo->PlayAttacking (); weapon->bAltFire = true; - if (state == NULL) + if (state == nullptr) { state = weapon->GetAltAtkState(!!player->refire); } - P_SetPsprite (player, ps_weapon, state); + player->GetPSprite(ps_weapon)->SetState(state); if (!(weapon->WeaponFlags & WIF_NOALERT)) { P_NoiseAlert (player->mo, player->mo, false); @@ -343,15 +416,15 @@ void P_FireWeaponAlt (player_t *player, FState *state) void P_DropWeapon (player_t *player) { - if (player == NULL) + if (player == nullptr) { return; } // Since the weapon is dropping, stop blocking switching. player->WeaponState &= ~WF_DISABLESWITCH; - if (player->ReadyWeapon != NULL) + if (player->ReadyWeapon != nullptr) { - P_SetPsprite (player, ps_weapon, player->ReadyWeapon->GetDownState()); + player->GetPSprite(ps_weapon)->SetState(player->ReadyWeapon->GetDownState()); } } @@ -367,7 +440,7 @@ void P_DropWeapon (player_t *player) // //============================================================================ -void P_BobWeapon (player_t *player, pspdef_t *psp, float *x, float *y, double ticfrac) +void P_BobWeapon (player_t *player, float *x, float *y, double ticfrac) { static float curbob; double xx[2], yy[2]; @@ -377,7 +450,7 @@ void P_BobWeapon (player_t *player, pspdef_t *psp, float *x, float *y, double ti weapon = player->ReadyWeapon; - if (weapon == NULL || weapon->WeaponFlags & WIF_DONTBOB) + if (weapon == nullptr || weapon->WeaponFlags & WIF_DONTBOB) { *x = *y = 0; return; @@ -528,7 +601,7 @@ void DoReadyWeaponToFire (AActor *self, bool prim, bool alt) } // Play ready sound, if any. - if (weapon->ReadySound && player->psprites[ps_weapon].state == weapon->FindState(NAME_Ready)) + if (weapon->ReadySound && player->GetPSprite(ps_weapon)->GetState() == weapon->FindState(NAME_Ready)) { if (!(weapon->WeaponFlags & WIF_READYSNDHALF) || pr_wpnreadysnd() < 128) { @@ -547,8 +620,8 @@ void DoReadyWeaponToBob (AActor *self) { // Prepare for bobbing action. self->player->WeaponState |= WF_WEAPONBOBBING; - self->player->psprites[ps_weapon].sx = 0; - self->player->psprites[ps_weapon].sy = WEAPONTOP; + self->player->GetPSprite(ps_weapon)->x = 0; + self->player->GetPSprite(ps_weapon)->y = WEAPONTOP; } } @@ -673,12 +746,12 @@ void P_CheckWeaponSwitch (player_t *player) static void P_CheckWeaponButtons (player_t *player) { - if (player->Bot == NULL && bot_observer) + if (player->Bot == nullptr && bot_observer) { return; } AWeapon *weapon = player->ReadyWeapon; - if (weapon == NULL) + if (weapon == nullptr) { return; } @@ -693,11 +766,11 @@ static void P_CheckWeaponButtons (player_t *player) // [XA] don't change state if still null, so if the modder // sets WRF_xxx to true but forgets to define the corresponding // state, the weapon won't disappear. ;) - if (state != NULL) + if (state != nullptr) { - P_SetPsprite(player, ps_weapon, state); + player->GetPSprite(ps_weapon)->SetState(state); return; - } + } } } } @@ -808,31 +881,31 @@ DEFINE_ACTION_FUNCTION(AInventory, A_WeaponOffset) } player_t *player = self->player; - pspdef_t *psp; + DPSprite *psp; if (player && (player->playerstate != PST_DEAD)) { - psp = &player->psprites[ps_weapon]; + psp = player->GetPSprite(ps_weapon); if (!(flags & WOF_KEEPX)) { if (flags & WOF_ADD) { - psp->sx += wx; + psp->x += wx; } else { - psp->sx = wx; + psp->x = wx; } } if (!(flags & WOF_KEEPY)) { if (flags & WOF_ADD) { - psp->sy += wy; + psp->y += wy; } else { - psp->sy = wy; + psp->y = wy; } } } @@ -851,35 +924,35 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Lower) PARAM_ACTION_PROLOGUE; player_t *player = self->player; - pspdef_t *psp; + DPSprite *psp; - if (NULL == player) + if (nullptr == player) { return 0; } - psp = &player->psprites[ps_weapon]; + psp = player->GetPSprite(ps_weapon); if (player->morphTics || player->cheats & CF_INSTANTWEAPSWITCH) { - psp->sy = WEAPONBOTTOM; + psp->y = WEAPONBOTTOM; } else { - psp->sy += LOWERSPEED; + psp->y += LOWERSPEED; } - if (psp->sy < WEAPONBOTTOM) + if (psp->y < WEAPONBOTTOM) { // Not lowered all the way yet return 0; } if (player->playerstate == PST_DEAD) { // Player is dead, so don't bring up a pending weapon - psp->sy = WEAPONBOTTOM; + psp->y = WEAPONBOTTOM; // Player is dead, so keep the weapon off screen - P_SetPsprite (player, ps_weapon, NULL); + psp->SetState(nullptr); return 0; } // [RH] Clear the flash state. Only needed for Strife. - P_SetPsprite (player, ps_flash, NULL); + player->GetPSprite(ps_flash)->SetState(nullptr); P_BringUpWeapon (player); return 0; } @@ -894,14 +967,14 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Raise) { PARAM_ACTION_PROLOGUE; - if (self == NULL) + if (self == nullptr) { return 0; } player_t *player = self->player; - pspdef_t *psp; + DPSprite *psp; - if (NULL == player) + if (nullptr == player) { return 0; } @@ -910,20 +983,20 @@ DEFINE_ACTION_FUNCTION(AInventory, A_Raise) P_DropWeapon(player); return 0; } - psp = &player->psprites[ps_weapon]; - psp->sy -= RAISESPEED; - if (psp->sy > WEAPONTOP) + psp = player->GetPSprite(ps_weapon); + psp->y -= RAISESPEED; + if (psp->y > WEAPONTOP) { // Not raised all the way yet return 0; } - psp->sy = WEAPONTOP; - if (player->ReadyWeapon != NULL) + psp->y = WEAPONTOP; + if (player->ReadyWeapon != nullptr) { - P_SetPsprite (player, ps_weapon, player->ReadyWeapon->GetReadyState()); + psp->SetState(player->ReadyWeapon->GetReadyState()); } else { - player->psprites[ps_weapon].state = NULL; + psp->SetState(nullptr); } return 0; } @@ -942,12 +1015,12 @@ enum GF_Flags DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_GunFlash) { PARAM_ACTION_PROLOGUE; - PARAM_STATE_OPT(flash) { flash = NULL; } + PARAM_STATE_OPT(flash) { flash = nullptr; } PARAM_INT_OPT (flags) { flags = 0; } player_t *player = self->player; - if (NULL == player) + if (nullptr == player) { return 0; } @@ -955,18 +1028,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_GunFlash) { player->mo->PlayAttacking2 (); } - if (flash == NULL) + if (flash == nullptr) { if (player->ReadyWeapon->bAltFire) { flash = player->ReadyWeapon->FindState(NAME_AltFlash); } - if (flash == NULL) + if (flash == nullptr) { flash = player->ReadyWeapon->FindState(NAME_Flash); } } - P_SetPsprite (player, ps_flash, flash); + player->GetPSprite(ps_flash)->SetState(flash); return 0; } @@ -1084,13 +1157,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_Light) void P_SetupPsprites(player_t *player, bool startweaponup) { - int i; - // Remove all psprites - for (i = 0; i < NUMPSPRITES; i++) - { - player->psprites[i].state = NULL; - } + player->DestroyPSprites(); + // Spawn the ready weapon player->PendingWeapon = !startweaponup ? player->ReadyWeapon : WP_NOCHANGE; P_BringUpWeapon (player); @@ -1104,61 +1173,167 @@ void P_SetupPsprites(player_t *player, bool startweaponup) // //------------------------------------------------------------------------ -void P_MovePsprites (player_t *player) +void player_t::TickPSprites() { - int i; - pspdef_t *psp; - FState *state; + DPSprite *weapon = nullptr; + DPSprite *flash = nullptr; + bool noweapon = (ReadyWeapon == nullptr && (health > 0 || mo->DamageType != NAME_Fire)); - // [RH] If you don't have a weapon, then the psprites should be NULL. - if (player->ReadyWeapon == NULL && (player->health > 0 || player->mo->DamageType != NAME_Fire)) + DPSprite *pspr = psprites; + while (pspr) { - P_SetPsprite (player, ps_weapon, NULL); - P_SetPsprite (player, ps_flash, NULL); - if (player->PendingWeapon != WP_NOCHANGE) + // Destroy the psprite if it's from a weapon that isn't currently selected by the player + // or if it's from an inventory item that the player no longer owns. + // (except for the old hardcoded layers) + if (!(pspr->ID > 0 && pspr->ID < NUMPSPRITES) && + (pspr->Caller == nullptr || + (pspr->Caller->IsKindOf(RUNTIME_CLASS(AWeapon)) && pspr->Caller != pspr->Owner->ReadyWeapon) || + (pspr->Caller->Owner != pspr->Owner->mo))) { - P_BringUpWeapon (player); + pspr->Destroy(); } + else if (!(pspr->ID > 0 && pspr->ID < NUMPSPRITES && noweapon)) + { + pspr->Tick(); + } + + if (pspr->ID == ps_weapon) + weapon = pspr; + else if (pspr->ID == ps_flash) + flash = pspr; + + pspr = pspr->Next; + } + + if (noweapon) + { + if (weapon) weapon->SetState(nullptr); + if (flash) flash->SetState(nullptr); + if (PendingWeapon != WP_NOCHANGE) + P_BringUpWeapon(this); } else { - psp = &player->psprites[0]; - for (i = 0; i < NUMPSPRITES; i++, psp++) + if (weapon && flash) { - if ((state = psp->state) != NULL && psp->processPending) // a null state means not active - { - // drop tic count and possibly change state - if (psp->tics != -1) // a -1 tic count never changes - { - psp->tics--; - - // [BC] Apply double firing speed. - if ( psp->tics && (player->cheats & CF_DOUBLEFIRINGSPEED)) - psp->tics--; - - if(!psp->tics) - { - P_SetPsprite (player, i, psp->state->GetNextState()); - } - } - } + flash->x = weapon->x; + flash->y = weapon->y; } - player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; - player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; - P_CheckWeaponSwitch (player); - if (player->WeaponState & (WF_WEAPONREADY | WF_WEAPONREADYALT)) + P_CheckWeaponSwitch(this); + if (WeaponState & (WF_WEAPONREADY | WF_WEAPONREADYALT)) { - P_CheckWeaponFire (player); + P_CheckWeaponFire(this); } - // Check custom buttons - P_CheckWeaponButtons(player); - } + P_CheckWeaponButtons(this); + } } -FArchive &operator<< (FArchive &arc, pspdef_t &def) +//------------------------------------------------------------------------ +// +// +// +//------------------------------------------------------------------------ + +void DPSprite::Tick() { - arc << def.state << def.tics << def.sx << def.sy - << def.sprite << def.frame; - return arc; + oldx = x; + oldy = y; + + if (processPending) + { + // drop tic count and possibly change state + if (Tics != -1) // a -1 tic count never changes + { + Tics--; + + // [BC] Apply double firing speed. + // This is applied to the targeter layers too. + if (((ID > 0 && ID < NUMPSPRITES) || (Caller->IsKindOf(RUNTIME_CLASS(AWeapon)))) && + (Tics && Owner->cheats & CF_DOUBLEFIRINGSPEED)) + Tics--; + + if (!Tics) + SetState(State->GetNextState()); + } + } +} + +//------------------------------------------------------------------------ +// +// +// +//------------------------------------------------------------------------ + +void DPSprite::Serialize(FArchive &arc) +{ + Super::Serialize(arc); + + arc << Next << Caller << Owner + << State << Tics << Sprite << Frame + << ID << x << y << oldx << oldy; +} + +//------------------------------------------------------------------------ +// +// +// +//------------------------------------------------------------------------ + +void player_t::DestroyPSprites() +{ + DPSprite *pspr = psprites; + while (pspr) + { + pspr->Destroy(); + pspr = pspr->Next; + } +} + +//------------------------------------------------------------------------ +// +// +// +//------------------------------------------------------------------------ + +void DPSprite::Destroy() +{ + DPSprite **prev = &Owner->psprites; + while (*prev != this) + prev = &(*prev)->Next; + + *prev = Next; + + Super::Destroy(); +} + +//------------------------------------------------------------------------ +// +// +// +//------------------------------------------------------------------------ + +ADD_STAT(psprites) +{ + FString out; + DPSprite *pspr; + for (int i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + out.AppendFormat("[psprites] player: %d | layers: ", i); + + pspr = players[i].psprites; + while (pspr) + { + out.AppendFormat("%d, ", pspr->GetID()); + + pspr = pspr->GetNext(); + } + + out.AppendFormat("\n"); + } + + return out; } diff --git a/src/p_pspr.h b/src/p_pspr.h index 397ac4fff..87e78ef1f 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -34,59 +34,72 @@ // the right spot at 320x200. #define WEAPONTOP (32+6./16) +class AInventory; +class FArchive; // // Overlay psprites are scaled shapes // drawn directly on the view screen, // coordinates are given for a 320*200 view screen. // -typedef enum +enum psprnum_t // These are all called by the owner's ReadyWeapon. { - ps_weapon, + ps_weapon = 1, ps_flash, ps_targetcenter, ps_targetleft, ps_targetright, NUMPSPRITES - -} psprnum_t; - -/* -inline FArchive &operator<< (FArchive &arc, psprnum_t &i) -{ - BYTE val = (BYTE)i; - arc << val; - i = (psprnum_t)val; - return arc; -} -*/ - -struct pspdef_t -{ - FState* state; // a NULL state means not active - int tics; - double sx; - double sy; - int sprite; - int frame; - bool processPending; // true: waiting for periodic processing on this tick }; -class FArchive; +class DPSprite : public DObject +{ + DECLARE_CLASS (DPSprite, DObject) + HAS_OBJECT_POINTERS +public: + DPSprite(player_t *owner, AInventory *caller, int id); -FArchive &operator<< (FArchive &, pspdef_t &); + static void NewTick(); + void SetState(FState *newstate, bool pending = false); -class player_t; -class AActor; -struct FState; + int GetID() const { return ID; } + int GetSprite() const { return Sprite; } + int GetFrame() const { return Frame; } + FState* GetState() const { return State; } + DPSprite* GetNext() const { return Next; } + TObjPtr GetCaller() const { return Caller; } + + double x, y; + double oldx, oldy; + bool firstTic; + int Tics; + +private: + DPSprite () {} + + void Serialize(FArchive &arc); + void Tick(); + void Destroy(); + + TObjPtr Caller; + DPSprite *Next; + player_t *Owner; + FState *State; + int Sprite; + int Frame; + int ID; + bool processPending; // true: waiting for periodic processing on this tick + + friend class player_t; + friend void CopyPlayer(player_t *dst, player_t *src, const char *name); +}; void P_NewPspriteTick(); -void P_SetPsprite (player_t *player, int position, FState *state, bool nofunction=false); void P_CalcSwing (player_t *player); void P_BringUpWeapon (player_t *player); void P_FireWeapon (player_t *player); void P_DropWeapon (player_t *player); -void P_BobWeapon (player_t *player, pspdef_t *psp, float *x, float *y, double ticfrac); +void P_BobWeapon (player_t *player, float *x, float *y, double ticfrac); DAngle P_BulletSlope (AActor *mo, FTranslatedLineTarget *pLineTarget = NULL, int aimflags = 0); void P_GunShot (AActor *mo, bool accurate, PClassActor *pufftype, DAngle pitch); diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index af5992488..049673abd 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -274,7 +274,7 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name) dst->cheats |= chasecam; - if (dst->Bot != NULL) + if (dst->Bot != nullptr) { botinfo_t *thebot = bglobal.botinfo; while (thebot && stricmp (name, thebot->name)) @@ -296,10 +296,23 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name) dst->userinfo.SkinNumChanged(R_FindSkin(skins[dst->userinfo.GetSkin()].name, dst->CurrentPlayerClass)); // Make sure the player pawn points to the proper player struct. - if (dst->mo != NULL) + if (dst->mo != nullptr) { dst->mo->player = dst; } + + // Same for the psprites. + DPSprite *pspr = dst->psprites; + while (pspr) + { + pspr->Owner = dst; + + pspr = pspr->Next; + } + + // Don't let the psprites be destroyed when src is destroyed. + src->psprites = nullptr; + // These 2 variables may not be overwritten. dst->attackdown = attackdown; dst->usedown = usedown; diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 032aa8bf5..e3704d3ff 100644 --- a/src/p_tick.cpp +++ b/src/p_tick.cpp @@ -87,7 +87,7 @@ void P_Ticker (void) if (paused || P_CheckTickerPaused()) return; - P_NewPspriteTick(); + DPSprite::NewTick(); // [RH] Frozen mode is only changed every 4 tics, to make it work with A_Tracer(). if ((level.time & 3) == 0) diff --git a/src/p_user.cpp b/src/p_user.cpp index 486044070..353c35309 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -270,6 +270,7 @@ player_t::player_t() WeaponState(0), ReadyWeapon(0), PendingWeapon(0), + psprites(0), cheats(0), timefreezer(0), refire(0), @@ -315,7 +316,11 @@ player_t::player_t() { memset (&cmd, 0, sizeof(cmd)); memset (frags, 0, sizeof(frags)); - memset (psprites, 0, sizeof(psprites)); +} + +player_t::~player_t() +{ + DestroyPSprites(); } player_t &player_t::operator=(const player_t &p) @@ -371,7 +376,7 @@ player_t &player_t::operator=(const player_t &p) extralight = p.extralight; fixedcolormap = p.fixedcolormap; fixedlightlevel = p.fixedlightlevel; - memcpy(psprites, &p.psprites, sizeof(psprites)); + psprites = p.psprites; morphTics = p.morphTics; MorphedPlayerClass = p.MorphedPlayerClass; MorphStyle = p.MorphStyle; @@ -433,6 +438,7 @@ size_t player_t::FixPointers (const DObject *old, DObject *rep) if (ReadyWeapon == old) ReadyWeapon = static_cast(rep), changed++; if (PendingWeapon == old) PendingWeapon = static_cast(rep), changed++; if (*&PremorphWeapon == old) PremorphWeapon = static_cast(rep), changed++; + if (psprites == old) psprites = static_cast(rep), changed++; if (*&ConversationNPC == old) ConversationNPC = replacement, changed++; if (*&ConversationPC == old) ConversationPC = replacement, changed++; if (*&MUSINFOactor == old) MUSINFOactor = replacement, changed++; @@ -451,6 +457,7 @@ size_t player_t::PropagateMark() GC::Mark(ConversationPC); GC::Mark(MUSINFOactor); GC::Mark(PremorphWeapon); + GC::Mark(psprites); if (PendingWeapon != WP_NOCHANGE) { GC::Mark(PendingWeapon); @@ -1369,35 +1376,36 @@ void APlayerPawn::MorphPlayerThink () void APlayerPawn::ActivateMorphWeapon () { PClassActor *morphweapon = PClass::FindActor (MorphWeapon); + DPSprite *pspr = player->GetPSprite(ps_weapon); player->PendingWeapon = WP_NOCHANGE; - player->psprites[ps_weapon].sy = WEAPONTOP; + pspr->y = WEAPONTOP; - if (morphweapon == NULL || !morphweapon->IsDescendantOf (RUNTIME_CLASS(AWeapon))) + if (morphweapon == nullptr || !morphweapon->IsDescendantOf (RUNTIME_CLASS(AWeapon))) { // No weapon at all while morphed! - player->ReadyWeapon = NULL; - P_SetPsprite (player, ps_weapon, NULL); + player->ReadyWeapon = nullptr; + pspr->SetState(nullptr); } else { player->ReadyWeapon = static_cast(player->mo->FindInventory (morphweapon)); - if (player->ReadyWeapon == NULL) + if (player->ReadyWeapon == nullptr) { player->ReadyWeapon = static_cast(player->mo->GiveInventoryType (morphweapon)); - if (player->ReadyWeapon != NULL) + if (player->ReadyWeapon != nullptr) { player->ReadyWeapon->GivenAsMorphWeapon = true; // flag is used only by new beastweap semantics in P_UndoPlayerMorph } } - if (player->ReadyWeapon != NULL) + if (player->ReadyWeapon != nullptr) { - P_SetPsprite (player, ps_weapon, player->ReadyWeapon->GetReadyState()); + pspr->SetState(player->ReadyWeapon->GetReadyState()); } else { - P_SetPsprite (player, ps_weapon, NULL); + pspr->SetState(nullptr); } } - P_SetPsprite (player, ps_flash, NULL); + player->GetPSprite(ps_flash)->SetState(nullptr); player->PendingWeapon = WP_NOCHANGE; } @@ -2114,7 +2122,7 @@ void P_DeathThink (player_t *player) int dir; DAngle delta; - P_MovePsprites (player); + player->TickPSprites(); player->onground = (player->mo->Z() <= player->mo->floorz); if (player->mo->IsKindOf (RUNTIME_CLASS(APlayerChunk))) @@ -2634,7 +2642,7 @@ void P_PlayerThink (player_t *player) } } // Cycle psprites - P_MovePsprites (player); + player->TickPSprites(); // Other Counters if (player->damagecount) @@ -3064,8 +3072,37 @@ void player_t::Serialize (FArchive &arc) for (i = 0; i < MAXPLAYERS; i++) arc << frags[i]; - for (i = 0; i < NUMPSPRITES; i++) - arc << psprites[i]; + + if (SaveVersion < 4547) + { + for (i = ps_weapon; i < NUMPSPRITES; i++) + { + FState *state; + int tics; + double sx, sy; + int sprite; + int frame; + + arc << state << tics + << sx << sy + << sprite << frame; + + if (state != nullptr) + { + DPSprite *pspr; + 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; + } + } + } + else + arc << psprites; arc << CurrentPlayerClass; diff --git a/src/r_things.cpp b/src/r_things.cpp index 427e61b06..704b6509c 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -92,6 +92,7 @@ extern double globaluclip, globaldclip; extern float MaskedScaleY; #define MINZ double((2048*4) / double(1 << 20)) +#define BASEXCENTER (160) #define BASEYCENTER (100) EXTERN_CVAR (Bool, st_scale) @@ -111,9 +112,15 @@ double pspriteyscale; fixed_t sky1scale; // [RH] Sky 1 scale factor fixed_t sky2scale; // [RH] Sky 2 scale factor -vissprite_t *VisPSprites[NUMPSPRITES]; -int VisPSpritesX1[NUMPSPRITES]; -FDynamicColormap *VisPSpritesBaseColormap[NUMPSPRITES]; +// Used to store a psprite's drawing information if it needs to be drawn later. +struct vispsp_t +{ + vissprite_t *vis; + FDynamicColormap *basecolormap; + int x1; +}; +TArray vispsprites; +unsigned int vispspindex; static int spriteshade; @@ -1269,48 +1276,41 @@ void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) } } - // // R_DrawPSprite // -void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, double sx, double sy) +void R_DrawPSprite(DPSprite *pspr, AActor *owner, double ofsx, double ofsy, double ticfrac) { double tx; int x1; int x2; + double sx, sy; spritedef_t* sprdef; spriteframe_t* sprframe; FTextureID picnum; WORD flip; FTexture* tex; vissprite_t* vis; - static vissprite_t avis[NUMPSPRITES + 1]; - static vissprite_t *avisp[countof(avis)]; - bool noaccel; + bool noaccel; + bool isweapon; + static TArray avis; - assert(pspnum >= 0 && pspnum < NUMPSPRITES); - - if (avisp[0] == NULL) - { - for (unsigned i = 0; i < countof(avis); ++i) - { - avisp[i] = &avis[i]; - } - } + if (avis.Size() < vispspindex + 1) + avis.Reserve(avis.Size() - vispspindex + 1); // decide which patch to use - if ( (unsigned)psp->sprite >= (unsigned)sprites.Size ()) + if ((unsigned)pspr->GetSprite() >= (unsigned)sprites.Size()) { - DPrintf ("R_DrawPSprite: invalid sprite number %i\n", psp->sprite); + DPrintf("R_DrawPSprite: invalid sprite number %i\n", pspr->GetSprite()); return; } - sprdef = &sprites[psp->sprite]; - if (psp->frame >= sprdef->numframes) + sprdef = &sprites[pspr->GetSprite()]; + if (pspr->GetFrame() >= sprdef->numframes) { - DPrintf ("R_DrawPSprite: invalid sprite frame %i : %i\n", psp->sprite, psp->frame); + DPrintf("R_DrawPSprite: invalid sprite frame %i : %i\n", pspr->GetSprite(), pspr->GetFrame()); return; } - sprframe = &SpriteFrames[sprdef->spriteframes + psp->frame]; + sprframe = &SpriteFrames[sprdef->spriteframes + pspr->GetFrame()]; picnum = sprframe->Texture[0]; flip = sprframe->Flip & 1; @@ -1319,15 +1319,33 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, double sx, double if (tex->UseType == FTexture::TEX_Null) return; + isweapon = ((pspr->GetID() > 0 && pspr->GetID() < ps_targetcenter) || + (pspr->GetID() >= NUMPSPRITES && pspr->GetCaller() && pspr->GetCaller()->IsKindOf(RUNTIME_CLASS(AWeapon)))); + + if (pspr->firstTic) + { // Can't interpolate the first tic. + pspr->firstTic = false; + pspr->oldx = pspr->x; + pspr->oldy = pspr->y; + } + + 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; + } + // calculate edges of the shape - tx = sx - (320 / 2); + tx = sx - BASEXCENTER; tx -= tex->GetScaledLeftOffset(); x1 = xs_RoundToInt(CenterX + tx * pspritexscale); // off the right side if (x1 > viewwidth) - return; + return; tx += tex->GetScaledWidth(); x2 = xs_RoundToInt(CenterX + tx * pspritexscale); @@ -1335,9 +1353,9 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, double sx, double // off the left side if (x2 <= 0) return; - + // store information in a vissprite - vis = avisp[NUMPSPRITES]; + vis = &avis[vispspindex]; vis->renderflags = owner->renderflags; vis->floorclip = 0; @@ -1345,14 +1363,14 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, double sx, double if (camera->player && (RenderTarget != screen || viewheight == RenderTarget->GetHeight() || - (RenderTarget->GetWidth() > 320 && !st_scale))) + (RenderTarget->GetWidth() > (BASEXCENTER * 2) && !st_scale))) { // Adjust PSprite for fullscreen views - AWeapon *weapon = NULL; - if (camera->player != NULL) + AWeapon *weapon = nullptr; + if (camera->player != nullptr) { weapon = camera->player->ReadyWeapon; } - if (pspnum <= ps_flash && weapon != NULL && weapon->YAdjust != 0) + if (isweapon && weapon != nullptr && weapon->YAdjust != 0) { if (RenderTarget != screen || viewheight == RenderTarget->GetHeight()) { @@ -1360,11 +1378,11 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, double sx, double } else { - vis->texturemid -= StatusBar->GetDisplacement () * weapon->YAdjust; + vis->texturemid -= StatusBar->GetDisplacement() * weapon->YAdjust; } } } - if (pspnum <= ps_flash) + if (isweapon) { // Move the weapon down for 1280x1024. vis->texturemid -= BaseRatioSizes[WidescreenRatio][2]; } @@ -1388,11 +1406,11 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, double sx, double } if (vis->x1 > x1) - vis->startfrac += vis->xiscale*(vis->x1-x1); + vis->startfrac += vis->xiscale*(vis->x1 - x1); noaccel = false; - FDynamicColormap *colormap_to_use = NULL; - if (pspnum <= ps_flash) + FDynamicColormap *colormap_to_use = nullptr; + if (isweapon) { vis->Style.Alpha = float(owner->Alpha); vis->Style.RenderStyle = owner->RenderStyle; @@ -1413,16 +1431,16 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, double sx, double { if (invertcolormap) { // Fade to white - mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(255,255,255), mybasecolormap->Desaturate); + mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(255, 255, 255), mybasecolormap->Desaturate); invertcolormap = false; } else { // Fade to black - mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(0,0,0), mybasecolormap->Desaturate); + mybasecolormap = GetSpecialLights(mybasecolormap->Color, MAKERGB(0, 0, 0), mybasecolormap->Desaturate); } } - if (realfixedcolormap != NULL) + if (realfixedcolormap != nullptr) { // fixed color vis->Style.colormap = realfixedcolormap->Colormap; } @@ -1436,25 +1454,25 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, double sx, double { vis->Style.colormap = mybasecolormap->Maps + fixedlightlev; } - else if (!foggy && psp->state->GetFullbright()) + else if (!foggy && pspr->GetState()->GetFullbright()) { // full bright vis->Style.colormap = mybasecolormap->Maps; // [RH] use basecolormap } else { // local light - vis->Style.colormap = mybasecolormap->Maps + (GETPALOOKUP (0, spriteshade) << COLORMAPSHIFT); + vis->Style.colormap = mybasecolormap->Maps + (GETPALOOKUP(0, spriteshade) << COLORMAPSHIFT); } } - if (camera->Inventory != NULL) + if (camera->Inventory != nullptr) { lighttable_t *oldcolormap = vis->Style.colormap; - camera->Inventory->AlterWeaponSprite (&vis->Style); + camera->Inventory->AlterWeaponSprite(&vis->Style); if (vis->Style.colormap != oldcolormap) { // 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 || + if (vis->Style.colormap < SpecialColormaps[0].Colormap || vis->Style.colormap > SpecialColormaps.Last().Colormap) { noaccel = true; @@ -1462,7 +1480,7 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, double sx, double // 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) + vis->Style.colormap >= mybasecolormap->Maps + NUMCOLORMAPS * 256) { noaccel = true; } @@ -1482,7 +1500,7 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, double sx, double } // If the main colormap has fixed lights, and this sprite is being drawn with that // colormap, disable acceleration so that the lights can remain fixed. - if (!noaccel && realfixedcolormap == NULL && + if (!noaccel && realfixedcolormap == nullptr && NormalLightHasFixedLights && mybasecolormap == &NormalLight && vis->pic->UseBasePalette()) { @@ -1505,18 +1523,19 @@ void R_DrawPSprite (pspdef_t* psp, int pspnum, AActor *owner, double sx, double style.CheckFuzz(); if (style.BlendOp != STYLEOP_Fuzz) { - VisPSpritesX1[pspnum] = x1; - VisPSpritesBaseColormap[pspnum] = colormap_to_use; - VisPSprites[pspnum] = vis; - swapvalues(avisp[pspnum], avisp[NUMPSPRITES]); + if (vispsprites.Size() < vispspindex + 1) + vispsprites.Reserve(vispsprites.Size() - vispspindex + 1); + + vispsprites[vispspindex].vis = vis; + vispsprites[vispspindex].basecolormap = colormap_to_use; + vispsprites[vispspindex].x1 = x1; + vispspindex++; return; } } - R_DrawVisSprite (vis); + R_DrawVisSprite(vis); } - - //========================================================================== // // R_DrawPlayerSprites @@ -1527,7 +1546,7 @@ void R_DrawPlayerSprites () { int i; int lightnum; - pspdef_t* psp; + DPSprite* psp; sector_t* sec = NULL; static sector_t tempsec; int floorlight, ceilinglight; @@ -1540,28 +1559,35 @@ void R_DrawPlayerSprites () (r_deathcamera && camera->health <= 0)) return; - if(fixedlightlev < 0 && viewsector->e && viewsector->e->XFloor.lightlist.Size()) { - for(i = viewsector->e->XFloor.lightlist.Size() - 1; i >= 0; i--) - if(ViewPos.Z <= viewsector->e->XFloor.lightlist[i].plane.Zat0()) { + if (fixedlightlev < 0 && viewsector->e && viewsector->e->XFloor.lightlist.Size()) + { + for (i = viewsector->e->XFloor.lightlist.Size() - 1; i >= 0; i--) + { + if (ViewPos.Z <= viewsector->e->XFloor.lightlist[i].plane.Zat0()) + { rover = viewsector->e->XFloor.lightlist[i].caster; - if(rover) { - if(rover->flags & FF_DOUBLESHADOW && ViewPos.Z <= rover->bottom.plane->Zat0()) + if (rover) + { + if (rover->flags & FF_DOUBLESHADOW && ViewPos.Z <= rover->bottom.plane->Zat0()) break; sec = rover->model; - if(rover->flags & FF_FADEWALLS) + if (rover->flags & FF_FADEWALLS) basecolormap = sec->ColorMap; else basecolormap = viewsector->e->XFloor.lightlist[i].extra_colormap; } break; } - if(!sec) { + } + if(!sec) + { sec = viewsector; basecolormap = sec->ColorMap; } floorlight = ceilinglight = sec->lightlevel; - } else { - // This used to use camera->Sector but due to interpolation that can be incorrect + } + else + { // This used to use camera->Sector but due to interpolation that can be incorrect // when the interpolated viewpoint is in a different sector than the camera. sec = R_FakeFlat (viewsector, &tempsec, &floorlight, &ceilinglight, false); @@ -1589,23 +1615,19 @@ void R_DrawPlayerSprites () CenterY = viewheight / 2; - P_BobWeapon (camera->player, &camera->player->psprites[ps_weapon], &ofsx, &ofsy, r_TicFracF); + P_BobWeapon (camera->player, &ofsx, &ofsy, r_TicFracF); // add all active psprites - for (i = 0, psp = camera->player->psprites; - i < NUMPSPRITES; - i++, psp++) + psp = camera->player->psprites; + while (psp) { // [RH] Don't draw the targeter's crosshair if the player already has a crosshair set. - if (psp->state && (i != ps_targetcenter || CrosshairImage == NULL)) + if (psp->GetID() != ps_targetcenter || CrosshairImage == nullptr) { - R_DrawPSprite (psp, i, camera, psp->sx + ofsx, psp->sy + ofsy); - } - // [RH] Don't bob the targeter. - if (i == ps_flash) - { - ofsx = ofsy = 0; + R_DrawPSprite(psp, camera, ofsx, ofsy, r_TicFracF); } + + psp = psp->GetNext(); } CenterY = centerhack; @@ -1623,65 +1645,62 @@ void R_DrawPlayerSprites () void R_DrawRemainingPlayerSprites() { - for (int i = 0; i < NUMPSPRITES; ++i) + for (unsigned int i = 0; i < vispspindex; i++) { vissprite_t *vis; - vis = VisPSprites[i]; - VisPSprites[i] = NULL; + vis = vispsprites[i].vis; + FDynamicColormap *colormap = vispsprites[i].basecolormap; + bool flip = vis->xiscale < 0; + FSpecialColormap *special = NULL; + PalEntry overlay = 0; + FColormapStyle colormapstyle; + bool usecolormapstyle = false; - if (vis != NULL) + if (vis->Style.colormap >= SpecialColormaps[0].Colormap && + vis->Style.colormap < SpecialColormaps[SpecialColormaps.Size()].Colormap) { - FDynamicColormap *colormap = VisPSpritesBaseColormap[i]; - bool flip = vis->xiscale < 0; - FSpecialColormap *special = NULL; - PalEntry overlay = 0; - FColormapStyle colormapstyle; - bool usecolormapstyle = false; - - if (vis->Style.colormap >= SpecialColormaps[0].Colormap && - vis->Style.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); - 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); - } - else - { - usecolormapstyle = true; - colormapstyle.Color = colormap->Color; - colormapstyle.Fade = colormap->Fade; - colormapstyle.Desaturate = colormap->Desaturate; - colormapstyle.FadeLevel = ((vis->Style.colormap - colormap->Maps) >> 8) / float(NUMCOLORMAPS); - } - screen->DrawTexture(vis->pic, - viewwindowx + VisPSpritesX1[i], - viewwindowy + viewheight/2 - vis->texturemid * vis->yscale - 0.5, - DTA_DestWidthF, FIXED2DBL(vis->pic->GetWidth() * vis->xscale), - DTA_DestHeightF, vis->pic->GetHeight() * vis->yscale, - DTA_Translation, TranslationToTable(vis->Translation), - DTA_FlipX, flip, - DTA_TopOffset, 0, - DTA_LeftOffset, 0, - DTA_ClipLeft, viewwindowx, - DTA_ClipTop, viewwindowy, - DTA_ClipRight, viewwindowx + viewwidth, - DTA_ClipBottom, viewwindowy + viewheight, - DTA_AlphaF, vis->Style.Alpha, - DTA_RenderStyle, vis->Style.RenderStyle, - DTA_FillColor, vis->FillColor, - DTA_SpecialColormap, special, - DTA_ColorOverlay, overlay.d, - DTA_ColormapStyle, usecolormapstyle ? &colormapstyle : NULL, - TAG_DONE); + // 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); + 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); + } + else + { + usecolormapstyle = true; + colormapstyle.Color = colormap->Color; + colormapstyle.Fade = colormap->Fade; + colormapstyle.Desaturate = colormap->Desaturate; + colormapstyle.FadeLevel = ((vis->Style.colormap - colormap->Maps) >> 8) / float(NUMCOLORMAPS); + } + screen->DrawTexture(vis->pic, + viewwindowx + vispsprites[i].x1, + viewwindowy + viewheight/2 - vis->texturemid * vis->yscale - 0.5, + DTA_DestWidthF, FIXED2DBL(vis->pic->GetWidth() * vis->xscale), + DTA_DestHeightF, vis->pic->GetHeight() * vis->yscale, + DTA_Translation, TranslationToTable(vis->Translation), + DTA_FlipX, flip, + DTA_TopOffset, 0, + DTA_LeftOffset, 0, + DTA_ClipLeft, viewwindowx, + DTA_ClipTop, viewwindowy, + DTA_ClipRight, viewwindowx + viewwidth, + DTA_ClipBottom, viewwindowy + viewheight, + DTA_AlphaF, vis->Style.Alpha, + DTA_RenderStyle, vis->Style.RenderStyle, + DTA_FillColor, vis->FillColor, + DTA_SpecialColormap, special, + DTA_ColorOverlay, overlay.d, + DTA_ColormapStyle, usecolormapstyle ? &colormapstyle : NULL, + TAG_DONE); } + + vispspindex = 0; } // diff --git a/src/r_things.h b/src/r_things.h index 1cf9b0200..29e69d3a5 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -130,7 +130,6 @@ void R_WallSpriteColumn (void (*drawfunc)(const BYTE *column, const FTexture::Sp void R_CacheSprite (spritedef_t *sprite); void R_SortVisSprites (int (*compare)(const void *, const void *), size_t first); void R_AddSprites (sector_t *sec, int lightlevel, int fakeside); -void R_AddPSprites (); void R_DrawSprites (); void R_ClearSprites (); void R_DrawMasked (); diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index afbc036a6..aaa4981eb 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -5706,15 +5706,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetTics) PARAM_ACTION_PROLOGUE; PARAM_INT(tics_to_set); - if (stateowner != self && self->player != NULL && stateowner->IsKindOf(RUNTIME_CLASS(AWeapon))) - { // Is this a weapon? Need to check psp states for a match, then. Blah. - for (int i = 0; i < NUMPSPRITES; ++i) + if (stateowner != self && self->player != nullptr && stateowner->IsKindOf(RUNTIME_CLASS(AInventory))) + { // Need to check psp states for a match, then. Blah. + DPSprite *pspr = self->player->psprites; + while (pspr) { - if (self->player->psprites[i].state == callingstate) + if (pspr->GetState() == callingstate) { - self->player->psprites[i].tics = tics_to_set; + pspr->Tics = tics_to_set; return 0; } + + pspr = pspr->GetNext(); } } // Just set tics for self. diff --git a/src/version.h b/src/version.h index 52b7ea0ba..5378c5721 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4546 +#define SAVEVER 4547 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)