- 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.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.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) // 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 ); gGameExternalOptions.iInitialMercArrivalLocation = iniReader.ReadInteger("Tactical Gameplay Settings","INITIAL_MERC_ARRIVAL_LOCATION", 4870 );
+5
View File
@@ -1076,10 +1076,15 @@ typedef struct
FLOAT iCooldownModificatorLonelyBarrel; // Cooldown modificator for barrels alone in the landscape ;-) FLOAT iCooldownModificatorLonelyBarrel; // Cooldown modificator for barrels alone in the landscape ;-)
BOOLEAN fSetZeroUponNewSector; // Should loading a new sector set the temperatures of all items in the old sector to zero? (this doesn't apply to inventories) BOOLEAN 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 fWeaponResting; // Should it be possible to rest your weapon on structures in crouched position?
BOOLEAN fDisplayWeaponRestingIndicator; // Should a little indicator show if the weapon is currently rested on something? BOOLEAN fDisplayWeaponRestingIndicator; // Should a little indicator show if the weapon is currently rested on something?
UINT8 ubProneModifierPercentage; // for boni, use ubProneModifierPercentage*boni[PRONE] + (100 - ubProneModifierPercentage)*boni[CROUCHED] UINT8 ubProneModifierPercentage; // for boni, use ubProneModifierPercentage*boni[PRONE] + (100 - ubProneModifierPercentage)*boni[CROUCHED]
// Flugente: Scope Modes
BOOLEAN fScopeModes; // allow the player to toggle between existing scopes/sights
BOOLEAN fDisplayScopeModes; // allow display of scope modes
BOOLEAN gBriefingRoom; BOOLEAN gBriefingRoom;
BOOLEAN gEncyclopedia; BOOLEAN gEncyclopedia;
+3 -3
View File
@@ -2490,7 +2490,7 @@ void CreateMouseRegionForBigImage( UINT16 usPosY, UINT8 ubCount, INT16 *pItemNum
UINT16 usAttachment; UINT16 usAttachment;
CreateItem(pItemNumbers[ i ], 100, &pObject); 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 ) if ( Weapon[ pItemNumbers[ i ] ].NoSemiAuto )
swprintf( apStr, L"-" ); swprintf( apStr, L"-" );
@@ -2499,7 +2499,7 @@ void CreateMouseRegionForBigImage( UINT16 usPosY, UINT8 ubCount, INT16 *pItemNum
if (GetShotsPerBurst(&pObject) > 0) 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 ); wcscat( apStr, apStr2 );
} }
else else
@@ -2507,7 +2507,7 @@ void CreateMouseRegionForBigImage( UINT16 usPosY, UINT8 ubCount, INT16 *pItemNum
if (GetAutofireShotsPerFiveAPs(&pObject) > 0) 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 ); wcscat( apStr, apStr2 );
} }
else 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->snowCamo, sizeof(snowCamo), sizeof(INT8), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->wornSnowCamo, sizeof(wornSnowCamo), 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->sFacilityTypeOperated, sizeof(sFacilityTypeOperated), sizeof(INT16), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->bScopeMode, sizeof(bScopeMode), sizeof(INT8), numBytesRead);
#ifdef JA2UB #ifdef JA2UB
numBytesRead = ReadFieldByField(hFile, &this->fIgnoreGetupFromCollapseCheck, sizeof(fIgnoreGetupFromCollapseCheck), sizeof(BOOLEAN), numBytesRead); numBytesRead = ReadFieldByField(hFile, &this->fIgnoreGetupFromCollapseCheck, sizeof(fIgnoreGetupFromCollapseCheck), sizeof(BOOLEAN), numBytesRead);
numBytesRead = ReadFieldByField(hFile, &this->GetupFromJA25StartCounter, sizeof(GetupFromJA25StartCounter), sizeof(TIMECOUNTER), 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 ) if ( iResult >= 0 )
{ {
// EXPLOSIVES GAIN (25): Place a bomb, or buried and armed a mine // Less explosives gain for placing tripwire
StatChange( pSoldier, EXPLODEAMT, 25, FALSE ); 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 // SANDRO - STOMP traits - Demolitions bonus to trap level
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, DEMOLITIONS_NT )) if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, DEMOLITIONS_NT ))
@@ -4380,8 +4384,12 @@ void BombMessageBoxCallBack( UINT8 ubExitValue )
if ( iResult >= 0 ) if ( iResult >= 0 )
{ {
// EXPLOSIVES GAIN (25): Place a bomb, or buried and armed a mine // Less explosives gain for placing tripwire
StatChange( gpTempSoldier, EXPLODEAMT, 25, FALSE ); 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 else
{ {
+12 -12
View File
@@ -1593,7 +1593,7 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
/////////////////// OCTH MINIMUM RANGE FOR AIMING BONUS /////////////////// OCTH MINIMUM RANGE FOR AIMING BONUS
if( UsingNewCTHSystem() == false && if( UsingNewCTHSystem() == false &&
( Item[gpItemDescObject->usItem].minrangeforaimbonus > 0 || GetMinRangeForAimBonus( gpItemDescObject ) > 0 ) ) ( Item[gpItemDescObject->usItem].minrangeforaimbonus > 0 || GetMinRangeForAimBonus( NULL, gpItemDescObject ) > 0 ) )
{ {
ubRegionOffset = 5; ubRegionOffset = 5;
MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + ubRegionOffset ] ); MSYS_EnableRegion( &gUDBFasthelpRegions[ iFirstDataRegion + ubRegionOffset ] );
@@ -2644,7 +2644,7 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
///////////////////// AIM BONUS MODIFIER ///////////////////// AIM BONUS MODIFIER
if(UsingNewCTHSystem() == false) if(UsingNewCTHSystem() == false)
{ {
if ( GetAimBonus( gpItemDescObject, 100, 1 ) != 0 ) if ( GetAimBonus( NULL, gpItemDescObject, 100, 1 ) != 0 )
{ {
if (cnt >= sFirstLine && cnt < sLastLine) if (cnt >= sFirstLine && cnt < sLastLine)
{ {
@@ -3097,7 +3097,7 @@ void InternalInitEDBTooltipRegion( OBJECTTYPE * gpItemDescObject, UINT32 guiCurr
} }
///////////////////// SINGLE-ATTACK AP MODIFIER ///////////////////// SINGLE-ATTACK AP MODIFIER
if (GetPercentAPReduction( gpItemDescObject ) != 0 ) if (GetPercentAPReduction( NULL, gpItemDescObject ) != 0 )
{ {
if (cnt >= sFirstLine && cnt < sLastLine) if (cnt >= sFirstLine && cnt < sLastLine)
{ {
@@ -3955,7 +3955,7 @@ void DrawWeaponStats( OBJECTTYPE * gpItemDescObject )
//////////////////// OCTH MINIMUM RANGE FOR AIMING BONUS //////////////////// OCTH MINIMUM RANGE FOR AIMING BONUS
if( UsingNewCTHSystem() == false && if( UsingNewCTHSystem() == false &&
( Item[gpItemDescObject->usItem].minrangeforaimbonus > 0 || GetMinRangeForAimBonus( gpItemDescObject ) > 0 ) ) ( Item[gpItemDescObject->usItem].minrangeforaimbonus > 0 || GetMinRangeForAimBonus( NULL, gpItemDescObject ) > 0 ) )
{ {
ubNumLine = 5; ubNumLine = 5;
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoWeaponIcon, 27, gItemDescGenRegions[ubNumLine][0].sLeft+sOffsetX, gItemDescGenRegions[ubNumLine][0].sTop+sOffsetY, VO_BLT_SRCTRANSPARENCY, NULL ); 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 ///////////////////// SINGLE-ATTACK AP MODIFIER
if (GetPercentAPReduction( gpItemDescObject ) != 0 ) if (GetPercentAPReduction( NULL, gpItemDescObject ) != 0 )
{ {
if (cnt >= sFirstLine && cnt < sLastLine) if (cnt >= sFirstLine && cnt < sLastLine)
{ {
@@ -5372,7 +5372,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
return; return;
// ShotsPer4Turns -> ubAttackAPs, used later for all shot AP values // 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 ); INT16 ubBasicAttackAPs = BaseAPsToShootOrStabNoModifier( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], gpItemDescObject );
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@@ -5905,7 +5905,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
/////////////////// OCTH MINIMUM RANGE FOR AIMING BONUS /////////////////// OCTH MINIMUM RANGE FOR AIMING BONUS
if( UsingNewCTHSystem() == false && 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 // Set line to draw into
ubNumLine = 5; ubNumLine = 5;
@@ -5917,7 +5917,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
INT16 iMinRangeForAimBonusValue = Item[gpItemDescObject->usItem].minrangeforaimbonus / 10; INT16 iMinRangeForAimBonusValue = Item[gpItemDescObject->usItem].minrangeforaimbonus / 10;
// Get final Minimum Range For Aim Bonus value // 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 // Get Minimum Range For Aim Bonus modifier
INT16 iMinRangeForAimBonusModifier = iFinalMinRangeForAimBonusValue - iMinRangeForAimBonusValue; INT16 iMinRangeForAimBonusModifier = iFinalMinRangeForAimBonusValue - iMinRangeForAimBonusValue;
@@ -6571,7 +6571,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
sHeight = gItemDescGenRegions[ubNumLine][1].sBottom - sTop; sHeight = gItemDescGenRegions[ubNumLine][1].sBottom - sTop;
// Get final Burst Cost // 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 // Get base Burst Cost
INT16 iBurstAPCost = ubBasicAttackAPs + CalcAPsToBurstNoModifier( APBPConstants[DEFAULT_APS], gpItemDescObject ); INT16 iBurstAPCost = ubBasicAttackAPs + CalcAPsToBurstNoModifier( APBPConstants[DEFAULT_APS], gpItemDescObject );
@@ -6637,7 +6637,7 @@ void DrawWeaponValues( OBJECTTYPE * gpItemDescObject )
sHeight = gItemDescGenRegions[ubNumLine][1].sBottom - sTop; sHeight = gItemDescGenRegions[ubNumLine][1].sBottom - sTop;
// Get final Autofire Cost // 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 // Get base Autofire Cost
INT16 iAutoAPCost = ubBasicAttackAPs + CalcAPsToAutofireNoModifier( APBPConstants[DEFAULT_APS], gpItemDescObject, 3 ); INT16 iAutoAPCost = ubBasicAttackAPs + CalcAPsToAutofireNoModifier( APBPConstants[DEFAULT_APS], gpItemDescObject, 3 );
@@ -8578,7 +8578,7 @@ void DrawAdvancedValues( OBJECTTYPE *gpItemDescObject )
///////////////////// AIM BONUS MODIFIER ///////////////////// AIM BONUS MODIFIER
if(UsingNewCTHSystem() == false) if(UsingNewCTHSystem() == false)
{ {
iModifier[0] = GetAimBonus( gpItemDescObject, 100, 1 ); iModifier[0] = GetAimBonus( NULL, gpItemDescObject, 100, 1 );
iModifier[1] = 0; iModifier[1] = 0;
iModifier[2] = 0; iModifier[2] = 0;
if (iModifier[0] != 0 || 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 ///////////////////// SINGLE-ATTACK AP MODIFIER
iModifier[0] = GetPercentAPReduction( gpItemDescObject ); iModifier[0] = GetPercentAPReduction( NULL, gpItemDescObject );
iModifier[1] = iModifier[0]; iModifier[1] = iModifier[0];
iModifier[2] = iModifier[0]; iModifier[2] = iModifier[0];
if (iModifier[0] != 0 ) if (iModifier[0] != 0 )
+115 -18
View File
@@ -262,6 +262,10 @@ UINT32 guiItemDescBoxBackground;
UINT32 guiItemInfoLBEBackground; UINT32 guiItemInfoLBEBackground;
UINT32 guiMapItemDescBox; UINT32 guiMapItemDescBox;
UINT32 guiAttachmentSlot; UINT32 guiAttachmentSlot;
// HEADROCK HAM 4: This replaces "Misc" icons.
extern UINT32 guiItemInfoAdvancedIcon; // added here by Flugente
UINT32 guiItemGraphic; UINT32 guiItemGraphic;
UINT32 guiMoneyGraphicsForDescBox; UINT32 guiMoneyGraphicsForDescBox;
UINT32 guiBullet; UINT32 guiBullet;
@@ -667,8 +671,17 @@ void GenerateProsString( STR16 zItemPros, OBJECTTYPE * pObject, UINT32 uiPixLimi
ubWeight = ubWeight + Item[ (*pObject)[0]->data.gun.usGunAmmoItem ].ubWeight; 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 //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]; zTemp = Message[STR_ACCURATE];
if ( ! AttemptToAddSubstring( zItemPros, zTemp, &uiStringLength, uiPixLimit ) ) 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]; zTemp = Message[STR_QUICK_FIRING];
if ( ! AttemptToAddSubstring( zItemPros, zTemp, &uiStringLength, uiPixLimit ) ) if ( ! AttemptToAddSubstring( zItemPros, zTemp, &uiStringLength, uiPixLimit ) )
@@ -803,8 +816,17 @@ void GenerateConsString( STR16 zItemCons, OBJECTTYPE * pObject, UINT32 uiPixLimi
zItemCons[0] = 0; 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 //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]; zTemp = Message[STR_INACCURATE];
if ( ! AttemptToAddSubstring( zItemCons, zTemp, &uiStringLength, uiPixLimit ) ) 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]; zTemp = Message[STR_SLOW_FIRING];
if ( ! AttemptToAddSubstring( zItemCons, zTemp, &uiStringLength, uiPixLimit ) ) 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 ){ 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, 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 ); SetRGBFontForeground( 95, 160, 154 );
sNewY = sY + sHeight - 24; sNewY = sY;
swprintf( pStr, L"M" ); swprintf( pStr, L"M" );
// Get length of string // Get length of string
uiStringLength=StringPixLength(pStr, ITEM_FONT ); uiStringLength=StringPixLength(pStr, ITEM_FONT );
sNewX = sX + 25; sNewX = sX + sWidth - uiStringLength - 13;
if ( uiBuffer == guiSAVEBUFFER ) if ( uiBuffer == guiSAVEBUFFER )
{ {
RestoreExternBackgroundRect( sNewX, sNewY, 15, 15 ); RestoreExternBackgroundRect( sNewX, sNewY, uiStringLength, 15 );
} }
mprintf( sNewX, sNewY, pStr ); mprintf( sNewX, sNewY, pStr );
gprintfinvalidate( 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)) if((UsingNewInventorySystem() == true))
{ {
// CHRISL: Display astrisk when LBENODE active // 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 ] ); 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 // WANNE: Fixed CTD when trowing an item with open description box
if (ubAttackAPs != -1 ) if (ubAttackAPs != -1 )
@@ -6686,14 +6763,14 @@ void RenderItemDescriptionBox( )
{ {
SetFontForeground( 5 ); 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); 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 ); mprintf( usX, usY, pStr );
} }
else if (GetAutofireShotsPerFiveAPs(gpItemDescObject) > 0) else if (GetAutofireShotsPerFiveAPs(gpItemDescObject) > 0)
{ {
SetFontForeground( 5 ); 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); 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 ); mprintf( usX, usY, pStr );
} }
@@ -11115,7 +11192,7 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
//Calculate AP's //Calculate AP's
CHAR16 apStr[20]; CHAR16 apStr[20];
CHAR16 apStr2[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 ) if ( Weapon[ usItem ].NoSemiAuto )
{ {
@@ -11128,7 +11205,7 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
if (GetShotsPerBurst(pObject) > 0) 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 ); wcscat( apStr, apStr2 );
} }
else else
@@ -11138,7 +11215,7 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
if (GetAutofireShotsPerFiveAPs(pObject) > 0) 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 ); wcscat( apStr, apStr2 );
} }
else else
@@ -11146,10 +11223,20 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
wcscat( apStr, L" / -" ); 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 //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", //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); INT8 accuracy = (UsingNewCTHSystem()==true?Weapon[ usItem ].nAccuracy:Weapon[ usItem ].bAccuracy);
accuracy *= accuracyheatmultiplicator;
#ifdef CHINESE #ifdef CHINESE
swprintf( pStr, ChineseSpecString4, swprintf( pStr, ChineseSpecString4,
#else #else
@@ -11182,13 +11269,13 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
//Calculate AP's //Calculate AP's
CHAR16 apStr[20]; CHAR16 apStr[20];
CHAR16 apStr2[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 ); swprintf( apStr, L"%d", ubAttackAPs );
if (GetShotsPerBurst(pObject) > 0) 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 ); wcscat( apStr, apStr2 );
} }
else else
@@ -11198,7 +11285,7 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
if (GetAutofireShotsPerFiveAPs(pObject) > 0) 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 ); wcscat( apStr, apStr2 );
} }
else else
@@ -11206,8 +11293,18 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
wcscat( apStr, L" / -" ); 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 //Info for weapons
INT8 accuracy = (UsingNewCTHSystem()==true?Weapon[ usItem ].nAccuracy:Weapon[ usItem ].bAccuracy); INT8 accuracy = (UsingNewCTHSystem()==true?Weapon[ usItem ].nAccuracy:Weapon[ usItem ].bAccuracy);
accuracy *= accuracyheatmultiplicator;
#ifdef CHINESE #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", 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 gWeaponStatsDesc[ 11 ], //Damage String
GetDamage(pObject), //Melee damage GetDamage(pObject), //Melee damage
gWeaponStatsDesc[ 6 ], //AP String 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 gWeaponStatsDesc[ 12 ], //Weight String
fWeight, //Weight fWeight, //Weight
GetWeightUnitString() //Weight units GetWeightUnitString() //Weight units
+17 -10
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_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 ) #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 // Chrisl: Define attachment classes
#define AC_DEFAULT1 0x00000001 //1 #define AC_BIPOD 0x00000001 //1
#define AC_BARREL 0x00000002 //2 #define AC_SUPPRESSOR 0x00000002 //2
#define AC_LASER 0x00000004 //4 #define AC_LASER 0x00000004 //4
#define AC_SIGHT 0x00000008 //8 #define AC_SIGHT 0x00000008 //8
#define AC_SCOPE 0x00000010 //16 #define AC_SCOPE 0x00000010 //16
#define AC_STOCK 0x00000020 //32 #define AC_STOCK 0x00000020 //32
#define AC_AMMO 0x00000040 //64 #define AC_MAGWELL 0x00000040 //64
#define AC_INTERNAL 0x00000080 //128 #define AC_INTERNAL 0x00000080 //128
#define AC_EXTERNAL 0x00000100 //256 #define AC_EXTERNAL 0x00000100 //256
#define AC_UNDERBARREL 0x00000200 //512 #define AC_UNDERBARREL 0x00000200 //512
#define AC_GRENADE 0x00000400 //1024 #define AC_GRENADE 0x00000400 //1024
#define AC_ROCKET 0x00000800 //2048 #define AC_ROCKET 0x00000800 //2048
#define AC_MISC1 0x00001000 //4096 #define AC_FOREGRIP 0x00001000 //4096
#define AC_MISC2 0x00002000 //8192 #define AC_HELMET 0x00002000 //8192
#define AC_MISC3 0x00004000 //16384 #define AC_VEST 0x00004000 //16384
#define AC_MISC4 0x00008000 //32768 #define AC_PANTS 0x00008000 //32768
#define AC_MISC5 0x00010000 //65536 #define AC_DETONATOR 0x00010000 //65536
#define AC_MISC6 0x00020000 //131072 #define AC_BATTERY 0x00020000 //131072
#define AC_MISC7 0x00040000 //262144 #define AC_EXTENDER 0x00040000 //262144
#define AC_MISC8 0x00080000 //524288 #define AC_MISC8 0x00080000 //524288
#define AC_MISC9 0x00100000 //1048576 #define AC_MISC9 0x00100000 //1048576
#define AC_MISC10 0x00200000 //2097152 #define AC_MISC10 0x00200000 //2097152
@@ -654,6 +655,7 @@ extern OBJECTTYPE gTempObject;
#define AC_MISC19 0x40000000 //1073741824 #define AC_MISC19 0x40000000 //1073741824
#define AC_MISC20 0x80000000 //2147483648 #define AC_MISC20 0x80000000 //2147483648
// replaces candamage // replaces candamage
//#define ITEM_DAMAGEABLE 0x0001 //#define ITEM_DAMAGEABLE 0x0001
//// replaces canrepair //// replaces canrepair
@@ -887,6 +889,11 @@ typedef struct
FLOAT overheatJamThresholdModificator; // percentage modifier of a gun's jam threshold (read from attachments) 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; } INVTYPE;
// CHRISL: Added new structures to handle LBE gear and the two new XML files that will be needed to deal // CHRISL: Added new structures to handle LBE gear and the two new XML files that will be needed to deal
+449 -84
View File
@@ -2220,7 +2220,7 @@ BOOLEAN ValidItemAttachmentSlot( OBJECTTYPE * pObj, UINT16 usAttachment, BOOLEAN
//Search for incompatible attachments //Search for incompatible attachments
for(int i = 0;i<sizeof(IncompatibleAttachments);i++) 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 {//Search for identical attachments unless we're dealing with rifle grenades
fSameItem = TRUE; fSameItem = TRUE;
break; break;
@@ -5860,6 +5860,7 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
pSoldier->bDoBurst = TRUE; pSoldier->bDoBurst = TRUE;
pSoldier->bDoAutofire = TRUE; pSoldier->bDoAutofire = TRUE;
} }
pSoldier->bScopeMode = USE_BEST_SCOPE;
} }
// Lesh: end // Lesh: end
@@ -7528,6 +7529,7 @@ BOOLEAN OBJECTTYPE::RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNew
pSoldier->bDoBurst = TRUE; pSoldier->bDoBurst = TRUE;
pSoldier->bDoAutofire = 1; pSoldier->bDoAutofire = 1;
} }
pSoldier->bScopeMode = USE_BEST_SCOPE;
} }
} }
@@ -9036,16 +9038,30 @@ INT16 GetItemAimBonus( const INVTYPE* pItem, INT32 iRange, INT16 ubAimTime )
return(bonus); return(bonus);
} }
INT16 GetAimBonus( OBJECTTYPE * pObj, INT32 iRange, INT16 ubAimTime ) INT16 GetAimBonus( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, INT32 iRange, INT16 ubAimTime )
{ {
INT16 bonus = 0; INT16 bonus = 0;
if (pObj->exists() == true) { if (pObj->exists() == true)
bonus = BonusReduceMore( GetItemAimBonus( &Item[pObj->usItem], iRange, ubAimTime ), (*pObj)[0]->data.objectStatus ); {
// 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 ); bonus += GetItemAimBonus( &Item[(*pObj)[0]->data.gun.usGunAmmoItem], iRange, ubAimTime );
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { attachmentList::iterator iterend = (*pObj)[0]->attachments.end();
if(iter->exists()){ 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 ); 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; INT16 bonus = 0;
if (pObj->exists() == true) { if (pObj->exists() == true)
bonus = BonusReduceMore( Item[pObj->usItem].percentapreduction, (*pObj)[0]->data.objectStatus ); {
bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].percentapreduction; 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) { for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
if(iter->exists()){ if( iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) )
bonus += BonusReduceMore( Item[iter->usItem].percentapreduction, {
(*iter)[0]->data.objectStatus ); 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; 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 ); bonus += BonusReduceMore( pItem->visionrangebonus, (*pObj)[0]->data.objectStatus );
} }
@@ -9991,10 +10033,38 @@ INT16 GetVisionRangeBonus( SOLDIERTYPE * pSoldier )
// SANDRO - added scouting check // SANDRO - added scouting check
INT16 sScopebonus = 0; INT16 sScopebonus = 0;
pObj = &( pSoldier->inv[HANDPOS]); pObj = &( pSoldier->inv[HANDPOS]);
if (pObj->exists() == true) { if (pObj->exists() == true)
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { {
if(iter->exists()){ if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum )
sScopebonus += BonusReduceMore( Item[iter->usItem].visionrangebonus, (*iter)[0]->data.objectStatus ); {
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; continue;
} }
if (!IsWeapon(usItem) || (IsWeapon(usItem) && usingGunScope == true ) ) // Flugente: weapons are checked later on...
if (!IsWeapon(usItem) )//|| (IsWeapon(usItem) && usingGunScope == true ) )
{ {
bonus += BonusReduceMore( bonus += BonusReduceMore(
NightBonusScale( pItem->nightvisionrangebonus, bLightLevel ), NightBonusScale( pItem->nightvisionrangebonus, bLightLevel ),
@@ -10067,12 +10138,44 @@ INT16 GetNightVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel )
// SANDRO - added scouting check // SANDRO - added scouting check
INT16 sScopebonus = 0; INT16 sScopebonus = 0;
pObj = &( pSoldier->inv[HANDPOS]); pObj = &( pSoldier->inv[HANDPOS]);
if (pObj->exists() == true) { if (pObj->exists() == true)
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { {
if(iter->exists()){ 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( sScopebonus += BonusReduceMore(
NightBonusScale( Item[iter->usItem].nightvisionrangebonus, bLightLevel ), NightBonusScale( Item[ObjList[pSoldier->bScopeMode]->usItem].cavevisionrangebonus, bLightLevel ),
(*iter)[0]->data.objectStatus ); (*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; continue;
} }
if (!IsWeapon(usItem) || (IsWeapon(usItem) && usingGunScope == true ) ) // Flugente: weapons are checked later on...
if (!IsWeapon(usItem) )//|| (IsWeapon(usItem) && usingGunScope == true ) )
{ {
bonus += BonusReduceMore( bonus += BonusReduceMore(
NightBonusScale( pItem->cavevisionrangebonus, bLightLevel ), NightBonusScale( pItem->cavevisionrangebonus, bLightLevel ),
@@ -10132,12 +10236,44 @@ INT16 GetCaveVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel )
// SANDRO - added scouting check // SANDRO - added scouting check
INT16 sScopebonus = 0; INT16 sScopebonus = 0;
pObj = &( pSoldier->inv[HANDPOS]); pObj = &( pSoldier->inv[HANDPOS]);
if (pObj->exists() == true) { if (pObj->exists() == true)
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { {
if(iter->exists()){ 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( sScopebonus += BonusReduceMore(
NightBonusScale( Item[iter->usItem].cavevisionrangebonus, bLightLevel ), NightBonusScale( Item[ObjList[pSoldier->bScopeMode]->usItem].cavevisionrangebonus, bLightLevel ),
(*iter)[0]->data.objectStatus ); (*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 );
}
} }
} }
} }
@@ -10184,7 +10320,8 @@ INT16 GetDayVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel )
continue; 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 bonus += BonusReduceMore( idiv( pItem->dayvisionrangebonus
* (NORMAL_LIGHTLEVEL_NIGHT - bLightLevel), NORMAL_LIGHTLEVEL_NIGHT ), * (NORMAL_LIGHTLEVEL_NIGHT - bLightLevel), NORMAL_LIGHTLEVEL_NIGHT ),
@@ -10202,12 +10339,45 @@ INT16 GetDayVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel )
// SANDRO - added scouting check // SANDRO - added scouting check
INT16 sScopebonus = 0; INT16 sScopebonus = 0;
pObj = &( pSoldier->inv[HANDPOS]); pObj = &( pSoldier->inv[HANDPOS]);
if (pObj->exists() == true) {
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { if (pObj->exists() == true)
if(iter->exists()){ {
sScopebonus += BonusReduceMore( idiv( Item[iter->usItem].dayvisionrangebonus 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) ), * (NORMAL_LIGHTLEVEL_NIGHT - __max(bLightLevel,NORMAL_LIGHTLEVEL_DAY)), (NORMAL_LIGHTLEVEL_NIGHT-NORMAL_LIGHTLEVEL_DAY) ),
(*iter)[0]->data.objectStatus ); (*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; 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 bonus += BonusReduceMore( idiv( pItem->brightlightvisionrangebonus
* (NORMAL_LIGHTLEVEL_DAY - bLightLevel), NORMAL_LIGHTLEVEL_DAY ), * (NORMAL_LIGHTLEVEL_DAY - bLightLevel), NORMAL_LIGHTLEVEL_DAY ),
@@ -10269,12 +10440,44 @@ INT16 GetBrightLightVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel
// SANDRO - added scouting check // SANDRO - added scouting check
INT16 sScopebonus = 0; INT16 sScopebonus = 0;
pObj = &( pSoldier->inv[HANDPOS]); pObj = &( pSoldier->inv[HANDPOS]);
if (pObj->exists() == true) { if (pObj->exists() == true)
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { {
if(iter->exists()){ if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum )
sScopebonus += BonusReduceMore( idiv( Item[iter->usItem].brightlightvisionrangebonus {
* (NORMAL_LIGHTLEVEL_DAY - bLightLevel), NORMAL_LIGHTLEVEL_DAY ), for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
(*iter)[0]->data.objectStatus ); {
// 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 ) if ( usingGunScope == true )
{ {
OBJECTTYPE *pObj = &(pSoldier->inv[HANDPOS]); OBJECTTYPE *pObj = &(pSoldier->inv[HANDPOS]);
if (pObj->exists() == true) { if (pObj->exists() == true)
{
usItem = pObj->usItem; usItem = pObj->usItem;
pItem = &(Item[usItem]); pItem = &(Item[usItem]);
if ( IsWeapon(usItem) ) //if not a weapon, then it was added already above if ( IsWeapon(usItem) ) //if not a weapon, then it was added already above
bonus += Item[usItem].percenttunnelvision; bonus += Item[usItem].percenttunnelvision;
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { if ( gGameExternalOptions.fScopeModes && pSoldier && pSoldier->bTeam == gbPlayerNum )
if(iter->exists()) {
bonus += Item[iter->usItem].percenttunnelvision; 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,25 +11617,53 @@ FLOAT GetHighestScopeMagnificationFactor( OBJECTTYPE * pObj )
return( BestFactor ); return( BestFactor );
} }
INT16 GetMinRangeForAimBonus( OBJECTTYPE * pObj ) INT16 GetMinRangeForAimBonus( SOLDIERTYPE* pSoldier, OBJECTTYPE * pObj )
{ {
INT16 bonus = 0; INT16 bonus = 0;
if ( pObj->exists() == true ) { if ( pObj->exists() == true )
bonus = Item[pObj->usItem].minrangeforaimbonus; {
//bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].minrangeforaimbonus; // 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);
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { bonus = Item[ObjList[pSoldier->bScopeMode]->usItem].minrangeforaimbonus;
bonus += Item[iter->usItem].minrangeforaimbonus; }
else
bonus = Item[pObj->usItem].minrangeforaimbonus;
//bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].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 ); 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; 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 CurrentFactor = 0.0;
FLOAT TargetMagFactor = __max(1.0f,(FLOAT)uiRange / (FLOAT)gGameCTHConstants.NORMAL_SHOOTING_DISTANCE); FLOAT TargetMagFactor = __max(1.0f,(FLOAT)uiRange / (FLOAT)gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
FLOAT rangeModifier = gGameCTHConstants.SCOPE_RANGE_MULTIPLIER; FLOAT rangeModifier = gGameCTHConstants.SCOPE_RANGE_MULTIPLIER;
@@ -11414,9 +11674,10 @@ FLOAT GetScopeMagnificationFactor( OBJECTTYPE * pObj, FLOAT uiRange )
{ {
BestFactor = __max(1.0f, Item[pObj->usItem].scopemagfactor); 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) if(BestFactor == 1.0f)
BestFactor = __max(BestFactor, Item[iter->usItem].scopemagfactor); BestFactor = __max(BestFactor, Item[iter->usItem].scopemagfactor);
@@ -11431,6 +11692,17 @@ FLOAT GetScopeMagnificationFactor( OBJECTTYPE * pObj, FLOAT uiRange )
FLOAT GetBestScopeMagnificationFactor( SOLDIERTYPE *pSoldier, 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 BestFactor = 1.0;
FLOAT TargetMagFactor = __max(1.0f,uiRange / (FLOAT)gGameCTHConstants.NORMAL_SHOOTING_DISTANCE); FLOAT TargetMagFactor = __max(1.0f,uiRange / (FLOAT)gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
FLOAT CurrentFactor = 0.0; FLOAT CurrentFactor = 0.0;
@@ -11548,7 +11820,7 @@ FLOAT GetScopeRangeMultiplier( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, FLOAT d2
FLOAT iScopeFactor = 0; FLOAT iScopeFactor = 0;
FLOAT rangeModifier = gGameCTHConstants.SCOPE_RANGE_MULTIPLIER; FLOAT rangeModifier = gGameCTHConstants.SCOPE_RANGE_MULTIPLIER;
iScopeFactor = GetScopeMagnificationFactor( pObj, d2DDistance ); iScopeFactor = GetScopeMagnificationFactor( pSoldier, pObj, d2DDistance );
if( gGameOptions.fNewTraitSystem ) if( gGameOptions.fNewTraitSystem )
{ {
if(iScopeFactor > 5.0f) if(iScopeFactor > 5.0f)
@@ -11786,35 +12058,50 @@ UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier, INT32 sGridNo)
// don't break compatibility, let the users choose // don't break compatibility, let the users choose
if (gGameExternalOptions.iAimLevelsCompatibilityOption != 0) if (gGameExternalOptions.iAimLevelsCompatibilityOption != 0)
{
sScopeBonus = OldWayOfCalculatingScopeBonus(pSoldier); 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 else
sScopeBonus = gGameExternalOptions.fAimLevelsDependOnDistance ? {
//WarmSteel - Using scope aimbonus instead, as it is used elsewhere like this too. sScopeBonus = GetMinRangeForAimBonus( pSoldier, &pSoldier->inv[pSoldier->ubAttackingHand]);
//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]);
if ( sScopeBonus >= gGameExternalOptions.sVeryHighPowerScope ) if ( sScopeBonus >= gGameExternalOptions.sVeryHighPowerScope )
{ {
aimLevels *= 2; aimLevels *= 2;
} }
else if ( sScopeBonus >= gGameExternalOptions.sHighPowerScope ) else if ( sScopeBonus >= gGameExternalOptions.sHighPowerScope )
{ {
aimLevels = (UINT8)((float)(aimLevels+1) * (float)1.5); aimLevels = (UINT8)((float)(aimLevels+1) * (float)1.5);
} }
else if ( sScopeBonus >= gGameExternalOptions.sMediumPowerScope ) else if ( sScopeBonus >= gGameExternalOptions.sMediumPowerScope )
{ {
aimLevels = (UINT8)((float)(aimLevels+1) * (float)1.3); aimLevels = (UINT8)((float)(aimLevels+1) * (float)1.3);
} }
// Smaller scopes increase by one. // Smaller scopes increase by one.
else if ( sScopeBonus > 0 ) else if ( sScopeBonus > 0 )
{ {
aimLevels++; aimLevels++;
} }
// Make sure not over maximum allowed for weapon type. // Make sure not over maximum allowed for weapon type.
if (aimLevels > maxAimForType) if (aimLevels > maxAimForType)
@@ -11846,7 +12133,18 @@ UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier, INT32 sGridNo)
if (gGameExternalOptions.iAimLevelsCompatibilityOption != 0) if (gGameExternalOptions.iAimLevelsCompatibilityOption != 0)
sScopeBonus = OldWayOfCalculatingScopeBonus(pSoldier); sScopeBonus = OldWayOfCalculatingScopeBonus(pSoldier);
else 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 ) if ( sScopeBonus >= gGameExternalOptions.sVeryHighPowerScope )
{ {
@@ -12274,13 +12572,22 @@ INT16 GetBasicStealthBonus( OBJECTTYPE * pObj )
// HEADROCK HAM 4: Calculate a gun's accuracy, including bonuses from ammo and attachments. // HEADROCK HAM 4: Calculate a gun's accuracy, including bonuses from ammo and attachments.
INT32 GetGunAccuracy( OBJECTTYPE *pObj ) 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) if(UsingNewCTHSystem() == false)
return(Weapon[pObj->usItem].bAccuracy); return(accuracyheatmultiplicator * Weapon[pObj->usItem].bAccuracy);
INT32 bonus = 0; INT32 bonus = 0;
if ( pObj->exists() == true ) 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; bonus = (bonus * (*pObj)[0]->data.gun.bGunStatus) / 100;
INT32 iModifier = GetAccuracyModifier( pObj ); 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 // Yes, this may look stupid, maybe it IS stupid, but this is purely an option
// to use code that was checked in before. // to use code that was checked in before.
// Please, do not trash it again. // 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); * gGameExternalOptions.iAimLevelsCompatibilityOption / gGameExternalOptions.ubStraightSightRange);
} }
@@ -12627,6 +12934,64 @@ FLOAT GetItemCooldownFactor( OBJECTTYPE * pObj )
return cooldownfactor; 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. // HEADROCK HAM 5: Item Transformation.
// Item Transformation is a new way to interact with items. Where Merges combine two items into one, a 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 "Overhead Types.h"
#include "Weapons.h" #include "Weapons.h"
#include <map> // added by Flugente
//forward declarations of common classes to eliminate includes //forward declarations of common classes to eliminate includes
class OBJECTTYPE; class OBJECTTYPE;
@@ -237,7 +238,7 @@ UINT16 MagazineClassIndexToItemType(UINT16 usMagIndex);
BOOLEAN IsScoped( OBJECTTYPE * pObj ); BOOLEAN IsScoped( OBJECTTYPE * pObj );
BOOLEAN NCTHIsScoped( OBJECTTYPE * pObj ); BOOLEAN NCTHIsScoped( OBJECTTYPE * pObj );
INT16 GetReliability( 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. //WarmSteel - Used to determine the base aim bonus of the most powerful scope.
INT16 GetBaseScopeAimBonus( OBJECTTYPE * pObj, INT32 iRange ); INT16 GetBaseScopeAimBonus( OBJECTTYPE * pObj, INT32 iRange );
// HEADROCK: Function to get the natural aimbonus of the weapon and its attachments // 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 GetAutoToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance = FALSE );
INT16 GetGearAimBonus( SOLDIERTYPE * pSoldier, INT32 iRange, INT16 ubAimTime); INT16 GetGearAimBonus( SOLDIERTYPE * pSoldier, INT32 iRange, INT16 ubAimTime);
INT16 GetGearToHitBonus( SOLDIERTYPE * pSoldier ); 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 // HEADROCK: Function to get the final loudness value of a weapon, after reduction from its own characteristics, ammo and attachments
INT16 GetFinalLoudness( OBJECTTYPE * pObj ); INT16 GetFinalLoudness( OBJECTTYPE * pObj );
@@ -289,7 +290,7 @@ INT8 GetStanceModifierRef( INT8 ubStance );
INT16 GetDamageBonus( OBJECTTYPE * pObj ); INT16 GetDamageBonus( OBJECTTYPE * pObj );
INT16 GetMeleeDamageBonus( OBJECTTYPE * pObj ); INT16 GetMeleeDamageBonus( OBJECTTYPE * pObj );
INT16 GetPercentAPReduction( OBJECTTYPE * pObj ); INT16 GetPercentAPReduction( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj );
INT16 GetPercentAutofireAPReduction( OBJECTTYPE * pObj ); INT16 GetPercentAutofireAPReduction( OBJECTTYPE * pObj );
INT16 GetPercentBurstFireAPReduction( OBJECTTYPE * pObj ); INT16 GetPercentBurstFireAPReduction( OBJECTTYPE * pObj );
INT16 GetPercentReadyTimeAPReduction( OBJECTTYPE * pObj ); INT16 GetPercentReadyTimeAPReduction( OBJECTTYPE * pObj );
@@ -410,7 +411,7 @@ OBJECTTYPE* FindNightGogglesInInv( SOLDIERTYPE * pSoldier, INT8 * bSlot, BOOLEAN
UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier, INT32 sGridNo); UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier, INT32 sGridNo);
// HEADROCK HAM 4: New functions to determine Scope and Laser factors on a weapon. // HEADROCK HAM 4: New functions to determine Scope and Laser factors on a weapon.
FLOAT GetHighestScopeMagnificationFactor( OBJECTTYPE *pObj ); 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 GetBestScopeMagnificationFactor( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, FLOAT uiRange );
FLOAT GetProjectionFactor( OBJECTTYPE *pObj ); FLOAT GetProjectionFactor( OBJECTTYPE *pObj );
FLOAT GetScopeRangeMultiplier( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, FLOAT d2DDistance ); FLOAT GetScopeRangeMultiplier( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, FLOAT d2DDistance );
@@ -445,6 +446,10 @@ BOOLEAN UseTotalMedicalKitPoints( SOLDIERTYPE * pSoldier, UINT16 usPointsToConsu
// Flugente FTW 1.2 // Flugente FTW 1.2
FLOAT GetItemCooldownFactor( OBJECTTYPE * pObj ); 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 #endif
+25 -7
View File
@@ -7145,7 +7145,18 @@ FLOAT CalcProjectionFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2
if (ubAimTime > 0) 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)) if (floor(iTargetMagFactor*10) > floor(iProjectionFactor*10.001))
{ {
iProjectionFactor -= (iTargetMagFactor - iProjectionFactor); 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 CalcMagFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2DDistance, UINT8 ubAimTime )
{ {
FLOAT iFinalMagFactor = 0; FLOAT iFinalMagFactor = 1.0;
FLOAT iScopeFactor = 0; FLOAT iScopeFactor = 0;
FLOAT iProjectionFactor = 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 = GetBestScopeMagnificationFactor( pShooter, pWeapon, d2DDistance );
iScopeFactor = __min(iScopeFactor, __max(1.0f, iTargetMagFactor/rangeModifier));
iProjectionFactor = CalcProjectionFactor(pShooter, pWeapon, d2DDistance, ubAimTime); iProjectionFactor = CalcProjectionFactor(pShooter, pWeapon, d2DDistance, ubAimTime);
iFinalMagFactor = __max(iScopeFactor, iProjectionFactor); iFinalMagFactor = __max(iScopeFactor, iProjectionFactor);
} }
else 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; return iFinalMagFactor;
+1
View File
@@ -8650,6 +8650,7 @@ SOLDIERTYPE *InternalReduceAttackBusyCount( )
pSoldier->bDoAutofire = 1; pSoldier->bDoAutofire = 1;
pSoldier->bDoBurst = TRUE; pSoldier->bDoBurst = TRUE;
} }
pSoldier->bScopeMode = USE_BEST_SCOPE;
DirtyMercPanelInterface(pSoldier, DIRTYLEVEL2 ); DirtyMercPanelInterface(pSoldier, DIRTYLEVEL2 );
} }
+22 -22
View File
@@ -1338,7 +1338,7 @@ INT16 GetBreathPerAP( SOLDIERTYPE *pSoldier, UINT16 usAnimState )
} }
//UINT8 CalcAPsToBurst( INT8 bBaseActionPoints, UINT16 usItem ) //UINT8 CalcAPsToBurst( INT8 bBaseActionPoints, UINT16 usItem )
INT16 CalcAPsToBurst( INT16 bBaseActionPoints, OBJECTTYPE * pObj ) INT16 CalcAPsToBurst( INT16 bBaseActionPoints, OBJECTTYPE * pObj, SOLDIERTYPE* pSoldier )
{ {
INT32 aps; INT32 aps;
@@ -1351,15 +1351,15 @@ INT16 CalcAPsToBurst( INT16 bBaseActionPoints, OBJECTTYPE * pObj )
aps = (aps * 100) / (100 + GetBurstFireAPReductionStatus(pObj) / (100/GetPercentBurstFireAPReduction(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 // Snap: do this a little differently: % reduction means
// aps <- aps * ( 100 - red ) / 100 // 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% // Snap: moved this up to allow burst AP reduction up to 100%
aps = __max( aps, ( Weapon[ pObj->usItem ].bBurstAP + 1 ) / 2 ); aps = __max( aps, ( Weapon[ pObj->usItem ].bBurstAP + 1 ) / 2 );
@@ -1388,7 +1388,7 @@ INT16 CalcAPsToBurstNoModifier( INT16 bBaseActionPoints, OBJECTTYPE * pObj )
return (UINT8) aps; 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 //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 // 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: 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))); 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(pObj) ) ) / 100; aps = ( aps * ( 100 - GetPercentAPReduction(pSoldier, pObj) ) ) / 100;
aps = __max( aps, ( autofireaps + 1 ) / 2 ); aps = __max( aps, ( autofireaps + 1 ) / 2 );
@@ -1492,9 +1492,9 @@ INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTur
if ( pSoldier->bDoBurst ) if ( pSoldier->bDoBurst )
{ {
if(pSoldier->bDoAutofire && GetAutofireShotsPerFiveAPs(AttackingWeapon) > 0 ) if(pSoldier->bDoAutofire && GetAutofireShotsPerFiveAPs(AttackingWeapon) > 0 )
sAPCost += CalcAPsToAutofire( pSoldier->CalcActionPoints( ), AttackingWeapon, pSoldier->bDoAutofire ); sAPCost += CalcAPsToAutofire( pSoldier->CalcActionPoints( ), AttackingWeapon, pSoldier->bDoAutofire, pSoldier );
else else
sAPCost += CalcAPsToBurst( pSoldier->CalcActionPoints( ), AttackingWeapon ); sAPCost += CalcAPsToBurst( pSoldier->CalcActionPoints( ), AttackingWeapon, pSoldier );
} }
//else //ddd comment for aimed burst //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 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 )) ) || (UsingNewCTHSystem() == true && GetBestScopeMagnificationFactor(pSoldier, &pSoldier->inv[HANDPOS], (FLOAT)GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo ) > 1.0 )) )
{ {
// Add an individual cost for EACH click, as necessary. // Add an individual cost for EACH click, as necessary.
@@ -1742,7 +1742,7 @@ INT8 CalcAimSkill( SOLDIERTYPE * pSoldier, UINT16 usWeapon )
return( bAimSkill ); return( bAimSkill );
} }
INT16 BaseAPsToShootOrStab( INT16 bAPs, INT16 bAimSkill, OBJECTTYPE * pObj ) INT16 BaseAPsToShootOrStab( INT16 bAPs, INT16 bAimSkill, OBJECTTYPE * pObj, SOLDIERTYPE* pSoldier )
{ {
INT32 Top, Bottom; INT32 Top, Bottom;
FLOAT rof; 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 //CHRISL: Resolves a problem with stackable weapons not using attachments like Reflex sight. Found by Mugsy
//if (ItemSlotLimit(pObj, STACK_SIZE_LIMIT) == 1) //if (ItemSlotLimit(pObj, STACK_SIZE_LIMIT) == 1)
{ {
Top *= ( 100 - GetPercentAPReduction(pObj) ); Top *= ( 100 - GetPercentAPReduction(pSoldier, pObj) );
} }
//else //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 //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){ 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 { } 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 // 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 // SANDRO - gunslinger check for firing speed
if ( HAS_SKILL_TRAIT( pSoldier, GUNSLINGER_NT ) && gGameOptions.fNewTraitSystem ) if ( HAS_SKILL_TRAIT( pSoldier, GUNSLINGER_NT ) && gGameOptions.fNewTraitSystem )
{ {
INT16 bcst1 = BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[HANDPOS]) ); INT16 bcst1 = BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[HANDPOS]), pSoldier );
INT16 bcst2 = BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[SECONDHANDPOS]) ); INT16 bcst2 = BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[SECONDHANDPOS]), pSoldier );
if ( Weapon[ usItem ].ubWeaponType == GUN_PISTOL ) if ( Weapon[ usItem ].ubWeaponType == GUN_PISTOL )
bcst1 = (INT16)((bcst1 * ( 100 - gSkillTraitValues.ubGSFiringSpeedBonusPistols) / 100)+ 0.5); bcst1 = (INT16)((bcst1 * ( 100 - gSkillTraitValues.ubGSFiringSpeedBonusPistols) / 100)+ 0.5);
if ( Weapon[ pSoldier->inv[SECONDHANDPOS].usItem ].ubWeaponType == GUN_PISTOL ) 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 // charge the maximum of the two
bAPCost += __max( bAPCost += __max(
BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[HANDPOS]) ), BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[HANDPOS]), pSoldier ),
BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[SECONDHANDPOS]) ) ); BaseAPsToShootOrStab( bFullAPs, bAimSkill, &(pSoldier->inv[SECONDHANDPOS]), pSoldier ) );
} }
} }
else 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 //CHRISL: When prone and using a bipod, bipod should help compensate for recoil. To reflect this, our shot AP cost should be minimially reduced
if(gGameExternalOptions.ubFlatAFTHBtoPrecentMultiplier > 0 && gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE && GetBipodBonus(&(pSoldier->inv[HANDPOS])) > 0) if(gGameExternalOptions.ubFlatAFTHBtoPrecentMultiplier > 0 && gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE && GetBipodBonus(&(pSoldier->inv[HANDPOS])) > 0)
{ {
bAPCost += (BaseAPsToShootOrStab( bFullAPs, bAimSkill, pObjUsed ) * (100 - GetBipodBonus(&(pSoldier->inv[HANDPOS]))) / 100); bAPCost += (BaseAPsToShootOrStab( bFullAPs, bAimSkill, pObjUsed, pSoldier ) * (100 - GetBipodBonus(&(pSoldier->inv[HANDPOS]))) / 100);
} }
else else
{ {
bAPCost += BaseAPsToShootOrStab( bFullAPs, bAimSkill, pObjUsed ); bAPCost += BaseAPsToShootOrStab( bFullAPs, bAimSkill, pObjUsed, pSoldier );
} }
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
// SANDRO - STOMP traits // 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 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 ))) || (UsingNewCTHSystem() == true && GetBestScopeMagnificationFactor(pSoldier, &pSoldier->inv[HANDPOS], (FLOAT)GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sTargetGridNo ) > 1.0 )))
{ {
// Add an individual cost for EACH click, as necessary. // 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 //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]; 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. // HEADROCK HAM 4: Same function as above, except no modifier.
INT16 BaseAPsToShootOrStabNoModifier( INT16 bAPs, INT16 bAimSkill, OBJECTTYPE * pObj ); INT16 BaseAPsToShootOrStabNoModifier( INT16 bAPs, INT16 bAimSkill, OBJECTTYPE * pObj );
// HEADROCK HAM 4: Same function as above, except no modifier. // 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 MinAPsToPunch(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurningCost );
INT16 ApsToPunch( SOLDIERTYPE *pSoldier ); // SANDRO added this INT16 ApsToPunch( SOLDIERTYPE *pSoldier ); // SANDRO added this
INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurningCost, INT16 bAimTime ); 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. // HEADROCK HAM 4: Same as above, without percent modifiers.
INT16 CalcAPsToBurstNoModifier( INT16 bBaseActionPoints, OBJECTTYPE * pObj ); INT16 CalcAPsToBurstNoModifier( INT16 bBaseActionPoints, OBJECTTYPE * pObj );
// HEADROCK HAM 4: Same as above, without percent modifiers. // HEADROCK HAM 4: Same as above, without percent modifiers.
INT16 CalcAPsToBurstNoModifier( INT16 bBaseActionPoints, OBJECTTYPE * pObj ); 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 // HEADROCK HAM 4: Same as above, without modifiers
INT16 CalcAPsToAutofireNoModifier( INT16 bBaseActionPoints, OBJECTTYPE * pObj, UINT8 bDoAutofire ); INT16 CalcAPsToAutofireNoModifier( INT16 bBaseActionPoints, OBJECTTYPE * pObj, UINT8 bDoAutofire );
// HEADROCK HAM 4: Same as above, without modifiers // 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->snowCamo = src.snowCamo;
this->wornSnowCamo = src.wornSnowCamo; this->wornSnowCamo = src.wornSnowCamo;
this->bScopeMode = USE_BEST_SCOPE;
} }
return *this; return *this;
} }
@@ -12340,6 +12342,7 @@ void SOLDIERTYPE::ReLoadSoldierAnimationDueToHandItemChange( UINT16 usOldItem, U
this->bWeaponMode = WM_AUTOFIRE; this->bWeaponMode = WM_AUTOFIRE;
this->bDoAutofire = 1; this->bDoAutofire = 1;
} }
this->bScopeMode = USE_BEST_SCOPE;
if ( gAnimControl[ this->usAnimState ].uiFlags & ANIM_FIREREADY ) 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 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 #endif
// Flugente: Is this the correct position?
INT8 bScopeMode;
char endOfPOD; // marker for end of POD (plain old data) char endOfPOD; // marker for end of POD (plain old data)
// Note: Place all non-POD items at the end (after endOfPOD) // Note: Place all non-POD items at the end (after endOfPOD)
@@ -1319,7 +1322,7 @@ public:
BOOLEAN IsValidSecondHandShotForReloadingPurposes( void ); BOOLEAN IsValidSecondHandShotForReloadingPurposes( void );
BOOLEAN SoldierCarriesTwoHandedWeapon( void ); BOOLEAN SoldierCarriesTwoHandedWeapon( void );
void SoldierInventoryCoolDown( void ); // Flugente FTW 1: Cool down all items in inventory void SoldierInventoryCoolDown( void ); // Flugente FTW 1: Cool down all items in inventory
BOOLEAN IsWeaponMounted( void ); // 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 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 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 ToggleZBuffer();
void TogglePlanningMode(); void TogglePlanningMode();
void SetBurstMode(); void SetBurstMode();
void SetScopeMode();
void ObliterateSector(); void ObliterateSector();
void RandomizeMercProfile(); void RandomizeMercProfile();
void CreateNextCivType(); void CreateNextCivType();
@@ -4403,6 +4404,24 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
} }
//else if( gusSelectedSoldier != NOBODY ) //else if( gusSelectedSoldier != NOBODY )
break; break;
// added by Flugente
case '.':
if ( fCtrl )
{
}
else if ( fAlt )
{
}
else
{
SetScopeMode();
}
break;
case 'z': case 'z':
if( fCtrl && fAlt ) if( fCtrl && fAlt )
{ {
@@ -5175,6 +5194,17 @@ void SetBurstMode()
} }
} }
void SetScopeMode()
{
if ( gusSelectedSoldier != NOBODY )
{
ChangeScopeMode( MercPtrs[ gusSelectedSoldier ] );
// reevaluate sight
ManLooksForOtherTeams( MercPtrs[ gusSelectedSoldier ] );
}
}
void ObliterateSector() void ObliterateSector()
{ {
INT32 cnt; INT32 cnt;
+117 -30
View File
@@ -6077,7 +6077,17 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
iMaxRange = CELL_X_SIZE; // one tile iMaxRange = CELL_X_SIZE; // one tile
iCoverRange = __max(0,iSightRange - iRange); iCoverRange = __max(0,iSightRange - iRange);
iMinRange = iMaxRange / 10; 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 ) ) { else if ( HAS_SKILL_TRAIT( pSoldier, PROF_SNIPER_OT ) ) {
iSightRange -= ((gbSkillTraitBonus[ PROF_SNIPER_OT ] * NUM_SKILL_TRAITS( pSoldier, PROF_SNIPER_OT )) * iSightRange) /100; 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; 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; iPenalty += iSightRange * iScopeVisionRangeBonus / 100;
} }
iSightRange += iPenalty; iSightRange += iPenalty;
@@ -6311,15 +6321,28 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
// 25% penalty per tile closer than min range // 25% penalty per tile closer than min range
iChance -= 25 * ( ( MIN_TANK_RANGE - iRange ) / CELL_X_SIZE ); 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 = (Item[iter->usItem].aimbonus * (iRange - Item[iter->usItem].minrangeforaimbonus)) / 1000;
iPenalty = min(AIM_BONUS_PRONE, iPenalty); iPenalty = min(AIM_BONUS_PRONE, iPenalty);
iChance -= 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, // Bonus for heavy weapons moved here from above to get instant CtH bonus and not marksmanship bonus,
// which is supressed by weapon condition // 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 !!! 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 iChance += gSkillTraitValues.ubHWBonusCtHRocketLaunchers * NUM_SKILL_TRAITS( pSoldier, HEAVY_WEAPONS_NT ); // +25% per trait
} }
// Added CtH bonus for Gunslinger trait on pistols and machine-pistols // 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. 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 ) 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 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. 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 iChance += gSkillTraitValues.ubGSBonusCtHMachinePistols * NUM_SKILL_TRAITS( pSoldier, GUNSLINGER_NT ); // +5% per trait
} }
// Added CtH bonus for Machinegunner skill on assault rifles, SMGs and LMGs // 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. iChance += gSkillTraitValues.bCtHModifierAssaultRifles; // -5% for untrained mercs.
if ( HAS_SKILL_TRAIT( pSoldier, AUTO_WEAPONS_NT ) ) if ( HAS_SKILL_TRAIT( pSoldier, AUTO_WEAPONS_NT ) )
iChance += gSkillTraitValues.ubAWBonusCtHAssaultRifles * NUM_SKILL_TRAITS( pSoldier, AUTO_WEAPONS_NT ); // +5% per trait 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. iChance += gSkillTraitValues.bCtHModifierSMGs; // -5% for untrained mercs.
if ( HAS_SKILL_TRAIT( pSoldier, AUTO_WEAPONS_NT ) ) if ( HAS_SKILL_TRAIT( pSoldier, AUTO_WEAPONS_NT ) )
iChance += gSkillTraitValues.ubAWBonusCtHSMGs * NUM_SKILL_TRAITS( pSoldier, AUTO_WEAPONS_NT ); // +5% per trait 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. 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 iChance += gSkillTraitValues.ubAWBonusCtHLMGs * NUM_SKILL_TRAITS( pSoldier, AUTO_WEAPONS_NT ); // +5% per trait
} }
// Added CtH bonus for Gunslinger trait on pistols and machine-pistols // 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. 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 iChance += gSkillTraitValues.ubSNBonusCtHSniperRifles * NUM_SKILL_TRAITS( pSoldier, SNIPER_NT ); // +5% per trait
} }
// Added CtH bonus for Ranger skill on rifles and shotguns // 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. 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 ) 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 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. 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 // 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 // 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. // 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 // bonus to snipers and gunslingers
if ( Weapon[usInHand].ubWeaponType == GUN_PISTOL || Weapon[usInHand].ubWeaponType == GUN_M_PISTOL ) 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 else
maxBonus = 20+((FLOAT)iMarksmanship/20*(EffectiveExpLevel(pSoldier)))+(Weapon[Item[pInHand->usItem].ubClassIndex].bAccuracy*2)+(NUM_SKILL_TRAITS( pSoldier, SNIPER_NT )*gSkillTraitValues.ubSNAimingBonusPerClick); 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);
else
maxBonus = 20+((FLOAT)iMarksmanship/20*pSoldier->stats.bExpLevel)+(Weapon[Item[pInHand->usItem].ubClassIndex].bAccuracy*2)+(NUM_SKILL_TRAITS( pSoldier, PROF_SNIPER_OT )*10);
} }
iAimBonus = (float)GetAimBonus( pInHand, 100, 1 ); else
{
if(gGameExternalOptions.bAltAimEnabled)
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)+(accuracyheatmultiplicator * Weapon[Item[pInHand->usItem].ubClassIndex].bAccuracy*2)+(NUM_SKILL_TRAITS( pSoldier, PROF_SNIPER_OT )*10);
}
iAimBonus = (float)GetAimBonus( pSoldier, pInHand, 100, 1 );
for(int i = 0; i < ubAimTime; i++) { for(int i = 0; i < ubAimTime; i++) {
aimTimeBonus = __min((maxBonus*bonusProgression[i]/1000),maxClickBonus); aimTimeBonus = __min((maxBonus*bonusProgression[i]/1000),maxClickBonus);
maxBonus -= aimTimeBonus; maxBonus -= aimTimeBonus;
@@ -10231,6 +10267,7 @@ void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInv
pSoldier->bDoBurst = TRUE; pSoldier->bDoBurst = TRUE;
pSoldier->bDoAutofire = 1; pSoldier->bDoAutofire = 1;
} }
pSoldier->bScopeMode = USE_BEST_SCOPE;
} }
// if he is loaded tactically // if he is loaded tactically
@@ -10268,6 +10305,7 @@ void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInv
pSoldier->bDoAutofire = 1; pSoldier->bDoAutofire = 1;
pSoldier->bDoBurst = TRUE; pSoldier->bDoBurst = TRUE;
} }
pSoldier->bScopeMode = USE_BEST_SCOPE;
} }
} }
} }
@@ -10710,6 +10748,37 @@ void ChangeWeaponMode( SOLDIERTYPE * pSoldier )
gfUIForceReExamineCursorData = TRUE; 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 ) void DishoutQueenSwipeDamage( SOLDIERTYPE *pQueenSoldier )
{ {
INT8 bValidDishoutDirs[3][3] = { NORTH, NORTHEAST, -1, INT8 bValidDishoutDirs[3][3] = { NORTH, NORTHEAST, -1,
@@ -11160,16 +11229,14 @@ void CalcMagFactorSimple( SOLDIERTYPE *pSoldier, FLOAT d2DDistance, INT16 bAimTi
FLOAT iHighestMagFactor = 0; FLOAT iHighestMagFactor = 0;
FLOAT iScopeFactor = 0; FLOAT iScopeFactor = 0;
FLOAT iProjectionFactor = 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 ); iScopeFactor = GetBestScopeMagnificationFactor( pSoldier, pWeapon, d2DDistance );
// Set a display variable // Set a display variable
gCTHDisplay.ScopeMagFactor = iScopeFactor; gCTHDisplay.ScopeMagFactor = iScopeFactor;
iScopeFactor = __min(iScopeFactor, __max(1.0f, iTargetMagFactor/rangeModifier));
iProjectionFactor = CalcProjectionFactor(pSoldier, pWeapon, d2DDistance, (UINT8)bAimTime); iProjectionFactor = CalcProjectionFactor(pSoldier, pWeapon, d2DDistance, (UINT8)bAimTime);
// Set a display variable // Set a display variable
gCTHDisplay.ProjectionFactor = iProjectionFactor; gCTHDisplay.ProjectionFactor = iProjectionFactor;
@@ -11179,9 +11246,29 @@ void CalcMagFactorSimple( SOLDIERTYPE *pSoldier, FLOAT d2DDistance, INT16 bAimTi
} }
else else
{ {
gCTHDisplay.ScopeMagFactor = 1.0; FLOAT iTargetMagFactor = d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE;
gCTHDisplay.ProjectionFactor = 1.0; FLOAT rangeModifier = GetScopeRangeMultiplier(pSoldier, pWeapon, d2DDistance);
iHighestMagFactor = 1.0;
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; gCTHDisplay.FinalMagFactor = iHighestMagFactor;
+16
View File
@@ -18,6 +18,21 @@ enum WeaponMode
NUM_WEAPON_MODES 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 //ADB moved from Interface Panels.h
void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInvPos, UINT16 usOldItem, UINT16 usNewItem ); 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 UINT32 CalcThrownChanceToHit(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, UINT8 ubAimPos );
extern void ChangeWeaponMode( SOLDIERTYPE * pSoldier ); extern void ChangeWeaponMode( SOLDIERTYPE * pSoldier );
extern void ChangeScopeMode( SOLDIERTYPE * pSoldier ); // Flugente: use different scope
extern BOOLEAN UseHandToHand( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo, BOOLEAN fStealing ); 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->usAttackingWeapon = pSoldier->inv[HANDPOS].usItem;
pSoldier->bWeaponMode = WM_NORMAL; 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 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; INT8 bRecoilY = 0;
pSoldier->bDoAutofire++; pSoldier->bDoAutofire++;
dTotalRecoil += AICalcRecoilForShot( pSoldier, &(pSoldier->inv[BestShot.bWeaponIn]), 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 while( pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire
&& dTotalRecoil <= 10.0f ); && dTotalRecoil <= 10.0f );
@@ -2535,7 +2535,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
do do
{ {
pSoldier->bDoAutofire++; 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 && while( pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs &&
pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire &&
@@ -2545,7 +2545,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
pSoldier->bDoAutofire--; pSoldier->bDoAutofire--;
// Make sure we decided to fire at least one shot! // 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? // minimum 5 bullets //WarmSteel: 5 bullets sounds reasonable, no?
// Hmmm, automatic suppression? Howcome we don't get this? // 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"); 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. // HEADROCK HAM 3.6: Use Actual Aiming Time.
if (pSoldier->bActionPoints >= BestAttack.ubAPCost + sActualAimTime + ubBurstAPs ) if (pSoldier->bActionPoints >= BestAttack.ubAPCost + sActualAimTime + ubBurstAPs )
@@ -4937,7 +4937,7 @@ INT16 ubMinAPCost;
INT8 bRecoilY = 0; INT8 bRecoilY = 0;
pSoldier->bDoAutofire++; pSoldier->bDoAutofire++;
dTotalRecoil += AICalcRecoilForShot( pSoldier, &(pSoldier->inv[BestShot.bWeaponIn]), 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 while( pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs + sActualAimTime && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire
&& dTotalRecoil <= 10.0f ); && dTotalRecoil <= 10.0f );
@@ -4945,7 +4945,7 @@ INT16 ubMinAPCost;
do do
{ {
pSoldier->bDoAutofire++; 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 && while( pSoldier->bActionPoints >= BestAttack.ubAPCost + ubBurstAPs &&
pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire &&
@@ -4955,7 +4955,7 @@ INT16 ubMinAPCost;
pSoldier->bDoAutofire--; pSoldier->bDoAutofire--;
if (pSoldier->bDoAutofire > 0) 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 ) if (pSoldier->bActionPoints >= BestAttack.ubAPCost + ubBurstAPs )
{ {
@@ -5009,7 +5009,7 @@ INT16 ubMinAPCost;
{ {
pSoldier->aiData.bAimTime = BestAttack.ubAimTime ; pSoldier->aiData.bAimTime = BestAttack.ubAimTime ;
pSoldier->bDoBurst = 1; 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 else
{ {
@@ -5184,7 +5184,7 @@ INT16 ubMinAPCost;
{ {
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "DecideActionBlack: Doing burst calc"); 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 ) if ( (pSoldier->bActionPoints - BestAttack.ubAPCost) >= ubBurstAPs )
{ {
@@ -5215,7 +5215,7 @@ INT16 ubMinAPCost;
{ {
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "DecideActionBlack: Doing GL burst"); DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "DecideActionBlack: Doing GL burst");
BestAttack.ubAimTime = BURSTING; 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 // check for spread burst possibilities
if (pSoldier->aiData.bAttitude != ATTACKSLAYONLY) if (pSoldier->aiData.bAttitude != ATTACKSLAYONLY)
{ {
+104
View File
@@ -3609,6 +3609,87 @@ void AddBombToQueue( UINT32 uiWorldBombIndex, UINT32 uiTimeStamp, BOOL fFromRemo
gfExplosionQueueActive = TRUE; 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 ) void HandleExplosionQueue( void )
{ {
UINT32 uiIndex; UINT32 uiIndex;
@@ -3919,6 +4000,29 @@ BOOLEAN SetOffBombsInGridNo( UINT8 ubID, INT32 sGridNo, BOOLEAN fAllBombs, INT8
// isn't a bomb but a trigger // isn't a bomb but a trigger
SetOffBombsByFrequency( ubID, (*pObj)[0]->data.misc.bFrequency ); 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 else
{ {
gubPersonToSetOffExplosions = ubID; 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 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 ); 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 ToggleActionItemsByFrequency( INT8 bFrequency );
extern void PerformItemAction( INT32 sGridNo, OBJECTTYPE * pObj ); extern void PerformItemAction( INT32 sGridNo, OBJECTTYPE * pObj );
extern BOOLEAN gfExplosionQueueMayHaveChangedSight; extern BOOLEAN gfExplosionQueueMayHaveChangedSight;
+22
View File
@@ -256,6 +256,9 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at
strcmp(name, "overheatCooldownModificator") == 0 || strcmp(name, "overheatCooldownModificator") == 0 ||
strcmp(name, "overheatJamThresholdModificator") == 0 || strcmp(name, "overheatJamThresholdModificator") == 0 ||
strcmp(name, "overheatDamageThresholdModificator") == 0 || strcmp(name, "overheatDamageThresholdModificator") == 0 ||
strcmp(name, "attachmentclass") == 0 ||
strcmp(name, "tripwireactivation") == 0 ||
strcmp(name, "tripwire") == 0 ||
strcmp(name, "fFlags") == 0 )) strcmp(name, "fFlags") == 0 ))
{ {
@@ -1277,6 +1280,21 @@ itemEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT; pData->curElement = ELEMENT;
pData->curItem.overheatDamageThresholdModificator = (FLOAT) atof(pData->szCharData); 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--; pData->maxReadDepth--;
} }
@@ -1882,6 +1900,10 @@ BOOLEAN WriteItemStats()
FilePrintf(hFile,"\t\t<overheatJamThresholdModificator>%4.2f</overheatJamThresholdModificator>\r\n", Item[cnt].overheatJamThresholdModificator ); 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<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"); FilePrintf(hFile,"\t</ITEM>\r\n");
} }