diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index e60d507c..83e6a1fc 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -5612,8 +5612,17 @@ UINT8 StealItems(SOLDIERTYPE* pSoldier,SOLDIERTYPE* pOpponent, UINT8* ubIndexRet switch (i) { case HANDPOS: - case SECONDHANDPOS: case GUNSLINGPOCKPOS: + { + // Flugente: if item has a weapon sling attached, it can't be stolen + if ( HasAttachmentOfClass(pObject, AC_SLING) ) + fStealItem = FALSE; + else + fStealItem = TRUE; + + break; + } + case SECONDHANDPOS: case KNIFEPOCKPOS: case BIGPOCK1POS: case BIGPOCK2POS: diff --git a/Tactical/Interface Panels.cpp b/Tactical/Interface Panels.cpp index 5b14beb5..a620815f 100644 --- a/Tactical/Interface Panels.cpp +++ b/Tactical/Interface Panels.cpp @@ -3497,7 +3497,7 @@ UINT16 uiOIVSlotType[NUM_INV_SLOTS] = { 0, 0, 0, 0, 0, 0 //49-54 }; -UINT32 GetInvMovementCost(UINT16 item, UINT32 old_pos, UINT32 new_pos) +UINT32 GetInvMovementCost(OBJECTTYPE* pObj, UINT32 old_pos, UINT32 new_pos) { if (!(gTacticalStatus.uiFlags & INCOMBAT) || //Not in combat (old_pos == -1 || new_pos == -1)|| //Either position is invalid @@ -3552,7 +3552,7 @@ UINT32 GetInvMovementCost(UINT16 item, UINT32 old_pos, UINT32 new_pos) FLOAT Weight_Divisor = gGameExternalOptions.uWeightDivisor; UINT16 weight_modifier; if (Weight_Divisor != 0) - weight_modifier = DynamicAdjustAPConstants((int)((Item[item].ubWeight) / Weight_Divisor),(int)((Item[item].ubWeight) / Weight_Divisor)); + weight_modifier = DynamicAdjustAPConstants((int)((Item[pObj->usItem].ubWeight) / Weight_Divisor),(int)((Item[pObj->usItem].ubWeight) / Weight_Divisor)); else weight_modifier = 0; @@ -3562,6 +3562,15 @@ UINT32 GetInvMovementCost(UINT16 item, UINT32 old_pos, UINT32 new_pos) cost += uiAPCostToSlot[dst_type]; cost += weight_modifier; + // Flugente if we move an item from our hands to the sling, and item has a weapon sling, don't charge any APs + if ( 1 == src_type && 7 == dst_type ) + { + // if item has a weapon sling attached + if ( HasAttachmentOfClass(pObj, AC_SLING) ) + // we simply let go of the item, we can do that because the sling will catch it + cost = 0; + } + if (cost > APBPConstants[AP_INV_MAX_COST]) cost = APBPConstants[AP_INV_MAX_COST]; @@ -3709,7 +3718,7 @@ void SMInvClickCallback( MOUSE_REGION * pRegion, INT32 iReason ) { if (INV_AP_COST) //Jenilee: determine the cost of moving this item around in our inventory - usCostToMoveItem = GetInvMovementCost(gpItemPointer->usItem, uiLastHandPos, uiHandPos); + usCostToMoveItem = GetInvMovementCost(gpItemPointer, uiLastHandPos, uiHandPos); if ( ( usCostToMoveItem == 0 ) || ( gpSMCurrentMerc->bActionPoints >= usCostToMoveItem ) ) { diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index a2fe053b..0de77cac 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -641,9 +641,9 @@ extern OBJECTTYPE gTempObject; #define AC_DETONATOR 0x00010000 //65536 #define AC_BATTERY 0x00020000 //131072 #define AC_EXTENDER 0x00040000 //262144 -#define AC_MISC8 0x00080000 //524288 -#define AC_MISC9 0x00100000 //1048576 -#define AC_MISC10 0x00200000 //2097152 +#define AC_SLING 0x00080000 //524288 +#define AC_REMOTEDET 0x00100000 //1048576 +#define AC_DEFUSE 0x00200000 //2097152 #define AC_MISC11 0x00400000 //4194304 #define AC_MISC12 0x00800000 //8388608 #define AC_MISC13 0x01000000 //16777216 diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index 53b7b017..00e4be5f 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -9050,7 +9050,9 @@ INT16 GetAimBonus( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, INT32 iRange, INT1 std::map ObjList; GetScopeLists(pObj, ObjList); - bonus = BonusReduceMore( GetItemAimBonus( &Item[ObjList[pSoldier->bScopeMode]->usItem], iRange, ubAimTime ), (*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus ); + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == pObj ) + 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 ); @@ -9811,7 +9813,9 @@ INT16 GetPercentAPReduction( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj ) std::map ObjList; GetScopeLists(pObj, ObjList); - bonus += BonusReduceMore( Item[ObjList[pSoldier->bScopeMode]->usItem].percentapreduction, (*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus ); + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == pObj ) + bonus += BonusReduceMore( Item[ObjList[pSoldier->bScopeMode]->usItem].percentapreduction, (*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus ); } } else @@ -10052,8 +10056,10 @@ INT16 GetVisionRangeBonus( SOLDIERTYPE * pSoldier ) std::map 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 ); + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == pObj ) + // now apply the bonus from the scope we use + sScopebonus += BonusReduceMore( Item[ObjList[pSoldier->bScopeMode]->usItem].visionrangebonus, (*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus ); } } else @@ -10159,10 +10165,12 @@ INT16 GetNightVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel ) std::map ObjList; GetScopeLists(pObj, ObjList); - // now apply the bonus from the scope we use - sScopebonus += BonusReduceMore( - NightBonusScale( Item[ObjList[pSoldier->bScopeMode]->usItem].cavevisionrangebonus, bLightLevel ), - (*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus ); + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == pObj ) + // now apply the bonus from the scope we use + sScopebonus += BonusReduceMore( + NightBonusScale( Item[ObjList[pSoldier->bScopeMode]->usItem].cavevisionrangebonus, bLightLevel ), + (*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus ); } } else @@ -10257,10 +10265,12 @@ INT16 GetCaveVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel ) std::map ObjList; GetScopeLists(pObj, ObjList); - // now apply the bonus from the scope we use - sScopebonus += BonusReduceMore( - NightBonusScale( Item[ObjList[pSoldier->bScopeMode]->usItem].cavevisionrangebonus, bLightLevel ), - (*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus ); + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == pObj ) + // now apply the bonus from the scope we use + sScopebonus += BonusReduceMore( + NightBonusScale( Item[ObjList[pSoldier->bScopeMode]->usItem].cavevisionrangebonus, bLightLevel ), + (*ObjList[pSoldier->bScopeMode])[0]->data.objectStatus ); } } else @@ -10361,10 +10371,12 @@ INT16 GetDayVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel ) std::map 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 ); + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == pObj ) + // 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 @@ -10461,10 +10473,12 @@ INT16 GetBrightLightVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel std::map 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 ); + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == pObj ) + // 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 @@ -10598,8 +10612,10 @@ UINT8 GetPercentTunnelVision( SOLDIERTYPE * pSoldier ) std::map ObjList; GetScopeLists(pObj, ObjList); - // now apply the bonus from the scope we use - bonus += Item[ObjList[pSoldier->bScopeMode]->usItem].percenttunnelvision; + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == pObj ) + // now apply the bonus from the scope we use + bonus += Item[ObjList[pSoldier->bScopeMode]->usItem].percenttunnelvision; } } else @@ -11629,7 +11645,9 @@ INT16 GetMinRangeForAimBonus( SOLDIERTYPE* pSoldier, OBJECTTYPE * pObj ) std::map ObjList; GetScopeLists(pObj, ObjList); - bonus = Item[ObjList[pSoldier->bScopeMode]->usItem].minrangeforaimbonus; + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == pObj ) + bonus = Item[ObjList[pSoldier->bScopeMode]->usItem].minrangeforaimbonus; } else bonus = Item[pObj->usItem].minrangeforaimbonus; @@ -11658,8 +11676,10 @@ FLOAT GetScopeMagnificationFactor( SOLDIERTYPE *pSoldier, OBJECTTYPE * pObj, FLO std::map ObjList; GetScopeLists(pObj, ObjList); - // now apply the bonus from the scope we use - BestFactor = Item[ObjList[pSoldier->bScopeMode]->usItem].scopemagfactor; + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == pObj ) + // now apply the bonus from the scope we use + BestFactor = Item[ObjList[pSoldier->bScopeMode]->usItem].scopemagfactor; return __max(1.0f, BestFactor); } @@ -11699,8 +11719,12 @@ FLOAT GetBestScopeMagnificationFactor( SOLDIERTYPE *pSoldier, OBJECTTYPE * pObj, std::map ObjList; GetScopeLists(pObj, ObjList); - // now apply the bonus from the scope we use - return max(1.0f, Item[ObjList[pSoldier->bScopeMode]->usItem].scopemagfactor); + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == pObj ) + // now apply the bonus from the scope we use + return max(1.0f, Item[ObjList[pSoldier->bScopeMode]->usItem].scopemagfactor); + else + return( 1.0f ); } FLOAT BestFactor = 1.0; @@ -12072,7 +12096,9 @@ UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier, INT32 sGridNo) std::map ObjList; GetScopeLists(&pSoldier->inv[pSoldier->ubAttackingHand], ObjList); - sScopeBonus = Item[ObjList[pSoldier->bScopeMode]->usItem].aimbonus; + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == &pSoldier->inv[pSoldier->ubAttackingHand] ) + sScopeBonus = Item[ObjList[pSoldier->bScopeMode]->usItem].aimbonus; } else sScopeBonus = GetBaseScopeAimBonus( &pSoldier->inv[pSoldier->ubAttackingHand], uiRange ); @@ -12140,7 +12166,9 @@ UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier, INT32 sGridNo) std::map ObjList; GetScopeLists(pAttackingWeapon, ObjList); - sScopeBonus = Item[ObjList[pSoldier->bScopeMode]->usItem].aimbonus; + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pSoldier->inv[HANDPOS]) == pAttackingWeapon ) + sScopeBonus = Item[ObjList[pSoldier->bScopeMode]->usItem].aimbonus; } else sScopeBonus = gGameExternalOptions.fAimLevelsDependOnDistance ? GetBaseScopeAimBonus( pAttackingWeapon, uiRange ) : GetBaseScopeAimBonus( pAttackingWeapon, 25000 ); @@ -12989,7 +13017,20 @@ void GetScopeLists( OBJECTTYPE * pObj, std::map& arScopeMap BOOLEAN IsAttachmentClass( UINT16 usItem, UINT32 aFlag ) { - return( Item[usItem].attachmentclass & aFlag ); + return( (Item[usItem].attachmentclass & aFlag) != 0 ); +} + +BOOLEAN HasAttachmentOfClass( OBJECTTYPE * pObj, UINT32 aFlag ) +{ + // check all attachments + attachmentList::iterator iterend = (*pObj)[0]->attachments.end(); + for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter) + { + if ( iter->exists() && IsAttachmentClass( iter->usItem, aFlag ) ) + return( TRUE ); + } + + return( FALSE ); } /////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Tactical/Items.h b/Tactical/Items.h index 2585339e..d5d18f00 100644 --- a/Tactical/Items.h +++ b/Tactical/Items.h @@ -450,6 +450,7 @@ void GetScopeLists( OBJECTTYPE * pObj, std::map& arScopeMap // check if item belongs to a specific attachemnt class BOOLEAN IsAttachmentClass( UINT16 usItem, UINT32 aFlag ); +BOOLEAN HasAttachmentOfClass( OBJECTTYPE * pObj, UINT32 aFlag ); #endif diff --git a/Tactical/LOS.cpp b/Tactical/LOS.cpp index ec00edbf..ab3467c5 100644 --- a/Tactical/LOS.cpp +++ b/Tactical/LOS.cpp @@ -7152,7 +7152,9 @@ FLOAT CalcProjectionFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2 std::map ObjList; GetScopeLists(pWeapon, ObjList); - iProjectionFactor = Item[ObjList[pShooter->bScopeMode]->usItem].projectionfactor; + // only use scope mode if gun is in hand, otherwise an error might occur! + if ( (&pShooter->inv[HANDPOS]) == pWeapon ) + iProjectionFactor = Item[ObjList[pShooter->bScopeMode]->usItem].projectionfactor; } else iProjectionFactor = GetProjectionFactor( pWeapon ); diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 53e3b542..90cfadb4 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -9330,7 +9330,13 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr // OK, drop item in main hand... if ( this->inv[ HANDPOS ].exists() == true ) { - if ( !( this->inv[ HANDPOS ].fFlags & OBJECT_UNDROPPABLE ) ) + // Flugente: If item has an attached rifle sling, place it the sling position instead + int bSlot = GUNSLINGPOCKPOS; + if ( HasAttachmentOfClass(&(this->inv[ HANDPOS ]), AC_SLING) && TryToPlaceInSlot(this, &(this->inv[ HANDPOS ]), FALSE, bSlot, GUNSLINGPOCKPOS) ) + { + ; + } + else if ( !( this->inv[ HANDPOS ].fFlags & OBJECT_UNDROPPABLE ) ) { // ATE: if our guy, make visible.... if ( this->bTeam == gbPlayerNum ) diff --git a/TileEngine/Explosion Control.cpp b/TileEngine/Explosion Control.cpp index 54a70827..ec7809b1 100644 --- a/TileEngine/Explosion Control.cpp +++ b/TileEngine/Explosion Control.cpp @@ -3615,11 +3615,20 @@ 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) + UINT8 feasibletripwiredirections[4] = { + NORTH, + EAST, + SOUTH, + WEST + }; + + // for every orientation + for (UINT8 i = 0; i < 4; ++i) + { + UINT8 direction = feasibletripwiredirections[i]; // get adjacent grid - UINT32 adjgrid = NewGridNo( sGridNo, DirectionInc( ort ) ); + UINT32 adjgrid = NewGridNo( sGridNo, DirectionInc( direction ) ); // if there is a bomb at that grid and level, and it isn't disabled for (UINT32 uiWorldBombIndex = 0; uiWorldBombIndex < guiNumWorldBombs; uiWorldBombIndex++) @@ -3640,13 +3649,17 @@ BOOLEAN ActivateSurroundingTripwire( UINT8 ubID, INT32 sGridNo, INT8 bLevel ) // 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 ) + + // if no other bomb exists here + if ( FindWorldItemForBombInGridNo(adjgrid, bLevel) == -1 ) { - RemoveBlueFlag( adjgrid, 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); } - 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 ); @@ -4008,13 +4021,17 @@ BOOLEAN SetOffBombsInGridNo( UINT8 ubID, INT32 sGridNo, BOOLEAN fAllBombs, INT8 // 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 ) + + // if no other bomb exists here + if ( FindWorldItemForBombInGridNo(sGridNo, bLevel) == -1 ) { - RemoveBlueFlag( sGridNo, 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); } - 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 ); diff --git a/Utils/XML_Items.cpp b/Utils/XML_Items.cpp index c1a2d8e6..8f9e3b9b 100644 --- a/Utils/XML_Items.cpp +++ b/Utils/XML_Items.cpp @@ -1900,10 +1900,10 @@ BOOLEAN WriteItemStats() FilePrintf(hFile,"\t\t%4.2f\r\n", Item[cnt].overheatJamThresholdModificator ); FilePrintf(hFile,"\t\t%4.2f\r\n", Item[cnt].overheatDamageThresholdModificator ); - FilePrintf(hFile,"\t\t%4.2f\r\n", Item[cnt].attachmentclass ); + FilePrintf(hFile,"\t\t%4.2f\r\n", Item[cnt].attachmentclass ); - FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].tripwireactivation ); - FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].tripwire ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].tripwireactivation ); + FilePrintf(hFile,"\t\t%d\r\n", Item[cnt].tripwire ); FilePrintf(hFile,"\t\r\n"); }