- 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.
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.fSetZeroUponNewSector = iniReader.ReadBoolean("Tactical Weapon Overheating Settings","OVERHEATING_SET_ZERO_UPON_NEW_SECTOR",TRUE);
//################# Strategic Gamestart Settings ##################
//Lalien: Game starting time
+3 -1
View File
@@ -1072,8 +1072,10 @@ typedef struct
// Flugente FTW 1: Weapon Overheating
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 ;-)
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 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]
+2
View File
@@ -6113,6 +6113,8 @@ BOOLEAN HandleDefiniteUnloadingOfWorld( UINT8 ubUnloadCode )
//if we arent loading a 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
SaveCurrentSectorsInformationToTempItemFile();
+3 -1
View File
@@ -594,7 +594,9 @@ void DisplayRangeToTarget( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
pSoldier->bTargetLevel = bTempTargetLevel;
// 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 );
//Display the msg
+10 -9
View File
@@ -2531,15 +2531,18 @@ void UIHandleMercAttack( SOLDIERTYPE *pSoldier , SOLDIERTYPE *pTargetSoldier, IN
INT32 iHandleReturn;
INT32 sTargetGridNo;
INT8 bTargetLevel;
UINT16 usItem;
LEVELNODE *pIntNode;
STRUCTURE *pStructure;
INT32 sGridNo, sNewGridNo;
UINT8 ubItemCursor;
UINT16 usItem;
LEVELNODE* pIntNode;
STRUCTURE* pStructure;
INT32 sGridNo, sNewGridNo;
UINT8 ubItemCursor;
// get cursor
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 ( NPCFirstDraw( pSoldier, pTargetSoldier ) )
@@ -2555,8 +2558,6 @@ void UIHandleMercAttack( SOLDIERTYPE *pSoldier , SOLDIERTYPE *pTargetSoldier, IN
// Set aim time to one in UI
pSoldier->aiData.bAimTime = (pSoldier->aiData.bShownAimTime );
usItem = pSoldier->inv[ HANDPOS ].usItem;
// ATE: Check if we are targeting an interactive tile, and adjust gridno accordingly...
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 )
{
iHandleReturn = HandleItem( pSoldier, sTargetGridNo, bTargetLevel, GetAttachedGrenadeLauncher(&pSoldier->inv[ HANDPOS ]), TRUE );
iHandleReturn = HandleItem( pSoldier, sTargetGridNo, bTargetLevel, GetAttachedGrenadeLauncher(pObj), TRUE );
}
else
{
iHandleReturn = HandleItem( pSoldier, sTargetGridNo, bTargetLevel, pSoldier->inv[ HANDPOS ].usItem, TRUE );
iHandleReturn = HandleItem( pSoldier, sTargetGridNo, bTargetLevel, usItem, TRUE );
}
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
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;
*abBlue = 0;
@@ -2769,7 +2769,7 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
}
#endif
// FIRST DISPLAY FREE ROUNDS REMIANING
if ( pItem->usItemClass == IC_GUN && !Item[pObject->usItem].rocketlauncher )
{
sNewY = sY + sHeight - 10;
@@ -2779,75 +2779,76 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
if ( gGameOptions.fWeaponOverheating == TRUE && gGameExternalOptions.fDisplayOverheatThermometer == TRUE )
sNewX = sX + 6;
SetFontForeground ( AmmoTypes[(*pObject)[iter]->data.gun.ubGunAmmoType].fontColour );
//switch ((*pObject)[iter]->data.gun.ubGunAmmoType)
//{
// case AMMO_AP:
// 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) )
// Flugente: check for underbarrel weapons and use that object if necessary
OBJECTTYPE* pObjShown = pObject;
INVTYPE *pItemShown = pItem;
if ( pItem->usItemClass == IC_GUN && pSoldier && ( pSoldier->bWeaponMode == WM_ATTACHED_UB || pSoldier->bWeaponMode == WM_ATTACHED_UB_BURST || pSoldier->bWeaponMode == WM_ATTACHED_UB_AUTO ) )
{
// Soldier doesn't know.
EstimateBulletsLeft( pSoldier, pObject );
swprintf( pStr, L"%s", gBulletCount );
}
else
{
swprintf( pStr, L"%d", (*pObject)[iter]->data.gun.ubGunShotsLeft );
}
OBJECTTYPE *pObjectUnderBarrel = FindAttachment_UnderBarrel( pObject );
//swprintf( pStr, L"%d", (*pObject)[iter]->data.gun.ubGunShotsLeft );
//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 ) )
if ( pObjectUnderBarrel )
{
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
{
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 );
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
@@ -2908,20 +2909,25 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
// Flugente FTW 1
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;
UINT8 TemperatureStringNum = GetTemperatureString( overheatjampercentage, &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 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 );
@@ -2994,6 +3000,21 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
swprintf( pStr, New113Message[MSG113_GL_AUTO] );
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
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 );
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_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_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 ] = 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_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);
// Load button Graphics
@@ -2396,6 +2399,9 @@ void RemoveSMPanelButtons( )
UnloadButtonImage( iBurstButtonImages[ WM_ATTACHED_GL ] );
UnloadButtonImage( iBurstButtonImages[ WM_ATTACHED_GL_BURST ] );
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 );
}
pObj = &(pSoldier->inv[bWeaponIn]);
// Flugente: check for underbarrel weapons and use that object if necessary
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[bWeaponIn]) );
//<SB> manual recharge
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;
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
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!
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 );
if (bSlot != NO_SLOT)
{
@@ -4612,7 +4618,9 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
{
//Make sure it's actually on that gun..
//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
//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:
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
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(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;
}
}
@@ -5891,7 +5902,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
ubShotsLeft = (*pObj)[0]->data.ubShotsLeft;
for(UINT8 clip = 0; clip < 5; clip++)
{
magSize = GetMagSize(pInSlot);
magSize = GetMagSize(pObjUsed);
if(ubShotsLeft < magSize)
magSize = ubShotsLeft;
if(CreateAmmo(newItem, &tempClip, magSize))
@@ -5963,7 +5974,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
}
}
else
return( ReloadGun( pSoldier, pInSlot, pObj ) );
return( ReloadGun( pSoldier, pObjUsed, pObj ) );
}
}
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)){
fInterfacePanelDirty = DIRTYLEVEL2;
RenderBulletIcon(this, subObject);
@@ -9477,9 +9506,13 @@ void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *b
{
*bRecoilX = 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 < 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
// will have any recoil.
@@ -9488,13 +9521,15 @@ void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *b
return;
}
*bRecoilX = Weapon[pObj->usItem].bRecoilX;
*bRecoilY = Weapon[pObj->usItem].bRecoilY;
*bRecoilX = Weapon[pObjUsed->usItem].bRecoilX;
*bRecoilY = Weapon[pObjUsed->usItem].bRecoilY;
// Apply a percentage-based modifier. This can increase or decrease BOTH axes. At most, it can eliminate
// recoil on the gun.
INT16 sPercentRecoilModifier = GetPercentRecoilModifier( pObj );
//INT16 sPercentRecoilModifier = GetPercentRecoilModifier( pObj );
INT16 sPercentRecoilModifier = __max(-100, (GetBasePercentRecoilModifier( pObjUsed ) + GetAttachmentPercentRecoilModifier( pObjUsedInHand ) ));
*bRecoilX += (*bRecoilX * sPercentRecoilModifier ) / 100;
*bRecoilY += (*bRecoilY * sPercentRecoilModifier ) / 100;
@@ -9505,7 +9540,10 @@ void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *b
INT8 bRecoilAdjustX = 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);
*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
// 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.
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 )
{
@@ -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
// the percentage-based nature of this modifier, it cannot cause a gun to reverse its recoil - only diminish it to
// 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 sRecoilAdjust = 0;
@@ -10550,6 +10659,60 @@ UINT16 GetAttachedGrenadeLauncher( OBJECTTYPE * pObj )
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 )
{
+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.
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 );
INT16 GetBasePercentRecoilModifier( OBJECTTYPE *pObj );
INT16 GetAttachmentPercentRecoilModifier( OBJECTTYPE *pObj);
INT16 GetPercentRecoilModifier( OBJECTTYPE *pObj );
// HEADROCK HAM 4: This function returns whether the last bullet in a burst/autofire volley was a tracer.
BOOLEAN WasPrevBulletATracer( SOLDIERTYPE *pSoldier, OBJECTTYPE *pWeapon );
@@ -337,6 +341,14 @@ INT16 GetGrenadeLauncherStatus( OBJECTTYPE * pObj );
BOOLEAN IsGrenadeLauncherAttached( OBJECTTYPE * pObj, UINT8 subObject = 0 );
OBJECTTYPE* FindAttachment_GrenadeLauncher( 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 FindRocketLauncherOrCannon( SOLDIERTYPE * pSoldier );
INT8 FindNonSmokeLaunchable( SOLDIERTYPE * pSoldier, UINT16 usWeapon );
+36 -24
View File
@@ -3988,12 +3988,15 @@ INT8 FireBullet( SOLDIERTYPE * pFirer, BULLET * pBullet, BOOLEAN fFake )
}
else
{
OBJECTTYPE* pObjAttHand = pFirer->GetUsedWeapon( &pFirer->inv[pFirer->ubAttackingHand] );
UINT16 usItemUsed = pFirer->GetUsedWeaponNumber( &pFirer->inv[pFirer->ubAttackingHand] );
//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*/ ) )
pBullet->usClockTicksPerUpdate = (Weapon[ pFirer->usAttackingWeapon ].ubBulletSpeed + GetBulletSpeedBonus(&pFirer->inv[pFirer->ubAttackingHand]) ) / 10;
pBullet->usClockTicksPerUpdate = (Weapon[ usItemUsed ].ubBulletSpeed + GetBulletSpeedBonus( pObjAttHand ) ) / 10;
else
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
pBullet->usClockTicksPerUpdate = 1;
//afp-end
@@ -4068,6 +4071,8 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
UINT16 usBulletFlags = 0;
int n=0;
OBJECTTYPE* pObjAttHand = pFirer->GetUsedWeapon( &(pFirer->inv[pFirer->ubAttackingHand]) );
//DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("FireBulletGivenTarget"));
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
// New Tracer System.
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;
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)
{
@@ -4147,7 +4152,7 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
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;
fTracer = TRUE;
@@ -4156,9 +4161,9 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
ubImpact =(UINT8) GetDamage(&pFirer->inv[pFirer->ubAttackingHand]);
//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;
ubSpreadIndex = GetSpreadPattern( &pFirer->inv[pFirer->ubAttackingHand] );
ubSpreadIndex = GetSpreadPattern( pObjAttHand );
if( ubShots>1 && !fFake )
{
fBuckshot = true;
@@ -4407,7 +4412,7 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
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
@@ -4435,7 +4440,7 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
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->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
// 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)
&& AmmoTypes[ pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType ].tracerEffect )
&& AmmoTypes[ (*pObjAttHand)[0]->data.gun.ubGunAmmoType ].tracerEffect )
{
UINT16 iBulletsLeft, iBulletsPerTracer;
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
// a tracer magazine (INI-settable).
@@ -4540,6 +4545,8 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
UINT16 usBulletFlags = 0;
int n=0;
OBJECTTYPE* pObjAttHand = pFirer->GetUsedWeapon( &(pFirer->inv[pFirer->ubAttackingHand]) );
//DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("FireBulletGivenTarget"));
CalculateSoldierZPos( pFirer, FIRING_POS, &dStartZ );
@@ -4574,7 +4581,7 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
ubShots = 1;
fTracer = FALSE;
// Check if we have spit as a weapon!
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
// New Tracer System.
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;
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)
{
@@ -4625,7 +4632,7 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
fTracer = TRUE;
}
ubImpact =(UINT8) GetDamage(&pFirer->inv[pFirer->ubAttackingHand]);
ubImpact =(UINT8) GetDamage(pObjAttHand);
//zilpin: pellet spread patterns externalized in XML
/* 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.
@@ -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.
{
ObjectData *weapon = &(pFirer->inv[pFirer->ubAttackingHand][0]->data);
ObjectData *weapon = &((*pObjAttHand)[0]->data);
ubShots = AmmoTypes[ weapon->gun.ubGunAmmoType].numberOfBullets;
ubSpreadIndex = GetSpreadPattern( &pFirer->inv[pFirer->ubAttackingHand] );
ubSpreadIndex = GetSpreadPattern( pObjAttHand );
if( ubShots>1 && !fFake )
{
fBuckshot = true;
@@ -4905,7 +4912,7 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
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
@@ -4933,7 +4940,7 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
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->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
// 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)
&& AmmoTypes[ pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType ].tracerEffect )
&& AmmoTypes[ (*pObjAttHand)[0]->data.gun.ubGunAmmoType ].tracerEffect )
{
UINT16 iBulletsLeft, iBulletsPerTracer;
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
// a tracer magazine (INI-settable).
@@ -5008,10 +5015,12 @@ INT8 ChanceToGetThrough( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT d
{
BOOLEAN fBuckShot = FALSE;
OBJECTTYPE* pObjHand = pFirer->GetUsedWeapon( &pFirer->inv[HANDPOS] );
// 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;
}
@@ -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.
// Flugente: determine used gun
OBJECTTYPE* pObjAttHand = pShooter->GetUsedWeapon( &pShooter->inv[ pShooter->ubAttackingHand ] );
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).
// 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;
// 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;
uiItemClass = Item[ usItemNum ].usItemClass;
uiItemClass = Item[ usUBItemNum ].usItemClass;
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->bDoAutofire && GetAutofireShotsPerFiveAPs(&pSoldier->inv[HANDPOS]) > 0 )
sAPCost += CalcAPsToAutofire( pSoldier->CalcActionPoints( ), &(pSoldier->inv[HANDPOS]), pSoldier->bDoAutofire );
if(pSoldier->bDoAutofire && GetAutofireShotsPerFiveAPs(AttackingWeapon) > 0 )
sAPCost += CalcAPsToAutofire( pSoldier->CalcActionPoints( ), AttackingWeapon, pSoldier->bDoAutofire );
else
sAPCost += CalcAPsToBurst( pSoldier->CalcActionPoints( ), &(pSoldier->inv[HANDPOS]) );
sAPCost += CalcAPsToBurst( pSoldier->CalcActionPoints( ), AttackingWeapon );
}
//else //ddd comment for aimed burst
{
@@ -1513,7 +1517,7 @@ INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTur
UINT16 usWeaponReadyTime;
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;
sAPCost += usWeaponReadyTime / ubReadyTimeDivisor;
}
@@ -1696,8 +1700,10 @@ INT16 MinAPsToAttack(SOLDIERTYPE *pSoldier, INT32 sGridno, UINT8 ubAddTurningCos
}
else
{
UINT16 undbarItem = pSoldier->GetUsedWeaponNumber( &(pSoldier->inv[ HANDPOS ]) );
// 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 )
@@ -1936,16 +1942,21 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
UINT16 usRaiseGunCost = 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 )
{
usItem = GetAttachedGrenadeLauncher(&pSoldier->inv[HANDPOS] );//UNDER_GLAUNCHER;
usUBItem = usItem;
}
else
{
{
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 );
@@ -2013,51 +2024,53 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
}
}
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
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, &(pSoldier->inv[HANDPOS]) );
if(gGameExternalOptions.ubFlatAFTHBtoPrecentMultiplier > 0 && gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE && GetBipodBonus(&(pSoldier->inv[HANDPOS])) > 0)
{
bAPCost += (BaseAPsToShootOrStab( bFullAPs, bAimSkill, pObjUsed ) * (100 - GetBipodBonus(&(pSoldier->inv[HANDPOS]))) / 100);
}
else
{
bAPCost += BaseAPsToShootOrStab( bFullAPs, bAimSkill, pObjUsed );
}
/////////////////////////////////////////////////////////////////////////////////////
// SANDRO - STOMP traits
////////////////////////////////////////////////////
if ( gGameOptions.fNewTraitSystem )
{
// 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);
}
// 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);
}
// 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);
}
// 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);
}
// 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);
}
// 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);
}
// 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);
}
@@ -2073,7 +2086,7 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
fAddingRaiseGunCost = TRUE;
}
if ( Item[ usItem ].usItemClass == IC_THROWING_KNIFE )
if ( Item[ usUBItem ].usItemClass == IC_THROWING_KNIFE )
{
// Do we need to stand up?
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)
// 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];
}
@@ -2134,7 +2147,7 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
if ( bAPCost < 1 )
bAPCost = 1;
if ( Item[pSoldier->inv[HANDPOS].usItem].rocketlauncher )
if ( Item[(*pObjUsed).usItem].rocketlauncher )
{
bAPCost += GetAPsToChangeStance( pSoldier, ANIM_STAND );
}
@@ -2347,33 +2360,36 @@ BOOLEAN EnoughAmmo( SOLDIERTYPE *pSoldier, BOOLEAN fDisplay, INT8 bInvPos )
}
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
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 );
}
if (Item[pSoldier->inv[bInvPos].usItem].usItemClass == IC_BOMB)
if (Item[usItemUsed].usItemClass == IC_BOMB)
{
return (TRUE);
}
// ATE: Did an else if here...
if ( FindAttachmentByClass( &(pSoldier->inv[ bInvPos ]), IC_BOMB ) != 0 )
if ( FindAttachmentByClass( pObjUsed, IC_BOMB ) != 0 )
{
return( TRUE );
}
// 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 );
}
@@ -2385,9 +2401,9 @@ BOOLEAN EnoughAmmo( SOLDIERTYPE *pSoldier, BOOLEAN fDisplay, INT8 bInvPos )
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 )
{
@@ -2399,7 +2415,7 @@ BOOLEAN EnoughAmmo( SOLDIERTYPE *pSoldier, BOOLEAN fDisplay, INT8 bInvPos )
//<SB> manual recharge
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 );
}
@@ -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 )
{
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...
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?
}
(*pObjUsed)[0]->data.gun.ubGunShotsLeft--;
}
}
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;;
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
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( ) )
{
pObj = &(pSoldier->inv[SECONDHANDPOS]);
// Flugente: check for underbarrel weapons and use that object if necessary
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[SECONDHANDPOS]) );
bExcludeSlot = NO_SLOT;
bSlot2 = NO_SLOT;
+180 -161
View File
@@ -358,67 +358,77 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
break;
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
AddGameEvent( S_FIREWEAPON, 0, &SFireWeapon );
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
AddGameEvent( S_FIREWEAPON, 0, &SFireWeapon );
//hayden
if(is_server || (is_client && pSoldier->ubID <20) )
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 ) );
//hayden
if(is_server || (is_client && pSoldier->ubID <20) )
send_fireweapon( &SFireWeapon );
}
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 ( noisefactor < 100 ) volume = (volume * noisefactor) / 100;
//randomize the rate a bit so that the sound is more believable
PlayJA2Sample( Weapon[ pSoldier->usAttackingWeapon ].sSound, 44100-Random(5000)-Random(5000)-Random(5000), SoundVolume( volume, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
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;
}
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;
case 431:
@@ -764,133 +774,137 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
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");
fStop = TRUE;
fFreeUpAttacker = TRUE;
}
// CODE: HANDLE BURST
// FIRST CHECK IF WE'VE REACHED MAX FOR GUN
fStop = FALSE;
// 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 )
OBJECTTYPE* pObjHand = pSoldier->GetUsedWeapon( &pSoldier->inv[HANDPOS] );
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( pObjHand )))) )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ BURST_FIRE_DEPLETED_CLIP_STR ] );
}
}
// 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");
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"AdjustToNextAnimationFrame: Burst case 448, stopping because burst size too large");
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 );
}
}
// 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 )
{
PlayJA2Sample( S_DRYFIRE1, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Gun jammed!" );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[ BURST_FIRE_DEPLETED_CLIP_STR ] );
}
}
// 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") );
FreeUpAttacker( );
}
else if ( bWeaponJammed == 255 )
{
// Play intermediate animation...
if ( HandleUnjamAnimation( pSoldier ) )
pSoldier->flags.fDoSpread = FALSE;
pSoldier->bDoBurst = 1;
// pSoldier->flags.fBurstCompleted = TRUE;
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...
// 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 );
}
}
}
if ( fStop )
{
if(pSoldier->bDoAutofire) //reset the autofire cursor after firing
{
pSoldier->flags.autofireLastStep = FALSE;
pSoldier->bDoAutofire = 1;
}
// END: GOTO AIM STANCE BASED ON HEIGHT
// If we are a robot - we need to do stuff different here
// 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 );
}
else
{
switch ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
{
case ANIM_STAND:
pSoldier->ChangeSoldierState( AIM_RIFLE_STAND, 0 , FALSE );
break;
pSoldier->flags.fDoSpread = FALSE;
pSoldier->bDoBurst = 1;
// pSoldier->flags.fBurstCompleted = TRUE;
if ( fFreeUpAttacker )
{
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - aborting start of attack") );
// FreeUpAttacker( pSoldier->ubID );
}
case ANIM_PRONE:
pSoldier->ChangeSoldierState( AIM_RIFLE_PRONE, 0 , FALSE );
break;
// 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 );
case ANIM_CROUCH:
pSoldier->ChangeSoldierState( AIM_RIFLE_CROUCH, 0 , FALSE );
break;
if ( CheckForImproperFireGunEnd( pSoldier ) )
{
}
}
return( TRUE );
}
// END: GOTO AIM STANCE BASED ON HEIGHT
// If we are a robot - we need to do stuff different here
// 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 ) )
// MOVETO CURRENT SPREAD LOCATION
if ( pSoldier->flags.fDoSpread )
{
pSoldier->ChangeSoldierState( STANDING, 0 , FALSE );
}
else
{
switch ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
if ( pSoldier->sSpreadLocations[ pSoldier->flags.fDoSpread - 1 ] != 0 )
{
case ANIM_STAND:
pSoldier->ChangeSoldierState( AIM_RIFLE_STAND, 0 , FALSE );
break;
case ANIM_PRONE:
pSoldier->ChangeSoldierState( AIM_RIFLE_PRONE, 0 , FALSE );
break;
case ANIM_CROUCH:
pSoldier->ChangeSoldierState( AIM_RIFLE_CROUCH, 0 , FALSE );
break;
pSoldier->EVENT_SetSoldierDirection( (INT8)GetDirectionToGridNoFromGridNo( pSoldier->sGridNo, pSoldier->sSpreadLocations[ pSoldier->flags.fDoSpread - 1 ] ) );
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
}
}
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;
@@ -2381,9 +2395,12 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
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 )
{
@@ -3977,8 +3994,10 @@ BOOLEAN CheckForImproperFireGunEnd( SOLDIERTYPE *pSoldier )
return( FALSE );
}
OBJECTTYPE* pObjHand = pSoldier->GetUsedWeapon( &pSoldier->inv[ HANDPOS ] );
// 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 ( 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();
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 ...
@@ -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 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
if ( gAnimControl[ this->usAnimState ].ubEndHeight == ANIM_PRONE )
return( FALSE );
@@ -13022,6 +13030,33 @@ BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
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 )
{
INT8 bBandaged; //,savedOurTurn;
+3 -1
View File
@@ -1319,7 +1319,9 @@ public:
BOOLEAN IsValidSecondHandShotForReloadingPurposes( void );
BOOLEAN SoldierCarriesTwoHandedWeapon( void );
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;
+1 -1
View File
@@ -272,7 +272,7 @@ void HandleTacticalEndTurn( )
#endif
// 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 ) )
{
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
if ( (*pGun)[0]->data.gun.ubGunShotsLeft < GetMagSize( pGun ) )
+1 -2
View File
@@ -2574,8 +2574,7 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
return ( TRAJECTORYCURS );
}
usInHand = pSoldier->inv[HANDPOS].usItem;
usInHand = pSoldier->GetUsedWeaponNumber( &pSoldier->inv[HANDPOS] );
// Start off with what is in our hand
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_BURST,
WM_ATTACHED_GL_AUTO,
WM_ATTACHED_UB,
WM_ATTACHED_UB_BURST,
WM_ATTACHED_UB_AUTO,
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)
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 ...
{
@@ -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 ...
{
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 ...
cooldownfactor *= gGameExternalOptions.iCooldownModificatorLonelyBarrel;
FLOAT cooldownfactor = GetItemCooldownFactor(pObj); // ... get item cooldown factor provided of attachments ...
FLOAT newguntemperatre = max(0.0, guntemperature - cooldownfactor); // ... calculate new temperature ...
(*pObj)[i]->data.bTemperature = newguntemperatre; // ... set new temperature
if ( Item[gWorldItems[ uiCount ].object.usItem].barrel == TRUE ) // ... a barrel lying around cools down a bit faster ...
cooldownfactor *= gGameExternalOptions.iCooldownModificatorLonelyBarrel;
newguntemperature = max(0.0, guntemperature - cooldownfactor); // ... calculate new temperature ...
}
(*pObj)[i]->data.bTemperature = newguntemperature; // ... set new temperature
#if 0//def JA2TESTVERSION
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();
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
#if 0//def JA2TESTVERSION
+1 -1
View File
@@ -119,6 +119,6 @@ extern void FindPanicBombsAndTriggers( void );
extern INT32 FindWorldItemForBombInGridNo( INT32 sGridNo, INT8 bLevel);
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
+3
View File
@@ -2060,6 +2060,9 @@ enum
MSG113_GL,
MSG113_GL_BRST,
MSG113_GL_AUTO,
MSG113_UB,
MSG113_UB_BRST,
MSG113_UB_AUTO,
MSG113_SNIPER,
MSG113_UNABLETOSPLITMONEY,
MSG113_ARRIVINGREROUTED,
+3
View File
@@ -6051,6 +6051,9 @@ STR16 New113Message[] =
L"榴弹",
L"榴弹点射",
L"榴弹自动",
L"UB", // TODO.Translate, INFO: UB = Under Barrel
L"UBRST",
L"UAUTO",
L"狙击手!",
L"已经点选物品,此时无法分钱。",
L"新兵的会合地被挪至 %s, 因降落地点 %s 目前由敌人占据。",
+3
View File
@@ -6053,6 +6053,9 @@ STR16 New113Message[] =
L"GL",
L"GL BRST",
L"GL AUTO",
L"UB",
L"UBRST",
L"UAUTO",
L"Sniper!",
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.",
+3
View File
@@ -6051,6 +6051,9 @@ STR16 New113Message[] =
L"GL",
L"GL BRST",
L"GL AUTO",
L"UB",
L"UBRST",
L"UAUTO",
L"Sniper!",
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.",
+3
View File
@@ -6035,6 +6035,9 @@ STR16 New113Message[] =
L"LG",
L"RAF. LG",
L"LG AUTO",
L"UB", // TODO.Translate
L"UBRST",
L"UAUTO",
L"Tireur embusqué !",
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.",
+3
View File
@@ -5880,6 +5880,9 @@ STR16 New113Message[] =
L"GL",
L"GL BRST",
L"GL AUTO",
L"UB",
L"UBRST",
L"UAUTO",
L"Scharfschütze!",
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.",
+3
View File
@@ -6042,6 +6042,9 @@ STR16 New113Message[] =
L"GL",
L"GL BRST",
L"GL AUTO",
L"UB",
L"UBRST",
L"UAUTO",
L"Sniper!",
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.",
+3
View File
@@ -6048,6 +6048,9 @@ STR16 New113Message[] =
L"GL",
L"GL BRST",
L"GL AUTO",
L"UB", // TODO.Translate
L"UBRST",
L"UAUTO",
L"Snajper!",
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.",
+3
View File
@@ -6028,6 +6028,9 @@ STR16 New113Message[] =
L"ГР",
L"ГР *",
L"ГР ***",
L"UB", // TODO.Translate
L"UBRST",
L"UAUTO",
L"Снайпер!",
L"Невозможно разделить деньги из-за предмета на курсоре.",
L"Точка высадки новых наемников перенесена в %s, так как предыдущая точка высадки %s захвачена противником.",
+3
View File
@@ -6055,6 +6055,9 @@ STR16 New113Message[] =
L"GL",
L"GL BRST",
L"GL AUTO",
L"UB",
L"UBRST",
L"UAUTO",
L"Sniper!",
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.",