- New Feature: Toggle scope modes (by Flugente)

o This allows you to toggle between a gun's different scopes via the '.' key. Y
o You get the boni for vison, tunnel vison, sight range, scope magnification etc. only for the scope you use. 
o 2 new ja2_options.ini properties: USE_SCOPE_MODES, DISPLAY_SCOPE_MODES: Allows the display of an icon on your gun, to tell what scope is currently in use. If it is a scope, the magnification factor also gets written. Both options can be found under the  [Tactical Gameplay Settings] section in the ja2_options.ini
o new tag in items.xml (<attachmentclass>) now enables to specifiy what an attachment can do. At the moment used by grenades/rockets/scopes/sights. Items.xml changed accordingly, modders need to add this tag for those items.
o More infos: First post in: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=303038&#Post303038
- WARNING: This feature breaks savegame compatibility.

- New Feature: Tripwire-triggered mines (by Flugente)
o This allows creating complex networks of tripwire that can detonate multiple mines attached to them.
o 2 new Items.xml tags: tripwireactivation, tripwire
o More infos: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=303205&#Post303205 

- Overheating addition (by Flugente)
o Severe overheating now temporarily reduces a gun's accuracy. This exact amount is displayed in the UDB.

- Bugfix (by Flugente)
o Removed foregrip as an attachment from the Saiga 12K





