FixFix: non-merc planted explosives that fire fragments caused crashes. A few functions had to be fixed.

Note: keep in mind that we cannot assume that BULLET's pFirer will be valid. Check wether ubFirerID is NOBODY first.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6776 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2014-01-19 14:14:30 +00:00
parent 4541487c3b
commit f5dfddb0fc
10 changed files with 281 additions and 254 deletions
+39 -38
View File
@@ -3716,55 +3716,56 @@ void send_bullet( BULLET * pBullet,UINT16 usHandItem )
void recieveBULLET(RPCParameters *rpcParameters)
{
netb_struct* netb = (netb_struct*)rpcParameters->input;
netb_struct* netb = (netb_struct*)rpcParameters->input;
INT32 net_iBullet=netb->net_bullet.iBullet;
INT32 net_iBullet=netb->net_bullet.iBullet;
SOLDIERTYPE * pFirer=MercPtrs[ netb->net_bullet.ubFirerID ];
SOLDIERTYPE * pFirer = NULL;
INT8 bTeam = OUR_TEAM;
if ( netb->net_bullet.ubFirerID != NOBODY )
{
pFirer = MercPtrs[ netb->net_bullet.ubFirerID ];
bTeam=pFirer->bTeam;
}
INT8 bTeam=pFirer->bTeam;
INT32 iBullet;
BULLET * pBullet;
iBullet = CreateBullet( netb->net_bullet.ubFirerID, 0, netb->net_bullet.usFlags,netb->usHandItem );
if (iBullet == -1)
{
BULLET * pBullet;
INT32 iBullet = CreateBullet( netb->net_bullet.ubFirerID, 0, netb->net_bullet.usFlags,netb->usHandItem );
#ifdef BETAVERSION
ScreenMsg( FONT_YELLOW, MSG_MPSYSTEM, L"Failed to create bullet");
if (iBullet == -1)
{
ScreenMsg( FONT_YELLOW, MSG_MPSYSTEM, L"Failed to create bullet");
}
#endif
}
//add bullet to bullet table for translation
bTable[bTeam][net_iBullet].remote_id = net_iBullet;
bTable[bTeam][net_iBullet].local_id = iBullet;
//add bullet to bullet table for translation
bTable[bTeam][net_iBullet].remote_id = net_iBullet;
bTable[bTeam][net_iBullet].local_id = iBullet;
pBullet = GetBulletPtr( iBullet );
pBullet = GetBulletPtr( iBullet );
//ScreenMsg( FONT_YELLOW, MSG_MPSYSTEM, L"Created Bullet Id: %d",iBullet);
//ScreenMsg( FONT_YELLOW, MSG_MPSYSTEM, L"Created Bullet Id: %d",iBullet);
pBullet->fCheckForRoof=netb->net_bullet.fCheckForRoof;
pBullet->qIncrX=netb->net_bullet.qIncrX;
pBullet->qIncrY=netb->net_bullet.qIncrY;
pBullet->qIncrZ=netb->net_bullet.qIncrZ;
pBullet->sHitBy=netb->net_bullet.sHitBy;
pBullet->ddHorizAngle=netb->net_bullet.ddHorizAngle;
pBullet->fAimed=netb->net_bullet.fAimed;
pBullet->ubItemStatus=netb->net_bullet.ubItemStatus;
pBullet->qCurrX=netb->net_bullet.qCurrX;
pBullet->qCurrY=netb->net_bullet.qCurrY;
pBullet->qCurrZ=netb->net_bullet.qCurrZ;
pBullet->iImpact=netb->net_bullet.iImpact;
pBullet->iRange=netb->net_bullet.iRange;
pBullet->sTargetGridNo=netb->net_bullet.sTargetGridNo;
pBullet->bStartCubesAboveLevelZ=netb->net_bullet.bStartCubesAboveLevelZ;
pBullet->bEndCubesAboveLevelZ=netb->net_bullet.bEndCubesAboveLevelZ;
pBullet->iDistanceLimit=netb->net_bullet.iDistanceLimit;
pBullet->fCheckForRoof=netb->net_bullet.fCheckForRoof;
pBullet->qIncrX=netb->net_bullet.qIncrX;
pBullet->qIncrY=netb->net_bullet.qIncrY;
pBullet->qIncrZ=netb->net_bullet.qIncrZ;
pBullet->sHitBy=netb->net_bullet.sHitBy;
pBullet->ddHorizAngle=netb->net_bullet.ddHorizAngle;
pBullet->fAimed=netb->net_bullet.fAimed;
pBullet->ubItemStatus=netb->net_bullet.ubItemStatus;
pBullet->qCurrX=netb->net_bullet.qCurrX;
pBullet->qCurrY=netb->net_bullet.qCurrY;
pBullet->qCurrZ=netb->net_bullet.qCurrZ;
pBullet->iImpact=netb->net_bullet.iImpact;
pBullet->iRange=netb->net_bullet.iRange;
pBullet->sTargetGridNo=netb->net_bullet.sTargetGridNo;
pBullet->bStartCubesAboveLevelZ=netb->net_bullet.bStartCubesAboveLevelZ;
pBullet->bEndCubesAboveLevelZ=netb->net_bullet.bEndCubesAboveLevelZ;
pBullet->iDistanceLimit=netb->net_bullet.iDistanceLimit;
FireBullet( pFirer, pBullet, FALSE );
FireBullet( pFirer->ubID, pBullet, FALSE );
}
void send_changestate (EV_S_CHANGESTATE * SChangeState)
+2 -2
View File
@@ -123,7 +123,7 @@ void send_disarm_explosive(UINT32 sGridNo, UINT32 uiWorldIndex, UINT8 ubID);
void OpenChatMsgBox(void);
INT8 FireBullet( SOLDIERTYPE * pFirer, BULLET * pBullet, BOOLEAN fFake );
INT8 FireBullet( UINT8 ubFirer, BULLET * pBullet, BOOLEAN fFake );
void reapplySETTINGS();
@@ -155,7 +155,7 @@ extern char cServerName[30];
// WANNE: This features seems to work without any errors, so it is enabled :)
#define ENABLE_MP_FRIENDLY_PLAYERS_SHARE_SAME_FOV
#define ENABLE_COLLISION (is_server && pBullet->pFirer->ubID<120) || (!is_server && is_client && pBullet->pFirer->ubID<20) || (!is_server && !is_client)
#define ENABLE_COLLISION (is_server && pBullet->ubFirerID<120) || (!is_server && is_client && pBullet->ubFirerID<20) || (!is_server && !is_client)
extern bool auto_retry;
extern int giNumTries;
+1 -1
View File
@@ -56,7 +56,7 @@ typedef struct
UINT32 uiLastUpdate;
UINT8 ubTilesPerUpdate;
UINT16 usClockTicksPerUpdate;
SOLDIERTYPE *pFirer;
SOLDIERTYPE *pFirer; // Flugente: WARNING! We cannot assume this will be valid. Check wether ubFirerID is NOBODY first
INT32 sOrigGridNo; // HEADROCK HAM 5.1: Original tile does not necessarily have to be the pFirer's tile
INT32 sTargetGridNo;
INT16 sHitBy;
+91 -77
View File
@@ -2332,7 +2332,6 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
INT32 iImpact, iDamage;
EV_S_WEAPONHIT SWeaponHit;
INT32 sRange;
SOLDIERTYPE * pFirer = pBullet->pFirer;
FLOAT dZPosRelToMerc;
UINT8 ubHitLocation = AIM_SHOT_RANDOM;
UINT8 ubAttackDirection;
@@ -2348,10 +2347,16 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
BOOLEAN fCanSpewBlood = FALSE;
INT8 bSpewBloodLevel;
SOLDIERTYPE * pFirer = NULL;
if ( pBullet->ubFirerID != NOBODY )
{
pFirer = pBullet->pFirer;
}
// HEADROCK HAM 5: Fragments read attacking weapon from explosive, not from firer. Theoretically,
// all bullets should read this value...
UINT16 usAttackingWeapon = 0;
if (pBullet->fFragment)
if ( pBullet->ubFirerID == NOBODY || pBullet->fFragment)
{
usAttackingWeapon = pBullet->fromItem;
}
@@ -2387,7 +2392,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
else if (pBullet->fFragment)
{
// Read ammo type from the explosive data.
ubAmmoType = Explosive[Item[pBullet->fromItem].ubClassIndex].ubFragType;
ubAmmoType = Explosive[Item[usAttackingWeapon].ubClassIndex].ubFragType;
}
else
{
@@ -2397,7 +2402,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
// HEADROCK HAM 5.1: This is an utter hack, but it may be necessary. This soldier is hit by a fragment,
// so he needs to have his animations be interruptible. This takes care of soldiers hitting themselves
// with their own fragments.
if (pBullet->fFragment && pTarget == pBullet->pFirer)
if ( pBullet->ubFirerID != NOBODY && pBullet->fFragment && pTarget == pBullet->pFirer)
{
if (pTarget->usAniCode >1)
{
@@ -2592,7 +2597,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
// Determine damage, checking guy's armour, etc
sRange = GetRangeInCellCoordsFromGridNoDiff( pBullet->sOrigGridNo, pTarget->sGridNo );
if ( gTacticalStatus.uiFlags & GODMODE && !(pFirer->flags.uiStatusFlags & SOLDIER_PC))
if ( gTacticalStatus.uiFlags & GODMODE && pBullet->ubFirerID != NOBODY && !(pFirer->flags.uiStatusFlags & SOLDIER_PC))
{
// in god mode, and firer is computer controlled
iImpact = 0;
@@ -2600,7 +2605,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
}
else if (fIntended)
{
if (pFirer->aiData.bOppList[pTarget->ubID] == SEEN_CURRENTLY)
if ( pBullet->ubFirerID != NOBODY && pFirer->aiData.bOppList[pTarget->ubID] == SEEN_CURRENTLY)
{
sHitBy = pBullet->sHitBy;
}
@@ -2622,7 +2627,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
iDamage = BulletImpact( pFirer, pBullet, pTarget, ubHitLocation, iImpact, sHitBy, &ubSpecial );
// handle hit here...
// HEADROCK HAM 5: Fragments not counted as shots.
if( ( pFirer->bTeam == 0 ) && !(pBullet->fFragment) )
if( pBullet->ubFirerID != NOBODY && pFirer->bTeam == OUR_TEAM && !(pBullet->fFragment) )
{
// SANDRO - new mercs' records
// if we shoot with buckshot or similar, do not count a hit for every pellet
@@ -2641,7 +2646,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
// intentionally shot
pTarget->flags.fIntendedTarget = TRUE;
if ( (pBullet->usFlags & BULLET_FLAG_BUCKSHOT) && ( pTarget->ubID == pFirer->ubTargetID ) )
if ( pBullet->ubFirerID != NOBODY && (pBullet->usFlags & BULLET_FLAG_BUCKSHOT) && ( pTarget->ubID == pFirer->ubTargetID ) )
{
pTarget->bNumPelletsHitBy++;
}
@@ -2656,7 +2661,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
// we aimed though, so now that the bullet hits the intended target, we can calculate extra experience
// based on the aiming value.
if (UsingNewCTHSystem() == true && pFirer->bTeam == gbPlayerNum && pBullet->fAimed) // Only for single shot, first bullet in volley, or first bullet in spread.
if ( UsingNewCTHSystem() && pBullet->ubFirerID != NOBODY && pFirer->bTeam == gbPlayerNum && pBullet->fAimed) // Only for single shot, first bullet in volley, or first bullet in spread.
{
UINT16 usExpGain = 10;
usExpGain = (usExpGain * pBullet->sHitBy) / 100;
@@ -2758,7 +2763,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
}
// check to see if someone was accidentally hit when no target was specified by the player
if ( pFirer->bTeam == gbPlayerNum && pFirer->ubTargetID == NOBODY && pTarget->aiData.bNeutral )
if ( pBullet->ubFirerID != NOBODY && pFirer->bTeam == gbPlayerNum && pFirer->ubTargetID == NOBODY && pTarget->aiData.bNeutral )
{
if ( pTarget->ubCivilianGroup == KINGPIN_CIV_GROUP || pTarget->ubCivilianGroup == HICKS_CIV_GROUP )
{
@@ -2770,30 +2775,28 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
// get touchy
pFirer->ubTargetID = pTarget->ubID;
}
}
// Send event for getting hit
memset( &(SWeaponHit), 0, sizeof( SWeaponHit ) );
SWeaponHit.usSoldierID = pTarget->ubID;
SWeaponHit.uiUniqueId = pTarget->uiUniqueSoldierIdValue;
SWeaponHit.uiUniqueId = pTarget->uiUniqueSoldierIdValue;
// HEADROCK HAM 5: Already defined.
SWeaponHit.usWeaponIndex = usAttackingWeapon;
SWeaponHit.sDamage = (INT16) iDamage;
SWeaponHit.sDamage = (INT16) iDamage;
// breath loss is based on original impact of bullet
SWeaponHit.sBreathLoss = (INT16) ( (iImpact * APBPConstants[BP_GET_WOUNDED] * (pTarget->bBreathMax * 100 - pTarget->sBreathRed)) / 10000 );
// HEADROCK HAM 5.1: Bullet data contains the correct original GridNo
SWeaponHit.usDirection = GetDirectionFromGridNo( pBullet->sOrigGridNo, pTarget );
SWeaponHit.sXPos = (INT16)pTarget->dXPos;
SWeaponHit.sYPos = (INT16)pTarget->dYPos;
SWeaponHit.sZPos = 20;
SWeaponHit.sRange = sRange;
SWeaponHit.ubAttackerID = pFirer->ubID;
SWeaponHit.fHit = TRUE;
SWeaponHit.ubLocation = ubHitLocation;
SWeaponHit.sXPos = (INT16)pTarget->dXPos;
SWeaponHit.sYPos = (INT16)pTarget->dYPos;
SWeaponHit.sZPos = 20;
SWeaponHit.sRange = sRange;
SWeaponHit.ubAttackerID = pBullet->ubFirerID;
SWeaponHit.fHit = TRUE;
SWeaponHit.ubLocation = ubHitLocation;
if ( (pFirer->bDoBurst) && (ubSpecial == FIRE_WEAPON_NO_SPECIAL) )
if ( pBullet->ubFirerID != NOBODY && pFirer->bDoBurst && (ubSpecial == FIRE_WEAPON_NO_SPECIAL) )
{
// the animation required by the bullet hit (head explosion etc) overrides the
// hit-by-a-burst animation
@@ -2826,7 +2829,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
// adjust for bullet going through person
iImpact -= CalcBodyImpactReduction( ubAmmoType, ubHitLocation );
// adjust for other side of armour!
iImpact -= TotalArmourProtection( pFirer, pTarget, ubHitLocation, iImpact, ubAmmoType );
iImpact -= TotalArmourProtection( pTarget, ubHitLocation, iImpact, ubAmmoType );
if (iImpact > 0)
{
pBullet->iImpact = (INT8) iImpact;
@@ -2905,7 +2908,7 @@ BOOLEAN BulletHitMerc( BULLET * pBullet, STRUCTURE * pStructure, BOOLEAN fIntend
return( fStopped );
}
void BulletHitStructure( BULLET * pBullet, UINT16 usStructureID, INT32 iImpact, SOLDIERTYPE * pFirer, FIXEDPT qCurrX, FIXEDPT qCurrY, FIXEDPT qCurrZ, BOOLEAN fStopped )
void BulletHitStructure( BULLET * pBullet, UINT16 usStructureID, INT32 iImpact, FIXEDPT qCurrX, FIXEDPT qCurrY, FIXEDPT qCurrZ, BOOLEAN fStopped )
{
EV_S_STRUCTUREHIT SStructureHit;
@@ -2915,10 +2918,10 @@ void BulletHitStructure( BULLET * pBullet, UINT16 usStructureID, INT32 iImpact,
// HEADROCK HAM 5.1: Bullet already contains this data...
SStructureHit.usWeaponIndex = pBullet->fromItem;
SStructureHit.bWeaponStatus = pBullet->ubItemStatus;
SStructureHit.ubAttackerID = pFirer->ubID;
SStructureHit.ubAttackerID = pBullet->ubFirerID;
SStructureHit.usStructureID = usStructureID;
SStructureHit.iImpact = iImpact;
SStructureHit.iBullet = pBullet->iBullet;
SStructureHit.iImpact = iImpact;
SStructureHit.iBullet = pBullet->iBullet;
if (is_networked)
SStructureHit.fStopped = fStopped;
@@ -2961,7 +2964,7 @@ void BulletMissed( BULLET *pBullet, SOLDIERTYPE * pFirer )
send_miss(&SMiss);
}
ShotMiss( pFirer->ubID, pBullet->iBullet );
ShotMiss( pBullet->ubFirerID, pBullet->iBullet );
}
UINT32 ChanceOfBulletHittingStructure( INT32 iDistance, INT32 iDistanceToTarget, INT16 sHitBy )
@@ -4048,7 +4051,8 @@ void CalculateFiringIncrementsSimple( DOUBLE ddHorizAngle, DOUBLE ddVerticAngle,
pBullet->qIncrY = FloatToFixed( (FLOAT) sin( ddHorizAngle ) );
pBullet->qIncrZ = FloatToFixed( (FLOAT) ( sin( ddVerticAngle ) / sin( (PI/2) - ddVerticAngle ) * HEIGHTUNITS_PER_CELL ) );//dnl ch60 010913
}
INT8 FireBullet( SOLDIERTYPE * pFirer, BULLET * pBullet, BOOLEAN fFake )
INT8 FireBullet( UINT8 ubFirer, BULLET * pBullet, BOOLEAN fFake )
{
//DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("FireBullet"));
@@ -4058,20 +4062,32 @@ INT8 FireBullet( SOLDIERTYPE * pFirer, BULLET * pBullet, BOOLEAN fFake )
pBullet->bLOSIndexY = CONVERT_WITHINTILE_TO_INDEX( FIXEDPT_TO_INT32( pBullet->qCurrY ) % CELL_Y_SIZE );
pBullet->iCurrCubesZ = CONVERT_HEIGHTUNITS_TO_INDEX( FIXEDPT_TO_INT32( pBullet->qCurrZ ) );
pBullet->iLoop = 1;
pBullet->pFirer = pFirer;
pBullet->iImpactReduction = 0;
pBullet->sGridNo = MAPROWCOLTOPOS( pBullet->iCurrTileY, pBullet->iCurrTileX );
if ( ubFirer != NOBODY )
pBullet->pFirer = MercPtrs[ ubFirer ];
else
pBullet->pFirer = NULL;
//DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("FireBullet: bullet info set"));
if (fFake)
{
pBullet->ubTargetID = pFirer->ubCTGTTargetID;
if ( ubFirer != NOBODY )
pBullet->ubTargetID = pBullet->pFirer->ubCTGTTargetID;
else
pBullet->ubTargetID = NOBODY;
return( CalcChanceToGetThrough( pBullet ) );
}
else
{
pBullet->ubTargetID = pFirer->ubTargetID;
if ( ubFirer != NOBODY )
pBullet->ubTargetID = pBullet->pFirer->ubTargetID;
else
pBullet->ubTargetID = NOBODY;
//if ( gGameSettings.fOptions[ TOPTION_HIDE_BULLETS ] )
//{
// pBullet->uiLastUpdate = 0;
@@ -4100,12 +4116,12 @@ INT8 FireBullet( SOLDIERTYPE * pFirer, BULLET * pBullet, BOOLEAN fFake )
// /////////////////////////////////////////////////////////////////////////////////////
//}
if ( Item[ pFirer->usAttackingWeapon ].usItemClass == IC_THROWING_KNIFE )
if ( ubFirer != NOBODY && Item[ pBullet->pFirer->usAttackingWeapon ].usItemClass == IC_THROWING_KNIFE )
{
pBullet->usClockTicksPerUpdate = 30;
}
// HEADROCK HAM 5: Bomb Fragments
else if (pBullet->fFragment)
else if (ubFirer == NOBODY && pBullet->fFragment)
{
pBullet->usClockTicksPerUpdate = 30;
}
@@ -4113,10 +4129,10 @@ INT8 FireBullet( SOLDIERTYPE * pFirer, BULLET * pBullet, BOOLEAN fFake )
{
//afp-start //always a fast bullet
if ( pBullet->usFlags & ( BULLET_FLAG_CREATURE_SPIT | BULLET_FLAG_KNIFE | BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME /*| BULLET_FLAG_TRACER*/ ) )
pBullet->usClockTicksPerUpdate = (Weapon[ pFirer->usAttackingWeapon ].ubBulletSpeed + GetBulletSpeedBonus(&pFirer->inv[pFirer->ubAttackingHand]) ) / 10;
pBullet->usClockTicksPerUpdate = (Weapon[ pBullet->pFirer->usAttackingWeapon ].ubBulletSpeed + GetBulletSpeedBonus(&pBullet->pFirer->inv[pBullet->pFirer->ubAttackingHand]) ) / 10;
else
if (gGameSettings.fOptions[TOPTION_ALTERNATE_BULLET_GRAPHICS])
pBullet->usClockTicksPerUpdate = (Weapon[ pFirer->usAttackingWeapon ].ubBulletSpeed + GetBulletSpeedBonus(&pFirer->inv[pFirer->ubAttackingHand]) ) / 10;
pBullet->usClockTicksPerUpdate = (Weapon[ pBullet->pFirer->usAttackingWeapon ].ubBulletSpeed + GetBulletSpeedBonus(&pBullet->pFirer->inv[pBullet->pFirer->ubAttackingHand]) ) / 10;
else
pBullet->usClockTicksPerUpdate = 1;
//afp-end
@@ -4597,7 +4613,7 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
}
if (fFake)
{
bCTGT = FireBullet( pFirer, pBullet, TRUE );
bCTGT = FireBullet( pFirer->ubID, pBullet, TRUE );
RemoveBullet( iBullet );
return( bCTGT );
}
@@ -4610,7 +4626,7 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
// }
//hayden
if(is_client)send_bullet( pBullet, usHandItem );
FireBullet( pFirer, pBullet, FALSE );
FireBullet( pFirer->ubID, pBullet, FALSE );
}
}
@@ -5103,7 +5119,7 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
}
if (fFake)
{
bCTGT = FireBullet( pFirer, pBullet, TRUE );
bCTGT = FireBullet( pFirer->ubID, pBullet, TRUE );
RemoveBullet( iBullet );
return( bCTGT );
}
@@ -5118,7 +5134,7 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
if(is_client)
send_bullet( pBullet, usHandItem );
FireBullet( pFirer, pBullet, FALSE );
FireBullet( pFirer->ubID, pBullet, FALSE );
}
}
@@ -5149,7 +5165,7 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
// Note that this function does not make provisions for Fake Firing. There is no need for it, and it would needlessly
// complicate things anyway.
// Also note we receive start coordinates from the bomb itself, because there's nowhere else to get them.
INT8 FireFragmentGivenTarget( SOLDIERTYPE * pThrower, FLOAT dStartX, FLOAT dStartY, FLOAT dStartZ, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usExplosiveItem )
INT8 FireFragmentGivenTarget( UINT8 ubOwner, FLOAT dStartX, FLOAT dStartY, FLOAT dStartZ, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usExplosiveItem )
{
// Artificial...
dStartZ++;
@@ -5214,7 +5230,7 @@ INT8 FireFragmentGivenTarget( SOLDIERTYPE * pThrower, FLOAT dStartX, FLOAT dStar
ubImpact =(UINT8) Explosive[Item[usExplosiveItem].ubClassIndex].ubFragDamage;
iBullet = CreateBullet( pThrower->ubID, false, usBulletFlags, usExplosiveItem );
iBullet = CreateBullet( ubOwner, false, usBulletFlags, usExplosiveItem );
if (iBullet == -1)
{
//DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Failed to create bullet") );
@@ -5289,7 +5305,7 @@ INT8 FireFragmentGivenTarget( SOLDIERTYPE * pThrower, FLOAT dStartX, FLOAT dStar
pBullet->fTracer = false;
if(is_client)send_bullet( pBullet, usExplosiveItem );
FireBullet( pThrower, pBullet, FALSE );
FireBullet( ubOwner, pBullet, FALSE );
/////////////////////////////////////////////////////////////////////////////////////
// SANDRO - new mercs' records
@@ -5759,7 +5775,7 @@ INT8 FireBulletGivenTargetTrapOnly( SOLDIERTYPE* pThrower, OBJECTTYPE* pObj, INT
}*/
if(is_client)send_bullet( pBullet, pObj->usItem );
FireBullet( pThrower, pBullet, FALSE );
FireBullet( pThrower->ubID, pBullet, FALSE );
}
///////////////////////// SOUND ////////////////////////////
@@ -6153,7 +6169,7 @@ void MoveBullet( INT32 iBullet )
{
// hit a roof
StopBullet( pBullet->iBullet );
BulletHitStructure( pBullet, 0, 0, pBullet->pFirer, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE );
BulletHitStructure( pBullet, 0, 0, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE );
return;
}
@@ -6201,7 +6217,7 @@ void MoveBullet( INT32 iBullet )
}
// this might be a close call
if ( MercPtrs[ pStructure->usStructureID ]->bTeam == gbPlayerNum && pBullet->pFirer->bTeam != gbPlayerNum && sDesiredLevel == MercPtrs[ pStructure->usStructureID ]->pathing.bLevel )
if ( pBullet->ubFirerID != NOBODY && MercPtrs[ pStructure->usStructureID ]->bTeam == gbPlayerNum && pBullet->pFirer->bTeam != gbPlayerNum && sDesiredLevel == MercPtrs[ pStructure->usStructureID ]->pathing.bLevel )
{
MercPtrs[ pStructure->usStructureID ]->flags.fCloseCall = TRUE;
}
@@ -6214,7 +6230,7 @@ void MoveBullet( INT32 iBullet )
// apply suppression, regardless of friendly or enemy
// except if friendly, not within a few tiles of shooter
if ( MercPtrs[ pStructure->usStructureID ]->bSide != pBullet->pFirer->bSide || pBullet->iLoop > MIN_DIST_FOR_SCARE_FRIENDS )
if ( pBullet->ubFirerID == NOBODY || MercPtrs[ pStructure->usStructureID ]->bSide != pBullet->pFirer->bSide || pBullet->iLoop > MIN_DIST_FOR_SCARE_FRIENDS )
{
// buckshot has only a 1 in 2 chance of applying a suppression point
// HEADROCK HAM 5: For NCTH, make pellets as effective as any other bullet.
@@ -6249,7 +6265,7 @@ void MoveBullet( INT32 iBullet )
// else fall through
default:
MercPtrs[pStructure->usStructureID]->ubSuppressionPoints++;
MercPtrs[pStructure->usStructureID]->ubSuppressorID = pBullet->pFirer->ubID;
MercPtrs[pStructure->usStructureID]->ubSuppressorID = pBullet->ubFirerID;
break;
}
}
@@ -6322,7 +6338,7 @@ void MoveBullet( INT32 iBullet )
if (ubTargetID != NOBODY)
{
pTarget = MercPtrs[ ubTargetID ];
if ( IS_MERC_BODY_TYPE( pTarget ) && pBullet->pFirer->bSide != pTarget->bSide )
if ( IS_MERC_BODY_TYPE( pTarget ) && (pBullet->ubFirerID == NOBODY || pBullet->pFirer->bSide != pTarget->bSide) )
{
// HEADROCK HAM 5: For NCTH, make pellets as effective as any other bullet.
BOOLEAN fInflictSuppression = FALSE;
@@ -6356,7 +6372,7 @@ void MoveBullet( INT32 iBullet )
// else fall through
default:
pTarget->ubSuppressionPoints++;
pTarget->ubSuppressorID = pBullet->pFirer->ubID;
pTarget->ubSuppressorID = pBullet->ubFirerID;
break;
}
}
@@ -6368,7 +6384,6 @@ void MoveBullet( INT32 iBullet )
pTarget->flags.fCloseCall = TRUE;
}
*/
}
}
}
@@ -6389,13 +6404,13 @@ void MoveBullet( INT32 iBullet )
//hayden not hit ground
if(ENABLE_COLLISION)
{
if (iCurrAboveLevelZ < 0)
{
// ground is in the way!
StopBullet( pBullet->iBullet );
BulletHitStructure( pBullet, INVALID_STRUCTURE_ID, 0, pBullet->pFirer, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE );
return;
}
if (iCurrAboveLevelZ < 0)
{
// ground is in the way!
StopBullet( pBullet->iBullet );
BulletHitStructure( pBullet, INVALID_STRUCTURE_ID, 0, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE );
return;
}
}
// check for the existence of structures
if (iNumLocalStructures == 0 && !pRoofStructure)
@@ -6447,20 +6462,20 @@ void MoveBullet( INT32 iBullet )
//hayden, stop hit ground
if(ENABLE_COLLISION)
{
if (pBullet->qCurrZ + pBullet->qIncrZ * iStepsToTravel < qLandHeight)
{
// WANNE - BMP: BUGFIX: Had to change abs to _abs64 because FIXEDPT is now INT64
//iStepsToTravel = __min( iStepsToTravel, abs( (pBullet->qCurrZ - qLandHeight) / pBullet->qIncrZ ) );
iStepsToTravel = __min( iStepsToTravel, _abs64( (pBullet->qCurrZ - qLandHeight) / pBullet->qIncrZ ) );
if (pBullet->qCurrZ + pBullet->qIncrZ * iStepsToTravel < qLandHeight)
{
// WANNE - BMP: BUGFIX: Had to change abs to _abs64 because FIXEDPT is now INT64
//iStepsToTravel = __min( iStepsToTravel, abs( (pBullet->qCurrZ - qLandHeight) / pBullet->qIncrZ ) );
iStepsToTravel = __min( iStepsToTravel, _abs64( (pBullet->qCurrZ - qLandHeight) / pBullet->qIncrZ ) );
pBullet->qCurrX += pBullet->qIncrX * iStepsToTravel;
pBullet->qCurrY += pBullet->qIncrY * iStepsToTravel;
pBullet->qCurrZ += pBullet->qIncrZ * iStepsToTravel;
pBullet->qCurrX += pBullet->qIncrX * iStepsToTravel;
pBullet->qCurrY += pBullet->qIncrY * iStepsToTravel;
pBullet->qCurrZ += pBullet->qIncrZ * iStepsToTravel;
StopBullet( pBullet->iBullet );
BulletHitStructure( pBullet, INVALID_STRUCTURE_ID, 0, pBullet->pFirer, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE );
return;
}
StopBullet( pBullet->iBullet );
BulletHitStructure( pBullet, INVALID_STRUCTURE_ID, 0, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE );
return;
}
}
// HEADROCK HAM B2.5: Changed condition to read fTracer flag directly from bullet's struct.
@@ -6542,7 +6557,7 @@ void MoveBullet( INT32 iBullet )
{
if (pStructure->fFlags & STRUCTURE_PERSON)
{
if(!(UsingNewCTHSystem() || pBullet->fFragment || (pBullet->usFlags & BULLET_FLAG_BUCKSHOT)) && fIntended && pBullet->sHitBy < 0 && pBullet->pFirer->ubTargetID == pStructure->usStructureID)//dnl ch60 010913 don't hit target if CTH roll decide to miss
if(!(UsingNewCTHSystem() || pBullet->fFragment || (pBullet->usFlags & BULLET_FLAG_BUCKSHOT)) && fIntended && pBullet->sHitBy < 0 && pBullet->ubFirerID != NOBODY && pBullet->pFirer->ubTargetID == pStructure->usStructureID)//dnl ch60 010913 don't hit target if CTH roll decide to miss
{
gpLocalStructure[iStructureLoop] = NULL;
//SendFmtMsg("shoot me, miss me, lucky me :-)");
@@ -6626,7 +6641,7 @@ void MoveBullet( INT32 iBullet )
// bullet must end here!
StopBullet( pBullet->iBullet );
BulletHitStructure( pBullet, pStructure->usStructureID, 1, pBullet->pFirer, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE );
BulletHitStructure( pBullet, pStructure->usStructureID, 1, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE );
return;
}
}
@@ -6703,13 +6718,13 @@ void MoveBullet( INT32 iBullet )
else if ( iRemainingImpact <= 0 )
{
StopBullet( pBullet->iBullet );
BulletHitStructure( pBullet, pStructure->usStructureID, 1, pBullet->pFirer, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE );
BulletHitStructure( pBullet, pStructure->usStructureID, 1, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE );
return;
}
else if (fHitStructure && (gubLocalStructureNumTimesHit[iStructureLoop] == 0) )
{
// play animation to indicate structure being hit
BulletHitStructure( pBullet, pStructure->usStructureID, 1, pBullet->pFirer, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, FALSE );
BulletHitStructure( pBullet, pStructure->usStructureID, 1, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, FALSE );
gubLocalStructureNumTimesHit[iStructureLoop] = 1;
}
}
@@ -6741,7 +6756,7 @@ void MoveBullet( INT32 iBullet )
if ( 1 /*HandleBulletStructureInteraction( pBullet, pRoofStructure, &fHitStructure ) <= 0 */)
{
StopBullet( pBullet->iBullet );
BulletHitStructure( pBullet, 0, 0, pBullet->pFirer, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE );
BulletHitStructure( pBullet, 0, 0, pBullet->qCurrX, pBullet->qCurrY, pBullet->qCurrZ, TRUE );
return;
}
/*
@@ -6839,7 +6854,7 @@ void MoveBullet( INT32 iBullet )
}
// check to see if bullet is close to target
if ( pBullet->pFirer->ubTargetID != NOBODY && !(pBullet->pFirer->flags.uiStatusFlags & SOLDIER_ATTACK_NOTICED) && PythSpacesAway( pBullet->sGridNo, pBullet->sTargetGridNo ) <= 3 )
if ( pBullet->ubFirerID != NOBODY && pBullet->pFirer->ubTargetID != NOBODY && !(pBullet->pFirer->flags.uiStatusFlags & SOLDIER_ATTACK_NOTICED) && PythSpacesAway( pBullet->sGridNo, pBullet->sTargetGridNo ) <= 3 )
{
pBullet->pFirer->flags.uiStatusFlags |= SOLDIER_ATTACK_NOTICED;
}
@@ -6847,7 +6862,6 @@ void MoveBullet( INT32 iBullet )
// unless the distance is integral, after the loop there will be a
// fractional amount of distance remaining which is unchecked
// but we shouldn't(?) need to check it because the target is there!
}
+1 -1
View File
@@ -68,7 +68,7 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
// HEADROCK HAM 4: Changed the name of one argument to avoid confusion with the new CTH system.
INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usHandItem, INT16 sApertureRatio, BOOLEAN fBuckshot, BOOLEAN fFake );
// HEADROCK HAM 5: Function for fragments ejected from an explosion.
INT8 FireFragmentGivenTarget( SOLDIERTYPE * pThrower, FLOAT dStartX, FLOAT dStartY, FLOAT dStartZ, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usExplosiveItem );
INT8 FireFragmentGivenTarget( UINT8 ubOwner, FLOAT dStartX, FLOAT dStartY, FLOAT dStartZ, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usExplosiveItem );
// Flugente: fire a shot from a gun that has no user (used for traps with attached guns)
INT8 FireBulletGivenTargetTrapOnly( SOLDIERTYPE* pThrower, OBJECTTYPE* pObj, INT32 gridno, FLOAT dStartZ, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, INT16 sHitBy);
+1 -1
View File
@@ -15949,7 +15949,7 @@ void SOLDIERTYPE::StartMultiTurnAction(UINT8 usActionType)
void SOLDIERTYPE::CancelMultiTurnAction(BOOLEAN fFinished)
{
// stop action
if ( !fFinished )
if ( !fFinished && this->usMultiTurnAction )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szMTATextStr[STR_MTA_CANCEL], this->GetName(), szMTATextStr[this->usMultiTurnAction] );
bOverTurnAPS = 0;
+136 -128
View File
@@ -4234,17 +4234,20 @@ BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
return( TRUE );
}
BOOLEAN DoSpecialEffectAmmoMiss( UINT8 ubAttackerID, INT32 sGridNo, INT16 sXPos, INT16 sYPos, INT16 sZPos, BOOLEAN fSoundOnly, BOOLEAN fFreeupAttacker, INT32 iBullet )
BOOLEAN DoSpecialEffectAmmoMiss( UINT8 ubAttackerID, UINT16 usWeaponIndex, INT32 sGridNo, INT16 sXPos, INT16 sYPos, INT16 sZPos, BOOLEAN fSoundOnly, BOOLEAN fFreeupAttacker, INT32 iBullet )
{
ANITILE_PARAMS AniParams;
UINT8 ubAmmoType;
UINT16 usItem;
UINT8 ubAmmoType = 0;
UINT16 usItem = usWeaponIndex;
// Flugente: check for underbarrel weapons and use that object if necessary
OBJECTTYPE* pObj = MercPtrs[ ubAttackerID ]->GetUsedWeapon( &MercPtrs[ ubAttackerID ]->inv[ MercPtrs[ ubAttackerID ]->ubAttackingHand ] );
if ( ubAttackerID != NOBODY )
{
OBJECTTYPE* pObj = MercPtrs[ ubAttackerID ]->GetUsedWeapon( &MercPtrs[ ubAttackerID ]->inv[ MercPtrs[ ubAttackerID ]->ubAttackingHand ] );
ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
usItem = (*pObj).usItem;
ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
usItem = (*pObj).usItem;
}
memset( &AniParams, 0, sizeof( ANITILE_PARAMS ) );
@@ -4252,14 +4255,14 @@ BOOLEAN DoSpecialEffectAmmoMiss( UINT8 ubAttackerID, INT32 sGridNo, INT16 sXPos,
{
if ( !fSoundOnly )
{
AniParams.sGridNo = sGridNo;
AniParams.sGridNo = sGridNo;
AniParams.ubLevelID = ANI_TOPMOST_LEVEL;
AniParams.sDelay = (INT16)( 100 );
AniParams.sDelay = (INT16)( 100 );
AniParams.sStartFrame = 0;
AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD | ANITILE_ALWAYS_TRANSLUCENT;
AniParams.sX = sXPos;
AniParams.sY = sYPos;
AniParams.sZ = sZPos;
AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD | ANITILE_ALWAYS_TRANSLUCENT;
AniParams.sX = sXPos;
AniParams.sY = sYPos;
AniParams.sZ = sZPos;
strcpy( AniParams.zCachedFile, "TILECACHE\\MINIBOOM.STI" );
@@ -4289,14 +4292,14 @@ BOOLEAN DoSpecialEffectAmmoMiss( UINT8 ubAttackerID, INT32 sGridNo, INT16 sXPos,
{
if ( !fSoundOnly )
{
AniParams.sGridNo = sGridNo;
AniParams.sGridNo = sGridNo;
AniParams.ubLevelID = ANI_TOPMOST_LEVEL;
AniParams.sDelay = (INT16)( 100 );
AniParams.sDelay = (INT16)( 100 );
AniParams.sStartFrame = 0;
AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD | ANITILE_ALWAYS_TRANSLUCENT;
AniParams.sX = sXPos;
AniParams.sY = sYPos;
AniParams.sZ = sZPos;
AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD | ANITILE_ALWAYS_TRANSLUCENT;
AniParams.sX = sXPos;
AniParams.sY = sYPos;
AniParams.sZ = sZPos;
strcpy( AniParams.zCachedFile, "TILECACHE\\ZGRAV_D.STI" );
@@ -4326,14 +4329,14 @@ BOOLEAN DoSpecialEffectAmmoMiss( UINT8 ubAttackerID, INT32 sGridNo, INT16 sXPos,
{
if ( !fSoundOnly )
{
AniParams.sGridNo = sGridNo;
AniParams.sGridNo = sGridNo;
AniParams.ubLevelID = ANI_TOPMOST_LEVEL;
AniParams.sDelay = (INT16)( 100 );
AniParams.sDelay = (INT16)( 100 );
AniParams.sStartFrame = 0;
AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD | ANITILE_ALWAYS_TRANSLUCENT;
AniParams.sX = sXPos;
AniParams.sY = sYPos;
AniParams.sZ = sZPos;
AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD | ANITILE_ALWAYS_TRANSLUCENT;
AniParams.sX = sXPos;
AniParams.sY = sYPos;
AniParams.sZ = sZPos;
strcpy( AniParams.zCachedFile, "TILECACHE\\ZGRAV_C.STI" );
@@ -4396,13 +4399,18 @@ BOOLEAN DoSpecialEffectAmmoMiss( UINT8 ubAttackerID, INT32 sGridNo, INT16 sXPos,
void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 sBreathLoss, UINT16 usDirection, INT16 sXPos, INT16 sYPos, INT16 sZPos, INT16 sRange , UINT8 ubAttackerID, BOOLEAN fHit, UINT8 ubSpecial, UINT8 ubHitLocation )
{
SOLDIERTYPE *pTargetSoldier, *pSoldier;
OBJECTTYPE *pObj;
// Get attacker
pSoldier = MercPtrs[ ubAttackerID ];
SOLDIERTYPE* pTargetSoldier = NULL;
SOLDIERTYPE* pSoldier = NULL;
OBJECTTYPE* pObj = NULL;
// Flugente: check for underbarrel weapons and use that object if necessary
pObj = pSoldier->GetUsedWeapon( &pSoldier->inv[pSoldier->ubAttackingHand] );
// Get attacker
if ( ubAttackerID != NOBODY )
{
pSoldier = MercPtrs[ ubAttackerID ];
// Flugente: check for underbarrel weapons and use that object if necessary
pObj = pSoldier->GetUsedWeapon( &pSoldier->inv[pSoldier->ubAttackingHand] );
}
// Get Target
pTargetSoldier = MercPtrs[ usSoldierID ];
@@ -4412,7 +4420,7 @@ void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 s
// CALLAHAN START BUGFIX
// 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 || EXPLOSIVE_GUN( usWeaponIndex )) // WANNE: This fixes the bug, that ONE shot LAWs do not explode on a direct target hit!
if ( pObj && (pObj->usItem == usWeaponIndex || EXPLOSIVE_GUN( usWeaponIndex ) ) ) // WANNE: This fixes the bug, that ONE shot LAWs do not explode on a direct target hit!
{
ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
}
@@ -4437,7 +4445,7 @@ void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 s
IgniteExplosion( ubAttackerID, sXPos, sYPos, 0, GETWORLDINDEXFROMWORLDCOORDS( sYPos, sXPos ), C1, pTargetSoldier->pathing.bLevel );
}
// changed rpg type to work only with two flags matching
else if ( !Item[usWeaponIndex].singleshotrocketlauncher && Item[usWeaponIndex].rocketlauncher)
else if ( pSoldier && !Item[usWeaponIndex].singleshotrocketlauncher && Item[usWeaponIndex].rocketlauncher)
//we shouldn't be able to have an underbarrel firing mode in this step, so we keep the original code :JMich
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("WeaponHit: RPG7 item: %d, Ammo: %d",pSoldier->inv[HANDPOS].usItem , pSoldier->inv[HANDPOS][0]->data.gun.usGunAmmoItem ) );
@@ -4446,9 +4454,12 @@ void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 s
//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( &(pSoldier->inv[pSoldier->ubAttackingHand ]), pSoldier->inv[pSoldier->ubAttackingHand ].usItem );
if(pLaunchable){
if(pLaunchable)
{
pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = pLaunchable->usItem;
} else {
}
else
{
pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
}
}
@@ -4471,14 +4482,14 @@ void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 s
return;
}
DoSpecialEffectAmmoMiss( ubAttackerID, pTargetSoldier->sGridNo, sXPos, sYPos, sZPos, FALSE, FALSE, 0 );
DoSpecialEffectAmmoMiss( ubAttackerID, usWeaponIndex, pTargetSoldier->sGridNo, sXPos, sYPos, sZPos, FALSE, FALSE, 0 );
// OK, SHOT HAS HIT, DO THINGS APPROPRIATELY
// ATE: This is 'cause of that darn smoke effect that could potentially kill
// the poor bastard .. so check
if ( !pTargetSoldier->flags.fDoingExternalDeath )
{
pTargetSoldier->EVENT_SoldierGotHit( usWeaponIndex, sDamage, sBreathLoss, usDirection, sRange, ubAttackerID, ubSpecial, ubHitLocation, 0, NOWHERE );
pTargetSoldier->EVENT_SoldierGotHit( usWeaponIndex, sDamage, sBreathLoss, usDirection, sRange, ubAttackerID, ubSpecial, ubHitLocation, 0, NOWHERE );
}
// else
// {
@@ -4502,17 +4513,16 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
BOOLEAN fHitSameStructureAsBefore;
BULLET * pBullet;
SOLDIERTYPE * pAttacker = NULL;
OBJECTTYPE * pObj;
OBJECTTYPE * pObj = NULL;
pBullet = GetBulletPtr( iBullet );
Assert(pBullet);
// Flugente: check for underbarrel weapons and use that object if necessary
pObj = MercPtrs[ ubAttackerID ]->GetUsedWeapon( &MercPtrs [ ubAttackerID ]->inv[MercPtrs[ubAttackerID]->ubAttackingHand] );
// Get attacker
if (ubAttackerID != NOBODY)
if ( ubAttackerID != NOBODY )
{
pObj = MercPtrs[ ubAttackerID ]->GetUsedWeapon( &MercPtrs [ ubAttackerID ]->inv[MercPtrs[ubAttackerID]->ubAttackingHand] );
pAttacker = MercPtrs[ ubAttackerID ];
}
@@ -4561,8 +4571,6 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
sGridNo = MAPROWCOLTOPOS( (sYPos/CELL_Y_SIZE), (sXPos/CELL_X_SIZE) );
if ( !fHitSameStructureAsBefore )
{
if (sZPos > WALL_HEIGHT)
{
MakeNoise( ubAttackerID, sGridNo, 1, gpWorldLevelData[sGridNo].ubTerrainID, ubHitVolume, NOISE_BULLET_IMPACT );
@@ -4571,18 +4579,19 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
{
MakeNoise( ubAttackerID, sGridNo, 0, gpWorldLevelData[sGridNo].ubTerrainID, ubHitVolume, NOISE_BULLET_IMPACT );
}
}
if (fStopped)
{
// marke need another attacker id assignment
SOLDIERTYPE *pSoldier;
SOLDIERTYPE *pSoldier = NULL;
// Get attacker
pSoldier = MercPtrs[ ubAttackerID ];
if ( ubAttackerID != NOBODY )
pSoldier = MercPtrs[ ubAttackerID ];
// marke added one 'or' to get this working with HE ammo
if ( Item[usWeaponIndex].rocketlauncher || AmmoTypes[ (*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
if ( Item[usWeaponIndex].rocketlauncher || (pObj && AmmoTypes[ (*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1 ))
{
// Reduce attacker count!
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - end of LAW fire") );
@@ -4596,7 +4605,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
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)
else if ( ubAttackerID != NOBODY && !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 ) );
@@ -4604,9 +4613,12 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
//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){
if(pLaunchable)
{
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = pLaunchable->usItem;
} else {
}
else
{
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
}
}
@@ -4661,7 +4673,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
case MGCLASS:
// Guy has missed, play random sound
if ( MercPtrs[ ubAttackerID ]->bTeam == gbPlayerNum )
if ( ubAttackerID != NOBODY && MercPtrs[ ubAttackerID ]->bTeam == gbPlayerNum )
{
if ( !MercPtrs[ ubAttackerID ]->bDoBurst )
{
@@ -4678,7 +4690,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
case MONSTERCLASS:
DoSpecialEffectAmmoMiss( ubAttackerID, sGridNo, sXPos, sYPos, sZPos, FALSE, TRUE, iBullet );
DoSpecialEffectAmmoMiss( ubAttackerID, usWeaponIndex, sGridNo, sXPos, sYPos, sZPos, FALSE, TRUE, iBullet );
RemoveBullet( iBullet );
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - monster attack hit structure") );
@@ -4769,7 +4781,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
UINT16 usItem = pBullet->fromItem;
if(usStructureID == INVALID_STRUCTURE_ID)
{
for(int i=0; i<MAXITEMS; i++)
for(int i=0; i<MAXITEMS; ++i)
if(Item[i].bloodieditem == pBullet->fromItem)
{
usItem = Item[i].uiIndex;// clean the blood from knife, actually this should be done during repair
@@ -4859,7 +4871,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
else
{
if ( !fStopped || !DoSpecialEffectAmmoMiss( ubAttackerID, sGridNo, sXPos, sYPos, sZPos, FALSE, TRUE, iBullet ) )
if ( !fStopped || !DoSpecialEffectAmmoMiss( ubAttackerID, usWeaponIndex, sGridNo, sXPos, sYPos, sZPos, FALSE, TRUE, iBullet ) )
{
if ( sZPos == 0 )
{
@@ -4882,13 +4894,13 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
// Add ripple
memset( &AniParams, 0, sizeof( ANITILE_PARAMS ) );
AniParams.sGridNo = sGridNo;
AniParams.ubLevelID = ANI_STRUCT_LEVEL;
AniParams.usTileType = THIRDMISS;
AniParams.usTileIndex = THIRDMISS1;
AniParams.sDelay = 50;
AniParams.sStartFrame = 0;
AniParams.uiFlags = ANITILE_FORWARD;
AniParams.sGridNo = sGridNo;
AniParams.ubLevelID = ANI_STRUCT_LEVEL;
AniParams.usTileType = THIRDMISS;
AniParams.usTileIndex = THIRDMISS1;
AniParams.sDelay = 50;
AniParams.sStartFrame = 0;
AniParams.uiFlags = ANITILE_FORWARD;
pNode = CreateAnimationTile( &AniParams );
@@ -4897,15 +4909,14 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
pNode->pLevelNode->sRelativeX = sXPos;
pNode->pLevelNode->sRelativeY = sYPos;
pNode->pLevelNode->sRelativeZ = sZPos;
}
memset( &AniParams, 0, sizeof( ANITILE_PARAMS ) );
AniParams.sGridNo = sGridNo;
AniParams.sGridNo = sGridNo;
AniParams.ubLevelID = ANI_STRUCT_LEVEL;
AniParams.usTileType = usMissTileType;
AniParams.usTileType = usMissTileType;
AniParams.usTileIndex = usMissTileIndex;
AniParams.sDelay = 80;
AniParams.sDelay = 80;
AniParams.sStartFrame = 0;
if (fStopped)
{
@@ -4932,12 +4943,9 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
// ATE: Show misses...( if our team )
if ( gGameSettings.fOptions[ TOPTION_SHOW_MISSES ] )
{
if ( ubAttackerID != NOBODY )
if ( ubAttackerID != NOBODY && MercPtrs[ ubAttackerID ]->bTeam == gbPlayerNum )
{
if ( MercPtrs[ ubAttackerID ]->bTeam == gbPlayerNum )
{
LocateGridNo( sGridNo );
}
LocateGridNo( sGridNo );
}
}
}
@@ -9191,7 +9199,7 @@ INT32 ArmourProtection( SOLDIERTYPE * pTarget, UINT16 ubArmourType, INT16 * pbSt
}
INT32 TotalArmourProtection( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iImpact, UINT8 ubAmmoType )
INT32 TotalArmourProtection( SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iImpact, UINT8 ubAmmoType )
{
INT32 iTotalProtection = 0, iSlot;
OBJECTTYPE * pArmour;
@@ -9207,7 +9215,6 @@ INT32 TotalArmourProtection( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 u
iTotalProtection += ArmourProtection( pTarget, (UINT8) pVehicleList[ pTarget->bVehicleID ].sArmourType, &bDummyStatus, iImpact, ubAmmoType, &dummyCoverage );
//pVehicleList[ pTarget->bVehicleID ].sExternalArmorLocationsStatus[ ubHitLocation ] = bDummyStatus;
}
else
{
@@ -9226,7 +9233,6 @@ INT32 TotalArmourProtection( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 u
default:
iSlot = VESTPOS;
break;
}
//zwwooooo - IoV: It can plates for the LBE bulletproof. Like CRIAS, MBSS, HSGI WASATCH...
@@ -9254,53 +9260,53 @@ INT32 TotalArmourProtection( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 u
if ( iImpact > iTotalProtection )
{
pArmour = &(pTarget->inv[ iSlot ]);
if (pArmour->exists() == true)
{
for (attachmentList::iterator iter = (*pArmour)[0]->attachments.begin(); iter != (*pArmour)[0]->attachments.end(); ++iter) {
if (Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 && iter->exists())
{
// bullet got through jacket; apply ceramic plate armour
iTotalProtection += ArmourProtection( pTarget, Item[iter->usItem].ubClassIndex, &((*iter)[0]->data.objectStatus), iImpact, ubAmmoType, &plateHit );
if ( (*iter)[0]->data.objectStatus < USABLE )
{
// destroy plates!
pArmour->RemoveAttachment(&(*iter));
DirtyMercPanelInterface( pTarget, DIRTYLEVEL2 );
//#ifdef ENGLISH
if ( pTarget->bTeam == gbPlayerNum )
{
// report plates destroyed!
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[61], pTarget->name );
}
//#endif
}
break;//original code only used the first ceramic plate
}
}
// if the plate didn't stop the bullet...
if ( iImpact > iTotalProtection )
pArmour = &(pTarget->inv[ iSlot ]);
if (pArmour->exists() == true)
{
iTotalProtection += ArmourProtection( pTarget, Item[pArmour->usItem].ubClassIndex, &((*pArmour)[0]->data.objectStatus), iImpact, ubAmmoType, &plateHit );
if ( (*pArmour)[0]->data.objectStatus < USABLE )
{
//Madd: put any attachments that someone might have added to the armour in the merc's inventory
for (attachmentList::iterator iter = (*pArmour)[0]->attachments.begin(); iter != (*pArmour)[0]->attachments.end(); ++iter) {
if ( !AutoPlaceObject( pTarget, &(*iter), FALSE ) && iter->exists())
{ // put it on the ground
AddItemToPool( pTarget->sGridNo, &(*iter), 1, pTarget->pathing.bLevel, 0 , -1 );
for (attachmentList::iterator iter = (*pArmour)[0]->attachments.begin(); iter != (*pArmour)[0]->attachments.end(); ++iter) {
if (Item[iter->usItem].usItemClass == IC_ARMOUR && (*iter)[0]->data.objectStatus > 0 && iter->exists())
{
// bullet got through jacket; apply ceramic plate armour
iTotalProtection += ArmourProtection( pTarget, Item[iter->usItem].ubClassIndex, &((*iter)[0]->data.objectStatus), iImpact, ubAmmoType, &plateHit );
if ( (*iter)[0]->data.objectStatus < USABLE )
{
// destroy plates!
pArmour->RemoveAttachment(&(*iter));
DirtyMercPanelInterface( pTarget, DIRTYLEVEL2 );
//#ifdef ENGLISH
if ( pTarget->bTeam == gbPlayerNum )
{
// report plates destroyed!
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[61], pTarget->name );
}
//#endif
}
break;//original code only used the first ceramic plate
}
}
DeleteObj( pArmour );//takes care of attachments, no need to remove() or erase()
DirtyMercPanelInterface( pTarget, DIRTYLEVEL2 );
// if the plate didn't stop the bullet...
if ( iImpact > iTotalProtection )
{
iTotalProtection += ArmourProtection( pTarget, Item[pArmour->usItem].ubClassIndex, &((*pArmour)[0]->data.objectStatus), iImpact, ubAmmoType, &plateHit );
if ( (*pArmour)[0]->data.objectStatus < USABLE )
{
//Madd: put any attachments that someone might have added to the armour in the merc's inventory
for (attachmentList::iterator iter = (*pArmour)[0]->attachments.begin(); iter != (*pArmour)[0]->attachments.end(); ++iter) {
if ( !AutoPlaceObject( pTarget, &(*iter), FALSE ) && iter->exists())
{ // put it on the ground
AddItemToPool( pTarget->sGridNo, &(*iter), 1, pTarget->pathing.bLevel, 0 , -1 );
}
}
DeleteObj( pArmour );//takes care of attachments, no need to remove() or erase()
DirtyMercPanelInterface( pTarget, DIRTYLEVEL2 );
}
}
}
}
}
}
return( iTotalProtection );
}
@@ -9310,7 +9316,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
UINT16 usAttackingWeapon = 0;
INT32 sOrigGridNo = 0;
BOOLEAN fFragment = FALSE;
if (pBullet == NULL)
if (pBullet == NULL && pFirer )
{
usAttackingWeapon = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType;
sOrigGridNo = pFirer->sGridNo;
@@ -9353,7 +9359,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
ubAmmoType = AMMO_KNIFE;
}
// HEADROCK HAM 5: Added provisions for fragments, which are not fired from the weapon in your hand.
else if ( fFragment == FALSE )
else if ( !fFragment && pFirer )
{
// Flugente: check for underbarrel weapons and use that object if necessary
OBJECTTYPE* pObj = pFirer->GetUsedWeapon( &pFirer->inv[pFirer->ubAttackingHand] );
@@ -9409,7 +9415,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
}
else
{
iImpact = iOrigImpact - TotalArmourProtection( pFirer, pTarget, ubHitLocation, iOrigImpact, ubAmmoType );
iImpact = iOrigImpact - TotalArmourProtection( pTarget, ubHitLocation, iOrigImpact, ubAmmoType );
}
// calc minimum damage
@@ -9431,7 +9437,6 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
{
iImpact += (pTarget->bNumPelletsHitBy - 1) / 2;
}
}
if (gfNextShotKills)
@@ -9468,7 +9473,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
//}
////////////////////////////////////////////////////////////////////////////////////
if ( gGameOptions.fNewTraitSystem ) // new traits bonuses - SANDRO
if ( gGameOptions.fNewTraitSystem && pFirer ) // new traits bonuses - SANDRO
{
// Throwing skill increases damage of knives here
if ( (ubAmmoType == AMMO_KNIFE) && HAS_SKILL_TRAIT( pFirer, THROWING_NT ))
@@ -9609,8 +9614,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
// don't do critical hits against people who are gonna die!
if( !IsAutoResolveActive() )
{
if ( AmmoTypes[ubAmmoType].knife && pFirer->aiData.bOppList[ pTarget->ubID ] == SEEN_CURRENTLY && !fFragment )
if ( AmmoTypes[ubAmmoType].knife && pFirer && 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 )
@@ -9673,7 +9677,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
}
BOOLEAN fMaliciousHit = FALSE;
// SANDRO - Malicious characters inflict stat loss more often
if ( gGameOptions.fNewTraitSystem && pFirer->ubProfile != NO_PROFILE && !fFragment)
if ( gGameOptions.fNewTraitSystem && pFirer && pFirer->ubProfile != NO_PROFILE && !fFragment)
{
if ( gMercProfiles[ pFirer->ubProfile ].bCharacterTrait == CHAR_TRAIT_MALICIOUS )
{
@@ -9697,9 +9701,10 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_SOLDIER_HIT_TO_GROIN], pTarget->GetName() );
}
// Gain morale for inflicting critical hit
HandleMoraleEvent( pFirer, MORALE_MALICIOUS_HIT, pFirer->sSectorX, pFirer->sSectorY, pFirer->bSectorZ );
if ( pFirer )
// Gain morale for inflicting critical hit
HandleMoraleEvent( pFirer, MORALE_MALICIOUS_HIT, pFirer->sSectorX, pFirer->sSectorY, pFirer->bSectorZ );
}
else
{
@@ -9902,7 +9907,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget,
}
// SANDRO - Gain morale for inflicting critical hit if malicious character
if ( fMaliciousHit )
if ( fMaliciousHit && pFirer )
{
HandleMoraleEvent( pFirer, MORALE_MALICIOUS_HIT, pFirer->sSectorX, pFirer->sSectorY, pFirer->bSectorZ );
}
@@ -10225,9 +10230,12 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
void ShotMiss( UINT8 ubAttackerID, INT32 iBullet )
{
BOOLEAN fDoMissForGun = FALSE;
SOLDIERTYPE *pAttacker;
BULLET *pBullet;
BOOLEAN fDoMissForGun = FALSE;
SOLDIERTYPE* pAttacker = NULL;
BULLET* pBullet;
if ( ubAttackerID == NOBODY )
return;
pAttacker = MercPtrs[ ubAttackerID ];
@@ -10237,7 +10245,7 @@ void ShotMiss( UINT8 ubAttackerID, INT32 iBullet )
if ( (pAttacker->bTeam != Menptr[ pAttacker->ubOppNum ].bTeam ) )
{
// if OPPONENT is under our control
if (Menptr[ pAttacker->ubOppNum ].bTeam == gbPlayerNum )
if (Menptr[ pAttacker->ubOppNum ].bTeam == gbPlayerNum )
{
// AGILITY GAIN: Opponent "dodged" a bullet shot at him (it missed)
StatChange( MercPtrs[ pAttacker->ubOppNum ], AGILAMT, 5, FROM_FAILURE );
@@ -10301,7 +10309,7 @@ void ShotMiss( UINT8 ubAttackerID, INT32 iBullet )
// PLAY SOUND AND FLING DEBRIS
// RANDOMIZE SOUND SYSTEM
if ( !DoSpecialEffectAmmoMiss( ubAttackerID, NOWHERE, 0, 0, 0, TRUE, TRUE, 0 ) )
if ( !DoSpecialEffectAmmoMiss( ubAttackerID, MercPtrs[ ubAttackerID ]->usAttackingWeapon, NOWHERE, 0, 0, 0, TRUE, TRUE, 0 ) )
{
PlayJA2Sample( MISS_1 + Random(8), RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
}
+1 -1
View File
@@ -480,7 +480,7 @@ extern BOOLEAN IsGunWeaponModeCapable( OBJECTTYPE* pObject, WeaponMode weaponMod
extern BOOLEAN IsGunBurstCapable( OBJECTTYPE* pObject, BOOLEAN fNotify, SOLDIERTYPE *pSoldier = NULL );
extern BOOLEAN IsGunAutofireCapable( OBJECTTYPE* pObject );
extern INT32 CalcBodyImpactReduction( UINT8 ubAmmoType, UINT8 ubHitLocation );
extern INT32 TotalArmourProtection( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iImpact, UINT8 ubAmmoType );
extern INT32 TotalArmourProtection( SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iImpact, UINT8 ubAmmoType );
extern INT32 ArmourPercent( SOLDIERTYPE * pSoldier );
extern void GetTargetWorldPositions( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, FLOAT *pdXPos, FLOAT *pdYPos, FLOAT *pdZPos );
+5 -1
View File
@@ -152,7 +152,11 @@ void HandleBulletSpecialFlags( INT32 iBulletIndex )
else if ( pBullet->usFlags & ( BULLET_FLAG_KNIFE ) )
{
strcpy( AniParams.zCachedFile, "TILECACHE\\KNIFING.STI" );
pBullet->ubItemStatus = pBullet->pFirer->inv[ HANDPOS ][0]->data.objectStatus;
if ( pBullet->ubFirerID != NOBODY )
pBullet->ubItemStatus = pBullet->pFirer->inv[ HANDPOS ][0]->data.objectStatus;
else
pBullet->ubItemStatus = 100;
}
// Get direction to use for this guy....
+4 -4
View File
@@ -104,7 +104,7 @@ BOOLEAN ExpAffect( INT32 sBombGridNo, INT32 sGridNo, UINT32 uiDist, UINT16 usIte
UINT8 DetermineFlashbangEffect( SOLDIERTYPE *pSoldier, INT8 ubExplosionDir, BOOLEAN fInBuilding);
// HEADROCK HAM 5.1: Explosion Fragments launcher
void FireFragments( SOLDIERTYPE * pThrower, INT16 sX, INT16 sY, INT16 sZ, UINT16 usItem, UINT8 ubDirection = DIRECTION_IRRELEVANT );
void FireFragments( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, UINT16 usItem, UINT8 ubDirection = DIRECTION_IRRELEVANT );
// Flugente: shoot a gun without anyone operating it (used for makeshift traps wih guns)
void FireFragmentsTrapGun( SOLDIERTYPE* pThrower, INT32 gridno, INT16 sZ, OBJECTTYPE* pObj, UINT8 ubDirection = NORTH );
@@ -383,7 +383,7 @@ void InternalIgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32
if (Explosive[ Item[ usItem ].ubClassIndex ].usNumFragments > 0 )
{
// HEADROCK HAM 5: Deactivated until the release of HAM 5.1.
FireFragments( MercPtrs[ubOwner], sX, sY, sZ, usItem, ubDirection );
FireFragments( ubOwner, sX, sY, sZ, usItem, ubDirection );
}
// Flugente: Items can have secondary explosions
@@ -4992,7 +4992,7 @@ UINT8 DetermineFlashbangEffect( SOLDIERTYPE *pSoldier, INT8 ubExplosionDir, BOOL
// HEADROCK HAM 5.1: This handles launching fragments out of an explosion. The number of fragments is read from
// the Explosives.XML file, and they each have a set amount of damage and range as well. They are currently
// fired at completely random trajectories.
void FireFragments( SOLDIERTYPE * pThrower, INT16 sX, INT16 sY, INT16 sZ, UINT16 usItem, UINT8 ubDirection )
void FireFragments( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, UINT16 usItem, UINT8 ubDirection )
{
UINT16 usNumFragments = Explosive[Item[usItem].ubClassIndex].usNumFragments;
UINT16 ubFragRange = Explosive[Item[usItem].ubClassIndex].ubFragRange;
@@ -5074,7 +5074,7 @@ void FireFragments( SOLDIERTYPE * pThrower, INT16 sX, INT16 sY, INT16 sZ, UINT16
FLOAT dStartY = (FLOAT)sY + (dRandomY * ((FLOAT)Random(4)+1.0f));
FLOAT dStartZ = (FLOAT)sZ + (dRandomZ * ((FLOAT)Random(4)+1.0f));
FireFragmentGivenTarget( pThrower, dStartX, dStartY, dStartZ, dEndX, dEndY, dEndZ, usItem );
FireFragmentGivenTarget( ubOwner, dStartX, dStartY, dStartZ, dEndX, dEndY, dEndZ, usItem );
}
}