mirror of
https://github.com/1dot13/source.git
synced 2026-09-02 14:36:06 +02:00
The new <BarrelConfiguration>-tag specifies how many bullets a gun shoots at once. Several values can be used. If no value is set, 1 will be used.
Toggling fire modes cycles between barrel configurations if several have been set. Requires GameDir >= r2461 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8652 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -4084,6 +4084,21 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
|
||||
++cnt;
|
||||
}
|
||||
|
||||
///////////////////// MULTIPLE BARRELS
|
||||
if ( ( Item[gpItemDescObject->usItem].usItemClass & IC_BOBBY_GUN ) )
|
||||
{
|
||||
if ( !fDrawGenIndexes )
|
||||
fDrawGenIndexes = ++cnt; // new index line here?
|
||||
|
||||
if ( cnt >= sFirstLine && cnt < sLastLine )
|
||||
{
|
||||
swprintf( pStr, L"%s%s", szUDBAdvStatsTooltipText[67], szUDBAdvStatsExplanationsTooltipText[67] );
|
||||
SetRegionFastHelpText( &( gUDBFasthelpRegions[iFirstDataRegion + ( cnt - sFirstLine )] ), pStr );
|
||||
MSYS_EnableRegion( &gUDBFasthelpRegions[iFirstDataRegion + ( cnt - sFirstLine )] );
|
||||
}
|
||||
++cnt;
|
||||
}
|
||||
|
||||
if ( UsingFoodSystem() && Item[gpItemDescObject->usItem].foodtype > 0 )
|
||||
{
|
||||
if (!fDrawGenIndexes)
|
||||
@@ -5766,6 +5781,16 @@ void DrawAdvancedStats( OBJECTTYPE * gpItemDescObject )
|
||||
++cnt;
|
||||
}
|
||||
|
||||
///////////////////// MULTIPLE BARRELS
|
||||
if ( ( ( Item[gpItemDescObject->usItem].usItemClass & IC_BOBBY_GUN ) || ( fComparisonMode && ( Item[gpComparedItemDescObject->usItem].usItemClass & IC_BOBBY_GUN ) ) ) )
|
||||
{
|
||||
if ( cnt >= sFirstLine && cnt < sLastLine )
|
||||
{
|
||||
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoAdvancedIcon, 66, gItemDescAdvRegions[cnt - sFirstLine][0].sLeft + sOffsetX, gItemDescAdvRegions[cnt - sFirstLine][0].sTop + sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
|
||||
}
|
||||
++cnt;
|
||||
}
|
||||
|
||||
if ( UsingFoodSystem() )
|
||||
{
|
||||
if ( ( Item[gpItemDescObject->usItem].foodtype > 0 ) ||
|
||||
@@ -10075,7 +10100,7 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
|
||||
INT16 sLastLine = gubDescBoxLine + NUM_UDB_ADV_LINES;
|
||||
INT16 cnt = 0;
|
||||
|
||||
static CHAR16 pStr[ 100 ];
|
||||
static CHAR16 pStr[ 100 ], pStr2[100];
|
||||
INT16 usY;
|
||||
INT16 usX;
|
||||
INT16 sLeft, sTop, sWidth, sHeight;
|
||||
@@ -14095,6 +14120,55 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
|
||||
++cnt;
|
||||
}
|
||||
|
||||
///////////////////// MULTIPLE BARRELS
|
||||
if ( ( ( Item[gpItemDescObject->usItem].usItemClass & ( IC_GUN | IC_LAUNCHER ) ) || ( fComparisonMode && Item[gpComparedItemDescObject->usItem].usItemClass & ( IC_GUN | IC_LAUNCHER ) ) ) )
|
||||
{
|
||||
if ( !fDrawGenIndexes )
|
||||
fDrawGenIndexes = ++cnt; //insert Indexes here?
|
||||
|
||||
if ( cnt >= sFirstLine && cnt < sLastLine )
|
||||
{
|
||||
// Set Y coordinates
|
||||
sTop = gItemDescAdvRegions[cnt - sFirstLine][1].sTop;
|
||||
sHeight = gItemDescAdvRegions[cnt - sFirstLine][1].sBottom - sTop;
|
||||
|
||||
// list all modes
|
||||
swprintf( pStr, L"" );
|
||||
swprintf( pStr2, L"" );
|
||||
|
||||
std::vector<UINT8> tmp = Weapon[Item[gpItemDescObject->usItem].ubClassIndex].barrelconfigurations;
|
||||
|
||||
for ( std::vector<UINT8>::iterator it = tmp.begin(); it != tmp.end(); ++it )
|
||||
{
|
||||
UINT8 bla = ( *it );
|
||||
swprintf( pStr2, L"%s x%d", pStr, bla );
|
||||
swprintf( pStr, L"%s", pStr2 );
|
||||
}
|
||||
|
||||
if ( ( fComparisonMode && Item[gpComparedItemDescObject->usItem].usItemClass & ( IC_GUN | IC_LAUNCHER ) ) )
|
||||
{
|
||||
wcscat( pStr, L" / " );
|
||||
|
||||
std::vector<UINT8> tmp2 = Weapon[Item[gpComparedItemDescObject->usItem].ubClassIndex].barrelconfigurations;
|
||||
|
||||
for ( std::vector<UINT8>::iterator it = tmp2.begin(); it != tmp2.end(); ++it )
|
||||
{
|
||||
swprintf( pStr2, L"%s x%d", pStr, ( *it ) );
|
||||
swprintf( pStr, L"%s", pStr2 );
|
||||
}
|
||||
}
|
||||
|
||||
SetFontForeground( 5 );
|
||||
sLeft = gItemDescAdvRegions[cnt - sFirstLine][1].sLeft;
|
||||
sWidth = gItemDescAdvRegions[cnt - sFirstLine][1].sRight - sLeft;
|
||||
|
||||
FindFontCenterCoordinates( sLeft, sTop, sWidth, sHeight, pStr, BLOCKFONT2, &usX, &usY );
|
||||
mprintf( usX, usY, pStr );
|
||||
}
|
||||
|
||||
++cnt;
|
||||
}
|
||||
|
||||
////////////////////// FOOD
|
||||
if ( UsingFoodSystem() )
|
||||
{
|
||||
|
||||
@@ -4191,10 +4191,16 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
|
||||
}
|
||||
}
|
||||
|
||||
if ( pSoldier && pObject == &(pSoldier->inv[HANDPOS] ) && pSoldier->bWeaponMode != WM_NORMAL && Item[pSoldier->inv[HANDPOS].usItem].usItemClass & IC_GUN )
|
||||
if ( pSoldier && pObject == &(pSoldier->inv[HANDPOS] ) && Item[pSoldier->inv[HANDPOS].usItem].usItemClass & (IC_GUN|IC_LAUNCHER) )
|
||||
{
|
||||
sNewY = sY + 13; // rather arbitrary
|
||||
if ( pSoldier->bWeaponMode == WM_BURST )
|
||||
|
||||
if ( pSoldier->bWeaponMode == WM_NORMAL )
|
||||
{
|
||||
swprintf( pStr, L"" );
|
||||
SetFontForeground( FONT_RED );
|
||||
}
|
||||
else if ( pSoldier->bWeaponMode == WM_BURST )
|
||||
{
|
||||
swprintf( pStr, New113Message[MSG113_BRST] );
|
||||
SetFontForeground( FONT_RED );
|
||||
@@ -4239,9 +4245,15 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
|
||||
swprintf( pStr, New113Message[MSG113_BAYONET] );
|
||||
SetFontForeground( FONT_ORANGE );
|
||||
}
|
||||
|
||||
// Flugente: display barrel mode if necessary
|
||||
if ( pSoldier->usBarrelMode > 1 )
|
||||
swprintf( pStr2, L"%s x%d", pStr, pSoldier->usBarrelMode );
|
||||
else
|
||||
swprintf( pStr2, L"%s", pStr );
|
||||
|
||||
// Get length of string
|
||||
uiStringLength=StringPixLength(pStr, ITEM_FONT );
|
||||
uiStringLength=StringPixLength( pStr2, ITEM_FONT );
|
||||
|
||||
sNewX = sX + sWidth - uiStringLength - 4;
|
||||
|
||||
@@ -4249,10 +4261,11 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
|
||||
{
|
||||
RestoreExternBackgroundRect( sNewX, sNewY, 15, 15 );
|
||||
}
|
||||
mprintf( sNewX, sNewY, pStr );
|
||||
gprintfinvalidate( sNewX, sNewY, pStr );
|
||||
|
||||
mprintf( sNewX, sNewY, pStr2 );
|
||||
gprintfinvalidate( sNewX, sNewY, pStr2 );
|
||||
}
|
||||
|
||||
// SANDRO - display BRST/AUTO on the second weapon too, if we are going to fire dual bursts
|
||||
if ( pSoldier && pObject == &(pSoldier->inv[SECONDHANDPOS] ) &&
|
||||
(pSoldier->bWeaponMode == WM_BURST || pSoldier->bWeaponMode == WM_AUTOFIRE) &&
|
||||
|
||||
@@ -13842,6 +13842,10 @@ void SOLDIERTYPE::ReLoadSoldierAnimationDueToHandItemChange( UINT16 usOldItem, U
|
||||
else
|
||||
this->bScopeMode = USE_BEST_SCOPE;
|
||||
|
||||
// Flugente: use lowest valid barrel configuration
|
||||
this->usBarrelMode = 1;
|
||||
this->usBarrelMode = GetNextBarrelMode( usNewItem, this->usBarrelMode );
|
||||
|
||||
if ( gAnimControl[this->usAnimState].uiFlags & ANIM_FIREREADY )
|
||||
{
|
||||
// Stop aiming!
|
||||
|
||||
@@ -1549,7 +1549,12 @@ public:
|
||||
|
||||
// Flugente: Decrease this filler by 1 for each new UINT8 / BOOLEAN variable, so we can maintain savegame compatibility!!
|
||||
// Note that we also have to account for padding, so you might need to substract more than just the size of the new variables
|
||||
UINT8 ubFiller[16];
|
||||
UINT8 ubFiller[12];
|
||||
UINT8 ubFiller1[2];
|
||||
|
||||
// Flugente: keep track of data for multi-barrel guns
|
||||
UINT8 usBarrelMode; // states how many barrels we are currently using as modifier for our fire mode
|
||||
UINT8 usBarrelCounter; // states which barrel we are currently firing from (used during the firing process)
|
||||
|
||||
// Flugente: focus skill gridno
|
||||
INT32 sFocusGridNo;
|
||||
|
||||
+193
-38
@@ -103,10 +103,15 @@ extern BOOLEAN gfNextFireJam;
|
||||
|
||||
BOOLEAN WillExplosiveWeaponFail( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj );
|
||||
|
||||
// Flugente: this function calls UseGun and handles the firing of severeal shots at once
|
||||
BOOLEAN UseGunWrapper( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo );
|
||||
BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo );
|
||||
BOOLEAN UseGunNCTH( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo );
|
||||
BOOLEAN UseBlade( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo );
|
||||
BOOLEAN UseThrown( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo );
|
||||
|
||||
// Flugente: this function calls UseLauncher and handles the firing of severeal shots at once
|
||||
BOOLEAN UseLauncherWrapper( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo );
|
||||
BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo );
|
||||
|
||||
// new subroutines for NCTH calculation
|
||||
@@ -374,6 +379,9 @@ struct
|
||||
}
|
||||
typedef weaponParseData;
|
||||
|
||||
// for compliation reasons, this may not be a part of weaponParseData
|
||||
std::vector<UINT8> barrelconfigurationvector;
|
||||
|
||||
static void XMLCALL
|
||||
weaponStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
@@ -443,7 +451,8 @@ weaponStartElementHandle(void *userData, const XML_Char *name, const XML_Char **
|
||||
strcmp(name, "usOverheatingDamageThreshold") == 0 || // Flugente
|
||||
strcmp(name, "usOverheatingSingleShotTemperature") == 0 || // Flugente
|
||||
strcmp(name, "HeavyGun") == 0 || // SANDRO - cannot be shouldered while standing
|
||||
strcmp(name, "fBurstOnlyByFanTheHammer" ) == 0))
|
||||
strcmp(name, "fBurstOnlyByFanTheHammer" ) == 0 ||
|
||||
strcmp(name, "BarrelConfiguration" ) == 0))
|
||||
{
|
||||
pData->curElement = WEAPON_ELEMENT_WEAPON_PROPERY;
|
||||
|
||||
@@ -488,6 +497,21 @@ weaponEndElementHandle(void *userData, const XML_Char *name)
|
||||
if(pData->curWeapon.uiIndex < pData->maxWeapons)
|
||||
{
|
||||
pData->curWeaponList[pData->curWeapon.uiIndex] = pData->curWeapon; //write the weapon into the table
|
||||
|
||||
if ( !barrelconfigurationvector.empty() )
|
||||
{
|
||||
for ( std::vector<UINT8>::iterator it = barrelconfigurationvector.begin(), itend = barrelconfigurationvector.end(); it != itend; ++it )
|
||||
{
|
||||
pData->curWeaponList[pData->curWeapon.uiIndex].barrelconfigurations.push_back( (*it) );
|
||||
}
|
||||
|
||||
barrelconfigurationvector.clear();
|
||||
}
|
||||
// if no configuration is set, assume one barrel is possible
|
||||
else
|
||||
{
|
||||
pData->curWeaponList[pData->curWeapon.uiIndex].barrelconfigurations.push_back( 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, "uiIndex") == 0)
|
||||
@@ -733,6 +757,14 @@ weaponEndElementHandle(void *userData, const XML_Char *name)
|
||||
pData->curElement = WEAPON_ELEMENT_WEAPON;
|
||||
pData->curWeapon.fBurstOnlyByFanTheHammer = (BOOLEAN)atof( pData->szCharData );
|
||||
}
|
||||
else if ( strcmp( name, "BarrelConfiguration" ) == 0 )
|
||||
{
|
||||
pData->curElement = WEAPON_ELEMENT_WEAPON;
|
||||
|
||||
UINT8 barrelmode = (UINT8)atol( pData->szCharData );
|
||||
if ( barrelmode )
|
||||
barrelconfigurationvector.push_back( barrelmode );
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
@@ -906,13 +938,17 @@ BOOLEAN WriteWeaponStats()
|
||||
FilePrintf(hFile,"\t\t<ubAimLevels>%d</ubAimLevels>\r\n", Weapon[cnt].ubAimLevels );
|
||||
FilePrintf(hFile,"\t\t<EasyUnjam>%d</EasyUnjam>\r\n", Weapon[cnt].EasyUnjam);
|
||||
FilePrintf(hFile,"\t\t<Handling>%d</Handling>\r\n", Weapon[cnt].ubHandling);
|
||||
FilePrintf(hFile,"\t\t<usOverheatingJamThreshold>%4.2f</usOverheatingJamThreshold>\r\n", Weapon[cnt].usOverheatingJamThreshold); // Flugente FTW 1
|
||||
FilePrintf(hFile,"\t\t<usOverheatingJamThreshold>%4.2f</usOverheatingJamThreshold>\r\n", Weapon[cnt].usOverheatingJamThreshold);
|
||||
FilePrintf(hFile,"\t\t<usOverheatingDamageThreshold>%4.2f</usOverheatingDamageThreshold>\r\n", Weapon[cnt].usOverheatingDamageThreshold);
|
||||
FilePrintf(hFile,"\t\t<usOverheatingSingleShotTemperature>%4.2f</usOverheatingSingleShotTemperature>\r\n", Weapon[cnt].usOverheatingSingleShotTemperature);
|
||||
FilePrintf(hFile,"\t\t<HeavyGun>%d</HeavyGun>\r\n", Weapon[cnt].HeavyGun);
|
||||
FilePrintf(hFile,"\t\t<fBurstOnlyByFanTheHammer>%d</fBurstOnlyByFanTheHammer>\r\n", Weapon[cnt].fBurstOnlyByFanTheHammer );
|
||||
|
||||
|
||||
for ( std::vector<UINT8>::iterator it = Weapon[cnt].barrelconfigurations.begin(), itend = Weapon[cnt].barrelconfigurations.end(); it != itend; ++it )
|
||||
{
|
||||
FilePrintf( hFile, "\t\t<BarrelConfiguration>%d</BarrelConfiguration>\r\n", (*it) );
|
||||
}
|
||||
|
||||
FilePrintf(hFile,"\t</WEAPON>\r\n");
|
||||
}
|
||||
FilePrintf(hFile,"</WEAPONLIST>\r\n");
|
||||
@@ -1496,7 +1532,7 @@ BOOLEAN FireWeapon( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
case IC_GUN:
|
||||
|
||||
if ( pSoldier->bWeaponMode == WM_ATTACHED_GL )
|
||||
UseLauncher ( pSoldier, sTargetGridNo );
|
||||
UseLauncherWrapper ( pSoldier, sTargetGridNo );
|
||||
else
|
||||
{
|
||||
// ATE: PAtch up - bookkeeping for spreading done out of whak
|
||||
@@ -1530,15 +1566,14 @@ BOOLEAN FireWeapon( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( pSoldier->flags.fDoSpread )
|
||||
{
|
||||
UseGun( pSoldier, pSoldier->sSpreadLocations[ pSoldier->flags.fDoSpread - 1 ] );
|
||||
UseGunWrapper( pSoldier, pSoldier->sSpreadLocations[pSoldier->flags.fDoSpread - 1] );
|
||||
pSoldier->flags.fDoSpread++;
|
||||
}
|
||||
else
|
||||
{
|
||||
UseGun( pSoldier, sTargetGridNo );
|
||||
UseGunWrapper( pSoldier, sTargetGridNo );
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1552,7 +1587,7 @@ BOOLEAN FireWeapon( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
|
||||
case IC_LAUNCHER:
|
||||
if ( Item[pSoldier->usAttackingWeapon].rocketlauncher ){
|
||||
UseGun( pSoldier, sTargetGridNo );
|
||||
UseGunWrapper( pSoldier, sTargetGridNo );
|
||||
} else {
|
||||
// ATE: PAtch up - bookkeeping for spreading done out of whak
|
||||
if ( pSoldier->flags.fDoSpread)
|
||||
@@ -1584,12 +1619,12 @@ BOOLEAN FireWeapon( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
|
||||
if ( pSoldier->flags.fDoSpread )
|
||||
{
|
||||
UseLauncher( pSoldier, pSoldier->sSpreadLocations[ pSoldier->flags.fDoSpread - 1 ] );
|
||||
UseLauncherWrapper( pSoldier, pSoldier->sSpreadLocations[ pSoldier->flags.fDoSpread - 1 ] );
|
||||
pSoldier->flags.fDoSpread++;
|
||||
}
|
||||
else
|
||||
{
|
||||
UseLauncher( pSoldier, sTargetGridNo );
|
||||
UseLauncherWrapper( pSoldier, sTargetGridNo );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2304,7 +2339,8 @@ BOOLEAN UseGunNCTH( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
|
||||
MakeNoise( pSoldier->ubID, pSoldier->sGridNo, pSoldier->pathing.bLevel, pSoldier->bOverTerrainType, ubVolume, NOISE_GUNFIRE );
|
||||
|
||||
if ( pSoldier->bDoBurst )
|
||||
// Flugente: if we fire multiple barrels, only do this on first one
|
||||
if ( pSoldier->bDoBurst && !pSoldier->usBarrelCounter )
|
||||
{
|
||||
// done, if bursting, increment
|
||||
pSoldier->bDoBurst++;
|
||||
@@ -2420,6 +2456,77 @@ BOOLEAN UseGunNCTH( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
// Flugente: functions for using several barrels at once
|
||||
UINT8 GetNextBarrelMode( UINT16 usItem, UINT8 aBarrelMode )
|
||||
{
|
||||
if ( ( Item[usItem].usItemClass & IC_BOBBY_GUN ) )
|
||||
{
|
||||
std::vector<UINT8> tmp = Weapon[Item[usItem].ubClassIndex].barrelconfigurations;
|
||||
|
||||
for ( std::vector<UINT8>::iterator it = tmp.begin(); it != tmp.end(); ++it )
|
||||
{
|
||||
if ( ( *it ) > aBarrelMode )
|
||||
return ( *it );
|
||||
}
|
||||
|
||||
// if nothing was found, take the first result
|
||||
if ( !tmp.empty() )
|
||||
return tmp[0];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Flugente: return a number of barrels this gun can fire, equal or below aBarrelMode
|
||||
UINT8 GetFittingBarrelMode( UINT16 usItem, UINT8 aBarrelMode )
|
||||
{
|
||||
UINT8 bestfound = 1;
|
||||
|
||||
if ( ( Item[usItem].usItemClass & IC_BOBBY_GUN ) )
|
||||
{
|
||||
std::vector<UINT8> tmp = Weapon[Item[usItem].ubClassIndex].barrelconfigurations;
|
||||
|
||||
for ( std::vector<UINT8>::reverse_iterator it = tmp.rbegin(); it != tmp.rend(); ++it )
|
||||
{
|
||||
if ( ( *it ) == aBarrelMode )
|
||||
return ( *it );
|
||||
|
||||
if ( ( *it ) < aBarrelMode )
|
||||
{
|
||||
if ( ( *it ) > bestfound )
|
||||
bestfound = ( *it );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestfound;
|
||||
}
|
||||
|
||||
// Flugente: this function calls UseGun and handles the firing of severeal shots at once
|
||||
BOOLEAN UseGunWrapper( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
|
||||
{
|
||||
// determine how many barrels to fire - if we want more than 1, check whether the gun supports this, if not, adjust
|
||||
UINT8 barrelstofire = 1;
|
||||
pSoldier->usBarrelMode = max( 1, pSoldier->usBarrelMode );
|
||||
if ( pSoldier->usBarrelMode > barrelstofire )
|
||||
{
|
||||
// determine how many barrels the gun can fire in the first place (we need this check in case the weapon changed in our hands or we firing a different weapon from the second hand)
|
||||
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( &pSoldier->inv[pSoldier->ubAttackingHand] );
|
||||
|
||||
barrelstofire = GetFittingBarrelMode( pObjUsed->usItem, pSoldier->usBarrelMode );
|
||||
|
||||
// limit shots by ammo
|
||||
barrelstofire = min( barrelstofire, ( *pObjUsed )[0]->data.gun.ubGunShotsLeft );
|
||||
}
|
||||
|
||||
for ( pSoldier->usBarrelCounter = 0; pSoldier->usBarrelCounter < barrelstofire; ++pSoldier->usBarrelCounter )
|
||||
{
|
||||
UseGun( pSoldier, sTargetGridNo );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
{
|
||||
if(UsingNewCTHSystem() == true)
|
||||
@@ -2504,7 +2611,9 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
*/
|
||||
}
|
||||
|
||||
DeductPoints( pSoldier, sAPCost, iBPCost, AFTERSHOT_INTERRUPT );
|
||||
// Flugente: if we fire multiple barrels, only deduct points APs on the first one
|
||||
if ( !pSoldier->usBarrelCounter )
|
||||
DeductPoints( pSoldier, sAPCost, iBPCost, AFTERSHOT_INTERRUPT );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2516,12 +2625,16 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
// only deduct APs when the main gun fires
|
||||
if ( pSoldier->ubAttackingHand == HANDPOS )
|
||||
{
|
||||
DeductPoints( pSoldier, sAPCost, iBPCost, AFTERSHOT_INTERRUPT );
|
||||
// Flugente: if we fire multiple barrels, only deduct points APs on the first one
|
||||
if ( !pSoldier->usBarrelCounter )
|
||||
DeductPoints( pSoldier, sAPCost, iBPCost, AFTERSHOT_INTERRUPT );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DeductPoints( pSoldier, sAPCost, iBPCost, AFTERSHOT_INTERRUPT );
|
||||
// Flugente: if we fire multiple barrels, only deduct points APs on the first one
|
||||
if ( !pSoldier->usBarrelCounter )
|
||||
DeductPoints( pSoldier, sAPCost, iBPCost, AFTERSHOT_INTERRUPT );
|
||||
}
|
||||
|
||||
//PLAY SOUND
|
||||
@@ -3003,7 +3116,8 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
|
||||
MakeNoise( pSoldier->ubID, pSoldier->sGridNo, pSoldier->pathing.bLevel, pSoldier->bOverTerrainType, ubVolume, NOISE_GUNFIRE );
|
||||
|
||||
if ( pSoldier->bDoBurst )
|
||||
// Flugente: if we fire multiple barrels, only do this on first one
|
||||
if ( pSoldier->bDoBurst && !pSoldier->usBarrelCounter )
|
||||
{
|
||||
// done, if bursting, increment
|
||||
pSoldier->bDoBurst++;
|
||||
@@ -4183,6 +4297,30 @@ BOOLEAN UseThrown( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
// Flugente: this function calls UseLauncher and handles the firing of severeal shots at once
|
||||
BOOLEAN UseLauncherWrapper( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
|
||||
{
|
||||
// determine how many barrels to fire - if we want more than 1, check whether the gun supports this, if not, adjust
|
||||
UINT8 barrelstofire = 1;
|
||||
pSoldier->usBarrelMode = max( 1, pSoldier->usBarrelMode );
|
||||
if ( pSoldier->usBarrelMode > barrelstofire )
|
||||
{
|
||||
// determine how many barrels the gun can fire in the first place (we need this check in case the weapon changed in our hands or we firing a different weapon from the second hand)
|
||||
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( &pSoldier->inv[pSoldier->ubAttackingHand] );
|
||||
|
||||
barrelstofire = GetFittingBarrelMode( pObjUsed->usItem, pSoldier->usBarrelMode );
|
||||
|
||||
// limit shots by ammo
|
||||
//barrelstofire = min( barrelstofire, ( *pObjUsed )[0]->data.gun.ubGunShotsLeft );
|
||||
}
|
||||
|
||||
for ( pSoldier->usBarrelCounter = 0; pSoldier->usBarrelCounter < barrelstofire; ++pSoldier->usBarrelCounter )
|
||||
{
|
||||
UseLauncher( pSoldier, sTargetGridNo );
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
|
||||
{
|
||||
@@ -4338,18 +4476,21 @@ BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
|
||||
iBPCost = 0;
|
||||
}
|
||||
|
||||
if ( pSoldier->bDoBurst )
|
||||
if ( !pSoldier->usBarrelCounter )
|
||||
{
|
||||
// ONly deduct points once
|
||||
if ( pSoldier->bDoBurst == 1 )
|
||||
if ( pSoldier->bDoBurst )
|
||||
{
|
||||
// ONly deduct points once
|
||||
if ( pSoldier->bDoBurst == 1 )
|
||||
{
|
||||
DeductPoints( pSoldier, sAPCost, iBPCost, AFTERSHOT_INTERRUPT );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DeductPoints( pSoldier, sAPCost, iBPCost, AFTERSHOT_INTERRUPT );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DeductPoints( pSoldier, sAPCost, iBPCost, AFTERSHOT_INTERRUPT );
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// SANDRO - new mercs' records
|
||||
@@ -4381,7 +4522,7 @@ BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
|
||||
MemFree( pSoldier->pThrowParams );
|
||||
pSoldier->pThrowParams = NULL;
|
||||
|
||||
if ( pSoldier->bDoBurst )
|
||||
if ( pSoldier->bDoBurst && !pSoldier->usBarrelCounter )
|
||||
{
|
||||
// done, if bursting, increment
|
||||
pSoldier->bDoBurst++;
|
||||
@@ -9470,7 +9611,6 @@ UINT32 CalcThrownChanceToHit(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
|
||||
return (iChance);
|
||||
}
|
||||
|
||||
|
||||
void ChangeWeaponMode( SOLDIERTYPE * pSoldier )
|
||||
{
|
||||
// ATE: Don't do this if in a fire amimation.....
|
||||
@@ -9479,30 +9619,45 @@ void ChangeWeaponMode( SOLDIERTYPE * pSoldier )
|
||||
return;
|
||||
}
|
||||
|
||||
do
|
||||
// Flugente: if there is a higher barrel configuration, use that
|
||||
// otherwise, go back to one barrel and try next mode
|
||||
pSoldier->usBarrelMode = max( 1, pSoldier->usBarrelMode );
|
||||
UINT8 nextbarrelmode = GetNextBarrelMode( pSoldier->inv[HANDPOS].usItem, pSoldier->usBarrelMode );
|
||||
if ( nextbarrelmode > pSoldier->usBarrelMode )
|
||||
{
|
||||
pSoldier->bWeaponMode++;
|
||||
if(pSoldier->bWeaponMode == NUM_WEAPON_MODES)
|
||||
pSoldier->usBarrelMode = nextbarrelmode;
|
||||
}
|
||||
else
|
||||
{
|
||||
// start again with the first barrel configuration
|
||||
pSoldier->usBarrelMode = nextbarrelmode;
|
||||
|
||||
do
|
||||
{
|
||||
if ( Weapon[pSoldier->inv[HANDPOS].usItem].NoSemiAuto )
|
||||
pSoldier->bWeaponMode = WM_AUTOFIRE;
|
||||
else
|
||||
pSoldier->bWeaponMode = WM_NORMAL;
|
||||
pSoldier->bWeaponMode++;
|
||||
|
||||
if ( HasAttachmentOfClass( &(pSoldier->inv[HANDPOS]), AC_RIFLEGRENADE) )
|
||||
if ( pSoldier->bWeaponMode == NUM_WEAPON_MODES )
|
||||
{
|
||||
OBJECTTYPE* pRifleGrenadeDeviceObj = FindAttachment_GrenadeLauncher( &(pSoldier->inv[HANDPOS]) );
|
||||
if ( Weapon[pSoldier->inv[HANDPOS].usItem].NoSemiAuto )
|
||||
pSoldier->bWeaponMode = WM_AUTOFIRE;
|
||||
else
|
||||
pSoldier->bWeaponMode = WM_NORMAL;
|
||||
|
||||
if ( pRifleGrenadeDeviceObj && FindLaunchableAttachment( &(pSoldier->inv[HANDPOS]), pRifleGrenadeDeviceObj->usItem) )
|
||||
if ( HasAttachmentOfClass( &( pSoldier->inv[HANDPOS] ), AC_RIFLEGRENADE ) )
|
||||
{
|
||||
pSoldier->bWeaponMode = WM_ATTACHED_GL;
|
||||
OBJECTTYPE* pRifleGrenadeDeviceObj = FindAttachment_GrenadeLauncher( &( pSoldier->inv[HANDPOS] ) );
|
||||
|
||||
if ( pRifleGrenadeDeviceObj && FindLaunchableAttachment( &( pSoldier->inv[HANDPOS] ), pRifleGrenadeDeviceObj->usItem ) )
|
||||
{
|
||||
pSoldier->bWeaponMode = WM_ATTACHED_GL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Changed by ADB, rev 1513
|
||||
//while(IsGunWeaponModeCapable( pSoldier, HANDPOS, pSoldier->bWeaponMode ) == FALSE && pSoldier->bWeaponMode != WM_NORMAL);
|
||||
while ( IsGunWeaponModeCapable( &pSoldier->inv[HANDPOS], static_cast<WeaponMode>( pSoldier->bWeaponMode ), pSoldier ) == FALSE && pSoldier->bWeaponMode != WM_NORMAL );
|
||||
}
|
||||
// Changed by ADB, rev 1513
|
||||
//while(IsGunWeaponModeCapable( pSoldier, HANDPOS, pSoldier->bWeaponMode ) == FALSE && pSoldier->bWeaponMode != WM_NORMAL);
|
||||
while(IsGunWeaponModeCapable( &pSoldier->inv[HANDPOS], static_cast<WeaponMode>(pSoldier->bWeaponMode), pSoldier ) == FALSE && pSoldier->bWeaponMode != WM_NORMAL);
|
||||
|
||||
if (pSoldier->bWeaponMode == WM_AUTOFIRE || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO || pSoldier->bWeaponMode == WM_ATTACHED_UB_AUTO)
|
||||
{
|
||||
|
||||
@@ -393,6 +393,10 @@ typedef struct
|
||||
// this is intended for guns that normally don't possess burst mode, like revolvers
|
||||
BOOLEAN fBurstOnlyByFanTheHammer;
|
||||
|
||||
// Flugente: multi-barrel weapons can fire a variety of barrels at once in all firemodes.
|
||||
// This vector stores the possible configurations
|
||||
std::vector<UINT8> barrelconfigurations;
|
||||
|
||||
} WEAPONTYPE;
|
||||
typedef struct
|
||||
{
|
||||
@@ -537,4 +541,8 @@ FLOAT GetOverheatDamageThreshold( OBJECTTYPE *pObj );
|
||||
|
||||
BOOLEAN ArtilleryStrike( UINT16 usItem, UINT8 ubOwnerID, UINT32 usStartingGridNo, UINT32 usTargetMapPos );
|
||||
|
||||
// Flugente: functions for using several barrels at once
|
||||
UINT8 GetNextBarrelMode( UINT16 usItem, UINT8 aBarrelMode );
|
||||
UINT8 GetFittingBarrelMode( UINT16 usItem, UINT8 aBarrelMode ); // return a number of barrels this gun can fire, equal or below aBarrelMode
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user