diff --git a/Tactical/Interface Items.cpp b/Tactical/Interface Items.cpp index 532c288a5..ce693284c 100644 --- a/Tactical/Interface Items.cpp +++ b/Tactical/Interface Items.cpp @@ -6060,7 +6060,8 @@ void ItemDescAmmoCallback(GUI_BUTTON *btn,INT32 reason) gfItemAmmoDown = FALSE; //CHRISL: We dont' want to be able to reload guns using the ammo crate from this function - if((gpItemPointer != NULL && Magazine[Item[gpItemPointer->usItem].ubClassIndex].ubMagType >= AMMO_BOX) || !EnoughPoints(gpItemDescSoldier, APBPConstants[AP_RELOAD_GUN], 0, TRUE))//dnl ch65 040913 + //Greysa: add check for ammo item + if( gpItemPointer != NULL && ( (Item[gpItemPointer->usItem].usItemClass != IC_AMMO || Magazine[Item[gpItemPointer->usItem].ubClassIndex].ubMagType >= AMMO_BOX) ) || !EnoughPoints(gpItemDescSoldier, APBPConstants[AP_RELOAD_GUN], 0, TRUE) )//dnl ch65 040913 { fInterfacePanelDirty = DIRTYLEVEL2; btn->uiFlags &= (~BUTTON_CLICKED_ON ); @@ -6083,7 +6084,8 @@ void ItemDescAmmoCallback(GUI_BUTTON *btn,INT32 reason) else { //holding an item - if(Magazine[Item[gpItemPointer->usItem].ubClassIndex].ubCalibre == Weapon[Item[gpItemDescObject->usItem].ubClassIndex].ubCalibre) + //Greysa: add check for ammo item + if( Item[gpItemPointer->usItem].usItemClass == IC_AMMO && Magazine[Item[gpItemPointer->usItem].ubClassIndex].ubCalibre == Weapon[Item[gpItemDescObject->usItem].ubClassIndex].ubCalibre ) { ReloadGun(gpItemDescSoldier, gpItemDescObject, gpItemPointer, ubStatusIndex); } diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index c8e802e87..890369a38 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -3872,13 +3872,113 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier, bool aReloadEvenIfNotEmpty ) { OBJECTTYPE *pObj, *pObj2; INT8 bSlot; - INT16 bAPCost; + INT16 bAPCost; BOOLEAN fRet = FALSE; CHECKF( pSoldier ); // Flugente: check for underbarrel weapons and use that object if necessary pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) ); + if (pSoldier->IsValidSecondHandShotForReloadingPurposes()) //check for valid second hand weapon for reloading purposes (something that doesn't use ammo) + { + pObj2 = pSoldier->GetUsedWeapon( &(pSoldier->inv[SECONDHANDPOS]) ); + } + else + { + pObj2 = NULL; + } + // Greysa: Check if weapon is jammed and unjam it first + if ((*pObj)[0]->data.gun.bGunAmmoStatus < 0 || ((pObj2 != NULL) && (*pObj2)[0]->data.gun.bGunAmmoStatus < 0)) + { + 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[pObj->usItem].EasyUnjam) + bChanceMod = 100; + else + bChanceMod = (INT8)(GetReliability(pObj) * 4); + + int iResult = SkillCheck(pSoldier, UNJAM_GUN_CHECK, bChanceMod); + + if (iResult > 0) + { + // 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); + PlayJA2Sample(Weapon[Item[pObj->usItem].ubClassIndex].ManualReloadSound, RATE_11025, SoundVolume(HIGHVOLUME, pSoldier->sGridNo), 1, SoundDir(pSoldier->sGridNo)); + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_UNJAMMED], pSoldier->GetName(), ItemNames[pObj->usItem]); + // merc voice feedback? + } + else + { + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_FAILED_UNJAM], pSoldier->GetName(), ItemNames[pObj->usItem]); + } + } + else + { + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_NO_AP_NO_UNJAM], pSoldier->GetName(), ItemNames[pObj->usItem]); + } + } + if ((pObj2 != NULL) && (*pObj2)[0]->data.gun.bGunAmmoStatus < 0) + { + if (EnoughPoints(pSoldier, APBPConstants[AP_UNJAM], APBPConstants[BP_UNJAM], FALSE)) + { + DeductPoints(pSoldier, APBPConstants[AP_UNJAM], APBPConstants[BP_UNJAM]); + + INT8 bChanceMod; + + if (Weapon[pObj2->usItem].EasyUnjam) + bChanceMod = 100; + else + bChanceMod = (INT8)(GetReliability(pObj2) * 4); + + int iResult = SkillCheck(pSoldier, UNJAM_GUN_CHECK, bChanceMod); + + if (iResult > 0) + { + // yay! unjammed the gun + (*pObj2)[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); + PlayJA2Sample(Weapon[Item[pObj2->usItem].ubClassIndex].ManualReloadSound, RATE_11025, SoundVolume(HIGHVOLUME, pSoldier->sGridNo), 1, SoundDir(pSoldier->sGridNo)); + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_UNJAMMED], pSoldier->GetName(), ItemNames[pObj2->usItem]); + // merc voice feedback? + } + else + { + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_FAILED_UNJAM], pSoldier->GetName(), ItemNames[pObj2->usItem]); + } + } + else + { + ScreenMsg(FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_NO_AP_NO_UNJAM], pSoldier->GetName(), ItemNames[pObj2->usItem]); + } + } + return FALSE; // Greysa: We want to skip reloading if we attempted to unjam, regardless of outcome. Return value doesn't seem to matter as there doesn't seem to be any actual checks on the returned value. I picked FALSE as actual reload hasn't occurred + } // manual recharge if ((*pObj)[0]->data.gun.ubGunShotsLeft && !((*pObj)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) ) @@ -3915,9 +4015,9 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier, bool aReloadEvenIfNotEmpty ) PlayJA2Sample( Weapon[ Item[pObj->usItem].ubClassIndex ].ManualReloadSound, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) ); - if ( pSoldier->IsValidSecondHandShot( ) ) + if (pObj2 != NULL)//( pSoldier->IsValidSecondHandShot( ) ) { - pObj2 = &(pSoldier->inv[SECONDHANDPOS]); + //pObj2 = &(pSoldier->inv[SECONDHANDPOS]); if ((*pObj2)[0]->data.gun.ubGunShotsLeft && !((*pObj2)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) ) { @@ -3930,9 +4030,9 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier, bool aReloadEvenIfNotEmpty ) } else { - if ( pSoldier->IsValidSecondHandShot( ) ) + if (pObj2 != NULL)//( pSoldier->IsValidSecondHandShot( ) ) { - pObj2 = &(pSoldier->inv[SECONDHANDPOS]); + //pObj2 = &(pSoldier->inv[SECONDHANDPOS]); if ((*pObj2)[0]->data.gun.ubGunShotsLeft && !((*pObj2)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) ) { @@ -3989,21 +4089,21 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier, bool aReloadEvenIfNotEmpty ) // if we are valid for two-pistol shooting (reloading) and we have enough APs still // then do a reload of both guns! // Flugente: only reload if it's empty, or we really want to - if ( pSoldier->IsValidSecondHandShotForReloadingPurposes() + if ( pObj2 != NULL //pSoldier->IsValidSecondHandShotForReloadingPurposes() && ( aReloadEvenIfNotEmpty || !EnoughAmmo( pSoldier, FALSE, SECONDHANDPOS ) ) ) { // Flugente: check for underbarrel weapons and use that object if necessary - pObj = pSoldier->GetUsedWeapon( &( pSoldier->inv[SECONDHANDPOS] ) ); + //pObj2 = pSoldier->GetUsedWeapon( &( pSoldier->inv[SECONDHANDPOS] ) ); bSlot = FindAmmoToReload( pSoldier, SECONDHANDPOS, NO_SLOT ); if ( bSlot != NO_SLOT ) { // ce would reload using this ammo! - bAPCost = GetAPsToReloadGunWithAmmo( pSoldier, pObj, &( pSoldier->inv[bSlot] ) ); + bAPCost = GetAPsToReloadGunWithAmmo( pSoldier, pObj2, &( pSoldier->inv[bSlot] ) ); if ( EnoughPoints( pSoldier, (INT16)bAPCost, 0, FALSE ) ) { // reload the 2nd gun too - fRet = ReloadGun( pSoldier, pObj, &( pSoldier->inv[bSlot] ) ); + fRet = ReloadGun( pSoldier, pObj2, &( pSoldier->inv[bSlot] ) ); } else { diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp index 9bdee0c15..adad80e86 100644 --- a/Tactical/Turn Based Input.cpp +++ b/Tactical/Turn Based Input.cpp @@ -4303,21 +4303,25 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) // Make auto reload with magazines from sector inventory case 'R': - HandleTBReloadAll(); - + if (fAlt && gusSelectedSoldier != NOBODY ) // Greysa: Moved here from 'r' to retain all functionality during testing. + { + if (CHEATER_CHEAT_LEVEL()) + { + ReloadWeapon(gusSelectedSoldier, gusSelectedSoldier->ubAttackingHand); + } + } + else + { + HandleTBReloadAll(); + } break; case 'r': if( gusSelectedSoldier != NOBODY ) { - if( fAlt ) //reload selected merc's weapon + if( fAlt ) { - if ( CHEATER_CHEAT_LEVEL( ) ) - { - ReloadWeapon( gusSelectedSoldier, gusSelectedSoldier->ubAttackingHand ); - } - else - HandleTBReload(); - } + HandleTBReload(); + } else if( fCtrl ) { if ( INFORMATION_CHEAT_LEVEL( ) ) diff --git a/i18n/_ChineseText.cpp b/i18n/_ChineseText.cpp index 2f951f6d3..1976fbe8d 100644 --- a/i18n/_ChineseText.cpp +++ b/i18n/_ChineseText.cpp @@ -2361,6 +2361,11 @@ CHAR16 Message[][STRING_LENGTH] = L"没有能够训练的民兵。", //L"No militia that can be drilled present.", L"%s 已经完全的探索了 %s。", //L"%s has fully explored %s." + + // The first %s is a merc name and the second %s is an item name + L"%s unjammed %s.", + L"%s failed to unjam %s.", + L"%s does not have enough APs to unjam %s." }; // the country and its noun in the game diff --git a/i18n/_DutchText.cpp b/i18n/_DutchText.cpp index 509040f7d..56283c9b6 100644 --- a/i18n/_DutchText.cpp +++ b/i18n/_DutchText.cpp @@ -2360,6 +2360,11 @@ CHAR16 Message[][STRING_LENGTH] = L"No militia that can be drilled present.", L"%s has fully explored %s.", // TODO.Translate + + // The first %s is a merc name and the second %s is an item name + L"%s unjammed %s.", + L"%s failed to unjam %s.", + L"%s does not have enough APs to unjam %s." }; // the country and its noun in the game diff --git a/i18n/_EnglishText.cpp b/i18n/_EnglishText.cpp index f3284709f..a93dc98c0 100644 --- a/i18n/_EnglishText.cpp +++ b/i18n/_EnglishText.cpp @@ -2361,6 +2361,11 @@ CHAR16 Message[][STRING_LENGTH] = L"No militia that can be drilled present.", L"%s has fully explored %s.", + + // The first %s is a merc name and the second %s is an item name + L"%s unjammed %s.", + L"%s failed to unjam %s.", + L"%s does not have enough APs to unjam %s." }; // the country and its noun in the game diff --git a/i18n/_FrenchText.cpp b/i18n/_FrenchText.cpp index a859908d8..7d47cf68c 100644 --- a/i18n/_FrenchText.cpp +++ b/i18n/_FrenchText.cpp @@ -2369,6 +2369,11 @@ CHAR16 Message[][STRING_LENGTH] = L"No militia that can be drilled present.", L"%s has fully explored %s.", // TODO.Translate + + // The first %s is a merc name and the second %s is an item name + L"%s unjammed %s.", + L"%s failed to unjam %s.", + L"%s does not have enough APs to unjam %s." }; // the country and its noun in the game // TODO.Translate diff --git a/i18n/_GermanText.cpp b/i18n/_GermanText.cpp index cfd6a7ed7..5fbec512a 100644 --- a/i18n/_GermanText.cpp +++ b/i18n/_GermanText.cpp @@ -2403,6 +2403,11 @@ CHAR16 Message[][STRING_LENGTH] = L"No militia that can be drilled present.", L"%s hat %s vollständig erkundet.", + + // The first %s is a merc name and the second %s is an item name + L"%s unjammed %s.", + L"%s failed to unjam %s.", + L"%s does not have enough APs to unjam %s." }; // the country and its noun in the game diff --git a/i18n/_ItalianText.cpp b/i18n/_ItalianText.cpp index a8da7833b..5411245db 100644 --- a/i18n/_ItalianText.cpp +++ b/i18n/_ItalianText.cpp @@ -2355,6 +2355,11 @@ CHAR16 Message[][STRING_LENGTH] = L"No militia that can be drilled present.", L"%s has fully explored %s.", // TODO.Translate + + // The first %s is a merc name and the second %s is an item name + L"%s unjammed %s.", + L"%s failed to unjam %s.", + L"%s does not have enough APs to unjam %s." }; // the country and its noun in the game diff --git a/i18n/_PolishText.cpp b/i18n/_PolishText.cpp index 526206375..46dd6b536 100644 --- a/i18n/_PolishText.cpp +++ b/i18n/_PolishText.cpp @@ -2367,6 +2367,11 @@ CHAR16 Message[][STRING_LENGTH] = L"No militia that can be drilled present.", L"%s has fully explored %s.", // TODO.Translate + + // The first %s is a merc name and the second %s is an item name + L"%s unjammed %s.", + L"%s failed to unjam %s.", + L"%s does not have enough APs to unjam %s." }; // the country and its noun in the game diff --git a/i18n/_RussianText.cpp b/i18n/_RussianText.cpp index ae91c3121..4a4e8c468 100644 --- a/i18n/_RussianText.cpp +++ b/i18n/_RussianText.cpp @@ -2361,6 +2361,11 @@ CHAR16 Message[][STRING_LENGTH] = L"No militia that can be drilled present.", L"%s has fully explored %s.", // TODO.Translate + + // The first %s is a merc name and the second %s is an item name + L"%s unjammed %s.", + L"%s failed to unjam %s.", + L"%s does not have enough APs to unjam %s." }; // the country and its noun in the game diff --git a/i18n/include/Text.h b/i18n/include/Text.h index 470398476..0c890d6b3 100644 --- a/i18n/include/Text.h +++ b/i18n/include/Text.h @@ -612,6 +612,10 @@ enum STR_ASSIGNMENT_EXPLORATION_DONE, + STR_UNJAMMED, + STR_FAILED_UNJAM, + STR_NO_AP_NO_UNJAM, + TEXT_NUM_STR_MESSAGE, };