- New Feature: Allow attaching and using underbarrel weapons (by Flugente & JMich)

o You can now attach weapons to other weapons (only one at a time). Comes with additional fire modes (by cycling in tactical with key 'b')
o A new item, the KAC masterkey, demonstrates this. Raider and Kelly have one in their starting kit 4. (pics by smeagol)
o works both in OCTh and NCTH. Aiming is done via the main gun, but all physical values of the attached gun are considered.
o reload an underbarrel gun while it is attached by dropping the ammo on the main gun while an underbarrel fire mode is active. Cycle firemodes in tactical by pressing 'b'
o Attachments to underbarrel weapons are inseparable while weapon is attached, but they do work.

- Overheating weapons additions (by Flugente)
o New option OVERHEATING_DISPLAY_THERMOMETER_RED_OFFSET controls how red the temperature bar is at the beginning.
o New option OVERHEATING_SET_ZERO_UPON_NEW_SECTOR sets temperature of items on the floor to zero if loading a new sector

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5133 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2012-04-01 15:36:55 +00:00
parent e4514b2cff
commit 7a40ecd777
31 changed files with 984 additions and 580 deletions
+3 -1
View File
@@ -1320,8 +1320,10 @@ void LoadGameExternalOptions()
// Flugente FTW 1: These settings control the behavior of Weapon Overheating, its severity, and its display. // Flugente FTW 1: These settings control the behavior of Weapon Overheating, its severity, and its display.
gGameExternalOptions.fDisplayOverheatThermometer = iniReader.ReadBoolean("Tactical Weapon Overheating Settings","OVERHEATING_DISPLAY_THERMOMETER",TRUE); gGameExternalOptions.fDisplayOverheatThermometer = iniReader.ReadBoolean("Tactical Weapon Overheating Settings","OVERHEATING_DISPLAY_THERMOMETER",TRUE);
gGameExternalOptions.ubOverheatThermometerRedOffset = iniReader.ReadInteger("Tactical Weapon Overheating Settings","OVERHEATING_DISPLAY_THERMOMETER_RED_OFFSET", 100, 0, 255);
gGameExternalOptions.iCooldownModificatorLonelyBarrel = iniReader.ReadFloat ("Tactical Weapon Overheating Settings","OVERHEATING_COOLDOWN_MODIFICATOR_LONELYBARREL", 1.15f, 1.0f, 10.0f); gGameExternalOptions.iCooldownModificatorLonelyBarrel = iniReader.ReadFloat ("Tactical Weapon Overheating Settings","OVERHEATING_COOLDOWN_MODIFICATOR_LONELYBARREL", 1.15f, 1.0f, 10.0f);
gGameExternalOptions.fSetZeroUponNewSector = iniReader.ReadBoolean("Tactical Weapon Overheating Settings","OVERHEATING_SET_ZERO_UPON_NEW_SECTOR",TRUE);
//################# Strategic Gamestart Settings ################## //################# Strategic Gamestart Settings ##################
//Lalien: Game starting time //Lalien: Game starting time
+3 -1
View File
@@ -1072,8 +1072,10 @@ typedef struct
// Flugente FTW 1: Weapon Overheating // Flugente FTW 1: Weapon Overheating
BOOLEAN fDisplayOverheatThermometer; // Should a 'thermometer' for guns and replacable barrels be displayed? BOOLEAN fDisplayOverheatThermometer; // Should a 'thermometer' for guns and replacable barrels be displayed?
UINT8 ubOverheatThermometerRedOffset; // amount of red colour while temperature is below threshold
FLOAT iCooldownModificatorLonelyBarrel; // Cooldown modificator for barrels alone in the landscape ;-) FLOAT iCooldownModificatorLonelyBarrel; // Cooldown modificator for barrels alone in the landscape ;-)
BOOLEAN fSetZeroUponNewSector; // Should loading a new sector set the temperatures of all items in the old sector to zero? (this doesn't apply to inventories)
BOOLEAN fWeaponResting; // Should it be possible to rest your weapon on structures in crouched position? BOOLEAN fWeaponResting; // Should it be possible to rest your weapon on structures in crouched position?
BOOLEAN fDisplayWeaponRestingIndicator; // Should a little indicator show if the weapon is currently rested on something? BOOLEAN fDisplayWeaponRestingIndicator; // Should a little indicator show if the weapon is currently rested on something?
UINT8 ubProneModifierPercentage; // for boni, use ubProneModifierPercentage*boni[PRONE] + (100 - ubProneModifierPercentage)*boni[CROUCHED] UINT8 ubProneModifierPercentage; // for boni, use ubProneModifierPercentage*boni[PRONE] + (100 - ubProneModifierPercentage)*boni[CROUCHED]
+2
View File
@@ -6113,6 +6113,8 @@ BOOLEAN HandleDefiniteUnloadingOfWorld( UINT8 ubUnloadCode )
//if we arent loading a saved game //if we arent loading a saved game
if( !(gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) ) if( !(gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) )
{ {
// Flugente: Set temperares of all items in the old sector to zero before entering a new sector
CoolDownWorldItems( TRUE );
// Save the current sectors Item list to a temporary file, if its not the first time in // Save the current sectors Item list to a temporary file, if its not the first time in
SaveCurrentSectorsInformationToTempItemFile(); SaveCurrentSectorsInformationToTempItemFile();
+3 -1
View File
@@ -594,7 +594,9 @@ void DisplayRangeToTarget( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
pSoldier->bTargetLevel = bTempTargetLevel; pSoldier->bTargetLevel = bTempTargetLevel;
// HEADROCK HAM 3.6: Calculate Gun Range using formula. // HEADROCK HAM 3.6: Calculate Gun Range using formula.
UINT16 usGunRange = GunRange(&pSoldier->inv[HANDPOS], pSoldier ); // SANDRO - added argument // Flugente: we might be equipped with an underbarrel gun....
OBJECTTYPE* pObjhand = pSoldier->GetUsedWeapon(&pSoldier->inv[HANDPOS]);
UINT16 usGunRange = GunRange(pObjhand, pSoldier ); // SANDRO - added argument
swprintf( zOutputString, gzDisplayCoverText[title], usRange / 10, usGunRange / 10, uiHitChance ); swprintf( zOutputString, gzDisplayCoverText[title], usRange / 10, usGunRange / 10, uiHitChance );
//Display the msg //Display the msg
+10 -9
View File
@@ -2531,15 +2531,18 @@ void UIHandleMercAttack( SOLDIERTYPE *pSoldier , SOLDIERTYPE *pTargetSoldier, IN
INT32 iHandleReturn; INT32 iHandleReturn;
INT32 sTargetGridNo; INT32 sTargetGridNo;
INT8 bTargetLevel; INT8 bTargetLevel;
UINT16 usItem; UINT16 usItem;
LEVELNODE *pIntNode; LEVELNODE* pIntNode;
STRUCTURE *pStructure; STRUCTURE* pStructure;
INT32 sGridNo, sNewGridNo; INT32 sGridNo, sNewGridNo;
UINT8 ubItemCursor; UINT8 ubItemCursor;
// get cursor // get cursor
ubItemCursor = GetActionModeCursor( pSoldier ); ubItemCursor = GetActionModeCursor( pSoldier );
OBJECTTYPE* pObj = pSoldier->GetUsedWeapon(&pSoldier->inv[HANDPOS]);
usItem = pSoldier->GetUsedWeaponNumber(&pSoldier->inv[HANDPOS]);
if ( !(gTacticalStatus.uiFlags & INCOMBAT) && pTargetSoldier && Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass & IC_WEAPON ) if ( !(gTacticalStatus.uiFlags & INCOMBAT) && pTargetSoldier && Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass & IC_WEAPON )
{ {
if ( NPCFirstDraw( pSoldier, pTargetSoldier ) ) if ( NPCFirstDraw( pSoldier, pTargetSoldier ) )
@@ -2555,8 +2558,6 @@ void UIHandleMercAttack( SOLDIERTYPE *pSoldier , SOLDIERTYPE *pTargetSoldier, IN
// Set aim time to one in UI // Set aim time to one in UI
pSoldier->aiData.bAimTime = (pSoldier->aiData.bShownAimTime ); pSoldier->aiData.bAimTime = (pSoldier->aiData.bShownAimTime );
usItem = pSoldier->inv[ HANDPOS ].usItem;
// ATE: Check if we are targeting an interactive tile, and adjust gridno accordingly... // ATE: Check if we are targeting an interactive tile, and adjust gridno accordingly...
pIntNode = GetCurInteractiveTileGridNoAndStructure( &sGridNo, &pStructure ); pIntNode = GetCurInteractiveTileGridNoAndStructure( &sGridNo, &pStructure );
@@ -2642,11 +2643,11 @@ void UIHandleMercAttack( SOLDIERTYPE *pSoldier , SOLDIERTYPE *pTargetSoldier, IN
if (pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO ) if (pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )
{ {
iHandleReturn = HandleItem( pSoldier, sTargetGridNo, bTargetLevel, GetAttachedGrenadeLauncher(&pSoldier->inv[ HANDPOS ]), TRUE ); iHandleReturn = HandleItem( pSoldier, sTargetGridNo, bTargetLevel, GetAttachedGrenadeLauncher(pObj), TRUE );
} }
else else
{ {
iHandleReturn = HandleItem( pSoldier, sTargetGridNo, bTargetLevel, pSoldier->inv[ HANDPOS ].usItem, TRUE ); iHandleReturn = HandleItem( pSoldier, sTargetGridNo, bTargetLevel, usItem, TRUE );
} }
if ( iHandleReturn < 0 ) if ( iHandleReturn < 0 )
+87 -66
View File
@@ -2646,7 +2646,7 @@ void INVRenderSilhouette( UINT32 uiBuffer, INT16 PocketIndex, INT16 SilIndex, IN
// Flugente FTW 1: Function to get the number of the item condition string // Flugente FTW 1: Function to get the number of the item condition string
UINT8 GetTemperatureString( FLOAT overheatpercentage, UINT32* apRed, UINT32* apGreen, UINT32* abBlue ) UINT8 GetTemperatureString( FLOAT overheatpercentage, UINT32* apRed, UINT32* apGreen, UINT32* abBlue )
{ {
*apRed = (UINT32) ( 100 + 155 * ( (max(1.0, overheatpercentage) - 1.0)/(max(1.0, overheatpercentage)) ) ); *apRed = (UINT32) ( gGameExternalOptions.ubOverheatThermometerRedOffset + (255 - gGameExternalOptions.ubOverheatThermometerRedOffset) * ( (max(1.0, overheatpercentage) - 1.0)/(max(1.0, overheatpercentage)) ) );
*apGreen = 0; *apGreen = 0;
*abBlue = 0; *abBlue = 0;
@@ -2769,7 +2769,7 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
} }
#endif #endif
// FIRST DISPLAY FREE ROUNDS REMIANING
if ( pItem->usItemClass == IC_GUN && !Item[pObject->usItem].rocketlauncher ) if ( pItem->usItemClass == IC_GUN && !Item[pObject->usItem].rocketlauncher )
{ {
sNewY = sY + sHeight - 10; sNewY = sY + sHeight - 10;
@@ -2779,75 +2779,76 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
if ( gGameOptions.fWeaponOverheating == TRUE && gGameExternalOptions.fDisplayOverheatThermometer == TRUE ) if ( gGameOptions.fWeaponOverheating == TRUE && gGameExternalOptions.fDisplayOverheatThermometer == TRUE )
sNewX = sX + 6; sNewX = sX + 6;
SetFontForeground ( AmmoTypes[(*pObject)[iter]->data.gun.ubGunAmmoType].fontColour ); // Flugente: check for underbarrel weapons and use that object if necessary
//switch ((*pObject)[iter]->data.gun.ubGunAmmoType) OBJECTTYPE* pObjShown = pObject;
//{ INVTYPE *pItemShown = pItem;
// case AMMO_AP: if ( pItem->usItemClass == IC_GUN && pSoldier && ( pSoldier->bWeaponMode == WM_ATTACHED_UB || pSoldier->bWeaponMode == WM_ATTACHED_UB_BURST || pSoldier->bWeaponMode == WM_ATTACHED_UB_AUTO ) )
// case AMMO_SUPER_AP:
// SetFontForeground( ITEMDESC_FONTAPFORE );
// break;
// case AMMO_HP:
// SetFontForeground( ITEMDESC_FONTHPFORE );
// break;
// case AMMO_BUCKSHOT:
// SetFontForeground( ITEMDESC_FONTBSFORE );
// break;
// case AMMO_HE:
// case AMMO_GRENADE:
// SetFontForeground( ITEMDESC_FONTHEFORE );
// break;
// case AMMO_HEAT:
// SetFontForeground( ITEMDESC_FONTHEAPFORE );
// break;
// default:
// SetFontForeground( FONT_MCOLOR_DKGRAY );
// break;
//}
// HEADROCK HAM 3.4: Get estimate of bullets left.
if ( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) )
{ {
// Soldier doesn't know. OBJECTTYPE *pObjectUnderBarrel = FindAttachment_UnderBarrel( pObject );
EstimateBulletsLeft( pSoldier, pObject );
swprintf( pStr, L"%s", gBulletCount );
}
else
{
swprintf( pStr, L"%d", (*pObject)[iter]->data.gun.ubGunShotsLeft );
}
//swprintf( pStr, L"%d", (*pObject)[iter]->data.gun.ubGunShotsLeft ); if ( pObjectUnderBarrel )
//swprintf( pStr, L"%d", GetEstimateBulletsLeft(pSoldier, pObject) );
if ( uiBuffer == guiSAVEBUFFER )
{
RestoreExternBackgroundRect( sNewX, sNewY, 20, 15 );
}
mprintf( sNewX, sNewY, pStr );
gprintfinvalidate( sNewX, sNewY, pStr );
sNewX = sX + 1;
SetFontForeground( FONT_MCOLOR_DKGRAY );
// Display 'JAMMED' if we are jammed
if ( (*pObject)[iter]->data.gun.bGunAmmoStatus < 0 )
{
SetFontForeground( FONT_MCOLOR_RED );
if ( sWidth >= ( BIG_INV_SLOT_WIDTH - 10 ) )
{ {
swprintf( pStr, TacticalStr[ JAMMED_ITEM_STR ] ); INVTYPE *pItemUnderBarrel;
if ( ubStatusIndex < RENDER_ITEM_ATTACHMENT1 )
{
pItemUnderBarrel = &Item[ pObjectUnderBarrel->usItem ];
}
else
{
pItemUnderBarrel = &Item[ (*pObjectUnderBarrel)[iter]->GetAttachmentAtIndex( ubStatusIndex - RENDER_ITEM_ATTACHMENT1 )->usItem ];
}
pObjShown = pObjectUnderBarrel;
pItemShown = pItemUnderBarrel;
}
}
if ( pItemShown->usItemClass == IC_GUN && !Item[pObjShown->usItem].rocketlauncher )
{
SetFontForeground ( AmmoTypes[(*pObjShown)[iter]->data.gun.ubGunAmmoType].fontColour );
// HEADROCK HAM 3.4: Get estimate of bullets left.
if ( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) )
{
// Soldier doesn't know.
EstimateBulletsLeft( pSoldier, pObjShown );
swprintf( pStr, L"%s", gBulletCount );
} }
else else
{ {
swprintf( pStr, TacticalStr[ SHORT_JAMMED_GUN ] ); swprintf( pStr, L"%d", (*pObjShown)[iter]->data.gun.ubGunShotsLeft );
}
if ( uiBuffer == guiSAVEBUFFER )
{
RestoreExternBackgroundRect( sNewX, sNewY, 20, 15 );
} }
VarFindFontCenterCoordinates( sX, sY, sWidth, sHeight , ITEM_FONT, &sNewX, &sNewY, pStr );
mprintf( sNewX, sNewY, pStr ); mprintf( sNewX, sNewY, pStr );
gprintfinvalidate( sNewX, sNewY, pStr ); gprintfinvalidate( sNewX, sNewY, pStr );
sNewX = sX + 1;
SetFontForeground( FONT_MCOLOR_DKGRAY );
// Display 'JAMMED' if we are jammed
if ( (*pObjShown)[iter]->data.gun.bGunAmmoStatus < 0 )
{
SetFontForeground( FONT_MCOLOR_RED );
if ( sWidth >= ( BIG_INV_SLOT_WIDTH - 10 ) )
{
swprintf( pStr, TacticalStr[ JAMMED_ITEM_STR ] );
}
else
{
swprintf( pStr, TacticalStr[ SHORT_JAMMED_GUN ] );
}
VarFindFontCenterCoordinates( sX, sY, sWidth, sHeight , ITEM_FONT, &sNewX, &sNewY, pStr );
mprintf( sNewX, sNewY, pStr );
gprintfinvalidate( sNewX, sNewY, pStr );
}
} }
} }
#if 0 #if 0
@@ -2908,20 +2909,25 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
// Flugente FTW 1 // Flugente FTW 1
if ( gGameOptions.fWeaponOverheating == TRUE && gGameExternalOptions.fDisplayOverheatThermometer == TRUE && ( pItem->usItemClass & (IC_GUN | IC_LAUNCHER) || Item[pObject->usItem].barrel == TRUE ) ) if ( gGameOptions.fWeaponOverheating == TRUE && gGameExternalOptions.fDisplayOverheatThermometer == TRUE && ( pItem->usItemClass & (IC_GUN | IC_LAUNCHER) || Item[pObject->usItem].barrel == TRUE ) )
{ {
FLOAT overheatjampercentage = GetGunOverheatJamPercentage( pObject); OBJECTTYPE* pObjShown = pObject;
if ( pSoldier )
pObjShown = pSoldier->GetUsedWeapon(pObject);
FLOAT overheatjampercentage = GetGunOverheatJamPercentage( pObjShown );
UINT32 red, green, blue; UINT32 red, green, blue;
UINT8 TemperatureStringNum = GetTemperatureString( overheatjampercentage, &red, &green, &blue ); UINT8 TemperatureStringNum = GetTemperatureString( overheatjampercentage, &red, &green, &blue );
UINT16 colour = Get16BPPColor( FROMRGB( red, green, blue ) ); UINT16 colour = Get16BPPColor( FROMRGB( red, green, blue ) );
DrawItemUIBarEx( pObject, DRAW_ITEM_TEMPERATURE, sX, sY + sHeight-1, ITEMDESC_ITEM_STATUS_WIDTH, sHeight-1, colour, colour, TRUE, guiSAVEBUFFER ); DrawItemUIBarEx( pObjShown, DRAW_ITEM_TEMPERATURE, sX, sY + sHeight-1, ITEMDESC_ITEM_STATUS_WIDTH, sHeight-1, colour, colour, TRUE, guiSAVEBUFFER );
} }
// display symbol if we are leaning our weapon on something // display symbol if we are leaning our weapon on something
// display only if eapon resting is allowed, display is allowed, item is a gun/launcher, we are a person, we hold the gun in our hand, and we are resting the gun // display only if eapon resting is allowed, display is allowed, item is a gun/launcher, we are a person, we hold the gun in our hand, and we are resting the gun
if ( gGameExternalOptions.fWeaponResting && gGameExternalOptions.fDisplayWeaponRestingIndicator && pItem->usItemClass & (IC_GUN | IC_LAUNCHER) && pSoldier && pSoldier->bActive && pSoldier->bInSector && &(pSoldier->inv[pSoldier->ubAttackingHand]) == pObject && pSoldier->IsWeaponMounted() ) if ( gGameExternalOptions.fWeaponResting && gGameExternalOptions.fDisplayWeaponRestingIndicator && pItem->usItemClass & (IC_GUN | IC_LAUNCHER) && pSoldier && &(pSoldier->inv[pSoldier->ubAttackingHand]) == pObject && pSoldier->IsWeaponMounted() )
{ {
SetRGBFontForeground( 95, 160, 154 ); SetRGBFontForeground( 95, 160, 154 );
@@ -2994,6 +3000,21 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
swprintf( pStr, New113Message[MSG113_GL_AUTO] ); swprintf( pStr, New113Message[MSG113_GL_AUTO] );
SetFontForeground( FONT_YELLOW ); SetFontForeground( FONT_YELLOW );
} }
else if(pSoldier->bWeaponMode == WM_ATTACHED_UB)
{
swprintf( pStr, New113Message[MSG113_UB] );
SetFontForeground( FONT_ORANGE );
}
else if(pSoldier->bWeaponMode == WM_ATTACHED_UB_BURST)
{
swprintf( pStr, New113Message[MSG113_UB_BRST] );
SetFontForeground( FONT_ORANGE );
}
else if(pSoldier->bWeaponMode == WM_ATTACHED_UB_AUTO)
{
swprintf( pStr, New113Message[MSG113_UB_AUTO] );
SetFontForeground( FONT_ORANGE );
}
// Get length of string // Get length of string
uiStringLength=StringPixLength(pStr, ITEM_FONT ); uiStringLength=StringPixLength(pStr, ITEM_FONT );
+10 -4
View File
@@ -2167,12 +2167,15 @@ BOOLEAN CreateSMPanelButtons( )
iSMPanelImages[ OPTIONS_IMAGES ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ] ,-1,24,-1,25,-1 ); iSMPanelImages[ OPTIONS_IMAGES ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ] ,-1,24,-1,25,-1 );
iBurstButtonImages[ WM_NORMAL ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 7, -1, -1, -1 ); iBurstButtonImages[ WM_NORMAL ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 7, -1, -1, -1 );
iBurstButtonImages[ WM_BURST ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 17, -1, -1, -1 ); iBurstButtonImages[ WM_BURST ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 17, -1, -1, -1 );
iBurstButtonImages[ WM_AUTOFIRE ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 17, -1, -1, -1 ); iBurstButtonImages[ WM_AUTOFIRE ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 17, -1, -1, -1 );
iBurstButtonImages[ WM_ATTACHED_GL ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 26, -1, -1, -1 ); iBurstButtonImages[ WM_ATTACHED_GL ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 26, -1, -1, -1 );
iBurstButtonImages[ WM_ATTACHED_GL_BURST ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 17, -1, -1, -1 ); iBurstButtonImages[ WM_ATTACHED_GL_BURST ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 17, -1, -1, -1 );
iBurstButtonImages[ WM_ATTACHED_GL_AUTO ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 17, -1, -1, -1 ); iBurstButtonImages[ WM_ATTACHED_GL_AUTO ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 17, -1, -1, -1 );
iBurstButtonImages[ WM_ATTACHED_UB ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 7, -1, -1, -1 );
iBurstButtonImages[ WM_ATTACHED_UB_BURST ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 17, -1, -1, -1 );
iBurstButtonImages[ WM_ATTACHED_UB_AUTO ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 17, -1, -1, -1 );
FilenameForBPP("INTERFACE\\invadd-ons.sti", ubString); FilenameForBPP("INTERFACE\\invadd-ons.sti", ubString);
// Load button Graphics // Load button Graphics
@@ -2396,6 +2399,9 @@ void RemoveSMPanelButtons( )
UnloadButtonImage( iBurstButtonImages[ WM_ATTACHED_GL ] ); UnloadButtonImage( iBurstButtonImages[ WM_ATTACHED_GL ] );
UnloadButtonImage( iBurstButtonImages[ WM_ATTACHED_GL_BURST ] ); UnloadButtonImage( iBurstButtonImages[ WM_ATTACHED_GL_BURST ] );
UnloadButtonImage( iBurstButtonImages[ WM_ATTACHED_GL_AUTO ] ); UnloadButtonImage( iBurstButtonImages[ WM_ATTACHED_GL_AUTO ] );
UnloadButtonImage( iBurstButtonImages[ WM_ATTACHED_UB ] );
UnloadButtonImage( iBurstButtonImages[ WM_ATTACHED_UB_BURST ] );
UnloadButtonImage( iBurstButtonImages[ WM_ATTACHED_UB_AUTO ] );
} }
+176 -13
View File
@@ -3587,7 +3587,9 @@ INT8 FindAmmoToReload( SOLDIERTYPE * pSoldier, INT8 bWeaponIn, INT8 bExcludeSlot
{ {
return( NO_SLOT ); return( NO_SLOT );
} }
pObj = &(pSoldier->inv[bWeaponIn]);
// Flugente: check for underbarrel weapons and use that object if necessary
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[bWeaponIn]) );
//<SB> manual recharge //<SB> manual recharge
if ((*pObj)[0]->data.gun.ubGunShotsLeft && !((*pObj)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) ) if ((*pObj)[0]->data.gun.ubGunShotsLeft && !((*pObj)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) )
@@ -3656,7 +3658,9 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier )
BOOLEAN fRet; BOOLEAN fRet;
CHECKF( pSoldier ); CHECKF( pSoldier );
pObj = &(pSoldier->inv[HANDPOS]);
// Flugente: check for underbarrel weapons and use that object if necessary
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) );
//<SB> manual recharge //<SB> manual recharge
if ((*pObj)[0]->data.gun.ubGunShotsLeft && !((*pObj)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) ) if ((*pObj)[0]->data.gun.ubGunShotsLeft && !((*pObj)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) )
@@ -3746,7 +3750,9 @@ BOOLEAN AutoReload( SOLDIERTYPE * pSoldier )
// then do a reload of both guns! // then do a reload of both guns!
if ( (fRet == TRUE) && pSoldier->IsValidSecondHandShotForReloadingPurposes( ) ) if ( (fRet == TRUE) && pSoldier->IsValidSecondHandShotForReloadingPurposes( ) )
{ {
pObj = &(pSoldier->inv[SECONDHANDPOS]); // Flugente: check for underbarrel weapons and use that object if necessary
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[SECONDHANDPOS]) );
bSlot = FindAmmoToReload( pSoldier, SECONDHANDPOS, NO_SLOT ); bSlot = FindAmmoToReload( pSoldier, SECONDHANDPOS, NO_SLOT );
if (bSlot != NO_SLOT) if (bSlot != NO_SLOT)
{ {
@@ -4612,7 +4618,9 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
{ {
//Make sure it's actually on that gun.. //Make sure it's actually on that gun..
//if(FindAttachment_GrenadeLauncher(this)->usItem == attachmentObject.usItem){ //if(FindAttachment_GrenadeLauncher(this)->usItem == attachmentObject.usItem){
if(FindAttachment(this, attachmentObject.usItem, subObject)->usItem == attachmentObject.usItem){ // Flugente: if we attach a gun to another gun, do not transfer attachments
if( Item[attachmentObject.usItem].usItemClass != IC_GUN && FindAttachment(this, attachmentObject.usItem, subObject)->usItem == attachmentObject.usItem)
{
// transfer the grenade from the grenade launcher to the gun // transfer the grenade from the grenade launcher to the gun
//To know wether this grenade is valid, we need to correct the slots, because they may have changed when attaching the UGL //To know wether this grenade is valid, we need to correct the slots, because they may have changed when attaching the UGL
@@ -5861,7 +5869,10 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
case IC_GUN: case IC_GUN:
if (Item[pObj->usItem].usItemClass == IC_AMMO) if (Item[pObj->usItem].usItemClass == IC_AMMO)
{ {
if (Weapon[pInSlot->usItem].ubCalibre == Magazine[Item[pObj->usItem].ubClassIndex].ubCalibre) // Flugente: if we have an underbarrel weapon, we can reload that
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon(pInSlot);
if (Weapon[pObjUsed->usItem].ubCalibre == Magazine[Item[pObj->usItem].ubClassIndex].ubCalibre)
{ {
//CHRISL: Work differently with ammo crates but only when not in combat //CHRISL: Work differently with ammo crates but only when not in combat
if(Magazine[Item[pObj->usItem].ubClassIndex].ubMagType >= AMMO_BOX) if(Magazine[Item[pObj->usItem].ubClassIndex].ubMagType >= AMMO_BOX)
@@ -5881,7 +5892,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
{ {
if(Item[loop].usItemClass == IC_AMMO) if(Item[loop].usItemClass == IC_AMMO)
{ {
if(Magazine[Item[loop].ubClassIndex].ubCalibre == Weapon[pInSlot->usItem].ubCalibre && Magazine[Item[loop].ubClassIndex].ubAmmoType == Magazine[Item[pObj->usItem].ubClassIndex].ubAmmoType && Magazine[Item[loop].ubClassIndex].ubMagSize == GetMagSize(pInSlot)) if(Magazine[Item[loop].ubClassIndex].ubCalibre == Weapon[pObjUsed->usItem].ubCalibre && Magazine[Item[loop].ubClassIndex].ubAmmoType == Magazine[Item[pObj->usItem].ubClassIndex].ubAmmoType && Magazine[Item[loop].ubClassIndex].ubMagSize == GetMagSize(pObjUsed))
newItem = loop; newItem = loop;
} }
} }
@@ -5891,7 +5902,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
ubShotsLeft = (*pObj)[0]->data.ubShotsLeft; ubShotsLeft = (*pObj)[0]->data.ubShotsLeft;
for(UINT8 clip = 0; clip < 5; clip++) for(UINT8 clip = 0; clip < 5; clip++)
{ {
magSize = GetMagSize(pInSlot); magSize = GetMagSize(pObjUsed);
if(ubShotsLeft < magSize) if(ubShotsLeft < magSize)
magSize = ubShotsLeft; magSize = ubShotsLeft;
if(CreateAmmo(newItem, &tempClip, magSize)) if(CreateAmmo(newItem, &tempClip, magSize))
@@ -5963,7 +5974,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
} }
} }
else else
return( ReloadGun( pSoldier, pInSlot, pObj ) ); return( ReloadGun( pSoldier, pObjUsed, pObj ) );
} }
} }
break; break;
@@ -7470,6 +7481,24 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNew
} }
} }
// if in attached weapon mode and don't have weapon with GL attached in hand, reset weapon mode
if ( ( (pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )&& !IsGrenadeLauncherAttached( &(pSoldier->inv[ HANDPOS ]) ) ) ||
( (pSoldier->bWeaponMode == WM_ATTACHED_UB || pSoldier->bWeaponMode == WM_ATTACHED_UB_BURST || pSoldier->bWeaponMode == WM_ATTACHED_UB_AUTO )&& !IsUnderBarrelAttached( &(pSoldier->inv[ HANDPOS ] ) ) ) )
{
if ( !Weapon[pSoldier->inv[ HANDPOS ].usItem].NoSemiAuto )
{
pSoldier->bWeaponMode = WM_NORMAL;
pSoldier->bDoBurst = FALSE;
pSoldier->bDoAutofire = 0;
}
else
{
pSoldier->bWeaponMode = WM_AUTOFIRE;
pSoldier->bDoBurst = TRUE;
pSoldier->bDoAutofire = 1;
}
}
if(Item[this->usItem].usItemClass == IC_GUN && oldMagSize != GetMagSize(this, subObject)){ if(Item[this->usItem].usItemClass == IC_GUN && oldMagSize != GetMagSize(this, subObject)){
fInterfacePanelDirty = DIRTYLEVEL2; fInterfacePanelDirty = DIRTYLEVEL2;
RenderBulletIcon(this, subObject); RenderBulletIcon(this, subObject);
@@ -9477,9 +9506,13 @@ void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *b
{ {
*bRecoilX = 0; *bRecoilX = 0;
*bRecoilY = 0; *bRecoilY = 0;
// Flugente: get weapon actually used (might be an underbarrel shotgun)
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon(pObj);
OBJECTTYPE* pObjUsedInHand = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) );
//if (ubNumBullet < 2) //if (ubNumBullet < 2)
if (ubNumBullet < Weapon[pObj->usItem].ubRecoilDelay) if (ubNumBullet < Weapon[pObjUsed->usItem].ubRecoilDelay)
{ {
// The first bullet in a volley never has recoil - it hasn't "set in" yet. Only the second+ bullets // The first bullet in a volley never has recoil - it hasn't "set in" yet. Only the second+ bullets
// will have any recoil. // will have any recoil.
@@ -9488,13 +9521,15 @@ void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *b
return; return;
} }
*bRecoilX = Weapon[pObj->usItem].bRecoilX; *bRecoilX = Weapon[pObjUsed->usItem].bRecoilX;
*bRecoilY = Weapon[pObj->usItem].bRecoilY; *bRecoilY = Weapon[pObjUsed->usItem].bRecoilY;
// Apply a percentage-based modifier. This can increase or decrease BOTH axes. At most, it can eliminate // Apply a percentage-based modifier. This can increase or decrease BOTH axes. At most, it can eliminate
// recoil on the gun. // recoil on the gun.
INT16 sPercentRecoilModifier = GetPercentRecoilModifier( pObj ); //INT16 sPercentRecoilModifier = GetPercentRecoilModifier( pObj );
INT16 sPercentRecoilModifier = __max(-100, (GetBasePercentRecoilModifier( pObjUsed ) + GetAttachmentPercentRecoilModifier( pObjUsedInHand ) ));
*bRecoilX += (*bRecoilX * sPercentRecoilModifier ) / 100; *bRecoilX += (*bRecoilX * sPercentRecoilModifier ) / 100;
*bRecoilY += (*bRecoilY * sPercentRecoilModifier ) / 100; *bRecoilY += (*bRecoilY * sPercentRecoilModifier ) / 100;
@@ -9505,7 +9540,10 @@ void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *b
INT8 bRecoilAdjustX = 0; INT8 bRecoilAdjustX = 0;
INT8 bRecoilAdjustY = 0; INT8 bRecoilAdjustY = 0;
GetFlatRecoilModifier( pObj, &bRecoilAdjustX, &bRecoilAdjustY ); //GetFlatRecoilModifier( pObj, &bRecoilAdjustX, &bRecoilAdjustY );
GetBaseFlatRecoilModifier( pObj, &bRecoilAdjustX, &bRecoilAdjustY );
GetAttachmentFlatRecoilModifier( &pSoldier->inv[HANDPOS], &bRecoilAdjustX, &bRecoilAdjustY);
//JMich TODO: Currently no check for dual wielding
*bRecoilX = __max(0, *bRecoilX + bRecoilAdjustX); *bRecoilX = __max(0, *bRecoilX + bRecoilAdjustX);
*bRecoilY = __max(0, *bRecoilY + bRecoilAdjustY); *bRecoilY = __max(0, *bRecoilY + bRecoilAdjustY);
@@ -9517,6 +9555,44 @@ void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *b
// HEADROCK HAM 4: This function calculates the flat recoil adjustment for a gun. Flat adjustment increases // HEADROCK HAM 4: This function calculates the flat recoil adjustment for a gun. Flat adjustment increases
// or decreases recoil by a specific number of points in either the vertical or horizontal axes (or both). // or decreases recoil by a specific number of points in either the vertical or horizontal axes (or both).
// It can potentially cause a weapon it reverse its recoil direction. // It can potentially cause a weapon it reverse its recoil direction.
void GetBaseFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRecoilModifierY )
{
INT8 bRecoilAdjustX = 0;
INT8 bRecoilAdjustY = 0;
if (pObj->exists() == true && UsingNewCTHSystem() == true)
{
// Inherent item modifiers
bRecoilAdjustX += BonusReduceMore( Item[pObj->usItem].RecoilModifierX, (*pObj)[0]->data.objectStatus );
bRecoilAdjustY += BonusReduceMore( Item[pObj->usItem].RecoilModifierY, (*pObj)[0]->data.objectStatus );
// Ammo item modifiers
bRecoilAdjustX += Item[(*pObj)[0]->data.gun.usGunAmmoItem].RecoilModifierX;
bRecoilAdjustY += Item[(*pObj)[0]->data.gun.usGunAmmoItem].RecoilModifierY;
}
*bRecoilModifierX = bRecoilAdjustX;
*bRecoilModifierY = bRecoilAdjustY;
}
void GetAttachmentFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRecoilModifierY )
{
INT8 bRecoilAdjustX = 0;
INT8 bRecoilAdjustY = 0;
if (pObj->exists() == true && UsingNewCTHSystem() == true)
{
// Attachment item modifiers
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
if (iter->exists())
{
bRecoilAdjustX += BonusReduceMore( Item[iter->usItem].RecoilModifierX, (*iter)[0]->data.objectStatus );
bRecoilAdjustY += BonusReduceMore( Item[iter->usItem].RecoilModifierY, (*iter)[0]->data.objectStatus );
}
}
}
*bRecoilModifierX += bRecoilAdjustX;
*bRecoilModifierY += bRecoilAdjustY;
}
void GetFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRecoilModifierY ) void GetFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRecoilModifierY )
{ {
@@ -9553,6 +9629,39 @@ void GetFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRec
// This adjustment either increases or decreases the gun's vertical and horizontal recoil at the same time. Due to // This adjustment either increases or decreases the gun's vertical and horizontal recoil at the same time. Due to
// the percentage-based nature of this modifier, it cannot cause a gun to reverse its recoil - only diminish it to // the percentage-based nature of this modifier, it cannot cause a gun to reverse its recoil - only diminish it to
// zero. // zero.
INT16 GetBasePercentRecoilModifier( OBJECTTYPE *pObj)
{
INT16 sRecoilAdjust = 0;
if (pObj->exists() == true && UsingNewCTHSystem() == true)
{
// Inherent item modifiers
sRecoilAdjust += BonusReduceMore( Item[pObj->usItem].PercentRecoilModifier, (*pObj)[0]->data.objectStatus );
// Ammo item modifiers
sRecoilAdjust += Item[(*pObj)[0]->data.gun.usGunAmmoItem].PercentRecoilModifier;
}
return (sRecoilAdjust);
}
INT16 GetAttachmentPercentRecoilModifier( OBJECTTYPE *pObj)
{
INT16 sRecoilAdjust = 0;
if (pObj->exists() == true && UsingNewCTHSystem() == true)
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
if (iter->exists())
{
sRecoilAdjust += BonusReduceMore( Item[iter->usItem].PercentRecoilModifier, (*iter)[0]->data.objectStatus );
}
}
}
return (sRecoilAdjust);
}
INT16 GetPercentRecoilModifier( OBJECTTYPE *pObj ) INT16 GetPercentRecoilModifier( OBJECTTYPE *pObj )
{ {
INT16 sRecoilAdjust = 0; INT16 sRecoilAdjust = 0;
@@ -10550,6 +10659,60 @@ UINT16 GetAttachedGrenadeLauncher( OBJECTTYPE * pObj )
return( NONE ); return( NONE );
} }
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())
{
return( (UINT16) Item[iter->usItem].uiIndex );
}
}
}
return( NONE );
}
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() )
{
return TRUE;
}
}
}
return FALSE;
}
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() )
{
return( &(*iter) );
}
}
}
return( NULL );
}
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())
{
return( (*iter)[0]->data.objectStatus );
}
}
}
return( ITEM_NOT_FOUND );
}
INT16 GetAttachedArmourBonus( OBJECTTYPE * pObj ) INT16 GetAttachedArmourBonus( OBJECTTYPE * pObj )
{ {
+12
View File
@@ -300,7 +300,11 @@ INT16 GetMagSizeBonus( OBJECTTYPE * pObj, UINT8 subObject = 0 );
// HEADROCK HAM 4: This function now calculates and returns the weapon's recoil as X/Y offsets. // HEADROCK HAM 4: This function now calculates and returns the weapon's recoil as X/Y offsets.
void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *bRecoilY, UINT8 ubNumBullet ); void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *bRecoilY, UINT8 ubNumBullet );
void GetBaseFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRecoilModifierY);
void GetAttachmentFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRecoilModifierY);
void GetFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRecoilModifierY ); void GetFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRecoilModifierY );
INT16 GetBasePercentRecoilModifier( OBJECTTYPE *pObj );
INT16 GetAttachmentPercentRecoilModifier( OBJECTTYPE *pObj);
INT16 GetPercentRecoilModifier( OBJECTTYPE *pObj ); INT16 GetPercentRecoilModifier( OBJECTTYPE *pObj );
// HEADROCK HAM 4: This function returns whether the last bullet in a burst/autofire volley was a tracer. // HEADROCK HAM 4: This function returns whether the last bullet in a burst/autofire volley was a tracer.
BOOLEAN WasPrevBulletATracer( SOLDIERTYPE *pSoldier, OBJECTTYPE *pWeapon ); BOOLEAN WasPrevBulletATracer( SOLDIERTYPE *pSoldier, OBJECTTYPE *pWeapon );
@@ -337,6 +341,14 @@ INT16 GetGrenadeLauncherStatus( OBJECTTYPE * pObj );
BOOLEAN IsGrenadeLauncherAttached( OBJECTTYPE * pObj, UINT8 subObject = 0 ); BOOLEAN IsGrenadeLauncherAttached( OBJECTTYPE * pObj, UINT8 subObject = 0 );
OBJECTTYPE* FindAttachment_GrenadeLauncher( OBJECTTYPE * pObj ); OBJECTTYPE* FindAttachment_GrenadeLauncher( OBJECTTYPE * pObj );
UINT16 GetAttachedGrenadeLauncher( OBJECTTYPE * pObj ); UINT16 GetAttachedGrenadeLauncher( OBJECTTYPE * pObj );
// JMich & Flugente: functions for underbarrel weapons
INT16 GetUnderBarrelStatus( OBJECTTYPE * pObj );
BOOLEAN IsUnderBarrelAttached( OBJECTTYPE * pObj, UINT8 subObject = 0 );
OBJECTTYPE* FindAttachment_UnderBarrel( OBJECTTYPE * pObj );
UINT16 GetAttachedUnderBarrel( OBJECTTYPE * pObj );
OBJECTTYPE* GetUsedWeapon( OBJECTTYPE * pObj );
INT8 FindRocketLauncher( SOLDIERTYPE * pSoldier ); INT8 FindRocketLauncher( SOLDIERTYPE * pSoldier );
INT8 FindRocketLauncherOrCannon( SOLDIERTYPE * pSoldier ); INT8 FindRocketLauncherOrCannon( SOLDIERTYPE * pSoldier );
INT8 FindNonSmokeLaunchable( SOLDIERTYPE * pSoldier, UINT16 usWeapon ); INT8 FindNonSmokeLaunchable( SOLDIERTYPE * pSoldier, UINT16 usWeapon );
+36 -24
View File
@@ -3988,12 +3988,15 @@ INT8 FireBullet( SOLDIERTYPE * pFirer, BULLET * pBullet, BOOLEAN fFake )
} }
else else
{ {
OBJECTTYPE* pObjAttHand = pFirer->GetUsedWeapon( &pFirer->inv[pFirer->ubAttackingHand] );
UINT16 usItemUsed = pFirer->GetUsedWeaponNumber( &pFirer->inv[pFirer->ubAttackingHand] );
//afp-start //always a fast bullet //afp-start //always a fast bullet
if ( pBullet->usFlags & ( BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_KNIFE | BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME /*| BULLET_FLAG_TRACER*/ ) ) if ( pBullet->usFlags & ( BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_KNIFE | BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME /*| BULLET_FLAG_TRACER*/ ) )
pBullet->usClockTicksPerUpdate = (Weapon[ pFirer->usAttackingWeapon ].ubBulletSpeed + GetBulletSpeedBonus(&pFirer->inv[pFirer->ubAttackingHand]) ) / 10; pBullet->usClockTicksPerUpdate = (Weapon[ usItemUsed ].ubBulletSpeed + GetBulletSpeedBonus( pObjAttHand ) ) / 10;
else else
if (gGameSettings.fOptions[TOPTION_ALTERNATE_BULLET_GRAPHICS]) if (gGameSettings.fOptions[TOPTION_ALTERNATE_BULLET_GRAPHICS])
pBullet->usClockTicksPerUpdate = (Weapon[ pFirer->usAttackingWeapon ].ubBulletSpeed + GetBulletSpeedBonus(&pFirer->inv[pFirer->ubAttackingHand]) ) / 10; pBullet->usClockTicksPerUpdate = (Weapon[ usItemUsed ].ubBulletSpeed + GetBulletSpeedBonus( pObjAttHand ) ) / 10;
else else
pBullet->usClockTicksPerUpdate = 1; pBullet->usClockTicksPerUpdate = 1;
//afp-end //afp-end
@@ -4068,6 +4071,8 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
UINT16 usBulletFlags = 0; UINT16 usBulletFlags = 0;
int n=0; int n=0;
OBJECTTYPE* pObjAttHand = pFirer->GetUsedWeapon( &(pFirer->inv[pFirer->ubAttackingHand]) );
//DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("FireBulletGivenTarget")); //DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("FireBulletGivenTarget"));
CalculateSoldierZPos( pFirer, FIRING_POS, &dStartZ ); CalculateSoldierZPos( pFirer, FIRING_POS, &dStartZ );
@@ -4132,11 +4137,11 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
// HEADROCK HAM B2.5: Set tracer effect on/off for individual bullets in a Tracer Magazine, as part of the // HEADROCK HAM B2.5: Set tracer effect on/off for individual bullets in a Tracer Magazine, as part of the
// New Tracer System. // New Tracer System.
else if (gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0) else if (gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0)
&& AmmoTypes[ pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType ].tracerEffect ) && AmmoTypes[ (*pObjAttHand)[0]->data.gun.ubGunAmmoType ].tracerEffect )
{ {
UINT16 iBulletsLeft, iBulletsPerTracer; UINT16 iBulletsLeft, iBulletsPerTracer;
iBulletsPerTracer = gGameExternalOptions.ubNumBulletsPerTracer; iBulletsPerTracer = gGameExternalOptions.ubNumBulletsPerTracer;
iBulletsLeft = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunShotsLeft + pFirer->bDoBurst; iBulletsLeft = (*pObjAttHand)[0]->data.gun.ubGunShotsLeft + pFirer->bDoBurst;
if ((((iBulletsLeft - (pFirer->bDoBurst - 1)) / iBulletsPerTracer) - ((iBulletsLeft - pFirer->bDoBurst) / iBulletsPerTracer)) == 1) if ((((iBulletsLeft - (pFirer->bDoBurst - 1)) / iBulletsPerTracer) - ((iBulletsLeft - pFirer->bDoBurst) / iBulletsPerTracer)) == 1)
{ {
@@ -4147,7 +4152,7 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
fTracer = FALSE; fTracer = FALSE;
} }
} }
else if ( AmmoTypes[ pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType ].tracerEffect && (pFirer->bDoBurst || gGameSettings.fOptions[ TOPTION_TRACERS_FOR_SINGLE_FIRE ]) ) else if ( AmmoTypes[ (*pObjAttHand)[0]->data.gun.ubGunAmmoType ].tracerEffect && (pFirer->bDoBurst || gGameSettings.fOptions[ TOPTION_TRACERS_FOR_SINGLE_FIRE ]) )
{ {
//usBulletFlags |= BULLET_FLAG_TRACER; //usBulletFlags |= BULLET_FLAG_TRACER;
fTracer = TRUE; fTracer = TRUE;
@@ -4156,9 +4161,9 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
ubImpact =(UINT8) GetDamage(&pFirer->inv[pFirer->ubAttackingHand]); ubImpact =(UINT8) GetDamage(&pFirer->inv[pFirer->ubAttackingHand]);
//zilpin: Begin new code block for spread patterns, number of projectiles, impact adjustment, etc. //zilpin: Begin new code block for spread patterns, number of projectiles, impact adjustment, etc.
{ {
ObjectData *weapon = &(pFirer->inv[pFirer->ubAttackingHand][0]->data); ObjectData *weapon = &((*pObjAttHand)[0]->data);
ubShots = AmmoTypes[ weapon->gun.ubGunAmmoType].numberOfBullets; ubShots = AmmoTypes[ weapon->gun.ubGunAmmoType].numberOfBullets;
ubSpreadIndex = GetSpreadPattern( &pFirer->inv[pFirer->ubAttackingHand] ); ubSpreadIndex = GetSpreadPattern( pObjAttHand );
if( ubShots>1 && !fFake ) if( ubShots>1 && !fFake )
{ {
fBuckshot = true; fBuckshot = true;
@@ -4407,7 +4412,7 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
if ( pBullet->usFlags & BULLET_FLAG_KNIFE ) if ( pBullet->usFlags & BULLET_FLAG_KNIFE )
{ {
pBullet->ubItemStatus = pFirer->inv[pFirer->ubAttackingHand][0]->data.objectStatus; pBullet->ubItemStatus = (*pObjAttHand)[0]->data.objectStatus;
} }
// apply increments for first move // apply increments for first move
@@ -4435,7 +4440,7 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
pBullet->iImpact = ubImpact; pBullet->iImpact = ubImpact;
pBullet->iRange = GunRange( &(pFirer->inv[pFirer->ubAttackingHand]), pFirer ); // SANDRO - added argument pBullet->iRange = GunRange( pObjAttHand, pFirer ); // SANDRO - added argument
pBullet->sTargetGridNo = ((INT32)dEndX) / CELL_X_SIZE + ((INT32)dEndY) / CELL_Y_SIZE * WORLD_COLS; pBullet->sTargetGridNo = ((INT32)dEndX) / CELL_X_SIZE + ((INT32)dEndY) / CELL_Y_SIZE * WORLD_COLS;
pBullet->bStartCubesAboveLevelZ = (INT8) CONVERT_HEIGHTUNITS_TO_INDEX( (INT32)dStartZ - CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[ pFirer->sGridNo ].sHeight ) ); pBullet->bStartCubesAboveLevelZ = (INT8) CONVERT_HEIGHTUNITS_TO_INDEX( (INT32)dStartZ - CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[ pFirer->sGridNo ].sHeight ) );
@@ -4447,11 +4452,11 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
// HEADROCK HAM BETA2.5: New method for signifying whether a bullet is a tracer or not, using an individual // HEADROCK HAM BETA2.5: New method for signifying whether a bullet is a tracer or not, using an individual
// bullet structure flag. Hehehehe, I think this is kind of reverting to old code, isn't it? // bullet structure flag. Hehehehe, I think this is kind of reverting to old code, isn't it?
if (gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0) if (gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0)
&& AmmoTypes[ pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType ].tracerEffect ) && AmmoTypes[ (*pObjAttHand)[0]->data.gun.ubGunAmmoType ].tracerEffect )
{ {
UINT16 iBulletsLeft, iBulletsPerTracer; UINT16 iBulletsLeft, iBulletsPerTracer;
iBulletsPerTracer = gGameExternalOptions.ubNumBulletsPerTracer; iBulletsPerTracer = gGameExternalOptions.ubNumBulletsPerTracer;
iBulletsLeft = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunShotsLeft + pFirer->bDoBurst; iBulletsLeft = (*pObjAttHand)[0]->data.gun.ubGunShotsLeft + pFirer->bDoBurst;
// Is this specific bullet a tracer? - based on how many tracers there are per regular bullets in // Is this specific bullet a tracer? - based on how many tracers there are per regular bullets in
// a tracer magazine (INI-settable). // a tracer magazine (INI-settable).
@@ -4540,6 +4545,8 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
UINT16 usBulletFlags = 0; UINT16 usBulletFlags = 0;
int n=0; int n=0;
OBJECTTYPE* pObjAttHand = pFirer->GetUsedWeapon( &(pFirer->inv[pFirer->ubAttackingHand]) );
//DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("FireBulletGivenTarget")); //DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("FireBulletGivenTarget"));
CalculateSoldierZPos( pFirer, FIRING_POS, &dStartZ ); CalculateSoldierZPos( pFirer, FIRING_POS, &dStartZ );
@@ -4574,7 +4581,7 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
ubShots = 1; ubShots = 1;
fTracer = FALSE; fTracer = FALSE;
// Check if we have spit as a weapon! // Check if we have spit as a weapon!
if ( Weapon[ usHandItem ].ubWeaponClass == MONSTERCLASS ) if ( Weapon[ usHandItem ].ubWeaponClass == MONSTERCLASS )
{ {
@@ -4604,11 +4611,11 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
// HEADROCK HAM B2.5: Set tracer effect on/off for individual bullets in a Tracer Magazine, as part of the // HEADROCK HAM B2.5: Set tracer effect on/off for individual bullets in a Tracer Magazine, as part of the
// New Tracer System. // New Tracer System.
else if (gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0) else if (gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0)
&& AmmoTypes[ pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType ].tracerEffect ) && AmmoTypes[ (*pObjAttHand)[0]->data.gun.ubGunAmmoType ].tracerEffect )
{ {
UINT16 iBulletsLeft, iBulletsPerTracer; UINT16 iBulletsLeft, iBulletsPerTracer;
iBulletsPerTracer = gGameExternalOptions.ubNumBulletsPerTracer; iBulletsPerTracer = gGameExternalOptions.ubNumBulletsPerTracer;
iBulletsLeft = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunShotsLeft + pFirer->bDoBurst; iBulletsLeft = (*pObjAttHand)[0]->data.gun.ubGunShotsLeft + pFirer->bDoBurst;
if ((((iBulletsLeft - (pFirer->bDoBurst - 1)) / iBulletsPerTracer) - ((iBulletsLeft - pFirer->bDoBurst) / iBulletsPerTracer)) == 1) if ((((iBulletsLeft - (pFirer->bDoBurst - 1)) / iBulletsPerTracer) - ((iBulletsLeft - pFirer->bDoBurst) / iBulletsPerTracer)) == 1)
{ {
@@ -4625,7 +4632,7 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
fTracer = TRUE; fTracer = TRUE;
} }
ubImpact =(UINT8) GetDamage(&pFirer->inv[pFirer->ubAttackingHand]); ubImpact =(UINT8) GetDamage(pObjAttHand);
//zilpin: pellet spread patterns externalized in XML //zilpin: pellet spread patterns externalized in XML
/* zilpin: The section below, including line comments, is the original adjustment made to multiple projectile stats. /* zilpin: The section below, including line comments, is the original adjustment made to multiple projectile stats.
Left in comments for reference, but the new handling is after it. Left in comments for reference, but the new handling is after it.
@@ -4661,9 +4668,9 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
*/ */
//zilpin: Begin new code block for spread patterns, number of projectiles, impact adjustment, etc. //zilpin: Begin new code block for spread patterns, number of projectiles, impact adjustment, etc.
{ {
ObjectData *weapon = &(pFirer->inv[pFirer->ubAttackingHand][0]->data); ObjectData *weapon = &((*pObjAttHand)[0]->data);
ubShots = AmmoTypes[ weapon->gun.ubGunAmmoType].numberOfBullets; ubShots = AmmoTypes[ weapon->gun.ubGunAmmoType].numberOfBullets;
ubSpreadIndex = GetSpreadPattern( &pFirer->inv[pFirer->ubAttackingHand] ); ubSpreadIndex = GetSpreadPattern( pObjAttHand );
if( ubShots>1 && !fFake ) if( ubShots>1 && !fFake )
{ {
fBuckshot = true; fBuckshot = true;
@@ -4905,7 +4912,7 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
if ( pBullet->usFlags & BULLET_FLAG_KNIFE ) if ( pBullet->usFlags & BULLET_FLAG_KNIFE )
{ {
pBullet->ubItemStatus = pFirer->inv[pFirer->ubAttackingHand][0]->data.objectStatus; pBullet->ubItemStatus = (*pObjAttHand)[0]->data.objectStatus;
} }
// apply increments for first move // apply increments for first move
@@ -4933,7 +4940,7 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
pBullet->iImpact = ubImpact; pBullet->iImpact = ubImpact;
pBullet->iRange = GunRange( &(pFirer->inv[pFirer->ubAttackingHand]), pFirer ); // SANDRO - added argument pBullet->iRange = GunRange( pObjAttHand, pFirer ); // SANDRO - added argument
pBullet->sTargetGridNo = ((INT32)dEndX) / CELL_X_SIZE + ((INT32)dEndY) / CELL_Y_SIZE * WORLD_COLS; pBullet->sTargetGridNo = ((INT32)dEndX) / CELL_X_SIZE + ((INT32)dEndY) / CELL_Y_SIZE * WORLD_COLS;
pBullet->bStartCubesAboveLevelZ = (INT8) CONVERT_HEIGHTUNITS_TO_INDEX( (INT32)dStartZ - CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[ pFirer->sGridNo ].sHeight ) ); pBullet->bStartCubesAboveLevelZ = (INT8) CONVERT_HEIGHTUNITS_TO_INDEX( (INT32)dStartZ - CONVERT_PIXELS_TO_HEIGHTUNITS( gpWorldLevelData[ pFirer->sGridNo ].sHeight ) );
@@ -4945,11 +4952,11 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
// HEADROCK HAM BETA2.5: New method for signifying whether a bullet is a tracer or not, using an individual // HEADROCK HAM BETA2.5: New method for signifying whether a bullet is a tracer or not, using an individual
// bullet structure flag. Hehehehe, I think this is kind of reverting to old code, isn't it? // bullet structure flag. Hehehehe, I think this is kind of reverting to old code, isn't it?
if (gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0) if (gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0)
&& AmmoTypes[ pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType ].tracerEffect ) && AmmoTypes[ (*pObjAttHand)[0]->data.gun.ubGunAmmoType ].tracerEffect )
{ {
UINT16 iBulletsLeft, iBulletsPerTracer; UINT16 iBulletsLeft, iBulletsPerTracer;
iBulletsPerTracer = gGameExternalOptions.ubNumBulletsPerTracer; iBulletsPerTracer = gGameExternalOptions.ubNumBulletsPerTracer;
iBulletsLeft = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunShotsLeft + pFirer->bDoBurst; iBulletsLeft = (*pObjAttHand)[0]->data.gun.ubGunShotsLeft + pFirer->bDoBurst;
// Is this specific bullet a tracer? - based on how many tracers there are per regular bullets in // Is this specific bullet a tracer? - based on how many tracers there are per regular bullets in
// a tracer magazine (INI-settable). // a tracer magazine (INI-settable).
@@ -5008,10 +5015,12 @@ INT8 ChanceToGetThrough( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT d
{ {
BOOLEAN fBuckShot = FALSE; BOOLEAN fBuckShot = FALSE;
OBJECTTYPE* pObjHand = pFirer->GetUsedWeapon( &pFirer->inv[HANDPOS] );
// if shotgun, shotgun would have to be in main hand // if shotgun, shotgun would have to be in main hand
if ( pFirer->inv[ HANDPOS ].usItem == pFirer->usAttackingWeapon ) if ( pObjHand->usItem == pFirer->usAttackingWeapon )
{ {
if ( AmmoTypes[pFirer->inv[ HANDPOS ][0]->data.gun.ubGunAmmoType].numberOfBullets > 1 ) if ( AmmoTypes[ (*pObjHand)[0]->data.gun.ubGunAmmoType].numberOfBullets > 1 )
{ {
fBuckShot = TRUE; fBuckShot = TRUE;
} }
@@ -7332,8 +7341,11 @@ FLOAT CalcBulletDeviation( SOLDIERTYPE *pShooter, FLOAT *dShotOffsetX, FLOAT *dS
// We start by reading the gun's Accuracy value. We'll use that as the basis for everything else. // We start by reading the gun's Accuracy value. We'll use that as the basis for everything else.
// Flugente: determine used gun
OBJECTTYPE* pObjAttHand = pShooter->GetUsedWeapon( &pShooter->inv[ pShooter->ubAttackingHand ] );
INT16 sAccuracy = GetGunAccuracy( pWeapon ); INT16 sAccuracy = GetGunAccuracy( pWeapon );
UINT16 sEffRange = Weapon[Item[pShooter->inv[pShooter->ubAttackingHand].usItem].ubClassIndex].usRange + GetRangeBonus(&(pShooter->inv[ pShooter->ubAttackingHand ])); UINT16 sEffRange = Weapon[Item[pObjAttHand->usItem].ubClassIndex].usRange + GetRangeBonus( pObjAttHand );
// WANNE: I got a CTD in a multiplayer test game, because sEffRange was 0 (division to zero). // WANNE: I got a CTD in a multiplayer test game, because sEffRange was 0 (division to zero).
// I don't know why this happend? // I don't know why this happend?
+62 -52
View File
@@ -1478,8 +1478,12 @@ INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTur
BOOLEAN fAddingRaiseGunCost = FALSE; BOOLEAN fAddingRaiseGunCost = FALSE;
// LOOK IN BUDDY'S HAND TO DETERMINE WHAT TO DO HERE // LOOK IN BUDDY'S HAND TO DETERMINE WHAT TO DO HERE
// Flugente: check for underbarrel weapons and use that object if necessary
OBJECTTYPE* AttackingWeapon = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) );
UINT16 usUBItemNum = pSoldier->GetUsedWeaponNumber( &(pSoldier->inv[HANDPOS]) );
usItemNum = pSoldier->inv[HANDPOS].usItem; usItemNum = pSoldier->inv[HANDPOS].usItem;
uiItemClass = Item[ usItemNum ].usItemClass; uiItemClass = Item[ usUBItemNum ].usItemClass;
if ( uiItemClass == IC_GUN || uiItemClass == IC_LAUNCHER || uiItemClass == IC_TENTACLES || uiItemClass == IC_THROWING_KNIFE ) if ( uiItemClass == IC_GUN || uiItemClass == IC_LAUNCHER || uiItemClass == IC_TENTACLES || uiItemClass == IC_THROWING_KNIFE )
{ {
@@ -1487,10 +1491,10 @@ INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTur
if ( pSoldier->bDoBurst ) if ( pSoldier->bDoBurst )
{ {
if(pSoldier->bDoAutofire && GetAutofireShotsPerFiveAPs(&pSoldier->inv[HANDPOS]) > 0 ) if(pSoldier->bDoAutofire && GetAutofireShotsPerFiveAPs(AttackingWeapon) > 0 )
sAPCost += CalcAPsToAutofire( pSoldier->CalcActionPoints( ), &(pSoldier->inv[HANDPOS]), pSoldier->bDoAutofire ); sAPCost += CalcAPsToAutofire( pSoldier->CalcActionPoints( ), AttackingWeapon, pSoldier->bDoAutofire );
else else
sAPCost += CalcAPsToBurst( pSoldier->CalcActionPoints( ), &(pSoldier->inv[HANDPOS]) ); sAPCost += CalcAPsToBurst( pSoldier->CalcActionPoints( ), AttackingWeapon );
} }
//else //ddd comment for aimed burst //else //ddd comment for aimed burst
{ {
@@ -1513,7 +1517,7 @@ INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTur
UINT16 usWeaponReadyTime; UINT16 usWeaponReadyTime;
UINT8 ubReadyTimeDivisor; UINT8 ubReadyTimeDivisor;
usWeaponReadyTime = Weapon[ usItemNum ].ubReadyTime * (100 - GetPercentReadyTimeAPReduction(&pSoldier->inv[HANDPOS])) / 100; usWeaponReadyTime = Weapon[ pSoldier->inv[HANDPOS].usItem ].ubReadyTime * (100 - GetPercentReadyTimeAPReduction(&pSoldier->inv[HANDPOS])) / 100;
ubReadyTimeDivisor = gGameExternalOptions.ubFirstAimReadyCostDivisor; ubReadyTimeDivisor = gGameExternalOptions.ubFirstAimReadyCostDivisor;
sAPCost += usWeaponReadyTime / ubReadyTimeDivisor; sAPCost += usWeaponReadyTime / ubReadyTimeDivisor;
} }
@@ -1696,8 +1700,10 @@ INT16 MinAPsToAttack(SOLDIERTYPE *pSoldier, INT32 sGridno, UINT8 ubAddTurningCos
} }
else else
{ {
UINT16 undbarItem = pSoldier->GetUsedWeaponNumber( &(pSoldier->inv[ HANDPOS ]) );
// LOOK IN BUDDY'S HAND TO DETERMINE WHAT TO DO HERE // LOOK IN BUDDY'S HAND TO DETERMINE WHAT TO DO HERE
uiItemClass = Item[ pSoldier->inv[HANDPOS].usItem ].usItemClass; uiItemClass = Item[ undbarItem ].usItemClass;
} }
if ( uiItemClass == IC_BLADE || uiItemClass == IC_GUN || uiItemClass == IC_LAUNCHER || uiItemClass == IC_TENTACLES || uiItemClass == IC_THROWING_KNIFE ) if ( uiItemClass == IC_BLADE || uiItemClass == IC_GUN || uiItemClass == IC_LAUNCHER || uiItemClass == IC_TENTACLES || uiItemClass == IC_THROWING_KNIFE )
@@ -1936,16 +1942,21 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
UINT16 usRaiseGunCost = 0; UINT16 usRaiseGunCost = 0;
UINT16 usTurningCost = 0; UINT16 usTurningCost = 0;
UINT16 usUBItem = 0;
if ( pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO ) if ( pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )
{ {
usItem = GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS] );//UNDER_GLAUNCHER; usItem = GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS] );//UNDER_GLAUNCHER;
usUBItem = usItem;
} }
else else
{ {
usItem = pSoldier->inv[ HANDPOS ].usItem; usItem = pSoldier->inv[ HANDPOS ].usItem;
// Flugente: we need a secon temnr in case we are using an underbarrel weapon. Not all checks should apply for that one, as aiming is still done with the main weapon
usUBItem = pSoldier->GetUsedWeaponNumber(&pSoldier->inv[HANDPOS]);
} }
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) );
GetAPChargeForShootOrStabWRTGunRaises( pSoldier, sGridNo, ubAddTurningCost, &fAddingTurningCost, &fAddingRaiseGunCost ); GetAPChargeForShootOrStabWRTGunRaises( pSoldier, sGridNo, ubAddTurningCost, &fAddingTurningCost, &fAddingRaiseGunCost );
@@ -2013,51 +2024,53 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
} }
} }
else else
{ {
//CHRISL: When prone and using a bipod, bipod should help compensate for recoil. To reflect this, our shot AP cost should be minimially reduced //CHRISL: When prone and using a bipod, bipod should help compensate for recoil. To reflect this, our shot AP cost should be minimially reduced
if(gGameExternalOptions.ubFlatAFTHBtoPrecentMultiplier > 0 && gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE && GetBipodBonus(&(pSoldier->inv[HANDPOS])) > 0){ if(gGameExternalOptions.ubFlatAFTHBtoPrecentMultiplier > 0 && gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE && GetBipodBonus(&(pSoldier->inv[HANDPOS])) > 0)
bAPCost += (BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[HANDPOS]) ) * (100 - GetBipodBonus(&(pSoldier->inv[HANDPOS]))) / 100); {
} else { bAPCost += (BaseAPsToShootOrStab( bFullAPs, bAimSkill, pObjUsed ) * (100 - GetBipodBonus(&(pSoldier->inv[HANDPOS]))) / 100);
bAPCost += BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[HANDPOS]) ); }
else
{
bAPCost += BaseAPsToShootOrStab( bFullAPs, bAimSkill, pObjUsed );
} }
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
// SANDRO - STOMP traits // SANDRO - STOMP traits
//////////////////////////////////////////////////// ////////////////////////////////////////////////////
if ( gGameOptions.fNewTraitSystem ) if ( gGameOptions.fNewTraitSystem )
{ {
// Decreased APs needed for LMG - Auto Weapons // Decreased APs needed for LMG - Auto Weapons
if (Weapon[usItem].ubWeaponType == GUN_LMG && (pSoldier->bDoBurst || pSoldier->bDoAutofire) && ( HAS_SKILL_TRAIT( pSoldier, AUTO_WEAPONS_NT ) ) ) if (Weapon[usUBItem].ubWeaponType == GUN_LMG && (pSoldier->bDoBurst || pSoldier->bDoAutofire) && ( HAS_SKILL_TRAIT( pSoldier, AUTO_WEAPONS_NT ) ) )
{ {
bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubAWFiringSpeedBonusLMGs ) / 100)+ 0.5); bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubAWFiringSpeedBonusLMGs ) / 100)+ 0.5);
} }
// Decreased APs needed for melee attacks - Melee // Decreased APs needed for melee attacks - Melee
if ( Item[ usItem ].usItemClass == IC_BLADE && ( HAS_SKILL_TRAIT( pSoldier, MELEE_NT ) ) ) if ( Item[ usUBItem ].usItemClass == IC_BLADE && ( HAS_SKILL_TRAIT( pSoldier, MELEE_NT ) ) )
{ {
bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubMEBladesAPsReduction ) / 100)+ 0.5); bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubMEBladesAPsReduction ) / 100)+ 0.5);
} }
// Decreased APs needed for throwing knives - Throwing // Decreased APs needed for throwing knives - Throwing
else if ( Item[ usItem ].usItemClass == IC_THROWING_KNIFE && ( HAS_SKILL_TRAIT( pSoldier, THROWING_NT ) ) ) else if ( Item[ usUBItem ].usItemClass == IC_THROWING_KNIFE && ( HAS_SKILL_TRAIT( pSoldier, THROWING_NT ) ) )
{ {
bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubTHBladesAPsReduction ) / 100)+ 0.5); bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubTHBladesAPsReduction ) / 100)+ 0.5);
} }
// Decreased APs needed for launchers - Heavy Eeapons // Decreased APs needed for launchers - Heavy Eeapons
else if ( (Item[ usItem ].usItemClass == IC_LAUNCHER || Item[usItem].grenadelauncher ) && !(Item[usItem].rocketlauncher) && !(Item[usItem].mortar) && ( HAS_SKILL_TRAIT( pSoldier, HEAVY_WEAPONS_NT ) )) else if ( (Item[ usUBItem ].usItemClass == IC_LAUNCHER || Item[usUBItem].grenadelauncher ) && !(Item[usUBItem].rocketlauncher) && !(Item[usUBItem].mortar) && ( HAS_SKILL_TRAIT( pSoldier, HEAVY_WEAPONS_NT ) ))
{ {
bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubHWGrenadeLaunchersAPsReduction * NUM_SKILL_TRAITS( pSoldier, HEAVY_WEAPONS_NT ) ) / 100)+ 0.5); bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubHWGrenadeLaunchersAPsReduction * NUM_SKILL_TRAITS( pSoldier, HEAVY_WEAPONS_NT ) ) / 100)+ 0.5);
} }
// Decreased APs needed for launchers - Heavy Eeapons // Decreased APs needed for launchers - Heavy Eeapons
else if (( Item[usItem].rocketlauncher || Item[usItem].singleshotrocketlauncher ) && !(Item[usItem].mortar) && ( HAS_SKILL_TRAIT( pSoldier, HEAVY_WEAPONS_NT ) )) else if (( Item[usUBItem].rocketlauncher || Item[usUBItem].singleshotrocketlauncher ) && !(Item[usUBItem].mortar) && ( HAS_SKILL_TRAIT( pSoldier, HEAVY_WEAPONS_NT ) ))
{ {
bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubHWRocketLaunchersAPsReduction * NUM_SKILL_TRAITS( pSoldier, HEAVY_WEAPONS_NT ) ) / 100)+ 0.5); bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubHWRocketLaunchersAPsReduction * NUM_SKILL_TRAITS( pSoldier, HEAVY_WEAPONS_NT ) ) / 100)+ 0.5);
} }
// Decreased APs needed for mortar - Heavy Eeapons // Decreased APs needed for mortar - Heavy Eeapons
else if ( Item[usItem].mortar && HAS_SKILL_TRAIT( pSoldier, HEAVY_WEAPONS_NT ) ) else if ( Item[usUBItem].mortar && HAS_SKILL_TRAIT( pSoldier, HEAVY_WEAPONS_NT ) )
{ {
bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubHWMortarAPsReduction * NUM_SKILL_TRAITS( pSoldier, HEAVY_WEAPONS_NT ) ) / 100)+ 0.5); bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubHWMortarAPsReduction * NUM_SKILL_TRAITS( pSoldier, HEAVY_WEAPONS_NT ) ) / 100)+ 0.5);
} }
// Decreased APs needed for pistols and machine pistols - Gunslinger // Decreased APs needed for pistols and machine pistols - Gunslinger
else if (Weapon[ usItem ].ubWeaponType == GUN_PISTOL && HAS_SKILL_TRAIT( pSoldier, GUNSLINGER_NT ) ) else if (Weapon[ usUBItem ].ubWeaponType == GUN_PISTOL && HAS_SKILL_TRAIT( pSoldier, GUNSLINGER_NT ) )
{ {
bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubGSFiringSpeedBonusPistols * NUM_SKILL_TRAITS( pSoldier, GUNSLINGER_NT ) ) / 100)+ 0.5); bAPCost = (INT16)((bAPCost * (100 - gSkillTraitValues.ubGSFiringSpeedBonusPistols * NUM_SKILL_TRAITS( pSoldier, GUNSLINGER_NT ) ) / 100)+ 0.5);
} }
@@ -2073,7 +2086,7 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
fAddingRaiseGunCost = TRUE; fAddingRaiseGunCost = TRUE;
} }
if ( Item[ usItem ].usItemClass == IC_THROWING_KNIFE ) if ( Item[ usUBItem ].usItemClass == IC_THROWING_KNIFE )
{ {
// Do we need to stand up? // Do we need to stand up?
bAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND ); bAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND );
@@ -2120,7 +2133,7 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
// if attacking a new target (or if the specific target is uncertain) // if attacking a new target (or if the specific target is uncertain)
// Added check if the weapon is a throwing knife - otherwise it would add APs for change taregt on cursor but not actually deduct them afterwards - SANDRO // Added check if the weapon is a throwing knife - otherwise it would add APs for change taregt on cursor but not actually deduct them afterwards - SANDRO
if (ubForceRaiseGunCost || (( sGridNo != pSoldier->sLastTarget ) && !Item[usItem].rocketlauncher && (Item[ usItem ].usItemClass != IC_THROWING_KNIFE) )) if (ubForceRaiseGunCost || (( sGridNo != pSoldier->sLastTarget ) && !Item[usUBItem].rocketlauncher && (Item[ usUBItem ].usItemClass != IC_THROWING_KNIFE) ))
{ {
bAPCost += APBPConstants[AP_CHANGE_TARGET]; bAPCost += APBPConstants[AP_CHANGE_TARGET];
} }
@@ -2134,7 +2147,7 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
if ( bAPCost < 1 ) if ( bAPCost < 1 )
bAPCost = 1; bAPCost = 1;
if ( Item[pSoldier->inv[HANDPOS].usItem].rocketlauncher ) if ( Item[(*pObjUsed).usItem].rocketlauncher )
{ {
bAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND ); bAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND );
} }
@@ -2347,33 +2360,36 @@ BOOLEAN EnoughAmmo( SOLDIERTYPE *pSoldier, BOOLEAN fDisplay, INT8 bInvPos )
} }
else else
{ {
if ( Item[pSoldier->inv[ bInvPos ].usItem].singleshotrocketlauncher ) OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( &(pSoldier->inv[bInvPos]) );
UINT16 usItemUsed = pSoldier->GetUsedWeaponNumber( &(pSoldier->inv[bInvPos]) );
if ( Item[usItemUsed].singleshotrocketlauncher )
{ {
// hack... they turn empty afterwards anyways // hack... they turn empty afterwards anyways
return( TRUE ); return( TRUE );
} }
if (Item[ pSoldier->inv[ bInvPos ].usItem ].usItemClass == IC_LAUNCHER || Item[pSoldier->inv[ bInvPos ].usItem].cannon ) if (Item[ usItemUsed ].usItemClass == IC_LAUNCHER || Item[usItemUsed].cannon )
{ {
if ( FindAttachmentByClass( &(pSoldier->inv[ bInvPos ]), IC_GRENADE ) != 0 ) if ( FindAttachmentByClass( pObjUsed, IC_GRENADE ) != 0 )
{ {
return( TRUE ); return( TRUE );
} }
if (Item[pSoldier->inv[bInvPos].usItem].usItemClass == IC_BOMB) if (Item[usItemUsed].usItemClass == IC_BOMB)
{ {
return (TRUE); return (TRUE);
} }
// ATE: Did an else if here... // ATE: Did an else if here...
if ( FindAttachmentByClass( &(pSoldier->inv[ bInvPos ]), IC_BOMB ) != 0 ) if ( FindAttachmentByClass( pObjUsed, IC_BOMB ) != 0 )
{ {
return( TRUE ); return( TRUE );
} }
// WANNE: If there is a tank, it always have ammo to shoot, no check! // WANNE: If there is a tank, it always have ammo to shoot, no check!
if (Item[pSoldier->inv[bInvPos].usItem].cannon) if (Item[usItemUsed].cannon)
{ {
return ( TRUE ); return ( TRUE );
} }
@@ -2385,9 +2401,9 @@ BOOLEAN EnoughAmmo( SOLDIERTYPE *pSoldier, BOOLEAN fDisplay, INT8 bInvPos )
return( FALSE ); return( FALSE );
} }
else if (Item[ pSoldier->inv[ bInvPos ].usItem ].usItemClass == IC_GUN) else if (Item[ usItemUsed ].usItemClass == IC_GUN)
{ {
if ( pSoldier->inv[ bInvPos ][0]->data.gun.ubGunShotsLeft == 0 ) if ( (*pObjUsed)[0]->data.gun.ubGunShotsLeft == 0 )
{ {
if ( fDisplay ) if ( fDisplay )
{ {
@@ -2399,7 +2415,7 @@ BOOLEAN EnoughAmmo( SOLDIERTYPE *pSoldier, BOOLEAN fDisplay, INT8 bInvPos )
//<SB> manual recharge //<SB> manual recharge
if( pSoldier->bTeam == OUR_TEAM ) if( pSoldier->bTeam == OUR_TEAM )
{ {
if ( !( pSoldier->inv[ bInvPos ][0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER ) ) if ( !( (*pObjUsed)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER ) )
{ {
return( FALSE ); return( FALSE );
} }
@@ -2435,24 +2451,14 @@ void DeductAmmo( SOLDIERTYPE *pSoldier, INT8 bInvPos )
} }
else if ( Item[ pObj->usItem ].usItemClass == IC_GUN && !Item[pObj->usItem].cannon && pSoldier->bWeaponMode != WM_ATTACHED_GL && pSoldier->bWeaponMode != WM_ATTACHED_GL_BURST && pSoldier->bWeaponMode != WM_ATTACHED_GL_AUTO ) else if ( Item[ pObj->usItem ].usItemClass == IC_GUN && !Item[pObj->usItem].cannon && pSoldier->bWeaponMode != WM_ATTACHED_GL && pSoldier->bWeaponMode != WM_ATTACHED_GL_BURST && pSoldier->bWeaponMode != WM_ATTACHED_GL_AUTO )
{ {
if ( pSoldier->usAttackingWeapon == pObj->usItem) // Flugente: check for underbarrel weapons and use that object if necessary
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( &(pSoldier->inv[bInvPos]) );
// OK, let's see, don't overrun...
if ( (*pObjUsed)[0]->data.gun.ubGunShotsLeft != 0 )
{ {
// OK, let's see, don't overrun... (*pObjUsed)[0]->data.gun.ubGunShotsLeft--;
if ( (*pObj)[0]->data.gun.ubGunShotsLeft != 0 ) }
{
(*pObj)[0]->data.gun.ubGunShotsLeft--;
//Pulmu: Update weight after firing gun to account for bullets fired
if( gGameExternalOptions.fAmmoDynamicWeight == TRUE)
{
//ADB ubWeight has been removed, see comments in OBJECTTYPE
//pSoldier->inv[HANDPOS].ubWeight = CalculateObjectWeight( &(pSoldier->inv[HANDPOS]));
}
}
}
else
{
// firing an attachment?
}
} }
else if ( Item[ pObj->usItem ].usItemClass == IC_LAUNCHER || Item[pObj->usItem].cannon || pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO ) else if ( Item[ pObj->usItem ].usItemClass == IC_LAUNCHER || Item[pObj->usItem].cannon || pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )
{ {
@@ -2645,7 +2651,9 @@ INT16 GetAPsToAutoReload( SOLDIERTYPE * pSoldier )
INT16 bAPCost = 0, bAPCost2 = 0;; INT16 bAPCost = 0, bAPCost2 = 0;;
CHECKF( pSoldier ); CHECKF( pSoldier );
pObj = &(pSoldier->inv[HANDPOS]);
// Flugente: check for underbarrel weapons and use that object if necessary
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[HANDPOS]) );
//<SB> manual recharge //<SB> manual recharge
if ((*pObj)[0]->data.gun.ubGunShotsLeft && !((*pObj)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) ) if ((*pObj)[0]->data.gun.ubGunShotsLeft && !((*pObj)[0]->data.gun.ubGunState & GS_CARTRIDGE_IN_CHAMBER) )
@@ -2682,7 +2690,9 @@ INT16 GetAPsToAutoReload( SOLDIERTYPE * pSoldier )
if ( pSoldier->IsValidSecondHandShotForReloadingPurposes( ) ) if ( pSoldier->IsValidSecondHandShotForReloadingPurposes( ) )
{ {
pObj = &(pSoldier->inv[SECONDHANDPOS]); // Flugente: check for underbarrel weapons and use that object if necessary
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[SECONDHANDPOS]) );
bExcludeSlot = NO_SLOT; bExcludeSlot = NO_SLOT;
bSlot2 = NO_SLOT; bSlot2 = NO_SLOT;
+180 -161
View File
@@ -358,67 +358,77 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
break; break;
case 430: case 430:
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: case 430");
// SHOOT GUN
// MAKE AN EVENT, BUT ONLY DO STUFF IF WE OWN THE GUY!
SFireWeapon.usSoldierID = pSoldier->ubID;
SFireWeapon.uiUniqueId = pSoldier->uiUniqueSoldierIdValue;
SFireWeapon.sTargetGridNo = pSoldier->sTargetGridNo;
SFireWeapon.bTargetLevel = pSoldier->bTargetLevel;
SFireWeapon.bTargetCubeLevel= pSoldier->bTargetCubeLevel;
if((is_server && pSoldier->ubID<120) || (!is_server && is_client && pSoldier->ubID<20) || (!is_server && !is_client) )
{ {
//only carry on if own werc DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: case 430");
AddGameEvent( S_FIREWEAPON, 0, &SFireWeapon ); // SHOOT GUN
// MAKE AN EVENT, BUT ONLY DO STUFF IF WE OWN THE GUY!
SFireWeapon.usSoldierID = pSoldier->ubID;
SFireWeapon.uiUniqueId = pSoldier->uiUniqueSoldierIdValue;
SFireWeapon.sTargetGridNo = pSoldier->sTargetGridNo;
SFireWeapon.bTargetLevel = pSoldier->bTargetLevel;
SFireWeapon.bTargetCubeLevel= pSoldier->bTargetCubeLevel;
if((is_server && pSoldier->ubID<120) || (!is_server && is_client && pSoldier->ubID<20) || (!is_server && !is_client) )
{
//only carry on if own werc
AddGameEvent( S_FIREWEAPON, 0, &SFireWeapon );
//hayden //hayden
if(is_server || (is_client && pSoldier->ubID <20) ) if(is_server || (is_client && pSoldier->ubID <20) )
send_fireweapon( &SFireWeapon ); send_fireweapon( &SFireWeapon );
}
//DIGICRAB: Burst UnCap
//Loop around in the animation if we still have burst rounds to fire
if (pSoldier->bDoBurst && (pSoldier->bDoBurst <= ((pSoldier->bDoAutofire)?(pSoldier->bDoAutofire):(GetShotsPerBurst(&pSoldier->inv[HANDPOS]))) || (( pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST && pSoldier->bDoBurst <= Weapon[GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS])].ubShotsPerBurst)) ))
{
if(pSoldier->usAnimState == 44 || pSoldier->usAnimState == 109 || pSoldier->usAnimState == 108 && pSoldier->usAniCode == 33) //we are standing, crounching or prone, firing the fast shot
pSoldier->usAniCode = 3;
else if(pSoldier->usAnimState == 175 && pSoldier->usAniCode == 37) //we are firing down to something very close, last shot
pSoldier->usAniCode = 14;
}
//DIGICRAB: Burst Sound
//This code is stolen from Tactical\Weapons.c - UseGun(...)
if (pSoldier->bDoBurst && pSoldier->iBurstSoundID == NO_SAMPLE && Weapon[ pSoldier->usAttackingWeapon ].sSound != 0 && Item[ pSoldier->usAttackingWeapon ].usItemClass != IC_THROWING_KNIFE )
{
// Switch on silencer...
INT16 noisefactor = GetPercentNoiseVolume( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
if( noisefactor < MAX_PERCENT_NOISE_VOLUME_FOR_SILENCED_SOUND || Weapon[ pSoldier->usAttackingWeapon ].ubAttackVolume <= 10 )
{
INT32 uiSound;
uiSound = Weapon [ pSoldier->usAttackingWeapon ].silencedSound;
//if ( Weapon[ pSoldier->usAttackingWeapon ].ubCalibre == AMMO9 || Weapon[ pSoldier->usAttackingWeapon ].ubCalibre == AMMO38 || Weapon[ pSoldier->usAttackingWeapon ].ubCalibre == AMMO57 )
//{
// uiSound = S_SILENCER_1;
//}
//else
//{
// uiSound = S_SILENCER_2;
//}
//randomize the rate a bit so that the sound is more believable
PlayJA2Sample( uiSound, 44100-Random(5000)-Random(5000)-Random(5000), SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
} }
else
OBJECTTYPE* pObjHand = pSoldier->GetUsedWeapon( &pSoldier->inv[HANDPOS] );
//DIGICRAB: Burst UnCap
//Loop around in the animation if we still have burst rounds to fire
if (pSoldier->bDoBurst
&& (
pSoldier->bDoBurst <= ( (pSoldier->bDoAutofire)?(pSoldier->bDoAutofire):(GetShotsPerBurst( pObjHand )) )
|| (( pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST && pSoldier->bDoBurst <= Weapon[GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS])].ubShotsPerBurst))
)
)
{ {
INT8 volume = HIGHVOLUME; if(pSoldier->usAnimState == 44 || pSoldier->usAnimState == 109 || pSoldier->usAnimState == 108 && pSoldier->usAniCode == 33) //we are standing, crounching or prone, firing the fast shot
if ( noisefactor < 100 ) volume = (volume * noisefactor) / 100; pSoldier->usAniCode = 3;
//randomize the rate a bit so that the sound is more believable else if(pSoldier->usAnimState == 175 && pSoldier->usAniCode == 37) //we are firing down to something very close, last shot
PlayJA2Sample( Weapon[ pSoldier->usAttackingWeapon ].sSound, 44100-Random(5000)-Random(5000)-Random(5000), SoundVolume( volume, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) ); pSoldier->usAniCode = 14;
}
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
UINT16 usedGun = pSoldier->GetUsedWeaponNumber( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
//DIGICRAB: Burst Sound
//This code is stolen from Tactical\Weapons.c - UseGun(...)
if (pSoldier->bDoBurst && pSoldier->iBurstSoundID == NO_SAMPLE && Weapon[ usedGun ].sSound != 0 && Item[ usedGun ].usItemClass != IC_THROWING_KNIFE )
{
// Switch on silencer...
INT16 noisefactor = GetPercentNoiseVolume( pObjUsed );
if( noisefactor < MAX_PERCENT_NOISE_VOLUME_FOR_SILENCED_SOUND || Weapon[ usedGun ].ubAttackVolume <= 10 )
{
INT32 uiSound;
uiSound = Weapon [ usedGun ].silencedSound;
//if ( Weapon[ pSoldier->usAttackingWeapon ].ubCalibre == AMMO9 || Weapon[ pSoldier->usAttackingWeapon ].ubCalibre == AMMO38 || Weapon[ pSoldier->usAttackingWeapon ].ubCalibre == AMMO57 )
//{
// uiSound = S_SILENCER_1;
//}
//else
//{
// uiSound = S_SILENCER_2;
//}
//randomize the rate a bit so that the sound is more believable
PlayJA2Sample( uiSound, 44100-Random(5000)-Random(5000)-Random(5000), SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
}
else
{
INT8 volume = HIGHVOLUME;
if ( noisefactor < 100 ) volume = (volume * noisefactor) / 100;
//randomize the rate a bit so that the sound is more believable
PlayJA2Sample( Weapon[ usedGun ].sSound, 44100-Random(5000)-Random(5000)-Random(5000), SoundVolume( volume, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
}
} }
} }
break; break;
case 431: case 431:
@@ -764,133 +774,137 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
case 448: case 448:
// CODE: HANDLE BURST
// FIRST CHECK IF WE'VE REACHED MAX FOR GUN
fStop = FALSE;
if ( ( pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST && pSoldier->bDoBurst > Weapon[GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS])].ubShotsPerBurst) || (pSoldier->bWeaponMode != WM_ATTACHED_GL_BURST && pSoldier->bDoBurst > ((pSoldier->bDoAutofire)?(pSoldier->bDoAutofire):(GetShotsPerBurst(&pSoldier->inv[HANDPOS])))) )
{ {
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because burst size too large"); // CODE: HANDLE BURST
fStop = TRUE; // FIRST CHECK IF WE'VE REACHED MAX FOR GUN
fFreeUpAttacker = TRUE; fStop = FALSE;
}
// CHECK IF WE HAVE AMMO LEFT, IF NOT, END ANIMATION! OBJECTTYPE* pObjHand = pSoldier->GetUsedWeapon( &pSoldier->inv[HANDPOS] );
if ( !EnoughAmmo( pSoldier, FALSE, pSoldier->ubAttackingHand ) )
{ if ( ( pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST && pSoldier->bDoBurst > Weapon[GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS])].ubShotsPerBurst)
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because not enough ammo"); || (pSoldier->bWeaponMode != WM_ATTACHED_GL_BURST && pSoldier->bDoBurst > ((pSoldier->bDoAutofire)?(pSoldier->bDoAutofire):(GetShotsPerBurst( pObjHand )))) )
fStop = TRUE;
fFreeUpAttacker = TRUE;
if ( pSoldier->bTeam == gbPlayerNum )
{ {
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ BURST_FIRE_DEPLETED_CLIP_STR ] ); DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because burst size too large");
}
}
// Why only check for a jam on the first bullet?
else if (pSoldier->bDoBurst == 1)
{
// CHECK FOR GUN JAM
bWeaponJammed = CheckForGunJam( pSoldier );
if ( bWeaponJammed == TRUE )
{
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because weapon jammed");
fStop = TRUE; fStop = TRUE;
fFreeUpAttacker = TRUE; fFreeUpAttacker = TRUE;
// stop shooting! }
// Yeah, but what does this have to do with that?
// pSoldier->bBulletsLeft = 0;
// OK, Stop burst sound...
if ( pSoldier->iBurstSoundID != NO_SAMPLE )
{
SoundStop( pSoldier->iBurstSoundID );
}
// CHECK IF WE HAVE AMMO LEFT, IF NOT, END ANIMATION!
if ( !EnoughAmmo( pSoldier, FALSE, pSoldier->ubAttackingHand ) )
{
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because not enough ammo");
fStop = TRUE;
fFreeUpAttacker = TRUE;
if ( pSoldier->bTeam == gbPlayerNum ) if ( pSoldier->bTeam == gbPlayerNum )
{ {
PlayJA2Sample( S_DRYFIRE1, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ BURST_FIRE_DEPLETED_CLIP_STR ] );
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Gun jammed!" ); }
}
// Why only check for a jam on the first bullet?
else if (pSoldier->bDoBurst == 1)
{
// CHECK FOR GUN JAM
bWeaponJammed = CheckForGunJam( pSoldier );
if ( bWeaponJammed == TRUE )
{
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because weapon jammed");
fStop = TRUE;
fFreeUpAttacker = TRUE;
// stop shooting!
// Yeah, but what does this have to do with that?
// pSoldier->bBulletsLeft = 0;
// OK, Stop burst sound...
if ( pSoldier->iBurstSoundID != NO_SAMPLE )
{
SoundStop( pSoldier->iBurstSoundID );
}
if ( pSoldier->bTeam == gbPlayerNum )
{
PlayJA2Sample( S_DRYFIRE1, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Gun jammed!" );
}
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - aborting start of attack due to burst gun jam") );
FreeUpAttacker( );
}
else if ( bWeaponJammed == 255 )
{
// Play intermediate animation...
if ( HandleUnjamAnimation( pSoldier ) )
{
return( TRUE );
}
}
}
if ( fStop )
{
if(pSoldier->bDoAutofire) //reset the autofire cursor after firing
{
pSoldier->flags.autofireLastStep = FALSE;
pSoldier->bDoAutofire = 1;
} }
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - aborting start of attack due to burst gun jam") ); pSoldier->flags.fDoSpread = FALSE;
FreeUpAttacker( ); pSoldier->bDoBurst = 1;
} // pSoldier->flags.fBurstCompleted = TRUE;
else if ( bWeaponJammed == 255 ) if ( fFreeUpAttacker )
{ {
// Play intermediate animation... // DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - aborting start of attack") );
if ( HandleUnjamAnimation( pSoldier ) ) // FreeUpAttacker( pSoldier->ubID );
}
// ATE; Reduce it due to animation being stopped...
// 0verhaul: No longer necessary or desired
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - Burst animation ended") );
// ReduceAttackBusyCount( pSoldier->ubID, FALSE );
if ( CheckForImproperFireGunEnd( pSoldier ) )
{ {
return( TRUE ); return( TRUE );
} }
}
}
if ( fStop ) // END: GOTO AIM STANCE BASED ON HEIGHT
{ // If we are a robot - we need to do stuff different here
if(pSoldier->bDoAutofire) //reset the autofire cursor after firing // 0verhaul: Ya know, if the robot simply used the same animation for standing and rifle standing,
{ // we probably wouldn't need this special case code.
pSoldier->flags.autofireLastStep = FALSE; if ( AM_A_ROBOT( pSoldier ) )
pSoldier->bDoAutofire = 1; {
} pSoldier->ChangeSoldierState( STANDING, 0 , FALSE );
}
else
{
switch ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
{
case ANIM_STAND:
pSoldier->ChangeSoldierState( AIM_RIFLE_STAND, 0 , FALSE );
break;
pSoldier->flags.fDoSpread = FALSE; case ANIM_PRONE:
pSoldier->bDoBurst = 1; pSoldier->ChangeSoldierState( AIM_RIFLE_PRONE, 0 , FALSE );
// pSoldier->flags.fBurstCompleted = TRUE; break;
if ( fFreeUpAttacker )
{
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - aborting start of attack") );
// FreeUpAttacker( pSoldier->ubID );
}
// ATE; Reduce it due to animation being stopped... case ANIM_CROUCH:
// 0verhaul: No longer necessary or desired pSoldier->ChangeSoldierState( AIM_RIFLE_CROUCH, 0 , FALSE );
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - Burst animation ended") ); break;
// ReduceAttackBusyCount( pSoldier->ubID, FALSE );
}
if ( CheckForImproperFireGunEnd( pSoldier ) ) }
{
return( TRUE ); return( TRUE );
} }
// END: GOTO AIM STANCE BASED ON HEIGHT // MOVETO CURRENT SPREAD LOCATION
// If we are a robot - we need to do stuff different here if ( pSoldier->flags.fDoSpread )
// 0verhaul: Ya know, if the robot simply used the same animation for standing and rifle standing,
// we probably wouldn't need this special case code.
if ( AM_A_ROBOT( pSoldier ) )
{ {
pSoldier->ChangeSoldierState( STANDING, 0 , FALSE ); if ( pSoldier->sSpreadLocations[ pSoldier->flags.fDoSpread - 1 ] != 0 )
}
else
{
switch ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
{ {
case ANIM_STAND: pSoldier->EVENT_SetSoldierDirection( (INT8)GetDirectionToGridNoFromGridNo( pSoldier->sGridNo, pSoldier->sSpreadLocations[ pSoldier->flags.fDoSpread - 1 ] ) );
pSoldier->ChangeSoldierState( AIM_RIFLE_STAND, 0 , FALSE ); pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
break;
case ANIM_PRONE:
pSoldier->ChangeSoldierState( AIM_RIFLE_PRONE, 0 , FALSE );
break;
case ANIM_CROUCH:
pSoldier->ChangeSoldierState( AIM_RIFLE_CROUCH, 0 , FALSE );
break;
} }
} }
return( TRUE );
}
// MOVETO CURRENT SPREAD LOCATION
if ( pSoldier->flags.fDoSpread )
{
if ( pSoldier->sSpreadLocations[ pSoldier->flags.fDoSpread - 1 ] != 0 )
{
pSoldier->EVENT_SetSoldierDirection( (INT8)GetDirectionToGridNoFromGridNo( pSoldier->sGridNo, pSoldier->sSpreadLocations[ pSoldier->flags.fDoSpread - 1 ] ) );
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
}
} }
break; break;
@@ -2381,9 +2395,12 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
usItem = pSoldier->inv[ HANDPOS ].usItem; usItem = pSoldier->inv[ HANDPOS ].usItem;
if ( pSoldier->inv[ HANDPOS ].exists() == true ) OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( &pSoldier->inv[ HANDPOS ] );
UINT16 usItemUsemUsed = pSoldier->GetUsedWeaponNumber( &pSoldier->inv[ HANDPOS ] );
if ( pObjUsed->exists() == true )
{ {
usSoundID = Weapon[ usItem ].sLocknLoadSound; usSoundID = Weapon[ usItemUsemUsed ].sLocknLoadSound;
if ( usSoundID != 0 ) if ( usSoundID != 0 )
{ {
@@ -3977,8 +3994,10 @@ BOOLEAN CheckForImproperFireGunEnd( SOLDIERTYPE *pSoldier )
return( FALSE ); return( FALSE );
} }
OBJECTTYPE* pObjHand = pSoldier->GetUsedWeapon( &pSoldier->inv[ HANDPOS ] );
// Check single hand for jammed status, ( or ammo is out.. ) // Check single hand for jammed status, ( or ammo is out.. )
if ( pSoldier->inv[ HANDPOS ][0]->data.gun.bGunAmmoStatus < 0 || pSoldier->inv[ HANDPOS ][0]->data.gun.ubGunShotsLeft == 0 ) if ( (*pObjHand)[0]->data.gun.bGunAmmoStatus < 0 || (*pObjHand)[0]->data.gun.ubGunShotsLeft == 0 )
{ {
// If we have 2 pistols, donot go back! // If we have 2 pistols, donot go back!
if ( Item[ pSoldier->inv[ SECONDHANDPOS ].usItem ].usItemClass != IC_GUN ) if ( Item[ pSoldier->inv[ SECONDHANDPOS ].usItem ].usItemClass != IC_GUN )
+37 -2
View File
@@ -12911,7 +12911,7 @@ void SOLDIERTYPE::SoldierInventoryCoolDown(void)
attachmentList::iterator iterend = (*pObj)[i]->attachments.end(); attachmentList::iterator iterend = (*pObj)[i]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[i]->attachments.begin(); iter != iterend; ++iter) for (attachmentList::iterator iter = (*pObj)[i]->attachments.begin(); iter != iterend; ++iter)
{ {
if ( iter->exists() && Item[ iter->usItem ].usItemClass & (IC_LAUNCHER|IC_LAUNCHER) ) if ( iter->exists() && Item[ iter->usItem ].usItemClass & (IC_GUN|IC_LAUNCHER) )
{ {
FLOAT temperature = (*iter)[i]->data.bTemperature; // ... get temperature of item ... FLOAT temperature = (*iter)[i]->data.bTemperature; // ... get temperature of item ...
@@ -12934,11 +12934,19 @@ void SOLDIERTYPE::SoldierInventoryCoolDown(void)
} }
} }
// Flugente: determien if we can rest our weapon on something. This can only happen when STANDING/CROUCHED. As a result, we get superior handling modifiers (we apply the PRONE modfiers) // Flugente: determine if we can rest our weapon on something. This can only happen when STANDING/CROUCHED. As a result, we get superior handling modifiers (we apply the PRONE modfiers)
BOOLEAN SOLDIERTYPE::IsWeaponMounted( void ) BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
{ {
BOOLEAN applybipod = FALSE; BOOLEAN applybipod = FALSE;
// we must be active
if ( !bActive)
return( FALSE );
// we must be in a sector (not travelling)
if ( !bInSector )
return( FALSE );
// not possible if already prone // not possible if already prone
if ( gAnimControl[ this->usAnimState ].ubEndHeight == ANIM_PRONE ) if ( gAnimControl[ this->usAnimState ].ubEndHeight == ANIM_PRONE )
return( FALSE ); return( FALSE );
@@ -13022,6 +13030,33 @@ BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
return( applybipod ); return( applybipod );
} }
// Flugente: return weapon currently used
OBJECTTYPE* SOLDIERTYPE::GetUsedWeapon( OBJECTTYPE * pObj )
{
if ( bWeaponMode == WM_ATTACHED_UB || bWeaponMode == WM_ATTACHED_UB_BURST || bWeaponMode == WM_ATTACHED_UB_AUTO )
{
OBJECTTYPE* pObjUnderBarrel = FindAttachment_UnderBarrel(pObj);
if ( pObjUnderBarrel )
return( pObjUnderBarrel );
}
return( pObj );
}
UINT16 SOLDIERTYPE::GetUsedWeaponNumber( OBJECTTYPE * pObj )
{
if ( bWeaponMode == WM_ATTACHED_UB || bWeaponMode == WM_ATTACHED_UB_BURST || bWeaponMode == WM_ATTACHED_UB_AUTO )
{
UINT16 weaponnr = GetAttachedUnderBarrel(pObj);
if ( weaponnr != NONE )
return( weaponnr );
}
return( pObj->usItem );
}
INT32 CheckBleeding( SOLDIERTYPE *pSoldier ) INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
{ {
INT8 bBandaged; //,savedOurTurn; INT8 bBandaged; //,savedOurTurn;
+3 -1
View File
@@ -1319,7 +1319,9 @@ public:
BOOLEAN IsValidSecondHandShotForReloadingPurposes( void ); BOOLEAN IsValidSecondHandShotForReloadingPurposes( void );
BOOLEAN SoldierCarriesTwoHandedWeapon( void ); BOOLEAN SoldierCarriesTwoHandedWeapon( void );
void SoldierInventoryCoolDown( void ); // Flugente FTW 1: Cool down all items in inventory void SoldierInventoryCoolDown( void ); // Flugente FTW 1: Cool down all items in inventory
BOOLEAN IsWeaponMounted( void ); BOOLEAN IsWeaponMounted( void ); // determine if we receive a bonus for mouning our weapon on something
OBJECTTYPE* GetUsedWeapon( OBJECTTYPE * pObj ); // if in an underbarrel fire mode, return underbarrel weapon
UINT16 GetUsedWeaponNumber( OBJECTTYPE * pObj ); // if in an underbarrel fire mode, return number of underbarrel weapon
}; // SOLDIERTYPE; }; // SOLDIERTYPE;
+1 -1
View File
@@ -272,7 +272,7 @@ void HandleTacticalEndTurn( )
#endif #endif
// Flugente FTW 1: Cool down all items not in a soldier's inventory // Flugente FTW 1: Cool down all items not in a soldier's inventory
CoolDownWorldItems(); CoolDownWorldItems( FALSE );
} }
+40 -1
View File
@@ -3959,6 +3959,44 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
} }
} }
} }
if (IsUnderBarrelAttached(pGun))
{
OBJECTTYPE *pGun2 = FindAttachment_UnderBarrel(pGun);
if ( (*pGun2)[0]->data.gun.ubGunShotsLeft < GetMagSize( pGun2 ) )
{
// Search for ammo in sector
for ( UINT32 uiLoop = 0; uiLoop < guiNumWorldItems; uiLoop++ )
{
if ( (gWorldItems[ uiLoop ].bVisible == TRUE) && (gWorldItems[ uiLoop ].fExists) && (gWorldItems[ uiLoop ].usFlags & WORLD_ITEM_REACHABLE) && !(gWorldItems[ uiLoop ].usFlags & WORLD_ITEM_ARMED_BOMB) )//item exists, is reachable, is visible and is not trapped
{
if ( ( Item[ gWorldItems[ uiLoop ].object.usItem ].usItemClass & IC_AMMO ) ) // the item is ammo
{
pAmmo = &( gWorldItems[ uiLoop ].object );
if ( CompatibleAmmoForGun( pAmmo, pGun2 ) ) // can use the ammo with this gun
{
// same ammo type in gun and magazine
if ( Magazine[Item[(*pGun2)[0]->data.gun.usGunAmmoItem].ubClassIndex].ubAmmoType == Magazine[Item[pAmmo->usItem].ubClassIndex].ubAmmoType )
{
ReloadGun( pTeamSoldier, pGun2, pAmmo );
}
if ((*pAmmo)[0]->data.ubShotsLeft == 0)
{
RemoveItemFromPool( gWorldItems[ uiLoop ].sGridNo, uiLoop, gWorldItems[ uiLoop ].ubLevel );
}
}
}
}
}
}
//CHRISL: if not enough ammo in sector, reload using ammo carried in inventory
if ( (*pGun2)[0]->data.gun.ubGunShotsLeft < GetMagSize( pGun2 ) )
{
AutoReload( pTeamSoldier );
}
}
} }
} }
} }
@@ -3978,7 +4016,8 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
{ {
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) ) if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
{ {
pGun = &(pTeamSoldier->inv[HANDPOS]); // Flugente: check for underbarrel weapons and use that object if necessary
pGun = pTeamSoldier->GetUsedWeapon( &(pTeamSoldier->inv[HANDPOS]) );
//magazine is not full //magazine is not full
if ( (*pGun)[0]->data.gun.ubGunShotsLeft < GetMagSize( pGun ) ) if ( (*pGun)[0]->data.gun.ubGunShotsLeft < GetMagSize( pGun ) )
+1 -2
View File
@@ -2574,8 +2574,7 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
return ( TRAJECTORYCURS ); return ( TRAJECTORYCURS );
} }
usInHand = pSoldier->inv[HANDPOS].usItem; usInHand = pSoldier->GetUsedWeaponNumber( &pSoldier->inv[HANDPOS] );
// Start off with what is in our hand // Start off with what is in our hand
ubCursor = Item[ usInHand ].ubCursor; ubCursor = Item[ usInHand ].ubCursor;
+260 -229
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -12,6 +12,9 @@ enum WeaponMode
WM_ATTACHED_GL, WM_ATTACHED_GL,
WM_ATTACHED_GL_BURST, WM_ATTACHED_GL_BURST,
WM_ATTACHED_GL_AUTO, WM_ATTACHED_GL_AUTO,
WM_ATTACHED_UB,
WM_ATTACHED_UB_BURST,
WM_ATTACHED_UB_AUTO,
NUM_WEAPON_MODES NUM_WEAPON_MODES
} ; } ;
+24 -11
View File
@@ -812,7 +812,8 @@ void RefreshWorldItemsIntoItemPools( WORLDITEM * pItemList, INT32 iNumberOfItems
// Flugente FTW 1: Cool down all items in the world (no, really) // Flugente FTW 1: Cool down all items in the world (no, really)
void CoolDownWorldItems( void ) // fSetZero sets all temperatures to 0 (used in old sector upon loading a new sector)
void CoolDownWorldItems( BOOLEAN fSetZero )
{ {
if ( gGameOptions.fWeaponOverheating ) // if Overheating is used ... if ( gGameOptions.fWeaponOverheating ) // if Overheating is used ...
{ {
@@ -829,15 +830,21 @@ void CoolDownWorldItems( void )
{ {
for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ... for(INT16 i = 0; i < pObj->ubNumberOfObjects; ++i) // ... there might be multiple items here (item stack), so for each one ...
{ {
FLOAT guntemperature = (*pObj)[i]->data.bTemperature; // ... get temperature ... FLOAT newguntemperature = 0.0;
FLOAT cooldownfactor = GetItemCooldownFactor(pObj); // ... get item cooldown factor provided of attachments ... if ( !fSetZero && gGameExternalOptions.fSetZeroUponNewSector )
{
FLOAT guntemperature = (*pObj)[i]->data.bTemperature; // ... get temperature ...
if ( Item[gWorldItems[ uiCount ].object.usItem].barrel == TRUE ) // ... a barrel lying around cools down a bit faster ... FLOAT cooldownfactor = GetItemCooldownFactor(pObj); // ... get item cooldown factor provided of attachments ...
cooldownfactor *= gGameExternalOptions.iCooldownModificatorLonelyBarrel;
FLOAT newguntemperatre = max(0.0, guntemperature - cooldownfactor); // ... calculate new temperature ... if ( Item[gWorldItems[ uiCount ].object.usItem].barrel == TRUE ) // ... a barrel lying around cools down a bit faster ...
(*pObj)[i]->data.bTemperature = newguntemperatre; // ... set new temperature cooldownfactor *= gGameExternalOptions.iCooldownModificatorLonelyBarrel;
newguntemperature = max(0.0, guntemperature - cooldownfactor); // ... calculate new temperature ...
}
(*pObj)[i]->data.bTemperature = newguntemperature; // ... set new temperature
#if 0//def JA2TESTVERSION #if 0//def JA2TESTVERSION
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"World: Item temperature lowered from %4.2f to %4.2f", guntemperature, newguntemperatre ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"World: Item temperature lowered from %4.2f to %4.2f", guntemperature, newguntemperatre );
@@ -846,13 +853,19 @@ void CoolDownWorldItems( void )
attachmentList::iterator iterend = (*pObj)[i]->attachments.end(); attachmentList::iterator iterend = (*pObj)[i]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[i]->attachments.begin(); iter != iterend; ++iter) for (attachmentList::iterator iter = (*pObj)[i]->attachments.begin(); iter != iterend; ++iter)
{ {
if ( iter->exists() && Item[ iter->usItem ].usItemClass & (IC_LAUNCHER|IC_LAUNCHER) ) if ( iter->exists() && Item[ iter->usItem ].usItemClass & (IC_GUN|IC_LAUNCHER) )
{ {
FLOAT temperature = (*iter)[i]->data.bTemperature; // ... get temperature of item ... FLOAT newtemperature = 0.0;
FLOAT cooldownfactor = GetItemCooldownFactor( &(*iter) ); // ... get cooldown factor ... if ( !fSetZero && gGameExternalOptions.fSetZeroUponNewSector )
{
FLOAT temperature = (*iter)[i]->data.bTemperature; // ... get temperature of item ...
FLOAT cooldownfactor = GetItemCooldownFactor( &(*iter) ); // ... get cooldown factor ...
newtemperature = max(0.0, temperature - cooldownfactor); // ... calculate new temperature ...
}
FLOAT newtemperature = max(0.0, temperature - cooldownfactor); // ... calculate new temperature ...
(*iter)[i]->data.bTemperature = newtemperature; // ... set new temperature (*iter)[i]->data.bTemperature = newtemperature; // ... set new temperature
#if 0//def JA2TESTVERSION #if 0//def JA2TESTVERSION
+1 -1
View File
@@ -119,6 +119,6 @@ extern void FindPanicBombsAndTriggers( void );
extern INT32 FindWorldItemForBombInGridNo( INT32 sGridNo, INT8 bLevel); extern INT32 FindWorldItemForBombInGridNo( INT32 sGridNo, INT8 bLevel);
void RefreshWorldItemsIntoItemPools( WORLDITEM * pItemList, INT32 iNumberOfItems ); void RefreshWorldItemsIntoItemPools( WORLDITEM * pItemList, INT32 iNumberOfItems );
void CoolDownWorldItems( void ); // Flugente FTW 1: Cool down all items in the world (no, really) void CoolDownWorldItems( BOOLEAN fSetZero = FALSE ); // Flugente FTW 1: Cool down all items in the world (no, really)
#endif #endif
+3
View File
@@ -2060,6 +2060,9 @@ enum
MSG113_GL, MSG113_GL,
MSG113_GL_BRST, MSG113_GL_BRST,
MSG113_GL_AUTO, MSG113_GL_AUTO,
MSG113_UB,
MSG113_UB_BRST,
MSG113_UB_AUTO,
MSG113_SNIPER, MSG113_SNIPER,
MSG113_UNABLETOSPLITMONEY, MSG113_UNABLETOSPLITMONEY,
MSG113_ARRIVINGREROUTED, MSG113_ARRIVINGREROUTED,
+3
View File
@@ -6051,6 +6051,9 @@ STR16 New113Message[] =
L"榴弹", L"榴弹",
L"榴弹点射", L"榴弹点射",
L"榴弹自动", L"榴弹自动",
L"UB", // TODO.Translate, INFO: UB = Under Barrel
L"UBRST",
L"UAUTO",
L"狙击手!", L"狙击手!",
L"已经点选物品,此时无法分钱。", L"已经点选物品,此时无法分钱。",
L"新兵的会合地被挪至 %s, 因降落地点 %s 目前由敌人占据。", L"新兵的会合地被挪至 %s, 因降落地点 %s 目前由敌人占据。",
+3
View File
@@ -6053,6 +6053,9 @@ STR16 New113Message[] =
L"GL", L"GL",
L"GL BRST", L"GL BRST",
L"GL AUTO", L"GL AUTO",
L"UB",
L"UBRST",
L"UAUTO",
L"Sniper!", L"Sniper!",
L"Unable to split money due to having an item on your cursor.", L"Unable to split money due to having an item on your cursor.",
L"Arrival of new recruits is being rerouted to sector %s, as scheduled drop-off point of sector %s is enemy occupied.", L"Arrival of new recruits is being rerouted to sector %s, as scheduled drop-off point of sector %s is enemy occupied.",
+3
View File
@@ -6051,6 +6051,9 @@ STR16 New113Message[] =
L"GL", L"GL",
L"GL BRST", L"GL BRST",
L"GL AUTO", L"GL AUTO",
L"UB",
L"UBRST",
L"UAUTO",
L"Sniper!", L"Sniper!",
L"Unable to split money due to having an item on your cursor.", L"Unable to split money due to having an item on your cursor.",
L"Arrival of new recruits is being rerouted to sector %s, as scheduled drop-off point of sector %s is enemy occupied.", L"Arrival of new recruits is being rerouted to sector %s, as scheduled drop-off point of sector %s is enemy occupied.",
+3
View File
@@ -6035,6 +6035,9 @@ STR16 New113Message[] =
L"LG", L"LG",
L"RAF. LG", L"RAF. LG",
L"LG AUTO", L"LG AUTO",
L"UB", // TODO.Translate
L"UBRST",
L"UAUTO",
L"Tireur embusqué !", L"Tireur embusqué !",
L"Unable to split money due to having an item on your cursor.", L"Unable to split money due to having an item on your cursor.",
L"Arrivée de nouvelles recrues est déroutée au secteur %s, car le point d'arrivée prévu %s est sous contrôle ennemi.", L"Arrivée de nouvelles recrues est déroutée au secteur %s, car le point d'arrivée prévu %s est sous contrôle ennemi.",
+3
View File
@@ -5880,6 +5880,9 @@ STR16 New113Message[] =
L"GL", L"GL",
L"GL BRST", L"GL BRST",
L"GL AUTO", L"GL AUTO",
L"UB",
L"UBRST",
L"UAUTO",
L"Scharfschütze!", L"Scharfschütze!",
L"Geld kann nicht aufgeteilt werden, weil ein Gegenstand am Cursor ist.", L"Geld kann nicht aufgeteilt werden, weil ein Gegenstand am Cursor ist.",
L"Ankunft der neuen Söldner wurde in den Sektor %s verlegt, weil der geplante Sektor %s von Feinden belagert ist.", L"Ankunft der neuen Söldner wurde in den Sektor %s verlegt, weil der geplante Sektor %s von Feinden belagert ist.",
+3
View File
@@ -6042,6 +6042,9 @@ STR16 New113Message[] =
L"GL", L"GL",
L"GL BRST", L"GL BRST",
L"GL AUTO", L"GL AUTO",
L"UB",
L"UBRST",
L"UAUTO",
L"Sniper!", L"Sniper!",
L"Unable to split money due to having an item on your cursor.", L"Unable to split money due to having an item on your cursor.",
L"Arrival of new recruits is being rerouted to sector %s, as scheduled drop-off point of sector %s is enemy occupied.", L"Arrival of new recruits is being rerouted to sector %s, as scheduled drop-off point of sector %s is enemy occupied.",
+3
View File
@@ -6048,6 +6048,9 @@ STR16 New113Message[] =
L"GL", L"GL",
L"GL BRST", L"GL BRST",
L"GL AUTO", L"GL AUTO",
L"UB", // TODO.Translate
L"UBRST",
L"UAUTO",
L"Snajper!", L"Snajper!",
L"Nie można podzielić pieniędzy z powodu przedmiotu na kursorze.", L"Nie można podzielić pieniędzy z powodu przedmiotu na kursorze.",
L"Przybycie nowych rekrutów zostało przekierowane do sektora %s , z uwagi na to, że poprzedni punkt zrzutu w sektorze %s jest zajęty przez wroga.", L"Przybycie nowych rekrutów zostało przekierowane do sektora %s , z uwagi na to, że poprzedni punkt zrzutu w sektorze %s jest zajęty przez wroga.",
+3
View File
@@ -6028,6 +6028,9 @@ STR16 New113Message[] =
L"ГР", L"ГР",
L"ГР *", L"ГР *",
L"ГР ***", L"ГР ***",
L"UB", // TODO.Translate
L"UBRST",
L"UAUTO",
L"Снайпер!", L"Снайпер!",
L"Невозможно разделить деньги из-за предмета на курсоре.", L"Невозможно разделить деньги из-за предмета на курсоре.",
L"Точка высадки новых наемников перенесена в %s, так как предыдущая точка высадки %s захвачена противником.", L"Точка высадки новых наемников перенесена в %s, так как предыдущая точка высадки %s захвачена противником.",
+3
View File
@@ -6055,6 +6055,9 @@ STR16 New113Message[] =
L"GL", L"GL",
L"GL BRST", L"GL BRST",
L"GL AUTO", L"GL AUTO",
L"UB",
L"UBRST",
L"UAUTO",
L"Sniper!", L"Sniper!",
L"Unable to split money due to having an item on your cursor.", L"Unable to split money due to having an item on your cursor.",
L"Arrival of new recruits is being rerouted to sector %s, as scheduled drop-off point of sector %s is enemy occupied.", L"Arrival of new recruits is being rerouted to sector %s, as scheduled drop-off point of sector %s is enemy occupied.",