diff --git a/Laptop/BobbyRGuns.cpp b/Laptop/BobbyRGuns.cpp index 6d3618754..1ec33fdce 100644 --- a/Laptop/BobbyRGuns.cpp +++ b/Laptop/BobbyRGuns.cpp @@ -166,7 +166,7 @@ BobbyRayPurchaseStruct BobbyRayPurchases[ 100 ]; #define BOBBYR_MISC_FILTER_BUTTON_GAP BOBBYR_CATALOGUE_BUTTON_GAP - 1 //Madd: new BR filters -#define BR_MISC_FILTER_OPTICS (AC_SCOPE | AC_SIGHT) +#define BR_MISC_FILTER_OPTICS (AC_SCOPE | AC_SIGHT | AC_IRONSIGHT) #define BR_MISC_FILTER_SIDE_BOTTOM (AC_LASER | AC_FOREGRIP | AC_BIPOD) #define BR_MISC_FILTER_MUZZLE (AC_SUPPRESSOR | AC_EXTENDER) #define BR_MISC_FILTER_STOCK AC_STOCK diff --git a/Tactical/Interface Items.cpp b/Tactical/Interface Items.cpp index aca3af183..051272621 100644 --- a/Tactical/Interface Items.cpp +++ b/Tactical/Interface Items.cpp @@ -3837,6 +3837,27 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec mprintf( sMagX, sNewY, pStr ); gprintfinvalidate( sMagX, sNewY, pStr ); } + // improved iron sights are attachable iron sights (the 'normal' iron sight is the gun itself) + else if ( IsAttachmentClass(ObjList[pSoldier->bScopeMode]->usItem, AC_IRONSIGHT ) ) + { + BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoAdvancedIcon, 52, sNewX, sNewY, VO_BLT_TRANSSHADOW, NULL ); + + SetFontForeground( FONT_ORANGE ); + + INT16 sMagX = sNewX + 13; + + swprintf( pStr, L"*" ); + + // 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 ); diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index 6abcc9241..a033ce8da 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -648,10 +648,10 @@ extern OBJECTTYPE gTempObject; #define AC_DETONATOR 0x00010000 //65536 #define AC_BATTERY 0x00020000 //131072 #define AC_EXTENDER 0x00040000 //262144 -#define AC_SLING 0x00080000 //524288 -#define AC_REMOTEDET 0x00100000 //1048576 -#define AC_DEFUSE 0x00200000 //2097152 -#define AC_MISC11 0x00400000 //4194304 +#define AC_SLING 0x00080000 //524288 // rifle sling +#define AC_REMOTEDET 0x00100000 //1048576 // remote detonator for bombs +#define AC_DEFUSE 0x00200000 //2097152 // defuse item for bombs +#define AC_IRONSIGHT 0x00400000 //4194304 // for attachable Iron Sights #define AC_MISC12 0x00800000 //8388608 #define AC_MISC13 0x01000000 //16777216 #define AC_MISC14 0x02000000 //33554432 @@ -954,6 +954,8 @@ typedef struct UINT32 drugtype; // this flagmask determines what different components are used in a drug, which results in different effects + BOOLEAN blockironsight; // if a gun or any attachment have this property, the iron sight won't be usable (if there is at least one other usable sight) + } INVTYPE; // CHRISL: Added new structures to handle LBE gear and the two new XML files that will be needed to deal diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index 4eb431bd5..4f7cd9c95 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -9200,7 +9200,7 @@ INT16 GetAimBonus( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, INT32 iRange, INT1 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 ) ) + if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT ) ) { bonus += BonusReduceMore( GetItemAimBonus( &Item[iter->usItem], iRange, ubAimTime ), (*iter)[0]->data.objectStatus ); } @@ -9938,7 +9938,7 @@ INT16 GetPercentAPReduction( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj ) 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() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) ) + if( iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT ) ) { bonus += BonusReduceMore( Item[iter->usItem].percentapreduction, (*iter)[0]->data.objectStatus ); @@ -10182,7 +10182,7 @@ INT16 GetVisionRangeBonus( SOLDIERTYPE * pSoldier ) 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 ) ) + if( iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT ) ) { sScopebonus += BonusReduceMore( Item[iter->usItem].visionrangebonus, (*iter)[0]->data.objectStatus ); } @@ -10289,7 +10289,7 @@ INT16 GetNightVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel ) 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 ) ) + if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT ) ) { sScopebonus += BonusReduceMore( NightBonusScale( Item[iter->usItem].nightvisionrangebonus, bLightLevel ), @@ -10389,7 +10389,7 @@ INT16 GetCaveVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel ) 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 ) ) + if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT ) ) { sScopebonus += BonusReduceMore( NightBonusScale( Item[iter->usItem].cavevisionrangebonus, bLightLevel ), @@ -10495,7 +10495,7 @@ INT16 GetDayVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel ) 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 ) ) + if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT ) ) { sScopebonus += BonusReduceMore( idiv( Item[iter->usItem].dayvisionrangebonus * (NORMAL_LIGHTLEVEL_NIGHT - __max(bLightLevel,NORMAL_LIGHTLEVEL_DAY)), (NORMAL_LIGHTLEVEL_NIGHT-NORMAL_LIGHTLEVEL_DAY) ), @@ -10597,7 +10597,7 @@ INT16 GetBrightLightVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel 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 ) ) + if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT ) ) { sScopebonus += BonusReduceMore( idiv( Item[iter->usItem].brightlightvisionrangebonus * (NORMAL_LIGHTLEVEL_DAY - bLightLevel), NORMAL_LIGHTLEVEL_DAY ), @@ -10748,7 +10748,7 @@ UINT8 GetPercentTunnelVision( SOLDIERTYPE * pSoldier ) 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 ) ) + if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT ) ) { bonus += Item[iter->usItem].percenttunnelvision; } @@ -11810,7 +11810,7 @@ INT16 GetMinRangeForAimBonus( SOLDIERTYPE* pSoldier, OBJECTTYPE * pObj ) 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 ) ) + if ( !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT ) ) bonus += Item[iter->usItem].minrangeforaimbonus; } } @@ -13141,46 +13141,80 @@ void GetScopeLists( OBJECTTYPE * pObj, std::map& arScopeMap { arScopeMap[i] = NULL; } - + + // certain attachments prohibit the use of an iron sight once they are installed (flip-up built-in sights) + BOOLEAN noironsight = ( Item[pObj->usItem].blockironsight == TRUE ); + 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 ) ) + if ( iter->exists() ) { - FLOAT magfactor = Item[iter->usItem].scopemagfactor; - BOOLEAN isplaced = false; + if ( Item[iter->usItem].blockironsight == TRUE ) + noironsight = TRUE; + if ( IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT ) ) + { + 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; + } + } + } + } + } + } + + // attachments might block the iron sights, we might not be able to use them... + if ( noironsight ) + { + // if we have at least one other scope to use + if ( arScopeMap[USE_BEST_SCOPE] != NULL && arScopeMap[USE_SCOPE_2] != NULL ) + { + // determine position of iron sight, delete it, move up all following scopes 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 + if ( arScopeMap[i] == pObj ) + { + arScopeMap.erase(i); + + // 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; - } - } - } } } } diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 24654d2af..cd85f7f5c 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -12458,6 +12458,24 @@ void SOLDIERTYPE::ReLoadSoldierAnimationDueToHandItemChange( UINT16 usOldItem, U { fNewRifle = TRUE; } + + // Flugente: if we are using dual weapons, only allow iron sights (we can't look through two scopes simultaneously, can we?) + if ( (Item[ inv[ HANDPOS ].usItem ].usItemClass & IC_WEAPON) && (Item[ inv[ SECONDHANDPOS ].usItem ].usItemClass & IC_WEAPON) ) + { + std::map ObjList; + GetScopeLists(&inv[ HANDPOS ], ObjList); + + std::map::iterator itend = ObjList.end(); + for (std::map::iterator it = ObjList.begin(); it != itend; ++it) + { + if ( (*it).second != NULL ) + { + bScopeMode = (*it).first; + } + else + break; + } + } } } diff --git a/Tactical/Weapons.cpp b/Tactical/Weapons.cpp index 78604d2ac..c7d54775a 100644 --- a/Tactical/Weapons.cpp +++ b/Tactical/Weapons.cpp @@ -6350,7 +6350,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, 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() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT ) && Item[iter->usItem].aimbonus >= gGameExternalOptions.sHighPowerScope && iRange > Item[iter->usItem].minrangeforaimbonus) + if(iter->exists() && !IsAttachmentClass(iter->usItem, AC_SCOPE|AC_SIGHT|AC_IRONSIGHT ) && Item[iter->usItem].aimbonus >= gGameExternalOptions.sHighPowerScope && iRange > Item[iter->usItem].minrangeforaimbonus) { iPenalty = (Item[iter->usItem].aimbonus * (iRange - Item[iter->usItem].minrangeforaimbonus)) / 1000; iPenalty = min(AIM_BONUS_PRONE, iPenalty); @@ -10212,6 +10212,27 @@ void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInv pSoldier->bScopeMode = USE_BEST_SCOPE; } } + + // Flugente: if we are using dual weapons, only allow iron sights (we can't look through two scopes simultaneously, can we?) + if ( uiInvPos == HANDPOS || uiInvPos == SECONDHANDPOS ) + { + if ( (Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass & IC_WEAPON) && (Item[ pSoldier->inv[ SECONDHANDPOS ].usItem ].usItemClass & IC_WEAPON) ) + { + std::map ObjList; + GetScopeLists(&pSoldier->inv[ HANDPOS ], ObjList); + + std::map::iterator itend = ObjList.end(); + for (std::map::iterator it = ObjList.begin(); it != itend; ++it) + { + if ( (*it).second != NULL ) + { + pSoldier->bScopeMode = (*it).first; + } + else + break; + } + } + } } diff --git a/Utils/XML_Items.cpp b/Utils/XML_Items.cpp index 9f973c84f..b840c692c 100644 --- a/Utils/XML_Items.cpp +++ b/Utils/XML_Items.cpp @@ -264,6 +264,7 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at strcmp(name, "TripWire") == 0 || strcmp(name, "Directional") == 0 || strcmp(name, "DrugType") == 0 || + strcmp(name, "BlockIronSight") == 0 || strcmp(name, "fFlags") == 0 )) { @@ -1325,7 +1326,13 @@ itemEndElementHandle(void *userData, const XML_Char *name) pData->curElement = ELEMENT; pData->curItem.drugtype = (UINT32) atol(pData->szCharData); } + else if(strcmp(name, "BlockIronSight") == 0) + { + pData->curElement = ELEMENT; + pData->curItem.blockironsight = (BOOLEAN) atol(pData->szCharData); + } + pData->maxReadDepth--; } @@ -1938,6 +1945,8 @@ BOOLEAN WriteItemStats() FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].drugtype ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].blockironsight ); + FilePrintf(hFile,"\t\r\n"); } FilePrintf(hFile,"\r\n");