diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index 577d283e..1d916dd4 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -665,7 +665,7 @@ extern OBJECTTYPE gTempObject; #define AC_IRONSIGHT 0x00400000 //4194304 // for attachable Iron Sights #define AC_FEEDER 0x00800000 //8388608 // allow external feeding #define AC_MODPOUCH 0x01000000 //16777216 // for new modular pouches -#define AC_MISC14 0x02000000 //33554432 +#define AC_RIFLEGRENADE 0x02000000 //33554432 // rifle grenades are oneshot grenade launchers that launch themselves (and need bullet) #define AC_MISC15 0x04000000 //67108864 #define AC_MISC16 0x08000000 //134217728 #define AC_MISC17 0x10000000 //268435456 diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index 770faa02..b99d3209 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -1959,11 +1959,16 @@ INT8 FindNonSmokeLaunchable( SOLDIERTYPE * pSoldier, UINT16 usWeapon ) OBJECTTYPE* FindLaunchableAttachment( OBJECTTYPE * pObj, UINT16 usWeapon ) { - if (pObj->exists() == true) { - for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { - if (ValidLaunchable( iter->usItem, usWeapon) && iter->exists()) + if (pObj->exists() == true) + { + for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) + { + if (iter->exists() ) { - return &(*iter); + if (ValidLaunchable( iter->usItem, usWeapon) ) + { + return &(*iter); + } } } } @@ -2282,7 +2287,7 @@ BOOLEAN ValidItemAttachmentSlot( OBJECTTYPE * pObj, UINT16 usAttachment, BOOLEAN { for(int i = 0;iusItem].usItemClass == IC_GUN && this == &(pSoldier->inv[ HANDPOS ]) ) + { + // get rifle grenade device + OBJECTTYPE* pRifleGrenadeDeviceObj = FindAttachment_GrenadeLauncher( this ); + + // if it exists... + if ( pRifleGrenadeDeviceObj ) + { + // check if it now has a launchable grenade attached + OBJECTTYPE* pRiflefileGrenade = FindLaunchableAttachment( this, pRifleGrenadeDeviceObj->usItem); + + // if that grenade is of the same type as the item we attached, adjust firing mode + if ( pRiflefileGrenade && pRiflefileGrenade->usItem == attachmentObject.usItem ) + { + pSoldier->bWeaponMode = WM_ATTACHED_GL; + } + } + } } } @@ -11402,12 +11427,14 @@ INT16 GetFlashSuppressorStatus( OBJECTTYPE * pObj ) BOOLEAN IsGrenadeLauncherAttached( OBJECTTYPE * pObj, UINT8 subObject ) { - if (pObj->exists() == true) { + if (pObj->exists() == true) + { if (Item[pObj->usItem].grenadelauncher ) return TRUE; - for (attachmentList::iterator iter = (*pObj)[subObject]->attachments.begin(); iter != (*pObj)[subObject]->attachments.end(); ++iter) { - if (Item[iter->usItem].grenadelauncher && iter->exists() ) + for (attachmentList::iterator iter = (*pObj)[subObject]->attachments.begin(); iter != (*pObj)[subObject]->attachments.end(); ++iter) + { + if (iter->exists() && (Item[iter->usItem].grenadelauncher || IsAttachmentClass( iter->usItem, AC_RIFLEGRENADE ) ) ) { return TRUE; } @@ -11418,12 +11445,26 @@ BOOLEAN IsGrenadeLauncherAttached( OBJECTTYPE * pObj, UINT8 subObject ) OBJECTTYPE* FindAttachment_GrenadeLauncher( OBJECTTYPE * pObj ) { - if (pObj->exists() == true) { + if (pObj->exists() == true) + { + // Flugente: as it is now possible to have both a grenade launcher and a rifle grenade attached to a gun, the rifle grenade has priority. We thus have to search for it first + for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) + { + if (iter->exists() ) + { + if ( IsAttachmentClass(iter->usItem, AC_RIFLEGRENADE) ) + { + return &(*iter); + } + } + } + if (Item[pObj->usItem].grenadelauncher ) return pObj; - for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { - if (Item[iter->usItem].grenadelauncher && iter->exists() ) + for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) + { + if (iter->exists() && Item[iter->usItem].grenadelauncher ) { return( &(*iter) ); } @@ -11431,14 +11472,29 @@ OBJECTTYPE* FindAttachment_GrenadeLauncher( OBJECTTYPE * pObj ) } return( 0 ); } + INT16 GetGrenadeLauncherStatus( OBJECTTYPE * pObj ) { - if (pObj->exists() == true) { + if (pObj->exists() == true) + { + // Flugente: as it is now possible to have both a grenade launcher and a rifle grenade attached to a gun, the rifle grenade has priority. We thus have to search for it first + for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) + { + if (iter->exists() ) + { + if ( IsAttachmentClass(iter->usItem, AC_RIFLEGRENADE) ) + { + return( (*iter)[0]->data.objectStatus ); + } + } + } + if (Item[pObj->usItem].grenadelauncher ) return (*pObj)[0]->data.objectStatus; - for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { - if (Item[iter->usItem].grenadelauncher && iter->exists()) + for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) + { + if (iter->exists() && Item[iter->usItem].grenadelauncher ) { return( (*iter)[0]->data.objectStatus ); } @@ -11446,14 +11502,29 @@ INT16 GetGrenadeLauncherStatus( OBJECTTYPE * pObj ) } return( ITEM_NOT_FOUND ); } + UINT16 GetAttachedGrenadeLauncher( OBJECTTYPE * pObj ) { - if (pObj->exists() == true) { + if (pObj->exists() == true) + { + // Flugente: as it is now possible to have both a grenade launcher and a rifle grenade attached to a gun, the rifle grenade has priority. We thus have to search for it first + for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) + { + if (iter->exists() ) + { + if ( IsAttachmentClass(iter->usItem, AC_RIFLEGRENADE) ) + { + return( (UINT16) Item[iter->usItem].uiIndex ); + } + } + } + if (Item[pObj->usItem].grenadelauncher ) return pObj->usItem; - for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { - if (Item[iter->usItem].grenadelauncher && iter->exists()) + for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) + { + if (iter->exists() && Item[iter->usItem].grenadelauncher ) { return( (UINT16) Item[iter->usItem].uiIndex ); } @@ -11466,8 +11537,9 @@ UINT16 GetAttachedUnderBarrel( OBJECTTYPE * pObj ) { if (pObj->exists() == true) { - for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { - if ((Item[iter->usItem].usItemClass & (IC_GUN | IC_BLADE) ) && iter->exists()) + for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) + { + if (iter->exists() && (Item[iter->usItem].usItemClass & (IC_GUN | IC_BLADE) )) { return( (UINT16) Item[iter->usItem].uiIndex ); } @@ -11479,8 +11551,9 @@ BOOLEAN IsUnderBarrelAttached( OBJECTTYPE * pObj, UINT8 subObject ) { if (pObj->exists() == true) { - for (attachmentList::iterator iter = (*pObj)[subObject]->attachments.begin(); iter != (*pObj)[subObject]->attachments.end(); ++iter) { - if (Item[iter->usItem].usItemClass & (IC_GUN | IC_BLADE) && iter->exists() ) + for (attachmentList::iterator iter = (*pObj)[subObject]->attachments.begin(); iter != (*pObj)[subObject]->attachments.end(); ++iter) + { + if (iter->exists() && Item[iter->usItem].usItemClass & (IC_GUN | IC_BLADE) ) { return TRUE; } @@ -11493,8 +11566,9 @@ OBJECTTYPE* FindAttachment_UnderBarrel( OBJECTTYPE * pObj ) { if (pObj->exists() == true) { - for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { - if (Item[iter->usItem].usItemClass & (IC_GUN | IC_BLADE) && iter->exists() ) + for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) + { + if (iter->exists() && Item[iter->usItem].usItemClass & (IC_GUN | IC_BLADE) ) { return( &(*iter) ); } @@ -11507,8 +11581,9 @@ INT16 GetUnderBarrelStatus( OBJECTTYPE * pObj ) { if (pObj->exists() == true) { - for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { - if (Item[iter->usItem].usItemClass & (IC_GUN | IC_BLADE) && iter->exists()) + for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) + { + if (iter->exists() && Item[iter->usItem].usItemClass & (IC_GUN | IC_BLADE) ) { return( (*iter)[0]->data.objectStatus ); } diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 6efb536b..a2d8e92f 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -12995,6 +12995,16 @@ void SOLDIERTYPE::ReLoadSoldierAnimationDueToHandItemChange( UINT16 usOldItem, U this->bWeaponMode = WM_AUTOFIRE; this->bDoAutofire = 1; } + + // Flugente: if using a rifle grenade device, and a grenade i equipped, only grenade launching is allowed + if ( HasAttachmentOfClass( &(this->inv[HANDPOS]), AC_RIFLEGRENADE) ) + { + OBJECTTYPE* pRifleGrenadeDeviceObj = FindAttachment_GrenadeLauncher( &(this->inv[HANDPOS]) ); + + if ( pRifleGrenadeDeviceObj && FindLaunchableAttachment( &(this->inv[HANDPOS]), pRifleGrenadeDeviceObj->usItem) ) + this->bWeaponMode = WM_ATTACHED_GL; + } + if ( Item[ usNewItem ].twohanded && Weapon[ usNewItem ].HeavyGun && gGameExternalOptions.ubAllowAlternativeWeaponHolding == 3 ) this->bScopeMode = USE_ALT_WEAPON_HOLD; else diff --git a/Tactical/UI Cursors.cpp b/Tactical/UI Cursors.cpp index d987b0d1..99edd7fd 100644 --- a/Tactical/UI Cursors.cpp +++ b/Tactical/UI Cursors.cpp @@ -2632,6 +2632,16 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier ) if ( pSoldier->bWeaponMode == WM_ATTACHED_GL ) { + // Flugente: if using a rifle grenade, only allow firing if there is a bullet in the gun's magazine (required for firing) + if ( HasAttachmentOfClass( &(pSoldier->inv[HANDPOS]), AC_RIFLEGRENADE) ) + { + OBJECTTYPE* pObj = &(pSoldier->inv[HANDPOS]); + if ( (*pObj)[0]->data.gun.ubGunShotsLeft> 0 ) + return( TRAJECTORYCURS ); + else + return( INVALIDCURS ); + } + return( TRAJECTORYCURS ); } if ( pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || ( pSoldier->bWeaponMode == WM_BURST && Item[pSoldier->inv[HANDPOS].usItem].grenadelauncher ) ) diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index 116c4005..eff2ee76 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -3803,8 +3803,8 @@ BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo ) OBJECTTYPE Launchable; OBJECTTYPE * pObj; UINT16 usItemNum; - INT32 iID; - REAL_OBJECT *pObject; + INT32 iID; + REAL_OBJECT *pObject; DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("UseLauncher, target = %d", sTargetGridNo) ); usItemNum = pSoldier->usAttackingWeapon; @@ -3855,7 +3855,7 @@ BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo ) attachmentList::iterator iterend = (*pObj)[0]->attachments.end(); for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter) { - if ( iter->exists() && Item[ iter->usItem ].usItemClass & (IC_LAUNCHER|IC_LAUNCHER) ) + if ( iter->exists() && Item[ iter->usItem ].usItemClass & IC_LAUNCHER ) { pgunobj = &(*iter); break; @@ -3885,6 +3885,16 @@ BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo ) GunIncreaseHeat( pgunobj ); + // Flugente: if we are using a rifle grenade, we also use up one of the gun's bullets + if ( IsAttachmentClass(pgunobj->usItem, AC_RIFLEGRENADE) ) + { + if ( (*pObj)[0]->data.gun.ubGunShotsLeft> 0 ) + (*pObj)[0]->data.gun.ubGunShotsLeft--; + + // increase heat, as we 'fired' a bullet + GunIncreaseHeat( pObj ); + } + if ( Weapon[ usItemNum ].sSound != NO_WEAPON_SOUND ) { if (Item[ usItemNum ].usItemClass == IC_GUN ) @@ -10435,6 +10445,22 @@ BOOLEAN IsGunWeaponModeCapable( OBJECTTYPE* pObject, WeaponMode bWpnMode, SOLDIE { DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("IsGunWeaponModeCapable: weapon mode=%d",bWpnMode)); + // Flugente: if have a riflegrenade device attached, and that thing has a launchable grenade, block all other firing modes + if ( HasAttachmentOfClass(pObject, AC_RIFLEGRENADE) ) + { + OBJECTTYPE* pRifleGrenadeDeviceObj = FindAttachment_GrenadeLauncher(pObject); + + if ( pRifleGrenadeDeviceObj && FindLaunchableAttachment( pObject, pRifleGrenadeDeviceObj->usItem) ) + { + if ( bWpnMode == WM_ATTACHED_GL ) + { + return TRUE; + } + else + return FALSE; + } + } + switch(bWpnMode) { case WM_NORMAL: @@ -10453,11 +10479,11 @@ BOOLEAN IsGunWeaponModeCapable( OBJECTTYPE* pObject, WeaponMode bWpnMode, SOLDIE // return (FindAttachment( &(pSoldier->inv[ubHandPos]), UNDER_GLAUNCHER ) != 0 && FindLaunchableAttachment( &(pSoldier->inv[ubHandPos]), UNDER_GLAUNCHER ) != 0 ); //return (!Item[pSoldier->inv[ubHandPos].usItem].grenadelauncher && IsGrenadeLauncherAttached( &(pSoldier->inv[ubHandPos]) ) && FindLaunchableAttachment( &(pSoldier->inv[ubHandPos]), GetAttachedGrenadeLauncher( &(pSoldier->inv[ubHandPos]) )) != 0 ); - return (!Item[pObject->usItem].grenadelauncher && IsGrenadeLauncherAttached( pObject ) && FindLaunchableAttachment( pObject, GetAttachedGrenadeLauncher( pObject )) != 0 ); + return ( (!Item[pObject->usItem].grenadelauncher && !IsAttachmentClass(pObject->usItem, AC_RIFLEGRENADE) ) && IsGrenadeLauncherAttached( pObject ) && FindLaunchableAttachment( pObject, GetAttachedGrenadeLauncher( pObject )) != 0 ); case WM_ATTACHED_GL_BURST: //return (!Item[pSoldier->inv[ubHandPos].usItem].grenadelauncher && IsGrenadeLauncherAttached( &(pSoldier->inv[ubHandPos]) ) && Weapon[GetAttachedGrenadeLauncher(&pSoldier->inv[ubHandPos])].ubShotsPerBurst > 0 && FindLaunchableAttachment( &(pSoldier->inv[ubHandPos]), GetAttachedGrenadeLauncher( &(pSoldier->inv[ubHandPos]))) != 0 ); - return (!Item[pObject->usItem].grenadelauncher && IsGrenadeLauncherAttached( pObject ) && Weapon[GetAttachedGrenadeLauncher(pObject)].ubShotsPerBurst > 0 && FindLaunchableAttachment( pObject, GetAttachedGrenadeLauncher( pObject)) != 0 ); + return ( (!Item[pObject->usItem].grenadelauncher && !HasAttachmentOfClass( pObject, AC_RIFLEGRENADE ) ) && IsGrenadeLauncherAttached( pObject ) && Weapon[GetAttachedGrenadeLauncher(pObject)].ubShotsPerBurst > 0 && FindLaunchableAttachment( pObject, GetAttachedGrenadeLauncher( pObject)) != 0 ); case WM_ATTACHED_GL_AUTO: return FALSE; @@ -11053,6 +11079,16 @@ void ChangeWeaponMode( SOLDIERTYPE * pSoldier ) pSoldier->bWeaponMode = WM_AUTOFIRE; else pSoldier->bWeaponMode = WM_NORMAL; + + if ( HasAttachmentOfClass( &(pSoldier->inv[HANDPOS]), AC_RIFLEGRENADE) ) + { + OBJECTTYPE* pRifleGrenadeDeviceObj = FindAttachment_GrenadeLauncher( &(pSoldier->inv[HANDPOS]) ); + + if ( pRifleGrenadeDeviceObj && FindLaunchableAttachment( &(pSoldier->inv[HANDPOS]), pRifleGrenadeDeviceObj->usItem) ) + { + pSoldier->bWeaponMode = WM_ATTACHED_GL; + } + } } } // Changed by ADB, rev 1513