Generalized the psprites implementation
This commit is contained in:
parent
bd396ccb7c
commit
1966b61b8f
25 changed files with 744 additions and 478 deletions
477
src/p_pspr.cpp
477
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; i<MAXPLAYERS; i++)
|
||||
for (int i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
pspdef_t *pspdef = players[i].psprites;
|
||||
for (int j = 0;j < NUMPSPRITES; j++)
|
||||
DPSprite *pspr = players[i].psprites;
|
||||
while (pspr)
|
||||
{
|
||||
pspdef[j].processPending = true;
|
||||
pspr->processPending = 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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue