From bb55299ff6101adae3ed67a394e2e73d308cf564 Mon Sep 17 00:00:00 2001 From: Greysa <52637570+Greysa@users.noreply.github.com> Date: Sat, 21 Mar 2026 22:06:00 +1100 Subject: [PATCH] Basic implementaion of unjamming on reload hotkey. TODO: text strings check dual wielding --- Tactical/Items.cpp | 55 ++++++++++++++++++++++++++++++++++- Tactical/Turn Based Input.cpp | 22 +++++++++----- 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index c8e802e8..a66336ac 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -3872,7 +3872,7 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier, bool aReloadEvenIfNotEmpty ) { OBJECTTYPE *pObj, *pObj2; INT8 bSlot; - INT16 bAPCost; + INT16 bAPCost; BOOLEAN fRet = FALSE; CHECKF( pSoldier ); @@ -3880,6 +3880,59 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier, bool aReloadEvenIfNotEmpty ) // Flugente: check for underbarrel weapons and use that object if necessary pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) ); + // Greysa: Check if weapon is jammed and unjam it first + // Greysa: need to implement and test duel wield jamming and unjamming + if ((*pObj)[0]->data.gun.bGunAmmoStatus < 0) + { + //borrowed from Weapons.cpp + if (EnoughPoints(pSoldier, APBPConstants[AP_UNJAM], APBPConstants[BP_UNJAM], FALSE)) + { + DeductPoints(pSoldier, APBPConstants[AP_UNJAM], APBPConstants[BP_UNJAM]); + + INT8 bChanceMod; + + if (Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].EasyUnjam) + bChanceMod = 100; + else + bChanceMod = (INT8)(GetReliability(pObj) * 4); + + int iResult = SkillCheck(pSoldier, UNJAM_GUN_CHECK, bChanceMod); + + // sevenfm: AI always unjams successfully + // Greysa: no AI check required here + if (iResult > 0)// || !(pSoldier->flags.uiStatusFlags & SOLDIER_PC)) + { + // yay! unjammed the gun + (*pObj)[0]->data.gun.bGunAmmoStatus *= -1; + + // MECHANICAL/DEXTERITY GAIN: Unjammed a gun + + if (bChanceMod < 100) // don't give exp for unjamming an easily unjammable gun + { + StatChange(pSoldier, MECHANAMT, 5, FALSE); + StatChange(pSoldier, DEXTAMT, 5, FALSE); + } + + DirtyMercPanelInterface(pSoldier, DIRTYLEVEL2); // Greysa: what does this do? + PlayJA2Sample(Weapon[Item[pObj->usItem].ubClassIndex].ManualReloadSound, RATE_11025, SoundVolume(HIGHVOLUME, pSoldier->sGridNo), 1, SoundDir(pSoldier->sGridNo)); + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s unjammed %s.", pSoldier->GetName(), ItemNames[pObj->usItem]); + //print unjam message and merc voice feedback + // Greysa: We want to skip reloading if we unjammed + return FALSE; // Greysa: Do we return false or true here to skip rest of reload? I think true, but test this! Also, need to figure out animation + } + else + { + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s failed to unjam %s.", pSoldier->GetName(), ItemNames[pObj->usItem]); + return FALSE; + } + } + else + { + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s does not have enough APs to unjam %s.", pSoldier->GetName(), ItemNames[pObj->usItem]); + return FALSE; + } + } + // manual recharge if ((*pObj)[0]->data.gun.ubGunShotsLeft && !((*pObj)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) ) { diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp index 9bdee0c1..866b5e10 100644 --- a/Tactical/Turn Based Input.cpp +++ b/Tactical/Turn Based Input.cpp @@ -4309,15 +4309,21 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) case 'r': if( gusSelectedSoldier != NOBODY ) { - if( fAlt ) //reload selected merc's weapon + // Greysa: Commented out for testing purposes. + //if( fAlt ) //reload selected merc's weapon + //{ + // if ( CHEATER_CHEAT_LEVEL( ) ) + // { + // ReloadWeapon( gusSelectedSoldier, gusSelectedSoldier->ubAttackingHand ); + // } + // else + // HandleTBReload(); + //} + // Remove this once testing and above commenting finished with. + if( fAlt ) { - if ( CHEATER_CHEAT_LEVEL( ) ) - { - ReloadWeapon( gusSelectedSoldier, gusSelectedSoldier->ubAttackingHand ); - } - else - HandleTBReload(); - } + HandleTBReload(); + } else if( fCtrl ) { if ( INFORMATION_CHEAT_LEVEL( ) )