git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5196 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2012-04-12 08:45:36 +00:00
parent 0e64603c9a
commit 756220941b
25 changed files with 1001 additions and 223 deletions
+3
View File
@@ -1072,6 +1072,9 @@ void LoadGameExternalOptions()
gGameExternalOptions.fDisplayWeaponRestingIndicator = iniReader.ReadBoolean("Tactical Gameplay Settings","WEAPON_RESTING_DISPLAY",TRUE);
gGameExternalOptions.ubProneModifierPercentage = iniReader.ReadInteger("Tactical Gameplay Settings","WEAPON_RESTING_PRONE_BONI_PERCENTAGE", 50, 0, 100);
gGameExternalOptions.fScopeModes = iniReader.ReadBoolean("Tactical Gameplay Settings","USE_SCOPE_MODES", FALSE);
gGameExternalOptions.fDisplayScopeModes = iniReader.ReadBoolean("Tactical Gameplay Settings","DISPLAY_SCOPE_MODES", FALSE);
// WANNE: Externalized grid number of new merc when they arrive with the helicopter (by Jazz)
gGameExternalOptions.iInitialMercArrivalLocation = iniReader.ReadInteger("Tactical Gameplay Settings","INITIAL_MERC_ARRIVAL_LOCATION", 4870 );
+5
View File
@@ -1076,9 +1076,14 @@ typedef struct
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)
// Flugente: Weapon Mounting
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]
// Flugente: Scope Modes
BOOLEAN fScopeModes; // allow the player to toggle between existing scopes/sights
BOOLEAN fDisplayScopeModes; // allow display of scope modes
BOOLEAN gBriefingRoom;
BOOLEAN gEncyclopedia;
+1 -1
View File
@@ -347,7 +347,7 @@ BOOLEAN LoadExternalGameplayData(STR directoryName)
strcpy(fileName, directoryName);
strcat(fileName, ATTACHMENTINFOFILENAME);
SGP_THROW_IFFALSE(ReadInAttachmentInfoStats(fileName),ATTACHMENTINFOFILENAME);
strcpy(fileName, directoryName);
strcat(fileName, LAUNCHABLESFILENAME);
SGP_THROW_IFFALSE(ReadInLaunchableStats(fileName),LAUNCHABLESFILENAME);
+3 -3
View File
@@ -2490,7 +2490,7 @@ void CreateMouseRegionForBigImage( UINT16 usPosY, UINT8 ubCount, INT16 *pItemNum
UINT16 usAttachment;
CreateItem(pItemNumbers[ i ], 100, &pObject);
UINT16 ubAttackAPs = BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], &pObject );
UINT16 ubAttackAPs = BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], &pObject, NULL );
if ( Weapon[ pItemNumbers[ i ] ].NoSemiAuto )
swprintf( apStr, L"-" );
@@ -2499,7 +2499,7 @@ void CreateMouseRegionForBigImage( UINT16 usPosY, UINT8 ubCount, INT16 *pItemNum
if (GetShotsPerBurst(&pObject) > 0)
{
swprintf( apStr2, L" / %d", ubAttackAPs + CalcAPsToBurst( APBPConstants[DEFAULT_APS], &pObject ) );
swprintf( apStr2, L" / %d", ubAttackAPs + CalcAPsToBurst( APBPConstants[DEFAULT_APS], &pObject, NULL ) );
wcscat( apStr, apStr2 );
}
else
@@ -2507,7 +2507,7 @@ void CreateMouseRegionForBigImage( UINT16 usPosY, UINT8 ubCount, INT16 *pItemNum
if (GetAutofireShotsPerFiveAPs(&pObject) > 0)
{
swprintf( apStr2, L" / %d", ubAttackAPs + CalcAPsToAutofire( APBPConstants[DEFAULT_APS], &pObject, 3 ) );
swprintf( apStr2, L" / %d", ubAttackAPs + CalcAPsToAutofire( APBPConstants[DEFAULT_APS], &pObject, 3, NULL ) );
wcscat( apStr, apStr2 );
}
else
+1
View File
@@ -1971,6 +1971,7 @@ BOOLEAN SOLDIERTYPE::Load(HWFILE hFile)
numBytesRead = ReadFieldByField(hFile, &this->snowCamo, sizeof(snowCamo), sizeof(INT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->wornSnowCamo, sizeof(wornSnowCamo), sizeof(INT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->sFacilityTypeOperated, sizeof(sFacilityTypeOperated), sizeof(INT16), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->bScopeMode, sizeof(bScopeMode), sizeof(INT8), numBytesRead);
#ifdef JA2UB
numBytesRead = ReadFieldByField(hFile, &this->fIgnoreGetupFromCollapseCheck, sizeof(fIgnoreGetupFromCollapseCheck), sizeof(BOOLEAN), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->GetupFromJA25StartCounter, sizeof(GetupFromJA25StartCounter), sizeof(TIMECOUNTER), numBytesRead);
+12 -4
View File
@@ -1496,8 +1496,12 @@ void HandleSoldierDropBomb( SOLDIERTYPE *pSoldier, INT32 sGridNo )
if ( iResult >= 0 )
{
// EXPLOSIVES GAIN (25): Place a bomb, or buried and armed a mine
StatChange( pSoldier, EXPLODEAMT, 25, FALSE );
// Less explosives gain for placing tripwire
if ( Item[ pSoldier->inv[ HANDPOS ].usItem ].tripwire == 1 )
StatChange( pSoldier, EXPLODEAMT, 5, FALSE );
else
// EXPLOSIVES GAIN (25): Place a bomb, or buried and armed a mine
StatChange( pSoldier, EXPLODEAMT, 25, FALSE );
// SANDRO - STOMP traits - Demolitions bonus to trap level
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, DEMOLITIONS_NT ))
@@ -4380,8 +4384,12 @@ void BombMessageBoxCallBack( UINT8 ubExitValue )
if ( iResult >= 0 )
{
// EXPLOSIVES GAIN (25): Place a bomb, or buried and armed a mine
StatChange( gpTempSoldier, EXPLODEAMT, 25, FALSE );
// Less explosives gain for placing tripwire
if ( Item[ gpTempSoldier->inv[ HANDPOS ].usItem ].tripwire == 1 )
StatChange( gpTempSoldier, EXPLODEAMT, 5, FALSE );
else
// EXPLOSIVES GAIN (25): Place a bomb, or buried and armed a mine
StatChange( gpTempSoldier, EXPLODEAMT, 25, FALSE );
}
else
{
+12 -12
View File
@@ -1593,7 +1593,7 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
/////////////////// OCTH MINIMUM RANGE FOR AIMING BONUS
if( UsingNewCTHSystem() == false &&
( Item[gpItemDescObject->usItem].minrangeforaimbonus > 0 || GetMinRangeForAimBonus( gpItemDescObject ) > 0 ) )
( Item[gpItemDescObject->usItem].minrangeforaimbonus > 0 || GetMinRangeForAimBonus( NULL, gpItemDescObject ) > 0 ) )
{
ubRegionOffset = 5;
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + ubRegionOffset ] );
@@ -2644,7 +2644,7 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
///////////////////// AIM BONUS MODIFIER
if(UsingNewCTHSystem() == false)
{
if ( GetAimBonus( gpItemDescObject, 100, 1 ) != 0 )
if ( GetAimBonus( NULL, gpItemDescObject, 100, 1 ) != 0 )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
@@ -3097,7 +3097,7 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
}
///////////////////// SINGLE-ATTACK AP MODIFIER
if (GetPercentAPReduction( gpItemDescObject ) != 0 )
if (GetPercentAPReduction( NULL, gpItemDescObject ) != 0 )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
@@ -3955,7 +3955,7 @@ void DrawWeaponStats( OBJECTTYPE * gpItemDescObject )
//////////////////// OCTH MINIMUM RANGE FOR AIMING BONUS
if( UsingNewCTHSystem() == false &&
( Item[gpItemDescObject->usItem].minrangeforaimbonus > 0 || GetMinRangeForAimBonus( gpItemDescObject ) > 0 ) )
( Item[gpItemDescObject->usItem].minrangeforaimbonus > 0 || GetMinRangeForAimBonus( NULL, gpItemDescObject ) > 0 ) )
{
ubNumLine = 5;
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoWeaponIcon, 27, gItemDescGenRegions[ubNumLine][0].sLeft+sOffsetX, gItemDescGenRegions[ubNumLine][0].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL );
@@ -4793,7 +4793,7 @@ void DrawAdvancedStats( OBJECTTYPE * gpItemDescObject )
}
///////////////////// SINGLE-ATTACK AP MODIFIER
if (GetPercentAPReduction( gpItemDescObject ) != 0 )
if (GetPercentAPReduction( NULL, gpItemDescObject ) != 0 )
{
if (cnt >= sFirstLine && cnt < sLastLine)
{
@@ -5372,7 +5372,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
return;
// ShotsPer4Turns -> ubAttackAPs, used later for all shot AP values
ubAttackAPs = BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], gpItemDescObject );
ubAttackAPs = BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], gpItemDescObject, NULL );
INT16 ubBasicAttackAPs = BaseAPsToShootOrStabNoModifier( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], gpItemDescObject );
//////////////////////////////////////////////////////////////////////////////////////////
@@ -5905,7 +5905,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
/////////////////// OCTH MINIMUM RANGE FOR AIMING BONUS
if( UsingNewCTHSystem() == false &&
( Item[gpItemDescObject->usItem].minrangeforaimbonus > 0 || GetMinRangeForAimBonus( gpItemDescObject ) > 0 ) )
( Item[gpItemDescObject->usItem].minrangeforaimbonus > 0 || GetMinRangeForAimBonus( NULL, gpItemDescObject ) > 0 ) )
{
// Set line to draw into
ubNumLine = 5;
@@ -5917,7 +5917,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
INT16 iMinRangeForAimBonusValue = Item[gpItemDescObject->usItem].minrangeforaimbonus / 10;
// Get final Minimum Range For Aim Bonus value
INT16 iFinalMinRangeForAimBonusValue = GetMinRangeForAimBonus(gpItemDescObject) / 10;
INT16 iFinalMinRangeForAimBonusValue = GetMinRangeForAimBonus( NULL, gpItemDescObject ) / 10;
// Get Minimum Range For Aim Bonus modifier
INT16 iMinRangeForAimBonusModifier = iFinalMinRangeForAimBonusValue - iMinRangeForAimBonusValue;
@@ -6571,7 +6571,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
sHeight = gItemDescGenRegions[ubNumLine][1].sBottom - sTop;
// Get final Burst Cost
INT16 iFinalBurstAPCost = ubAttackAPs + CalcAPsToBurst( APBPConstants[DEFAULT_APS], gpItemDescObject );
INT16 iFinalBurstAPCost = ubAttackAPs + CalcAPsToBurst( APBPConstants[DEFAULT_APS], gpItemDescObject, NULL );
// Get base Burst Cost
INT16 iBurstAPCost = ubBasicAttackAPs + CalcAPsToBurstNoModifier( APBPConstants[DEFAULT_APS], gpItemDescObject );
@@ -6637,7 +6637,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
sHeight = gItemDescGenRegions[ubNumLine][1].sBottom - sTop;
// Get final Autofire Cost
INT16 iFinalAutoAPCost = ubAttackAPs + CalcAPsToAutofire( APBPConstants[DEFAULT_APS], gpItemDescObject, 3 );
INT16 iFinalAutoAPCost = ubAttackAPs + CalcAPsToAutofire( APBPConstants[DEFAULT_APS], gpItemDescObject, 3, NULL );
// Get base Autofire Cost
INT16 iAutoAPCost = ubBasicAttackAPs + CalcAPsToAutofireNoModifier( APBPConstants[DEFAULT_APS], gpItemDescObject, 3 );
@@ -8578,7 +8578,7 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
///////////////////// AIM BONUS MODIFIER
if(UsingNewCTHSystem() == false)
{
iModifier[0] = GetAimBonus( gpItemDescObject, 100, 1 );
iModifier[0] = GetAimBonus( NULL, gpItemDescObject, 100, 1 );
iModifier[1] = 0;
iModifier[2] = 0;
if (iModifier[0] != 0 || iModifier[1] != 0 || iModifier[2] != 0)
@@ -9506,7 +9506,7 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
}
///////////////////// SINGLE-ATTACK AP MODIFIER
iModifier[0] = GetPercentAPReduction( gpItemDescObject );
iModifier[0] = GetPercentAPReduction( NULL, gpItemDescObject );
iModifier[1] = iModifier[0];
iModifier[2] = iModifier[0];
if (iModifier[0] != 0 )
+115 -18
View File
@@ -262,6 +262,10 @@ UINT32 guiItemDescBoxBackground;
UINT32 guiItemInfoLBEBackground;
UINT32 guiMapItemDescBox;
UINT32 guiAttachmentSlot;
// HEADROCK HAM 4: This replaces "Misc" icons.
extern UINT32 guiItemInfoAdvancedIcon; // added here by Flugente
UINT32 guiItemGraphic;
UINT32 guiMoneyGraphicsForDescBox;
UINT32 guiBullet;
@@ -667,8 +671,17 @@ void GenerateProsString( STR16 zItemPros, OBJECTTYPE * pObject, UINT32 uiPixLimi
ubWeight = ubWeight + Item[ (*pObject)[0]->data.gun.usGunAmmoItem ].ubWeight;
}
// Flugente: If overheating is allowed, an overheated gun receives a slight malus to accuracy
FLOAT accuracyheatmultiplicator = 1.0;
if ( gGameOptions.fWeaponOverheating )
{
FLOAT overheatdamagepercentage = GetGunOverheatDamagePercentage( pObject );
FLOAT accuracymalus = (FLOAT)((max(1.0, overheatdamagepercentage) - 1.0) * 0.1);
accuracyheatmultiplicator = (FLOAT)max(0.0, 1.0 - accuracymalus);
}
//CHRISL: TODO - This needs to be updated for NCTH
if (Weapon[usItem].bAccuracy >= EXCEPTIONAL_ACCURACY )
if (accuracyheatmultiplicator * Weapon[usItem].bAccuracy >= EXCEPTIONAL_ACCURACY )
{
zTemp = Message[STR_ACCURATE];
if ( ! AttemptToAddSubstring( zItemPros, zTemp, &uiStringLength, uiPixLimit ) )
@@ -730,7 +743,7 @@ void GenerateProsString( STR16 zItemPros, OBJECTTYPE * pObject, UINT32 uiPixLimi
}
}
if (BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], gpItemDescObject ) <= EXCEPTIONAL_AP_COST)
if (BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], gpItemDescObject, NULL ) <= EXCEPTIONAL_AP_COST)
{
zTemp = Message[STR_QUICK_FIRING];
if ( ! AttemptToAddSubstring( zItemPros, zTemp, &uiStringLength, uiPixLimit ) )
@@ -803,8 +816,17 @@ void GenerateConsString( STR16 zItemCons, OBJECTTYPE * pObject, UINT32 uiPixLimi
zItemCons[0] = 0;
// Flugente: If overheating is allowed, an overheated gun receives a slight malus to accuracy
FLOAT accuracyheatmultiplicator = 1.0;
if ( gGameOptions.fWeaponOverheating )
{
FLOAT overheatdamagepercentage = GetGunOverheatDamagePercentage( pObject );
FLOAT accuracymalus = (FLOAT)((max(1.0, overheatdamagepercentage) - 1.0) * 0.1);
accuracyheatmultiplicator = (FLOAT)max(0.0, 1.0 - accuracymalus);
}
//CHRISL: TODO - This needs to be updated for NCTH
if (Weapon[usItem].bAccuracy <= BAD_ACCURACY)
if (accuracyheatmultiplicator * Weapon[usItem].bAccuracy <= BAD_ACCURACY)
{
zTemp = Message[STR_INACCURATE];
if ( ! AttemptToAddSubstring( zItemCons, zTemp, &uiStringLength, uiPixLimit ) )
@@ -858,7 +880,7 @@ void GenerateConsString( STR16 zItemCons, OBJECTTYPE * pObject, UINT32 uiPixLimi
}
}
if (BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], gpItemDescObject ) >= APBPConstants[BAD_AP_COST])
if (BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], gpItemDescObject, NULL ) >= APBPConstants[BAD_AP_COST])
{
zTemp = Message[STR_SLOW_FIRING];
if ( ! AttemptToAddSubstring( zItemCons, zTemp, &uiStringLength, uiPixLimit ) )
@@ -2043,7 +2065,7 @@ void addWeaponGroupsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP*
void addGrenadesToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup ){
addItemsToPocketPopup( pSoldier, sPocket, popup, IC_GRENADE, -1, -1, 0 );
addItemsToPocketPopup( pSoldier, sPocket, popup, IC_GRENADE, -1, -1, AC_DEFAULT1 );
addItemsToPocketPopup( pSoldier, sPocket, popup, IC_GRENADE, -1, -1, AC_GRENADE );
}
@@ -3747,22 +3769,77 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
{
SetRGBFontForeground( 95, 160, 154 );
sNewY = sY + sHeight - 24;
sNewY = sY;
swprintf( pStr, L"M" );
// Get length of string
uiStringLength=StringPixLength(pStr, ITEM_FONT );
sNewX = sX + 25;
sNewX = sX + sWidth - uiStringLength - 13;
if ( uiBuffer == guiSAVEBUFFER )
{
RestoreExternBackgroundRect( sNewX, sNewY, 15, 15 );
RestoreExternBackgroundRect( sNewX, sNewY, uiStringLength, 15 );
}
mprintf( sNewX, sNewY, pStr );
gprintfinvalidate( sNewX, sNewY, pStr );
}
if ( gGameExternalOptions.fScopeModes && gGameExternalOptions.fDisplayScopeModes && pSoldier && pObject == &(pSoldier->inv[HANDPOS] ) && Item[pSoldier->inv[HANDPOS].usItem].usItemClass == IC_GUN )
{
sNewX = sX + 5; // rather arbitrary
sNewY = sY;
// added by Flugente
// HEADROCK HAM 4: Advanced Icons
VOBJECT_DESC VObjectDesc;
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
strcpy( VObjectDesc.ImageFile, "INTERFACE\\ItemInfoAdvancedIcons.STI" );
AddStandardVideoObject( &VObjectDesc, &guiItemInfoAdvancedIcon );
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(&pSoldier->inv[HANDPOS], ObjList);
if ( IsAttachmentClass(ObjList[pSoldier->bScopeMode]->usItem, AC_SCOPE ) )
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoAdvancedIcon, 54, sNewX, sNewY, VO_BLT_TRANSSHADOW, NULL );
SetFontForeground( FONT_ORANGE );
FLOAT scopemagfactor = Item[ObjList[pSoldier->bScopeMode]->usItem].scopemagfactor;
INT16 sMagX = sNewX + 9;
if ( scopemagfactor > (INT8)scopemagfactor )
swprintf( pStr, L"%2.1f", scopemagfactor );
else
{
swprintf( pStr, L"%2.0f", scopemagfactor );
}
// Get length of string
uiStringLength=StringPixLength(pStr, ITEM_FONT );
if ( uiBuffer == guiSAVEBUFFER )
{
RestoreExternBackgroundRect( sNewX, sNewY, 20, 15 );
}
mprintf( sMagX, sNewY, pStr );
gprintfinvalidate( sMagX, sNewY, pStr );
}
else if ( IsAttachmentClass(ObjList[pSoldier->bScopeMode]->usItem, AC_SIGHT ) )
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoAdvancedIcon, 53, sNewX, sNewY, VO_BLT_TRANSSHADOW, NULL );
RestoreExternBackgroundRect( sNewX, sNewY, 15, 15 );
}
else
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoAdvancedIcon, 52, sNewX, sNewY, VO_BLT_TRANSSHADOW, NULL );
RestoreExternBackgroundRect( sNewX, sNewY, 15, 15 );
}
}
if((UsingNewInventorySystem() == true))
{
// CHRISL: Display astrisk when LBENODE active
@@ -6654,7 +6731,7 @@ void RenderItemDescriptionBox( )
mprintf( gODBItemDescRegions[3][6].sLeft, gODBItemDescRegions[3][6].sTop, L"%s", gWeaponStatsDesc[ 8 ] );
}
ubAttackAPs = BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], gpItemDescObject );
ubAttackAPs = BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], gpItemDescObject, NULL );
// WANNE: Fixed CTD when trowing an item with open description box
if (ubAttackAPs != -1 )
@@ -6686,14 +6763,14 @@ void RenderItemDescriptionBox( )
{
SetFontForeground( 5 );
}
swprintf( pStr, L"%2d", ubAttackAPs + CalcAPsToBurst( APBPConstants[DEFAULT_APS], gpItemDescObject ) );
swprintf( pStr, L"%2d", ubAttackAPs + CalcAPsToBurst( APBPConstants[DEFAULT_APS], gpItemDescObject, NULL ) );
FindFontRightCoordinates( gODBItemDescRegions[3][7].sLeft, gODBItemDescRegions[3][7].sTop, gODBItemDescRegions[3][7].sRight - gODBItemDescRegions[3][7].sLeft, gODBItemDescRegions[3][7].sBottom - gODBItemDescRegions[3][7].sTop ,pStr, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY, pStr );
}
else if (GetAutofireShotsPerFiveAPs(gpItemDescObject) > 0)
{
SetFontForeground( 5 );
swprintf( pStr, L"%2d", ubAttackAPs + CalcAPsToAutofire( APBPConstants[DEFAULT_APS], gpItemDescObject, 3 ) );
swprintf( pStr, L"%2d", ubAttackAPs + CalcAPsToAutofire( APBPConstants[DEFAULT_APS], gpItemDescObject, 3, NULL ) );
FindFontRightCoordinates( gODBItemDescRegions[3][7].sLeft, gODBItemDescRegions[3][7].sTop, gODBItemDescRegions[3][7].sRight - gODBItemDescRegions[3][7].sLeft, gODBItemDescRegions[3][7].sBottom - gODBItemDescRegions[3][7].sTop ,pStr, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY, pStr );
}
@@ -11115,7 +11192,7 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
//Calculate AP's
CHAR16 apStr[20];
CHAR16 apStr2[20];
INT16 ubAttackAPs = BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], pObject );
INT16 ubAttackAPs = BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], pObject, pSoldier );
if ( Weapon[ usItem ].NoSemiAuto )
{
@@ -11128,7 +11205,7 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
if (GetShotsPerBurst(pObject) > 0)
{
swprintf( apStr2, L" / %d", ubAttackAPs + CalcAPsToBurst( APBPConstants[DEFAULT_APS], pObject ) );
swprintf( apStr2, L" / %d", ubAttackAPs + CalcAPsToBurst( APBPConstants[DEFAULT_APS], pObject, NULL ) );
wcscat( apStr, apStr2 );
}
else
@@ -11138,7 +11215,7 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
if (GetAutofireShotsPerFiveAPs(pObject) > 0)
{
swprintf( apStr2, L" / %d", ubAttackAPs + CalcAPsToAutofire( APBPConstants[DEFAULT_APS], pObject, 3 ) );
swprintf( apStr2, L" / %d", ubAttackAPs + CalcAPsToAutofire( APBPConstants[DEFAULT_APS], pObject, 3, NULL ) );
wcscat( apStr, apStr2 );
}
else
@@ -11146,10 +11223,20 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
wcscat( apStr, L" / -" );
}
// Flugente: If overheating is allowed, an overheated gun receives a slight malus to accuracy
FLOAT accuracyheatmultiplicator = 1.0;
if ( gGameOptions.fWeaponOverheating )
{
FLOAT overheatdamagepercentage = GetGunOverheatDamagePercentage( pObject );
FLOAT accuracymalus = (FLOAT)((max(1.0, overheatdamagepercentage) - 1.0) * 0.1);
accuracyheatmultiplicator = (FLOAT)max(0.0, 1.0 - accuracymalus);
}
//Info for weapons
//swprintf( pStr, L"%s (%s) [%d%%]\n%s %d\n%s %d\n%s %d (%d)\n%s %s\n%s %1.1f %s",
INT8 accuracy = (UsingNewCTHSystem()==true?Weapon[ usItem ].nAccuracy:Weapon[ usItem ].bAccuracy);
accuracy *= accuracyheatmultiplicator;
#ifdef CHINESE
swprintf( pStr, ChineseSpecString4,
#else
@@ -11182,13 +11269,13 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
//Calculate AP's
CHAR16 apStr[20];
CHAR16 apStr2[20];
INT16 ubAttackAPs = BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], pObject );
INT16 ubAttackAPs = BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], pObject, pSoldier );
swprintf( apStr, L"%d", ubAttackAPs );
if (GetShotsPerBurst(pObject) > 0)
{
swprintf( apStr2, L" / %d", ubAttackAPs + CalcAPsToBurst( APBPConstants[DEFAULT_APS], pObject ) );
swprintf( apStr2, L" / %d", ubAttackAPs + CalcAPsToBurst( APBPConstants[DEFAULT_APS], pObject, NULL ) );
wcscat( apStr, apStr2 );
}
else
@@ -11198,7 +11285,7 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
if (GetAutofireShotsPerFiveAPs(pObject) > 0)
{
swprintf( apStr2, L" / %d", ubAttackAPs + CalcAPsToAutofire( APBPConstants[DEFAULT_APS], pObject, 3 ) );
swprintf( apStr2, L" / %d", ubAttackAPs + CalcAPsToAutofire( APBPConstants[DEFAULT_APS], pObject, 3, NULL ) );
wcscat( apStr, apStr2 );
}
else
@@ -11206,8 +11293,18 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
wcscat( apStr, L" / -" );
}
// Flugente: If overheating is allowed, an overheated gun receives a slight malus to accuracy
FLOAT accuracyheatmultiplicator = 1.0;
if ( gGameOptions.fWeaponOverheating )
{
FLOAT overheatdamagepercentage = GetGunOverheatDamagePercentage( pObject );
FLOAT accuracymalus = (FLOAT)((max(1.0, overheatdamagepercentage) - 1.0) * 0.1);
accuracyheatmultiplicator = (FLOAT)max(0.0, 1.0 - accuracymalus);
}
//Info for weapons
INT8 accuracy = (UsingNewCTHSystem()==true?Weapon[ usItem ].nAccuracy:Weapon[ usItem ].bAccuracy);
accuracy *= accuracyheatmultiplicator;
#ifdef CHINESE
swprintf( pStr, L"%s [%d%£¥]\n%s %d\n%s %d\n%s %d (%d)\n%s %s\n%s %1.1f %s",
@@ -11248,7 +11345,7 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
gWeaponStatsDesc[ 11 ], //Damage String
GetDamage(pObject), //Melee damage
gWeaponStatsDesc[ 6 ], //AP String
BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], pObject ), //AP's
BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], pObject, pSoldier ), //AP's
gWeaponStatsDesc[ 12 ], //Weight String
fWeight, //Weight
GetWeightUnitString() //Weight units
+20 -13
View File
@@ -620,26 +620,27 @@ extern OBJECTTYPE gTempObject;
#define IC_MAPFILTER_MISC ( IC_TENTACLES | IC_KEY | IC_MISC | IC_MONEY | IC_NONE )
#define IC_MAPFILTER_ALL ( IC_MAPFILTER_GUN | IC_MAPFILTER_AMMO | IC_MAPFILTER_EXPLOSV | IC_MAPFILTER_MELEE | IC_MAPFILTER_KIT | IC_MAPFILTER_LBE | IC_MAPFILTER_ARMOR | IC_MAPFILTER_MISC )
// redesigned by Flugente on 12-04-10
// Chrisl: Define attachment classes
#define AC_DEFAULT1 0x00000001 //1
#define AC_BARREL 0x00000002 //2
#define AC_BIPOD 0x00000001 //1
#define AC_SUPPRESSOR 0x00000002 //2
#define AC_LASER 0x00000004 //4
#define AC_SIGHT 0x00000008 //8
#define AC_SCOPE 0x00000010 //16
#define AC_STOCK 0x00000020 //32
#define AC_AMMO 0x00000040 //64
#define AC_MAGWELL 0x00000040 //64
#define AC_INTERNAL 0x00000080 //128
#define AC_EXTERNAL 0x00000100 //256
#define AC_UNDERBARREL 0x00000200 //512
#define AC_GRENADE 0x00000400 //1024
#define AC_ROCKET 0x00000800 //2048
#define AC_MISC1 0x00001000 //4096
#define AC_MISC2 0x00002000 //8192
#define AC_MISC3 0x00004000 //16384
#define AC_MISC4 0x00008000 //32768
#define AC_MISC5 0x00010000 //65536
#define AC_MISC6 0x00020000 //131072
#define AC_MISC7 0x00040000 //262144
#define AC_FOREGRIP 0x00001000 //4096
#define AC_HELMET 0x00002000 //8192
#define AC_VEST 0x00004000 //16384
#define AC_PANTS 0x00008000 //32768
#define AC_DETONATOR 0x00010000 //65536
#define AC_BATTERY 0x00020000 //131072
#define AC_EXTENDER 0x00040000 //262144
#define AC_MISC8 0x00080000 //524288
#define AC_MISC9 0x00100000 //1048576
#define AC_MISC10 0x00200000 //2097152
@@ -654,6 +655,7 @@ extern OBJECTTYPE gTempObject;
#define AC_MISC19 0x40000000 //1073741824
#define AC_MISC20 0x80000000 //2147483648
// replaces candamage
//#define ITEM_DAMAGEABLE 0x0001
//// replaces canrepair
@@ -816,7 +818,7 @@ typedef struct
BOOLEAN robotremotecontrol;
BOOLEAN camouflagekit;
BOOLEAN locksmithkit;
BOOLEAN mine;
BOOLEAN mine;
BOOLEAN alcohol;
BOOLEAN hardware;
BOOLEAN medical;
@@ -885,7 +887,12 @@ typedef struct
FLOAT overheatTemperatureModificator; // percentage modifier of heat a shot generates (read from attachments)
FLOAT overheatCooldownModificator; // percentage modifier of cooldown amount (read from attachments, applies to guns & barrels)
FLOAT overheatJamThresholdModificator; // percentage modifier of a gun's jam threshold (read from attachments)
FLOAT overheatDamageThresholdModificator; // percentage modifier of a gun's damage threshold (read from attachments)
FLOAT overheatDamageThresholdModificator; // percentage modifier of a gun's damage threshold (read from attachments)
UINT32 attachmentclass; // attachmentclass used
BOOLEAN tripwireactivation; // item (mine) can be activated by nearby tripwire
BOOLEAN tripwire; // item is tripwire
} INVTYPE;
@@ -1450,7 +1457,7 @@ typedef struct
UINT32 uiIndex;
} AttachmentInfoStruct;
extern AttachmentInfoStruct AttachmentInfo[MAXITEMS+1];
extern AttachmentInfoStruct AttachmentInfo[MAXITEMS+1];
extern UINT16 Launchable[MAXITEMS+1][2];
extern UINT16 CompatibleFaceItems[MAXITEMS+1][2];
+455 -90
View File
@@ -2220,7 +2220,7 @@ BOOLEAN ValidItemAttachmentSlot( OBJECTTYPE * pObj, UINT16 usAttachment, BOOLEAN
//Search for incompatible attachments
for(int i = 0;i<sizeof(IncompatibleAttachments);i++)
{
if ( FindAttachment(pObj, usAttachment, subObject) != 0 && !(Item[usAttachment].nasAttachmentClass & AC_GRENADE) && !(Item[usAttachment].nasAttachmentClass & AC_ROCKET))
if ( FindAttachment(pObj, usAttachment, subObject) != 0 && !IsAttachmentClass(usAttachment, AC_GRENADE|AC_ROCKET ) )
{//Search for identical attachments unless we're dealing with rifle grenades
fSameItem = TRUE;
break;
@@ -5860,6 +5860,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
pSoldier->bDoBurst = TRUE;
pSoldier->bDoAutofire = TRUE;
}
pSoldier->bScopeMode = USE_BEST_SCOPE;
}
// Lesh: end
@@ -7528,6 +7529,7 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNew
pSoldier->bDoBurst = TRUE;
pSoldier->bDoAutofire = 1;
}
pSoldier->bScopeMode = USE_BEST_SCOPE;
}
}
@@ -9036,16 +9038,30 @@ INT16 GetItemAimBonus( const INVTYPE* pItem, INT32 iRange, INT16 ubAimTime )
return(bonus);
}
INT16 GetAimBonus( OBJECTTYPE * pObj, INT32 iRange, INT16 ubAimTime )
INT16 GetAimBonus( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, INT32 iRange, INT16 ubAimTime )
{
INT16 bonus = 0;
if (pObj->exists() == true) {
bonus = BonusReduceMore( GetItemAimBonus( &Item[pObj->usItem], iRange, ubAimTime ), (*pObj)[0]->data.objectStatus );
if (pObj->exists() == true)
{
// Flugente: check for scope mode
if ( gGameExternalOptions.fScopeModes && pSoldier && Item[pObj->usItem].usItemClass == IC_GUN )
{
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pObj, ObjList);
bonus = BonusReduceMore( GetItemAimBonus( &Item[ObjList[pSoldier->bScopeMode]->usItem], iRange, ubAimTime ), (*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus );
}
else
bonus = BonusReduceMore( GetItemAimBonus( &Item[pObj->usItem], iRange, ubAimTime ), (*pObj)[0]->data.objectStatus );
bonus += GetItemAimBonus( &Item[(*pObj)[0]->data.gun.usGunAmmoItem], iRange, ubAimTime );
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if(iter->exists()){
attachmentList::iterator iterend = (*pObj)[0]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter)
{
if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) )
{
bonus += BonusReduceMore( GetItemAimBonus( &Item[iter->usItem], iRange, ubAimTime ), (*iter)[0]->data.objectStatus );
}
}
@@ -9772,17 +9788,42 @@ INT16 GetMeleeDamageBonus( OBJECTTYPE * pObj )
}
INT16 GetPercentAPReduction( OBJECTTYPE * pObj )
INT16 GetPercentAPReduction( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj )
{
INT16 bonus = 0;
if (pObj->exists() == true) {
bonus = BonusReduceMore( Item[pObj->usItem].percentapreduction, (*pObj)[0]->data.objectStatus );
bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].percentapreduction;
if (pObj->exists() == true)
{
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum )
{
bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].percentapreduction;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if(iter->exists()){
bonus += BonusReduceMore( Item[iter->usItem].percentapreduction,
(*iter)[0]->data.objectStatus );
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if( iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) )
{
bonus += BonusReduceMore( Item[iter->usItem].percentapreduction,
(*iter)[0]->data.objectStatus );
}
}
// Flugente: check for scope mode
if ( Item[pObj->usItem].usItemClass == IC_GUN )
{
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pObj, ObjList);
bonus += BonusReduceMore( Item[ObjList[pSoldier->bScopeMode]->usItem].percentapreduction, (*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus );
}
}
else
{
bonus = BonusReduceMore( Item[pObj->usItem].percentapreduction, (*pObj)[0]->data.objectStatus );
bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].percentapreduction;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if(iter->exists()){
bonus += BonusReduceMore( Item[iter->usItem].percentapreduction,
(*iter)[0]->data.objectStatus );
}
}
}
}
@@ -9976,7 +10017,8 @@ INT16 GetVisionRangeBonus( SOLDIERTYPE * pSoldier )
continue;
}
if (!IsWeapon(usItem) || (IsWeapon(usItem) && usingGunScope == true) )
// Flugente: weapons are checked later on...
if (!IsWeapon(usItem) )//|| (IsWeapon(usItem) && usingGunScope == true) )
{
bonus += BonusReduceMore( pItem->visionrangebonus, (*pObj)[0]->data.objectStatus );
}
@@ -9991,10 +10033,38 @@ INT16 GetVisionRangeBonus( SOLDIERTYPE * pSoldier )
// SANDRO - added scouting check
INT16 sScopebonus = 0;
pObj = &( pSoldier->inv[HANDPOS]);
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if(iter->exists()){
sScopebonus += BonusReduceMore( Item[iter->usItem].visionrangebonus, (*iter)[0]->data.objectStatus );
if (pObj->exists() == true)
{
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum )
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
// add boni only from non-scope items
if( iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) )
{
sScopebonus += BonusReduceMore( Item[iter->usItem].visionrangebonus, (*iter)[0]->data.objectStatus );
}
}
// Flugente: check for scope mode
if ( Item[pObj->usItem].usItemClass == IC_GUN )
{
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pObj, ObjList);
// now apply the bonus from the scope we use
sScopebonus += BonusReduceMore( Item[ObjList[pSoldier->bScopeMode]->usItem].visionrangebonus, (*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus );
}
}
else
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
// add boni only from non-scope items
if( iter->exists() )
{
sScopebonus += BonusReduceMore( Item[iter->usItem].visionrangebonus, (*iter)[0]->data.objectStatus );
}
}
}
}
@@ -10052,7 +10122,8 @@ INT16 GetNightVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel )
continue;
}
if (!IsWeapon(usItem) || (IsWeapon(usItem) && usingGunScope == true ) )
// Flugente: weapons are checked later on...
if (!IsWeapon(usItem) )//|| (IsWeapon(usItem) && usingGunScope == true ) )
{
bonus += BonusReduceMore(
NightBonusScale( pItem->nightvisionrangebonus, bLightLevel ),
@@ -10067,12 +10138,44 @@ INT16 GetNightVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel )
// SANDRO - added scouting check
INT16 sScopebonus = 0;
pObj = &( pSoldier->inv[HANDPOS]);
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if(iter->exists()){
if (pObj->exists() == true)
{
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum )
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
// add boni only from non-scope items
if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) )
{
sScopebonus += BonusReduceMore(
NightBonusScale( Item[iter->usItem].nightvisionrangebonus, bLightLevel ),
(*iter)[0]->data.objectStatus );
}
}
// Flugente: check for scope mode
if ( Item[pObj->usItem].usItemClass == IC_GUN )
{
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pObj, ObjList);
// now apply the bonus from the scope we use
sScopebonus += BonusReduceMore(
NightBonusScale( Item[iter->usItem].nightvisionrangebonus, bLightLevel ),
(*iter)[0]->data.objectStatus );
NightBonusScale( Item[ObjList[pSoldier->bScopeMode]->usItem].cavevisionrangebonus, bLightLevel ),
(*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus );
}
}
else
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
// add boni only from non-scope items
if(iter->exists() )
{
sScopebonus += BonusReduceMore(
NightBonusScale( Item[iter->usItem].nightvisionrangebonus, bLightLevel ),
(*iter)[0]->data.objectStatus );
}
}
}
}
@@ -10117,7 +10220,8 @@ INT16 GetCaveVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel )
continue;
}
if (!IsWeapon(usItem) || (IsWeapon(usItem) && usingGunScope == true ) )
// Flugente: weapons are checked later on...
if (!IsWeapon(usItem) )//|| (IsWeapon(usItem) && usingGunScope == true ) )
{
bonus += BonusReduceMore(
NightBonusScale( pItem->cavevisionrangebonus, bLightLevel ),
@@ -10132,12 +10236,44 @@ INT16 GetCaveVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel )
// SANDRO - added scouting check
INT16 sScopebonus = 0;
pObj = &( pSoldier->inv[HANDPOS]);
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if(iter->exists()){
if (pObj->exists() == true)
{
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum )
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
// add boni only from non-scope items
if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) )
{
sScopebonus += BonusReduceMore(
NightBonusScale( Item[iter->usItem].cavevisionrangebonus, bLightLevel ),
(*iter)[0]->data.objectStatus );
}
}
// Flugente: check for scope mode
if ( Item[pObj->usItem].usItemClass == IC_GUN )
{
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pObj, ObjList);
// now apply the bonus from the scope we use
sScopebonus += BonusReduceMore(
NightBonusScale( Item[iter->usItem].cavevisionrangebonus, bLightLevel ),
(*iter)[0]->data.objectStatus );
NightBonusScale( Item[ObjList[pSoldier->bScopeMode]->usItem].cavevisionrangebonus, bLightLevel ),
(*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus );
}
}
else
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
// add boni only from non-scope items
if(iter->exists() )
{
sScopebonus += BonusReduceMore(
NightBonusScale( Item[iter->usItem].cavevisionrangebonus, bLightLevel ),
(*iter)[0]->data.objectStatus );
}
}
}
}
@@ -10157,7 +10293,7 @@ INT16 GetDayVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel )
OBJECTTYPE *pObj;
UINT16 usItem;
INVTYPE *pItem;
// Snap: Scale the bonus with the light level
//ADB and AXP 28.03.2007: CtH bug fix: We also want to check on a firing weapon, "raised" alone is not enough ;)
@@ -10184,7 +10320,8 @@ INT16 GetDayVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel )
continue;
}
if (!IsWeapon(usItem) || (IsWeapon(usItem) && usingGunScope == true ) )
// Flugente: weapons are checked later on...
if (!IsWeapon(usItem) )//|| (IsWeapon(usItem) && usingGunScope == true ) )
{
bonus += BonusReduceMore( idiv( pItem->dayvisionrangebonus
* (NORMAL_LIGHTLEVEL_NIGHT - bLightLevel), NORMAL_LIGHTLEVEL_NIGHT ),
@@ -10202,12 +10339,45 @@ INT16 GetDayVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel )
// SANDRO - added scouting check
INT16 sScopebonus = 0;
pObj = &( pSoldier->inv[HANDPOS]);
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if(iter->exists()){
sScopebonus += BonusReduceMore( idiv( Item[iter->usItem].dayvisionrangebonus
if (pObj->exists() == true)
{
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum )
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
// add boni only from non-scope items
if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) )
{
sScopebonus += BonusReduceMore( idiv( Item[iter->usItem].dayvisionrangebonus
* (NORMAL_LIGHTLEVEL_NIGHT - __max(bLightLevel,NORMAL_LIGHTLEVEL_DAY)), (NORMAL_LIGHTLEVEL_NIGHT-NORMAL_LIGHTLEVEL_DAY) ),
(*iter)[0]->data.objectStatus );
}
}
// Flugente: check for scope mode
if ( Item[pObj->usItem].usItemClass == IC_GUN )
{
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pObj, ObjList);
// now apply the bonus from the scope we use
sScopebonus += BonusReduceMore( idiv( Item[ObjList[pSoldier->bScopeMode]->usItem].dayvisionrangebonus
* (NORMAL_LIGHTLEVEL_NIGHT - __max(bLightLevel,NORMAL_LIGHTLEVEL_DAY)), (NORMAL_LIGHTLEVEL_NIGHT-NORMAL_LIGHTLEVEL_DAY) ),
(*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus );
}
}
else
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
// add boni only from non-scope items
if(iter->exists() )
{
sScopebonus += BonusReduceMore( idiv( Item[iter->usItem].dayvisionrangebonus
* (NORMAL_LIGHTLEVEL_NIGHT - __max(bLightLevel,NORMAL_LIGHTLEVEL_DAY)), (NORMAL_LIGHTLEVEL_NIGHT-NORMAL_LIGHTLEVEL_DAY) ),
(*iter)[0]->data.objectStatus );
}
}
}
}
@@ -10254,7 +10424,8 @@ INT16 GetBrightLightVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel
continue;
}
if (!IsWeapon(usItem) || (IsWeapon(usItem) && usingGunScope == true ) )
// Flugente: weapons are checked later on...
if (!IsWeapon(usItem) )//|| (IsWeapon(usItem) && usingGunScope == true ) )
{
bonus += BonusReduceMore( idiv( pItem->brightlightvisionrangebonus
* (NORMAL_LIGHTLEVEL_DAY - bLightLevel), NORMAL_LIGHTLEVEL_DAY ),
@@ -10269,12 +10440,44 @@ INT16 GetBrightLightVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel
// SANDRO - added scouting check
INT16 sScopebonus = 0;
pObj = &( pSoldier->inv[HANDPOS]);
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if(iter->exists()){
sScopebonus += BonusReduceMore( idiv( Item[iter->usItem].brightlightvisionrangebonus
* (NORMAL_LIGHTLEVEL_DAY - bLightLevel), NORMAL_LIGHTLEVEL_DAY ),
(*iter)[0]->data.objectStatus );
if (pObj->exists() == true)
{
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum )
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
// add boni only from non-scope items
if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) )
{
sScopebonus += BonusReduceMore( idiv( Item[iter->usItem].brightlightvisionrangebonus
* (NORMAL_LIGHTLEVEL_DAY - bLightLevel), NORMAL_LIGHTLEVEL_DAY ),
(*iter)[0]->data.objectStatus );
}
}
// Flugente: check for scope mode
if ( Item[pObj->usItem].usItemClass == IC_GUN )
{
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pObj, ObjList);
// now apply the bonus from the scope we use
sScopebonus += BonusReduceMore( idiv( Item[ObjList[pSoldier->bScopeMode]->usItem].brightlightvisionrangebonus
* (NORMAL_LIGHTLEVEL_DAY - bLightLevel), NORMAL_LIGHTLEVEL_DAY ),
(*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus );
}
}
else
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
// add boni only from non-scope items
if(iter->exists() )
{
sScopebonus += BonusReduceMore( idiv( Item[iter->usItem].brightlightvisionrangebonus
* (NORMAL_LIGHTLEVEL_DAY - bLightLevel), NORMAL_LIGHTLEVEL_DAY ),
(*iter)[0]->data.objectStatus );
}
}
}
}
@@ -10370,16 +10573,45 @@ UINT8 GetPercentTunnelVision( SOLDIERTYPE * pSoldier )
if ( usingGunScope == true )
{
OBJECTTYPE *pObj = &(pSoldier->inv[HANDPOS]);
if (pObj->exists() == true) {
if (pObj->exists() == true)
{
usItem = pObj->usItem;
pItem = &(Item[usItem]);
if ( IsWeapon(usItem) ) //if not a weapon, then it was added already above
bonus += Item[usItem].percenttunnelvision;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if(iter->exists())
bonus += Item[iter->usItem].percenttunnelvision;
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum )
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
// add boni only from non-scope items
if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) )
{
bonus += Item[iter->usItem].percenttunnelvision;
}
}
// Flugente: check for scope mode
if ( Item[pObj->usItem].usItemClass == IC_GUN )
{
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pObj, ObjList);
// now apply the bonus from the scope we use
bonus += Item[ObjList[pSoldier->bScopeMode]->usItem].percenttunnelvision;
}
}
else
{
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
// add boni only from non-scope items
if(iter->exists() )
{
bonus += Item[iter->usItem].percenttunnelvision;
}
}
}
}
}
@@ -11385,44 +11617,73 @@ FLOAT GetHighestScopeMagnificationFactor( OBJECTTYPE * pObj )
return( BestFactor );
}
INT16 GetMinRangeForAimBonus( OBJECTTYPE * pObj )
INT16 GetMinRangeForAimBonus( SOLDIERTYPE* pSoldier, OBJECTTYPE * pObj )
{
INT16 bonus = 0;
if ( pObj->exists() == true ) {
bonus = Item[pObj->usItem].minrangeforaimbonus;
//bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].minrangeforaimbonus;
if ( pObj->exists() == true )
{
// Flugente: check for scope mode
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum && Item[pObj->usItem].usItemClass == IC_GUN )
{
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pObj, ObjList);
bonus = Item[ObjList[pSoldier->bScopeMode]->usItem].minrangeforaimbonus;
}
else
bonus = Item[pObj->usItem].minrangeforaimbonus;
//bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].minrangeforaimbonus;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
bonus += Item[iter->usItem].minrangeforaimbonus;
attachmentList::iterator iterend = (*pObj)[0]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter)
{
if ( !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) )
bonus += Item[iter->usItem].minrangeforaimbonus;
}
}
return( bonus );
}
FLOAT GetScopeMagnificationFactor( OBJECTTYPE * pObj, FLOAT uiRange )
// altered by Flugente: uiRange is no more considered
FLOAT GetScopeMagnificationFactor( SOLDIERTYPE *pSoldier, OBJECTTYPE * pObj, FLOAT uiRange )
{
FLOAT BestFactor = 1.0;
// Flugente: if scope modes are allowed, player team uses them
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum && pObj->exists() == true && Item[pObj->usItem].usItemClass == IC_GUN)
{
// Flugente: check for scope mode
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pObj, ObjList);
// now apply the bonus from the scope we use
BestFactor = Item[ObjList[pSoldier->bScopeMode]->usItem].scopemagfactor;
return __max(1.0f, BestFactor);
}
FLOAT CurrentFactor = 0.0;
FLOAT TargetMagFactor = __max(1.0f,(FLOAT)uiRange / (FLOAT)gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
FLOAT rangeModifier = gGameCTHConstants.SCOPE_RANGE_MULTIPLIER;
TargetMagFactor = TargetMagFactor / rangeModifier;
if(pObj->exists() == true && UsingNewCTHSystem() == true)
{
BestFactor = __max(1.0f, Item[pObj->usItem].scopemagfactor);
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
attachmentList::iterator iterend = (*pObj)[0]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter)
{
if(iter->exists() == true)
if(iter->exists() == true )
{
if(BestFactor == 1.0f)
BestFactor = __max(BestFactor, Item[iter->usItem].scopemagfactor);
else if(Item[iter->usItem].scopemagfactor >= TargetMagFactor)
BestFactor = Item[iter->usItem].scopemagfactor;
}
}
}
}
@@ -11431,6 +11692,17 @@ FLOAT GetScopeMagnificationFactor( OBJECTTYPE * pObj, FLOAT uiRange )
FLOAT GetBestScopeMagnificationFactor( SOLDIERTYPE *pSoldier, OBJECTTYPE * pObj, FLOAT uiRange )
{
// Flugente: if scope modes are allowed, player team uses them
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum && pObj->exists() == true && Item[pObj->usItem].usItemClass == IC_GUN )
{
// Flugente: check for scope mode
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pObj, ObjList);
// now apply the bonus from the scope we use
return max(1.0f, Item[ObjList[pSoldier->bScopeMode]->usItem].scopemagfactor);
}
FLOAT BestFactor = 1.0;
FLOAT TargetMagFactor = __max(1.0f,uiRange / (FLOAT)gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
FLOAT CurrentFactor = 0.0;
@@ -11527,7 +11799,7 @@ FLOAT GetBestScopeMagnificationFactor( SOLDIERTYPE *pSoldier, OBJECTTYPE * pObj,
FLOAT GetProjectionFactor( OBJECTTYPE * pObj )
{
FLOAT BestFactor = 1.0;
if ( pObj->exists() == true && UsingNewCTHSystem() == true ) {
BestFactor = __max((FLOAT)Item[pObj->usItem].projectionfactor, 1.0f);
@@ -11548,7 +11820,7 @@ FLOAT GetScopeRangeMultiplier( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, FLOAT d2
FLOAT iScopeFactor = 0;
FLOAT rangeModifier = gGameCTHConstants.SCOPE_RANGE_MULTIPLIER;
iScopeFactor = GetScopeMagnificationFactor( pObj, d2DDistance );
iScopeFactor = GetScopeMagnificationFactor( pSoldier, pObj, d2DDistance );
if( gGameOptions.fNewTraitSystem )
{
if(iScopeFactor > 5.0f)
@@ -11786,35 +12058,50 @@ UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier, INT32 sGridNo)
// don't break compatibility, let the users choose
if (gGameExternalOptions.iAimLevelsCompatibilityOption != 0)
{
sScopeBonus = OldWayOfCalculatingScopeBonus(pSoldier);
}
//WarmSteel - Using scope aimbonus instead, as it is used elsewhere like this too.
//Also, you won't get extra aimclicks anymore if you're too close to use your scope.
//I've externalized the scope types.
else if ( gGameExternalOptions.fAimLevelsDependOnDistance )
{
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum && (&pSoldier->inv[pSoldier->ubAttackingHand])->exists() == true && Item[(&pSoldier->inv[pSoldier->ubAttackingHand])->usItem].usItemClass == IC_GUN)
{
// Flugente: check for scope mode
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(&pSoldier->inv[pSoldier->ubAttackingHand], ObjList);
sScopeBonus = Item[ObjList[pSoldier->bScopeMode]->usItem].aimbonus;
}
else
sScopeBonus = GetBaseScopeAimBonus( &pSoldier->inv[pSoldier->ubAttackingHand], uiRange );
}
else
sScopeBonus = gGameExternalOptions.fAimLevelsDependOnDistance ?
//WarmSteel - Using scope aimbonus instead, as it is used elsewhere like this too.
//Also, you won't get extra aimclicks anymore if you're too close to use your scope.
//I've externalized the scope types.
GetBaseScopeAimBonus( &pSoldier->inv[pSoldier->ubAttackingHand], uiRange )
: GetMinRangeForAimBonus( &pSoldier->inv[pSoldier->ubAttackingHand]);
{
sScopeBonus = GetMinRangeForAimBonus( pSoldier, &pSoldier->inv[pSoldier->ubAttackingHand]);
}
if ( sScopeBonus >= gGameExternalOptions.sVeryHighPowerScope )
{
aimLevels *= 2;
}
if ( sScopeBonus >= gGameExternalOptions.sVeryHighPowerScope )
{
aimLevels *= 2;
}
else if ( sScopeBonus >= gGameExternalOptions.sHighPowerScope )
{
aimLevels = (UINT8)((float)(aimLevels+1) * (float)1.5);
}
else if ( sScopeBonus >= gGameExternalOptions.sHighPowerScope )
{
aimLevels = (UINT8)((float)(aimLevels+1) * (float)1.5);
}
else if ( sScopeBonus >= gGameExternalOptions.sMediumPowerScope )
{
aimLevels = (UINT8)((float)(aimLevels+1) * (float)1.3);
}
else if ( sScopeBonus >= gGameExternalOptions.sMediumPowerScope )
{
aimLevels = (UINT8)((float)(aimLevels+1) * (float)1.3);
}
// Smaller scopes increase by one.
else if ( sScopeBonus > 0 )
{
aimLevels++;
}
// Smaller scopes increase by one.
else if ( sScopeBonus > 0 )
{
aimLevels++;
}
// Make sure not over maximum allowed for weapon type.
if (aimLevels > maxAimForType)
@@ -11846,7 +12133,18 @@ UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier, INT32 sGridNo)
if (gGameExternalOptions.iAimLevelsCompatibilityOption != 0)
sScopeBonus = OldWayOfCalculatingScopeBonus(pSoldier);
else
sScopeBonus = gGameExternalOptions.fAimLevelsDependOnDistance ? GetBaseScopeAimBonus( pAttackingWeapon, uiRange ) : GetBaseScopeAimBonus( pAttackingWeapon, 25000 );
{
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum && pAttackingWeapon->exists() == true && Item[pAttackingWeapon->usItem].usItemClass == IC_GUN)
{
// Flugente: check for scope mode
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pAttackingWeapon, ObjList);
sScopeBonus = Item[ObjList[pSoldier->bScopeMode]->usItem].aimbonus;
}
else
sScopeBonus = gGameExternalOptions.fAimLevelsDependOnDistance ? GetBaseScopeAimBonus( pAttackingWeapon, uiRange ) : GetBaseScopeAimBonus( pAttackingWeapon, 25000 );
}
if ( sScopeBonus >= gGameExternalOptions.sVeryHighPowerScope )
{
@@ -12150,7 +12448,7 @@ INT16 GetBipodBonus( OBJECTTYPE * pObj )
INT16 GetItemVisionRangeBonus( OBJECTTYPE * pObj, INT16 VisionType )
{
INT16 bonus = 0;
if (VisionType == 0)
{
bonus += Item[ pObj->usItem ].visionrangebonus;
@@ -12274,13 +12572,22 @@ INT16 GetBasicStealthBonus( OBJECTTYPE * pObj )
// HEADROCK HAM 4: Calculate a gun's accuracy, including bonuses from ammo and attachments.
INT32 GetGunAccuracy( OBJECTTYPE *pObj )
{
// Flugente: If overheating is allowed, an overheated gun receives a slight malus to accuracy
FLOAT accuracyheatmultiplicator = 1.0;
if ( gGameOptions.fWeaponOverheating )
{
FLOAT overheatdamagepercentage = GetGunOverheatDamagePercentage( pObj );
FLOAT accuracymalus = (max(1.0, overheatdamagepercentage) - 1.0) * 0.1;
accuracyheatmultiplicator = max(0.0, 1.0 - accuracymalus);
}
if(UsingNewCTHSystem() == false)
return(Weapon[pObj->usItem].bAccuracy);
return(accuracyheatmultiplicator * Weapon[pObj->usItem].bAccuracy);
INT32 bonus = 0;
if ( pObj->exists() == true )
{
bonus = Weapon[Item[pObj->usItem].uiIndex].nAccuracy;
bonus = accuracyheatmultiplicator * Weapon[Item[pObj->usItem].uiIndex].nAccuracy;
bonus = (bonus * (*pObj)[0]->data.gun.bGunStatus) / 100;
INT32 iModifier = GetAccuracyModifier( pObj );
@@ -12598,7 +12905,7 @@ static UINT16 OldWayOfCalculatingScopeBonus(SOLDIERTYPE *pSoldier)
// Yes, this may look stupid, maybe it IS stupid, but this is purely an option
// to use code that was checked in before.
// Please, do not trash it again.
return max(0, GetMinRangeForAimBonus(& pSoldier->inv[pSoldier->ubAttackingHand])
return max(0, GetMinRangeForAimBonus( pSoldier, &pSoldier->inv[pSoldier->ubAttackingHand])
* gGameExternalOptions.iAimLevelsCompatibilityOption / gGameExternalOptions.ubStraightSightRange);
}
@@ -12627,6 +12934,64 @@ FLOAT GetItemCooldownFactor( OBJECTTYPE * pObj )
return cooldownfactor;
}
void GetScopeLists( OBJECTTYPE * pObj, std::map<INT8, OBJECTTYPE*>& arScopeMap )
{
// build a list of all available scopes and sights ( we always have at least one: our weapon's iron sights)
arScopeMap[USE_BEST_SCOPE] = pObj;
for (INT8 i = USE_SCOPE_2; i < NUM_SCOPE_MODES; ++i)
{
arScopeMap[i] = NULL;
}
attachmentList::iterator iterend = (*pObj)[0]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter)
{
if ( iter->exists() && IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) )
{
FLOAT magfactor = Item[iter->usItem].scopemagfactor;
BOOLEAN isplaced = false;
for (INT8 i = USE_BEST_SCOPE; i < NUM_SCOPE_MODES; ++i)
{
if ( arScopeMap[i] && magfactor > Item[arScopeMap[i]->usItem].scopemagfactor )
{
// fit scope into existing list: move other entries down
for (INT8 j = NUM_SCOPE_MODES; j > i; --j)
{
arScopeMap[j] = arScopeMap[j-1];
}
arScopeMap[i] = &(*iter);
isplaced = true;
break;
}
}
// we have a scope that wasn't placed anywhere, as its magfactor is worse than everything else we have. Still, we put this thing to the end of our list
if ( !isplaced )
{
// determine which scope this would be and insert it
for (INT8 i = USE_BEST_SCOPE; i < NUM_SCOPE_MODES; ++i)
{
if ( !arScopeMap[i] )
{
arScopeMap[i] = &(*iter);
break;
}
}
}
}
}
}
BOOLEAN IsAttachmentClass( UINT16 usItem, UINT32 aFlag )
{
return( Item[usItem].attachmentclass & aFlag );
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// HEADROCK HAM 5: Item Transformation.
// Item Transformation is a new way to interact with items. Where Merges combine two items into one, a Transformation
+9 -4
View File
@@ -4,6 +4,7 @@
#include "Overhead Types.h"
#include "Weapons.h"
#include <map> // added by Flugente
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
@@ -237,7 +238,7 @@ UINT16 MagazineClassIndexToItemType(UINT16 usMagIndex);
BOOLEAN IsScoped( OBJECTTYPE * pObj );
BOOLEAN NCTHIsScoped( OBJECTTYPE * pObj );
INT16 GetReliability( OBJECTTYPE * pObj );
INT16 GetAimBonus( OBJECTTYPE * pObj, INT32 iRange, INT16 ubAimTime );
INT16 GetAimBonus( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, INT32 iRange, INT16 ubAimTime );
//WarmSteel - Used to determine the base aim bonus of the most powerful scope.
INT16 GetBaseScopeAimBonus( OBJECTTYPE * pObj, INT32 iRange );
// HEADROCK: Function to get the natural aimbonus of the weapon and its attachments
@@ -256,7 +257,7 @@ INT16 GetBurstToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance = FALSE );
INT16 GetAutoToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance = FALSE );
INT16 GetGearAimBonus( SOLDIERTYPE * pSoldier, INT32 iRange, INT16 ubAimTime);
INT16 GetGearToHitBonus( SOLDIERTYPE * pSoldier );
INT16 GetMinRangeForAimBonus( OBJECTTYPE * pObj );
INT16 GetMinRangeForAimBonus( SOLDIERTYPE* pSoldier, OBJECTTYPE * pObj );
// HEADROCK: Function to get the final loudness value of a weapon, after reduction from its own characteristics, ammo and attachments
INT16 GetFinalLoudness( OBJECTTYPE * pObj );
@@ -289,7 +290,7 @@ INT8 GetStanceModifierRef( INT8 ubStance );
INT16 GetDamageBonus( OBJECTTYPE * pObj );
INT16 GetMeleeDamageBonus( OBJECTTYPE * pObj );
INT16 GetPercentAPReduction( OBJECTTYPE * pObj );
INT16 GetPercentAPReduction( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj );
INT16 GetPercentAutofireAPReduction( OBJECTTYPE * pObj );
INT16 GetPercentBurstFireAPReduction( OBJECTTYPE * pObj );
INT16 GetPercentReadyTimeAPReduction( OBJECTTYPE * pObj );
@@ -410,7 +411,7 @@ OBJECTTYPE* FindNightGogglesInInv( SOLDIERTYPE * pSoldier, INT8 * bSlot, BOOLEAN
UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier, INT32 sGridNo);
// HEADROCK HAM 4: New functions to determine Scope and Laser factors on a weapon.
FLOAT GetHighestScopeMagnificationFactor( OBJECTTYPE *pObj );
FLOAT GetScopeMagnificationFactor( OBJECTTYPE *pObj, FLOAT uiRange );
FLOAT GetScopeMagnificationFactor( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, FLOAT uiRange );
FLOAT GetBestScopeMagnificationFactor( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, FLOAT uiRange );
FLOAT GetProjectionFactor( OBJECTTYPE *pObj );
FLOAT GetScopeRangeMultiplier( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, FLOAT d2DDistance );
@@ -445,6 +446,10 @@ BOOLEAN UseTotalMedicalKitPoints( SOLDIERTYPE * pSoldier, UINT16 usPointsToConsu
// Flugente FTW 1.2
FLOAT GetItemCooldownFactor( OBJECTTYPE * pObj );
void GetScopeLists( OBJECTTYPE * pObj, std::map<INT8, OBJECTTYPE*>& arScopeMap );
// check if item belongs to a specific attachemnt class
BOOLEAN IsAttachmentClass( UINT16 usItem, UINT32 aFlag );
#endif
+25 -7
View File
@@ -7145,7 +7145,18 @@ FLOAT CalcProjectionFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2
if (ubAimTime > 0)
{
iProjectionFactor = GetProjectionFactor( pWeapon );
// Flugente: if scope modes are allowed, player team uses them
if ( gGameExternalOptions.fScopeModes && pShooter && pShooter->bTeam == gbPlayerNum && pWeapon->exists() == true && Item[pWeapon->usItem].usItemClass == IC_GUN )
{
// Flugente: check for scope mode
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(pWeapon, ObjList);
iProjectionFactor = Item[ObjList[pShooter->bScopeMode]->usItem].projectionfactor;
}
else
iProjectionFactor = GetProjectionFactor( pWeapon );
if (floor(iTargetMagFactor*10) > floor(iProjectionFactor*10.001))
{
iProjectionFactor -= (iTargetMagFactor - iProjectionFactor);
@@ -7158,22 +7169,29 @@ FLOAT CalcProjectionFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2
FLOAT CalcMagFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2DDistance, UINT8 ubAimTime )
{
FLOAT iFinalMagFactor = 0;
FLOAT iFinalMagFactor = 1.0;
FLOAT iScopeFactor = 0;
FLOAT iProjectionFactor = 0;
FLOAT iTargetMagFactor = d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE;
FLOAT rangeModifier = GetScopeRangeMultiplier(pShooter, pWeapon, d2DDistance);
if (ubAimTime > 0)
// Flugente: if scope modes are allowed, player team uses them. We either use a scope or we don't, so the magnification factor isn't fitted to range (this is actually bad)
if ( gGameExternalOptions.fScopeModes && pShooter && pShooter->bTeam == gbPlayerNum && pWeapon->exists() == true && Item[pWeapon->usItem].usItemClass == IC_GUN )
{
iScopeFactor = GetBestScopeMagnificationFactor( pShooter, pWeapon, d2DDistance );
iScopeFactor = __min(iScopeFactor, __max(1.0f, iTargetMagFactor/rangeModifier));
iProjectionFactor = CalcProjectionFactor(pShooter, pWeapon, d2DDistance, ubAimTime);
iFinalMagFactor = __max(iScopeFactor, iProjectionFactor);
}
else
{
iFinalMagFactor = 1.0;
FLOAT iTargetMagFactor = d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE;
FLOAT rangeModifier = GetScopeRangeMultiplier(pShooter, pWeapon, d2DDistance);
if (ubAimTime > 0)
{
iScopeFactor = GetBestScopeMagnificationFactor( pShooter, pWeapon, d2DDistance );
iScopeFactor = __min(iScopeFactor, __max(1.0f, iTargetMagFactor/rangeModifier));
iProjectionFactor = CalcProjectionFactor(pShooter, pWeapon, d2DDistance, ubAimTime);
iFinalMagFactor = __max(iScopeFactor, iProjectionFactor);
}
}
return iFinalMagFactor;
+1
View File
@@ -8650,6 +8650,7 @@ SOLDIERTYPE *InternalReduceAttackBusyCount( )
pSoldier->bDoAutofire = 1;
pSoldier->bDoBurst = TRUE;
}
pSoldier->bScopeMode = USE_BEST_SCOPE;
DirtyMercPanelInterface(pSoldier, DIRTYLEVEL2 );
}
+22 -22
View File
@@ -1338,7 +1338,7 @@ INT16 GetBreathPerAP( SOLDIERTYPE *pSoldier, UINT16 usAnimState )
}
//UINT8 CalcAPsToBurst( INT8 bBaseActionPoints, UINT16 usItem )
INT16 CalcAPsToBurst( INT16 bBaseActionPoints, OBJECTTYPE * pObj )
INT16 CalcAPsToBurst( INT16 bBaseActionPoints, OBJECTTYPE * pObj, SOLDIERTYPE* pSoldier )
{
INT32 aps;
@@ -1351,15 +1351,15 @@ INT16 CalcAPsToBurst( INT16 bBaseActionPoints, OBJECTTYPE * pObj )
aps = (aps * 100) / (100 + GetBurstFireAPReductionStatus(pObj) / (100/GetPercentBurstFireAPReduction(pObj)));
}
if ( GetPercentAPReduction(pObj)>0 )
if ( GetPercentAPReduction(pSoldier, pObj)>0 )
{
aps = (aps * 100) / (100 + GetAPReductionStatus(pObj) / (100/GetPercentAPReduction(pObj)));
aps = (aps * 100) / (100 + GetAPReductionStatus(pObj) / (100/GetPercentAPReduction(pSoldier, pObj)));
}*/
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcAPsToBurst: before bonus aps = %d, std bonus = %d, burst bonus = %d", aps,GetPercentAPReduction(pObj),GetPercentBurstFireAPReduction(pObj)));
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcAPsToBurst: before bonus aps = %d, std bonus = %d, burst bonus = %d", aps,GetPercentAPReduction(pSoldier, pObj),GetPercentBurstFireAPReduction(pObj)));
// Snap: do this a little differently: % reduction means
// aps <- aps * ( 100 - red ) / 100
aps = ( aps * ( 100 - GetPercentAPReduction(pObj) ) ) / 100;
aps = ( aps * ( 100 - GetPercentAPReduction(pSoldier, pObj) ) ) / 100;
// Snap: moved this up to allow burst AP reduction up to 100%
aps = __max( aps, ( Weapon[ pObj->usItem ].bBurstAP + 1 ) / 2 );
@@ -1388,7 +1388,7 @@ INT16 CalcAPsToBurstNoModifier( INT16 bBaseActionPoints, OBJECTTYPE * pObj )
return (UINT8) aps;
}
INT16 CalcAPsToAutofire( INT16 bBaseActionPoints, OBJECTTYPE * pObj, UINT8 bDoAutofire )
INT16 CalcAPsToAutofire( INT16 bBaseActionPoints, OBJECTTYPE * pObj, UINT8 bDoAutofire, SOLDIERTYPE* pSoldier )
{
//CHRISL: We send the actual number of rounds being fired in the bDoAutofire paramter. But that implies that it would take longer to fire the first round
// in an autofire sequence then it would take to fire a single round during a single fire sequence. That doesn't make any sense. It should only cost
@@ -1428,8 +1428,8 @@ INT16 CalcAPsToAutofire( INT16 bBaseActionPoints, OBJECTTYPE * pObj, UINT8 bDoAu
// DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcAPsToAutofire: found reflex sight, aps = %d, # shots = %d",aps,pSoldier->bDoAutofire ));
//}
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcAPsToAutoFire: before bonus aps = %d, std bonus = %d, auto bonus = %d", aps,GetPercentAPReduction(pObj),GetPercentAutofireAPReduction(pObj)));
aps = ( aps * ( 100 - GetPercentAPReduction(pObj) ) ) / 100;
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcAPsToAutoFire: before bonus aps = %d, std bonus = %d, auto bonus = %d", aps,GetPercentAPReduction(pSoldier, pObj),GetPercentAutofireAPReduction(pObj)));
aps = ( aps * ( 100 - GetPercentAPReduction(pSoldier, pObj) ) ) / 100;
aps = __max( aps, ( autofireaps + 1 ) / 2 );
@@ -1492,9 +1492,9 @@ INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTur
if ( pSoldier->bDoBurst )
{
if(pSoldier->bDoAutofire && GetAutofireShotsPerFiveAPs(AttackingWeapon) > 0 )
sAPCost += CalcAPsToAutofire( pSoldier->CalcActionPoints( ), AttackingWeapon, pSoldier->bDoAutofire );
sAPCost += CalcAPsToAutofire( pSoldier->CalcActionPoints( ), AttackingWeapon, pSoldier->bDoAutofire, pSoldier );
else
sAPCost += CalcAPsToBurst( pSoldier->CalcActionPoints( ), AttackingWeapon );
sAPCost += CalcAPsToBurst( pSoldier->CalcActionPoints( ), AttackingWeapon, pSoldier );
}
//else //ddd comment for aimed burst
{
@@ -1524,7 +1524,7 @@ INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTur
// If the weapon has a scope, and the target is within eligible range for scope use
if ( (UsingNewCTHSystem() == false && IsScoped(&pSoldier->inv[HANDPOS]) && GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo ) >= GetMinRangeForAimBonus(&pSoldier->inv[HANDPOS]))
if ( (UsingNewCTHSystem() == false && IsScoped(&pSoldier->inv[HANDPOS]) && GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo ) >= GetMinRangeForAimBonus( pSoldier, &pSoldier->inv[HANDPOS]))
|| (UsingNewCTHSystem() == true && GetBestScopeMagnificationFactor(pSoldier, &pSoldier->inv[HANDPOS], (FLOAT)GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo ) > 1.0 )) )
{
// Add an individual cost for EACH click, as necessary.
@@ -1742,7 +1742,7 @@ INT8 CalcAimSkill( SOLDIERTYPE * pSoldier, UINT16 usWeapon )
return( bAimSkill );
}
INT16 BaseAPsToShootOrStab( INT16 bAPs, INT16 bAimSkill, OBJECTTYPE * pObj )
INT16 BaseAPsToShootOrStab( INT16 bAPs, INT16 bAimSkill, OBJECTTYPE * pObj, SOLDIERTYPE* pSoldier )
{
INT32 Top, Bottom;
FLOAT rof;
@@ -1785,7 +1785,7 @@ INT16 BaseAPsToShootOrStab( INT16 bAPs, INT16 bAimSkill, OBJECTTYPE * pObj )
//CHRISL: Resolves a problem with stackable weapons not using attachments like Reflex sight. Found by Mugsy
//if (ItemSlotLimit(pObj, STACK_SIZE_LIMIT) == 1)
{
Top *= ( 100 - GetPercentAPReduction(pObj) );
Top *= ( 100 - GetPercentAPReduction(pSoldier, pObj) );
}
//else
//{
@@ -1990,9 +1990,9 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
//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(&GrenadeLauncher) > 0){
bAPCost += (BaseAPsToShootOrStab( bFullAPs, bAimSkill, &GrenadeLauncher ) * (100 - GetBipodBonus(&GrenadeLauncher)) / 100);
bAPCost += (BaseAPsToShootOrStab( bFullAPs, bAimSkill, &GrenadeLauncher, pSoldier ) * (100 - GetBipodBonus(&GrenadeLauncher)) / 100);
} else {
bAPCost += BaseAPsToShootOrStab( bFullAPs, bAimSkill, &GrenadeLauncher );
bAPCost += BaseAPsToShootOrStab( bFullAPs, bAimSkill, &GrenadeLauncher, pSoldier );
}
// SANDRO - STOMP traits - reduced APs needed to fire underbarrel grenade launchers for Heavy Weapons trait
@@ -2006,8 +2006,8 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
// SANDRO - gunslinger check for firing speed
if ( HAS_SKILL_TRAIT( pSoldier, GUNSLINGER_NT ) && gGameOptions.fNewTraitSystem )
{
INT16 bcst1 = BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[HANDPOS]) );
INT16 bcst2 = BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[SECONDHANDPOS]) );
INT16 bcst1 = BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[HANDPOS]), pSoldier );
INT16 bcst2 = BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[SECONDHANDPOS]), pSoldier );
if ( Weapon[ usItem ].ubWeaponType == GUN_PISTOL )
bcst1 = (INT16)((bcst1 * ( 100 - gSkillTraitValues.ubGSFiringSpeedBonusPistols) / 100)+ 0.5);
if ( Weapon[ pSoldier->inv[SECONDHANDPOS].usItem ].ubWeaponType == GUN_PISTOL )
@@ -2019,8 +2019,8 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
{
// charge the maximum of the two
bAPCost += __max(
BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[HANDPOS]) ),
BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[SECONDHANDPOS]) ) );
BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[HANDPOS]), pSoldier ),
BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[SECONDHANDPOS]), pSoldier ) );
}
}
else
@@ -2028,11 +2028,11 @@ INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurni
//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, pObjUsed ) * (100 - GetBipodBonus(&(pSoldier->inv[HANDPOS]))) / 100);
bAPCost += (BaseAPsToShootOrStab( bFullAPs, bAimSkill, pObjUsed, pSoldier ) * (100 - GetBipodBonus(&(pSoldier->inv[HANDPOS]))) / 100);
}
else
{
bAPCost += BaseAPsToShootOrStab( bFullAPs, bAimSkill, pObjUsed );
bAPCost += BaseAPsToShootOrStab( bFullAPs, bAimSkill, pObjUsed, pSoldier );
}
/////////////////////////////////////////////////////////////////////////////////////
// SANDRO - STOMP traits
@@ -3512,7 +3512,7 @@ INT32 CalcAPCostForAiming( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bAim
// If the weapon has a scope, and the target is within eligible range for scope use
if ( (UsingNewCTHSystem() == false && IsScoped(&pSoldier->inv[HANDPOS]) && GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sTargetGridNo ) >= GetMinRangeForAimBonus(&pSoldier->inv[HANDPOS]))
if ( (UsingNewCTHSystem() == false && IsScoped(&pSoldier->inv[HANDPOS]) && GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sTargetGridNo ) >= GetMinRangeForAimBonus(pSoldier, &pSoldier->inv[HANDPOS]))
|| (UsingNewCTHSystem() == true && GetBestScopeMagnificationFactor(pSoldier, &pSoldier->inv[HANDPOS], (FLOAT)GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sTargetGridNo ) > 1.0 )))
{
// Add an individual cost for EACH click, as necessary.
+3 -3
View File
@@ -275,7 +275,7 @@
//Just so the compiler will be able to use it in init.cpp, I'm a careful person. Gotthard 1/18/07
extern INT16 APBPConstants[TOTAL_APBP_VALUES];
INT16 BaseAPsToShootOrStab( INT16 bAPs, INT16 bAimSkill, OBJECTTYPE * pObj );
INT16 BaseAPsToShootOrStab( INT16 bAPs, INT16 bAimSkill, OBJECTTYPE * pObj, SOLDIERTYPE *pSoldier );
// HEADROCK HAM 4: Same function as above, except no modifier.
INT16 BaseAPsToShootOrStabNoModifier( INT16 bAPs, INT16 bAimSkill, OBJECTTYPE * pObj );
// HEADROCK HAM 4: Same function as above, except no modifier.
@@ -306,12 +306,12 @@ UINT16 GetAPsToPickupItem( SOLDIERTYPE *pSoldier, INT32 usMapPos );
INT16 MinAPsToPunch(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurningCost );
INT16 ApsToPunch( SOLDIERTYPE *pSoldier ); // SANDRO added this
INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurningCost, INT16 bAimTime );
INT16 CalcAPsToBurst( INT16 bBaseActionPoints, OBJECTTYPE * pObj );
INT16 CalcAPsToBurst( INT16 bBaseActionPoints, OBJECTTYPE * pObj, SOLDIERTYPE* pSoldier );
// HEADROCK HAM 4: Same as above, without percent modifiers.
INT16 CalcAPsToBurstNoModifier( INT16 bBaseActionPoints, OBJECTTYPE * pObj );
// HEADROCK HAM 4: Same as above, without percent modifiers.
INT16 CalcAPsToBurstNoModifier( INT16 bBaseActionPoints, OBJECTTYPE * pObj );
INT16 CalcAPsToAutofire( INT16 bBaseActionPoints, OBJECTTYPE * pObj, UINT8 bDoAutofire );
INT16 CalcAPsToAutofire( INT16 bBaseActionPoints, OBJECTTYPE * pObj, UINT8 bDoAutofire, SOLDIERTYPE* pSoldier );
// HEADROCK HAM 4: Same as above, without modifiers
INT16 CalcAPsToAutofireNoModifier( INT16 bBaseActionPoints, OBJECTTYPE * pObj, UINT8 bDoAutofire );
// HEADROCK HAM 4: Same as above, without modifiers
+3
View File
@@ -983,6 +983,8 @@ SOLDIERTYPE& SOLDIERTYPE::operator=(const OLDSOLDIERTYPE_101& src)
this->snowCamo = src.snowCamo;
this->wornSnowCamo = src.wornSnowCamo;
this->bScopeMode = USE_BEST_SCOPE;
}
return *this;
}
@@ -12340,6 +12342,7 @@ void SOLDIERTYPE::ReLoadSoldierAnimationDueToHandItemChange( UINT16 usOldItem, U
this->bWeaponMode = WM_AUTOFIRE;
this->bDoAutofire = 1;
}
this->bScopeMode = USE_BEST_SCOPE;
if ( gAnimControl[ this->usAnimState ].uiFlags & ANIM_FIREREADY )
{
+4 -1
View File
@@ -1151,6 +1151,9 @@ public:
UINT8 ubPercentDamageInflictedByTeam[NUM_ASSIST_SLOTS]; //The percent of damage inflicted by the player team. Each element corresponds to the Soldier ID. Each element contains the percent damage inflicted by that merc
#endif
// Flugente: Is this the correct position?
INT8 bScopeMode;
char endOfPOD; // marker for end of POD (plain old data)
// Note: Place all non-POD items at the end (after endOfPOD)
@@ -1319,7 +1322,7 @@ public:
BOOLEAN IsValidSecondHandShotForReloadingPurposes( void );
BOOLEAN SoldierCarriesTwoHandedWeapon( void );
void SoldierInventoryCoolDown( void ); // Flugente FTW 1: Cool down all items in inventory
BOOLEAN IsWeaponMounted( void ); // determine if we receive a bonus for mouning our weapon on something
BOOLEAN IsWeaponMounted( void ); // determine if we receive a bonus for mounting 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
+30
View File
@@ -220,6 +220,7 @@ void ToggleTreeTops();
void ToggleZBuffer();
void TogglePlanningMode();
void SetBurstMode();
void SetScopeMode();
void ObliterateSector();
void RandomizeMercProfile();
void CreateNextCivType();
@@ -4403,6 +4404,24 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
}
//else if( gusSelectedSoldier != NOBODY )
break;
// added by Flugente
case '.':
if ( fCtrl )
{
}
else if ( fAlt )
{
}
else
{
SetScopeMode();
}
break;
case 'z':
if( fCtrl && fAlt )
{
@@ -5175,6 +5194,17 @@ void SetBurstMode()
}
}
void SetScopeMode()
{
if ( gusSelectedSoldier != NOBODY )
{
ChangeScopeMode( MercPtrs[ gusSelectedSoldier ] );
// reevaluate sight
ManLooksForOtherTeams( MercPtrs[ gusSelectedSoldier ] );
}
}
void ObliterateSector()
{
INT32 cnt;
+118 -31
View File
@@ -6077,7 +6077,17 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
iMaxRange = CELL_X_SIZE; // one tile
iCoverRange = __max(0,iSightRange - iRange);
iMinRange = iMaxRange / 10;
iAccRangeMod = iRange * Weapon[usItemUsed].bAccuracy / 100;
// Flugente: If overheating is allowed, an overheated gun receives a slight malus to accuracy
FLOAT accuracyheatmultiplicator = 1.0;
if ( gGameOptions.fWeaponOverheating )
{
FLOAT overheatjampercentage = GetGunOverheatJamPercentage( pInHand );
FLOAT accuracymalus = (FLOAT)((max(1.0, overheatjampercentage) - 1.0) * 0.1);
accuracyheatmultiplicator = (FLOAT)max(0.0, 1.0 - accuracymalus);
}
iAccRangeMod = iRange * accuracyheatmultiplicator * Weapon[usItemUsed].bAccuracy / 100;
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
@@ -6097,9 +6107,9 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
else if ( HAS_SKILL_TRAIT( pSoldier, PROF_SNIPER_OT ) ) {
iSightRange -= ((gbSkillTraitBonus[ PROF_SNIPER_OT ] * NUM_SKILL_TRAITS( pSoldier, PROF_SNIPER_OT )) * iSightRange) /100;
}
if (iRange < GetMinRangeForAimBonus(&(pSoldier->inv[pSoldier->ubAttackingHand])) && iScopeVisionRangeBonus > 50){ // iSightRange penalty for using a high power scope within min range due to poor focus
if (iRange < GetMinRangeForAimBonus(pSoldier, &(pSoldier->inv[pSoldier->ubAttackingHand])) && iScopeVisionRangeBonus > 50){ // iSightRange penalty for using a high power scope within min range due to poor focus
iPenalty = 0;
for(UINT8 loop = 0; loop < ((GetMinRangeForAimBonus(&(pSoldier->inv[pSoldier->ubAttackingHand])) - iRange)/CELL_X_SIZE); loop++){
for(UINT8 loop = 0; loop < ((GetMinRangeForAimBonus(pSoldier, &(pSoldier->inv[pSoldier->ubAttackingHand])) - iRange)/CELL_X_SIZE); loop++){
iPenalty += iSightRange * iScopeVisionRangeBonus / 100;
}
iSightRange += iPenalty;
@@ -6311,15 +6321,28 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
// 25% penalty per tile closer than min range
iChance -= 25 * ( ( MIN_TANK_RANGE - iRange ) / CELL_X_SIZE );
}
for(attachmentList::iterator iter = (*&(pSoldier->inv[pSoldier->ubAttackingHand]))[0]->attachments.begin(); iter != (*&(pSoldier->inv[pSoldier->ubAttackingHand]))[0]->attachments.end(); iter++)
attachmentList::iterator iter_end = (*&(pSoldier->inv[pSoldier->ubAttackingHand]))[0]->attachments.end();
for(attachmentList::iterator iter = (*&(pSoldier->inv[pSoldier->ubAttackingHand]))[0]->attachments.begin(); iter != iter_end; ++iter)
{
if(iter->exists() && Item[iter->usItem].aimbonus >= gGameExternalOptions.sHighPowerScope && iRange > Item[iter->usItem].minrangeforaimbonus)
if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) && Item[iter->usItem].aimbonus >= gGameExternalOptions.sHighPowerScope && iRange > Item[iter->usItem].minrangeforaimbonus)
{
iPenalty = (Item[iter->usItem].aimbonus * (iRange - Item[iter->usItem].minrangeforaimbonus)) / 1000;
iPenalty = min(AIM_BONUS_PRONE, iPenalty);
iChance -= iPenalty;
}
}
// Flugente: check for scope mode
if ( Item[(&(pSoldier->inv[pSoldier->ubAttackingHand]))->usItem].usItemClass == IC_GUN )
{
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists((&(pSoldier->inv[pSoldier->ubAttackingHand])), ObjList);
iPenalty = (Item[ObjList[pSoldier->bScopeMode]->usItem].aimbonus * (iRange - Item[ObjList[pSoldier->bScopeMode]->usItem].minrangeforaimbonus)) / 1000;
iPenalty = min(AIM_BONUS_PRONE, iPenalty);
iChance -= iPenalty;
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
@@ -6328,7 +6351,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
{
// Bonus for heavy weapons moved here from above to get instant CtH bonus and not marksmanship bonus,
// which is supressed by weapon condition
if (Item[usItemUsed].rocketlauncher || Item[usItemUsed].singleshotrocketlauncher)
if (Item[usInHand].rocketlauncher || Item[usInHand].singleshotrocketlauncher)
{
iChance += gSkillTraitValues.bCtHModifierRocketLaunchers; // -25% for untrained mercs !!!
@@ -6336,7 +6359,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
iChance += gSkillTraitValues.ubHWBonusCtHRocketLaunchers * NUM_SKILL_TRAITS( pSoldier, HEAVY_WEAPONS_NT ); // +25% per trait
}
// Added CtH bonus for Gunslinger trait on pistols and machine-pistols
else if ( Weapon[usItemUsed].ubWeaponType == GUN_PISTOL )
else if ( Weapon[usInHand].ubWeaponType == GUN_PISTOL )
{
iChance += gSkillTraitValues.bCtHModifierPistols; // -5% for untrained mercs.
@@ -6344,7 +6367,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
if ( HAS_SKILL_TRAIT( pSoldier, GUNSLINGER_NT ) && pSoldier->bDoBurst == 0 && pSoldier->bDoAutofire == 0 )
iChance += gSkillTraitValues.ubGSBonusCtHPistols * NUM_SKILL_TRAITS( pSoldier, GUNSLINGER_NT ); // +10% per trait
}
else if ( Weapon[usItemUsed].ubWeaponType == GUN_M_PISTOL )
else if ( Weapon[usInHand].ubWeaponType == GUN_M_PISTOL )
{
iChance += gSkillTraitValues.bCtHModifierMachinePistols; // -5% for untrained mercs.
@@ -6353,21 +6376,21 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
iChance += gSkillTraitValues.ubGSBonusCtHMachinePistols * NUM_SKILL_TRAITS( pSoldier, GUNSLINGER_NT ); // +5% per trait
}
// Added CtH bonus for Machinegunner skill on assault rifles, SMGs and LMGs
else if ( Weapon[usItemUsed].ubWeaponType == GUN_AS_RIFLE )
else if ( Weapon[usInHand].ubWeaponType == GUN_AS_RIFLE )
{
iChance += gSkillTraitValues.bCtHModifierAssaultRifles; // -5% for untrained mercs.
if ( HAS_SKILL_TRAIT( pSoldier, AUTO_WEAPONS_NT ) )
iChance += gSkillTraitValues.ubAWBonusCtHAssaultRifles * NUM_SKILL_TRAITS( pSoldier, AUTO_WEAPONS_NT ); // +5% per trait
}
else if ( Weapon[usItemUsed].ubWeaponType == GUN_SMG )
else if ( Weapon[usInHand].ubWeaponType == GUN_SMG )
{
iChance += gSkillTraitValues.bCtHModifierSMGs; // -5% for untrained mercs.
if ( HAS_SKILL_TRAIT( pSoldier, AUTO_WEAPONS_NT ) )
iChance += gSkillTraitValues.ubAWBonusCtHSMGs * NUM_SKILL_TRAITS( pSoldier, AUTO_WEAPONS_NT ); // +5% per trait
}
else if ( Weapon[usItemUsed].ubWeaponType == GUN_LMG )
else if ( Weapon[usInHand].ubWeaponType == GUN_LMG )
{
iChance += gSkillTraitValues.bCtHModifierLMGs; // -10% for untrained mercs.
@@ -6375,7 +6398,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
iChance += gSkillTraitValues.ubAWBonusCtHLMGs * NUM_SKILL_TRAITS( pSoldier, AUTO_WEAPONS_NT ); // +5% per trait
}
// Added CtH bonus for Gunslinger trait on pistols and machine-pistols
else if ( Weapon[usItemUsed].ubWeaponType == GUN_SN_RIFLE )
else if ( Weapon[usInHand].ubWeaponType == GUN_SN_RIFLE )
{
iChance += gSkillTraitValues.bCtHModifierSniperRifles; // -5% for untrained mercs.
@@ -6384,7 +6407,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
iChance += gSkillTraitValues.ubSNBonusCtHSniperRifles * NUM_SKILL_TRAITS( pSoldier, SNIPER_NT ); // +5% per trait
}
// Added CtH bonus for Ranger skill on rifles and shotguns
else if ( Weapon[usItemUsed].ubWeaponType == GUN_RIFLE )
else if ( Weapon[usInHand].ubWeaponType == GUN_RIFLE )
{
iChance += gSkillTraitValues.bCtHModifierRifles; // -5% for untrained mercs.
@@ -6396,7 +6419,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
if ( HAS_SKILL_TRAIT( pSoldier, SNIPER_NT ) && pSoldier->bDoBurst == 0 && pSoldier->bDoAutofire == 0 )
iChance += gSkillTraitValues.ubSNBonusCtHRifles * NUM_SKILL_TRAITS( pSoldier, SNIPER_NT ); // +5% per trait
}
else if ( Weapon[usItemUsed].ubWeaponType == GUN_SHOTGUN )
else if ( Weapon[usInHand].ubWeaponType == GUN_SHOTGUN )
{
iChance += gSkillTraitValues.bCtHModifierShotguns; // -5% for untrained mercs.
@@ -6716,19 +6739,32 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
// progressivly less the more we aim. Everything is based on the maxBonus that a merc can possibly get which
// uses the equation: 20+(MRK/20*LVL)+Accuracy+(Sniper trait * 10). This value is then split between the 8
// possible AimTime's using a max aimTime bonus of 10.
if ( gGameOptions.fNewTraitSystem ) {
// Flugente: If overheating is allowed, an overheated gun receives a slight malus to accuracy
FLOAT accuracyheatmultiplicator = 1.0;
if ( gGameOptions.fWeaponOverheating )
{
FLOAT overheatdamagepercentage = GetGunOverheatDamagePercentage( pInHand );
FLOAT accuracymalus = (FLOAT)((max(1.0, overheatdamagepercentage) - 1.0) * 0.1);
accuracyheatmultiplicator = (FLOAT)max(0.0, 1.0 - accuracymalus);
}
if ( gGameOptions.fNewTraitSystem )
{
// bonus to snipers and gunslingers
if ( Weapon[usInHand].ubWeaponType == GUN_PISTOL || Weapon[usInHand].ubWeaponType == GUN_M_PISTOL )
maxBonus = 20+((FLOAT)iMarksmanship/20*(EffectiveExpLevel(pSoldier)))+(Weapon[Item[pInHand->usItem].ubClassIndex].bAccuracy*2)+(NUM_SKILL_TRAITS( pSoldier, GUNSLINGER_NT )*gSkillTraitValues.ubGSAimingBonusPerClick);
maxBonus = 20+((FLOAT)iMarksmanship/20*(EffectiveExpLevel(pSoldier)))+(accuracyheatmultiplicator * Weapon[Item[pInHand->usItem].ubClassIndex].bAccuracy*2)+(NUM_SKILL_TRAITS( pSoldier, GUNSLINGER_NT )*gSkillTraitValues.ubGSAimingBonusPerClick);
else
maxBonus = 20+((FLOAT)iMarksmanship/20*(EffectiveExpLevel(pSoldier)))+(Weapon[Item[pInHand->usItem].ubClassIndex].bAccuracy*2)+(NUM_SKILL_TRAITS( pSoldier, SNIPER_NT )*gSkillTraitValues.ubSNAimingBonusPerClick);
} else {
maxBonus = 20+((FLOAT)iMarksmanship/20*(EffectiveExpLevel(pSoldier)))+(accuracyheatmultiplicator * Weapon[Item[pInHand->usItem].ubClassIndex].bAccuracy*2)+(NUM_SKILL_TRAITS( pSoldier, SNIPER_NT )*gSkillTraitValues.ubSNAimingBonusPerClick);
}
else
{
if(gGameExternalOptions.bAltAimEnabled)
maxBonus = (20*(iMarksmanship/100))+((FLOAT)iMarksmanship/20*pSoldier->stats.bExpLevel)+(Weapon[Item[pInHand->usItem].ubClassIndex].bAccuracy*2)+(NUM_SKILL_TRAITS( pSoldier, PROF_SNIPER_OT )*10);
maxBonus = (20*(iMarksmanship/100))+((FLOAT)iMarksmanship/20*pSoldier->stats.bExpLevel)+(accuracyheatmultiplicator * Weapon[Item[pInHand->usItem].ubClassIndex].bAccuracy*2)+(NUM_SKILL_TRAITS( pSoldier, PROF_SNIPER_OT )*10);
else
maxBonus = 20+((FLOAT)iMarksmanship/20*pSoldier->stats.bExpLevel)+(Weapon[Item[pInHand->usItem].ubClassIndex].bAccuracy*2)+(NUM_SKILL_TRAITS( pSoldier, PROF_SNIPER_OT )*10);
maxBonus = 20+((FLOAT)iMarksmanship/20*pSoldier->stats.bExpLevel)+(accuracyheatmultiplicator * Weapon[Item[pInHand->usItem].ubClassIndex].bAccuracy*2)+(NUM_SKILL_TRAITS( pSoldier, PROF_SNIPER_OT )*10);
}
iAimBonus = (float)GetAimBonus( pInHand, 100, 1 );
iAimBonus = (float)GetAimBonus( pSoldier, pInHand, 100, 1 );
for(int i = 0; i < ubAimTime; i++) {
aimTimeBonus = __min((maxBonus*bonusProgression[i]/1000),maxClickBonus);
maxBonus -= aimTimeBonus;
@@ -10223,7 +10259,7 @@ void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInv
{
pSoldier->bWeaponMode = WM_NORMAL;
pSoldier->bDoBurst = FALSE;
pSoldier->bDoAutofire = 0;
pSoldier->bDoAutofire = 0;
}
else
{
@@ -10231,6 +10267,7 @@ void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInv
pSoldier->bDoBurst = TRUE;
pSoldier->bDoAutofire = 1;
}
pSoldier->bScopeMode = USE_BEST_SCOPE;
}
// if he is loaded tactically
@@ -10260,7 +10297,7 @@ void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInv
{
pSoldier->bWeaponMode = WM_NORMAL;
pSoldier->bDoBurst = FALSE;
pSoldier->bDoAutofire = 0;
pSoldier->bDoAutofire = 0;
}
else
{
@@ -10268,6 +10305,7 @@ void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInv
pSoldier->bDoAutofire = 1;
pSoldier->bDoBurst = TRUE;
}
pSoldier->bScopeMode = USE_BEST_SCOPE;
}
}
}
@@ -10710,6 +10748,37 @@ void ChangeWeaponMode( SOLDIERTYPE * pSoldier )
gfUIForceReExamineCursorData = TRUE;
}
// Flugente: use a different scope
void ChangeScopeMode( SOLDIERTYPE * pSoldier )
{
// just to be safe...
if ( !pSoldier )
return;
// ATE: Don't do this if in a fire animation.....
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_FIRE )
return;
if ( (&pSoldier->inv[HANDPOS])->exists() != true )
return;
std::map<INT8, OBJECTTYPE*> ObjList;
GetScopeLists(&pSoldier->inv[HANDPOS], ObjList);
do
{
pSoldier->bScopeMode++;
if(pSoldier->bScopeMode == NUM_SCOPE_MODES)
{
pSoldier->bScopeMode = USE_BEST_SCOPE;
}
}
while( ObjList[pSoldier->bScopeMode] == NULL && pSoldier->bScopeMode != USE_BEST_SCOPE);
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
gfUIForceReExamineCursorData = TRUE;
}
void DishoutQueenSwipeDamage( SOLDIERTYPE *pQueenSoldier )
{
INT8 bValidDishoutDirs[3][3] = { NORTH, NORTHEAST, -1,
@@ -11155,21 +11224,19 @@ void EstimateBulletsLeft( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj )
void CalcMagFactorSimple( SOLDIERTYPE *pSoldier, FLOAT d2DDistance, INT16 bAimTime )
{
OBJECTTYPE *pWeapon = &(pSoldier->inv[pSoldier->ubAttackingHand]);
FLOAT iActualMagFactor = 0;
FLOAT iHighestMagFactor = 0;
FLOAT iScopeFactor = 0;
FLOAT iProjectionFactor = 0;
FLOAT iTargetMagFactor = d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE;
FLOAT rangeModifier = GetScopeRangeMultiplier(pSoldier, pWeapon, d2DDistance);
if (bAimTime > 0)
// Flugente: if scope modes are allowed, player team uses them. We either use a scope or we don't, so the magnification factor isn't fitted to range (this is actually bad)
if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum && pWeapon->exists() == true && Item[pWeapon->usItem].usItemClass == IC_GUN )
{
iScopeFactor = GetBestScopeMagnificationFactor( pSoldier, pWeapon, d2DDistance );
// Set a display variable
gCTHDisplay.ScopeMagFactor = iScopeFactor;
iScopeFactor = __min(iScopeFactor, __max(1.0f, iTargetMagFactor/rangeModifier));
iProjectionFactor = CalcProjectionFactor(pSoldier, pWeapon, d2DDistance, (UINT8)bAimTime);
// Set a display variable
gCTHDisplay.ProjectionFactor = iProjectionFactor;
@@ -11179,9 +11246,29 @@ void CalcMagFactorSimple( SOLDIERTYPE *pSoldier, FLOAT d2DDistance, INT16 bAimTi
}
else
{
gCTHDisplay.ScopeMagFactor = 1.0;
gCTHDisplay.ProjectionFactor = 1.0;
iHighestMagFactor = 1.0;
FLOAT iTargetMagFactor = d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE;
FLOAT rangeModifier = GetScopeRangeMultiplier(pSoldier, pWeapon, d2DDistance);
if (bAimTime > 0)
{
iScopeFactor = GetBestScopeMagnificationFactor( pSoldier, pWeapon, d2DDistance );
// Set a display variable
gCTHDisplay.ScopeMagFactor = iScopeFactor;
iScopeFactor = __min(iScopeFactor, __max(1.0f, iTargetMagFactor/rangeModifier));
iProjectionFactor = CalcProjectionFactor(pSoldier, pWeapon, d2DDistance, (UINT8)bAimTime);
// Set a display variable
gCTHDisplay.ProjectionFactor = iProjectionFactor;
// The final factor is the largest of the two.
iHighestMagFactor = __max( iScopeFactor, iProjectionFactor );
}
else
{
gCTHDisplay.ScopeMagFactor = 1.0;
gCTHDisplay.ProjectionFactor = 1.0;
iHighestMagFactor = 1.0;
}
}
gCTHDisplay.FinalMagFactor = iHighestMagFactor;
+16
View File
@@ -18,6 +18,21 @@ enum WeaponMode
NUM_WEAPON_MODES
} ;
enum ScopeMode
{
USE_BEST_SCOPE = 0,
USE_SCOPE_2,
USE_SCOPE_3,
USE_SCOPE_4,
USE_SCOPE_5,
USE_SCOPE_6,
USE_SCOPE_7,
USE_SCOPE_8,
USE_SCOPE_9,
USE_SCOPE_10,
NUM_SCOPE_MODES
};
//ADB moved from Interface Panels.h
void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInvPos, UINT16 usOldItem, UINT16 usNewItem );
@@ -416,6 +431,7 @@ extern INT32 CalcMaxTossRange( SOLDIERTYPE * pSoldier, UINT16 usItem, BOOLEAN fA
extern UINT32 CalcThrownChanceToHit(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, UINT8 ubAimPos );
extern void ChangeWeaponMode( SOLDIERTYPE * pSoldier );
extern void ChangeScopeMode( SOLDIERTYPE * pSoldier ); // Flugente: use different scope
extern BOOLEAN UseHandToHand( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo, BOOLEAN fStealing );
+1 -1
View File
@@ -167,7 +167,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
pSoldier->usAttackingWeapon = pSoldier->inv[HANDPOS].usItem;
pSoldier->bWeaponMode = WM_NORMAL;
ubBurstAPs = CalcAPsToBurst( pSoldier->CalcActionPoints( ), &(pSoldier->inv[HANDPOS]) );
ubBurstAPs = CalcAPsToBurst( pSoldier->CalcActionPoints( ), &(pSoldier->inv[HANDPOS]), pSoldier );
InitAttackType(pBestShot); // set all structure fields to defaults
+10 -10
View File
@@ -2527,7 +2527,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
INT8 bRecoilY = 0;
pSoldier->bDoAutofire++;
dTotalRecoil += AICalcRecoilForShot( pSoldier, &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire, pSoldier );
}
while( pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire
&& dTotalRecoil <= 10.0f );
@@ -2535,7 +2535,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
do
{
pSoldier->bDoAutofire++;
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire, pSoldier );
}
while( pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs &&
pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire &&
@@ -2545,7 +2545,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
pSoldier->bDoAutofire--;
// Make sure we decided to fire at least one shot!
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire, pSoldier );
// minimum 5 bullets //WarmSteel: 5 bullets sounds reasonable, no?
// Hmmm, automatic suppression? Howcome we don't get this?
@@ -4859,7 +4859,7 @@ INT16 ubMinAPCost;
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"DecideActionBlack: ENOUGH APs TO BURST, RANDOM CHANCE OF DOING SO");
ubBurstAPs = CalcAPsToBurst( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]) );
ubBurstAPs = CalcAPsToBurst( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier );
// HEADROCK HAM 3.6: Use Actual Aiming Time.
if (pSoldier->bActionPoints >= BestAttack.ubAPCost + sActualAimTime + ubBurstAPs )
@@ -4937,7 +4937,7 @@ INT16 ubMinAPCost;
INT8 bRecoilY = 0;
pSoldier->bDoAutofire++;
dTotalRecoil += AICalcRecoilForShot( pSoldier, &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire, pSoldier );
}
while( pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs + sActualAimTime && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire
&& dTotalRecoil <= 10.0f );
@@ -4945,7 +4945,7 @@ INT16 ubMinAPCost;
do
{
pSoldier->bDoAutofire++;
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire );
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire, pSoldier );
}
while( pSoldier->bActionPoints >= BestAttack.ubAPCost + ubBurstAPs &&
pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire &&
@@ -4955,7 +4955,7 @@ INT16 ubMinAPCost;
pSoldier->bDoAutofire--;
if (pSoldier->bDoAutofire > 0)
{
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire );
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire, pSoldier );
if (pSoldier->bActionPoints >= BestAttack.ubAPCost + ubBurstAPs )
{
@@ -5009,7 +5009,7 @@ INT16 ubMinAPCost;
{
pSoldier->aiData.bAimTime = BestAttack.ubAimTime ;
pSoldier->bDoBurst = 1;
BestAttack.ubAPCost = BestAttack.ubAPCost + CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire ) + sActualAimTime;
BestAttack.ubAPCost = BestAttack.ubAPCost + CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier->bDoAutofire, pSoldier ) + sActualAimTime;
}
else
{
@@ -5184,7 +5184,7 @@ INT16 ubMinAPCost;
{
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "DecideActionBlack: Doing burst calc");
ubBurstAPs = CalcAPsToBurst( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]) );
ubBurstAPs = CalcAPsToBurst( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestAttack.bWeaponIn]), pSoldier );
if ( (pSoldier->bActionPoints - BestAttack.ubAPCost) >= ubBurstAPs )
{
@@ -5215,7 +5215,7 @@ INT16 ubMinAPCost;
{
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "DecideActionBlack: Doing GL burst");
BestAttack.ubAimTime = BURSTING;
BestAttack.ubAPCost = BestAttack.ubAPCost + CalcAPsToBurst( pSoldier->CalcActionPoints(), &(pSoldier->inv[HANDPOS]) );
BestAttack.ubAPCost = BestAttack.ubAPCost + CalcAPsToBurst( pSoldier->CalcActionPoints(), &(pSoldier->inv[HANDPOS]), pSoldier );
// check for spread burst possibilities
if (pSoldier->aiData.bAttitude != ATTACKSLAYONLY)
{
+105 -1
View File
@@ -3609,6 +3609,87 @@ void AddBombToQueue( UINT32 uiWorldBombIndex, UINT32 uiTimeStamp, BOOL fFromRemo
gfExplosionQueueActive = TRUE;
}
// Flugente: activate everything connected to a tripwire in the surrounding if sGridNo on level bLevel
BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 bLevel )
{
UINT32 uiTimeStamp= GetJA2Clock();
BOOLEAN fFoundMine = FALSE;
// for every orientation
for (UINT8 ort = NORTH; ort < NUM_WORLD_DIRECTIONS; ++ort)
{
// get adjacent grid
UINT32 adjgrid = NewGridNo( sGridNo, DirectionInc( ort ) );
// if there is a bomb at that grid and level, and it isn't disabled
for (UINT32 uiWorldBombIndex = 0; uiWorldBombIndex < guiNumWorldBombs; uiWorldBombIndex++)
{
if (gWorldBombs[uiWorldBombIndex].fExists && gWorldItems[ gWorldBombs[uiWorldBombIndex].iItemIndex ].sGridNo == adjgrid && gWorldItems[ gWorldBombs[uiWorldBombIndex].iItemIndex ].ubLevel == bLevel )
{
OBJECTTYPE* pObj = &( gWorldItems[ gWorldBombs[uiWorldBombIndex].iItemIndex ].object );
if (!((*pObj).fFlags & OBJECT_DISABLED_BOMB))
{
// if item can be activated by tripwire, detonate it
if ( Item[pObj->usItem].tripwireactivation == 1 )
{
// tripwire just gets activated
if ( Item[pObj->usItem].tripwire == 1 )
{
OBJECTTYPE newtripwireObject;
CreateItem( pObj->usItem, (*pObj)[0]->data.objectStatus, &newtripwireObject );
// this is important: delete the tripwire, otherwise we get into an infinite loop if there are two piecs of tripwire....
RemoveItemFromPool( adjgrid, gWorldBombs[ uiWorldBombIndex ].iItemIndex, bLevel );
// make sure no one thinks there is a bomb here any more!
if ( gpWorldLevelData[adjgrid].uiFlags & MAPELEMENT_PLAYER_MINE_PRESENT )
{
RemoveBlueFlag( adjgrid, bLevel );
}
gpWorldLevelData[adjgrid].uiFlags &= ~(MAPELEMENT_ENEMY_MINE_PRESENT);
// no add a tripwire item to the floor, simulating that activating tripwire deactivates it
AddItemToPool( adjgrid, &newtripwireObject, 1, bLevel, 0, -1 );
// activate surrounding tripwires, unless tripwire is too much damaged and we are unlucky..
if ( newtripwireObject[0]->data.objectStatus > (INT16)Random(50) )
fFoundMine = ActivateSurroundingTripwire(ubID, adjgrid, bLevel);
}
// bombs go off
else
{
gubPersonToSetOffExplosions = ubID;
// SANDRO - merc records
// only if we blew up somebody not in our team(no achievement for blowing our guys :)), only if owner exists and have profile
if ( (MercPtrs[ubID]->bTeam != gbPlayerNum) && ((*pObj)[0]->data.misc.ubBombOwner > 1) )
{
if ( MercPtrs[ ((*pObj)[0]->data.misc.ubBombOwner - 2) ]->ubProfile != NO_PROFILE && MercPtrs[ ((*pObj)[0]->data.misc.ubBombOwner - 2) ]->bTeam == gbPlayerNum )
gMercProfiles[ MercPtrs[ ((*pObj)[0]->data.misc.ubBombOwner - 2) ]->ubProfile ].records.usExpDetonated++;
}
// put this bomb on the queue
AddBombToQueue( uiWorldBombIndex, uiTimeStamp );
if (pObj->usItem != ACTION_ITEM || (*pObj)[0]->data.misc.bActionValue == ACTION_ITEM_BLOW_UP)
{
uiTimeStamp += BOMB_QUEUE_DELAY;
}
if ( (*pObj)[0]->data.misc.usBombItem != NOTHING && Item[ (*pObj)[0]->data.misc.usBombItem ].usItemClass & IC_EXPLOSV )
{
fFoundMine = TRUE;
}
}
}
}
}
}
}
return( fFoundMine );
}
void HandleExplosionQueue( void )
{
UINT32 uiIndex;
@@ -3914,11 +3995,34 @@ BOOLEAN SetOffBombsInGridNo( UINT8 ubID, INT32 sGridNo, BOOLEAN fAllBombs, INT8
}*/
if (pObj->usItem == SWITCH)
{
{
// send out a signal to detonate other bombs, rather than this which
// isn't a bomb but a trigger
SetOffBombsByFrequency( ubID, (*pObj)[0]->data.misc.bFrequency );
}
// Flugente: a tripwire activates all other tripwires in connection, and detonates all bombs in connection that are tripwire-activated
else if ( Item[pObj->usItem].tripwire == 1 )
{
OBJECTTYPE newtripwireObject;
CreateItem( pObj->usItem, (*pObj)[0]->data.objectStatus, &newtripwireObject );
// this is important: delete the tripwire, otherwise we get into an infinite loop if there are two piecs of tripwire....
RemoveItemFromPool( sGridNo, gWorldBombs[ uiWorldBombIndex ].iItemIndex, bLevel );
// make sure no one thinks there is a bomb here any more!
if ( gpWorldLevelData[sGridNo].uiFlags & MAPELEMENT_PLAYER_MINE_PRESENT )
{
RemoveBlueFlag( sGridNo, bLevel );
}
gpWorldLevelData[sGridNo].uiFlags &= ~(MAPELEMENT_ENEMY_MINE_PRESENT);
// no add a tripwire item to the floor, simulating that activating tripwire deactivates it
AddItemToPool( sGridNo, &newtripwireObject, 1, bLevel, 0, -1 );
// activate surrounding tripwires and tripwire-activated mines, unless tripwire is too much damaged and we are unlucky..
if ( newtripwireObject[0]->data.objectStatus > (INT16)Random(50) )
fFoundMine = ActivateSurroundingTripwire(ubID, sGridNo, bLevel);
}
else
{
gubPersonToSetOffExplosions = ubID;
+3
View File
@@ -133,6 +133,9 @@ BOOLEAN DishOutGasDamage( SOLDIERTYPE * pSoldier, EXPLOSIVETYPE * pExplosive, IN
void SpreadEffect( INT32 sGridNo, UINT8 ubRadius, UINT16 usItem, UINT8 ubOwner, BOOLEAN fSubsequent, INT8 bLevel, INT32 iSmokeEffectNum , BOOL fFromRemoteClient = FALSE , BOOL fNewSmokeEffect = FALSE );
void AddBombToQueue( UINT32 uiWorldBombIndex, UINT32 uiTimeStamp, BOOL fFromRemoteClient = FALSE );
// Flugente: activate everything connected to a tripwire in the surrounding if sGridNo on level bLevel
BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 bLevel );
extern void ToggleActionItemsByFrequency( INT8 bFrequency );
extern void PerformItemAction( INT32 sGridNo, OBJECTTYPE * pObj );
extern BOOLEAN gfExplosionQueueMayHaveChangedSight;
+24 -2
View File
@@ -256,6 +256,9 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at
strcmp(name, "overheatCooldownModificator") == 0 ||
strcmp(name, "overheatJamThresholdModificator") == 0 ||
strcmp(name, "overheatDamageThresholdModificator") == 0 ||
strcmp(name, "attachmentclass") == 0 ||
strcmp(name, "tripwireactivation") == 0 ||
strcmp(name, "tripwire") == 0 ||
strcmp(name, "fFlags") == 0 ))
{
@@ -1077,7 +1080,7 @@ itemEndElementHandle(void *userData, const XML_Char *name)
{
pData->curElement = ELEMENT;
pData->curItem.mine = (BOOLEAN) atol(pData->szCharData);
}
}
else if(strcmp(name, "GasCan") == 0)
{
pData->curElement = ELEMENT;
@@ -1277,6 +1280,21 @@ itemEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT;
pData->curItem.overheatDamageThresholdModificator = (FLOAT) atof(pData->szCharData);
}
else if(strcmp(name, "attachmentclass") == 0)
{
pData->curElement = ELEMENT;
pData->curItem.attachmentclass = (UINT32) atol(pData->szCharData);
}
else if(strcmp(name, "tripwireactivation") == 0)
{
pData->curElement = ELEMENT;
pData->curItem.tripwireactivation = (BOOLEAN) atol(pData->szCharData);
}
else if(strcmp(name, "tripwire") == 0)
{
pData->curElement = ELEMENT;
pData->curItem.tripwire = (BOOLEAN) atol(pData->szCharData);
}
pData->maxReadDepth--;
}
@@ -1754,7 +1772,7 @@ BOOLEAN WriteItemStats()
FilePrintf(hFile,"\t\t<GrenadeLauncher>%d</GrenadeLauncher>\r\n", Item[cnt].grenadelauncher );
FilePrintf(hFile,"\t\t<Duckbill>%d</Duckbill>\r\n", Item[cnt].duckbill );
FilePrintf(hFile,"\t\t<GLGrenade>%d</GLGrenade>\r\n", Item[cnt].glgrenade );
FilePrintf(hFile,"\t\t<Mine>%d</Mine>\r\n", Item[cnt].mine );
FilePrintf(hFile,"\t\t<Mine>%d</Mine>\r\n", Item[cnt].mine );
FilePrintf(hFile,"\t\t<Mortar>%d</Mortar>\r\n", Item[cnt].mortar );
FilePrintf(hFile,"\t\t<RocketLauncher>%d</RocketLauncher>\r\n", Item[cnt].rocketlauncher );
FilePrintf(hFile,"\t\t<SingleShotRocketLauncher>%d</SingleShotRocketLauncher>\r\n", Item[cnt].singleshotrocketlauncher );
@@ -1882,6 +1900,10 @@ BOOLEAN WriteItemStats()
FilePrintf(hFile,"\t\t<overheatJamThresholdModificator>%4.2f</overheatJamThresholdModificator>\r\n", Item[cnt].overheatJamThresholdModificator );
FilePrintf(hFile,"\t\t<overheatDamageThresholdModificator>%4.2f</overheatDamageThresholdModificator>\r\n", Item[cnt].overheatDamageThresholdModificator );
FilePrintf(hFile,"\t\t<attachmentclass>%4.2f</attachmentclass>\r\n", Item[cnt].attachmentclass );
FilePrintf(hFile,"\t\t<tripwireactivation>%d</tripwireactivation>\r\n", Item[cnt].tripwireactivation );
FilePrintf(hFile,"\t\t<tripwire>%d</tripwire>\r\n", Item[cnt].tripwire );
FilePrintf(hFile,"\t</ITEM>\r\n");
}