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