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:
Flugente
2019-01-27 19:48:18 +00:00
parent 61553feb57
commit a5e5ff6bd8
15 changed files with 338 additions and 50 deletions
+75 -1
View File
@@ -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() )
{
+18 -5
View File
@@ -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) &&
+4
View File
@@ -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!
+6 -1
View File
@@ -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
View File
@@ -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)
{
+8
View File
@@ -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