mirror of
https://github.com/1dot13/source.git
synced 2026-08-05 14:00:23 +02:00
HAM5.5b2 merged in!
Notes: -There may still be bugs!! (In fact, I almost guarantee it -- there's -Ammo box code added to HR's crate code -Splitting a crate/box also automatically refills half empty magazines -new pathing arrows for map screen not included -code for scouts to know where enemies are going doesn't appear to work... but i'm not sure it was completed. -lots of gobledy gook (chinese?) comments turned back to english -also added Bob's popups -other languages besides english still need to have there language.cpp files updated with array changes -AI enhancements by Warmsteel (reloading, suppression, roaming, avoiding gas, and other fixes) git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5181 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+251
-102
@@ -1747,9 +1747,19 @@ BOOLEAN UseGunNCTH( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
OBJECTTYPE* pA= &(*iter);
|
||||
if ( (*pA)[0]->data.objectStatus >=USABLE)
|
||||
{
|
||||
INT8 bAmmoReliability = Item[(*pObjAttHand)[0]->data.gun.usGunAmmoItem].bReliability;
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 *
|
||||
(Item[ iter->usItem ].bReliability + bAmmoReliability), 0);
|
||||
INT16 ammoReliability = Item[(*pObjAttHand)[0]->data.gun.usGunAmmoItem].bReliability;
|
||||
// HEADROCK HAM 5: Variable base chance
|
||||
if ( UsingNewCTHSystem() == true)
|
||||
{
|
||||
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
|
||||
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
|
||||
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * (Item[ iter->usItem ].bReliability + ammoReliability) );
|
||||
uiDepreciateTest = max(0, uiDepreciateTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDepreciateTest = max(0,BASIC_DEPRECIATE_CHANCE + 3 * (Item[ iter->usItem ].bReliability + ammoReliability));
|
||||
}
|
||||
if ( !PreRandom( uiDepreciateTest ) && ( (*pObjAttHand)[0]->data.objectStatus > 1) )
|
||||
(*pA)[0]->data.objectStatus--;
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"rel =%d ",Item[ iter->usItem ].bReliability );
|
||||
@@ -2107,8 +2117,18 @@ BOOLEAN UseGunNCTH( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
//}
|
||||
|
||||
// Flugente FTW 1: Added a malus to reliability for overheated guns
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * GetReliability( pObjAttHand ) - iOverheatReliabilityMalus, 0);
|
||||
|
||||
// HEADROCK HAM 5: Variable NCTH base change
|
||||
if ( UsingNewCTHSystem() == true)
|
||||
{
|
||||
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
|
||||
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
|
||||
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * GetReliability( &(pSoldier->inv[pSoldier->ubAttackingHand]) - iOverheatReliabilityMalus) );
|
||||
uiDepreciateTest = max(0, uiDepreciateTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * GetReliability( pObjAttHand ) - iOverheatReliabilityMalus, 0);
|
||||
}
|
||||
if ( !PreRandom( uiDepreciateTest ) && ( (*pObjAttHand)[0]->data.objectStatus > 1) )
|
||||
{
|
||||
(*pObjAttHand)[0]->data.objectStatus--;
|
||||
@@ -2284,9 +2304,19 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
OBJECTTYPE* pA= &(*iter);
|
||||
if ( (*pA)[0]->data.objectStatus >=USABLE)
|
||||
{
|
||||
INT8 bAmmoReliability = Item[(*pObjUsed)[0]->data.gun.usGunAmmoItem].bReliability;
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 *
|
||||
(Item[ iter->usItem ].bReliability + bAmmoReliability), 0);
|
||||
INT16 ammoReliability = Item[(*pObjUsed)[0]->data.gun.usGunAmmoItem].bReliability;
|
||||
// HEADROCK HAM 5: Variable base chance
|
||||
if ( UsingNewCTHSystem() == true )
|
||||
{
|
||||
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
|
||||
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
|
||||
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * (Item[ iter->usItem ].bReliability + ammoReliability) );
|
||||
uiDepreciateTest = __max(0, uiDepreciateTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDepreciateTest = __max(0,BASIC_DEPRECIATE_CHANCE + 3 * (Item[ iter->usItem ].bReliability + ammoReliability));
|
||||
}
|
||||
if ( !PreRandom( uiDepreciateTest ) && ( (*pObjUsed)[0]->data.objectStatus > 1) )
|
||||
(*pA)[0]->data.objectStatus--;
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"rel =%d ",Item[ iter->usItem ].bReliability );
|
||||
@@ -2675,7 +2705,17 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
*/
|
||||
|
||||
// Flugente FTW 1: Added a malus to reliability for overheated guns
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * ( GetReliability( pObjUsed ) ) - iOverheatReliabilityMalus, 0);
|
||||
if ( UsingNewCTHSystem() == true )
|
||||
{
|
||||
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
|
||||
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
|
||||
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * GetReliability( &(pSoldier->inv[ pSoldier->ubAttackingHand ])) - iOverheatReliabilityMalus);
|
||||
uiDepreciateTest = max(0, uiDepreciateTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * ( GetReliability( pObjUsed ) ) - iOverheatReliabilityMalus, 0);
|
||||
}
|
||||
|
||||
if ( !PreRandom( uiDepreciateTest ) && ( (*pObjUsed)[0]->data.objectStatus > 1) )
|
||||
{
|
||||
@@ -4003,14 +4043,27 @@ void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 s
|
||||
MakeNoise( ubAttackerID, pTargetSoldier->sGridNo, pTargetSoldier->pathing.bLevel, gpWorldLevelData[pTargetSoldier->sGridNo].ubTerrainID, Weapon[ usWeaponIndex ].ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
|
||||
// CALLAHAN START BUGFIX
|
||||
if ( EXPLOSIVE_GUN( usWeaponIndex ) || AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
|
||||
// Provisions for Fragments, which are resulting from a different weapon than the one we are holding in our hand.
|
||||
UINT8 ubAmmoType = 0;
|
||||
if ( pObj->usItem == usWeaponIndex )
|
||||
{
|
||||
ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Must be a fragment.
|
||||
ubAmmoType = Explosive[Item[usWeaponIndex].ubClassIndex].ubFragType;
|
||||
usWeaponIndex = 1; // Set to default gun.
|
||||
}
|
||||
|
||||
if ( EXPLOSIVE_GUN( usWeaponIndex ) || AmmoTypes[ubAmmoType].explosionSize > 1)
|
||||
// CALLAHAN END BUGFIX
|
||||
{
|
||||
// Reduce attacker count!
|
||||
//TODO: Madd --- I don't think this code will ever get called for the HE ammo -- the EXPLOSIVE_GUN check filters out regular guns
|
||||
// marke test mag ammo type: pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.ubGunAmmoType
|
||||
// 2cond 'or' added
|
||||
if ( Item[usWeaponIndex].rocketlauncher || AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1 )
|
||||
if ( Item[usWeaponIndex].rocketlauncher || AmmoTypes[ubAmmoType].explosionSize > 1 )
|
||||
{
|
||||
if ( Item[usWeaponIndex].singleshotrocketlauncher )
|
||||
{
|
||||
@@ -4032,15 +4085,16 @@ void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 s
|
||||
pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
}
|
||||
else if ( AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
|
||||
else if ( AmmoTypes[ubAmmoType].explosionSize > 1)
|
||||
{
|
||||
// re-routed the Highexplosive value to define exposion type
|
||||
IgniteExplosion( ubAttackerID, sXPos, sYPos, 0, GETWORLDINDEXFROMWORLDCOORDS( sYPos, sXPos ), AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].highExplosive , pTargetSoldier->pathing.bLevel );
|
||||
IgniteExplosion( ubAttackerID, sXPos, sYPos, 0, GETWORLDINDEXFROMWORLDCOORDS( sYPos, sXPos ), AmmoTypes[ubAmmoType].highExplosive , pTargetSoldier->pathing.bLevel );
|
||||
// pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
}
|
||||
else // tank cannon
|
||||
{
|
||||
// HEADROCK HAM 5 TODO: TANK_SHELL!
|
||||
IgniteExplosion( ubAttackerID, sXPos, sYPos, 0, GETWORLDINDEXFROMWORLDCOORDS( sYPos, sXPos ), TANK_SHELL, pTargetSoldier->pathing.bLevel );
|
||||
}
|
||||
|
||||
@@ -4088,10 +4142,29 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
pObj = MercPtrs[ ubAttackerID ]->GetUsedWeapon( &MercPtrs [ ubAttackerID ]->inv[MercPtrs[ubAttackerID]->ubAttackingHand] );
|
||||
|
||||
if ( fStopped && ubAttackerID != NOBODY )
|
||||
// Get attacker
|
||||
if (ubAttackerID != NOBODY)
|
||||
{
|
||||
pAttacker = MercPtrs[ ubAttackerID ];
|
||||
}
|
||||
|
||||
// HEADROCK HAM 5: Define differently for fragments
|
||||
UINT8 ubHitVolume = 0;
|
||||
UINT8 ubAmmoType = 0;
|
||||
|
||||
if (pBullet->fFragment)
|
||||
{
|
||||
ubHitVolume = 1;
|
||||
ubAmmoType = Explosive[Item[pBullet->fromItem].ubClassIndex].ubFragType;
|
||||
}
|
||||
else
|
||||
{
|
||||
ubHitVolume = Weapon[usWeaponIndex].ubHitVolume;
|
||||
ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
|
||||
}
|
||||
|
||||
if ( fStopped && ubAttackerID != NOBODY )
|
||||
{
|
||||
if ( pAttacker->ubOppNum != NOBODY )
|
||||
{
|
||||
// if it was another team shooting at someone under our control
|
||||
@@ -4124,11 +4197,11 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
|
||||
if (sZPos > WALL_HEIGHT)
|
||||
{
|
||||
MakeNoise( ubAttackerID, sGridNo, 1, gpWorldLevelData[sGridNo].ubTerrainID, Weapon[ usWeaponIndex ].ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
MakeNoise( ubAttackerID, sGridNo, 1, gpWorldLevelData[sGridNo].ubTerrainID, ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeNoise( ubAttackerID, sGridNo, 0, gpWorldLevelData[sGridNo].ubTerrainID, Weapon[ usWeaponIndex ].ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
MakeNoise( ubAttackerID, sGridNo, 0, gpWorldLevelData[sGridNo].ubTerrainID, ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4146,30 +4219,35 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
// Reduce attacker count!
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - end of LAW fire") );
|
||||
// FreeUpAttacker( ubAttackerID );
|
||||
if ( Item[usWeaponIndex].singleshotrocketlauncher )
|
||||
// HEADROCK HAM 5: Fragments fired by such weapons should not explode.
|
||||
if ( pBullet->fFragment == false)
|
||||
{
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, C1, (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
}
|
||||
// changed too to use 2 flag to determine
|
||||
else if ( !Item[usWeaponIndex].singleshotrocketlauncher && Item[usWeaponIndex].rocketlauncher)
|
||||
//there shouldn't be a way to enter here with an UnderBarrel weapon, so retaining original code :JMich
|
||||
{
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("StructureHit: RPG7 item: %d, Ammo: %d",pAttacker->inv[HANDPOS].usItem , pAttacker->inv[HANDPOS][0]->data.gun.usGunAmmoItem ) );
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem , (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
|
||||
//This is just to make multishot launchers work in semi auto. It's not really a permanent solution because it still doesn't allow autofire, but it will do for now.
|
||||
OBJECTTYPE * pLaunchable = FindLaunchableAttachment( &(pAttacker->inv[pAttacker->ubAttackingHand ]), pAttacker->inv[pAttacker->ubAttackingHand ].usItem );
|
||||
if(pLaunchable){
|
||||
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = pLaunchable->usItem;
|
||||
} else {
|
||||
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
if ( Item[usWeaponIndex].singleshotrocketlauncher )
|
||||
{
|
||||
// HEADROCK HAM 5 TODO: C1!!!
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, C1, (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
}
|
||||
// changed too to use 2 flag to determine
|
||||
else if ( !Item[usWeaponIndex].singleshotrocketlauncher && Item[usWeaponIndex].rocketlauncher)
|
||||
//there shouldn't be a way to enter here with an UnderBarrel weapon, so retaining original code :JMich
|
||||
{
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("StructureHit: RPG7 item: %d, Ammo: %d",pAttacker->inv[HANDPOS].usItem , pAttacker->inv[HANDPOS][0]->data.gun.usGunAmmoItem ) );
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem , (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
|
||||
//This is just to make multishot launchers work in semi auto. It's not really a permanent solution because it still doesn't allow autofire, but it will do for now.
|
||||
OBJECTTYPE * pLaunchable = FindLaunchableAttachment( &(pAttacker->inv[pAttacker->ubAttackingHand ]), pAttacker->inv[pAttacker->ubAttackingHand ].usItem );
|
||||
if(pLaunchable){
|
||||
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = pLaunchable->usItem;
|
||||
} else {
|
||||
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
}
|
||||
else if ( AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
|
||||
{
|
||||
// re-routed the Highexplosive value to define exposion type
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, AmmoTypes[ (*pObj)[0]->data.gun.ubGunAmmoType].highExplosive , (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
// pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
}
|
||||
else if ( AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
|
||||
{
|
||||
// re-routed the Highexplosive value to define exposion type
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, AmmoTypes[ (*pObj)[0]->data.gun.ubGunAmmoType].highExplosive , (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
// pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
|
||||
// Moved here to make sure ABC stays >0 until everything done
|
||||
@@ -4184,6 +4262,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
//DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - end of TANK fire") );
|
||||
//FreeUpAttacker( ubAttackerID );
|
||||
|
||||
// HEADROCK HAM 5 TODO: Tank shell!!
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, TANK_SHELL, (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
//FreeUpAttacker( (UINT8) ubAttackerID );
|
||||
|
||||
@@ -4202,67 +4281,83 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
DamageStructure( pStructure, (UINT8)iImpact, STRUCTURE_DAMAGE_GUNFIRE, sGridNo, sXPos, sYPos, ubAttackerID );
|
||||
}
|
||||
|
||||
switch( Weapon[ usWeaponIndex ].ubWeaponClass )
|
||||
// HEADROCK HAM 5: Fragments are not fired from guns, so they need a special case.
|
||||
if (pBullet->fFragment == false)
|
||||
{
|
||||
case HANDGUNCLASS:
|
||||
case RIFLECLASS:
|
||||
case SHOTGUNCLASS:
|
||||
case SMGCLASS:
|
||||
case MGCLASS:
|
||||
switch( Weapon[ usWeaponIndex ].ubWeaponClass )
|
||||
{
|
||||
case HANDGUNCLASS:
|
||||
case RIFLECLASS:
|
||||
case SHOTGUNCLASS:
|
||||
case SMGCLASS:
|
||||
case MGCLASS:
|
||||
|
||||
// Guy has missed, play random sound
|
||||
if ( MercPtrs[ ubAttackerID ]->bTeam == gbPlayerNum )
|
||||
{
|
||||
if ( !MercPtrs[ ubAttackerID ]->bDoBurst )
|
||||
// Guy has missed, play random sound
|
||||
if ( MercPtrs[ ubAttackerID ]->bTeam == gbPlayerNum )
|
||||
{
|
||||
if ( Random( 40 ) == 0 )
|
||||
if ( !MercPtrs[ ubAttackerID ]->bDoBurst )
|
||||
{
|
||||
MercPtrs[ ubAttackerID ]->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
|
||||
if ( Random( 40 ) == 0 )
|
||||
{
|
||||
MercPtrs[ ubAttackerID ]->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//fDoMissForGun = TRUE;
|
||||
//break;
|
||||
fDoMissForGun = TRUE;
|
||||
break;
|
||||
//fDoMissForGun = TRUE;
|
||||
//break;
|
||||
fDoMissForGun = TRUE;
|
||||
break;
|
||||
|
||||
case MONSTERCLASS:
|
||||
case MONSTERCLASS:
|
||||
|
||||
DoSpecialEffectAmmoMiss( ubAttackerID, sGridNo, sXPos, sYPos, sZPos, FALSE, TRUE, iBullet );
|
||||
|
||||
RemoveBullet( iBullet );
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - monster attack hit structure") );
|
||||
// FreeUpAttacker( (UINT8) ubAttackerID );
|
||||
|
||||
//PlayJA2Sample( SPIT_RICOCHET , RATE_11025, uiMissVolume, 1, SoundDir( sGridNo ) );
|
||||
break;
|
||||
|
||||
case KNIFECLASS:
|
||||
|
||||
// When it hits the ground, leave on map...
|
||||
if ( Item[ usWeaponIndex ].usItemClass == IC_THROWING_KNIFE )
|
||||
{
|
||||
// OK, have we hit ground?
|
||||
if ( usStructureID == INVALID_STRUCTURE_ID )
|
||||
{
|
||||
// Add item
|
||||
CreateItem( usWeaponIndex, bWeaponStatus, &gTempObject );
|
||||
|
||||
AddItemToPool( sGridNo, &gTempObject, -1 , 0, 0, -1 );
|
||||
|
||||
// Make team look for items
|
||||
NotifySoldiersToLookforItems( );
|
||||
}
|
||||
|
||||
if ( !fHitSameStructureAsBefore )
|
||||
{
|
||||
PlayJA2Sample( MISS_KNIFE, RATE_11025, uiMissVolume, 1, SoundDir( sGridNo ) );
|
||||
}
|
||||
DoSpecialEffectAmmoMiss( ubAttackerID, sGridNo, sXPos, sYPos, sZPos, FALSE, TRUE, iBullet );
|
||||
|
||||
RemoveBullet( iBullet );
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - knife attack hit structure") );
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - monster attack hit structure") );
|
||||
// FreeUpAttacker( (UINT8) ubAttackerID );
|
||||
}
|
||||
|
||||
//PlayJA2Sample( SPIT_RICOCHET , RATE_11025, uiMissVolume, 1, SoundDir( sGridNo ) );
|
||||
break;
|
||||
|
||||
case KNIFECLASS:
|
||||
|
||||
// When it hits the ground, leave on map...
|
||||
if ( Item[ usWeaponIndex ].usItemClass == IC_THROWING_KNIFE )
|
||||
{
|
||||
// OK, have we hit ground?
|
||||
if ( usStructureID == INVALID_STRUCTURE_ID )
|
||||
{
|
||||
// Add item
|
||||
CreateItem( usWeaponIndex, bWeaponStatus, &gTempObject );
|
||||
|
||||
AddItemToPool( sGridNo, &gTempObject, -1 , 0, 0, -1 );
|
||||
|
||||
// Make team look for items
|
||||
NotifySoldiersToLookforItems( );
|
||||
}
|
||||
|
||||
if ( !fHitSameStructureAsBefore )
|
||||
{
|
||||
PlayJA2Sample( MISS_KNIFE, RATE_11025, uiMissVolume, 1, SoundDir( sGridNo ) );
|
||||
}
|
||||
|
||||
RemoveBullet( iBullet );
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - knife attack hit structure") );
|
||||
// FreeUpAttacker( (UINT8) ubAttackerID );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( sZPos == 0 )
|
||||
{
|
||||
PlayJA2Sample( MISS_G2 , RATE_11025, 5, 1, SoundDir( sGridNo ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayJA2Sample( MISS_1 + Random(8), RATE_11025, 5, 1, SoundDir( sGridNo ) );
|
||||
}
|
||||
RemoveBullet( iBullet );
|
||||
}
|
||||
|
||||
if ( fDoMissForGun )
|
||||
@@ -8442,8 +8537,24 @@ INT32 TotalArmourProtection( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 u
|
||||
return( iTotalProtection );
|
||||
}
|
||||
|
||||
INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iOrigImpact, INT16 sHitBy, UINT8 * pubSpecial )
|
||||
// HEADROCK HAM 5: Added argument the bullet!
|
||||
INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iOrigImpact, INT16 sHitBy, UINT8 * pubSpecial )
|
||||
{
|
||||
UINT16 usAttackingWeapon = 0;
|
||||
INT32 sOrigGridNo = 0;
|
||||
BOOLEAN fFragment = FALSE;
|
||||
if (pBullet == NULL)
|
||||
{
|
||||
usAttackingWeapon = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType;
|
||||
sOrigGridNo = pFirer->sGridNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
usAttackingWeapon = pBullet->fromItem;
|
||||
sOrigGridNo = pBullet->sOrigGridNo;
|
||||
fFragment = pBullet->fFragment;
|
||||
}
|
||||
|
||||
INT32 iImpact, iFluke, iBonus, iImpactForCrits = 0;
|
||||
INT8 bStatLoss = 0;
|
||||
UINT8 ubAmmoType;
|
||||
@@ -8452,17 +8563,21 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
// in MoveBullet.
|
||||
|
||||
// Set a few things up:
|
||||
if ( Item[ pFirer->usAttackingWeapon ].usItemClass == IC_THROWING_KNIFE )
|
||||
if ( Item[ usAttackingWeapon ].usItemClass == IC_THROWING_KNIFE )
|
||||
{
|
||||
ubAmmoType = AMMO_KNIFE;
|
||||
}
|
||||
else
|
||||
// HEADROCK HAM 5: Added provisions for fragments, which are not fired from the weapon in your hand.
|
||||
else if ( fFragment == FALSE )
|
||||
{
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
OBJECTTYPE* pObj = pFirer->GetUsedWeapon( &pFirer->inv[pFirer->ubAttackingHand] );
|
||||
|
||||
ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
|
||||
}
|
||||
else
|
||||
{
|
||||
ubAmmoType = Explosive[Item[usAttackingWeapon].ubClassIndex].ubFragType;
|
||||
}
|
||||
|
||||
if ( TANK( pTarget ) )
|
||||
{
|
||||
@@ -8569,7 +8684,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
}
|
||||
|
||||
// Sniper trait adds bonus damage per aim click
|
||||
if (HAS_SKILL_TRAIT( pFirer, SNIPER_NT ) && (pFirer->aiData.bAimTime >= gSkillTraitValues.ubSNDamageBonusFromNumClicks))
|
||||
if (HAS_SKILL_TRAIT( pFirer, SNIPER_NT ) && (pFirer->aiData.bAimTime >= gSkillTraitValues.ubSNDamageBonusFromNumClicks) && !fFragment)
|
||||
{
|
||||
iImpact += (INT32)(iImpact * (pFirer->aiData.bAimTime - gSkillTraitValues.ubSNDamageBonusFromNumClicks + 1) * gSkillTraitValues.ubSNDamageBonusPerClick * NUM_SKILL_TRAITS( pFirer, SNIPER_NT ))/100; // +5% per trait
|
||||
}
|
||||
@@ -8593,8 +8708,15 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
else if (pTarget->ubSoldierClass == SOLDIER_CLASS_ELITE && gGameExternalOptions.sEnemyEliteDamageResistance != 0)
|
||||
iImpact -= ((iImpact * gGameExternalOptions.sEnemyEliteDamageResistance) /100);
|
||||
|
||||
|
||||
iImpact = max( 1, iImpact);
|
||||
// HEADROCK HAM 5.1: Oh sandro, you rendered zerominimumdamage moot...
|
||||
if ( AmmoTypes[ubAmmoType].zeroMinimumDamage )
|
||||
{
|
||||
iImpact = __max( 0, iImpact );
|
||||
}
|
||||
else
|
||||
{
|
||||
iImpact = __max( 1, iImpact);
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -8622,7 +8744,15 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
case MIKE:
|
||||
// Only 1/2 of the bonus
|
||||
iImpact -= (INT32)(iImpact * gGameExternalOptions.usSpecialNPCStronger / 200);
|
||||
iImpact = max( 1, iImpact);
|
||||
// HEADROCK HAM 5.1: Oh sandro, you rendered zerominimumdamage moot...
|
||||
if ( AmmoTypes[ubAmmoType].zeroMinimumDamage )
|
||||
{
|
||||
iImpact = __max( 0, iImpact );
|
||||
}
|
||||
else
|
||||
{
|
||||
iImpact = __max( 1, iImpact);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -8631,7 +8761,16 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// STOMP traits - Bodybuilding damage resistance
|
||||
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pTarget, BODYBUILDING_NT ) )
|
||||
iImpact = max( 1, (INT32)(iImpact * (100 - gSkillTraitValues.ubBBDamageResistance) / 100));
|
||||
// HEADROCK HAM 5.1: Oh sandro, you rendered zerominimumdamage moot...
|
||||
if ( AmmoTypes[ubAmmoType].zeroMinimumDamage )
|
||||
{
|
||||
iImpact = __max( 0, (INT32)(iImpact * (100 - gSkillTraitValues.ubBBDamageResistance) / 100));
|
||||
}
|
||||
else
|
||||
{
|
||||
iImpact = __max( 1, (INT32)(iImpact * (100 - gSkillTraitValues.ubBBDamageResistance) / 100));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AdjustImpactByHitLocation( iImpact, ubHitLocation, &iImpact, &iImpactForCrits );
|
||||
@@ -8642,7 +8781,8 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
// is the blow deadly enough for an instant kill?
|
||||
// HEADROCK HAM 3.6: Reattached "Max Distance For Messy Death" tag from the XML! God knows why it wasn't attached when they MADE THAT TAG.
|
||||
//if ( PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= MAX_DISTANCE_FOR_MESSY_DEATH || (PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= MAX_BARRETT_DISTANCE_FOR_MESSY_DEATH && pFirer->usAttackingWeapon == BARRETT ))
|
||||
if ( PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= Weapon[ pFirer->usAttackingWeapon ].maxdistformessydeath )
|
||||
// HEADROCK HAM 5.1: Using usAttackingWeapon
|
||||
if ( PythSpacesAway( sOrigGridNo, pTarget->sGridNo ) <= Weapon[ usAttackingWeapon ].maxdistformessydeath )
|
||||
{
|
||||
if (iImpactForCrits > MIN_DAMAGE_FOR_INSTANT_KILL && iImpactForCrits < pTarget->stats.bLife)
|
||||
{
|
||||
@@ -8695,7 +8835,8 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
// since this value is much lower than the others, it only applies at short range...
|
||||
// HEADROCK HAM 3.6: Reattached "Max Distance For Messy Death" tag from the XML! God knows why it wasn't attached when they MADE THAT TAG.
|
||||
//if ( PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= MAX_DISTANCE_FOR_MESSY_DEATH || (PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= MAX_BARRETT_DISTANCE_FOR_MESSY_DEATH && pFirer->usAttackingWeapon == BARRETT ))
|
||||
if ( PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= Weapon[ pFirer->usAttackingWeapon ].maxdistformessydeath )
|
||||
// HEADROCK HAM 5.1: Using usAttackingWeapon
|
||||
if ( PythSpacesAway( sOrigGridNo, pTarget->sGridNo ) <= Weapon[ usAttackingWeapon ].maxdistformessydeath )
|
||||
{
|
||||
if (iImpact > MIN_DAMAGE_FOR_INSTANT_KILL && iImpact < pTarget->stats.bLife)
|
||||
{
|
||||
@@ -8741,7 +8882,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
if( !IsAutoResolveActive() )
|
||||
{
|
||||
|
||||
if ( AmmoTypes[ubAmmoType].knife && pFirer->aiData.bOppList[ pTarget->ubID ] == SEEN_CURRENTLY )
|
||||
if ( AmmoTypes[ubAmmoType].knife && pFirer->aiData.bOppList[ pTarget->ubID ] == SEEN_CURRENTLY && !fFragment )
|
||||
{
|
||||
// is this a stealth attack?
|
||||
if ( pTarget->aiData.bOppList[ pFirer->ubID ] == NOT_HEARD_OR_SEEN && !CREATURE_OR_BLOODCAT( pTarget )
|
||||
@@ -8793,10 +8934,18 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
|
||||
if (iImpactForCrits > 0 && iImpactForCrits < pTarget->stats.bLife && !(pTarget->flags.uiStatusFlags & SOLDIER_MONSTER) ) // not to monsters - SANDRO
|
||||
{
|
||||
UINT32 uiCritChance = (iImpactForCrits / 2) + (pFirer->aiData.bAimTime * 5);
|
||||
UINT32 uiCritChance = 0;
|
||||
if (fFragment)
|
||||
{
|
||||
uiCritChance = (iImpactForCrits / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiCritChance = (iImpactForCrits / 2) + (pFirer->aiData.bAimTime * 5);
|
||||
}
|
||||
BOOLEAN fMaliciousHit = FALSE;
|
||||
// SANDRO - Malicious characters inflict stat loss more often
|
||||
if ( gGameOptions.fNewTraitSystem && pFirer->ubProfile != NO_PROFILE )
|
||||
if ( gGameOptions.fNewTraitSystem && pFirer->ubProfile != NO_PROFILE && !fFragment)
|
||||
{
|
||||
if ( gMercProfiles[ pFirer->ubProfile ].bCharacterTrait == CHAR_TRAIT_MALICIOUS )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user