diff --git a/src/d_player.h b/src/d_player.h index e27bf1087f..1e7eef61ed 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -221,6 +221,10 @@ enum WF_WEAPONRELOADOK = 1 << 5, // [XA] Okay to reload this weapon. WF_WEAPONZOOMOK = 1 << 6, // [XA] Okay to use weapon zoom function. WF_REFIRESWITCHOK = 1 << 7, // Mirror WF_WEAPONSWITCHOK for A_ReFire + WF_USER1OK = 1 << 8, // [MC] Allow pushing of custom state buttons 1-4 + WF_USER2OK = 1 << 9, + WF_USER3OK = 1 << 10, + WF_USER4OK = 1 << 11, }; #define WPIECE1 1 diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 74b10206b2..80e1744e64 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -307,6 +307,7 @@ public: virtual FState *GetAltAtkState (bool hold); virtual FState *GetRelState (); virtual FState *GetZoomState (); + virtual FState *GetUserState(int state); virtual void PostMorphWeapon (); virtual void EndPowerup (); diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index fae232557b..79546737e5 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -703,6 +703,30 @@ FState *AWeapon::GetZoomState () return FindState(NAME_Zoom); } +//=========================================================================== +// +// AWeapon :: GetUserState +// +//=========================================================================== + +FState *AWeapon::GetUserState(int state) +{ + switch (state) + { + case 4: + return FindState(NAME_User4); + case 3: + return FindState(NAME_User3); + case 2: + return FindState(NAME_User2); + case 1: + return FindState(NAME_User1); + default: + return NULL; + } +} + + /* Weapon giver ***********************************************************/ IMPLEMENT_CLASS(AWeaponGiver) diff --git a/src/namedef.h b/src/namedef.h index 22dbe1b516..f9d436f287 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -221,6 +221,10 @@ xx(Flash) xx(AltFlash) xx(Reload) xx(Zoom) +xx(User1) +xx(User2) +xx(User3) +xx(User4) // State names used by ASwitchableDecoration xx(Active) diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 63f3bc6486..df05b9611f 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -95,7 +95,8 @@ void P_SetPsprite (player_t *player, int position, FState *state, bool nofunctio if (position == ps_weapon && !nofunction) { // A_WeaponReady will re-set these as needed - player->WeaponState &= ~(WF_WEAPONREADY | WF_WEAPONREADYALT | WF_WEAPONBOBBING | WF_WEAPONSWITCHOK | WF_WEAPONRELOADOK | WF_WEAPONZOOMOK); + player->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]; @@ -349,6 +350,34 @@ void P_ZoomWeapon (player_t *player, FState *state) P_SetPsprite (player, ps_weapon, state); } +//-------------------------------------------------------------------------- - +// +// PROC P_UserStateWeapon +// +//--------------------------------------------------------------------------- + +void P_UserStateWeapon(player_t *player, FState *state, int userstate) +{ + if (!userstate) + return; + + AWeapon *weapon; + if (player->Bot == NULL && bot_observer) + return; + + weapon = player->ReadyWeapon; + if (weapon == NULL) + return; + + if (state == NULL) + { + state = weapon->GetUserState(userstate); + } + if (state != NULL) + P_SetPsprite(player, ps_weapon, state); +} + + //--------------------------------------------------------------------------- // // PROC P_DropWeapon @@ -573,13 +602,24 @@ void DoReadyWeaponToReload (AActor *self) void DoReadyWeaponToZoom (AActor *self) { - // Prepare for reload action. + // Prepare for zoom action. player_t *player; if (self && (player = self->player)) player->WeaponState |= WF_WEAPONZOOMOK; return; } +void DoReadyWeaponToUser(AActor *self, int userStates) +{ + // Prepare for user state action. + player_t *player; + if (self && (player = self->player) && userStates) + { + player->WeaponState |= userStates; + } + return; +} + // This function replaces calls to A_WeaponReady in other codepointers. void DoReadyWeapon(AActor *self) { @@ -588,18 +628,23 @@ void DoReadyWeapon(AActor *self) DoReadyWeaponToSwitch(self); DoReadyWeaponToReload(self); DoReadyWeaponToZoom(self); + DoReadyWeaponToUser(self, (WF_USER1OK + WF_USER2OK + WF_USER3OK + WF_USER4OK)); } enum EWRF_Options { - WRF_NoBob = 1, - WRF_NoSwitch = 2, - WRF_NoPrimary = 4, - WRF_NoSecondary = 8, + WRF_NoBob = 1, + WRF_NoSwitch = 1 << 1, + WRF_NoPrimary = 1 << 2, + WRF_NoSecondary = 1 << 3, WRF_NoFire = WRF_NoPrimary + WRF_NoSecondary, - WRF_AllowReload = 16, - WRF_AllowZoom = 32, - WRF_DisableSwitch = 64, + WRF_AllowReload = 1 << 4, + WRF_AllowZoom = 1 << 5, + WRF_DisableSwitch = 1 << 6, + WRF_User1 = 1 << 7, + WRF_User2 = 1 << 8, + WRF_User3 = 1 << 9, + WRF_User4 = 1 << 10, }; DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_WeaponReady) @@ -613,6 +658,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_WeaponReady) if ((paramflags & WRF_AllowReload)) DoReadyWeaponToReload(self); if ((paramflags & WRF_AllowZoom)) DoReadyWeaponToZoom(self); + int userStates = 0; + if (paramflags & WRF_User1) userStates |= WF_USER1OK; + if (paramflags & WRF_User2) userStates |= WF_USER2OK; + if (paramflags & WRF_User3) userStates |= WF_USER3OK; + if (paramflags & WRF_User4) userStates |= WF_USER4OK; + if (userStates) DoReadyWeaponToUser(self, userStates); + DoReadyWeaponDisableSwitch(self, paramflags & WRF_DisableSwitch); } @@ -732,6 +784,40 @@ void P_CheckWeaponZoom (player_t *player) } } +//--------------------------------------------------------------------------- +// +// PROC P_CheckWeaponUserState +// +// The player can use the weapon's user state functionalities. +// +//--------------------------------------------------------------------------- + +void P_CheckWeaponUserState(player_t *player) +{ + AWeapon *weapon = player->ReadyWeapon; + + if (weapon == NULL) + return; + + // Check for user state(s). + if ((player->WeaponState & WF_USER1OK) && (player->cmd.ucmd.buttons & BT_USER1)) + { + P_UserStateWeapon(player, NULL, 1); + } + else if ((player->WeaponState & WF_USER2OK) && (player->cmd.ucmd.buttons & BT_USER2)) + { + P_UserStateWeapon(player, NULL, 2); + } + else if ((player->WeaponState & WF_USER3OK) && (player->cmd.ucmd.buttons & BT_USER3)) + { + P_UserStateWeapon(player, NULL, 3); + } + else if ((player->WeaponState & WF_USER4OK) && (player->cmd.ucmd.buttons & BT_USER4)) + { + P_UserStateWeapon(player, NULL, 4); + } +} + //--------------------------------------------------------------------------- // // PROC A_ReFire @@ -1103,6 +1189,10 @@ void P_MovePsprites (player_t *player) { P_CheckWeaponZoom (player); } + if (player->WeaponState & (WF_USER1OK | WF_USER2OK | WF_USER3OK | WF_USER4OK)) + { + P_CheckWeaponUserState(player); + } } } diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 956ed119f7..32a45e54ce 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -129,6 +129,11 @@ const int WRF_NOFIRE = WRF_NOPRIMARY | WRF_NOSECONDARY; const int WRF_ALLOWRELOAD = 16; const int WRF_ALLOWZOOM = 32; const int WRF_DISABLESWITCH = 64; +const int WRF_USER1 = 128; +const int WRF_USER2 = 256; +const int WRF_USER3 = 512; +const int WRF_USER4 = 1024; +const int WRF_ALLUSER = WRF_USER1 | WRF_USER2 | WRF_USER3 | WRF_USER4; // Morph constants const int MRF_ADDSTAMINA = 1; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 244b146912..087c067d14 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -435,8 +435,12 @@ OptionMenu "CustomizeControls" StaticText "Controls", 1 Control "Fire", "+attack" Control "Secondary Fire", "+altattack" - Control "Weapon Reload", "+reload" - Control "Weapon Zoom", "+zoom" + Control "Weapon Reload", "+reload" + Control "Weapon Zoom", "+zoom" + Control "Weapon State 1", "+user1" + Control "Weapon State 2", "+user2" + Control "Weapon State 3", "+user3" + Control "Weapon State 4", "+user4" Control "Use / Open", "+use" Control "Move forward", "+forward" Control "Move backward", "+back"