mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
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:
+63
-20
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
@@ -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 )
|
||||
|
||||
Reference in New Issue
Block a user