diff --git a/src/d_player.h b/src/d_player.h index 011335a85..7d8dbf380 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -100,7 +100,6 @@ public: void ActivateMorphWeapon (); AWeapon *PickNewWeapon (PClassActor *ammotype); AWeapon *BestWeapon (PClassActor *ammotype); - void CheckWeaponSwitch(PClassActor *ammotype); void GiveDeathmatchInventory (); void FilterCoopRespawnInventory (APlayerPawn *oldplayer); @@ -109,7 +108,6 @@ public: // These are virtual on the script side only. void PlayIdle(); - void PlayAttacking (); void PlayAttacking2 (); const char *GetSoundClass () const; diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index 5086d7832..440c67f9b 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -446,46 +446,6 @@ FState *AWeapon::GetReadyState () return nullptr; } -//=========================================================================== -// -// AWeapon :: GetAtkState -// -//=========================================================================== - -FState *AWeapon::GetAtkState (bool hold) -{ - IFVIRTUAL(AWeapon, GetAtkState) - { - VMValue params[2] = { (DObject*)this, hold }; - VMReturn ret; - FState *retval; - ret.PointerAt((void**)&retval); - VMCall(func, params, 2, &ret, 1); - return retval; - } - return nullptr; -} - -//=========================================================================== -// -// AWeapon :: GetAtkState -// -//=========================================================================== - -FState *AWeapon::GetAltAtkState (bool hold) -{ - IFVIRTUAL(AWeapon, GetAltAtkState) - { - VMValue params[2] = { (DObject*)this, hold }; - VMReturn ret; - FState *retval; - ret.PointerAt((void**)&retval); - VMCall(func, params, 2, &ret, 1); - return retval; - } - return nullptr; -} - //=========================================================================== // // AWeapon :: GetStateForButtonName diff --git a/src/g_inventory/a_weapons.h b/src/g_inventory/a_weapons.h index 9841d1a5a..9b397e402 100644 --- a/src/g_inventory/a_weapons.h +++ b/src/g_inventory/a_weapons.h @@ -132,8 +132,6 @@ public: FState *GetUpState (); FState *GetDownState (); FState *GetReadyState (); - FState *GetAtkState (bool hold); - FState *GetAltAtkState (bool hold); FState *GetStateForButtonName (FName button); diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index f2c4b9590..bd2e4219c 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -126,6 +126,7 @@ DEFINE_FIELD(DPSprite, Next) DEFINE_FIELD(DPSprite, Owner) DEFINE_FIELD(DPSprite, Sprite) DEFINE_FIELD(DPSprite, Frame) +DEFINE_FIELD(DPSprite, Flags) DEFINE_FIELD(DPSprite, ID) DEFINE_FIELD(DPSprite, processPending) DEFINE_FIELD(DPSprite, x) @@ -601,82 +602,6 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, BringUpWeapon) return 0; } -//--------------------------------------------------------------------------- -// -// PROC P_FireWeapon -// -//--------------------------------------------------------------------------- - -void P_FireWeapon (player_t *player, FState *state) -{ - AWeapon *weapon; - - // [SO] 9/2/02: People were able to do an awful lot of damage - // when they were observers... - if (player->Bot == nullptr && bot_observer) - { - return; - } - - weapon = player->ReadyWeapon; - if (weapon == nullptr || !weapon->CheckAmmo (AWeapon::PrimaryFire, true)) - { - return; - } - - player->WeaponState &= ~WF_WEAPONBOBBING; - player->mo->PlayAttacking (); - weapon->bAltFire = false; - if (state == nullptr) - { - state = weapon->GetAtkState(!!player->refire); - } - P_SetPsprite(player, PSP_WEAPON, state); - if (!(weapon->WeaponFlags & WIF_NOALERT)) - { - P_NoiseAlert (player->mo, player->mo, false); - } -} - -//--------------------------------------------------------------------------- -// -// PROC P_FireWeaponAlt -// -//--------------------------------------------------------------------------- - -void P_FireWeaponAlt (player_t *player, FState *state) -{ - AWeapon *weapon; - - // [SO] 9/2/02: People were able to do an awful lot of damage - // when they were observers... - if (player->Bot == nullptr && bot_observer) - { - return; - } - - weapon = player->ReadyWeapon; - if (weapon == nullptr || weapon->FindState(NAME_AltFire) == nullptr || !weapon->CheckAmmo (AWeapon::AltFire, true)) - { - return; - } - - player->WeaponState &= ~WF_WEAPONBOBBING; - player->mo->PlayAttacking (); - weapon->bAltFire = true; - - if (state == nullptr) - { - state = weapon->GetAltAtkState(!!player->refire); - } - - P_SetPsprite(player, PSP_WEAPON, state); - if (!(weapon->WeaponFlags & WIF_NOALERT)) - { - P_NoiseAlert (player->mo, player->mo, false); - } -} - //--------------------------------------------------------------------------- // // PROC P_DropWeapon @@ -935,78 +860,6 @@ DEFINE_ACTION_FUNCTION(AStateProvider, A_WeaponReady) return 0; } -//--------------------------------------------------------------------------- -// -// PROC P_CheckWeaponFire -// -// The player can fire the weapon. -// [RH] This was in A_WeaponReady before, but that only works well when the -// weapon's ready frames have a one tic delay. -// -//--------------------------------------------------------------------------- - -void P_CheckWeaponFire (player_t *player) -{ - AWeapon *weapon = player->ReadyWeapon; - - if (weapon == NULL) - return; - - // Check for fire. Some weapons do not auto fire. - if ((player->WeaponState & WF_WEAPONREADY) && (player->cmd.ucmd.buttons & BT_ATTACK)) - { - if (!player->attackdown || !(weapon->WeaponFlags & WIF_NOAUTOFIRE)) - { - player->attackdown = true; - P_FireWeapon (player, NULL); - return; - } - } - else if ((player->WeaponState & WF_WEAPONREADYALT) && (player->cmd.ucmd.buttons & BT_ALTATTACK)) - { - if (!player->attackdown || !(weapon->WeaponFlags & WIF_NOAUTOFIRE)) - { - player->attackdown = true; - P_FireWeaponAlt (player, NULL); - return; - } - } - else - { - player->attackdown = false; - } -} - -//--------------------------------------------------------------------------- -// -// PROC P_CheckWeaponSwitch -// -// The player can change to another weapon at this time. -// [GZ] This was cut from P_CheckWeaponFire. -// -//--------------------------------------------------------------------------- - -void P_CheckWeaponSwitch (player_t *player) -{ - if (player == NULL) - { - return; - } - if ((player->WeaponState & WF_DISABLESWITCH) || // Weapon changing has been disabled. - player->morphTics != 0) // Morphed classes cannot change weapons. - { // ...so throw away any pending weapon requests. - player->PendingWeapon = WP_NOCHANGE; - } - - // Put the weapon away if the player has a pending weapon or has died, and - // we're at a place in the state sequence where dropping the weapon is okay. - if ((player->PendingWeapon != WP_NOCHANGE || player->health <= 0) && - player->WeaponState & WF_WEAPONSWITCHOK) - { - P_DropWeapon(player); - } -} - //--------------------------------------------------------------------------- // // PROC P_CheckWeaponButtons @@ -1046,53 +899,13 @@ static void P_CheckWeaponButtons (player_t *player) } } -//--------------------------------------------------------------------------- -// -// PROC A_ReFire -// -// The player can re-fire the weapon without lowering it entirely. -// -//--------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AStateProvider, A_ReFire) +DEFINE_ACTION_FUNCTION(APlayerPawn, CheckWeaponButtons) { - PARAM_ACTION_PROLOGUE(AStateProvider); - PARAM_STATE_ACTION_DEF(state); - A_ReFire(self, state); + PARAM_SELF_PROLOGUE(APlayerPawn); + P_CheckWeaponButtons(self->player); return 0; } -void A_ReFire(AActor *self, FState *state) -{ - player_t *player = self->player; - bool pending; - - if (NULL == player) - { - return; - } - pending = player->PendingWeapon != WP_NOCHANGE && (player->WeaponState & WF_REFIRESWITCHOK); - if ((player->cmd.ucmd.buttons & BT_ATTACK) - && !player->ReadyWeapon->bAltFire && !pending && player->health > 0) - { - player->refire++; - P_FireWeapon (player, state); - } - else if ((player->cmd.ucmd.buttons & BT_ALTATTACK) - && player->ReadyWeapon->bAltFire && !pending && player->health > 0) - { - player->refire++; - P_FireWeaponAlt (player, state); - } - else - { - player->refire = 0; - player->ReadyWeapon->CheckAmmo (player->ReadyWeapon->bAltFire - ? AWeapon::AltFire : AWeapon::PrimaryFire, true); - } -} - - //--------------------------------------------------------------------------- // // PROC A_OverlayOffset @@ -1459,86 +1272,6 @@ void P_SetupPsprites(player_t *player, bool startweaponup) P_BringUpWeapon (player); } -//------------------------------------------------------------------------ -// -// PROC P_MovePsprites -// -// Called every tic by player thinking routine -// -//------------------------------------------------------------------------ - -void player_t::TickPSprites() -{ - DPSprite *pspr = psprites; - while (pspr) - { - // 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. - if ((pspr->Caller == nullptr || - (pspr->Caller->IsKindOf(RUNTIME_CLASS(AInventory)) && barrier_cast(pspr->Caller)->Owner != pspr->Owner->mo) || - (pspr->Caller->IsKindOf(NAME_Weapon) && pspr->Caller != pspr->Owner->ReadyWeapon))) - { - pspr->Destroy(); - } - else - { - pspr->Tick(); - } - - pspr = pspr->Next; - } - - if ((health > 0) || (ReadyWeapon != nullptr && !(ReadyWeapon->WeaponFlags & WIF_NODEATHINPUT))) - { - if (ReadyWeapon == nullptr) - { - if (PendingWeapon != WP_NOCHANGE) - P_BringUpWeapon(this); - } - else - { - P_CheckWeaponSwitch(this); - if (WeaponState & (WF_WEAPONREADY | WF_WEAPONREADYALT)) - { - P_CheckWeaponFire(this); - } - // Check custom buttons - P_CheckWeaponButtons(this); - } - } -} - -DEFINE_ACTION_FUNCTION(_PlayerInfo, TickPSprites) -{ - PARAM_SELF_STRUCT_PROLOGUE(player_t); - self->TickPSprites(); - return 0; -} -//------------------------------------------------------------------------ -// -// -// -//------------------------------------------------------------------------ - -void DPSprite::Tick() -{ - if (processPending) - { - // drop tic count and possibly change state - if (Tics != -1) // a -1 tic count never changes - { - Tics--; - - // [BC] Apply double firing speed. - if ((Flags & PSPF_POWDOUBLE) && Tics && (Owner->mo->FindInventory (PClass::FindActor(NAME_PowerDoubleFiringSpeed), true))) - Tics--; - - if (!Tics) - SetState(State->GetNextState()); - } - } -} - //------------------------------------------------------------------------ // // diff --git a/src/p_pspr.h b/src/p_pspr.h index 615af3c3c..5964ace20 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -103,7 +103,6 @@ private: DPSprite () {} void Serialize(FSerializer &arc); - void Tick(); public: // must be public to be able to generate the field export tables. Grrr... TObjPtr Caller; diff --git a/src/p_user.cpp b/src/p_user.cpp index e2d803afb..7ca8258b2 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1217,6 +1217,12 @@ AWeapon *APlayerPawn::BestWeapon(PClassActor *ammotype) return bestMatch; } +DEFINE_ACTION_FUNCTION(APlayerPawn, BestWeapon) +{ + PARAM_SELF_PROLOGUE(APlayerPawn); + PARAM_CLASS(ammo, AActor); + ACTION_RETURN_POINTER(self->BestWeapon(ammo)); +} //=========================================================================== // // APlayerPawn :: PickNewWeapon @@ -1246,38 +1252,6 @@ AWeapon *APlayerPawn::PickNewWeapon(PClassActor *ammotype) return best; } - -//=========================================================================== -// -// APlayerPawn :: CheckWeaponSwitch -// -// Checks if weapons should be changed after picking up ammo -// -//=========================================================================== - -void APlayerPawn::CheckWeaponSwitch(PClassActor *ammotype) -{ - if (!player->userinfo.GetNeverSwitch() && - player->PendingWeapon == WP_NOCHANGE && - (player->ReadyWeapon == NULL || - (player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))) - { - AWeapon *best = BestWeapon (ammotype); - if (best != NULL && (player->ReadyWeapon == NULL || - best->SelectionOrder < player->ReadyWeapon->SelectionOrder)) - { - player->PendingWeapon = best; - } - } -} - -DEFINE_ACTION_FUNCTION(APlayerPawn, CheckWeaponSwitch) -{ - PARAM_SELF_PROLOGUE(APlayerPawn); - PARAM_POINTER(ammotype, PClassActor); - self->CheckWeaponSwitch(ammotype); - return 0; -} //=========================================================================== // // APlayerPawn :: GiveDeathmatchInventory @@ -1541,15 +1515,6 @@ void APlayerPawn::PlayIdle () } } -void APlayerPawn::PlayAttacking () -{ - IFVIRTUAL(APlayerPawn, PlayAttacking) - { - VMValue params[1] = { (DObject*)this }; - VMCall(func, params, 1, nullptr, 0); - } -} - void APlayerPawn::PlayAttacking2 () { IFVIRTUAL(APlayerPawn, PlayAttacking2) diff --git a/wadsrc/static/zscript/inventory/stateprovider.txt b/wadsrc/static/zscript/inventory/stateprovider.txt index 4d842dc80..abbc8db71 100644 --- a/wadsrc/static/zscript/inventory/stateprovider.txt +++ b/wadsrc/static/zscript/inventory/stateprovider.txt @@ -8,7 +8,43 @@ class StateProvider : Inventory native action native void A_RailAttack(int damage, int spawnofs_xy = 0, bool useammo = true, color color1 = 0, color color2 = 0, int flags = 0, double maxdiff = 0, class pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class spawnclass = "none", double spawnofs_z = 0, int spiraloffset = 270, int limit = 0); action native void A_WeaponReady(int flags = 0); - action native void A_ReFire(statelabel flash = null); + //--------------------------------------------------------------------------- + // + // PROC A_ReFire + // + // The player can re-fire the weapon without lowering it entirely. + // + //--------------------------------------------------------------------------- + + action void A_ReFire(statelabel flash = null) + { + let player = self.player; + bool pending; + + if (NULL == player) + { + return; + } + pending = player.PendingWeapon != WP_NOCHANGE && (player.WeaponState & WF_REFIRESWITCHOK); + if ((player.cmd.buttons & BT_ATTACK) + && !player.ReadyWeapon.bAltFire && !pending && player.health > 0) + { + player.refire++; + player.mo.FireWeapon(ResolveState(flash)); + } + else if ((player.cmd.buttons & BT_ALTATTACK) + && player.ReadyWeapon.bAltFire && !pending && player.health > 0) + { + player.refire++; + player.mo.FireWeaponAlt(ResolveState(flash)); + } + else + { + player.refire = 0; + player.ReadyWeapon.CheckAmmo (player.ReadyWeapon.bAltFire? Weapon.AltFire : Weapon.PrimaryFire, true); + } + } + action native state A_CheckForReload(int counter, statelabel label, bool dontincrement = false); action native void A_ResetReloadCounter(); diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 1caf03c8e..380ffd2d8 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -218,6 +218,224 @@ class PlayerPawn : Actor native return -1, -1; } + + //=========================================================================== + // + // APlayerPawn :: CheckWeaponSwitch + // + // Checks if weapons should be changed after picking up ammo + // + //=========================================================================== + + void CheckWeaponSwitch(Class ammotype) + { + let player = self.player; + if (!player.GetNeverSwitch() && player.PendingWeapon == WP_NOCHANGE && + (player.ReadyWeapon == NULL || player.ReadyWeapon.bWimpy_Weapon)) + { + let best = BestWeapon (ammotype); + if (best != NULL && (player.ReadyWeapon == NULL || + best.SelectionOrder < player.ReadyWeapon.SelectionOrder)) + { + player.PendingWeapon = best; + } + } + } + + //--------------------------------------------------------------------------- + // + // PROC P_FireWeapon + // + //--------------------------------------------------------------------------- + + virtual void FireWeapon (State stat) + { + let player = self.player; + + // [SO] 9/2/02: People were able to do an awful lot of damage + // when they were observers... + if (player.Bot == null && bot_observer) + { + return; + } + + let weapn = player.ReadyWeapon; + if (weapn == null || !weapn.CheckAmmo (Weapon.PrimaryFire, true)) + { + return; + } + + player.WeaponState &= ~WF_WEAPONBOBBING; + PlayAttacking (); + weapn.bAltFire = false; + if (stat == null) + { + stat = weapn.GetAtkState(!!player.refire); + } + player.SetPsprite(PSP_WEAPON, stat); + if (!weapn.bNoAlert) + { + SoundAlert (self, false); + } + } + + //--------------------------------------------------------------------------- + // + // PROC P_FireWeaponAlt + // + //--------------------------------------------------------------------------- + + virtual void FireWeaponAlt (State stat) + { + // [SO] 9/2/02: People were able to do an awful lot of damage + // when they were observers... + if (player.Bot == null && bot_observer) + { + return; + } + + let weapn = player.ReadyWeapon; + if (weapn == null || weapn.FindState('AltFire') == null || !weapn.CheckAmmo (Weapon.AltFire, true)) + { + return; + } + + player.WeaponState &= ~WF_WEAPONBOBBING; + PlayAttacking (); + weapn.bAltFire = true; + + if (stat == null) + { + stat = weapn.GetAltAtkState(!!player.refire); + } + + player.SetPsprite(PSP_WEAPON, stat); + if (!weapn.bNoAlert) + { + SoundAlert (self, false); + } + } + + //--------------------------------------------------------------------------- + // + // PROC P_CheckWeaponFire + // + // The player can fire the weapon. + // [RH] This was in A_WeaponReady before, but that only works well when the + // weapon's ready frames have a one tic delay. + // + //--------------------------------------------------------------------------- + + void CheckWeaponFire () + { + let player = self.player; + let weapon = player.ReadyWeapon; + + if (weapon == NULL) + return; + + // Check for fire. Some weapons do not auto fire. + if ((player.WeaponState & WF_WEAPONREADY) && (player.cmd.buttons & BT_ATTACK)) + { + if (!player.attackdown || !weapon.bNoAutofire) + { + player.attackdown = true; + FireWeapon (NULL); + return; + } + } + else if ((player.WeaponState & WF_WEAPONREADYALT) && (player.cmd.buttons & BT_ALTATTACK)) + { + if (!player.attackdown || !weapon.bNoAutofire) + { + player.attackdown = true; + FireWeaponAlt (NULL); + return; + } + } + else + { + player.attackdown = false; + } + } + + //--------------------------------------------------------------------------- + // + // PROC P_CheckWeaponChange + // + // The player can change to another weapon at this time. + // [GZ] This was cut from P_CheckWeaponFire. + // + //--------------------------------------------------------------------------- + + virtual void CheckWeaponChange () + { + let player = self.player; + if ((player.WeaponState & WF_DISABLESWITCH) || // Weapon changing has been disabled. + player.morphTics != 0) // Morphed classes cannot change weapons. + { // ...so throw away any pending weapon requests. + player.PendingWeapon = WP_NOCHANGE; + } + + // Put the weapon away if the player has a pending weapon or has died, and + // we're at a place in the state sequence where dropping the weapon is okay. + if ((player.PendingWeapon != WP_NOCHANGE || player.health <= 0) && + player.WeaponState & WF_WEAPONSWITCHOK) + { + player.DropWeapon(); + } + } + + //------------------------------------------------------------------------ + // + // PROC P_MovePsprites + // + // Called every tic by player thinking routine + // + //------------------------------------------------------------------------ + + virtual void TickPSprites() + { + let player = self.player; + let pspr = player.psprites; + while (pspr) + { + // 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. + if ((pspr.Caller == null || + (pspr.Caller is "Inventory" && Inventory(pspr.Caller).Owner != pspr.Owner.mo) || + (pspr.Caller is "Weapon" && pspr.Caller != pspr.Owner.ReadyWeapon))) + { + pspr.Destroy(); + } + else + { + pspr.Tick(); + } + + pspr = pspr.Next; + } + + if ((health > 0) || (player.ReadyWeapon != null && !player.ReadyWeapon.bNoDeathInput)) + { + if (player.ReadyWeapon == null) + { + if (player.PendingWeapon != WP_NOCHANGE) + player.BringUpWeapon(); + } + else + { + CheckWeaponChange(); + if (player.WeaponState & (WF_WEAPONREADY | WF_WEAPONREADYALT)) + { + CheckWeaponFire(); + } + // Check custom buttons + CheckWeaponButtons(); + } + } + } + //========================================================================== // // P_DeathThink @@ -231,7 +449,7 @@ class PlayerPawn : Actor native double delta; player.Uncrouch(); - player.TickPSprites(); + TickPSprites(); player.onground = (pos.Z <= floorz); if (self is "PlayerChunk") @@ -1022,7 +1240,7 @@ class PlayerPawn : Actor native CheckUse(); CheckUndoMorph(); // Cycle psprites - player.TickPSprites(); + TickPSprites(); // Other Counters if (player.damagecount) player.damagecount--; @@ -1049,12 +1267,13 @@ class PlayerPawn : Actor native native clearscope int GetMaxHealth(bool withupgrades = false) const; native bool ResetAirSupply (bool playgasp = false); - native void CheckWeaponSwitch(class item); native clearscope static String GetPrintableDisplayName(Class cls); native void CheckMusicChange(); native void CalcHeight (); native void CheckEnvironment(); native void CheckUse(); + native void CheckWeaponButtons(); + native Weapon BestWeapon(class ammotype); } @@ -1112,6 +1331,26 @@ class PSprite : Object native play native void SetState(State newstate, bool pending = false); + //------------------------------------------------------------------------ + // + // + // + //------------------------------------------------------------------------ + + void Tick() + { + if (processPending) + { + // drop tic count and possibly change state + if (Tics != -1) // a -1 tic count never changes + { + Tics--; + // [BC] Apply double firing speed. + if (bPowDouble && Tics && (Owner.mo.FindInventory ("PowerDoubleFiringSpeed", true))) Tics--; + if (!Tics) SetState(CurState.NextState); + } + } + } } enum EPlayerState @@ -1243,7 +1482,6 @@ struct PlayerInfo native play // this is what internally is known as player_t native bool GetNoAutostartMap() const; native void SetFOV(float fov); native clearscope bool HasWeaponsInSlot(int slot) const; - native void TickPSprites(); bool IsTotallyFrozen() {