Data and Source v1.13 Mod High Resolution version from 2006-04-15

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@25 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
lalien
2006-04-19 18:16:27 +00:00
parent 8b2d0e33aa
commit 8d448f9c64
83 changed files with 2125 additions and 3651 deletions
+1 -1
View File
@@ -1590,4 +1590,4 @@ void EnemyCallInAirStrike (INT16 sSectorX, INT16 sSectorY)
ScheduleAirRaid( &AirRaidDef );
return;
}
}
+15 -15
View File
@@ -176,8 +176,8 @@ ANIMCONTROLTYPE gAnimControl[ NUMANIMATIONSTATES ] =
// GENERIC HIT CROUCHED
{"GENERIC HIT CROUCH" , 0, 80, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_HITSTART | ANIM_NONINTERRUPT | ANIM_NO_EFFORT | ANIM_NOCHANGE_WEAPON, ANIM_CROUCH, ANIM_CROUCH, -1},
// STAND BURST
{"STAND BURST SHOOT" , 0, 100, (FLOAT)0, ANIM_NORESTART | ANIM_STATIONARY | ANIM_TURNING | ANIM_RAISE_WEAPON | ANIM_LIGHT_EFFORT | ANIM_NOCHANGE_WEAPON | ANIM_FIRE, ANIM_STAND, ANIM_STAND, -1},
// STAND BURST // Lesh: AniDelay, speed=0 for control it
{"STAND BURST SHOOT" , 0, 0, (FLOAT)0, ANIM_NORESTART | ANIM_STATIONARY | ANIM_TURNING | ANIM_RAISE_WEAPON | ANIM_LIGHT_EFFORT | ANIM_NOCHANGE_WEAPON | ANIM_FIRE, ANIM_STAND, ANIM_STAND, -1},
// STANDING BURST HIT
{"STAND BUTST HIT" , 0, 80, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_HITSTART | ANIM_NO_EFFORT | ANIM_NOCHANGE_WEAPON | ANIM_IGNORE_AUTOSTANCE, ANIM_STAND, ANIM_STAND, -1},
@@ -262,8 +262,8 @@ ANIMCONTROLTYPE gAnimControl[ NUMANIMATIONSTATES ] =
{"JFK DEATHHIT B" , 0, 100, (FLOAT)0, ANIM_STATIONARY | ANIM_HITWHENDOWN | ANIM_NONINTERRUPT | ANIM_NOSHOW_MARKER | ANIM_NO_EFFORT | ANIM_NOCHANGE_WEAPON, ANIM_PRONE, ANIM_PRONE, -1},
// STAND BURST
{"STAND BURST SPREAD" , 0, 100, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_LIGHT_EFFORT, ANIM_STAND, ANIM_STAND, -1},
// STAND BURST // Lesh: AniDelay, speed=0 for control it
{"STAND BURST SPREAD" , 0, 0, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_LIGHT_EFFORT, ANIM_STAND, ANIM_STAND, -1},
// FALLOFF DEATH
{"FALLOFF DEATH" , 0, 120, (FLOAT)0, ANIM_STATIONARY | ANIM_NONINTERRUPT | ANIM_NO_EFFORT | ANIM_NOCHANGE_WEAPON, ANIM_PRONE, ANIM_PRONE, -1},
@@ -356,11 +356,11 @@ ANIMCONTROLTYPE gAnimControl[ NUMANIMATIONSTATES ] =
//QUEEN MONSTER STATIONARY
{"MONSTER_STATIONARY" , 0, 100, (FLOAT)0, ANIM_STATIONARY | ANIM_NOMOVE_MARKER | ANIM_NO_EFFORT | ANIM_BREATH, ANIM_STAND, ANIM_STAND, -1},
// CROUCHED BURST
{"CROUCHED BURST SHOOT" , 0, 100, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_LIGHT_EFFORT | ANIM_FIRE, ANIM_CROUCH, ANIM_CROUCH, -1},
// CROUCHED BURST // Lesh: AniDelay, speed=0 for control it
{"CROUCHED BURST SHOOT" , 0, 0, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_LIGHT_EFFORT | ANIM_FIRE, ANIM_CROUCH, ANIM_CROUCH, -1},
// PRONE BURST
{"PRONE BURST SHOOT" , 0, 100, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_LIGHT_EFFORT | ANIM_FIRE, ANIM_PRONE, ANIM_PRONE, -1},
// PRONE BURST // Lesh: AniDelay, speed=0 for control it
{"PRONE BURST SHOOT" , 0, 0, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_LIGHT_EFFORT | ANIM_FIRE, ANIM_PRONE, ANIM_PRONE, -1},
//180
{"NOT USED 1" , 20, 20, (FLOAT)0.9, ANIM_MOVING | ANIM_TURNING | ANIM_NORESTART | ANIM_NO_EFFORT, ANIM_STAND, ANIM_STAND, -1},
@@ -527,8 +527,8 @@ ANIMCONTROLTYPE gAnimControl[ NUMANIMATIONSTATES ] =
// SHOOT_RIFLE_STAND LOW
"SHOOT (R) STAND LOW" , 0, 100, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_RAISE_WEAPON | ANIM_LIGHT_EFFORT | ANIM_FIRE, ANIM_STAND, ANIM_STAND, -1,
// SHOOT_RIFLE_STAND LOW
"BURST SHOOT (R) STAND LOW" , 0, 100, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_RAISE_WEAPON | ANIM_LIGHT_EFFORT | ANIM_FIRE, ANIM_STAND, ANIM_STAND, -1,
// SHOOT_RIFLE_STAND LOW // Lesh: AniDelay, speed=0 for control it
"BURST SHOOT (R) STAND LOW" , 0, 0, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_RAISE_WEAPON | ANIM_LIGHT_EFFORT | ANIM_FIRE, ANIM_STAND, ANIM_STAND, -1,
//LARVAE Breathing
"LARVAE BREATH" , 0, 250, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_NORESTART | ANIM_NO_EFFORT | ANIM_NOCHANGE_WEAPON, ANIM_STAND, ANIM_STAND, -1,
@@ -786,8 +786,8 @@ ANIMCONTROLTYPE gAnimControl[ NUMANIMATIONSTATES ] =
// TANK SHOOT
"TANK SHOOT" , 0, 200, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_NOCHANGE_WEAPON | ANIM_LIGHT_EFFORT | ANIM_FIRE, ANIM_STAND, ANIM_STAND, -1,
// TANK SHOOT
"TANK BURST" , 0, 100, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_NOCHANGE_WEAPON | ANIM_LIGHT_EFFORT | ANIM_FIRE, ANIM_STAND, ANIM_STAND, -1,
// TANK SHOOT // Lesh: AniDelay, speed=0 for control it
"TANK BURST" , 0, 0, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_NOCHANGE_WEAPON | ANIM_LIGHT_EFFORT | ANIM_FIRE, ANIM_STAND, ANIM_STAND, -1,
//Queen Slap
"QUEEN SLAP" , 0, 120, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_FASTTURN | ANIM_NORESTART | ANIM_LIGHT_EFFORT | ANIM_NOCHANGE_WEAPON, ANIM_STAND, ANIM_STAND, -1,
@@ -883,8 +883,8 @@ ANIMCONTROLTYPE gAnimControl[ NUMANIMATIONSTATES ] =
// KID SKIPPING
"KID SKIPPING", 0 , 70, (FLOAT)2.0, ANIM_MOVING | ANIM_TURNING | ANIM_NORESTART | ANIM_LIGHT_EFFORT | ANIM_NOCHANGE_WEAPON, ANIM_STAND, ANIM_STAND, -1,
// STAND BURST
"STAND BURST SHOOT" , 0, 100, (FLOAT)0, ANIM_NORESTART | ANIM_STATIONARY | ANIM_TURNING | ANIM_RAISE_WEAPON | ANIM_LIGHT_EFFORT | ANIM_NOCHANGE_WEAPON | ANIM_FIRE, ANIM_STAND, ANIM_STAND, -1,
// STAND BURST // Lesh: AniDelay, speed=0 for control it
"STAND BURST SHOOT" , 0, 0, (FLOAT)0, ANIM_NORESTART | ANIM_STATIONARY | ANIM_TURNING | ANIM_RAISE_WEAPON | ANIM_LIGHT_EFFORT | ANIM_NOCHANGE_WEAPON | ANIM_FIRE, ANIM_STAND, ANIM_STAND, -1,
//Attach string
"Attach String" , 0, 70, (FLOAT)0, ANIM_STATIONARY | ANIM_TURNING | ANIM_FASTTURN | ANIM_NORESTART | ANIM_NONINTERRUPT | ANIM_LOWER_WEAPON | ANIM_LIGHT_EFFORT, ANIM_CROUCH, ANIM_CROUCH, -1,
@@ -3210,7 +3210,7 @@ INT8 GetBodyTypePaletteSubstitutionCode( SOLDIERTYPE *pSoldier, UINT8 ubBodyType
}
// Check for cammo...
if ( ( pSoldier->bCamo + pSoldier->wornCamo ) > 0 )
if ( ( pSoldier->bCamo + pSoldier->wornCamo ) > 50 )
{
strcpy( zColFilename, "ANIMS\\camo.COL" );
return( 1 );
+19 -24
View File
@@ -529,14 +529,14 @@ DEALER_POSSIBLE_INV gGabbyInventory[MAXITEMS+1];// =
//
// Frank ( Alcohol )
//
DEALER_POSSIBLE_INV gFrankInventory[MAXITEMS+1] =
{
{ BEER, 12 },
{ WINE, 6 },
{ ALCOHOL, 9 },
{ LAST_DEALER_ITEM, NO_DEALER_ITEM }, //Last One
};
DEALER_POSSIBLE_INV gFrankInventory[MAXITEMS+1];// =
//{
// { BEER, 12 },
// { WINE, 6 },
// { ALCOHOL, 9 },
//
// { LAST_DEALER_ITEM, NO_DEALER_ITEM }, //Last One
//};
//
@@ -902,22 +902,6 @@ UINT8 GetCurrentSuitabilityForItem( INT8 bArmsDealer, UINT16 usItemIndex, BOOLEA
// the following staple items are always deemed highly suitable regardless of player's progress:
switch (usItemIndex)
{
case CLIP38_6:
case CLIP9_15:
case CLIP9_30:
case CLIP357_6:
case CLIP357_9:
case CLIP45_7:
case CLIP45_30:
case CLIP12G_7:
case CLIP12G_7_BUCKSHOT:
case CLIP545_30_HP:
case CLIP556_30_HP:
case CLIP762W_10_HP:
case CLIP762W_30_HP:
case CLIP762N_5_HP:
case CLIP762N_20_HP:
case FIRSTAIDKIT:
case MEDICKIT:
case TOOLKIT:
@@ -946,6 +930,9 @@ UINT8 GetCurrentSuitabilityForItem( INT8 bArmsDealer, UINT16 usItemIndex, BOOLEA
ubMinCoolness = HighestPlayerProgressPercentage() / 10;
ubMaxCoolness = ( HighestPlayerProgressPercentage() / 10 ) + 1;
if ( bArmsDealer == -1 )
ubMinCoolness = 1;
//Madd: Bobby Ray's will sell higher coolness stuff if it's used, and may also have a better selection at the start of the game, depending on selection
if ( bArmsDealer == -1 && gGameOptions.ubBobbyRay > BR_GOOD )
{
@@ -976,6 +963,14 @@ UINT8 GetCurrentSuitabilityForItem( INT8 bArmsDealer, UINT16 usItemIndex, BOOLEA
ubMinCoolness = max( 1, min( 9, ubMinCoolness ) );
ubMaxCoolness = max( 2, min( 10, ubMaxCoolness ) );
if ( bArmsDealer == -1 )
{
//Madd: BR's always sells ammo for its guns
if (Item[usItemIndex].usItemClass == IC_AMMO && ubItemCoolness <= ubMaxCoolness )
{
return(ITEM_SUITABILITY_ALWAYS);
}
}
// if item is too cool for current level of progress
if (ubItemCoolness > ubMaxCoolness)
+1 -1
View File
@@ -5430,4 +5430,4 @@ void SoldierStealItemFromSoldier( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent,
gpTempSoldier = pSoldier;
gsTempGridno = sGridNo;
SetCustomizableTimerCallbackAndDelay( 1000, CheckForPickedOwnership, TRUE );
}
}
+3 -3
View File
@@ -4528,12 +4528,12 @@ UINT32 UIHandleLCOnTerrain( UI_EVENT *pUIEvent )
if( usAnimState != INVALID_ANIMATION )
{
gsCurrentActionPoints = GetAPsToReadyWeapon( pSoldier, usAnimState ) + AP_TO_AIM_TILE_IF_GETTING_READY;
gsCurrentActionPoints = GetAPsToReadyWeapon( pSoldier, usAnimState );// Madd: removed the next part since it was deducting 2 extra aps that would not be deducted when readying the old way //+ AP_TO_AIM_TILE_IF_GETTING_READY;
}
else if( pSoldier->sLastTarget != sXPos + (MAXCOL * sYPos ) )
gsCurrentActionPoints = AP_TO_AIM_TILE_IF_ALREADY_READY;
else
gsCurrentActionPoints = 0;
gsCurrentActionPoints = 0;
gfUIHandleShowMoveGrid = TRUE;
gsUIHandleShowMoveGridLocation = sXPos + (MAXCOL * sYPos );
@@ -4604,7 +4604,7 @@ BOOLEAN MakeSoldierTurn( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos )
if( usAnimState != INVALID_ANIMATION )
{
sAPCostToReady = GetAPsToReadyWeapon( pSoldier, usAnimState );
sAPCost = sAPCostToReady + AP_TO_AIM_TILE_IF_GETTING_READY;
sAPCost = sAPCostToReady; // Madd: removed this part since it was costing too many aps to ready weapon -- see other comment //+ AP_TO_AIM_TILE_IF_GETTING_READY;
}
else if( pSoldier->sLastTarget != sXPos + (MAXCOL * sYPos ) )
sAPCost = AP_TO_AIM_TILE_IF_ALREADY_READY;
+99 -12
View File
@@ -1,4 +1,3 @@
// WANNE 2 <changed some lines>
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#include "language defines.h"
@@ -184,22 +183,24 @@
#define ITEM_FONT TINYFONT1
#define EXCEPTIONAL_DAMAGE 30
#define EXCEPTIONAL_DAMAGE 40
#define EXCEPTIONAL_WEIGHT 20
#define EXCEPTIONAL_RANGE 300
#define EXCEPTIONAL_MAGAZINE 30
#define EXCEPTIONAL_AP_COST 7
#define EXCEPTIONAL_RANGE 400
#define EXCEPTIONAL_MAGAZINE 50
#define EXCEPTIONAL_AP_COST 5
#define EXCEPTIONAL_BURST_SIZE 5
#define EXCEPTIONAL_RELIABILITY 2
#define EXCEPTIONAL_REPAIR_EASE 2
#define EXCEPTIONAL_ACCURACY 4
#define BAD_DAMAGE 23
#define BAD_WEIGHT 45
#define BAD_RANGE 150
#define BAD_RANGE 150
#define BAD_MAGAZINE 10
#define BAD_AP_COST 11
#define BAD_AP_COST 9
#define BAD_RELIABILITY -2
#define BAD_REPAIR_EASE -2
#define BAD_ACCURACY -1
#define KEYRING_X 487
#define KEYRING_Y (105 + INV_INTERFACE_START_Y)
@@ -603,6 +604,15 @@ void GenerateProsString( UINT16 * zItemPros, OBJECTTYPE * pObject, UINT32 uiPixL
ubWeight += Item[ pObject->usGunAmmoItem ].ubWeight;
}
if (Weapon[usItem].bAccuracy >= EXCEPTIONAL_ACCURACY )
{
zTemp = Message[STR_ACCURATE];
if ( ! AttemptToAddSubstring( zItemPros, zTemp, &uiStringLength, uiPixLimit ) )
{
return;
}
}
if (Item[usItem].ubWeight <= EXCEPTIONAL_WEIGHT)
{
zTemp = Message[STR_LIGHT];
@@ -712,6 +722,15 @@ void GenerateConsString( UINT16 * zItemCons, OBJECTTYPE * pObject, UINT32 uiPixL
zItemCons[0] = 0;
if (Weapon[usItem].bAccuracy <= BAD_ACCURACY)
{
zTemp = Message[STR_INACCURATE];
if ( ! AttemptToAddSubstring( zItemCons, zTemp, &uiStringLength, uiPixLimit ) )
{
return;
}
}
// calculate the weight of the item plus ammunition but not including any attachments
ubWeight = Item[ usItem ].ubWeight;
if (Item[ usItem ].usItemClass == IC_GUN)
@@ -1063,6 +1082,37 @@ void INVRenderINVPanelItem( SOLDIERTYPE *pSoldier, INT16 sPocket, UINT8 fDirtyLe
{
// CHECK FOR COMPATIBILITY WITH MAGAZINES
/* OLD VERSION OF GUN/AMMO MATCH HIGHLIGHTING
UINT32 uiDestPitchBYTES;
UINT8 *pDestBuf;
UINT16 usLineColor;
if ( ( Item [ pSoldier->inv[ HANDPOS ].usItem ].usItemClass & IC_GUN ) && ( Item[ pObject->usItem ].usItemClass & IC_AMMO ) )
{
// CHECK
if (Weapon[pSoldier->inv[ HANDPOS ].usItem].ubCalibre == Magazine[Item[pObject->usItem].ubClassIndex].ubCalibre )
{
// IT's an OK calibre ammo, do something!
// Render Item with specific color
//fOutline = TRUE;
//sOutlineColor = Get16BPPColor( FROMRGB( 96, 104, 128 ) );
//sOutlineColor = Get16BPPColor( FROMRGB( 20, 20, 120 ) );
// Draw rectangle!
pDestBuf = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES );
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 );
//usLineColor = Get16BPPColor( FROMRGB( 255, 255, 0 ) );
usLineColor = Get16BPPColor( FROMRGB( 230, 215, 196 ) );
RectangleDraw( TRUE, (sX+1), (sY+1), (sX + gSMInvData[ sPocket ].sWidth - 2 ),( sY + gSMInvData[ sPocket ].sHeight - 2 ), usLineColor, pDestBuf );
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 );
UnLockVideoSurface( guiSAVEBUFFER );
}
}
*/
if ( gbCompatibleAmmo[ sPocket ] )
{
fOutline = TRUE;
@@ -2212,6 +2262,11 @@ void CycleItemDescriptionItem( )
{
usOldItem--;
while ( usOldItem > 0 && ( Item[usOldItem].usItemClass == IC_NONE || Item[usOldItem].usItemClass == 0 ))
{
usOldItem--;
}
if ( usOldItem < 0 )
{
usOldItem = MAXITEMS-1;
@@ -2225,6 +2280,11 @@ void CycleItemDescriptionItem( )
{
usOldItem = 0;
}
while (usOldItem < MAXITEMS && (Item[usOldItem].usItemClass == IC_NONE || Item[usOldItem].usItemClass == 0 ))
{
usOldItem++;
}
}
CreateItem( (UINT16)usOldItem, 100, &( gpItemDescSoldier->inv[ HANDPOS ] ) );
@@ -2767,7 +2827,6 @@ void ItemDescAmmoCallback(GUI_BUTTON *btn,INT32 reason)
swprintf( (wchar_t *)pStr, L"0" );
SpecifyButtonText( giItemDescAmmoButton, (UINT16 *)pStr );
fItemDescDelete = TRUE;
}
@@ -3069,6 +3128,13 @@ void RenderItemDescriptionBox( )
BltVideoObjectFromIndex( guiSAVEBUFFER, guiBullet, 0, MAP_BULLET_BURST_X + cnt * (BULLET_WIDTH/2 + 1), MAP_BULLET_BURST_Y, VO_BLT_SRCTRANSPARENCY, NULL );
}
}
else if (GetAutofireShotsPerFiveAPs(gpItemDescObject) > 0 )
{
for ( cnt = 0; cnt < 10; cnt++ )
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiBullet, 0, MAP_BULLET_BURST_X + cnt * (BULLET_WIDTH/2 + 1), MAP_BULLET_BURST_Y, VO_BLT_SRCTRANSPARENCY, NULL );
}
}
}
@@ -3193,7 +3259,7 @@ void RenderItemDescriptionBox( )
mprintf( gMapWeaponStats[ 1 ].sX + gsInvDescX, gMapWeaponStats[ 1 ].sY + gsInvDescY, L"%s", gWeaponStatsDesc[ 1 ] );
if (GetShotsPerBurst(gpItemDescObject) > 0)
if (GetShotsPerBurst(gpItemDescObject) > 0 || GetAutofireShotsPerFiveAPs(gpItemDescObject)>0)
{
mprintf( gMapWeaponStats[ 8 ].sX + gsInvDescX, gMapWeaponStats[ 8 ].sY + gsInvDescY, L"%s", gWeaponStatsDesc[ 8 ] );
}
@@ -3289,7 +3355,15 @@ void RenderItemDescriptionBox( )
FindFontRightCoordinates( (INT16)(gMapWeaponStats[ 6 ].sX + gsInvDescX + gMapWeaponStats[ 6 ].sValDx), (INT16)(gMapWeaponStats[ 6 ].sY + gsInvDescY ), ITEM_STATS_WIDTH ,ITEM_STATS_HEIGHT ,pStr, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY, pStr );
}
else if (GetAutofireShotsPerFiveAPs(gpItemDescObject) > 0)
{
SetFontForeground( 5 );
swprintf( (wchar_t *)pStr, L"%2d", ubAttackAPs + CalcAPsToAutofire( DEFAULT_APS, gpItemDescObject, 3 ) );
FindFontRightCoordinates( (INT16)(gMapWeaponStats[ 6 ].sX + gsInvDescX + gMapWeaponStats[ 6 ].sValDx), (INT16)(gMapWeaponStats[ 6 ].sY + gsInvDescY ), ITEM_STATS_WIDTH ,ITEM_STATS_HEIGHT ,pStr, BLOCKFONT2, &usX, &usY);
mprintf( usX, usY, pStr );
}
}
else if ( gpItemDescObject->usItem == MONEY )
{
@@ -3528,6 +3602,13 @@ void RenderItemDescriptionBox( )
BltVideoObjectFromIndex( guiSAVEBUFFER, guiBullet, 0, BULLET_BURST_X + cnt * (BULLET_WIDTH/2 + 1), BULLET_BURST_Y, VO_BLT_SRCTRANSPARENCY, NULL );
}
}
else if ( GetAutofireShotsPerFiveAPs(gpItemDescObject) > 0 )
{
for ( cnt = 0; cnt < 10; cnt++ )
{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiBullet, 0, BULLET_BURST_X + cnt * (BULLET_WIDTH/2 + 1), BULLET_BURST_Y, VO_BLT_SRCTRANSPARENCY, NULL );
}
}
}
@@ -3643,7 +3724,7 @@ void RenderItemDescriptionBox( )
}
mprintf( gWeaponStats[ 1 ].sX + gsInvDescX, gWeaponStats[ 1 ].sY + gsInvDescY, L"%s", gWeaponStatsDesc[ 1 ] );
if (GetShotsPerBurst(gpItemDescObject) > 0)
if (GetShotsPerBurst(gpItemDescObject) > 0 || GetAutofireShotsPerFiveAPs(gpItemDescObject))
{
mprintf( gWeaponStats[ 8 ].sX + gsInvDescX, gWeaponStats[ 8 ].sY + gsInvDescY, L"%s", gWeaponStatsDesc[ 8 ] );
}
@@ -3732,6 +3813,13 @@ void RenderItemDescriptionBox( )
FindFontRightCoordinates( (INT16)(gWeaponStats[ 6 ].sX + gsInvDescX + gWeaponStats[ 6 ].sValDx), (INT16)(gWeaponStats[ 6 ].sY + gsInvDescY ), ITEM_STATS_WIDTH, ITEM_STATS_HEIGHT, pStr, BLOCKFONT2, &usX, &usY );
mprintf( usX, usY, pStr );
}
else if (GetAutofireShotsPerFiveAPs(gpItemDescObject)> 0)
{
SetFontForeground( 5 );
swprintf( (wchar_t *)pStr, L"%2d", ubAttackAPs + CalcAPsToBurst( DEFAULT_APS, gpItemDescObject ) );
FindFontRightCoordinates( (INT16)(gWeaponStats[ 6 ].sX + gsInvDescX + gWeaponStats[ 6 ].sValDx), (INT16)(gWeaponStats[ 6 ].sY + gsInvDescY ), ITEM_STATS_WIDTH, ITEM_STATS_HEIGHT, pStr, BLOCKFONT2, &usX, &usY );
mprintf( usX, usY, pStr );
}
}
else if ( gpItemDescObject->usItem == MONEY )
@@ -7203,8 +7291,7 @@ void GetHelpTextForItem( INT16 * pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldi
}
}
// The first tool tip is for rocket rifles
if ( !gGameOptions.fGunNut && Item[ usItem ].usItemClass == IC_GUN && !Item[usItem].rocketlauncher && !Item[usItem].rocketrifle )
if ( Item[ usItem ].usItemClass == IC_GUN && !Item[usItem].rocketlauncher && !Item[usItem].rocketrifle )
{
swprintf( (wchar_t *)pStr, L"%s (%s) [%d%%]", ItemNames[ usItem ], AmmoCaliber[ Weapon[ usItem ].ubCalibre ], sValue );
}
+25 -7
View File
@@ -995,7 +995,7 @@ void UpdateSMPanel( )
else
{
// Enable some buttons!
if ( IsGunAutofireCapable( gpSMCurrentMerc, HANDPOS ) || IsGunBurstCapable( gpSMCurrentMerc, HANDPOS , FALSE ) || IsGrenadeLauncherAttached ( &(gpSMCurrentMerc->inv[HANDPOS]) ) )
if ( ((IsGunAutofireCapable( gpSMCurrentMerc, HANDPOS ) || IsGunBurstCapable( gpSMCurrentMerc, HANDPOS , FALSE )) && !Weapon[gpSMCurrentMerc->inv[HANDPOS].usItem].NoSemiAuto ) || IsGrenadeLauncherAttached ( &(gpSMCurrentMerc->inv[HANDPOS]) ) )
{
EnableButton( iSMPanelButtons[ BURSTMODE_BUTTON ] );
}
@@ -5988,9 +5988,18 @@ void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInv
// if in attached weapon mode and don't have weapon with GL attached in hand, reset weapon mode
if ( (pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )&& !IsGrenadeLauncherAttached( &(pSoldier->inv[ HANDPOS ]) ) )
{
pSoldier->bWeaponMode = WM_NORMAL;
pSoldier->bDoBurst = FALSE;
pSoldier->bDoAutofire = 0;
if ( !Weapon[pSoldier->inv[ HANDPOS ].usItem].NoSemiAuto )
{
pSoldier->bWeaponMode = WM_NORMAL;
pSoldier->bDoBurst = FALSE;
pSoldier->bDoAutofire = 0;
}
else
{
pSoldier->bWeaponMode = WM_AUTOFIRE;
pSoldier->bDoBurst = TRUE;
pSoldier->bDoAutofire = 1;
}
}
// if he is loaded tactically
@@ -6016,9 +6025,18 @@ void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInv
// as a minimum
if ( (Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass & IC_WEAPON) && GetShotsPerBurst(&pSoldier->inv[ HANDPOS ]) == 0 )
{
pSoldier->bDoBurst = FALSE;
pSoldier->bWeaponMode = WM_NORMAL;
pSoldier->bDoAutofire = 0;
if ( !Weapon[pSoldier->inv[ HANDPOS ].usItem].NoSemiAuto )
{
pSoldier->bWeaponMode = WM_NORMAL;
pSoldier->bDoBurst = FALSE;
pSoldier->bDoAutofire = 0;
}
else
{
pSoldier->bWeaponMode = WM_AUTOFIRE;
pSoldier->bDoAutofire = 1;
pSoldier->bDoBurst = TRUE;
}
}
}
}
+26 -17
View File
@@ -99,16 +99,16 @@ void InitArmyGunTypes(void)
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"InitArmyGunTypes set gun choice table");
// depending on selection of the gun nut option
if (gGameOptions.fGunNut)
{
//if (gGameOptions.fGunNut)
//{
// use table of extended gun choices
pGunChoiceTable = &(gExtendedArmyGunChoices[0]);
}
else
{
// use table of regular gun choices
pGunChoiceTable = &(gRegularArmyGunChoices[0]);
}
//}
//else
//{
// // use table of regular gun choices
// pGunChoiceTable = &(gRegularArmyGunChoices[0]);
//}
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"InitArmyGunTypes pick a gun type");
// for each gun category
@@ -429,7 +429,7 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8
}
bAmmoClips = (INT8)(3 + Random( 2 ));
bGrenades = (INT8)(3 + Random( 3 ));
bGrenades = (INT8)(2 + Random( 3 ));
if( ( bRating >= AVERAGE_ELITE_EQUIPMENT_RATING ) && ( Random( 100 ) < 75 ) )
{
@@ -794,28 +794,35 @@ void ChooseWeaponForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bWeaponC
usAttachIndex = 0;
}
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"ChooseWeaponForSoldierCreateStruct: Gun Created");
if( usScopeIndex > 0 )
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("ChooseWeaponForSoldierCreateStruct: Create Scope %d",usScopeIndex));
CreateItem( usScopeIndex, 100, &Object );
Object.fFlags |= OBJECT_UNDROPPABLE;
AttachObject( NULL, &(pp->Inv[ HANDPOS ]), &Object );
}
if( usAttachIndex > 0 )
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("ChooseWeaponForSoldierCreateStruct: Create Attachment %d",usAttachIndex));
CreateItem( usAttachIndex, 100, &Object );
Object.fFlags |= OBJECT_UNDROPPABLE;
AttachObject( NULL, &(pp->Inv[ HANDPOS ]), &Object );
}
if( usAttachIndex2 > 0 )
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("ChooseWeaponForSoldierCreateStruct: Create 2nd Attachment %d",usAttachIndex2));
CreateItem( usAttachIndex2, 100, &Object );
Object.fFlags |= OBJECT_UNDROPPABLE;
AttachObject( NULL, &(pp->Inv[ HANDPOS ]), &Object );
}
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("ChooseWeaponForSoldierCreateStruct: Set bullets"));
//set bullets = to magsize including any attachments (c-mag adapters, etc)
pp->Inv[ HANDPOS ].ubGunShotsLeft = GetMagSize(&pp->Inv[ HANDPOS ]);
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("ChooseWeaponForSoldierCreateStruct: choose ammo"));
if( bAmmoClips )
{ //We have a gun, so choose ammo clips
@@ -842,6 +849,7 @@ void ChooseWeaponForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bWeaponC
}
//Ammo
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("ChooseWeaponForSoldierCreateStruct: create ammo"));
if( bAmmoClips && usAmmoIndex )
{
CreateItems( usAmmoIndex, 100, bAmmoClips, &Object );
@@ -849,6 +857,7 @@ void ChooseWeaponForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bWeaponC
PlaceObjectInSoldierCreateStruct( pp, &Object );
}
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("ChooseWeaponForSoldierCreateStruct: done"));
}
void ChooseGrenadesForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bGrenades, INT8 bGrenadeClass, BOOLEAN fGrenadeLauncher )
@@ -2520,16 +2529,16 @@ UINT16 SelectStandardArmyGun( UINT8 uiGunLevel )
// decided to randomize it afterall instead of repeating the same weapon over and over
// depending on selection of the gun nut option
if (gGameOptions.fGunNut)
{
//if (gGameOptions.fGunNut)
//{
// use table of extended gun choices
pGunChoiceTable = &(gExtendedArmyGunChoices[0]);
}
else
{
// use table of regular gun choices
pGunChoiceTable = &(gRegularArmyGunChoices[0]);
}
//}
//else
//{
// // use table of regular gun choices
// pGunChoiceTable = &(gRegularArmyGunChoices[0]);
//}
// choose one the of the possible gun choices
uiChoice = Random(pGunChoiceTable[ uiGunLevel ].ubChoices);
+1
View File
@@ -109,6 +109,7 @@ enum
SCOPE,
ATTACHMENTS,
KNIVES,
ENEMYAMMOTYPES,
MAX_ITEM_TYPES
};
+4 -1
View File
@@ -367,7 +367,8 @@ typedef struct
INT16 magsizebonus;
INT16 percentautofireapreduction;
INT16 autofirebonus;
INT16 autofiretohitbonus;
INT16 APBonus;
INT16 rateoffirebonus;
INT16 burstsizebonus;
INT16 bursttohitbonus;
@@ -829,6 +830,8 @@ typedef enum
EXPLOSIVE,
EASY_MERGE,
ELECTRONIC_MERGE,
USE_ITEM,
USE_ITEM_HARD
} MergeType;
extern UINT16 Merge[MAXITEMS+1][4];
+189 -18
View File
@@ -1176,10 +1176,10 @@ BOOLEAN ItemIsLegal( UINT16 usItemIndex )
if( !gGameOptions.fGunNut )
{
//if the item is a gun, or ammo
if( (Item[ usItemIndex ].usItemClass == IC_GUN) || (Item[ usItemIndex ].usItemClass == IC_AMMO ))
//if( (Item[ usItemIndex ].usItemClass == IC_GUN) || (Item[ usItemIndex ].usItemClass == IC_AMMO )) //Madd: restriction removed
{
// and the item is only available with the extended guns
if( ExtendedGunListGun( usItemIndex ) )
if( Item[usItemIndex].biggunlist )
{
return(FALSE);
}
@@ -3192,6 +3192,39 @@ BOOLEAN AttachObject( SOLDIERTYPE * pSoldier, OBJECTTYPE * pTargetObj, OBJECTTYP
switch( ubType )
{
case USE_ITEM:
case USE_ITEM_HARD:
// the merge will combine the two items
if ( pSoldier )
{
if ( ubType == USE_ITEM_HARD )
{
// requires a skill check, and gives experience
iCheckResult = SkillCheck( pSoldier, ATTACHING_SPECIAL_ITEM_CHECK, -30 );
if (iCheckResult < 0)
{
// could have a chance of detonation
// for now, damage both objects
DamageObj( pTargetObj, (INT8) -iCheckResult );
DamageObj( pAttachment, (INT8) -iCheckResult );
DoMercBattleSound( pSoldier, BATTLE_SOUND_CURSE1 );
return( FALSE );
}
StatChange( pSoldier, MECHANAMT, 25, FALSE );
StatChange( pSoldier, WISDOMAMT, 5, FALSE );
}
pTargetObj->usItem = usResult;
//AutoPlaceObject( pAttachment );
pTargetObj->ubWeight = CalculateObjectWeight( pTargetObj );
if (pSoldier->bTeam == gbPlayerNum)
{
DoMercBattleSound( pSoldier, BATTLE_SOUND_COOL1 );
}
return TRUE;
}
else
return FALSE;
case COMBINE_POINTS:
// transfer points...
if ( Item[ pTargetObj->usItem ].usItemClass == IC_AMMO )
@@ -3451,6 +3484,25 @@ BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj )
}
}
// Lesh: bugfix - replacing weapon in auto with another weapon w/o auto-mode
if (bPos == HANDPOS && Item[ pObj->usItem ].usItemClass == IC_GUN)
{
//Madd: added code for nosemiauto tag
if (!Weapon[ Item[pObj->usItem].ubClassIndex ].NoSemiAuto)
{
pSoldier->bWeaponMode = WM_NORMAL;
pSoldier->bDoBurst = FALSE;
pSoldier->bDoAutofire = FALSE;
}
else
{
pSoldier->bWeaponMode = WM_AUTOFIRE;
pSoldier->bDoBurst = TRUE;
pSoldier->bDoAutofire = TRUE;
}
}
// Lesh: end
ubSlotLimit = ItemSlotLimit( pObj->usItem, bPos );
pInSlot = &(pSoldier->inv[bPos]);
@@ -4272,17 +4324,22 @@ UINT16 MagazineClassIndexToItemType(UINT16 usMagIndex)
// Note: if any ammo items in the item table are separated from the main group,
// this function will have to be rewritten to scan the item table for an item
// with item class ammo, which has class index usMagIndex
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "MagazineClassIndexToItemType" ) );
for (usLoop = FIRST_AMMO; usLoop < MAXITEMS; usLoop++)
{
if ( Item[usLoop].usItemClass == 0 )
break;
if (Item[usLoop].ubClassIndex == usMagIndex)
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "MagazineClassIndexToItemType: breaking at index %d", usLoop ) );
break;
}
if (Item[usLoop].ubClassIndex == usMagIndex && Item[usLoop].usItemClass == IC_AMMO )
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "MagazineClassIndexToItemType: return %d", usLoop ) );
return( usLoop );
}
}
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "MagazineClassIndexToItemType: return none, got to %d", usLoop ) );
return(NONE);
}
@@ -4292,6 +4349,7 @@ UINT16 DefaultMagazine( UINT16 usItem )
WEAPONTYPE * pWeapon;
UINT16 usLoop;
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DefaultMagazine: item = %d",usItem));
if (!(Item[usItem].usItemClass & IC_GUN))
{
return( 0 );
@@ -4302,14 +4360,17 @@ UINT16 DefaultMagazine( UINT16 usItem )
while ( Magazine[usLoop].ubCalibre != NOAMMO )
{
if (Magazine[usLoop].ubCalibre == pWeapon->ubCalibre &&
Magazine[usLoop].ubMagSize == pWeapon->ubMagSize)
Magazine[usLoop].ubMagSize == pWeapon->ubMagSize &&
AmmoTypes[ Magazine[usLoop].ubAmmoType ].standardIssue )
{
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DefaultMagazine: found at index %d",usLoop));
return(MagazineClassIndexToItemType(usLoop));
}
usLoop++;
}
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DefaultMagazine: can't find any"));
return( 0 );
}
@@ -4363,13 +4424,14 @@ UINT16 FindReplacementMagazineIfNecessary( UINT16 usOldGun, UINT16 usOldAmmo, UI
}
// increase this if any gun can have more types that this
#define MAX_AMMO_TYPES_PER_GUN 6 // MADD MARKER
#define MAX_AMMO_TYPES_PER_GUN 24 // MADD MARKER
UINT16 RandomMagazine( UINT16 usItem, UINT8 ubPercentStandard )
{
// Note: if any ammo items in the item table are separated from the main group,
// this function will have to be rewritten to scan the item table for an item
// with item class ammo, which has class index ubLoop
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("RandomMagazine (by index)"));
WEAPONTYPE * pWeapon;
UINT16 usLoop;
@@ -4393,7 +4455,22 @@ UINT16 RandomMagazine( UINT16 usItem, UINT8 ubPercentStandard )
{
// store it! (make sure array is big enough)
Assert(usPossibleMagCnt < MAX_AMMO_TYPES_PER_GUN);
usPossibleMagIndex[usPossibleMagCnt++] = usLoop;
// Madd: check to see if allowed by army
if ( gArmyItemChoices[ENEMYAMMOTYPES].ubChoices > 0 )
{
for ( int i=0;i<gArmyItemChoices[ENEMYAMMOTYPES].ubChoices;i++ )
{
if ( gArmyItemChoices[ENEMYAMMOTYPES].bItemNo[i] == Magazine[usLoop].ubAmmoType )
{
usPossibleMagIndex[usPossibleMagCnt++] = usLoop;
break;
}
}
}
else
{
usPossibleMagIndex[usPossibleMagCnt++] = usLoop;
}
}
usLoop++;
@@ -4409,7 +4486,7 @@ UINT16 RandomMagazine( UINT16 usItem, UINT8 ubPercentStandard )
if (usPossibleMagCnt == 1)
{
// use that, no choice
return(MagazineClassIndexToItemType(usPossibleMagIndex[ 0 ] ));
return(MagazineClassIndexToItemType( usPossibleMagIndex[ 0 ] ));
}
else // multiple choices
{
@@ -4417,6 +4494,8 @@ UINT16 RandomMagazine( UINT16 usItem, UINT8 ubPercentStandard )
if (Random(100) < ubPercentStandard)
{
ubMagChosen = 0;
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("RandomMagazine: ubMagChosen = %d",ubMagChosen ));
return( DefaultMagazine(usItem) );
}
else
{
@@ -4424,6 +4503,7 @@ UINT16 RandomMagazine( UINT16 usItem, UINT8 ubPercentStandard )
ubMagChosen = ( UINT8 ) (1 + Random(( UINT32 ) ( usPossibleMagCnt - 1 )));
}
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("RandomMagazine: ubMagChosen = %d",ubMagChosen ));
return( MagazineClassIndexToItemType(usPossibleMagIndex[ ubMagChosen ] ) );
}
}
@@ -4433,6 +4513,7 @@ UINT16 RandomMagazine( OBJECTTYPE * pGun, UINT8 ubPercentStandard )
// Note: if any ammo items in the item table are separated from the main group,
// this function will have to be rewritten to scan the item table for an item
// with item class ammo, which has class index ubLoop
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("RandomMagazine"));
WEAPONTYPE * pWeapon;
UINT16 usLoop;
@@ -4456,7 +4537,22 @@ UINT16 RandomMagazine( OBJECTTYPE * pGun, UINT8 ubPercentStandard )
{
// store it! (make sure array is big enough)
Assert(usPossibleMagCnt < MAX_AMMO_TYPES_PER_GUN);
usPossibleMagIndex[usPossibleMagCnt++] = usLoop;
// Madd: check to see if allowed by army
if ( gArmyItemChoices[ENEMYAMMOTYPES].ubChoices > 0 )
{
for ( int i=0;i<gArmyItemChoices[ENEMYAMMOTYPES].ubChoices;i++ )
{
if ( gArmyItemChoices[ENEMYAMMOTYPES].bItemNo[i] == Magazine[usLoop].ubAmmoType )
{
usPossibleMagIndex[usPossibleMagCnt++] = usLoop;
break;
}
}
}
else
{
usPossibleMagIndex[usPossibleMagCnt++] = usLoop;
}
}
usLoop++;
@@ -4480,6 +4576,8 @@ UINT16 RandomMagazine( OBJECTTYPE * pGun, UINT8 ubPercentStandard )
if (Random(100) < ubPercentStandard)
{
ubMagChosen = 0;
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("RandomMagazine: ubMagChosen = %d",ubMagChosen ));
return( DefaultMagazine(pGun->usItem) );
}
else
{
@@ -4487,6 +4585,7 @@ UINT16 RandomMagazine( OBJECTTYPE * pGun, UINT8 ubPercentStandard )
ubMagChosen = ( UINT8 ) (1 + Random(( UINT32 ) ( usPossibleMagCnt - 1 )));
}
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("RandomMagazine: ubMagChosen = %d",ubMagChosen ));
return( MagazineClassIndexToItemType(usPossibleMagIndex[ ubMagChosen ] ) );
}
}
@@ -5785,6 +5884,9 @@ INT16 GetItemAimBonus( const INVTYPE* pItem, INT32 iRange, UINT8 ubAimTime )
// reduce effective sight range by aimbonus% per extra aiming time AP
// of the distance beyond minrangeforaimbonus.
if ( pItem->aimbonus < 0)
ubAimTime = 1;
return ( pItem->aimbonus * ubAimTime * ( iRange - pItem->minrangeforaimbonus ) ) / 100;
}
@@ -5804,6 +5906,56 @@ INT16 GetAimBonus( OBJECTTYPE * pObj, INT32 iRange, UINT8 ubAimTime )
return( bns );
}
// Madd: check equipment for aim bonus (penalties)
INT16 GetGearAimBonus( SOLDIERTYPE * pSoldier, INT32 iRange, UINT8 ubAimTime )
{
INT16 bns=0;
for (int j = HELMETPOS; j <= HEAD2POS; j++)
{
bns += GetItemAimBonus( &Item[pSoldier->inv[j].usItem], iRange, ubAimTime );
for ( int i = 0; i < MAX_ATTACHMENTS; i++)
{
bns += GetItemAimBonus(&Item[pSoldier->inv[j].usAttachItem[i]],iRange,ubAimTime);
}
}
return( bns );
}
// Madd: check equipment for to hit bonus (penalties)
INT16 GetGearToHitBonus( SOLDIERTYPE * pSoldier )
{
INT16 bns=0;
for (int j = HELMETPOS; j <= HEAD2POS; j++)
{
bns += Item[pSoldier->inv[j].usItem].tohitbonus;
for ( int i = 0; i < MAX_ATTACHMENTS; i++)
{
bns += Item[pSoldier->inv[j].usAttachItem[i]].tohitbonus;
}
}
return( bns );
}
// Madd: check equipment for AP bonus (penalties)
INT16 GetGearAPBonus( SOLDIERTYPE * pSoldier )
{
INT16 bns=0;
for (int j = HELMETPOS; j <= HEAD2POS; j++)
{
bns += Item[pSoldier->inv[j].usItem].APBonus;
for ( int i = 0; i < MAX_ATTACHMENTS; i++)
{
bns += Item[pSoldier->inv[j].usAttachItem[i]].APBonus;
}
}
return( bns );
}
UINT32 FindRangeBonusAttachment( OBJECTTYPE * pObj )
{
@@ -5825,7 +5977,9 @@ INT16 GetRangeBonus( OBJECTTYPE * pObj )
INT16 bns=0;
bns = BonusReduce( Item[pObj->usItem].rangebonus, pObj->bStatus[0] );
bns += Item[pObj->usGunAmmoItem].rangebonus;
if ( pObj->ubGunShotsLeft > 0 )
bns += Item[pObj->usGunAmmoItem].rangebonus;
for (bLoop = 0; bLoop < MAX_ATTACHMENTS; bLoop++)
{
@@ -5907,7 +6061,9 @@ INT16 GetDamageBonus( OBJECTTYPE * pObj )
INT16 bns=0;
bns = BonusReduce( Item[pObj->usItem].damagebonus, pObj->bStatus[0] );
bns += Item[pObj->usGunAmmoItem].damagebonus ;
if ( pObj->ubGunShotsLeft > 0 )
bns += Item[pObj->usGunAmmoItem].damagebonus ;
for (bLoop = 0; bLoop < MAX_ATTACHMENTS; bLoop++)
{
@@ -5999,18 +6155,22 @@ INT16 GetRateOfFireBonus( OBJECTTYPE * pObj )
return( bns );
}
INT16 GetAutofireBonus( OBJECTTYPE * pObj )
INT16 GetAutoToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance )
{
INT8 bLoop;
INT16 bns=0;
bns = BonusOnOff( Item[pObj->usItem].autofirebonus, pObj->bStatus[0] );
bns += Item[pObj->usGunAmmoItem].autofirebonus ;
// Snap: bipod is effective only in the prone stance
for (bLoop = 0; bLoop < MAX_ATTACHMENTS; bLoop++)
if ( ! Item[pObj->usItem].bipod || fProneStance )
bns = BonusReduceMore( Item[pObj->usItem].autofiretohitbonus, pObj->bStatus[0] );
bns += Item[pObj->usGunAmmoItem].autofiretohitbonus ;
for (int i = 0; i < MAX_ATTACHMENTS; i++)
{
bns += BonusOnOff( Item[pObj->usAttachItem[bLoop]].autofirebonus, pObj->bAttachStatus[bLoop] );
if ( ! Item[pObj->usAttachItem[i]].bipod || fProneStance )
bns += BonusReduceMore( Item[pObj->usAttachItem[i]].autofiretohitbonus, pObj->bAttachStatus[i] );
}
return( bns );
}
@@ -6893,4 +7053,15 @@ void ApplyEquipmentBonuses(SOLDIERTYPE * pSoldier)
if ( newCamo > oldCamo && pSoldier->bTeam == OUR_TEAM )
DoMercBattleSound( pSoldier, BATTLE_SOUND_COOL1 );
}
}
UINT16 GetFirstExplosiveOfType(UINT16 expType)
{
for (int i=0;i<MAXITEMS;i++)
{
if ( (Item[i].usItemClass == IC_EXPLOSV || Item[i].usItemClass == IC_GRENADE) && Explosive[Item[i].ubClassIndex].ubType == expType )
return i;
}
return 0;
}
+7 -1
View File
@@ -208,7 +208,7 @@ INT16 GetPercentAutofireAPReduction( OBJECTTYPE * pObj );
INT16 GetPercentBurstFireAPReduction( OBJECTTYPE * pObj );
INT16 GetPercentReadyTimeAPReduction( OBJECTTYPE * pObj );
INT16 GetPercentReloadTimeAPReduction( OBJECTTYPE * pObj );
INT16 GetAutofireBonus( OBJECTTYPE * pObj );
INT16 GetAutoToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance = FALSE );
INT16 GetRateOfFireBonus( OBJECTTYPE * pObj );
INT16 GetBurstSizeBonus( OBJECTTYPE * pObj );
BOOLEAN HasFastBurst( OBJECTTYPE * pObj );
@@ -279,5 +279,11 @@ INT16 GetCamoBonus( OBJECTTYPE * pObj );
void ApplyEquipmentBonuses(SOLDIERTYPE * pSoldier);
INT16 GetGearAimBonus( SOLDIERTYPE * pSoldier, INT32 iRange, UINT8 ubAimTime);
INT16 GetGearToHitBonus( SOLDIERTYPE * pSoldier );
INT16 GetGearAPBonus( SOLDIERTYPE * pSoldier );
UINT16 GetFirstExplosiveOfType(UINT16 expType);
#endif
+3 -2
View File
@@ -1304,7 +1304,8 @@ INT32 LineOfSightTest( FLOAT dStartX, FLOAT dStartY, FLOAT dStartZ, FLOAT dEndX,
} while( (iCurrTileX == iOldTileX) && (iCurrTileY == iOldTileY) && (iLoop < iDistance));
// leaving a tile, check to see if it had gas in it
if ( pMapElement->ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS) )
// if ( pMapElement->ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS) )
if ( pMapElement->ubExtFlags[0] & (MAPELEMENT_EXT_SMOKE | MAPELEMENT_EXT_TEARGAS | MAPELEMENT_EXT_MUSTARDGAS | MAPELEMENT_EXT_BURNABLEGAS) )
{
if ( (pMapElement->ubExtFlags[0] & MAPELEMENT_EXT_SMOKE) && !fSmell )
{
@@ -4295,7 +4296,7 @@ void MoveBullet( INT32 iBullet )
OBJECTTYPE Object;
INT32 iKnifeGridNo;
CreateItem( THROWING_KNIFE, (INT8) pBullet->ubItemStatus, &Object );
CreateItem( pBullet->fromItem, (INT8) pBullet->ubItemStatus, &Object );
// by default knife at same tile as window
iKnifeGridNo = (INT16) iGridNo;
+33 -11
View File
@@ -119,7 +119,7 @@ INT32 giPauseAllAITimer = 0;
BOOLEAN sniperwarning;
BOOLEAN biggunwarning;
BOOLEAN airstrikeavailable;
//BOOLEAN airstrikeavailable;
TacticalStatusType gTacticalStatus;
@@ -2073,21 +2073,26 @@ BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLE
// bPosOfMask = NO_SLOT;
//}
// TODO: Madd: This next section is pretty lame because it can't figure out which explosive was used to actually cause a gas effect
// so for now, the first explosive to use a gas effect decides the health and breath damage for all of the gasses of that type
// (this was hard coded before by the developers - i guess they figured they didn't need to look for the actual explosion item,
// since they only had one of each gas item?!?)
// anyway, it means that we can only have one set of health/breath damage values for each gas type, until someone has time
// to dig into this further and actually make it find the original item that caused the gas
if ( !AM_A_ROBOT( pSoldier ) )
{
if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->bLevel] & MAPELEMENT_EXT_TEARGAS )
{
if ( !(pSoldier->fHitByGasFlags & HIT_BY_TEARGAS) && bPosOfMask == NO_SLOT )
{
// check for gas mask
pExplosive = &(Explosive[ Item[ TEARGAS_GRENADE ].ubClassIndex ]);
pExplosive = &( Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_TEARGAS) ].ubClassIndex ]);
}
}
if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->bLevel] & MAPELEMENT_EXT_MUSTARDGAS )
{
if ( !(pSoldier->fHitByGasFlags & HIT_BY_MUSTARDGAS) && bPosOfMask == NO_SLOT )
{
pExplosive = &(Explosive[ Item[ MUSTARD_GRENADE ].ubClassIndex ]);
pExplosive = &(Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_MUSTGAS) ].ubClassIndex ]);
}
}
}
@@ -2095,7 +2100,14 @@ BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLE
{
if ( !(pSoldier->fHitByGasFlags & HIT_BY_CREATUREGAS) ) // gas mask doesn't help vs creaturegas
{
pExplosive = &(Explosive[ Item[ SMALL_CREATURE_GAS ].ubClassIndex ]);
pExplosive = &(Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_CREATUREGAS) ].ubClassIndex ]);
}
}
if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[pSoldier->bLevel] & MAPELEMENT_EXT_BURNABLEGAS )
{
if ( !(pSoldier->fHitByGasFlags & HIT_BY_BURNABLEGAS) )
{
pExplosive = &(Explosive[ Item[ GetFirstExplosiveOfType(EXPLOSV_BURNABLEGAS) ].ubClassIndex ]);
}
}
if ( pExplosive )
@@ -5576,14 +5588,14 @@ void SetEnemyPresence( )
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SetEnemyPresence: warnings = false"));
sniperwarning = FALSE;
biggunwarning = FALSE;
airstrikeavailable = TRUE;
// airstrikeavailable = TRUE;
}
else
{
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SetEnemyPresence: warnings = true"));
sniperwarning = TRUE;
biggunwarning = TRUE;
airstrikeavailable = FALSE;
// airstrikeavailable = FALSE;
}
// Say quote...
@@ -7519,10 +7531,20 @@ SOLDIERTYPE *InternalReduceAttackBusyCount( UINT8 ubID, BOOLEAN fCalledByAttacke
if ( pSoldier && (pSoldier->bWeaponMode == WM_ATTACHED_GL || pSoldier->bWeaponMode == WM_ATTACHED_GL_BURST || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO ))
{
// change back to single shot
pSoldier->bWeaponMode = WM_NORMAL;
pSoldier->bDoAutofire = 0;
pSoldier->bDoBurst = 0;
if ( !Weapon[pSoldier->inv[HANDPOS].usItem].NoSemiAuto )
{
// change back to single shot
pSoldier->bWeaponMode = WM_NORMAL;
pSoldier->bDoAutofire = 0;
pSoldier->bDoBurst = 0;
}
else
{
// change back to autofire
pSoldier->bWeaponMode = WM_AUTOFIRE;
pSoldier->bDoAutofire = 1;
pSoldier->bDoBurst = TRUE;
}
DirtyMercPanelInterface(pSoldier, DIRTYLEVEL2 );
}
+3 -3
View File
@@ -362,10 +362,10 @@ void SetSoldierNeutral( SOLDIERTYPE * pSoldier );
extern BOOLEAN sniperwarning;
extern BOOLEAN biggunwarning;
extern BOOLEAN airstrikeavailable;
//extern BOOLEAN airstrikeavailable;
void CheckForAndSetupAirRaid ();
void EnemyCallInAirStrike (INT16 sSectorX, INT16 sSectorY);
//void CheckForAndSetupAirRaid ();
//void EnemyCallInAirStrike (INT16 sSectorX, INT16 sSectorY);
// will a sam site under the players control shoot down an airraid?
BOOLEAN WillAirRaidBeStopped( INT16 sSectorX, INT16 sSectorY );
+5 -4
View File
@@ -882,6 +882,7 @@ UINT8 CalcAPsToBurst( INT8 bBaseActionPoints, OBJECTTYPE * pObj )
aps = (aps * 100) / (100 + GetAPReductionStatus(pObj) / (100/GetPercentAPReduction(pObj)));
}*/
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcAPsToBurst: before bonus aps = %d, std bonus = %d, burst bonus = %d", aps,GetPercentAPReduction(pObj),GetPercentBurstFireAPReduction(pObj)));
// Snap: do this a little differently: % reduction means
// aps <- aps * ( 100 - red ) / 100
aps = ( aps * ( 100 - GetPercentAPReduction(pObj) ) + 50 ) / 100;
@@ -894,6 +895,7 @@ UINT8 CalcAPsToBurst( INT8 bBaseActionPoints, OBJECTTYPE * pObj )
if ( aps < 0 ) aps = 0;
else if ( aps > AP_MAXIMUM ) aps = AP_MAXIMUM;
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcAPsToBurst: return aps = %d", aps));
return (UINT8) aps;
}
@@ -930,18 +932,19 @@ UINT8 CalcAPsToAutofire( INT8 bBaseActionPoints, OBJECTTYPE * pObj, UINT8 bDoAut
// DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcAPsToAutofire: found reflex sight, aps = %d, # shots = %d",aps,pSoldier->bDoAutofire ));
//}
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcAPsToAutoFire: before bonus aps = %d, std bonus = %d, auto bonus = %d", aps,GetPercentAPReduction(pObj),GetPercentAutofireAPReduction(pObj)));
aps = ( aps * ( 100 - GetPercentAPReduction(pObj) ) + 50 ) / 100;
aps = __max( aps, ( autofireaps + 1 ) / 2 );
// Snap: extend the burst bonus to autofire as well?
aps = ( aps * ( 100 - GetPercentBurstFireAPReduction(pObj) ) + 50 ) / 100;
aps = ( aps * ( 100 - GetPercentAutofireAPReduction(pObj) ) + 50 ) / 100;
if ( aps < 0 ) aps = 0;
else if ( aps > AP_MAXIMUM ) aps = AP_MAXIMUM;
}
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcAPsToAutoFire: return aps = %d", aps));
return (UINT8) aps;
}
@@ -1312,8 +1315,6 @@ UINT8 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAddTurni
// bFullAPs are BASE APs, which do not include APs caried over from the previous turn.
bFullAPs = CalcActionPoints( pSoldier );
//bFullAPs = pSoldier->bInitialActionPoints;//CalcActionPoints( pSoldier ); //lal
// aim skill is the same whether we are using 1 or 2 guns
bAimSkill = CalcAimSkill( pSoldier, usItem );
+17 -17
View File
@@ -198,7 +198,7 @@ void ResetRain()
void GenerateRainDropsList()
{
guiCurrMaxAmountOfRainDrops = (UINT32)BASE_MAXIMUM_DROPS * gbCurrentRainIntensity;
guiCurrMaxAmountOfRainDrops = (UINT32)(BASE_MAXIMUM_DROPS * gbCurrentRainIntensity);
pRainDrops = (TRainDrop *)MemAlloc( sizeof( TRainDrop ) * guiCurrMaxAmountOfRainDrops );
memset( pRainDrops, 0, sizeof( TRainDrop ) * guiCurrMaxAmountOfRainDrops );
@@ -235,8 +235,8 @@ void CreateRainDrops()
BOOLEAN fLoopIsDone;
UINT32 uiIndRand;
fpCos = cos( DEGREE(fpCurrDropAngleOfFalling) );
fpSin = sin( DEGREE(fpCurrDropAngleOfFalling) );
fpCos = (FLOAT)(cos( DEGREE(fpCurrDropAngleOfFalling) ));
fpSin = (FLOAT)(sin( DEGREE(fpCurrDropAngleOfFalling) ));
if( fpCos )
fpAbsTg = fabs( fpSin / fpCos ); // take only absolute valuse
@@ -288,20 +288,20 @@ void CreateRainDrops()
if( uiIndex >= fpNumDropsToXBorder )
{
pCurr->fpX = gRainRegion.left + Random( gRainRegion.right - gRainRegion.left );
pCurr->fpY = gRainRegion.bottom - 1;
pCurr->fpX = (FLOAT)(gRainRegion.left + Random( gRainRegion.right - gRainRegion.left ));
pCurr->fpY = (FLOAT)(gRainRegion.bottom - 1);
}
else if( fpCos > 0 )
{
pCurr->fpX = gRainRegion.right - 1;
pCurr->fpY = gRainRegion.top + Random( gRainRegion.bottom - gRainRegion.top );
pCurr->fpX = (FLOAT)(gRainRegion.right - 1);
pCurr->fpY = (FLOAT)(gRainRegion.top + Random( gRainRegion.bottom - gRainRegion.top ));
}else{
pCurr->fpX = 0;
pCurr->fpY = gRainRegion.top + Random( gRainRegion.bottom - gRainRegion.top );
pCurr->fpY = (FLOAT)(gRainRegion.top + Random( gRainRegion.bottom - gRainRegion.top ));
}
}else{
pCurr->fpX = gRainRegion.left + Random( gRainRegion.right - gRainRegion.left );
pCurr->fpY = gRainRegion.top + Random( gRainRegion.bottom - gRainRegion.top );
pCurr->fpX = (FLOAT)(gRainRegion.left + Random( gRainRegion.right - gRainRegion.left ));
pCurr->fpY = (FLOAT)(gRainRegion.top + Random( gRainRegion.bottom - gRainRegion.top ));
}
pCurr->uiAmountOfTicksToLive = 0;
@@ -405,7 +405,7 @@ void RenderRainOnSurface()
if( !pCurr->fAlive )continue;
LineDraw( TRUE, pCurr->fpX, pCurr->fpY, pCurr->fpX + pCurr->fpEndRelX, pCurr->fpY + pCurr->fpEndRelY, sDropsColor, pDestBuf );
LineDraw( TRUE, (int)pCurr->fpX, (int)pCurr->fpY, (int)pCurr->fpX + (int)pCurr->fpEndRelX, (int)(pCurr->fpY + pCurr->fpEndRelY), sDropsColor, pDestBuf );
}
UnLockVideoSurface( guiRainRenderSurface );
@@ -427,35 +427,35 @@ void GenerateRainMaximums()
fpMaxDropAngleOfFalling = 160;
}
fpCurrDropAngleOfFalling = fpMinDropAngleOfFalling + Random( fpMaxDropAngleOfFalling - fpMinDropAngleOfFalling );
fpCurrDropAngleOfFalling = fpMinDropAngleOfFalling + Random( (UINT32)(fpMaxDropAngleOfFalling - fpMinDropAngleOfFalling) );
fpMinDropLength = MIN_DROP_LENGTH + ADD_DROP_LENGTH_IF_STORM * ( gbCurrentRainIntensity - 1 );
fpMaxDropLength = fpMinDropLength + DROP_LENGTH_RANGE;
fpCurrDropLength = fpMinDropLength + Random( fpMaxDropLength - fpMinDropLength );
fpCurrDropLength = fpMinDropLength + Random( (UINT32)(fpMaxDropLength - fpMinDropLength) );
fpMinDropSpeed = BASE_DROP_SPEED * gbCurrentRainIntensity;
fpMaxDropSpeed = fpMinDropSpeed + DROP_SPEED_RANGE;
fpCurrDropSpeed = fpMinDropSpeed + Random( fpMaxDropSpeed - fpMinDropSpeed );
fpCurrDropSpeed = fpMinDropSpeed + Random( (UINT32)(fpMaxDropSpeed - fpMinDropSpeed) );
}
void UpdateRainDropsProperities()
{
fpCurrDropAngleOfFalling += Random( 1000 * DROP_ANGLE_CHANGE_RATE * gbCurrentRainIntensity * 2 ) / 1000.0f - DROP_ANGLE_CHANGE_RATE * gbCurrentRainIntensity;
fpCurrDropAngleOfFalling += Random( (UINT32)(1000 * DROP_ANGLE_CHANGE_RATE * gbCurrentRainIntensity * 2 )) / 1000.0f - DROP_ANGLE_CHANGE_RATE * gbCurrentRainIntensity;
fpCurrDropAngleOfFalling = max( fpMinDropAngleOfFalling, fpCurrDropAngleOfFalling );
fpCurrDropAngleOfFalling = min( fpMaxDropAngleOfFalling, fpCurrDropAngleOfFalling );
fpCurrDropLength += Random( 1000 * DROP_LENGTH_CHANGE_RATE * 2 ) / 1000.0f - DROP_LENGTH_CHANGE_RATE;
fpCurrDropLength += Random( (UINT32)(1000 * DROP_LENGTH_CHANGE_RATE * 2 )) / 1000.0f - DROP_LENGTH_CHANGE_RATE;
fpCurrDropLength = max( fpMinDropLength, fpCurrDropLength );
fpCurrDropLength = min( fpMaxDropLength, fpCurrDropLength );
fpCurrDropSpeed += Random( 1000 * DROP_SPEED_CHANGE_RATE * 2 ) / 1000.0f - DROP_SPEED_CHANGE_RATE;
fpCurrDropSpeed += Random( (UINT32)(1000 * DROP_SPEED_CHANGE_RATE * 2 )) / 1000.0f - DROP_SPEED_CHANGE_RATE;
fpCurrDropSpeed = max( fpMinDropSpeed, fpCurrDropSpeed );
fpCurrDropSpeed = min( fpMaxDropSpeed, fpCurrDropSpeed );
+54 -1
View File
@@ -85,6 +85,14 @@
#include "overhead map.h"
#endif
//turnspeed
UINT8 gubPlayerTurnSpeedUpFactor = 1;
UINT8 gubEnemyTurnSpeedUpFactor = 1;
UINT8 gubCreatureTurnSpeedUpFactor = 1;
UINT8 gubMilitiaTurnSpeedUpFactor = 1;
UINT8 gubCivTurnSpeedUpFactor = 1;
//turnspeed
extern INT16 DirIncrementer[8];
#define PALETTEFILENAME "BINARYDATA\\ja2pal.dat"
@@ -495,6 +503,8 @@ INT8 CalcActionPoints(SOLDIERTYPE *pSold)
//if (GameOption[INCREASEDAP] % 2 == 1)
//points += AP_INCREASE;
//Madd: Add in AP Bonuses (Penalties) from worn gear
ubPoints += GetGearAPBonus ( pSold );
// Calculate bandage
bBandage = pSold->bLifeMax - pSold->bLife - pSold->bBleeding;
@@ -5715,6 +5725,19 @@ void CalculateSoldierAniSpeed( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pStatsSoldier
// here. Some animation, such as water-movement, have an ADDITIONAL speed
switch( pSoldier->usAnimState )
{
// Lesh: bursting animation delay control begins
// Add your animation ID to control it
case STANDING_BURST:
case FIRE_STAND_BURST_SPREAD:
case FIRE_BURST_LOW_STAND:
case TANK_BURST:
case CROUCHED_BURST:
case PRONE_BURST:
pSoldier->sAniDelay = Weapon[Item[pSoldier->inv[HANDPOS].usItem].ubClassIndex].sAniDelay;
AdjustAniSpeed( pSoldier );
return;
// Lesh: end
case PRONE:
case STANDING:
@@ -5849,6 +5872,25 @@ void CalculateSoldierAniSpeed( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pStatsSoldier
}
UINT8 GetSpeedUpFactor( )
{
switch( gTacticalStatus.ubCurrentTeam )
{
case OUR_TEAM:
return gubPlayerTurnSpeedUpFactor;
case ENEMY_TEAM:
return gubEnemyTurnSpeedUpFactor;
case CREATURE_TEAM:
return gubCreatureTurnSpeedUpFactor;
case MILITIA_TEAM:
return gubMilitiaTurnSpeedUpFactor;
case CIV_TEAM:
return gubCivTurnSpeedUpFactor;
}
return 1;
}
void SetSoldierAniSpeed( SOLDIERTYPE *pSoldier )
{
@@ -5895,6 +5937,11 @@ void SetSoldierAniSpeed( SOLDIERTYPE *pSoldier )
//pSoldier->sAniDelay = 1000;
}
if ( gTacticalStatus.uiFlags & TURNBASED && gTacticalStatus.uiFlags & INCOMBAT )
if( GetSpeedUpFactor() )
pSoldier->sAniDelay /= GetSpeedUpFactor();
else
pSoldier->sAniDelay = 0;
}
@@ -9304,12 +9351,18 @@ void ReLoadSoldierAnimationDueToHandItemChange( SOLDIERTYPE *pSoldier, UINT16 us
// Shutoff burst....
// ( we could be on, then change gun that does not have burst )
if ( Weapon[ usNewItem ].ubShotsPerBurst == 0 )
if ( Weapon[ usNewItem ].ubShotsPerBurst == 0 && !Weapon[usNewItem].NoSemiAuto )
{
pSoldier->bDoBurst = FALSE;
pSoldier->bWeaponMode = WM_NORMAL;
pSoldier->bDoAutofire = 0;
}
else if ( Weapon[usNewItem].NoSemiAuto )
{
pSoldier->bDoBurst = TRUE;
pSoldier->bWeaponMode = WM_AUTOFIRE;
pSoldier->bDoAutofire = 1;
}
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_FIREREADY )
{
+1
View File
@@ -331,6 +331,7 @@ enum
HIT_BY_TEARGAS = 0x01,
HIT_BY_MUSTARDGAS = 0x02,
HIT_BY_CREATUREGAS = 0x04,
HIT_BY_BURNABLEGAS = 0x08,
};
+4 -4
View File
@@ -216,8 +216,8 @@ BOOLEAN LoadMercProfiles(void)
char *pFileName3 = "BINARYDATA\\Prof3.dat";
char *pFileName4 = "BINARYDATA\\Prof4.dat";
UINT32 uiLoop, uiLoop2, uiLoop3;
UINT16 usItem, usNewGun, usAmmo, usNewAmmo;
UINT32 uiLoop, uiLoop2;//, uiLoop3;
UINT16 usItem;//, usNewGun, usAmmo, usNewAmmo;
UINT32 uiNumBytesRead;
switch ( gGameOptions.ubDifficultyLevel)
@@ -275,7 +275,7 @@ BOOLEAN LoadMercProfiles(void)
// Setup face index value
// Default is the ubCharNum
gMercProfiles[uiLoop].ubFaceIndex = (UINT8)uiLoop;
/*
if ( !gGameOptions.fGunNut )
{
@@ -311,7 +311,7 @@ BOOLEAN LoadMercProfiles(void)
}
} // end of if not gun nut
*/
//ATE: Calculate some inital attractiveness values for buddy's inital equipment...
// Look for gun and armour
gMercProfiles[uiLoop].bMainGunAttractiveness = -1;
+65 -1265
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -163,6 +163,7 @@ void StartPlayerTeamTurn( BOOLEAN fDoBattleSnd, BOOLEAN fEnteringCombatMode )
// Check if this guy is able to be selected....
if ( MercPtrs[ gusSelectedSoldier ]->bLife < OKLIFE )
{
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("StartPlayerTeamTurn: SelectNextAvailSoldier"));
SelectNextAvailSoldier( MercPtrs[ gusSelectedSoldier ] );
}
@@ -924,6 +925,7 @@ void EndInterrupt( BOOLEAN fMarkInterruptOccurred )
// Select soldier....
if ( MercPtrs[ ubInterruptedSoldier ]->bLife < OKLIFE )
{
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("EndInterrupt: SelectNextAvailSoldier"));
SelectNextAvailSoldier( MercPtrs[ ubInterruptedSoldier ] );
}
else
+123 -42
View File
@@ -45,7 +45,7 @@
#endif
//rain
#define WEAPON_RELIABILITY_REDUCTION_PER_RAIN_INTENSITY 9
#define WEAPON_RELIABILITY_REDUCTION_PER_RAIN_INTENSITY 0
extern INT8 gbCurrentRainIntensity;
//end rain
@@ -283,7 +283,7 @@ EXPLOSIVETYPE Explosive[MAXITEMS+1];// =
//};
INT8 gzBurstSndStrings[MAXITEMS][30];// =
INT8 gzBurstSndStrings[MAXITEMS*2][128];// =
//{
// "", // NOAMMO
// "", // 38
@@ -383,14 +383,18 @@ weaponStartElementHandle(void *userData, const char *name, const char **atts)
strcmp(name, "ubHitVolume") == 0 ||
strcmp(name, "sSound") == 0 ||
strcmp(name, "sBurstSound") == 0 ||
strcmp(name, "sSilencedBurstSound") == 0 ||
strcmp(name, "sReloadSound") == 0 ||
strcmp(name, "sLocknLoadSound") == 0 ||
strcmp(name, "bBurstAP") == 0 ||
strcmp(name, "bAutofireShotsPerFiveAP") == 0 ||
strcmp(name, "APsToReload") == 0 ||
strcmp(name, "SwapClips") == 0 ||
strcmp(name, "AutoPenalty") == 0 ||
strcmp(name, "NoSemiAuto") == 0 ||
strcmp(name, "MaxDistForMessyDeath") == 0 ||
strcmp(name, "SilencedSound") == 0))
strcmp(name, "SilencedSound") == 0 || // Lesh: add new field (OR operand)
strcmp(name, "BurstAniDelay") == 0)) // Lesh: add new field (field itself)
{
pData->curElement = WEAPON_ELEMENT_WEAPON_PROPERY;
@@ -545,6 +549,11 @@ weaponEndElementHandle(void *userData, const char *name)
pData->curElement = WEAPON_ELEMENT_WEAPON;
pData->curWeapon.sBurstSound = (UINT16) atol(pData->szCharData);
}
else if(strcmp(name, "sSilencedBurstSound") == 0)
{
pData->curElement = WEAPON_ELEMENT_WEAPON;
pData->curWeapon.sSilencedBurstSound = (UINT16) atol(pData->szCharData);
}
else if(strcmp(name, "sReloadSound") == 0)
{
pData->curElement = WEAPON_ELEMENT_WEAPON;
@@ -573,18 +582,36 @@ weaponEndElementHandle(void *userData, const char *name)
else if(strcmp(name, "SilencedSound") == 0)
{
pData->curElement = WEAPON_ELEMENT_WEAPON;
pData->curWeapon.silencedSound = (UINT8) atol(pData->szCharData);
pData->curWeapon.silencedSound = (UINT16) atol(pData->szCharData);
}
else if(strcmp(name, "SwapClips") == 0)
{
pData->curElement = WEAPON_ELEMENT_WEAPON;
pData->curWeapon.swapClips = (UINT8) atol(pData->szCharData);
pData->curWeapon.swapClips = (BOOLEAN) atol(pData->szCharData);
}
else if(strcmp(name, "MaxDistForMessyDeath") == 0)
{
pData->curElement = WEAPON_ELEMENT_WEAPON;
pData->curWeapon.maxdistformessydeath = (UINT8) atol(pData->szCharData);
}
else if(strcmp(name, "AutoPenalty") == 0)
{
pData->curElement = WEAPON_ELEMENT_WEAPON;
pData->curWeapon.AutoPenalty = (UINT8) atol(pData->szCharData);
}
else if(strcmp(name, "NoSemiAuto") == 0)
{
pData->curElement = WEAPON_ELEMENT_WEAPON;
pData->curWeapon.NoSemiAuto = (BOOLEAN) atol(pData->szCharData);
}
// Lesh: xmlreader must handle new field
else if(strcmp(name, "BurstAniDelay") == 0)
{
pData->curElement = WEAPON_ELEMENT_WEAPON;
pData->curWeapon.sAniDelay = (INT16) atol(pData->szCharData);
}
// Lesh: end
pData->maxReadDepth--;
}
@@ -731,6 +758,7 @@ BOOLEAN ReadInWeaponStats(STR fileName)
FilePrintf(hFile,"\t\t<ubHitVolume>%d</ubHitVolume>\r\n", Weapon[cnt].ubHitVolume);
FilePrintf(hFile,"\t\t<sSound>%d</sSound>\r\n", Weapon[cnt].sSound);
FilePrintf(hFile,"\t\t<sBurstSound>%d</sBurstSound>\r\n", Weapon[cnt].sBurstSound);
FilePrintf(hFile,"\t\t<sSilencedBurstSound>%d</sSilencedBurstSound>\r\n", Weapon[cnt].sSilencedBurstSound);
FilePrintf(hFile,"\t\t<sReloadSound>%d</sReloadSound>\r\n", Weapon[cnt].sReloadSound);
FilePrintf(hFile,"\t\t<sLocknLoadSound>%d</sLocknLoadSound>\r\n", Weapon[cnt].sLocknLoadSound);
FilePrintf(hFile,"\t\t<bBurstAP>%d</bBurstAP>\r\n", Weapon[cnt].bBurstAP);
@@ -827,10 +855,12 @@ BOOLEAN WriteWeaponStats()
FilePrintf(hFile,"\t\t<ubMagSize>%d</ubMagSize>\r\n", Weapon[cnt].ubMagSize);
FilePrintf(hFile,"\t\t<usRange>%d</usRange>\r\n", Weapon[cnt].usRange);
FilePrintf(hFile,"\t\t<usReloadDelay>%d</usReloadDelay>\r\n", Weapon[cnt].usReloadDelay);
FilePrintf(hFile,"\t\t<BurstAniDelay>%d</BurstAniDelay>\r\n", Weapon[cnt].sAniDelay);
FilePrintf(hFile,"\t\t<ubAttackVolume>%d</ubAttackVolume>\r\n", Weapon[cnt].ubAttackVolume);
FilePrintf(hFile,"\t\t<ubHitVolume>%d</ubHitVolume>\r\n", Weapon[cnt].ubHitVolume);
FilePrintf(hFile,"\t\t<sSound>%d</sSound>\r\n", Weapon[cnt].sSound);
FilePrintf(hFile,"\t\t<sBurstSound>%d</sBurstSound>\r\n", Weapon[cnt].sBurstSound);
FilePrintf(hFile,"\t\t<sSilencedBurstSound>%d</sSilencedBurstSound>\r\n", Weapon[cnt].sSilencedBurstSound);
FilePrintf(hFile,"\t\t<sReloadSound>%d</sReloadSound>\r\n", Weapon[cnt].sReloadSound);
FilePrintf(hFile,"\t\t<sLocknLoadSound>%d</sLocknLoadSound>\r\n", Weapon[cnt].sLocknLoadSound);
FilePrintf(hFile,"\t\t<SilencedSound>%d</SilencedSound>\r\n", Weapon[cnt].silencedSound );
@@ -839,6 +869,8 @@ BOOLEAN WriteWeaponStats()
FilePrintf(hFile,"\t\t<APsToReload>%d</APsToReload>\r\n", Weapon[cnt].APsToReload);
FilePrintf(hFile,"\t\t<SwapClips>%d</SwapClips>\r\n", Weapon[cnt].swapClips );
FilePrintf(hFile,"\t\t<MaxDistForMessyDeath>%d</MaxDistForMessyDeath>\r\n", Weapon[cnt].maxdistformessydeath);
FilePrintf(hFile,"\t\t<AutoPenalty>%d</AutoPenalty>\r\n", Weapon[cnt].AutoPenalty);
FilePrintf(hFile,"\t\t<NoSemiAuto>%d</NoSemiAuto>\r\n", Weapon[cnt].NoSemiAuto);
@@ -924,7 +956,7 @@ INT32 EffectiveArmour( OBJECTTYPE * pObj )
iValue += iValue2;
}
return( iValue );
return( max(iValue,1) );
}
INT32 ArmourPercent( SOLDIERTYPE * pSoldier )
@@ -993,7 +1025,7 @@ INT32 ExplosiveEffectiveArmour( OBJECTTYPE * pObj )
iValue += iValue2;
}
return( iValue );
return( max(iValue,1) );
}
INT8 ArmourVersusExplosivesPercent( SOLDIERTYPE * pSoldier )
@@ -1064,7 +1096,6 @@ void AdjustImpactByHitLocation( INT32 iImpact, UINT8 ubHitLocation, INT32 * piNe
//rain
extern INT8 gbCurrentRainIntensity;
//end rain
BOOLEAN CheckForGunJam( SOLDIERTYPE * pSoldier )
{
OBJECTTYPE * pObj;
@@ -1096,7 +1127,7 @@ BOOLEAN CheckForGunJam( SOLDIERTYPE * pSoldier )
//iChance = iChance * (10 - Item[pObj->usItem].bReliability * 2) / 10;
//rain
iChance = iChance * (10 - Item[pObj->usItem].bReliability * 2) / 10;
// iChance = iChance * (10 - Item[pObj->usItem].bReliability * 2) / 10; // Madd: took it back out
//end rain
if (pSoldier->bDoBurst > 1)
@@ -1130,7 +1161,7 @@ BOOLEAN CheckForGunJam( SOLDIERTYPE * pSoldier )
else if (pObj->bGunAmmoStatus < 0)
{
// try to unjam gun
iResult = SkillCheck( pSoldier, UNJAM_GUN_CHECK, (INT8) (Item[pObj->usItem].bReliability * 4) );
iResult = SkillCheck( pSoldier, UNJAM_GUN_CHECK, (INT8) ((Item[pObj->usItem].bReliability + Item[pObj->usGunAmmoItem].bReliability)* 4) );
if (iResult > 0)
{
// yay! unjammed the gun
@@ -1457,7 +1488,7 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT16 sTargetGridNo )
if( noisefactor < MAX_PERCENT_NOISE_VOLUME_FOR_SILENCED_SOUND || Weapon[ usItemNum ].ubAttackVolume <= 10 )
{
// Pick sound file baed on how many bullets we are going to fire...
sprintf( (char *)zBurstString, "SOUNDS\\WEAPONS\\SILENCER BURST %d.wav", pSoldier->bBulletsLeft );
sprintf( (char *)zBurstString, (const char*)gzBurstSndStrings[ Weapon[ usItemNum ].sSilencedBurstSound ], pSoldier->bBulletsLeft );
// Try playing sound...
pSoldier->iBurstSoundID = PlayJA2SampleFromFile( (STR8) zBurstString, RATE_11025, SoundVolume( HIGHVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
@@ -1465,7 +1496,8 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT16 sTargetGridNo )
else
{
// Pick sound file baed on how many bullets we are going to fire...
sprintf( (char *)zBurstString, "SOUNDS\\WEAPONS\\%s%d.wav", gzBurstSndStrings[ Weapon[ usItemNum ].ubCalibre ], pSoldier->bBulletsLeft );
// Lesh: changed next line
sprintf( (char *)zBurstString, (const char*)gzBurstSndStrings[ Weapon[ usItemNum ].sBurstSound ], pSoldier->bBulletsLeft );
INT8 volume = HIGHVOLUME;
if ( noisefactor < 100 ) volume = (volume * noisefactor) / 100;
@@ -1860,7 +1892,11 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT16 sTargetGridNo )
}
// CJC: since jamming is no longer affected by reliability, increase chance of status going down for really unreliabile guns
uiDepreciateTest = BASIC_DEPRECIATE_CHANCE + 3 * Item[ usItemNum ].bReliability;
INT16 ammoReliability = 0; // Madd: ammo reliability affects gun
if ( Item[usItemNum].usItemClass == IC_GUN )
ammoReliability = Item[pSoldier->inv[pSoldier->ubAttackingHand].usItem].bReliability;
uiDepreciateTest = BASIC_DEPRECIATE_CHANCE + 3 * (Item[ usItemNum ].bReliability + ammoReliability);
if ( !PreRandom( uiDepreciateTest ) && ( pSoldier->inv[ pSoldier->ubAttackingHand ].bStatus[0] > 1) )
{
@@ -2929,7 +2965,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT8 bWeaponStatus, UINT
if ( usStructureID == INVALID_STRUCTURE_ID )
{
// Add item
CreateItem( THROWING_KNIFE, bWeaponStatus, &Object );
CreateItem( usWeaponIndex, bWeaponStatus, &Object );
AddItemToPool( sGridNo, &Object, -1 , 0, 0, -1 );
@@ -3209,7 +3245,7 @@ BOOLEAN InRange( SOLDIERTYPE *pSoldier, INT16 sGridNo )
if ( Item[ usInHand ].usItemClass == IC_THROWING_KNIFE )
{
// NB CalcMaxTossRange returns range in tiles, not in world units
if ( sRange <= CalcMaxTossRange( pSoldier, THROWING_KNIFE, TRUE ) * CELL_X_SIZE )
if ( sRange <= CalcMaxTossRange( pSoldier, usInHand, TRUE ) * CELL_X_SIZE )
{
return( TRUE );
}
@@ -3230,9 +3266,9 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, UINT16 sGridNo, UINT8 ubAimTime
{
//SOLDIERTYPE *vicpSoldier;
SOLDIERTYPE * pTarget;
INT32 iChance, iRange, iSightRange, iMaxRange, iBonus; //, minRange;
//rain
//INT32 iChance, iRange, iSightRange, iMaxRange, iBonus; //, minRange;
INT32 iChance, iRange, iSightRange, iMaxRange, iScopeBonus, iBonus; //, minRange;
//INT32 iScopeBonus;
//end rain
INT32 iGunCondition, iMarksmanship;
@@ -3347,36 +3383,43 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, UINT16 sGridNo, UINT8 ubAimTime
}
}
//Madd: inherent weapon accuracy bonus
iChance += Weapon[usInHand].bAccuracy;
// if ( !(Item[ usInHand ].fFlags & ITEM_TWO_HANDED) )
if ( !(Item[ usInHand ].twohanded ) )
{
// SMGs are treated as pistols for these purpose except there is a -5 penalty;
if (Weapon[usInHand].ubWeaponClass == SMGCLASS)
{
iChance -= AIM_PENALTY_SMG;
}
/*
if (pSoldier->inv[SECONDHANDPOS].usItem == NOTHING)
{
// firing with pistol in right hand, and second hand empty.
iChance += AIM_BONUS_TWO_HANDED_PISTOL;
// firing with gun in right hand, and second hand empty (ie: no grenade, med kit or anything there)
// Madd: easier to fire pistol/smg w/one hand free, essentially this will make pistols a little bit more accurate, and hopefully still useful later in the game
if (Weapon[usInHand].ubWeaponClass == HANDGUNCLASS)
iChance += AIM_BONUS_TWO_HANDED_PISTOL;
}
else */
if ( !HAS_SKILL_TRAIT( pSoldier, AMBIDEXT ) )
else
{
if ( IsValidSecondHandShot( pSoldier ) )
// Madd: harder to fire smgs w/something in other hand
// SMGs are treated as pistols for these purpose except there is a -5 penalty;
if (Weapon[usInHand].ubWeaponClass == SMGCLASS)
{
// penalty to aim when firing two pistols
iChance -= AIM_PENALTY_DUAL_PISTOLS;
iChance -= AIM_PENALTY_SMG;
}
/*
else
if ( !HAS_SKILL_TRAIT( pSoldier, AMBIDEXT ) )
{
// penalty to aim with pistol being fired one-handed
iChance -= AIM_PENALTY_ONE_HANDED_PISTOL;
if ( IsValidSecondHandShot( pSoldier ) )
{
// penalty to aim when firing two pistols
iChance -= AIM_PENALTY_DUAL_PISTOLS;
}
/*
else
{
// penalty to aim with pistol being fired one-handed
iChance -= AIM_PENALTY_ONE_HANDED_PISTOL;
}
*/
}
*/
}
}
@@ -3394,6 +3437,19 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, UINT16 sGridNo, UINT8 ubAimTime
}
iChance -= iPenalty;
}
else if ( pSoldier->bDoAutofire > 0 )
{
// Snap: bipod may reduce auto penalty
iPenalty = GetAutoPenalty(pInHand, gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE)
* (pSoldier->bDoBurst - 1);
// halve the penalty for people with the autofire trait
if ( HAS_SKILL_TRAIT( pSoldier, AUTO_WEAPS ) )
{
iPenalty /= 2 * NUM_SKILL_TRAITS( pSoldier, AUTO_WEAPS );
}
iChance -= iPenalty;
}
sDistVis = DistanceVisible( pSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, 0, pSoldier );
@@ -3497,7 +3553,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, UINT16 sGridNo, UINT8 ubAimTime
//rain
// reduce scope effectiveness when it's raining
iScopeBonus /= 1 + gbCurrentRainIntensity;
// iScopeBonus /= 1 + gbCurrentRainIntensity; //madd: commented out -- didn't do anything but cause a warning :S
//end rain
// // reduce effective range by the bonus obtained from the scope
@@ -3537,18 +3593,26 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, UINT16 sGridNo, UINT8 ubAimTime
//}
//Madd: Some gear can affect the to-hit bonus and the bonus from aiming
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcChanceToHitGun: before bonus - ubAimTime = %d, iSightRange = %d, iChance = %d ", ubAimTime, iSightRange, iChance));
iSightRange -= GetGearAimBonus ( pSoldier, iRange, ubAimTime );
iChance += GetGearToHitBonus ( pSoldier );
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcChanceToHitGun: after gear bonus - ubAimTime = %d, iSightRange = %d, iChance = %d ", ubAimTime, iSightRange, iChance));
// Reduce effective range by the aiming bonus (e.g. from sniper scope)
iSightRange -= GetAimBonus( pInHand, iRange, ubAimTime );
if (iSightRange < 1)
{
iSightRange = 1;
}
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcChanceToHitGun: after scope bonus - ubAimTime = %d, iSightRange = %d, iChance = %d ", ubAimTime, iSightRange, iChance));
UINT8 bLightLevel = LightTrueLevel(sGridNo, pSoldier->bTargetLevel);
// Apply flat to-hit bonus (e.g. from laser scope)
// Snap: If prone and range is good, apply bipod bonus here as well
iChance += GetToHitBonus( pInHand, iSightRange, bLightLevel,
gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE && iRange > MIN_PRONE_RANGE );
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcChanceToHitGun: after to hit bonus - ubAimTime = %d, iSightRange = %d, iChance = %d ", ubAimTime, iSightRange, iChance));
}
// if aiming at the head, reduce chance to hit
@@ -3838,6 +3902,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, UINT16 sGridNo, UINT8 ubAimTime
}
// NumMessage("ChanceToHit = ",chance);
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcChanceToHitGun: ichance = %d",iChance));
return (iChance);
}
@@ -4920,13 +4985,13 @@ BOOLEAN IsGunWeaponModeCapable( SOLDIERTYPE *pSoldier, UINT8 ubHandPos , UINT8 b
switch(bWpnMode)
{
case WM_NORMAL:
return (pSoldier->inv[ ubHandPos ].usItem != NOTHING && Item[ pSoldier->inv[ ubHandPos ].usItem ].usItemClass & IC_WEAPON); // Check for being a weapon....
return (pSoldier->inv[ ubHandPos ].usItem != NOTHING && Item[ pSoldier->inv[ ubHandPos ].usItem ].usItemClass & IC_WEAPON && !Weapon[ pSoldier->inv[ ubHandPos ].usItem ].NoSemiAuto ); // Check for being a weapon....
case WM_BURST:
return IsGunBurstCapable(pSoldier, ubHandPos, FALSE);
case WM_AUTOFIRE:
return (IsGunAutofireCapable(pSoldier, ubHandPos) && !Item[pSoldier->inv[ubHandPos].usItem].grenadelauncher );
return ((IsGunAutofireCapable(pSoldier, ubHandPos) || Weapon[ pSoldier->inv[ ubHandPos ].usItem ].NoSemiAuto )&& !Item[pSoldier->inv[ubHandPos].usItem].grenadelauncher );
case WM_ATTACHED_GL:
// return (FindAttachment( &(pSoldier->inv[ubHandPos]), UNDER_GLAUNCHER ) != ITEM_NOT_FOUND && FindLaunchableAttachment( &(pSoldier->inv[ubHandPos]), UNDER_GLAUNCHER ) != ITEM_NOT_FOUND );
@@ -5272,10 +5337,14 @@ void ChangeWeaponMode( SOLDIERTYPE * pSoldier )
{
pSoldier->bWeaponMode++;
if(pSoldier->bWeaponMode == NUM_WEAPON_MODES)
pSoldier->bWeaponMode = WM_NORMAL;
{
if ( Weapon[pSoldier->inv[HANDPOS].usItem].NoSemiAuto )
pSoldier->bWeaponMode = WM_AUTOFIRE;
else
pSoldier->bWeaponMode = WM_NORMAL;
}
}
while(IsGunWeaponModeCapable( pSoldier, HANDPOS, pSoldier->bWeaponMode ) == FALSE && pSoldier->bWeaponMode != WM_NORMAL);
if (pSoldier->bWeaponMode == WM_AUTOFIRE || pSoldier->bWeaponMode == WM_ATTACHED_GL_AUTO )
{
@@ -5414,11 +5483,22 @@ UINT8 GetBurstPenalty( OBJECTTYPE *pObj, BOOLEAN fProneStance )
return Weapon[ pObj->usItem ].ubBurstPenalty - bns;
}
UINT8 GetAutoPenalty( OBJECTTYPE *pObj, BOOLEAN fProneStance )
{
// Snap: Make sure burst bonus does not exceed burst penalty!
INT16 bns = GetAutoToHitBonus(pObj, fProneStance);
if ( bns > Weapon[ pObj->usItem ].AutoPenalty ) {
return 0;
}
return Weapon[ pObj->usItem ].AutoPenalty - bns;
}
UINT8 GetAutofireShotsPerFiveAPs( OBJECTTYPE *pObj )
{
// DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("GetAutofireShotsPerFiveAPs"));
return Weapon[ pObj->usItem ].bAutofireShotsPerFiveAP + GetAutofireBonus(pObj);
return Weapon[ pObj->usItem ].bAutofireShotsPerFiveAP;
}
UINT8 GetMagSize( OBJECTTYPE *pObj )
@@ -5444,3 +5524,4 @@ INT8 GetAPsToReload( OBJECTTYPE *pObj )
( 100 - GetPercentReloadTimeAPReduction(pObj) ) + 50 ) / 100;
}
+9 -4
View File
@@ -178,7 +178,8 @@ enum
EXPLOSV_FLARE,
EXPLOSV_NOISE,
EXPLOSV_SMOKE,
EXPLOSV_CREATUREGAS,
EXPLOSV_CREATUREGAS,
EXPLOSV_BURNABLEGAS,
};
#define AMMO_DAMAGE_ADJUSTMENT_BUCKSHOT( x ) (x / 4)
@@ -250,6 +251,7 @@ typedef struct
UINT8 ubHitVolume;
UINT16 sSound;
UINT16 sBurstSound;
UINT16 sSilencedBurstSound;
UINT16 sReloadSound;
UINT16 sLocknLoadSound;
UINT8 bBurstAP; // Snap: Burst AP cost replaces bBaseAutofireCost
@@ -259,12 +261,14 @@ typedef struct
UINT32 uiIndex;
BOOLEAN swapClips;
UINT8 silencedSound;
UINT16 silencedSound;
UINT8 APsToReload;
UINT8 maxdistformessydeath;
BOOLEAN NoSemiAuto;
UINT8 AutoPenalty;
INT16 sAniDelay; // Lesh: for burst animation delay
} WEAPONTYPE;
typedef struct
{
UINT8 ubCalibre;
@@ -302,7 +306,7 @@ extern WEAPONTYPE Weapon[ MAXITEMS ];
extern ARMOURTYPE Armour[MAXITEMS+1];
extern MAGTYPE Magazine[MAXITEMS+1];
extern EXPLOSIVETYPE Explosive[MAXITEMS+1];
extern INT8 gzBurstSndStrings[MAXITEMS][30];
extern INT8 gzBurstSndStrings[MAXITEMS*2][128]; // Lesh: changed this
extern AMMOTYPE AmmoTypes[MAXITEMS];
@@ -353,6 +357,7 @@ UINT8 GetDamage ( OBJECTTYPE *pObj );
UINT8 GetAutofireShotsPerFiveAPs( OBJECTTYPE *pObj );
UINT8 GetBaseAutoFireCost( OBJECTTYPE *pObj );
UINT8 GetBurstPenalty( OBJECTTYPE *pObj, BOOLEAN fProneStance = FALSE );
UINT8 GetAutoPenalty( OBJECTTYPE *pObj, BOOLEAN fProneStance = FALSE );
UINT8 GetShotsPerBurst( OBJECTTYPE *pObj );
UINT8 GetMagSize( OBJECTTYPE *pObj );
BOOLEAN WeaponReady(SOLDIERTYPE * pSoldier);
+3 -1
View File
@@ -415,7 +415,7 @@ void LoadWorldItemsFromMap( INT8 **hBuffer )
{ //no match, so don't add item to world
continue;
}
/*
if ( !gGameOptions.fGunNut )
{
UINT16 usReplacement;
@@ -458,6 +458,8 @@ void LoadWorldItemsFromMap( INT8 **hBuffer )
}
}
}
*/
}
if( dummyItem.o.usItem == ACTION_ITEM && gfLoadPitsWithoutArming )
{ //if we are loading a pit, they are typically loaded without being armed.
+6 -1
View File
@@ -57,6 +57,7 @@ typedef PARSE_STAGE;
#define BOBBYRAYSTRINGSFILENAME "BobbyRayStrings.xml"
#define AMMOCALIBERSTRINGSFILENAME "AmmoCaliberStrings.xml"
#define SOUNDSFILENAME "Sounds.xml"
#define BURSTSOUNDSFILENAME "BurstSounds.xml"
#define CITYTABLEFILENAME "Cities.xml"
@@ -117,4 +118,8 @@ extern BOOLEAN ReadInSoundArray(STR fileName);
extern BOOLEAN ReadInAmmoTypeStats(STR fileName);
extern BOOLEAN WriteAmmoTypeStats();
#endif
// Lesh: 2 lines added
extern BOOLEAN ReadInBurstSoundArray(STR fileName);
extern BOOLEAN WriteBurstSoundArray();
// Lesh: over
#endif
+345
View File
@@ -0,0 +1,345 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include "sgp.h"
#include "overhead types.h"
#include "Sound Control.h"
#include "Soldier Control.h"
#include "overhead.h"
#include "Event Pump.h"
#include "weapons.h"
#include "Animation Control.h"
#include "sys globals.h"
#include "Handle UI.h"
#include "Isometric Utils.h"
#include "worldman.h"
#include "math.h"
#include "points.h"
#include "ai.h"
#include "los.h"
#include "renderworld.h"
#include "opplist.h"
#include "interface.h"
#include "message.h"
#include "campaign.h"
#include "items.h"
#include "text.h"
#include "Soldier Profile.h"
#include "tile animation.h"
#include "Dialogue Control.h"
#include "SkillCheck.h"
#include "explosion control.h"
#include "Quests.h"
#include "Physics.h"
#include "Random.h"
#include "Vehicles.h"
#include "bullets.h"
#include "morale.h"
#include "meanwhile.h"
#include "SkillCheck.h"
#include "gamesettings.h"
#include "SaveLoadMap.h"
#include "Debug Control.h"
#include "expat.h"
#include "XML.h"
#endif
struct
{
PARSE_STAGE curElement;
INT8 szCharData[MAX_CHAR_DATA_LENGTH+1];
UINT32 maxArraySize;
UINT32 curIndex;
UINT32 currentDepth;
UINT32 maxReadDepth;
}
typedef ammoParseData;
static void XMLCALL
ammoStartElementHandle(void *userData, const char *name, const char **atts)
{
ammoParseData * pData = (ammoParseData *)userData;
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
{
if(strcmp(name, "AMMOLIST") == 0 && pData->curElement == ELEMENT_NONE)
{
pData->curElement = ELEMENT_LIST;
pData->maxReadDepth++; //we are not skipping this element
}
else if(strcmp(name, "AMMO") == 0 && pData->curElement == ELEMENT_LIST)
{
pData->curElement = ELEMENT;
pData->maxReadDepth++; //we are not skipping this element
pData->curIndex++;
}
else if(pData->curElement == ELEMENT &&
(strcmp(name, "AmmoCaliber") == 0 ||
strcmp(name, "BRCaliber") == 0 ))
{
pData->curElement = ELEMENT_PROPERTY;
pData->maxReadDepth++; //we are not skipping this element
}
pData->szCharData[0] = '\0';
}
pData->currentDepth++;
}
static void XMLCALL
ammoCharacterDataHandle(void *userData, const char *str, int len)
{
ammoParseData * pData = (ammoParseData *)userData;
if( (pData->currentDepth <= pData->maxReadDepth) &&
(strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH)
){
strncat(pData->szCharData,str,__min((unsigned int)len,MAX_CHAR_DATA_LENGTH-strlen(pData->szCharData)));
}
}
static void XMLCALL
ammoEndElementHandle(void *userData, const char *name)
{
char temp;
ammoParseData * pData = (ammoParseData *)userData;
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
{
if(strcmp(name, "AMMOLIST") == 0)
{
pData->curElement = ELEMENT_NONE;
}
else if(strcmp(name, "AMMO") == 0)
{
pData->curElement = ELEMENT_LIST;
}
else if(strcmp(name, "AmmoCaliber") == 0)
{
pData->curElement = ELEMENT;
if(pData->curIndex < pData->maxArraySize)
{
for(int i=0;i<min((int)strlen(pData->szCharData),MAX_CHAR_DATA_LENGTH);i++)
{
temp = pData->szCharData[i];
AmmoCaliber[pData->curIndex][i] = temp;
}
}
}
else if(strcmp(name, "BRCaliber") == 0)
{
pData->curElement = ELEMENT;
if(pData->curIndex < pData->maxArraySize)
{
for(int i=0;i<min((int)strlen(pData->szCharData),MAX_CHAR_DATA_LENGTH);i++)
{
temp = pData->szCharData[i];
BobbyRayAmmoCaliber[pData->curIndex][i] = temp;
}
}
}
pData->maxReadDepth--;
}
pData->currentDepth--;
}
BOOLEAN ReadInAmmoStats(STR fileName)
{
HWFILE hFile;
UINT32 uiBytesRead;
UINT32 uiFSize;
CHAR8 * lpcBuffer;
XML_Parser parser = XML_ParserCreate(NULL);
ammoParseData pData;
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading AmmoStrings.xml" );
// Open ammos file
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
if ( !hFile )
return( FALSE );
uiFSize = FileGetSize(hFile);
lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1);
//Read in block
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
{
MemFree(lpcBuffer);
return( FALSE );
}
lpcBuffer[uiFSize] = 0; //add a null terminator
FileClose( hFile );
XML_SetElementHandler(parser, ammoStartElementHandle, ammoEndElementHandle);
XML_SetCharacterDataHandler(parser, ammoCharacterDataHandle);
memset(&pData,0,sizeof(pData));
pData.maxArraySize = MAXITEMS;
pData.curIndex = -1;
XML_SetUserData(parser, &pData);
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
{
CHAR8 errorBuf[511];
sprintf(errorBuf, "XML Parser Error in AmmoStrings.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
LiveMessage(errorBuf);
MemFree(lpcBuffer);
return FALSE;
}
MemFree(lpcBuffer);
XML_ParserFree(parser);
return( TRUE );
}
BOOLEAN WriteAmmoStats()
{
HWFILE hFile;
//Debug code; make sure that what we got from the file is the same as what's there
// Open a new file
hFile = FileOpen( "TABLEDATA\\Ammos out.xml", FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE );
if ( !hFile )
return( FALSE );
{
UINT32 cnt;
FilePrintf(hFile,"<AMMOLIST>\r\n");
for(cnt = 0;cnt < MAXITEMS;cnt++)
{
FilePrintf(hFile,"\t<AMMO>\r\n");
UINT16 * szRemainder = AmmoCaliber[cnt]; //the remaining string to be output (for making valid XML)
FilePrintf(hFile,"\t\t<AmmoCaliber>");
while(szRemainder[0] != '\0')
{
UINT32 uiCharLoc = strcspn(szRemainder,"&<>\'\"\0");
UINT16 invChar = szRemainder[uiCharLoc];
if(uiCharLoc)
{
szRemainder[uiCharLoc] = '\0';
FilePrintf(hFile,"%s",szRemainder);
szRemainder[uiCharLoc] = invChar;
}
szRemainder += uiCharLoc;
switch(invChar)
{
case '&':
FilePrintf(hFile,"&amp;");
szRemainder++;
break;
case '<':
FilePrintf(hFile,"&lt;");
szRemainder++;
break;
case '>':
FilePrintf(hFile,"&gt;");
szRemainder++;
break;
case '\'':
FilePrintf(hFile,"&apos;");
szRemainder++;
break;
case '\"':
FilePrintf(hFile,"&quot;");
szRemainder++;
break;
}
}
FilePrintf(hFile,"</AmmoCaliber>\r\n");
szRemainder = BobbyRayAmmoCaliber[cnt]; //the remaining string to be output (for making valid XML)
FilePrintf(hFile,"\t\t<BRCaliber>");
while(szRemainder[0] != '\0')
{
UINT32 uiCharLoc = strcspn(szRemainder,"&<>\'\"\0");
UINT16 invChar = szRemainder[uiCharLoc];
if(uiCharLoc)
{
szRemainder[uiCharLoc] = '\0';
FilePrintf(hFile,"%s",szRemainder);
szRemainder[uiCharLoc] = invChar;
}
szRemainder += uiCharLoc;
switch(invChar)
{
case '&':
FilePrintf(hFile,"&amp;");
szRemainder++;
break;
case '<':
FilePrintf(hFile,"&lt;");
szRemainder++;
break;
case '>':
FilePrintf(hFile,"&gt;");
szRemainder++;
break;
case '\'':
FilePrintf(hFile,"&apos;");
szRemainder++;
break;
case '\"':
FilePrintf(hFile,"&quot;");
szRemainder++;
break;
}
}
FilePrintf(hFile,"</BRCaliber>\r\n");
FilePrintf(hFile,"\t</AMMO>\r\n");
}
FilePrintf(hFile,"</AMMOLIST>\r\n");
}
FileClose( hFile );
return( TRUE );
}
+270
View File
@@ -0,0 +1,270 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include "sgp.h"
#include "overhead types.h"
#include "Sound Control.h"
#include "Soldier Control.h"
#include "overhead.h"
#include "Event Pump.h"
#include "weapons.h"
#include "Animation Control.h"
#include "sys globals.h"
#include "Handle UI.h"
#include "Isometric Utils.h"
#include "worldman.h"
#include "math.h"
#include "points.h"
#include "ai.h"
#include "los.h"
#include "renderworld.h"
#include "opplist.h"
#include "interface.h"
#include "message.h"
#include "campaign.h"
#include "items.h"
#include "text.h"
#include "Soldier Profile.h"
#include "tile animation.h"
#include "Dialogue Control.h"
#include "SkillCheck.h"
#include "explosion control.h"
#include "Quests.h"
#include "Physics.h"
#include "Random.h"
#include "Vehicles.h"
#include "bullets.h"
#include "morale.h"
#include "meanwhile.h"
#include "SkillCheck.h"
#include "gamesettings.h"
#include "SaveLoadMap.h"
#include "Debug Control.h"
#include "expat.h"
#include "XML.h"
#endif
struct
{
PARSE_STAGE curElement;
INT8 szCharData[MAX_CHAR_DATA_LENGTH+1];
UINT32 maxArraySize;
UINT32 curIndex;
UINT32 currentDepth;
UINT32 maxReadDepth;
}
typedef burstSoundParseData;
static void XMLCALL
burstSoundStartElementHandle(void *userData, const char *name, const char **atts)
{
burstSoundParseData * pData = (burstSoundParseData *)userData;
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
{
if(strcmp(name, "SOUNDLIST") == 0 && pData->curElement == ELEMENT_NONE)
{
pData->curElement = ELEMENT_LIST;
pData->maxReadDepth++; //we are not skipping this element
}
else if(strcmp(name, "SOUND") == 0 && pData->curElement == ELEMENT_LIST)
{
pData->curElement = ELEMENT;
pData->maxReadDepth++; //we are not skipping this element
pData->curIndex++;
}
pData->szCharData[0] = '\0';
}
pData->currentDepth++;
}
static void XMLCALL
burstSoundCharacterDataHandle(void *userData, const char *str, int len)
{
burstSoundParseData * pData = (burstSoundParseData *)userData;
if( (pData->currentDepth <= pData->maxReadDepth) &&
(strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH)
){
strncat(pData->szCharData,str,__min((unsigned int)len,MAX_CHAR_DATA_LENGTH-strlen(pData->szCharData)));
}
}
static void XMLCALL
burstSoundEndElementHandle(void *userData, const char *name)
{
burstSoundParseData * pData = (burstSoundParseData *)userData;
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
{
if(strcmp(name, "SOUNDLIST") == 0)
{
pData->curElement = ELEMENT_NONE;
}
else if(strcmp(name, "SOUND") == 0)
{
pData->curElement = ELEMENT_LIST;
if(pData->curIndex < pData->maxArraySize)
{
char temp;
for(int i=0;i<min((int)strlen(pData->szCharData),128);i++)
{
temp = pData->szCharData[i];
gzBurstSndStrings[pData->curIndex][i] = temp;
}
}
}
pData->maxReadDepth--;
}
pData->currentDepth--;
}
BOOLEAN ReadInBurstSoundArray(STR fileName)
{
HWFILE hFile;
UINT32 uiBytesRead;
UINT32 uiFSize;
CHAR8 * lpcBuffer;
XML_Parser parser = XML_ParserCreate(NULL);
burstSoundParseData pData;
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("Loading %s",SOUNDSFILENAME ) );
// Open sounds file
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
if ( !hFile )
return( FALSE );
uiFSize = FileGetSize(hFile);
lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1);
//Read in block
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
{
MemFree(lpcBuffer);
return( FALSE );
}
lpcBuffer[uiFSize] = 0; //add a null terminator
FileClose( hFile );
XML_SetElementHandler(parser, burstSoundStartElementHandle, burstSoundEndElementHandle);
XML_SetCharacterDataHandler(parser, burstSoundCharacterDataHandle);
memset(&pData,0,sizeof(pData));
pData.maxArraySize = MAX_SAMPLES;
pData.curIndex = -1;
XML_SetUserData(parser, &pData);
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
{
CHAR8 errorBuf[511];
sprintf(errorBuf, "XML Parser Error in %s.xml: %s at line %d", SOUNDSFILENAME, XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
LiveMessage(errorBuf);
MemFree(lpcBuffer);
return FALSE;
}
MemFree(lpcBuffer);
XML_ParserFree(parser);
return( TRUE );
}
BOOLEAN WriteBurstSoundArray()
{
HWFILE hFile;
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("WriteSoundArray"));
//Debug code; make sure that what we got from the file is the same as what's there
// Open a new file
hFile = FileOpen( "TABLEDATA\\BurstSounds out.xml", FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE );
if ( !hFile )
return( FALSE );
{
UINT32 cnt;
FilePrintf(hFile,"<SOUNDLIST>\r\n");
for(cnt = 0;cnt < 19;cnt++)
{
FilePrintf(hFile,"\t<SOUND>");
INT8 * szRemainder = gzBurstSndStrings[cnt]; //the remaining string to be output (for making valid XML)
while(szRemainder[0] != '\0')
{
UINT32 uiCharLoc = strcspn(szRemainder,"&<>\'\"\0");
char invChar = szRemainder[uiCharLoc];
if(uiCharLoc)
{
szRemainder[uiCharLoc] = '\0';
FilePrintf(hFile,"%s",szRemainder);
szRemainder[uiCharLoc] = invChar;
}
szRemainder += uiCharLoc;
switch(invChar)
{
case '&':
FilePrintf(hFile,"&amp;");
szRemainder++;
break;
case '<':
FilePrintf(hFile,"&lt;");
szRemainder++;
break;
case '>':
FilePrintf(hFile,"&gt;");
szRemainder++;
break;
case '\'':
FilePrintf(hFile,"&apos;");
szRemainder++;
break;
case '\"':
FilePrintf(hFile,"&quot;");
szRemainder++;
break;
}
}
// FilePrintf(hFile,"\t\t<SOUND>%s</SOUND>\r\n", szSoundEffects[cnt]);
FilePrintf(hFile,"</SOUND>\r\n");
}
FilePrintf(hFile,"</SOUNDLIST>\r\n");
}
FileClose( hFile );
return( TRUE );
}
+7
View File
@@ -1158,6 +1158,13 @@ INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir,
sDistVisible = __min( sDistVisible, 2 );
}
}
if ( gpWorldLevelData[ pSoldier->sGridNo ].ubExtFlags[ bLevel ] & MAPELEMENT_EXT_BURNABLEGAS )
{
{
// in FLAMETHERgas ; reduce max distance visible to 2 tiles at most
sDistVisible = __min( sDistVisible, 2 );
}
}
return(sDistVisible);
}