New feature: bear traps are mechanical traps that function like bombs, cause no explosion, can be reused, deal significant damage to legs and pin down the target.

GameDir >= r2338 is recommended.

For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&goto=346624&#msg_346624

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8287 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2016-08-12 20:48:34 +00:00
parent d000e8c1a3
commit c32bf09bbb
6 changed files with 252 additions and 47 deletions
+63 -20
View File
@@ -433,7 +433,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
{
// first shot using "virgin" gun... set imprint ID
pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.ubImprintID = pSoldier->ubProfile;
// this could be an NPC (Krott)
if (pSoldier->bTeam == gbPlayerNum)
{
@@ -1876,14 +1876,24 @@ void HandleSoldierDropBomb( SOLDIERTYPE *pSoldier, INT32 sGridNo )
// We have something... all we do is place...
if ( ArmBomb( &(pSoldier->inv[ HANDPOS ]), 0 ) )
{
// Snap: Do a skill check here as well
INT32 iResult = SkillCheck( pSoldier, PLANTING_BOMB_CHECK, 0 );
INT32 iResult = 0;
if ( HasItemFlag( (pSoldier->inv[HANDPOS]).usItem, BEARTRAP ) )
{
iResult = SkillCheck( pSoldier, PLANTING_MECHANICAL_BOMB_CHECK, 0 );
}
else
{
iResult = SkillCheck( pSoldier, PLANTING_BOMB_CHECK, 0 );
}
if ( iResult >= 0 )
{
// Less explosives gain for placing tripwire
if ( Item[ pSoldier->inv[ HANDPOS ].usItem ].tripwire )
StatChange( pSoldier, EXPLODEAMT, 1, FALSE );
else if ( HasItemFlag( (pSoldier->inv[HANDPOS]).usItem, BEARTRAP ) )
StatChange( pSoldier, MECHANAMT, 10, FALSE );
else
// EXPLOSIVES GAIN (25): Place a bomb, or buried and armed a mine
StatChange( pSoldier, EXPLODEAMT, 25, FALSE );
@@ -1935,6 +1945,10 @@ void HandleSoldierDropBomb( SOLDIERTYPE *pSoldier, INT32 sGridNo )
}
else
{
// beartraps don't explode...
if ( HasItemFlag( (pSoldier->inv[HANDPOS]).usItem, BEARTRAP ) )
return;
// EXPLOSIVES GAIN (10): Failed to place a bomb, or bury and arm a mine
StatChange( pSoldier, EXPLODEAMT, 10, FROM_FAILURE );
@@ -5357,6 +5371,10 @@ void BombMessageBoxCallBack( UINT8 ubExitValue )
{
iResult = SkillCheck( gpTempSoldier, PLANTING_REMOTE_BOMB_CHECK, 0 );
}
else if ( HasItemFlag( (gpTempSoldier->inv[HANDPOS]).usItem, BEARTRAP ) )
{
iResult = SkillCheck( gpTempSoldier, PLANTING_MECHANICAL_BOMB_CHECK, 0 );
}
else
{
iResult = SkillCheck( gpTempSoldier, PLANTING_BOMB_CHECK, 0 );
@@ -5367,12 +5385,18 @@ void BombMessageBoxCallBack( UINT8 ubExitValue )
// Less explosives gain for placing tripwire
if ( Item[ gpTempSoldier->inv[ HANDPOS ].usItem ].tripwire == 1 )
StatChange( gpTempSoldier, EXPLODEAMT, 5, FALSE );
else if ( HasItemFlag( (gpTempSoldier->inv[HANDPOS]).usItem, BEARTRAP ) )
StatChange( gpTempSoldier, MECHANAMT, 10, FALSE );
else
// EXPLOSIVES GAIN (25): Place a bomb, or buried and armed a mine
StatChange( gpTempSoldier, EXPLODEAMT, 25, FALSE );
}
else
{
// beartraps don't explode...
if ( HasItemFlag( (gpTempSoldier->inv[HANDPOS]).usItem, BEARTRAP ) )
return;
// EXPLOSIVES GAIN (10): Failed to place a bomb, or bury and arm a mine
StatChange( gpTempSoldier, EXPLODEAMT, 10, FROM_FAILURE );
@@ -5809,7 +5833,6 @@ void BoobyTrapMessageBoxCallBack( UINT8 ubExitValue )
if ( CheckBombDisarmChance() >= 0)
{
if ( gTempObject[0]->data.misc.ubBombOwner > 1 && ( (INT32)gTempObject[0]->data.misc.ubBombOwner - 2 >= gTacticalStatus.Team[ OUR_TEAM ].bFirstID && gTempObject[0]->data.misc.ubBombOwner - 2 <= gTacticalStatus.Team[ OUR_TEAM ].bLastID ) )
{
if ( gTempObject[0]->data.misc.ubBombOwner - 2 == gpBoobyTrapSoldier->ubID )
@@ -5979,9 +6002,12 @@ void BoobyTrapMessageBoxCallBack( UINT8 ubExitValue )
else
{
// oops! trap goes off
StatChange( gpBoobyTrapSoldier, EXPLODEAMT, (INT8) (3 * gbTrapDifficulty ), FROM_FAILURE );
gpBoobyTrapSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
if ( HasItemFlag( gTempObject.usItem, BEARTRAP ) )
return;
gpBoobyTrapSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
StatChange( gpBoobyTrapSoldier, EXPLODEAMT, (INT8)(3 * gbTrapDifficulty), FROM_FAILURE );
if (gfDisarmingBuriedBomb)
{
@@ -6019,18 +6045,28 @@ void BoobyTrapInMapScreenMessageBoxCallBack( UINT8 ubExitValue )
if (ubExitValue == MSG_BOX_RETURN_YES)
{
INT32 iCheckResult;
iCheckResult = SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 0 );
if ( HasItemFlag( gpItemPointer->usItem, BEARTRAP ) )
{
iCheckResult = SkillCheck( gpBoobyTrapSoldier, DISARM_MECHANICAL_TRAP_CHECK, 0 );
}
else
{
iCheckResult = SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 0 );
}
if (iCheckResult >= 0)
{
// disarmed a boobytrap!
StatChange( gpBoobyTrapSoldier, EXPLODEAMT, (UINT16) (6 * gbTrapDifficulty), FALSE );
if ( HasItemFlag( gpItemPointer->usItem, BEARTRAP ) )
StatChange( gpBoobyTrapSoldier, MECHANAMT, (3 * gbTrapDifficulty), FALSE );
else
StatChange( gpBoobyTrapSoldier, EXPLODEAMT, (UINT16) (6 * gbTrapDifficulty), FALSE );
// SANDRO - merc records - trap removal count
if ( gpBoobyTrapSoldier->ubProfile != NO_PROFILE )
gMercProfiles[ gpBoobyTrapSoldier->ubProfile ].records.usTrapsRemoved++;
// have merc say this is good
gpBoobyTrapSoldier->DoMercBattleSound( BATTLE_SOUND_COOL1 );
@@ -6074,10 +6110,14 @@ void BoobyTrapInMapScreenMessageBoxCallBack( UINT8 ubExitValue )
else
{
// oops! trap goes off
StatChange( gpBoobyTrapSoldier, EXPLODEAMT, (INT8) (3 * gbTrapDifficulty ), FROM_FAILURE );
gpBoobyTrapSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
// beartraps don't explode...
if ( HasItemFlag( gpItemPointer->usItem, BEARTRAP ) )
return;
StatChange( gpBoobyTrapSoldier, EXPLODEAMT, (INT8) (3 * gbTrapDifficulty ), FROM_FAILURE );
if (gfDisarmingBuriedBomb)
{
SetOffBombsInGridNo( gpBoobyTrapSoldier->ubID, gsBoobyTrapGridNo, TRUE, gbBoobyTrapLevel );
@@ -8646,24 +8686,27 @@ INT32 GetFirstObjectInSectorPosition( UINT16 ausItem )
INT32 CheckBombDisarmChance(void)
{
INT8 diff = 0;
// NB owner grossness... bombs 'owned' by the enemy are stored with side value 1 in
// the map. So if we want to detect a bomb placed by the player, owner is > 1, and
// owner - 2 gives the ID of the character who planted it
if ( gTempObject[0]->data.misc.ubBombOwner > 1 && ( (INT32)gTempObject[0]->data.misc.ubBombOwner - 2 >= gTacticalStatus.Team[ OUR_TEAM ].bFirstID && gTempObject[0]->data.misc.ubBombOwner - 2 <= gTacticalStatus.Team[ OUR_TEAM ].bLastID ) )
{
// my own boobytrap!
if ( gTempObject[0]->data.misc.ubBombOwner - 2 == gpBoobyTrapSoldier->ubID )
{
// my own boobytrap!
return SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 40 );
}
diff = 40;
// our team's boobytrap!
else
{
// our team's boobytrap!
return SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 20 );
}
diff = 20;
}
return SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, 0 );
if ( HasItemFlag( gTempObject.usItem, BEARTRAP ) )
{
return SkillCheck( gpBoobyTrapSoldier, DISARM_MECHANICAL_TRAP_CHECK, diff );
}
return SkillCheck( gpBoobyTrapSoldier, DISARM_TRAP_CHECK, diff );
}
void ExtendedDisarmMessageBox(void)
+45 -26
View File
@@ -13718,6 +13718,10 @@ void BombInventoryMessageBoxCallBack( UINT8 ubExitValue )
{
iResult = SkillCheck( gpItemDescSoldier, PLANTING_REMOTE_BOMB_CHECK, 0 );
}
else if ( HasItemFlag( gpItemDescObject->usItem, BEARTRAP ) )
{
iResult = SkillCheck( gpItemDescSoldier, PLANTING_MECHANICAL_BOMB_CHECK, 0 );
}
else
{
iResult = SkillCheck( gpItemDescSoldier, PLANTING_BOMB_CHECK, 0 );
@@ -13725,11 +13729,18 @@ void BombInventoryMessageBoxCallBack( UINT8 ubExitValue )
if ( iResult >= 0 )
{
// EXPLOSIVES GAIN (25): Place a bomb, or buried and armed a mine
StatChange( gpItemDescSoldier, EXPLODEAMT, 25, FALSE );
if ( HasItemFlag( gpItemDescObject->usItem, BEARTRAP ) )
StatChange( gpItemDescSoldier, MECHANAMT, 10, FALSE );
else
// EXPLOSIVES GAIN (25): Place a bomb, or buried and armed a mine
StatChange( gpItemDescSoldier, EXPLODEAMT, 25, FALSE );
}
else
{
// beartraps don't explode...
if ( HasItemFlag( gpItemDescObject->usItem, BEARTRAP ) )
return;
// EXPLOSIVES GAIN (10): Failed to place a bomb, or bury and arm a mine
StatChange( gpItemDescSoldier, EXPLODEAMT, 10, FROM_FAILURE );
@@ -13834,54 +13845,57 @@ void BombInventoryDisArmMessageBoxCallBack( UINT8 ubExitValue )
return;
}
INT8 diff = 0;
// NB owner grossness... bombs 'owned' by the enemy are stored with side value 1 in
// the map. So if we want to detect a bomb placed by the player, owner is > 1, and
// owner - 2 gives the ID of the character who planted it
if ( (*gpItemDescObject)[0]->data.misc.ubBombOwner > 1 && ( (INT32)(*gpItemDescObject)[0]->data.misc.ubBombOwner - 2 >= gTacticalStatus.Team[ OUR_TEAM ].bFirstID && (*gpItemDescObject)[0]->data.misc.ubBombOwner - 2 <= gTacticalStatus.Team[ OUR_TEAM ].bLastID ) )
{
// Flugente: get a tripwire-related bonus if we have a wire cutter in our hands
INT8 wirecutterbonus = 0;
if ( ( (&gpItemDescSoldier->inv[HANDPOS])->exists() && Item[ gpItemDescSoldier->inv[HANDPOS].usItem ].wirecutters == 1 ) || ( (&gpItemDescSoldier->inv[SECONDHANDPOS])->exists() && Item[ gpItemDescSoldier->inv[SECONDHANDPOS].usItem ].wirecutters == 1 ) )
{
// + 10 if item gets activated by tripwire
if ( Item[gpItemDescObject->usItem].tripwireactivation == 1 )
wirecutterbonus += 10;
diff += 10;
// + 10 if item is tripwire
if ( Item[gpItemDescObject->usItem].tripwire == 1 )
wirecutterbonus += 10;
diff += 10;
}
// my own boobytrap!
if ( (*gpItemDescObject)[0]->data.misc.ubBombOwner - 2 == gpItemDescSoldier->ubID )
{
// my own boobytrap!
iCheckResult = SkillCheck( gpItemDescSoldier, DISARM_TRAP_CHECK, 40 + wirecutterbonus );
}
diff += 40;
// our team's boobytrap!
else
{
// our team's boobytrap!
iCheckResult = SkillCheck( gpItemDescSoldier, DISARM_TRAP_CHECK, 20 + wirecutterbonus );
}
diff += 20;
}
if ( HasItemFlag( gpItemDescObject->usItem, BEARTRAP ) )
{
iCheckResult = SkillCheck( gpItemDescSoldier, DISARM_MECHANICAL_TRAP_CHECK, diff );
}
else
{
iCheckResult = SkillCheck( gpItemDescSoldier, DISARM_TRAP_CHECK, 0 );
iCheckResult = SkillCheck( gpItemDescSoldier, DISARM_TRAP_CHECK, diff );
}
if (iCheckResult >= 0)
{
UINT16 gain = 0;
if ( (*gpItemDescObject)[0]->data.misc.ubBombOwner > 1 && ( (INT32)(*gpItemDescObject)[0]->data.misc.ubBombOwner - 2 >= gTacticalStatus.Team[ OUR_TEAM ].bFirstID && (*gpItemDescObject)[0]->data.misc.ubBombOwner - 2 <= gTacticalStatus.Team[ OUR_TEAM ].bLastID ) )
{
// disarmed our own boobytrap!
if ( (*gpItemDescObject)[0]->data.misc.ubBombOwner - 2 == gpItemDescSoldier->ubID )
{
// disarmed my own boobytrap!
StatChange( gpItemDescSoldier, EXPLODEAMT, (UINT16) (2 * trapdifficulty), FALSE );
gain = (UINT16)(2 * trapdifficulty);
}
else
{
// disarmed our team's boobytrap!
StatChange( gpItemDescSoldier, EXPLODEAMT, (UINT16) (4 * trapdifficulty), FALSE );
gain = (UINT16)(4 * trapdifficulty);
// SANDRO - merc records - trap removal count (don't count our own traps)
gMercProfiles[ gpItemDescSoldier->ubProfile ].records.usTrapsRemoved++;
@@ -13890,12 +13904,17 @@ void BombInventoryDisArmMessageBoxCallBack( UINT8 ubExitValue )
else
{
// disarmed a boobytrap!
StatChange( gpItemDescSoldier, EXPLODEAMT, (UINT16) (6 * trapdifficulty), FALSE );
gain = (UINT16)(6 * trapdifficulty);
// SANDRO - merc records - trap removal count
gMercProfiles[ gpItemDescSoldier->ubProfile ].records.usTrapsRemoved++;
}
if ( HasItemFlag( gpItemDescObject->usItem, BEARTRAP ) )
StatChange( gpItemDescSoldier, MECHANAMT, gain / 2, FALSE );
else
StatChange( gpItemDescSoldier, EXPLODEAMT, gain, FALSE );
// have merc say this is good
gpItemDescSoldier->DoMercBattleSound( BATTLE_SOUND_COOL1 );
@@ -13911,26 +13930,26 @@ void BombInventoryDisArmMessageBoxCallBack( UINT8 ubExitValue )
if ( (*gpItemDescObject).fFlags & OBJECT_ARMED_BOMB )
gpItemDescObject->fFlags &= ~( OBJECT_ARMED_BOMB );
/*if ( (*gpItemDescObject).fFlags & OBJECT_KNOWN_TO_BE_TRAPPED )
gpItemDescObject->fFlags &= ~( OBJECT_KNOWN_TO_BE_TRAPPED );*/
}
else
{
// oops! trap goes off
StatChange( gpItemDescSoldier, EXPLODEAMT, (INT8) (3 * trapdifficulty ), FROM_FAILURE );
gpItemDescSoldier->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
// beartraps don't explode...
if ( HasItemFlag( gpItemDescObject->usItem, BEARTRAP ) )
return;
StatChange( gpItemDescSoldier, EXPLODEAMT, (INT8) (3 * trapdifficulty ), FROM_FAILURE );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Disarming of bomb failed. Resulting explosion damages %s's inventory and health", gpItemDescSoldier->name );
INT8 screen = guiCurrentScreen;
if ( screen == GAME_SCREEN )
if ( guiCurrentScreen == GAME_SCREEN )
{
// ignite explosions manually - this item is not in the WorldBombs-structure, so we can't add it to the queue
IgniteExplosion( (*gpItemDescObject)[0]->data.misc.ubBombOwner - 2, gpItemDescSoldier->sX, gpItemDescSoldier->sY, (INT16) (gpWorldLevelData[gpItemDescSoldier->sGridNo].sHeight), gpItemDescSoldier->sGridNo, gpItemDescObject->usItem, gpItemDescSoldier->pathing.bLevel, gpItemDescSoldier->ubDirection, gpItemDescObject );
}
else if ( (screen == MAP_SCREEN) || (screen == MSG_BOX_SCREEN) )
else if ( guiCurrentScreen == MAP_SCREEN || guiCurrentScreen == MSG_BOX_SCREEN )
{
// no explosions in map screen - instead we simply damage the inventory and harm our health
gpItemDescSoldier->InventoryExplosion();
+1 -1
View File
@@ -733,7 +733,7 @@ extern OBJECTTYPE gTempObject;
// note that these should not be used to determine what kind of an attachment an item is, that is determined by attachmentclass and the AC_xxx flags above
//#define EMPTY_SANDBAG 0x00000001 //1
#define MANPAD 0x00000002 //2 // this item is a MAn-Portable Air-Defense System
//#define SHOVEL 0x00000004 //4 // a shovel is used for filling sandbags and other building-related tasks
#define BEARTRAP 0x00000004 //4 // a mechanical trap that does no explosion, but causes leg damage to whoever activates it
//#define CONCERTINA 0x00000008 //8
#define WATER_DRUM 0x00000010 //16 // water drums allow to refill canteens in the sector they are in
+51
View File
@@ -445,6 +445,14 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod )
iSkill = (iSkill + 100 * (iSkill / 25) ) / (iSkill / 25 + 1);
break;
case PLANTING_MECHANICAL_BOMB_CHECK:
iSkill = EffectiveMechanical( pSoldier ) * 3;
iSkill += EffectiveStrength(pSoldier, FALSE) * 5;
iSkill += EffectiveDexterity( pSoldier, FALSE ) * 1.5f;
iSkill += EffectiveExpLevel( pSoldier ) * 5;
iSkill = iSkill / 10; // bring the value down to a percentage
break;
case DISARM_TRAP_CHECK:
fForceDamnSound = TRUE;
@@ -565,6 +573,44 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod )
}
break;
case DISARM_MECHANICAL_TRAP_CHECK:
fForceDamnSound = TRUE;
// SANDRO - electronic traps are based more on mechanical skill
if ( gGameOptions.fNewTraitSystem)
{
// It is impossible without both skills
if ( (EffectiveMechanical( pSoldier ) <= 0) || (EffectiveStrength( pSoldier, FALSE ) <= 0) )
{
iSkill = 0;
break;
}
else
{
iSkill = EffectiveMechanical( pSoldier ) * 3;
iSkill += EffectiveStrength( pSoldier, FALSE ) * 5;
}
}
else
{
iSkill = __max( EffectiveMechanical( pSoldier ) , EffectiveStrength( pSoldier, FALSE ) ) * 7;
if ( iSkill == 0 )
{
break;
}
}
iSkill += EffectiveDexterity( pSoldier, FALSE ) * 1.5f;
iSkill += EffectiveExpLevel( pSoldier ) * 5;
iSkill = iSkill / 10; // bring the value down to a percentage
//JMich_SkillModifiers: Adding a Disarm Trap bonus
bSlot = FindDisarmKit( pSoldier);
if (bSlot != NO_SLOT)
{
iSkill += Item[pSoldier->inv[bSlot].usItem].DisarmModifier * pSoldier->inv[bSlot][0]->data.objectStatus / 100;
}
break;
case OPEN_WITH_CROWBAR:
// Add for crowbar...
//JMich_SkillModifiers: Changing the +20 to the crowbar's bonus.
@@ -708,8 +754,10 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod )
case ELECTRONIC_LOCKPICKING_CHECK:
case PLANTING_BOMB_CHECK:
case PLANTING_REMOTE_BOMB_CHECK:
case PLANTING_MECHANICAL_BOMB_CHECK:
case DISARM_TRAP_CHECK:
case DISARM_ELECTRONIC_TRAP_CHECK:
case DISARM_MECHANICAL_TRAP_CHECK:
case ATTACHING_SPECIAL_ITEM_CHECK:
case ATTACHING_SPECIAL_ELECTRONIC_ITEM_CHECK:
iChance -= 10;
@@ -725,8 +773,10 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod )
case ELECTRONIC_LOCKPICKING_CHECK:
case PLANTING_BOMB_CHECK:
case PLANTING_REMOTE_BOMB_CHECK:
case PLANTING_MECHANICAL_BOMB_CHECK:
case DISARM_TRAP_CHECK:
case DISARM_ELECTRONIC_TRAP_CHECK:
case DISARM_MECHANICAL_TRAP_CHECK:
case ATTACHING_SPECIAL_ITEM_CHECK:
case ATTACHING_SPECIAL_ELECTRONIC_ITEM_CHECK:
iChance += 5;
@@ -758,6 +808,7 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod )
case ELECTRONIC_LOCKPICKING_CHECK:
case DISARM_TRAP_CHECK:
case DISARM_ELECTRONIC_TRAP_CHECK:
case DISARM_MECHANICAL_TRAP_CHECK:
case OPEN_WITH_CROWBAR:
case SMASH_DOOR_CHECK:
case ATTACHING_SPECIAL_ITEM_CHECK:
+2
View File
@@ -39,6 +39,8 @@ enum SkillChecks
ATTACHING_SPECIAL_ELECTRONIC_ITEM_CHECK,
DISARM_ELECTRONIC_TRAP_CHECK,
ATTACH_POWER_PACK, // Flugente: attach a power pack to power armor
PLANTING_MECHANICAL_BOMB_CHECK,
DISARM_MECHANICAL_TRAP_CHECK,
} ;
+90
View File
@@ -67,6 +67,7 @@
#include "Text.h" // added by SANDRO
#include "campaign.h" // yet another one added
#include "CampaignStats.h" // added by Flugente
#include "Points.h" // added by Flugente
#endif
#include "Soldier Macros.h"
@@ -3956,6 +3957,95 @@ void HandleExplosionQueue( void )
RemoveItemFromPool( sGridNo, gWorldBombs[ uiWorldBombIndex ].iItemIndex, ubLevel );
}
// beartraps don't cause explosions, but cause special leg damage
else if ( HasItemFlag( pObj->usItem, BEARTRAP ) )
{
// play sound
UINT16 ubTypeID = Explosive[Item[pObj->usItem].ubClassIndex].ubAnimationID;
INT32 sSoundID = gExpAniData[ubTypeID].sExplosionSoundID;
// Randomize
if ( gExpAniData[ubTypeID].sAltExplosionSoundID > NO_ALT_SOUND && sSoundID < 0 )
sSoundID = gExpAniData[ubTypeID].sAltExplosionSoundID;
if ( sSoundID > NO_ALT_SOUND )
PlayJA2Sample( sSoundID, RATE_11025, SoundVolume( HIGHVOLUME, sGridNo ), 1, SoundDir( sGridNo ) );
UINT8 ubID = WhoIsThere2( sGridNo, ubLevel );
if ( ubID != NOBODY )
{
SOLDIERTYPE* pSoldier = MercPtrs[ubID];
INT16 damage = Explosive[Item[pObj->usItem].ubClassIndex].ubDamage * 0.67f + Random( Explosive[Item[pObj->usItem].ubClassIndex].ubDamage * 0.67f );
INT16 breathdamage = Explosive[Item[pObj->usItem].ubClassIndex].ubStunDamage * 0.67f + Random( Explosive[Item[pObj->usItem].ubClassIndex].ubStunDamage * 0.67f );
pSoldier->SoldierTakeDamage( 0, damage, breathdamage, TAKE_DAMAGE_EXPLOSION, NOBODY, sGridNo, 0, TRUE );
// play additional 'hit' sound
PlayJA2SampleFromFile( "Sounds\\beartrap_fleshhit.wav", RATE_11025, SoundVolume( HIGHVOLUME, sGridNo ), 1, SoundDir( sGridNo ) );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s activated %s!", pSoldier->GetName( ), Item[pObj->usItem].szItemName );
DeductPoints( pSoldier, 200, 0 );
SoldierCollapse( pSoldier );
// Flugente: disease
HandlePossibleInfection( pSoldier, NULL, INFECTION_TYPE_WOUND_AGI, 1.5f );
HandlePossibleInfection( pSoldier, NULL, INFECTION_TYPE_WOUND_AGI, 1.5f );
INT8 bStatLoss = min( 3 + Random( 5 ) + Random( 8 ), pSoldier->stats.bAgility - 1 );
if ( bStatLoss > 0 )
{
pSoldier->stats.bAgility -= bStatLoss;
// SANDRO - added this for healing lost stats feature
pSoldier->ubCriticalStatDamage[DAMAGED_STAT_AGILITY] += bStatLoss;
if ( pSoldier->ubProfile != NO_PROFILE )
{
gMercProfiles[pSoldier->ubProfile].bAgility = pSoldier->stats.bAgility;
}
if ( pSoldier->name[0] && pSoldier->bVisible == TRUE )
{
// make stat RED for a while...
pSoldier->timeChanges.uiChangeAgilityTime = GetJA2Clock( );
pSoldier->usValueGoneUp &= ~(AGIL_INCREASE);
if ( bStatLoss == 1 )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_LOSES_1_AGIL], pSoldier->GetName( ) );
}
else
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_LOSES_AGIL], pSoldier->GetName( ), bStatLoss );
}
}
}
}
// object can be used again
{
OBJECTTYPE newObject;
CreateItem( (*pObj)[0]->data.misc.usBombItem, (*pObj)[0]->data.objectStatus, &newObject );
// 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, ubLevel );
// if no other bomb exists here
CheckForBuriedBombsAndRemoveFlags( sGridNo, ubLevel );
// delete the flag, otherwise wire will only work once
(newObject)[0]->data.sObjectFlag &= ~TRIPWIRE_ACTIVATED;
// now add a tripwire item to the floor, simulating that activating tripwire deactivates it
AddItemToPool( sGridNo, &newObject, 1, ubLevel, 0, -1 );
}
}
// Flugente: handle tripwire gun traps here...
// tripwire gets called and activated in ActivateSurroundingTripwire
else if ( Item[pObj->usItem].tripwire == 1 )