****************************************************************************

** Merged Source Code from Development trunk, for the Spring 2011 Release **
****************************************************************************
o Development Trunk (Revision: 4444):  https://81.169.133.124/source/ja2/branches/Wanne/JA2%201.13%20MP
o This trunk (the official 1.13 source trunk) will only be used for fixing bugs. No new features will be added here.
  New Features are only included in the Development trunk
o !!! After we have fixed a bug here in this trunk, we should MANUALLY merge the bugfix in the development trunk !!!

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@4446 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2011-05-26 11:04:47 +00:00
parent c999420bb7
commit 6e2bdd557c
191 changed files with 17816 additions and 6106 deletions
+36 -4
View File
@@ -64,7 +64,8 @@ static UINT16 LobGrenadeStanceAnimationScript[MAX_FRAMES_PER_ANIM] = { 1,2,3,4,5
static UINT16 ROLL_L_AnimationScript[MAX_FRAMES_PER_ANIM] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,501,999,0,0,0,0 };
static UINT16 ROLL_R_AnimationScript[MAX_FRAMES_PER_ANIM] = { 14,13,12,11,10,9,8,7,6,5,4,3,2,1,501,999,0,0,0,0 };
static UINT16 JUMP_WALL_UP_AnimationScript[MAX_FRAMES_PER_ANIM] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,601,999,0,0,0,0 };
static UINT16 JUMP_WALL_DOWN_AnimationScript[MAX_FRAMES_PER_ANIM] = { 44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,601,999,0,0,0,0 };
@@ -979,6 +980,13 @@ ANIMCONTROLTYPE gAnimControl[ NUMANIMATIONSTATES ] =
//ROLL PRONE RIGHT
{"ROLL PRONE RIGHT" , 0, 80, (FLOAT)0.8 /*1.1*/, ANIM_MOVING | ANIM_NORESTART | ANIM_RAISE_WEAPON | ANIM_VARIABLE_EFFORT, ANIM_PRONE, ANIM_PRONE, -1},
// JUMPUPWALL
{"JUMPUPWALL" , 0, 30, (FLOAT)0, ANIM_NONINTERRUPT | ANIM_NORESTART | ANIM_STATIONARY | ANIM_NOSHOW_MARKER | ANIM_MODERATE_EFFORT | ANIM_LOWER_WEAPON, ANIM_STAND, ANIM_CROUCH, -1},
//JUMPDOWNWALL
{"JUMPDOWNWALL" , 0, 30, (FLOAT)0, ANIM_NONINTERRUPT | ANIM_NORESTART | ANIM_STATIONARY | ANIM_NOSHOW_MARKER | ANIM_MODERATE_EFFORT | ANIM_LOWER_WEAPON, ANIM_CROUCH, ANIM_STAND, -1},
{"JUMP WINDOWS" , 0, 50, (FLOAT)0, ANIM_NOCHANGE_PENDINGCOUNT | ANIM_NORESTART | ANIM_STATIONARY | ANIM_NOSHOW_MARKER | ANIM_MODERATE_EFFORT | ANIM_LOWER_WEAPON | ANIM_NONINTERRUPT, ANIM_STAND, ANIM_CROUCH, -1},
};
@@ -1376,7 +1384,10 @@ void InitAnimationSurfacesPerBodytype( )
gubAnimSurfaceIndex[ REGMALE ][ ROLL_PRONE_L ] = RGMROLL_PR;
gubAnimSurfaceIndex[ REGMALE ][ ROLL_PRONE_R ] = RGMROLL_PR;
gubAnimSurfaceIndex[ REGMALE ][ JUMPUPWALL ] = RGMWALLJUMP;
gubAnimSurfaceIndex[ REGMALE ][ JUMPDOWNWALL ] = RGMWALLJUMP;
gubAnimSurfaceIndex[ REGMALE ][ JUMPWINDOWS ] = RGMJUMPWINDOWS;
gubAnimSurfaceMidWaterSubIndex[ REGMALE ][ STANDING][0] = RGMWATER_R_STD;
gubAnimSurfaceMidWaterSubIndex[ REGMALE ][ WALKING ][0] = RGMWATER_R_WALK;
@@ -1747,6 +1758,11 @@ void InitAnimationSurfacesPerBodytype( )
//ïåðåêàò
gubAnimSurfaceIndex[ BIGMALE ][ ROLL_PRONE_L ] = BGMROLL_PR;
gubAnimSurfaceIndex[ BIGMALE ][ ROLL_PRONE_R ] = BGMROLL_PR;
gubAnimSurfaceIndex[ BIGMALE ][ JUMPUPWALL ] = BGMWALLJUMP;
gubAnimSurfaceIndex[ BIGMALE ][ JUMPDOWNWALL ] = BGMWALLJUMP;
gubAnimSurfaceIndex[ BIGMALE ][ JUMPWINDOWS ] = BGMJUMPWINDOWS;
gubAnimSurfaceItemSubIndex[ BIGMALE ][ STANDING ] = BGMPISTOLBREATH;
@@ -2135,7 +2151,11 @@ void InitAnimationSurfacesPerBodytype( )
//ïåðåêàò
gubAnimSurfaceIndex[ STOCKYMALE ][ ROLL_PRONE_L ] = RGMROLL_PR;
gubAnimSurfaceIndex[ STOCKYMALE ][ ROLL_PRONE_R ] = RGMROLL_PR;
gubAnimSurfaceIndex[ STOCKYMALE ][ JUMPUPWALL ] = RGMWALLJUMP;
gubAnimSurfaceIndex[ STOCKYMALE ][ JUMPDOWNWALL ] = RGMWALLJUMP;
gubAnimSurfaceIndex[ STOCKYMALE ][ JUMPWINDOWS ] = RGMJUMPWINDOWS;
gubAnimSurfaceItemSubIndex[ STOCKYMALE ][ STANDING ] = RGMPISTOLBREATH;
gubAnimSurfaceItemSubIndex[ STOCKYMALE ][ WALKING ] = RGMNOTHING_WALK;
@@ -2503,7 +2523,10 @@ void InitAnimationSurfacesPerBodytype( )
gubAnimSurfaceIndex[ REGFEMALE ][ ROLL_PRONE_L ] = RGFROLL_PR;
gubAnimSurfaceIndex[ REGFEMALE ][ ROLL_PRONE_R ] = RGFROLL_PR;
gubAnimSurfaceIndex[ REGFEMALE ][ JUMPUPWALL ] = RGFWALLJUMP;
gubAnimSurfaceIndex[ REGFEMALE ][ JUMPDOWNWALL ] = RGFWALLJUMP;
gubAnimSurfaceIndex[ REGFEMALE ][ JUMPWINDOWS ] = RGFJUMPWINDOWS;
gubAnimSurfaceItemSubIndex[ REGFEMALE ][ STANDING ] = RGFPISTOLBREATH;
gubAnimSurfaceItemSubIndex[ REGFEMALE ][ WALKING ] = RGFNOTHING_WALK;
@@ -3222,6 +3245,15 @@ BOOLEAN LoadAnimationStateInstructions( )
memcpy(gusAnimInst[ ROLL_PRONE_L ],ROLL_L_AnimationScript,sizeof(ROLL_L_AnimationScript));
memcpy(gusAnimInst[ ROLL_PRONE_R ],ROLL_R_AnimationScript,sizeof(ROLL_R_AnimationScript));
memcpy(gusAnimInst[JUMPUPWALL],fuckTheBoundz[32],sizeof(fuckTheBoundz[32])); // copy CLIMBROOF to JUMPUPWALL
memcpy(gusAnimInst[JUMPDOWNWALL],fuckTheBoundz[35],sizeof(fuckTheBoundz[35])); // copy CLIMBDOWNROOF to JUMPDOWNWALL
memcpy(gusAnimInst[JUMPWINDOWS],fuckTheBoundz[HOPFENCE],sizeof(fuckTheBoundz[HOPFENCE])); // copy HOPFENCE to JUMPDOWNWALL
//memcpy(gusAnimInst[ JUMPUPWALL ],JUMP_WALL_UP_AnimationScript,sizeof(JUMP_WALL_UP_AnimationScript));
//memcpy(gusAnimInst[ JUMPDOWNWALL ],JUMP_WALL_DOWN_AnimationScript,sizeof(JUMP_WALL_DOWN_AnimationScript));
return( TRUE );
}
+6
View File
@@ -554,6 +554,12 @@ enum AnimationStates
ROLL_PRONE_R,
ROLL_PRONE_L,
//jump wall
JUMPUPWALL,
JUMPDOWNWALL,
JUMPWINDOWS,
NUMANIMATIONSTATES
};
+9 -1
View File
@@ -502,7 +502,15 @@ AnimationSurfaceType gAnimSurfaceDatabase[ NUMANIMATIONSURFACETYPES ] =
RGMROLL_PR, "ANIMS\\S_MERC\\S_ROLL_N.STI", S_STRUCT, 0, 8, TO_INIT, NULL, NULL, 0, -1,
BGMROLL_PR, "ANIMS\\M_MERC\\M_ROLL_N.STI", S_STRUCT, 0, 8, TO_INIT, NULL, NULL, 0, -1,
RGFROLL_PR, "ANIMS\\F_MERC\\F_ROLL_N.STI", S_STRUCT, 0, 8, TO_INIT, NULL, NULL, 0, -1,
RGMWALLJUMP, "ANIMS\\S_MERC\\S_CLIMB.STI", S_STRUCT, 0, 4, TO_INIT, NULL, NULL, 0, -1,
BGMWALLJUMP, "ANIMS\\M_MERC\\M_CLIMB.STI", S_STRUCT, 0, 4, TO_INIT, NULL, NULL, 0, -1,
RGFWALLJUMP, "ANIMS\\F_MERC\\F_CLIMB.STI", S_STRUCT, 0, 4, TO_INIT, NULL, NULL, 0, -1,
RGMJUMPWINDOWS, "ANIMS\\S_MERC\\S_HOP.STI", NO_STRUCT, 0, 4, TO_INIT, NULL, NULL, 0, -1,
BGMJUMPWINDOWS, "ANIMS\\M_MERC\\M_HOP.STI", NO_STRUCT, 0, 4, TO_INIT, NULL, NULL, 0, -1,
RGFJUMPWINDOWS, "ANIMS\\F_MERC\\F_HOP.STI", NO_STRUCT, 0, 4, TO_INIT, NULL, NULL, 0, -1,
};
+9
View File
@@ -530,6 +530,15 @@ BGMWITHSTONE,
RGMROLL_PR,
BGMROLL_PR,
RGFROLL_PR,
RGMWALLJUMP,
BGMWALLJUMP,
RGFWALLJUMP,
//jump windows
RGMJUMPWINDOWS,
BGMJUMPWINDOWS,
RGFJUMPWINDOWS,
NUMANIMATIONSURFACETYPES
+9 -1
View File
@@ -14,6 +14,7 @@
#include "bobbyr.h"
#include "Random.h"
#include "Shopkeeper Interface.h"
#include "connect.h"
#endif
@@ -1184,7 +1185,14 @@ UINT8 DetermineInitialInvItems( INT8 bArmsDealerID, UINT16 usItemIndex, UINT8 ub
ubNumBought = 0;
for (ubCnt = 0; ubCnt < ubChances; ubCnt++)
{
if (ItemTransactionOccurs( bArmsDealerID, usItemIndex, DEALER_BUYING, fUsed))
if (!is_networked)
{
if (ItemTransactionOccurs( bArmsDealerID, usItemIndex, DEALER_BUYING, fUsed))
{
ubNumBought++;
}
}
else
{
ubNumBought++;
}
+1 -1
View File
@@ -383,7 +383,7 @@ BOOLEAN PickABoxer( void )
RESETTIMECOUNTER( pBoxer->timeCounters.AICounter, 0 );
gfBoxerFought[ uiLoop ] = TRUE;
// improve stats based on the # of rests these guys have had
pBoxer->stats.bStrength = __min( 100, pBoxer->stats.bStrength += gubBoxersRests * 5 );
pBoxer->stats.bStrength = __min( 100, pBoxer->stats.bStrength + gubBoxersRests * 5 );
pBoxer->stats.bDexterity = __min( 100, pBoxer->stats.bDexterity + gubBoxersRests * 5 );
pBoxer->stats.bAgility = __min( 100, pBoxer->stats.bAgility + gubBoxersRests * 5 );
pBoxer->stats.bLifeMax = __min( 100, pBoxer->stats.bLifeMax + gubBoxersRests * 5 );
+1 -1
View File
@@ -1866,5 +1866,5 @@ void MERCMercWentUpALevelSendEmail( UINT8 ubMercMercIdValue )
ubEmailOffset = MERC_UP_LEVEL_BIFF + MERC_UP_LEVEL_LENGTH_BIFF * ( ubMercMercIdValue );
}
AddEmail( ubEmailOffset, iMsgLength, SPECK_FROM_MERC, GetWorldTotalMin(), -1);
AddEmail( ubEmailOffset, iMsgLength, SPECK_FROM_MERC, GetWorldTotalMin(), -1, -1);
}
+23 -19
View File
@@ -1893,30 +1893,33 @@ BOOLEAN DialogueDataFileExistsForProfile( UINT8 ubCharacterNum, UINT16 usQuoteNu
BOOLEAN GetDialogue( UINT8 ubCharacterNum, UINT16 usQuoteNum, UINT32 iDataSize, STR16 zDialogueText, UINT32 *puiSoundID, CHAR8 *zSoundString )
{
STR8 pFilename;
BOOLEAN fTextAvailable = FALSE;
// first things first - grab the text (if player has SUBTITLE PREFERENCE ON)
//if ( gGameSettings.fOptions[ TOPTION_SUBTITLES ] )
{
if ( DialogueDataFileExistsForProfile( ubCharacterNum, 0, FALSE, &pFilename ) )
{
LoadEncryptedDataFromFile( pFilename, zDialogueText, usQuoteNum * iDataSize, iDataSize );
if(zDialogueText[0] == 0)
if ( DialogueDataFileExistsForProfile( ubCharacterNum, 0, FALSE, &pFilename ) )
{
swprintf( zDialogueText, L"I have no text in the EDT file ( %d ) %S", usQuoteNum, pFilename );
LoadEncryptedDataFromFile( pFilename, zDialogueText, usQuoteNum * iDataSize, iDataSize );
if(zDialogueText[0] == 0)
{
swprintf( zDialogueText, L"I have no text in the EDT file ( %d ) %S", usQuoteNum, pFilename );
#ifndef JA2BETAVERSION
return( FALSE );
#endif
}
else
fTextAvailable = TRUE;
}
else
{
swprintf( zDialogueText, L"I have no text in the file ( %d ) %S", usQuoteNum , pFilename );
#ifndef JA2BETAVERSION
return( FALSE );
#endif
}
}
else
{
swprintf( zDialogueText, L"I have no text in the file ( %d ) %S", usQuoteNum , pFilename );
#ifndef JA2BETAVERSION
return( FALSE );
#endif
}
}
@@ -1936,23 +1939,24 @@ BOOLEAN GetDialogue( UINT8 ubCharacterNum, UINT16 usQuoteNum, UINT32 iDataSize,
CHAR8 sString[512];
sprintf( sString, "ERROR: Missing file for character # %d, quote # %d", ubCharacterNum, usQuoteNum );
ShowCursor(TRUE);
ShowCursor(TRUE);
ShutdownWithErrorBox( sString );
ShowCursor(TRUE);
ShowCursor(TRUE);
ShutdownWithErrorBox( sString );
}
*/
//#endif
*puiSoundID = NO_SAMPLE;
// get speech if applicable
if ( gGameSettings.fOptions[ TOPTION_SPEECH ] )
{
// Load it into memory!
*puiSoundID = SoundLoadSample( pFilename );
}
return(TRUE);
return (*puiSoundID != NO_SAMPLE) || fTextAvailable;
}
+3 -2
View File
@@ -550,6 +550,7 @@ void DisplayRangeToTarget( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
{
UINT16 usRange=0;
CHAR16 zOutputString[512];
UINT8 title = (UsingNewCTHSystem() == true ? DC_MSG__NCTH_GUN_RANGE_INFORMATION : DC_MSG__GUN_RANGE_INFORMATION);
if( sTargetGridNo == NOWHERE || sTargetGridNo == 0 )
{
@@ -595,13 +596,13 @@ void DisplayRangeToTarget( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
// HEADROCK HAM 3.6: Calculate Gun Range using formula.
UINT16 usGunRange = GunRange(&pSoldier->inv[HANDPOS], pSoldier ); // SANDRO - added argument
swprintf( zOutputString, gzDisplayCoverText[DC_MSG__GUN_RANGE_INFORMATION], usRange / 10, usGunRange / 10, uiHitChance );
swprintf( zOutputString, gzDisplayCoverText[title], usRange / 10, usGunRange / 10, uiHitChance );
//Display the msg
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, zOutputString );
}
else
{
swprintf( zOutputString, gzDisplayCoverText[DC_MSG__GUN_RANGE_INFORMATION], usRange / 10, 0, 0 );
swprintf( zOutputString, gzDisplayCoverText[title], usRange / 10, 0, 0 );
//Display the msg
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, zOutputString );
+347 -37
View File
@@ -66,6 +66,9 @@ UINT8 ubRPCNumSmallFaceValues = 200;
CAMO_FACE gCamoFace[255];
FACE_GEAR_VALUES zNewFaceGear[MAXITEMS];
FACE_GEAR_VALUES zNewFaceGearIMP[MAXITEMS];
extern BOOLEAN gfSMDisableForItems;
extern INT16 gsCurInterfacePanel;
extern UINT16 gusSMCurrentMerc;
@@ -721,7 +724,73 @@ void SetAutoFaceInActive(INT32 iFaceIndex )
pFace->fDisabled = TRUE;
}
void SetCamoFace(SOLDIERTYPE * pSoldier)
{
INT8 worn = -1;
INT8 applied = -1;
INT16 wornCamo[4];
INT16 appliedCamo[4];
//reset gCamoFace
gCamoFace[pSoldier->ubProfile].gCamoface = FALSE;
gCamoFace[pSoldier->ubProfile].gUrbanCamoface = FALSE;
gCamoFace[pSoldier->ubProfile].gDesertCamoface = FALSE;
gCamoFace[pSoldier->ubProfile].gSnowCamoface = FALSE;
appliedCamo[0] = pSoldier->bCamo;
appliedCamo[1] = pSoldier->urbanCamo;
appliedCamo[2] = pSoldier->desertCamo;
appliedCamo[3] = pSoldier->snowCamo;
wornCamo[0] = pSoldier->wornCamo;
wornCamo[1] = pSoldier->wornUrbanCamo;
wornCamo[2] = pSoldier->wornDesertCamo;
wornCamo[3] = pSoldier->wornSnowCamo;
for(INT8 loop = 0; loop < 4; loop ++)
{
if(wornCamo[loop] > 50)
worn = loop;
if(appliedCamo[loop] > 50)
applied = loop;
}
if(applied != -1 && worn != -1)
{
if(appliedCamo[applied] >= wornCamo[worn])
{
if(applied == 0)
gCamoFace[pSoldier->ubProfile].gCamoface = TRUE;
if(applied == 1)
gCamoFace[pSoldier->ubProfile].gUrbanCamoface = TRUE;
if(applied == 2)
gCamoFace[pSoldier->ubProfile].gDesertCamoface = TRUE;
if(applied == 3)
gCamoFace[pSoldier->ubProfile].gSnowCamoface = TRUE;
}
else
{
if(worn == 0)
gCamoFace[pSoldier->ubProfile].gCamoface = TRUE;
if(worn == 1)
gCamoFace[pSoldier->ubProfile].gUrbanCamoface = TRUE;
if(worn == 2)
gCamoFace[pSoldier->ubProfile].gDesertCamoface = TRUE;
if(worn == 3)
gCamoFace[pSoldier->ubProfile].gSnowCamoface = TRUE;
}
}
else if(applied != -1 || worn != -1)
{
if(applied == 0 || worn == 0)
gCamoFace[pSoldier->ubProfile].gCamoface = TRUE;
if(applied == 1 || worn == 1)
gCamoFace[pSoldier->ubProfile].gUrbanCamoface = TRUE;
if(applied == 2 || worn == 2)
gCamoFace[pSoldier->ubProfile].gDesertCamoface = TRUE;
if(applied == 3 || worn == 3)
gCamoFace[pSoldier->ubProfile].gSnowCamoface = TRUE;
}
}
void SetAllAutoFacesInactive( )
{
@@ -1153,7 +1222,7 @@ BOOLEAN RenderAutoFaceFromSoldier( UINT8 ubSoldierID )
}
//---------------------------------------LEGION-------------------------------
/*
void GetXYForIconPlacement_legion( FACETYPE *pFace, UINT16 ubIndex, INT16 sFaceX, INT16 sFaceY, INT16 *psX, INT16 *psY )
{
INT16 sX, sY;
@@ -1174,7 +1243,8 @@ void GetXYForIconPlacement_legion( FACETYPE *pFace, UINT16 ubIndex, INT16 sFaceX
*psY = sY;
}
void GetXYForRightIconPlacement_legion_NV( FACETYPE *pFace, UINT16 ubIndex, INT16 sFaceX, INT16 sFaceY, INT16 *psX, INT16 *psY, INT8 bNumIcons )
void GetXYForRightIconPlacement_legion_NV( FACETYPE *pFace, UINT16 ubIndex, INT16 sFaceX, INT16 sFaceY, INT16 *psX, INT16 *psY, INT8 bNumIcons, BOOLEAN isIMP )
{
INT16 sX, sY;
UINT16 usWidth, usHeight;
@@ -1182,7 +1252,11 @@ void GetXYForRightIconPlacement_legion_NV( FACETYPE *pFace, UINT16 ubIndex, INT1
HVOBJECT hVObject;
// Get height, width of icon...
GetVideoObject( &hVObject, guiPORTRAITICONS_NV );
if (isIMP)
GetVideoObject( &hVObject, guiPORTRAITICONS_NV_IMP );
else
GetVideoObject( &hVObject, guiPORTRAITICONS_NV );
pTrav = &(hVObject->pETRLEObject[ ubIndex ] );
usHeight = pTrav->usHeight;
usWidth = pTrav->usWidth;
@@ -1193,16 +1267,21 @@ void GetXYForRightIconPlacement_legion_NV( FACETYPE *pFace, UINT16 ubIndex, INT1
*psX = sX;
*psY = sY;
}
void DoRightIcon_legion_NV( UINT32 uiRenderBuffer, FACETYPE *pFace, INT16 sFaceX, INT16 sFaceY, INT8 bNumIcons, UINT8 sIconIndex )
void DoRightIcon_legion_NV( UINT32 uiRenderBuffer, FACETYPE *pFace, INT16 sFaceX, INT16 sFaceY, INT8 bNumIcons, UINT8 sIconIndex, BOOLEAN isIMP )
{
INT16 sIconX, sIconY;
GetXYForRightIconPlacement_legion_NV( pFace, sIconIndex, sFaceX, sFaceY, &sIconX, &sIconY, bNumIcons );
BltVideoObjectFromIndex( uiRenderBuffer, guiPORTRAITICONS_NV, sIconIndex, sIconX, sIconY, VO_BLT_SRCTRANSPARENCY, NULL );
GetXYForRightIconPlacement_legion_NV( pFace, sIconIndex, sFaceX, sFaceY, &sIconX, &sIconY, bNumIcons, isIMP );
if (isIMP)
BltVideoObjectFromIndex( uiRenderBuffer, guiPORTRAITICONS_NV_IMP, sIconIndex, sIconX, sIconY, VO_BLT_SRCTRANSPARENCY, NULL );
else
BltVideoObjectFromIndex( uiRenderBuffer, guiPORTRAITICONS_NV, sIconIndex, sIconX, sIconY, VO_BLT_SRCTRANSPARENCY, NULL );
}
void GetXYForRightIconPlacement_legion_GAS_MASK( FACETYPE *pFace, UINT16 ubIndex, INT16 sFaceX, INT16 sFaceY, INT16 *psX, INT16 *psY, INT8 bNumIcons )
void GetXYForRightIconPlacement_legion_GAS_MASK( FACETYPE *pFace, UINT16 ubIndex, INT16 sFaceX, INT16 sFaceY, INT16 *psX, INT16 *psY, INT8 bNumIcons, BOOLEAN isIMP )
{
INT16 sX, sY;
UINT16 usWidth, usHeight;
@@ -1210,7 +1289,11 @@ void GetXYForRightIconPlacement_legion_GAS_MASK( FACETYPE *pFace, UINT16 ubIndex
HVOBJECT hVObject;
// Get height, width of icon...
GetVideoObject( &hVObject, guiPORTRAITICONS_GAS_MASK );
if (isIMP)
GetVideoObject( &hVObject, guiPORTRAITICONS_GAS_MASK_IMP );
else
GetVideoObject( &hVObject, guiPORTRAITICONS_GAS_MASK );
pTrav = &(hVObject->pETRLEObject[ ubIndex ] );
usHeight = pTrav->usHeight;
usWidth = pTrav->usWidth;
@@ -1221,16 +1304,61 @@ void GetXYForRightIconPlacement_legion_GAS_MASK( FACETYPE *pFace, UINT16 ubIndex
*psX = sX;
*psY = sY;
}
void DoRightIcon_legion_GAS_MASK( UINT32 uiRenderBuffer, FACETYPE *pFace, INT16 sFaceX, INT16 sFaceY, INT8 bNumIcons, UINT8 sIconIndex )
void DoRightIcon_legion_GAS_MASK( UINT32 uiRenderBuffer, FACETYPE *pFace, INT16 sFaceX, INT16 sFaceY, INT8 bNumIcons, UINT8 sIconIndex, BOOLEAN isIMP )
{
INT16 sIconX, sIconY;
// Find X, y for placement
GetXYForRightIconPlacement_legion_GAS_MASK( pFace, sIconIndex, sFaceX, sFaceY, &sIconX, &sIconY, bNumIcons, isIMP );
GetXYForRightIconPlacement_legion_GAS_MASK( pFace, sIconIndex, sFaceX, sFaceY, &sIconX, &sIconY, bNumIcons );
BltVideoObjectFromIndex( uiRenderBuffer, guiPORTRAITICONS_GAS_MASK, sIconIndex, sIconX, sIconY, VO_BLT_SRCTRANSPARENCY, NULL );
if (isIMP)
BltVideoObjectFromIndex( uiRenderBuffer, guiPORTRAITICONS_GAS_MASK_IMP, sIconIndex, sIconX, sIconY, VO_BLT_SRCTRANSPARENCY, NULL );
else
BltVideoObjectFromIndex( uiRenderBuffer, guiPORTRAITICONS_GAS_MASK, sIconIndex, sIconX, sIconY, VO_BLT_SRCTRANSPARENCY, NULL );
}
*/
void GetXYForRightIconPlacement_FaceGera( FACETYPE *pFace, UINT16 ubIndex, INT16 sFaceX, INT16 sFaceY, INT16 *psX, INT16 *psY, INT8 bNumIcons , UINT32 uIDFaceGear, BOOLEAN isIMP)
{
INT16 sX, sY;
UINT16 usWidth, usHeight;
ETRLEObject *pTrav;
HVOBJECT hVObject;
// Get height, width of icon...
if (isIMP)
GetVideoObject( &hVObject, zNewFaceGearIMP[uIDFaceGear].uiIndex );
else
GetVideoObject( &hVObject, zNewFaceGear[uIDFaceGear].uiIndex );
pTrav = &(hVObject->pETRLEObject[ ubIndex ] );
usHeight = pTrav->usHeight;
usWidth = pTrav->usWidth;
sX = sFaceX + ( usWidth * bNumIcons ) + 1;
sY = sFaceY + pFace->usFaceHeight - usHeight - 1;
*psX = sX;
*psY = sY;
}
void DoRightIcon_FaceGear( UINT32 uiRenderBuffer, FACETYPE *pFace, INT16 sFaceX, INT16 sFaceY, INT8 bNumIcons, UINT8 sIconIndex , UINT32 uIDFaceGear, BOOLEAN isIMP)
{
INT16 sIconX, sIconY;
// Find X, y for placement
if (isIMP)
{
GetXYForRightIconPlacement_FaceGera( pFace, sIconIndex, sFaceX, sFaceY, &sIconX, &sIconY, bNumIcons , uIDFaceGear,isIMP);
BltVideoObjectFromIndex( uiRenderBuffer, zNewFaceGearIMP[uIDFaceGear].uiIndex, sIconIndex, sIconX, sIconY, VO_BLT_SRCTRANSPARENCY, NULL );
}
else
{
GetXYForRightIconPlacement_FaceGera( pFace, sIconIndex, sFaceX, sFaceY, &sIconX, &sIconY, bNumIcons , uIDFaceGear,isIMP);
BltVideoObjectFromIndex( uiRenderBuffer, zNewFaceGear[uIDFaceGear].uiIndex, sIconIndex, sIconX, sIconY, VO_BLT_SRCTRANSPARENCY, NULL );
}
}
//----------------------------------------------------------------
@@ -1315,6 +1443,9 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
UINT32 uiFaceItemOne=0;
UINT32 uiFaceItemTwo=0;
UINT8 ubFaceItemsCombined=0;
UINT32 uiFaceOne=0;
UINT32 uiFaceTwo=0;
// If we are using an extern buffer...
if ( fUseExternBuffer )
@@ -1478,10 +1609,21 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
//------------------------------------Legion 2 by jazz--------------------------------
UINT8 faceProfileId = MercPtrs[ pFace->ubSoldierID ]->ubProfile;
BOOLEAN isIMP = FALSE;
//IMP
if ( gProfilesIMP[ MercPtrs[ pFace->ubSoldierID ]->ubProfile ].ProfilId == MercPtrs[ pFace->ubSoldierID ]->ubProfile )
{
faceProfileId = gMercProfiles[MercPtrs[ pFace->ubSoldierID ]->ubProfile].ubFaceIndex;
isIMP = TRUE;
}
// rewritten by silversurfer
// this section chooses the icons for face gear if the ini setting "SHOW_TACTICAL_FACE_ICONS" is TRUE
// and the merc actually wears something to be shown
if (gGameExternalOptions.fShowTacticalFaceIcons == TRUE && MercPtrs[ pFace->ubSoldierID ]->stats.bLife > 0 &&
if (gGameSettings.fOptions[ TOPTION_SHOW_TACTICAL_FACE_ICONS ] == TRUE && MercPtrs[ pFace->ubSoldierID ]->stats.bLife > 0 &&
( MercPtrs[ pFace->ubSoldierID ]->inv[HEAD1POS].usItem + MercPtrs[ pFace->ubSoldierID ]->inv[HEAD2POS].usItem ) > 0 )
{
uiFaceItemOne=MercPtrs[ pFace->ubSoldierID ]->inv[HEAD1POS].usItem;
@@ -1621,20 +1763,77 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
}
}
if (gGameSettings.fOptions[ TOPTION_SHOW_TACTICAL_FACE_GEAR ] == TRUE && MercPtrs[ pFace->ubSoldierID ]->stats.bLife > 0 &&
( MercPtrs[ pFace->ubSoldierID ]->inv[HELMETPOS].usItem > 0 ) )
{
uiFaceItemOne=MercPtrs[ pFace->ubSoldierID ]->inv[HELMETPOS].usItem;
if ( uiFaceItemOne != NONE && zNewFaceGear[uiFaceItemOne].Type == 1 ) //back
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceItemOne, isIMP);
}
}
// this section chooses the pictures for gas mask and NV goggles if the ini setting "SHOW_TACTICAL_FACE_GEAR" is TRUE
// and the merc actually wears something to be shown
if (gGameExternalOptions.fShowTacticalFaceGear == TRUE && MercPtrs[ pFace->ubSoldierID ]->stats.bLife > 0 &&
( MercPtrs[ pFace->ubSoldierID ]->inv[HEAD1POS].usItem + MercPtrs[ pFace->ubSoldierID ]->inv[HEAD2POS].usItem ) > 0 &&
// dirty hack for IMPs because they don't have pictures for face gear
( MercPtrs[ pFace->ubSoldierID ]->ubProfile < 51 || MercPtrs[ pFace->ubSoldierID ]->ubProfile > 56 ))
if (gGameSettings.fOptions[ TOPTION_SHOW_TACTICAL_FACE_GEAR ] == TRUE && MercPtrs[ pFace->ubSoldierID ]->stats.bLife > 0 &&
( MercPtrs[ pFace->ubSoldierID ]->inv[HEAD1POS].usItem + MercPtrs[ pFace->ubSoldierID ]->inv[HEAD2POS].usItem ) > 0 )
{
/*
BOOLEAN isIMP = FALSE;
UINT8 faceProfileId = MercPtrs[ pFace->ubSoldierID ]->ubProfile;
// WANNE: IMP: Special handling for face gear
if (MercPtrs[ pFace->ubSoldierID ]->ubProfile >= 51 && MercPtrs[ pFace->ubSoldierID ]->ubProfile <= 56)
{
// IMP: Imps anhand des FaceIndex rausfinden!!
faceProfileId = gMercProfiles[MercPtrs[ pFace->ubSoldierID ]->ubProfile].ubFaceIndex;
isIMP = TRUE;
}
*/
// WANNE: Removed the limitation
// silversurfer: don't overwrite icons if they shall be shown!
//if ( !gGameExternalOptions.fShowTacticalFaceIcons )
//if ( !gGameSettings.fOptions[ SHOW_TACTICAL_FACE_ICONS ] )
{
uiFaceItemOne=MercPtrs[ pFace->ubSoldierID ]->inv[HEAD1POS].usItem;
uiFaceItemTwo=MercPtrs[ pFace->ubSoldierID ]->inv[HEAD2POS].usItem;
uiFaceOne=MercPtrs[ pFace->ubSoldierID ]->inv[HEAD1POS].usItem;
uiFaceTwo=MercPtrs[ pFace->ubSoldierID ]->inv[HEAD2POS].usItem;
// check first face slot
if ( uiFaceItemOne != NONE )
{
if ( zNewFaceGear[uiFaceOne].Type == 3 )
{
uiFaceItemOne = 1;
}
else if ( zNewFaceGear[uiFaceOne].Type == 4 )
{
uiFaceItemOne = 2;
}
else uiFaceItemOne = 0;
}
// check second face slot
if ( uiFaceItemTwo != NONE )
{
if ( zNewFaceGear[uiFaceTwo].Type == 3 )
{
uiFaceItemTwo = 21;
}
else if ( zNewFaceGear[uiFaceTwo].Type == 4 )
{
uiFaceItemTwo = 42;
}
else uiFaceItemTwo = 0;
}
/*
// check first face slot
if ( uiFaceItemOne != NONE )
{
@@ -1678,7 +1877,8 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
break;
}
}
*/
// Now select the correct picture. This uses a matrix from uiFaceOneItem and uiFaceTwoItem (simple addition)
// the numbers on the outer border are used if that is the only item worn in that slot
//
@@ -1698,12 +1898,102 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
// silversurfer: we don't want to display icons for gas mask or NV goggles because you can actually see the merc wearing the gear
// in case of gas mask together with NV we display the picture of the item in face slot 1 and the icon of the item
// in face slot 2 (if icons are allowed)
//Type : 3 - gas mask ; 4 - NV googles
// gas mask only
if ( ubFaceItemsCombined == 1 || ubFaceItemsCombined == 21 )
{
if ( zNewFaceGear[uiFaceOne].Type == 3 )
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceOne, isIMP);
}
else if ( zNewFaceGear[uiFaceTwo].Type == 3 )
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceTwo, isIMP);
}
}
// NV goggles only
if ( ubFaceItemsCombined == 2 || ubFaceItemsCombined == 42 )
{
if ( zNewFaceGear[uiFaceOne].Type == 4 )
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceOne, isIMP);
}
else if ( zNewFaceGear[uiFaceTwo].Type == 4 )
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceTwo, isIMP);
}
}
// NV goggles + gas mask
if ( ubFaceItemsCombined == 23 )
{
if ( zNewFaceGear[uiFaceOne].Type == 4 && zNewFaceGear[uiFaceTwo].Type == 3 )
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceTwo, isIMP);
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceOne, isIMP);
}
}
// gas mask + NV goggles
if ( ubFaceItemsCombined == 43 )
{
if ( zNewFaceGear[uiFaceOne].Type == 3 && zNewFaceGear[uiFaceTwo].Type == 4 )
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceOne, isIMP);
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceTwo, isIMP);
}
}
// gas mask + extended ear
if ( ubFaceItemsCombined == 24 || ubFaceItemsCombined == 64 )
{
if ( zNewFaceGear[uiFaceOne].Type == 3 )
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceOne, isIMP);
}
else if ( zNewFaceGear[uiFaceTwo].Type == 3 )
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceTwo, isIMP);
}
}
// gas mask + extended ear
if ( ubFaceItemsCombined == 25 || ubFaceItemsCombined == 85 )
{
if ( zNewFaceGear[uiFaceOne].Type == 3 )
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceOne, isIMP);
}
else if ( zNewFaceGear[uiFaceTwo].Type == 3 )
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceTwo, isIMP);
}
}
// NV goggles + extended ear
if ( ubFaceItemsCombined == 46 || ubFaceItemsCombined == 86 )
{
if ( zNewFaceGear[uiFaceOne].Type == 4 )
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceOne, isIMP);
}
else if ( zNewFaceGear[uiFaceTwo].Type == 4 )
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceTwo, isIMP);
}
}
/*
switch( ubFaceItemsCombined )
{
// gas mask only
case 1:
case 21:
DoRightIcon_legion_GAS_MASK( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, MercPtrs[ pFace->ubSoldierID ]->ubProfile );
DoRightIcon_legion_GAS_MASK( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId, isIMP );
// WANNE: Removed silversurfers limitation, because it is too complex for the players :)
//fDoIcon = FALSE;
@@ -1712,7 +2002,7 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
// NV goggles only
case 2:
case 42:
DoRightIcon_legion_NV( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, MercPtrs[ pFace->ubSoldierID ]->ubProfile );
DoRightIcon_legion_NV( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId, isIMP );
// WANNE: Removed silversurfers limitation, because it is too complex for the players :)
//fDoIcon = FALSE;
@@ -1720,32 +2010,33 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
break;
// NV goggles + gas mask
case 23:
DoRightIcon_legion_NV( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, MercPtrs[ pFace->ubSoldierID ]->ubProfile );
DoRightIcon_legion_GAS_MASK( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId, isIMP );
DoRightIcon_legion_NV( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId, isIMP );
// WANNE: Removed silversurfers limitation, because it is too complex for the players :)
/*if ( gGameExternalOptions.fShowTacticalFaceIcons )
{
sIconIndex = 9;
fDoIcon = TRUE;
}*/
//if ( gGameSettings.fOptions[ SHOW_TACTICAL_FACE_ICONS ] )
//{
// sIconIndex = 9;
// fDoIcon = TRUE;
//}
break;
// gas mask + NV goggles
case 43:
DoRightIcon_legion_GAS_MASK( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, MercPtrs[ pFace->ubSoldierID ]->ubProfile );
DoRightIcon_legion_GAS_MASK( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId, isIMP );
DoRightIcon_legion_NV( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId, isIMP );
// WANNE: Removed silversurfers limitation, because it is too complex for the players :)
/*if ( gGameExternalOptions.fShowTacticalFaceIcons )
{
sIconIndex = 10;
fDoIcon = TRUE;
}*/
//if ( gGameSettings.fOptions[ SHOW_TACTICAL_FACE_ICONS ] )
//{
// sIconIndex = 10;
// fDoIcon = TRUE;
//}
break;
// gas mask + sun goggles
case 24:
case 64:
DoRightIcon_legion_GAS_MASK( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, MercPtrs[ pFace->ubSoldierID ]->ubProfile );
DoRightIcon_legion_GAS_MASK( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId, isIMP );
// WANNE: Removed silversurfers limitation, because it is too complex for the players :)
//sIconIndex = 15;
@@ -1755,7 +2046,7 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
// gas mask + extended ear
case 25:
case 85:
DoRightIcon_legion_GAS_MASK( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, MercPtrs[ pFace->ubSoldierID ]->ubProfile );
DoRightIcon_legion_GAS_MASK( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId, isIMP );
// WANNE: Removed silversurfers limitation, because it is too complex for the players :)
//sIconIndex = 12;
@@ -1765,7 +2056,7 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
// NV goggles + extended ear
case 46:
case 86:
DoRightIcon_legion_NV( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, MercPtrs[ pFace->ubSoldierID ]->ubProfile );
DoRightIcon_legion_NV( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId, isIMP );
// WANNE: Removed silversurfers limitation, because it is too complex for the players :)
//sIconIndex = 12;
@@ -1775,6 +2066,25 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
default:
break;
}
*/
}
if (gGameSettings.fOptions[ TOPTION_SHOW_TACTICAL_FACE_GEAR ] == TRUE && MercPtrs[ pFace->ubSoldierID ]->stats.bLife > 0 &&
( MercPtrs[ pFace->ubSoldierID ]->inv[HELMETPOS].usItem > 0 )
// dirty hack for IMPs because they don't have pictures for face gear
/* && ( MercPtrs[ pFace->ubSoldierID ]->ubProfile < 51 || MercPtrs[ pFace->ubSoldierID ]->ubProfile > 56 ) */ )
{
uiFaceItemOne=MercPtrs[ pFace->ubSoldierID ]->inv[HELMETPOS].usItem;
if ( uiFaceItemOne != NONE )
{
if ( uiFaceItemOne != NONE && zNewFaceGear[uiFaceItemOne].Type == 2 ) //front
{
DoRightIcon_FaceGear( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons_legion, faceProfileId ,uiFaceItemOne, isIMP);
}
}
}
//------------------------------------end of tactical face gear-----------------------------
+22 -4
View File
@@ -455,7 +455,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
// temporarily set burst to true to calculate action points
pSoldier->bDoBurst = TRUE;
sAPCost = CalcTotalAPsToAttack( pSoldier, sTargetGridNo, TRUE, 0 );
sAPCost = CalcTotalAPsToAttack( pSoldier, sTargetGridNo, TRUE, pSoldier->aiData.bAimTime );
// reset burst mode to false (which is what it was at originally)
pSoldier->bDoBurst = FALSE;
@@ -545,7 +545,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
misfirePenalty = misfirePenaltyConst + (Chance(misfirePenaltyRand)?1:0); //apply the base integral cost and the fractional cost (in the form of probablilite)
pSoldier->bDoAutofire += misfirePenalty;
sAPCost = CalcTotalAPsToAttack( pSoldier, sTargetGridNo, TRUE, 0 );
sAPCost = CalcTotalAPsToAttack( pSoldier, sTargetGridNo, TRUE, pSoldier->aiData.bAimTime );
}
while(EnoughPoints( pSoldier, sAPCost, 0, FALSE ) && roll < ((pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire)?chanceToMisfire:chanceToMisfireDry));
//note that we could misfire more bullets than we have rounds
@@ -553,7 +553,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
//the max that can be lost this way is 1AP
pSoldier->bDoAutofire -= misfirePenalty;
sAPCost = CalcTotalAPsToAttack( pSoldier, sTargetGridNo, TRUE, 0 );
sAPCost = CalcTotalAPsToAttack( pSoldier, sTargetGridNo, TRUE, pSoldier->aiData.bAimTime );
if((__min(pSoldier->bDoAutofire,pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft) - startAuto) > 0 && pSoldier->bTeam == OUR_TEAM)
{
@@ -673,6 +673,8 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
}
else
{
//CHRISL: Need to reset this as it doesn't automatically get reset when we don't have enough APs to shot
pSoldier->flags.fDoSpread = FALSE;
return( ITEM_HANDLE_NOAPS );
}
@@ -851,7 +853,11 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
}
}
if ( Item[usHandItem].wirecutters && pTargetSoldier == NULL ) // Madd: quick fix to allow wirecutter/knives
ROTTING_CORPSE *pCorpse = GetCorpseAtGridNo( sGridNo, pSoldier->pathing.bLevel );
BOOLEAN fCorpse = FALSE;
if(pCorpse != NULL)
fCorpse = IsValidDecapitationCorpse( pCorpse );
if ( Item[usHandItem].wirecutters && pTargetSoldier == NULL && !pCorpse ) // Madd: quick fix to allow wirecutter/knives
{
// See if we can get there to stab
sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
@@ -1842,6 +1848,12 @@ void SoldierGetItemFromWorld( SOLDIERTYPE *pSoldier, INT32 iItemIndex, INT32 sGr
}
else
{
//CHRISL: Make sure non-ammo item status is a valid 0-100 number
if(Item[gWorldItems[pItemPool->iItemIndex].object.usItem].usItemClass != IC_AMMO){
gWorldItems[pItemPool->iItemIndex].object[0]->data.objectStatus = __max(0,gWorldItems[pItemPool->iItemIndex].object[0]->data.objectStatus);
gWorldItems[pItemPool->iItemIndex].object[0]->data.objectStatus = __min(100,gWorldItems[pItemPool->iItemIndex].object[0]->data.objectStatus);
}
// Make copy of item
gTempObject = gWorldItems[ pItemPool->iItemIndex ].object;
@@ -1933,6 +1945,12 @@ void SoldierGetItemFromWorld( SOLDIERTYPE *pSoldier, INT32 iItemIndex, INT32 sGr
}
else
{
//CHRISL: Make sure non-ammo item status is a valid 0-100 number
if(Item[gWorldItems[iItemIndex].object.usItem].usItemClass != IC_AMMO){
gWorldItems[iItemIndex].object[0]->data.objectStatus = __max(0,gWorldItems[iItemIndex].object[0]->data.objectStatus);
gWorldItems[iItemIndex].object[0]->data.objectStatus = __min(100,gWorldItems[iItemIndex].object[0]->data.objectStatus);
}
/*
// handle theft.. will return true if theft has failed ( if soldier was caught )
if( pSoldier->bTeam == OUR_TEAM )
+2 -24
View File
@@ -517,28 +517,6 @@ void GetMercOknoDirection( UINT8 ubSoldierID, BOOLEAN *pfGoDown, BOOLEAN *pfGoUp
}
}
}
void GetMercFenceDirection( UINT8 ubSoldierID, BOOLEAN *pfGoDown, BOOLEAN *pfGoUp )
{
INT8 bNewDirection;
SOLDIERTYPE *pSoldier;
*pfGoDown = FALSE;
*pfGoUp = FALSE;
if ( !GetSoldier( &pSoldier, ubSoldierID ) )
{
return;
}
if ( pSoldier->pathing.bLevel == 0 )
{
if ( FindHeigherLevelFence( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) )
{
*pfGoUp = TRUE;
}
}
}
//----------------------------------------------------------------------------------
@@ -2062,7 +2040,7 @@ UINT32 UIHandleCMoveMerc( UI_EVENT *pUIEvent )
if(!(gTacticalStatus.uiFlags & INCOMBAT) && pSoldier->flags.ZipperFlag)
{
pSoldier->flags.ZipperFlag=FALSE;
RenderBackpackButtons(0);
RenderBackpackButtons(ACTIVATE_BUTTON);
}
}
// FOR REALTIME - DO MOVEMENT BASED ON STANCE!
@@ -5101,7 +5079,7 @@ UINT32 UIHandleTOnTerrain( UI_EVENT *pUIEvent )
gUIDisplayActionPointsOffY = 3;
// Set # of APs
gsCurrentActionPoints = 6;
gsCurrentActionPoints = APBPConstants[AP_TALK];
// Determine if we can afford!
if ( !EnoughPoints( pSoldier, gsCurrentActionPoints, 0, FALSE ) )
-4
View File
@@ -369,9 +369,5 @@ void GetGridNoScreenXY( INT32 sGridNo, INT16 *pScreenX, INT16 *pScreenY );
//Legion by Jazz
void GetMercOknoDirection( UINT8 ubSoldierID, BOOLEAN *pfGoDown, BOOLEAN *pfGoUp );
void GetMercFenceDirection( UINT8 ubSoldierID, BOOLEAN *pfGoDown, BOOLEAN *pfGoUp );
// HEADROCK HAM 4: Tells the targeting cursor whether we're adding bullets to autofire, or adding aim click levels.
extern BOOLEAN fAutofireBulletsMode;
#endif
+1
View File
@@ -2986,6 +2986,7 @@ void HandleNPCDoAction( UINT8 ubTargetNPC, UINT16 usActionCode, UINT8 ubQuoteNum
case NPC_ACTION_START_BLOODCAT_QUEST:
StartQuest( QUEST_BLOODCATS, gWorldSectorX, gWorldSectorY );
SetFactTrue( FACT_PLAYER_KNOWS_ABOUT_BLOODCAT_LAIR);
break;
case NPC_ACTION_START_MINE:
File diff suppressed because it is too large Load Diff
+172 -102
View File
@@ -200,7 +200,8 @@ extern int MAP_KEYRING_Y;
//#define MAP_KEYRING_X 217
//#define MAP_KEYRING_Y 271
#define KEYRING_WIDTH 30
#define KEYRING_HEIGHT 24
#define KEYRING_HEIGHT 22
#define TACTICAL_INVENTORY_KEYRING_GRAPHIC_OFFSET_X 215
//enum used for the money buttons
enum
@@ -240,6 +241,8 @@ BOOLEAN gfBadThrowItemCTGH;
BOOLEAN gfDontChargeAPsToPickup = FALSE;
BOOLEAN gbItemPointerLocateGood = FALSE;
INT32 iItemPosition = 0;
//CHRISL: Global variable to store stack item for message box system
UINT8 gbMessageBoxSubObject = 0;
// ITEM DESCRIPTION BOX STUFF
UINT32 guiItemDescBox;
@@ -808,7 +811,9 @@ void GenerateConsString( STR16 zItemCons, OBJECTTYPE * pObject, UINT32 uiPixLimi
BOOLEAN UseNASDesc(OBJECTTYPE *pObject){
if(pObject->exists() == FALSE)
return FALSE;
return (Item[pObject->usItem].usItemClass != IC_LBEGEAR && Item[pObject->usItem].usItemClass != IC_MONEY && UsingNewAttachmentSystem()==true);
if(guiCurrentScreen == MAP_SCREEN && Item[pObject->usItem].usItemClass == IC_LBEGEAR && UsingNewAttachmentSystem()==true)
return FALSE; // the map screen can't support NAS and LBEGEAR.
return (/*Item[pObject->usItem].usItemClass != IC_LBEGEAR && Item[pObject->usItem].usItemClass != IC_MONEY && */UsingNewAttachmentSystem()==true);
}
//WarmSteel - This function is used to move groups of items with NAS along the Y axe
@@ -895,6 +900,22 @@ void InitInvData(INV_REGIONS &InvData, BOOLEAN fBigPocket, INT16 sBarDx, INT16 s
InvData.sX = sX;
InvData.sY = sY;
}
void ResetInvData()
{
for ( INT32 cnt = 0; cnt < NUM_INV_SLOTS; cnt++ )
{
// set inventory pocket coordinates from the table passed in
gSMInvData[ cnt ].sX = 0;
gSMInvData[ cnt ].sY =0;
gSMInvData[ cnt ].sWidth =0;
gSMInvData[ cnt ].sHeight =0;
gSMInvData[ cnt ].sBarDx =0;
gSMInvData[ cnt ].sBarDy =0;
gSMInvData[ cnt ].fBigPocket =0;
}
}
void InitInventoryOld()
{
BODYPOSFINAL = GUNSLINGPOCKPOS;//RESET in initInventory
@@ -903,6 +924,8 @@ void InitInventoryOld()
MEDPOCKFINAL = SMALLPOCK1POS;//RESET in initInventory
SMALLPOCKFINAL = SMALLPOCK9POS;//RESET in initInventory
ResetInvData();
InitInvData(gSMInvData[HELMETPOS], FALSE, INV_BAR_DX, INV_BAR_DY, HEAD_INV_SLOT_WIDTH, HEAD_INV_SLOT_HEIGHT, 0, 0); // HELMETPOS
InitInvData(gSMInvData[VESTPOS], FALSE, INV_BAR_DX, INV_BAR_DY, VEST_INV_SLOT_WIDTH, VEST_INV_SLOT_HEIGHT, 0, 0); // VESTPOS
@@ -932,6 +955,8 @@ void InitInventoryNew()
MEDPOCKFINAL = SMALLPOCK1POS;//RESET in initInventory
SMALLPOCKFINAL = NUM_INV_SLOTS;//RESET in initInventory
ResetInvData();
if(iResolution == 0){
InitInvData(gSMInvData[0], FALSE, INV_BAR_DX, INV_BAR_DY, HEAD_INV_SLOT_WIDTH, HEAD_INV_SLOT_HEIGHT, 0, 0); // HELMETPOS
InitInvData(gSMInvData[1], FALSE, INV_BAR_DX, INV_BAR_DY, VEST_INV_SLOT_WIDTH, VEST_INV_SLOT_HEIGHT, 0, 0); // VESTPOS
@@ -1105,18 +1130,42 @@ BOOLEAN InitInvSlotInterface( INV_REGION_DESC *pRegionDesc , INV_REGION_DESC *pC
// HEADROCK: Readjusted this, for the TACTICAL Enhanced Description Box
if ( guiCurrentScreen == MAP_SCREEN )
{
gMoneyButtonLoc.x = 174;
gMoneyButtonLoc.y = 115;
if(UsingNewAttachmentSystem() == true)
{
gMoneyButtonLoc.x = 186;
gMoneyButtonLoc.y = 170;
}
else
{
gMoneyButtonLoc.x = 174;
gMoneyButtonLoc.y = 115;
}
}
else if ( UsingEDBSystem() > 0 )
{
gMoneyButtonLoc.x = ((UsingNewInventorySystem() == false)) ? (343 + INTERFACE_START_X) : (244 + INTERFACE_START_X);
gMoneyButtonLoc.y = ( 11 + INV_INTERFACE_START_Y );
if(UsingNewAttachmentSystem() == true)
{
gMoneyButtonLoc.x = ((UsingNewInventorySystem() == false)) ? (401 + INTERFACE_START_X) : (302 + INTERFACE_START_X);
gMoneyButtonLoc.y = ( 64 + INV_INTERFACE_START_Y );
}
else
{
gMoneyButtonLoc.x = ((UsingNewInventorySystem() == false)) ? (343 + INTERFACE_START_X) : (244 + INTERFACE_START_X);
gMoneyButtonLoc.y = ( 11 + INV_INTERFACE_START_Y );
}
}
else
{
gMoneyButtonLoc.x = ((UsingNewInventorySystem() == false)) ? (343 + INTERFACE_START_X) : (388 + INTERFACE_START_X);
gMoneyButtonLoc.y = ( 11 + INV_INTERFACE_START_Y );
if(UsingNewAttachmentSystem() == true)
{
gMoneyButtonLoc.x = ((UsingNewInventorySystem() == false)) ? (401 + INTERFACE_START_X) : (302 + INTERFACE_START_X);
gMoneyButtonLoc.y = ( 64 + INV_INTERFACE_START_Y );
}
else
{
gMoneyButtonLoc.x = ((UsingNewInventorySystem() == false)) ? (343 + INTERFACE_START_X) : (244 + INTERFACE_START_X);
gMoneyButtonLoc.y = ( 11 + INV_INTERFACE_START_Y );
}
}
// Load all four body type images
@@ -1233,6 +1282,15 @@ void ShutdownKeyRingInterface( void )
return;
}
void ShutdownInventoryInterface( void )
{
// Add regions for inventory slots
for ( INT32 cnt = 0; cnt < NUM_INV_SLOTS; cnt++ )
{
MSYS_RemoveRegion(&gSMInvRegion[ cnt ]);
}
}
void DisableInvRegions( BOOLEAN fDisable )
{
INT32 cnt;
@@ -1255,7 +1313,7 @@ void DisableInvRegions( BOOLEAN fDisable )
MSYS_DisableRegion( &gSM_SELMERCMoneyRegion );
EnableKeyRing( FALSE );
RenderBackpackButtons(3); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(DISABLE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
}
else
{
@@ -1263,7 +1321,7 @@ void DisableInvRegions( BOOLEAN fDisable )
MSYS_EnableRegion( &gSM_SELMERCMoneyRegion );
EnableKeyRing( TRUE );
RenderBackpackButtons(2); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(ENABLE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
}
}
@@ -1576,7 +1634,7 @@ void INVRenderINVPanelItem( SOLDIERTYPE *pSoldier, INT16 sPocket, UINT8 fDirtyLe
// CHRISL: Display pocket capacity if we're holding something in the cursor
if (!gfSMDisableForItems && (UsingNewInventorySystem() == true) && gpItemPointer != NULL)
{
int itemSlotLimit = ItemSlotLimit(gpItemPointer, sPocket, pSoldier);
UINT8 itemSlotLimit = ItemSlotLimit(gpItemPointer, sPocket, pSoldier);
RenderPocketItemCapacity( guiSAVEBUFFER, itemSlotLimit, sPocket, pSoldier, &pSoldier->inv[sPocket], sX, sY );
if(itemSlotLimit == 0 && !CanItemFitInPosition(pSoldier, gpItemPointer, (INT8)sPocket, FALSE)) {
fHatchItOut = TRUE;
@@ -1587,7 +1645,8 @@ void INVRenderINVPanelItem( SOLDIERTYPE *pSoldier, INT16 sPocket, UINT8 fDirtyLe
if(gpItemPointer != NULL)
{
if(!gfSMDisableForItems && !CanItemFitInPosition(pSoldier, gpItemPointer, (INT8)sPocket, FALSE)){
if(!ValidAttachment(gpItemPointer->usItem, pObject )){
if((UsingNewAttachmentSystem()==false && !ValidAttachment(gpItemPointer->usItem, pObject )) ||
(UsingNewAttachmentSystem()==true && !ValidItemAttachmentSlot(pObject, gpItemPointer->usItem, FALSE, FALSE))){
fHatchItOut = TRUE;
}
else{
@@ -1852,8 +1911,10 @@ BOOLEAN HandleCompatibleAmmoUIForMapScreen( SOLDIERTYPE *pSoldier, INT32 bInvPos
continue;
}
if ( ValidAttachment( pObject->usItem, pTestObject ) ||
ValidAttachment( pTestObject->usItem, pObject ) ||
if ( (UsingNewAttachmentSystem()==false && ValidAttachment( pObject->usItem, pTestObject )) ||
(UsingNewAttachmentSystem()==false && ValidAttachment( pTestObject->usItem, pObject )) ||
(UsingNewAttachmentSystem()==true && ValidItemAttachmentSlot(pTestObject, pObject->usItem, FALSE, FALSE, 0, cnt)) ||
(UsingNewAttachmentSystem()==true && ValidItemAttachmentSlot(pObject, pTestObject->usItem, FALSE, FALSE, 0, cnt)) ||
ValidLaunchable( pTestObject->usItem, pObject->usItem ) ||
ValidLaunchable( pObject->usItem, pTestObject->usItem ) )
{
@@ -2085,8 +2146,10 @@ BOOLEAN InternalHandleCompatibleAmmoUI( SOLDIERTYPE *pSoldier, OBJECTTYPE *pTest
continue;
}
if ( ValidAttachment( pObject->usItem, pTestObject ) ||
ValidAttachment( pTestObject->usItem, pObject ) ||
if ( (UsingNewAttachmentSystem()==false && ValidAttachment( pObject->usItem, pTestObject )) ||
(UsingNewAttachmentSystem()==false && ValidAttachment( pTestObject->usItem, pObject )) ||
(UsingNewAttachmentSystem()==true && ValidItemAttachmentSlot(pTestObject, pObject->usItem, FALSE, FALSE, 0, cnt)) ||
(UsingNewAttachmentSystem()==true && ValidItemAttachmentSlot(pObject, pTestObject->usItem, FALSE, FALSE, 0, cnt)) ||
ValidLaunchable( pTestObject->usItem, pObject->usItem ) ||
ValidLaunchable( pObject->usItem, pTestObject->usItem ) )
{
@@ -2403,7 +2466,7 @@ void InitItemInterface( )
}
// CHRISL: Function to display pocket inventory quantity based on object in cursor
void RenderPocketItemCapacity( UINT32 uiWhichBuffer, UINT8 pCapacity, INT16 bPos, SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT16 sX, INT16 sY )
void RenderPocketItemCapacity( UINT32 uiWhichBuffer, INT8 pCapacity, INT16 bPos, SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT16 sX, INT16 sY )
{
static CHAR16 pStr[ 100 ];
@@ -2443,7 +2506,8 @@ void RenderPocketItemCapacity( UINT32 uiWhichBuffer, UINT8 pCapacity, INT16 bPos
SetFontForeground( FONT_YELLOW );
swprintf( pStr, L"L" );
}
else if(ValidAttachment(gpItemPointer->usItem, &(pSoldier->inv[bPos]) ))
else if((UsingNewAttachmentSystem()==false && ValidAttachment(gpItemPointer->usItem, &(pSoldier->inv[bPos]) )) ||
(UsingNewAttachmentSystem()==true && ValidItemAttachmentSlot(&(pSoldier->inv[bPos]), gpItemPointer->usItem, FALSE, FALSE)))
{
SetFontForeground( FONT_YELLOW );
swprintf( pStr, L"A" );
@@ -2941,29 +3005,22 @@ void InitItemDescriptionBoxStartCoords( BOOLEAN fIsEnhanced, BOOLEAN fUsingNAS )
{
UINT8 mode = UsingEDBSystem();
if(fUsingNAS){
if (guiCurrentItemDescriptionScreen != SHOPKEEPER_SCREEN)
if( UsingNewInventorySystem() == true ) // NIV
{
ITEMDESC_START_X = 115;
ITEMDESC_START_Y = (1 + INV_INTERFACE_START_Y);
ITEMDESC_HEIGHT = 195;
ITEMDESC_WIDTH = 335; // OIV only
}
else if( UsingNewInventorySystem() == true ) // ODB/NIV
{
ITEMDESC_START_X = 200;//259;
ITEMDESC_START_Y = (1 + INV_INTERFACE_START_Y);
ITEMDESC_HEIGHT = guiCurrentItemDescriptionScreen == SHOPKEEPER_SCREEN ? 193 : 195;
ITEMDESC_WIDTH = 430; // OIV only
}
else // ODB/OIV
ITEMDESC_WIDTH = 335;
}
else // OIV
{
ITEMDESC_HEIGHT = 193;
ITEMDESC_WIDTH = 430; // OIV only
ITEMDESC_START_X = 214;//214
ITEMDESC_WIDTH = 430;
ITEMDESC_START_X = 214;
ITEMDESC_START_Y = (1-(ITEMDESC_HEIGHT-INV_INTERFACE_HEIGHT) + INV_INTERFACE_START_Y);
}
if(UsingNewInventorySystem() == true && guiCurrentScreen == GAME_SCREEN)
if(UsingNewInventorySystem() == true && (guiCurrentScreen == GAME_SCREEN || guiCurrentScreen == SHOPKEEPER_SCREEN))
{
if(iResolution == 0)
ITEMDESC_WIDTH = 526;
@@ -2987,7 +3044,7 @@ void InitItemDescriptionBoxStartCoords( BOOLEAN fIsEnhanced, BOOLEAN fUsingNAS )
} else {
if( UsingNewInventorySystem() == true ) // ODB/NIV
{
if (guiCurrentItemDescriptionScreen != SHOPKEEPER_SCREEN)
//if (guiCurrentItemDescriptionScreen != SHOPKEEPER_SCREEN)
{
// HEADROCK HAM 4:
ITEMDESC_START_X = 115;
@@ -2995,13 +3052,13 @@ void InitItemDescriptionBoxStartCoords( BOOLEAN fIsEnhanced, BOOLEAN fUsingNAS )
ITEMDESC_HEIGHT = 195;
ITEMDESC_WIDTH = 335; // OIV only
}
else
{
ITEMDESC_START_X = 259;
ITEMDESC_START_Y = (1 + INV_INTERFACE_START_Y);
ITEMDESC_HEIGHT = guiCurrentItemDescriptionScreen == SHOPKEEPER_SCREEN ? 133 : 195;
ITEMDESC_WIDTH = 320; // OIV only
}
//else
//{
// ITEMDESC_START_X = 259;
// ITEMDESC_START_Y = (1 + INV_INTERFACE_START_Y);
// ITEMDESC_HEIGHT = guiCurrentItemDescriptionScreen == SHOPKEEPER_SCREEN ? 133 : 195;
// ITEMDESC_WIDTH = 320; // OIV only
//}
}
else // ODB/OIV
{
@@ -3011,7 +3068,7 @@ void InitItemDescriptionBoxStartCoords( BOOLEAN fIsEnhanced, BOOLEAN fUsingNAS )
ITEMDESC_WIDTH = 320; // OIV only
}
if(UsingNewInventorySystem() == true && guiCurrentScreen == GAME_SCREEN)
if(UsingNewInventorySystem() == true && guiCurrentScreen == GAME_SCREEN || guiCurrentScreen == SHOPKEEPER_SCREEN)
{
if(iResolution == 0)
ITEMDESC_WIDTH = 526;
@@ -3073,7 +3130,7 @@ BOOLEAN InternalInitItemDescriptionBox( OBJECTTYPE *pObject, INT16 sX, INT16 sY,
InitItemDescriptionBoxStartCoords( gGameExternalOptions.iEnhancedDescriptionBox, UseNASDesc( pObject ) );
// Set X, Y
if(guiCurrentScreen == GAME_SCREEN)
if(guiCurrentScreen == GAME_SCREEN || (sX == 0 && sY == 0))
{
gsInvDescX = ITEMDESC_START_X; //sX;
gsInvDescY = ITEMDESC_START_Y; //sY;
@@ -3124,6 +3181,8 @@ BOOLEAN InternalInitItemDescriptionBox( OBJECTTYPE *pObject, INT16 sX, INT16 sY,
}
else if(guiCurrentItemDescriptionScreen == SHOPKEEPER_SCREEN)
{
// MSYS_DefineRegion( &gInvDesc, (UINT16)SM_ITEMDESC_START_X, (UINT16)SM_ITEMDESC_START_Y ,(UINT16)(SM_ITEMDESC_START_X + ITEMDESC_WIDTH), (UINT16)(SM_ITEMDESC_START_Y + ITEMDESC_HEIGHT), MSYS_PRIORITY_HIGHEST,
// MSYS_NO_CURSOR, MSYS_NO_CALLBACK, ItemDescCallback );
MSYS_DefineRegion( &gInvDesc, (UINT16)gsInvDescX, (UINT16)gsInvDescY ,(UINT16)(gsInvDescX + ITEMDESC_WIDTH), (UINT16)(gsInvDescY + ITEMDESC_HEIGHT), MSYS_PRIORITY_HIGHEST,
MSYS_NO_CURSOR, MSYS_NO_CALLBACK, ItemDescCallback );
MSYS_AddRegion( &gInvDesc);
@@ -3260,11 +3319,7 @@ BOOLEAN InternalInitItemDescriptionBox( OBJECTTYPE *pObject, INT16 sX, INT16 sY,
// Load graphic
// HEADROCK: Select STI based on Description Box used:
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
// HEADROCK HAM 4: No more need for two files. Just use one.
//if(UsingEDBSystem() > 0)
strcpy( VObjectDesc.ImageFile, "INTERFACE\\infobox_interface_edb.sti" );
//else
// strcpy( VObjectDesc.ImageFile, "INTERFACE\\infobox_interface.sti" );
strcpy( VObjectDesc.ImageFile, "INTERFACE\\infobox_interface.sti" );
CHECKF( AddVideoObject( &VObjectDesc, &guiItemDescBox) );
if(ubPosition != 255 && UsingNewInventorySystem() == true)
@@ -3278,21 +3333,9 @@ BOOLEAN InternalInitItemDescriptionBox( OBJECTTYPE *pObject, INT16 sX, INT16 sY,
// HEADROCK: Select STI based on Description Box used:
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
// HEADROCK HAM 4: No more need for two files. Just use the EDB one.
//if(UsingEDBSystem() > 0)
strcpy( VObjectDesc.ImageFile, "INTERFACE\\iteminfoc_edb.STI" );
//else
// strcpy( VObjectDesc.ImageFile, "INTERFACE\\iteminfoc.STI" );
strcpy( VObjectDesc.ImageFile, "INTERFACE\\iteminfoc.STI" );
CHECKF( AddVideoObject( &VObjectDesc, &guiMapItemDescBox) );
if(UsingNewInventorySystem())
{
// HEADROCK HAM 4: LBE backgrounds for desc box
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
strcpy( VObjectDesc.ImageFile, "INTERFACE\\INFOBOX_LBE.STI" );
CHECKF( AddVideoObject( &VObjectDesc, &guiItemInfoLBEBackground) );
}
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
strcpy( VObjectDesc.ImageFile, "INTERFACE\\bullet.STI" );
CHECKF( AddVideoObject( &VObjectDesc, &guiBullet) );
@@ -3558,7 +3601,7 @@ void UpdateAttachmentTooltips(OBJECTTYPE *pObject, UINT8 ubStatusIndex)
// Contains entire string of attachment names
CHAR16 attachStr[2500];
// Contains current attachment string
CHAR16 attachStr2[100];
CHAR16 attachStr2[200];
// Contains temporary attachment list before added to string constant from text.h
CHAR16 attachStr3[2500];
UINT16 usAttachment;
@@ -3754,12 +3797,33 @@ BOOLEAN ReloadItemDesc( )
return( TRUE );
}
void RenderBulletIcon(OBJECTTYPE *pObject, UINT32 ubStatusIndex)
{
CHAR16 pStr[10];
CHAR8 ubString[48];
if(pObject->exists() == false)
return;
if(!gfInItemDescBox)
return;
if ( GetMagSize(pObject) <= 99 )
swprintf( pStr, L"%d/%d", (*pObject)[ubStatusIndex]->data.gun.ubGunShotsLeft, GetMagSize(pObject));
else
swprintf( pStr, L"%d", (*pObject)[ubStatusIndex]->data.gun.ubGunShotsLeft );
FilenameForBPP("INTERFACE\\infobox.sti", ubString);
UnloadButtonImage(giItemDescAmmoButtonImages);
giItemDescAmmoButtonImages = LoadButtonImage(ubString,AmmoTypes[(*pObject)[ubStatusIndex]->data.gun.ubGunAmmoType].grayed,AmmoTypes[(*pObject)[ubStatusIndex]->data.gun.ubGunAmmoType].offNormal,-1,AmmoTypes[(*pObject)[ubStatusIndex]->data.gun.ubGunAmmoType].onNormal,-1 );
//swprintf( pStr, L"0" );
SpecifyButtonText( giItemDescAmmoButton, pStr );
}
void ItemDescAmmoCallback(GUI_BUTTON *btn,INT32 reason)
{
static BOOLEAN fRightDown = FALSE;
CHAR16 pStr[10];
CHAR8 ubString[48];
UINT32 ubStatusIndex = MSYS_GetBtnUserData( btn, 1 );
/* region gets disabled in SKI for shopkeeper boxes. It now works normally for merc's inventory boxes!
@@ -3828,7 +3892,8 @@ void ItemDescAmmoCallback(GUI_BUTTON *btn,INT32 reason)
if(AutoPlaceObject(gpItemDescSoldier, &gTempObject, TRUE) == FALSE)
{
// couldn't find a place on the merc, so drop into the sector
if(fShowMapInventoryPool) //sector inventory panel is open
AutoPlaceObjectToWorld(gpItemDescSoldier, &gTempObject);
/*if(fShowMapInventoryPool) //sector inventory panel is open
{
AutoPlaceObjectInInventoryStash(&gTempObject, gpItemDescSoldier->sGridNo);
fMapPanelDirty = TRUE;
@@ -3836,7 +3901,7 @@ void ItemDescAmmoCallback(GUI_BUTTON *btn,INT32 reason)
else //sector inventory panel is closed
{
AddItemToPool(gpItemDescSoldier->sGridNo, &gTempObject, 1, gpItemDescSoldier->pathing.bLevel, WORLD_ITEM_REACHABLE, 0);
}
}*/
}
}
}
@@ -3845,17 +3910,7 @@ void ItemDescAmmoCallback(GUI_BUTTON *btn,INT32 reason)
fInterfacePanelDirty = DIRTYLEVEL2;
gpItemPointerSoldier = gpItemDescSoldier;
if ( GetMagSize(gpItemDescObject) <= 99 )
swprintf( pStr, L"%d/%d", (*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunShotsLeft, GetMagSize(gpItemDescObject));
else
swprintf( pStr, L"%d", (*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunShotsLeft );
FilenameForBPP("INTERFACE\\infobox.sti", ubString);
UnloadButtonImage(giItemDescAmmoButtonImages);
giItemDescAmmoButtonImages = LoadButtonImage(ubString,AmmoTypes[(*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunAmmoType].grayed,AmmoTypes[(*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunAmmoType].offNormal,-1,AmmoTypes[(*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunAmmoType].onNormal,-1 );
//swprintf( pStr, L"0" );
SpecifyButtonText( giItemDescAmmoButton, pStr );
RenderBulletIcon(gpItemDescObject, ubStatusIndex);
// Set mouse
if(gpItemPointer->exists() == true)
@@ -3924,17 +3979,7 @@ void ItemDescAmmoCallback(GUI_BUTTON *btn,INT32 reason)
//fItemDescDelete = TRUE;
fInterfacePanelDirty = DIRTYLEVEL2;
if ( GetMagSize(gpItemDescObject) <= 99 )
swprintf( pStr, L"%d/%d", (*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunShotsLeft, GetMagSize(gpItemDescObject));
else
swprintf( pStr, L"%d", (*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunShotsLeft );
FilenameForBPP("INTERFACE\\infobox.sti", ubString);
UnloadButtonImage(giItemDescAmmoButtonImages);
giItemDescAmmoButtonImages = LoadButtonImage(ubString,AmmoTypes[(*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunAmmoType].grayed,AmmoTypes[(*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunAmmoType].offNormal,-1,AmmoTypes[(*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunAmmoType].onNormal,-1 );
//swprintf( pStr, L"0" );
SpecifyButtonText( giItemDescAmmoButton, pStr );
RenderBulletIcon(gpItemDescObject, ubStatusIndex);
fItemDescDelete = TRUE;
@@ -3999,8 +4044,9 @@ void PermanantAttachmentMessageBoxCallBack( UINT8 ubExitValue )
{
if ( ubExitValue == MSG_BOX_RETURN_YES )
{
DoAttachment(0, iItemPosition);
DoAttachment(gbMessageBoxSubObject, iItemPosition);
}
gbMessageBoxSubObject = 0;
// else do nothing
}
@@ -4038,6 +4084,7 @@ void ItemDescAttachmentsCallback( MOUSE_REGION * pRegion, INT32 iReason )
if ( (Item[ gpItemPointer->usItem ].inseparable ) && ValidAttachment( gpItemPointer->usItem, gpItemDescObject ) )
{
iItemPosition = uiItemPos;
gbMessageBoxSubObject = (UINT8)ubStatusIndex;
DoScreenIndependantMessageBox( Message[ STR_PERMANENT_ATTACHMENT ], ( UINT8 )MSG_BOX_FLAG_YESNO, PermanantAttachmentMessageBoxCallBack );
return;
}
@@ -4505,7 +4552,9 @@ void RenderItemDescriptionBox( )
sCenX = ITEMDESC_ITEM_X + (INT16)( abs( ITEMDESC_ITEM_WIDTH - (double)usWidth ) / 2 ) - sOffsetX;
sCenY = ITEMDESC_ITEM_Y + (INT16)( abs( ITEMDESC_ITEM_HEIGHT - (double)usHeight ) / 2 )- sOffsetY;
RenderBackpackButtons(1); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(DEACTIVATE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
if(guiCurrentItemDescriptionScreen == SHOPKEEPER_SCREEN && gGameSettings.fOptions[TOPTION_ENHANCED_DESC_BOX])
EnableDisableShopkeeperButtons(guiCurrentItemDescriptionScreen, DEACTIVATE_BUTTON);
if( guiCurrentItemDescriptionScreen == MAP_SCREEN )
BltVideoObjectFromIndex( guiSAVEBUFFER, guiMapItemDescBox, showBox, gsInvDescX, gsInvDescY, VO_BLT_SRCTRANSPARENCY, NULL );
@@ -4558,10 +4607,10 @@ void RenderItemDescriptionBox( )
// CHRISL: This block will display hatching for inactive LBE pockets
// Display LBENODE attached items
if(UsingNewInventorySystem() == true && Item[gpItemDescObject->usItem].usItemClass == IC_LBEGEAR)
{
RenderLBENODEItems( gpItemDescObject, gubItemDescStatusIndex );
}
// if(UsingNewInventorySystem() == true && Item[gpItemDescObject->usItem].usItemClass == IC_LBEGEAR)
// {
// RenderLBENODEItems( gpItemDescObject, gubItemDescStatusIndex );
// }
// HEADROCK HAM 4: First, display LBE Background
if(UsingNewInventorySystem() == true && Item[gpItemDescObject->usItem].usItemClass == IC_LBEGEAR && showLBE >= 0)
@@ -4575,7 +4624,7 @@ void RenderItemDescriptionBox( )
showLBEImage += 8;
// Draw LBE background image
BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoLBEBackground, showLBEImage, gItemDescLBEBackground[showLBE].sLeft, gItemDescLBEBackground[showLBE].sTop, VO_BLT_SRCTRANSPARENCY, NULL );
// BltVideoObjectFromIndex( guiSAVEBUFFER, guiItemInfoLBEBackground, showLBEImage, gItemDescLBEBackground[showLBE].sLeft, gItemDescLBEBackground[showLBE].sTop, VO_BLT_SRCTRANSPARENCY, NULL );
// Render LBE items
RenderLBENODEItems( gpItemDescObject, gubItemDescStatusIndex );
}
@@ -5342,7 +5391,7 @@ void RenderLBENODEItems( OBJECTTYPE *pObj, int subObject )
InitInvData(LBEInvPocketXY[1], FALSE, INV_BAR_DX, INV_BAR_DY, SM_INV_SLOT_WIDTH, SM_INV_SLOT_HEIGHT, usX + gLBEStats[1].sX, usY + gLBEStats[1].sY);
InitInvData(LBEInvPocketXY[2], FALSE, INV_BAR_DX, INV_BAR_DY, SM_INV_SLOT_WIDTH, SM_INV_SLOT_HEIGHT, usX + gLBEStats[2].sX, usY + gLBEStats[2].sY);
InitInvData(LBEInvPocketXY[3], FALSE, INV_BAR_DX, INV_BAR_DY, SM_INV_SLOT_WIDTH, SM_INV_SLOT_HEIGHT, usX + gLBEStats[3].sX, usY + gLBEStats[3].sY);
InitInvData(LBEInvPocketXY[4], FALSE, INV_BAR_DX, INV_BAR_DY, VEST_INV_SLOT_WIDTH, VEST_INV_SLOT_HEIGHT, usX + gLBEStats[4].sX, usY + gLBEStats[4].sY);
InitInvData(LBEInvPocketXY[4], 2 , INV_BAR_DX, INV_BAR_DY, VEST_INV_SLOT_WIDTH, VEST_INV_SLOT_HEIGHT, usX + gLBEStats[4].sX, usY + gLBEStats[4].sY);
InitInvData(LBEInvPocketXY[5], FALSE, INV_BAR_DX, INV_BAR_DY, SM_INV_SLOT_WIDTH, SM_INV_SLOT_HEIGHT, usX + gLBEStats[5].sX, usY + gLBEStats[5].sY);
InitInvData(LBEInvPocketXY[6], FALSE, INV_BAR_DX, INV_BAR_DY, SM_INV_SLOT_WIDTH, SM_INV_SLOT_HEIGHT, usX + gLBEStats[6].sX, usY + gLBEStats[6].sY);
InitInvData(LBEInvPocketXY[7], FALSE, INV_BAR_DX, INV_BAR_DY, SM_INV_SLOT_WIDTH, SM_INV_SLOT_HEIGHT, usX + gLBEStats[7].sX, usY + gLBEStats[7].sY);
@@ -5363,8 +5412,8 @@ void RenderLBENODEItems( OBJECTTYPE *pObj, int subObject )
InitInvData(LBEInvPocketXY[7], FALSE, INV_BAR_DX, INV_BAR_DY, SM_INV_SLOT_WIDTH, SM_INV_SLOT_HEIGHT, usX + gLBEStats[19].sX, usY + gLBEStats[19].sY);
InitInvData(LBEInvPocketXY[8], FALSE, INV_BAR_DX, INV_BAR_DY, SM_INV_SLOT_WIDTH, SM_INV_SLOT_HEIGHT, usX + gLBEStats[20].sX, usY + gLBEStats[20].sY);
InitInvData(LBEInvPocketXY[9], FALSE, INV_BAR_DX, INV_BAR_DY, SM_INV_SLOT_WIDTH, SM_INV_SLOT_HEIGHT, usX + gLBEStats[21].sX, usY + gLBEStats[21].sY);
InitInvData(LBEInvPocketXY[10], FALSE, INV_BAR_DX, INV_BAR_DY, VEST_INV_SLOT_WIDTH, VEST_INV_SLOT_HEIGHT, usX + gLBEStats[22].sX, usY + gLBEStats[22].sY);
InitInvData(LBEInvPocketXY[11], FALSE, INV_BAR_DX, INV_BAR_DY, VEST_INV_SLOT_WIDTH, VEST_INV_SLOT_HEIGHT, usX + gLBEStats[23].sX, usY + gLBEStats[23].sY);
InitInvData(LBEInvPocketXY[10], 2, INV_BAR_DX, INV_BAR_DY, VEST_INV_SLOT_WIDTH, VEST_INV_SLOT_HEIGHT, usX + gLBEStats[22].sX, usY + gLBEStats[22].sY);
InitInvData(LBEInvPocketXY[11], 2, INV_BAR_DX, INV_BAR_DY, VEST_INV_SLOT_WIDTH, VEST_INV_SLOT_HEIGHT, usX + gLBEStats[23].sX, usY + gLBEStats[23].sY);
break;
case COMBAT_PACK:
GetLBESlots(CPACKPOCKPOS, pocketKey);
@@ -5404,6 +5453,8 @@ void RenderLBENODEItems( OBJECTTYPE *pObj, int subObject )
{
sX = LBEInvPocketXY[cnt].sX;
sY = LBEInvPocketXY[cnt].sY;
if(sX != 0 && sY != 0)
BltVideoObjectFromIndex( guiSAVEBUFFER, guiAttachmentSlot, LBEInvPocketXY[cnt].fBigPocket, sX-7, sY-1, VO_BLT_SRCTRANSPARENCY, NULL );
lbePocket = LoadBearingEquipment[Item[pObj->usItem].ubClassIndex].lbePocketIndex[icPocket[pocketKey[cnt]]];
pObject = NULL;
if(wornItem == true)
@@ -5532,13 +5583,15 @@ void DeleteItemDescriptionBox( )
//Remove
DeleteVideoObjectFromIndex( guiItemDescBox );
if(UsingNewInventorySystem() == true && guiItemDescBoxBackground != 0)
if(UsingNewInventorySystem() == true && guiItemDescBoxBackground != 0 && !gfInKeyRingPopup)
DeleteVideoObjectFromIndex( guiItemDescBoxBackground );
if(UsingNewInventorySystem() == true && guiItemInfoLBEBackground != 0)
DeleteVideoObjectFromIndex( guiItemInfoLBEBackground );
DeleteVideoObjectFromIndex( guiMapItemDescBox );
DeleteVideoObjectFromIndex( guiAttachmentSlot );
RenderBackpackButtons(0); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(ACTIVATE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
if(guiCurrentItemDescriptionScreen == SHOPKEEPER_SCREEN && gGameSettings.fOptions[TOPTION_ENHANCED_DESC_BOX])
EnableDisableShopkeeperButtons(guiCurrentItemDescriptionScreen, ACTIVATE_BUTTON);
DeleteVideoObjectFromIndex( guiBullet );
DeleteEnhancedDescBox( guiCurrentItemDescriptionScreen );
// Delete item graphic
@@ -6827,7 +6880,7 @@ BOOLEAN InitItemStackPopup( SOLDIERTYPE *pSoldier, UINT8 ubPosition, INT16 sInvX
static CHAR16 pStr[ 512 ];
RenderBackpackButtons(1); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(DEACTIVATE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
if( guiCurrentScreen == MAP_SCREEN )
{
sItemWidth = MAP_INV_ITEM_ROW_WIDTH;
@@ -7150,7 +7203,7 @@ BOOLEAN InitKeyRingPopup( SOLDIERTYPE *pSoldier, INT16 sInvX, INT16 sInvY, INT16
INT16 sOffSetY = 0, sOffSetX = 0;
INT16 sKeyRingItemWidth = 0;
RenderBackpackButtons(1); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(DEACTIVATE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
if( guiCurrentScreen == MAP_SCREEN )
{
gsKeyRingPopupInvX = 0;
@@ -7602,6 +7655,7 @@ void ItemPopupRegionCallback( MOUSE_REGION * pRegion, INT32 iReason )
UINT32 uiItemPos;
UINT32 iItemCap;
INT32 ubID;
CHAR16 sString[ 128 ];
uiItemPos = MSYS_GetRegionUserData( pRegion, 0 );
iItemCap = MSYS_GetRegionUserData( pRegion, 1 );
@@ -7615,6 +7669,22 @@ void ItemPopupRegionCallback( MOUSE_REGION * pRegion, INT32 iReason )
if (iReason & MSYS_CALLBACK_REASON_LBUTTON_DWN)
{
if( ( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].sSectorX != sSelMapX ) ||
( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].sSectorY != sSelMapY ) ||
( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].bSectorZ != iCurrentMapSectorZ ) ||
( Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].flags.fBetweenSectors ) )
{
if ( gpItemPointer == NULL )
{
swprintf( sString, pMapInventoryErrorString[ 2 ], Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].name );
}
else
{
swprintf( sString, pMapInventoryErrorString[ 5 ], Menptr[ gCharactersList[ bSelectedInfoChar ].usSolID ].name );
}
DoMapMessageBox( MSG_BOX_BASIC_STYLE, sString, MAP_SCREEN, MSG_BOX_FLAG_OK, NULL );
return;
}
//If something in our hand, see if it's ammo and if we are trying to reload a gun
if ( gpItemPointer != NULL )
{
@@ -9384,7 +9454,7 @@ void GetHelpTextForItem( STR16 pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier
case IC_AMMO:
{
// The next is for ammunition which gets the measurement 'rnds'
swprintf( pStr, L"%s [%d rnds]\n%s %1.1f %s",
swprintf( pStr, New113Message[MSG113_AMMO_SPEC_STRING],
ItemNames[ usItem ], //Item long name
(*pObject)[subObject]->data.ubShotsLeft, //Shots left
gWeaponStatsDesc[ 12 ], //Weight String
+4 -1
View File
@@ -208,11 +208,12 @@ BOOLEAN HandleCompatibleAmmoUI( SOLDIERTYPE *pSoldier, INT8 bInvPos, BOOLEAN fOn
// - if == 1 will only dirty the name space and then set counter to 0
// Last parameter used mainly for when mouse is over item
void RenderBulletIcon(OBJECTTYPE *pObject, UINT32 ubStatusIndex = 0);
void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObject, INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, UINT8 fDirtyLevel, UINT8 *pubHighlightCounter, UINT8 ubStatusIndex, BOOLEAN fOutline, INT16 sOutlineColor, UINT8 iter = 0 );
// CHRISL: Add a new function that will be used to render a pocket silhouette
void INVRenderSilhouette( UINT32 uiBugger, INT16 PocketIndex, INT16 SilIndex, INT16 sX, INT16 sY, INT16 sWideth, INT16 sHeight);
// CHRISL: New function to handle display of inventory quantities based on item current in cursor
void RenderPocketItemCapacity( UINT32 uiWhichBuffer, UINT8 pCapacity, INT16 bPos, SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT16 sX, INT16 sY );
void RenderPocketItemCapacity( UINT32 uiWhichBuffer, INT8 pCapacity, INT16 bPos, SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT16 sX, INT16 sY );
// CHRISL: New function to display items stored in an LBENODE
void RenderLBENODEItems( OBJECTTYPE *pObj, int subObject );
// CHRISL: New function to setup GSMInvData based on game options
@@ -257,6 +258,8 @@ void DeleteKeyRingPopup( );
void ShutdownKeyRingInterface( void );
void ShutdownInventoryInterface( void );
BOOLEAN InKeyRingPopup( void );
void BeginKeyRingItemPointer( SOLDIERTYPE *pSoldier, UINT8 ubKeyRingPosition );
+89 -298
View File
@@ -511,8 +511,8 @@ INT8 gbZipperButPos[2][2] =
};
//Legion by Jazz
void BtnOknoCallback(GUI_BUTTON *btn,INT32 reason);
void BtnFenceCallback(GUI_BUTTON *btn,INT32 reason);
//void BtnOknoCallback(GUI_BUTTON *btn,INT32 reason);
//void BtnFenceCallback(GUI_BUTTON *btn,INT32 reason);
// Mouse button and region callbacks
//void BtnPositionCallback( GUI_BUTTON *btn, INT32 reason );
@@ -877,7 +877,7 @@ void UpdateSMPanel( )
giSMStealthButton = QuickCreateButton( giSMStealthImages, SM_STEALTHMODE_X, SM_STEALTHMODE_Y,
BUTTON_TOGGLE, MSYS_PRIORITY_HIGH - 1,
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnStealthModeCallback );
RenderBackpackButtons(0); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(ACTIVATE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
SetButtonFastHelpText( giSMStealthButton, TacticalStr[ TOGGLE_STEALTH_MODE_POPUPTEXT ] );
@@ -889,7 +889,7 @@ void UpdateSMPanel( )
{
DisableButton( giSMStealthButton );
}
RenderBackpackButtons(3); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(DISABLE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
}
}
@@ -953,49 +953,10 @@ void UpdateSMPanel( )
}
}
DisableButton( iSMPanelButtons[ CLIMB_BUTTON ] );
//DisableButton
//if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
//{
//DisableButton( iSMPanelButtons[ HOP_BUTTON ] ); //Legion by Jazz
//}
GetMercClimbDirection( gpSMCurrentMerc->ubID, &fNearLowerLevel, &fNearHeigherLevel );
//--------------------- Legion-----------------
/*
if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
{
if ( gpSMCurrentMerc->pathing.bLevel == 0 )
{
GetMercOknoDirection( gpSMCurrentMerc->ubID, &fNearLowerLevelOkno, &fNearHeigherLevelOkno ); //Legion by JAzz
if ( fNearLowerLevelOkno || fNearHeigherLevelOkno )
{
if ( fNearLowerLevelOkno )
{
if ( EnoughPoints( gpSMCurrentMerc, GetAPsToJumpThroughWindows( gpSMCurrentMerc, TRUE ), 0, FALSE ) )
{
EnableButton( iSMPanelButtons[ HOP_BUTTON ] );
}
}
if ( fNearHeigherLevelOkno )
{
if ( EnoughPoints( gpSMCurrentMerc, GetAPsToJumpThroughWindows( gpSMCurrentMerc, FALSE ), 0, FALSE ) )
{
EnableButton( iSMPanelButtons[ HOP_BUTTON ] );
}
}
}
}
}
*/
//---------
if ( fNearLowerLevel || fNearHeigherLevel )
{
if ( fNearLowerLevel )
@@ -1014,31 +975,24 @@ if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
}
}
}
//----------------------------Legion by Jazz------------------------------
//DisableButton
/*
if (gGameExternalOptions.fCanJumpThroughWindows == TRUE )
{
if ( FindOknoDirection( gpSMCurrentMerc, gpSMCurrentMerc->sGridNo, gpSMCurrentMerc->ubDirection, &bDirection ) && gpSMCurrentMerc->pathing.bLevel == 0 )
{
EnableButton( iSMPanelButtons[ HOP_BUTTON ] );
}
}
*/
if (gGameExternalOptions.fCanClimbOnWalls == TRUE)
{
if ( FindFenceDirection( gpSMCurrentMerc, gpSMCurrentMerc->sGridNo, gpSMCurrentMerc->ubDirection, &bDirection ) )
{
EnableButton( iSMPanelButtons[ CLIMB_BUTTON ] );
}
}
//------------------------------------------
if (gGameExternalOptions.fCanClimbOnWalls == TRUE)
{
if ( FindWallJumpDirection( gpSMCurrentMerc, gpSMCurrentMerc->sGridNo, gpSMCurrentMerc->ubDirection, &bDirection ) )
{
if ( EnoughPoints( gpSMCurrentMerc, GetAPsToJumpWall( gpSMCurrentMerc, FALSE ), 0, FALSE ) )
{
EnableButton( iSMPanelButtons[ CLIMB_BUTTON ] );
}
}
}
if ( FindFenceJumpDirection( gpSMCurrentMerc, gpSMCurrentMerc->sGridNo, gpSMCurrentMerc->ubDirection, &bDirection ) )
{
EnableButton( iSMPanelButtons[ CLIMB_BUTTON ] );
if ( EnoughPoints( gpSMCurrentMerc, GetAPsToJumpFence( gpSMCurrentMerc, FALSE ), 0, FALSE ) )
{
EnableButton( iSMPanelButtons[ CLIMB_BUTTON ] );
}
}
if ( (gTacticalStatus.ubCurrentTeam != gbPlayerNum) || (gTacticalStatus.uiFlags & REALTIME ) || !(gTacticalStatus.uiFlags & INCOMBAT ) )
@@ -1114,11 +1068,6 @@ if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
// If not selected ( or dead ), disable/gray some buttons
if ( gusSelectedSoldier != gpSMCurrentMerc->ubID || ( gpSMCurrentMerc->stats.bLife < OKLIFE ) || (gTacticalStatus.ubCurrentTeam != gbPlayerNum) || gfSMDisableForItems )
{
//DisableButton
//if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
//{
//DisableButton( iSMPanelButtons[ HOP_BUTTON ] ); //Legion by Jazz
//}
DisableButton( iSMPanelButtons[ CLIMB_BUTTON ] );
DisableButton( iSMPanelButtons[ BURSTMODE_BUTTON ] );
DisableButton( iSMPanelButtons[ STANCEUP_BUTTON ] );
@@ -1130,7 +1079,7 @@ if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
{
DisableButton( giSMStealthButton );
}
RenderBackpackButtons(3); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(DISABLE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
}
else
{
@@ -1154,7 +1103,7 @@ if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
EnableButton( giSMStealthButton );
}
if(!gfInItemDescBox)
RenderBackpackButtons(2); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(ENABLE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
}
// CJC Dec 4 2002: or if item pickup menu is up
@@ -1225,6 +1174,9 @@ void RenderBackpackButtons(int bpAction)
// Only run if the Tactical Inventory Panel is open
if(gsCurInterfacePanel != SM_PANEL)
return;
// Don't run if keyring is open
if(gfInKeyRingPopup)
return;
// If Merc hasn't been set, default to first merc
if(gpSMCurrentMerc==NULL)
gpSMCurrentMerc = MercPtrs[ 0 ];
@@ -1232,7 +1184,7 @@ void RenderBackpackButtons(int bpAction)
// Deal with buttons depending on which screen is currently active
switch (bpAction)
{
case 0:
case ACTIVATE_BUTTON:
// Activate buttons
if(giSMZipperButton != -1)
RemoveButton( giSMZipperButton );
@@ -1267,38 +1219,38 @@ void RenderBackpackButtons(int bpAction)
//SetButtonFastHelpText( giSMZipperButton, TacticalStr[ ] );
//SetButtonFastHelpText( giSMDropPackButton, TacticalStr[ ] );
break;
case 1:
case DEACTIVATE_BUTTON:
// Deactivate buttons
if(giSMZipperButton != -1)
RemoveButton( giSMZipperButton );
if(giSMDropPackButton != -1)
RemoveButton( giSMDropPackButton );
RenderBackpackButtons(4);
RenderBackpackButtons(UNLOAD_BUTTON);
giSMDropPackImages = -1;
giSMDropPackButton = -1;
giSMZipperImages = -1;
giSMZipperButton = -1;
break;
case 2:
case ENABLE_BUTTON:
// Enable buttons
if(giSMDropPackButton == -1 || giSMZipperButton == -1)
{
RenderBackpackButtons(1);
RenderBackpackButtons(0);
RenderBackpackButtons(DEACTIVATE_BUTTON);
RenderBackpackButtons(ACTIVATE_BUTTON);
}
if(giSMDropPackButton != -1)
EnableButton( giSMDropPackButton );
if(giSMZipperButton != -1)
EnableButton( giSMZipperButton );
break;
case 3:
case DISABLE_BUTTON:
// Disable buttons
if(giSMDropPackButton != -1)
DisableButton( giSMDropPackButton );
if(giSMZipperButton != -1)
DisableButton( giSMZipperButton );
break;
case 4:
case UNLOAD_BUTTON:
if(giSMZipperImages != -1)
UnloadButtonImage( giSMZipperImages );
if(giSMDropPackImages != -1)
@@ -1368,11 +1320,6 @@ void EnableSMPanelButtons( BOOLEAN fEnable , BOOLEAN fFromItemPickup )
// only enable the following if NOT in shopkeeper's interface
if ( !(guiTacticalInterfaceFlags & INTERFACE_SHOPKEEP_INTERFACE ) )
{
//DisableButton
//if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
//{
//EnableButton( iSMPanelButtons[ HOP_BUTTON ] ); //Legion by JAzz
//}
EnableButton( iSMPanelButtons[ CLIMB_BUTTON ] );
EnableButton( iSMPanelButtons[ BURSTMODE_BUTTON ] );
EnableButton( iSMPanelButtons[ STANCEUP_BUTTON ] );
@@ -1384,7 +1331,7 @@ void EnableSMPanelButtons( BOOLEAN fEnable , BOOLEAN fFromItemPickup )
{
EnableButton( giSMStealthButton );
}
RenderBackpackButtons(2); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(ENABLE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
if ( gfDisableTacticalPanelButtons )
{
@@ -1416,11 +1363,6 @@ void EnableSMPanelButtons( BOOLEAN fEnable , BOOLEAN fFromItemPickup )
}
else
{
//DisableButton
//if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
//{
//DisableButton( iSMPanelButtons[ HOP_BUTTON ] ); //Legion by Jazz
//}
DisableButton( iSMPanelButtons[ CLIMB_BUTTON ] );
DisableButton( iSMPanelButtons[ BURSTMODE_BUTTON ] );
DisableButton( iSMPanelButtons[ STANCEUP_BUTTON ] );
@@ -1432,7 +1374,7 @@ void EnableSMPanelButtons( BOOLEAN fEnable , BOOLEAN fFromItemPickup )
{
DisableButton( giSMStealthButton );
}
RenderBackpackButtons(3); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(DISABLE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
if ( !fFromItemPickup )
{
@@ -1662,7 +1604,7 @@ BOOLEAN InitializeSMPanelCoordsOld()
LOCATION_NAME_Y = ( 65 + INTERFACE_START_Y );
// Keyring
KEYRING_X = 487;
KEYRING_X = 494; //487;
KEYRING_Y = (105 + INV_INTERFACE_START_Y);
// so we got everything "dynamic" now we just return TRUE
@@ -1952,9 +1894,9 @@ BOOLEAN InitializeSMPanelCoordsNew()
}
// WANNE 2
SM_DONE_X = (SCREEN_WIDTH - 152);
SM_DONE_X = (SCREEN_WIDTH - 146); // 152
SM_DONE_Y = ( 118 + INV_INTERFACE_START_Y );
SM_MAPSCREEN_X = (SCREEN_WIDTH - 152);
SM_MAPSCREEN_X = (SCREEN_WIDTH - 146); // 152
SM_MAPSCREEN_Y = ( 140 + INV_INTERFACE_START_Y );
SM_POSITIONB_X = ( 106 + INTERFACE_START_X );
@@ -2030,13 +1972,13 @@ BOOLEAN InitializeSMPanelCoordsNew()
// ow and te clock and location i will put it here
INTERFACE_CLOCK_X = (SCREEN_WIDTH - 86);
INTERFACE_CLOCK_Y = ( 116 + INV_INTERFACE_START_Y );
INTERFACE_CLOCK_Y = ( 117 + INV_INTERFACE_START_Y );
LOCATION_NAME_X = (SCREEN_WIDTH - 92);
LOCATION_NAME_Y = ( 87 + INTERFACE_START_Y );
LOCATION_NAME_Y = ( 89 + INTERFACE_START_Y );
//Keyring
KEYRING_X = 209;
KEYRING_Y = (4 + INV_INTERFACE_START_Y);
KEYRING_X = 217; // 209
KEYRING_Y = (5 + INV_INTERFACE_START_Y);
// so we got everything "dynamic" now we just return TRUE
return ( TRUE );
@@ -2196,12 +2138,6 @@ BOOLEAN CreateSMPanelButtons( )
FilenameForBPP("INTERFACE\\inventory_buttons.sti", ubString);
//Legion by Jazz
//DisableButton
//if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
//{
// FilenameForBPP("INTERFACE\\inventory_buttons_WINDOW_2.sti", ubString2); //LEGION
//}
//-----------------------
// Load button Graphics
iSMPanelImages[ STANCEUP_IMAGES ] = LoadButtonImage(ubString,-1,0,-1,10,-1 );
@@ -2217,18 +2153,6 @@ BOOLEAN CreateSMPanelButtons( )
iSMPanelImages[ TALK_IMAGES ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ] ,-1,6,-1,16,-1 );
iSMPanelImages[ MUTE_IMAGES ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ] ,-1,5,-1,15,-1 );
//Legion by Jazz
//DisableButton
/*
if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
{
iSMPanelImages[ OPTIONS_IMAGES ] = LoadButtonImage(ubString2,-1,0,-1,1,-1 ); //legion
}
else
{
iSMPanelImages[ OPTIONS_IMAGES ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ] ,-1,24,-1,25,-1 );
}
*/
iSMPanelImages[ OPTIONS_IMAGES ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ] ,-1,24,-1,25,-1 );
iBurstButtonImages[ WM_NORMAL ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 7, -1, -1, -1 );
@@ -2238,13 +2162,6 @@ BOOLEAN CreateSMPanelButtons( )
iBurstButtonImages[ WM_ATTACHED_GL_BURST ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 17, -1, -1, -1 );
iBurstButtonImages[ WM_ATTACHED_GL_AUTO ] = UseLoadedButtonImage( iSMPanelImages[ STANCEUP_IMAGES ], -1, 17, -1, -1, -1 );
//Legion by JAzz
//DisableButton
//if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
//{
// iSMPanelImages[ HOP_IMAGES ] = LoadButtonImage(ubString2,-1,2,-1,3,-1 );
//}
FilenameForBPP("INTERFACE\\invadd-ons.sti", ubString);
// Load button Graphics
iSMPanelImages[ STANCE_IMAGES ] = LoadButtonImage(ubString,0,0,-1,2,-1 );
@@ -2263,30 +2180,7 @@ BOOLEAN CreateSMPanelButtons( )
// SET BUTTONS TO -1
memset( iSMPanelButtons, -1, sizeof( iSMPanelButtons ) );
//Legion by Jazz
//DisableButton
/*if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
{
if (UsingNewInventorySystem() == true)
{
iSMPanelButtons[ HOP_BUTTON ] = QuickCreateButton( iSMPanelImages[ HOP_IMAGES ], SM_BURSTMODEB_X-30, SM_BURSTMODEB_Y,
BUTTON_TOGGLE, MSYS_PRIORITY_HIGH - 1,
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnOknoCallback );
}
else
{
iSMPanelButtons[ HOP_BUTTON ] = QuickCreateButton( iSMPanelImages[ HOP_IMAGES ], SM_BURSTMODEB_X-98, SM_BURSTMODEB_Y+35,
BUTTON_TOGGLE, MSYS_PRIORITY_HIGH - 1,
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnOknoCallback );
}
}
*/
//-----------------------
iSMPanelButtons[ SM_MAP_SCREEN_BUTTON ] = QuickCreateButton( iSMPanelImages[ MAPSCREEN_IMAGES ], SM_MAPSCREEN_X, SM_MAPSCREEN_Y,
BUTTON_TOGGLE, MSYS_PRIORITY_HIGH - 1,
DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)BtnMapScreenCallback );
@@ -2477,13 +2371,13 @@ void RemoveSMPanelButtons( )
RemoveButton( giSMStealthButton );
}
RenderBackpackButtons(1); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(DEACTIVATE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
if ( giSMStealthImages != -1 )
{
UnloadButtonImage( giSMStealthImages );
}
RenderBackpackButtons(4); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(UNLOAD_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
UnloadButtonImage( iBurstButtonImages[ WM_NORMAL ] );
UnloadButtonImage( iBurstButtonImages[ WM_BURST ] );
@@ -2525,6 +2419,8 @@ BOOLEAN ShutdownSMPanel( )
// shutdown keyring interface
ShutdownKeyRingInterface( );
ShutdownInventoryInterface();
MSYS_RemoveRegion( &gSMPanelRegion );
MSYS_RemoveRegion( &gSM_SELMERCPanelRegion );
MSYS_RemoveRegion( &gSM_SELMERCBarsRegion );
@@ -3079,6 +2975,10 @@ void RenderSMPanel( BOOLEAN *pfDirty )
RenderClock( INTERFACE_CLOCK_X, INTERFACE_CLOCK_Y );
CreateMouseRegionForPauseOfClock( INTERFACE_CLOCK_X, INTERFACE_CLOCK_Y );
}
else
{
RemoveMouseRegionForPauseOfClock();
}
// CHRISL: Change function call to include X,Y coordinates.
RenderTownIDString( LOCATION_NAME_X, LOCATION_NAME_Y );
@@ -3268,78 +3168,57 @@ void SMInvClickCamoCallback( MOUSE_REGION * pRegion, INT32 iReason )
{
if (gGameExternalOptions.fShowCamouflageFaces == TRUE )
{
if ( gpSMCurrentMerc->bCamo > 0 )
{
gCamoFace[gpSMCurrentMerc->ubProfile].gCamoface = TRUE;
SetCamoFace( gpSMCurrentMerc );
DeleteSoldierFace( gpSMCurrentMerc );// remove face
gpSMCurrentMerc->iFaceIndex = InitSoldierFace( gpSMCurrentMerc );// create new face
}
if ( gpSMCurrentMerc->urbanCamo > 0 )
{
gCamoFace[gpSMCurrentMerc->ubProfile].gUrbanCamoface = TRUE;
DeleteSoldierFace( gpSMCurrentMerc );// remove face
gpSMCurrentMerc->iFaceIndex = InitSoldierFace( gpSMCurrentMerc );// create new face
}
if ( gpSMCurrentMerc->desertCamo > 0)
{
gCamoFace[gpSMCurrentMerc->ubProfile].gDesertCamoface = TRUE;
DeleteSoldierFace( gpSMCurrentMerc );// remove face
gpSMCurrentMerc->iFaceIndex = InitSoldierFace( gpSMCurrentMerc );// create new face
}
if ( gpSMCurrentMerc->snowCamo > 0)
{
gCamoFace[gpSMCurrentMerc->ubProfile].gSnowCamoface = TRUE;
DeleteSoldierFace( gpSMCurrentMerc );// remove face
gpSMCurrentMerc->iFaceIndex = InitSoldierFace( gpSMCurrentMerc );// create new face
}
}
// Dirty
fInterfacePanelDirty = DIRTYLEVEL2;
// Dirty
fInterfacePanelDirty = DIRTYLEVEL2;
// Check if it's the same now!
if ( gpItemPointer->exists() == false )
{
gbCompatibleApplyItem = FALSE;
EndItemPointer( );
// Check if it's the same now!
if ( gpItemPointer->exists() == false )
{
gbCompatibleApplyItem = FALSE;
EndItemPointer( );
}
// Say OK acknowledge....
gpSMCurrentMerc->DoMercBattleSound( BATTLE_SOUND_COOL1 );
}
// Say OK acknowledge....
gpSMCurrentMerc->DoMercBattleSound( BATTLE_SOUND_COOL1 );
}
}
else if ( ApplyCanteen( gpSMCurrentMerc, gpItemPointer, &fGoodAPs ) )
{
// Dirty
if ( fGoodAPs )
{
fInterfacePanelDirty = DIRTYLEVEL2;
// Check if it's the same now!
if ( gpItemPointer->exists() == false )
if ( fGoodAPs )
{
gbCompatibleApplyItem = FALSE;
EndItemPointer( );
fInterfacePanelDirty = DIRTYLEVEL2;
// Check if it's the same now!
if ( gpItemPointer->exists() == false )
{
gbCompatibleApplyItem = FALSE;
EndItemPointer( );
}
}
}
}
else if ( ApplyElixir( gpSMCurrentMerc, gpItemPointer, &fGoodAPs ) )
{
if ( fGoodAPs )
{
// Dirty
fInterfacePanelDirty = DIRTYLEVEL2;
// Check if it's the same now!
if ( gpItemPointer->exists() == false )
if ( fGoodAPs )
{
gbCompatibleApplyItem = FALSE;
EndItemPointer( );
}
// Dirty
fInterfacePanelDirty = DIRTYLEVEL2;
// Say OK acknowledge....
gpSMCurrentMerc->DoMercBattleSound( BATTLE_SOUND_COOL1 );
}
// Check if it's the same now!
if ( gpItemPointer->exists() == false )
{
gbCompatibleApplyItem = FALSE;
EndItemPointer( );
}
// Say OK acknowledge....
gpSMCurrentMerc->DoMercBattleSound( BATTLE_SOUND_COOL1 );
}
}
else if ( ApplyDrugs( gpSMCurrentMerc, gpItemPointer ) )
{
@@ -3586,7 +3465,7 @@ void SMInvClickCallback( MOUSE_REGION * pRegion, INT32 iReason )
break;
}
}
RenderBackpackButtons(0); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(ACTIVATE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
}
}
@@ -3724,7 +3603,7 @@ void SMInvClickCallback( MOUSE_REGION * pRegion, INT32 iReason )
return;
if(gpSMCurrentMerc->flags.DropPackFlag)
gpSMCurrentMerc->flags.DropPackFlag = FALSE;
RenderBackpackButtons(0); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(ACTIVATE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
}
}
@@ -3740,7 +3619,7 @@ void SMInvClickCallback( MOUSE_REGION * pRegion, INT32 iReason )
// try to place the item in the cursor into this inventory slot
if ( UIHandleItemPlacement( (UINT8) uiHandPos, usOldItemIndex, usNewItemIndex, fDeductPoints ) )
{
RenderBackpackButtons(0); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(ACTIVATE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
// it worked! if we're in the SKI...
if( guiTacticalInterfaceFlags & INTERFACE_SHOPKEEP_INTERFACE )
{
@@ -4445,9 +4324,9 @@ void BtnClimbCallback(GUI_BUTTON *btn,INT32 reason)
if (gGameExternalOptions.fCanClimbOnWalls == TRUE)
{
if ( FindFenceDirection( gpSMCurrentMerc, gpSMCurrentMerc->sGridNo, gpSMCurrentMerc->ubDirection, &bDirection ) )
if ( FindWallJumpDirection( gpSMCurrentMerc, gpSMCurrentMerc->sGridNo, gpSMCurrentMerc->ubDirection, &bDirection ) )
{
gpSMCurrentMerc->BeginSoldierFence( );
gpSMCurrentMerc->BeginSoldierClimbWall( );
}
}
@@ -4457,7 +4336,6 @@ void BtnClimbCallback(GUI_BUTTON *btn,INT32 reason)
{
gpSMCurrentMerc->BeginSoldierClimbFence( );
}
}
else if(reason & MSYS_CALLBACK_REASON_LOST_MOUSE )
{
@@ -7192,11 +7070,6 @@ void KeyRingSlotInvClickCallback( MOUSE_REGION * pRegion, INT32 iReason )
void DisableSMPpanelButtonsWhenInShopKeeperInterface( BOOLEAN fDontDrawButtons )
{
//Go through the buttons that will be under the ShopKeepers ATM panel and disable them
//DisableButton
//if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
//{
//DisableButton( iSMPanelButtons[ HOP_BUTTON ] ); //Legion by Jazz
//}
DisableButton( iSMPanelButtons[ STANCEUP_BUTTON ] );
DisableButton( iSMPanelButtons[ UPDOWN_BUTTON ] );
DisableButton( iSMPanelButtons[ CLIMB_BUTTON ] );
@@ -7216,10 +7089,6 @@ void DisableSMPpanelButtonsWhenInShopKeeperInterface( BOOLEAN fDontDrawButtons )
DisableButton( iSMPanelButtons[ SM_MAP_SCREEN_BUTTON ] );
//DisableButton
//if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
//{
//DisableButton( iSMPanelButtons[ HOP_BUTTON ] ); //legion by Jazz
//}
DisableButton( iSMPanelButtons[ STANCEUP_BUTTON ] );
DisableButton( iSMPanelButtons[ UPDOWN_BUTTON ] );
DisableButton( iSMPanelButtons[ CLIMB_BUTTON ] );
@@ -7231,20 +7100,15 @@ void DisableSMPpanelButtonsWhenInShopKeeperInterface( BOOLEAN fDontDrawButtons )
DisableButton( iSMPanelButtons[ MUTE_BUTTON ] );
DisableButton( giSMStealthButton );
RenderBackpackButtons(3); /* CHRISL: Needed for new inventory backpack buttons */
RenderBackpackButtons(DISABLE_BUTTON); /* CHRISL: Needed for new inventory backpack buttons */
if( fDontDrawButtons )
{
//ATM:
//Go through the buttons that will be under the ShopKeepers ATM panel and disable them
//DisableButton
//if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
//{
//ButtonList[ iSMPanelButtons[ HOP_BUTTON ] ]->uiFlags &= ~BUTTON_DIRTY; //Legion by Jazz
//}
ButtonList[ iSMPanelButtons[ STANCEUP_BUTTON ] ]->uiFlags &= ~BUTTON_DIRTY;
ButtonList[ iSMPanelButtons[ UPDOWN_BUTTON ] ]->uiFlags &= ~BUTTON_DIRTY;
ButtonList[ iSMPanelButtons[ CLIMB_BUTTON ] ]->uiFlags &= ~BUTTON_DIRTY;
@@ -7271,10 +7135,6 @@ void DisableSMPpanelButtonsWhenInShopKeeperInterface( BOOLEAN fDontDrawButtons )
ButtonList[ iSMPanelButtons[ SM_MAP_SCREEN_BUTTON ] ]->uiFlags &= ~BUTTON_ENABLED;
//DisableButton
//if (gGameExternalOptions.fCanJumpThroughWindows == TRUE)
//{
//ButtonList[ iSMPanelButtons[ HOP_BUTTON ] ]->uiFlags |= BUTTON_FORCE_UNDIRTY; //legion by Jazz
//}
ButtonList[ iSMPanelButtons[ STANCEUP_BUTTON ] ]->uiFlags |= BUTTON_FORCE_UNDIRTY;
ButtonList[ iSMPanelButtons[ UPDOWN_BUTTON ] ]->uiFlags |= BUTTON_FORCE_UNDIRTY;
ButtonList[ iSMPanelButtons[ CLIMB_BUTTON ] ]->uiFlags |= BUTTON_FORCE_UNDIRTY;
@@ -7457,75 +7317,6 @@ void GoToMapScreenFromTactical( void )
gfEnteringMapScreen = TRUE;
}
//-------------Legion by Jazz-----------------------------------
void BtnOknoCallback(GUI_BUTTON *btn,INT32 reason)
{
INT8 bDirection;
if (!(btn->uiFlags & BUTTON_ENABLED))
return;
if ( gpSMCurrentMerc->pathing.bLevel == 1 )
{
return;
}
if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
btn->uiFlags |= BUTTON_CLICKED_ON;
}
else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
btn->uiFlags &= (~BUTTON_CLICKED_ON );
if ( FindWindowJumpDirection( gpSMCurrentMerc, gpSMCurrentMerc->sGridNo, gpSMCurrentMerc->ubDirection, &bDirection ) )
{
gpSMCurrentMerc->BeginSoldierClimbWindow( );
}
}
else if(reason & MSYS_CALLBACK_REASON_LOST_MOUSE )
{
btn->uiFlags &= (~BUTTON_CLICKED_ON );
}
}
void BtnFenceCallback(GUI_BUTTON *btn,INT32 reason)
{
BOOLEAN fNearHeigherLevelFence;
BOOLEAN fNearLowerLevelFence;
INT8 bDirection;
if (!(btn->uiFlags & BUTTON_ENABLED))
return;
if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
btn->uiFlags |= BUTTON_CLICKED_ON;
}
else if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
{
btn->uiFlags &= (~BUTTON_CLICKED_ON );
GetMercFenceDirection( gpSMCurrentMerc->ubID, &fNearLowerLevelFence, &fNearHeigherLevelFence );
if ( FindFenceDirection( gpSMCurrentMerc, gpSMCurrentMerc->sGridNo, gpSMCurrentMerc->ubDirection, &bDirection ) )
{
gpSMCurrentMerc->BeginSoldierFence( );
}
}
else if(reason & MSYS_CALLBACK_REASON_LOST_MOUSE )
{
btn->uiFlags &= (~BUTTON_CLICKED_ON );
}
}
//----LEGION 2---------
BOOLEAN HandleKlerykPistolet( SOLDIERTYPE *pSoldier, UINT32 uiHandPos, UINT16 usReplaceItem )
{
+209 -88
View File
@@ -115,8 +115,12 @@ UINT8 gubProgCurEnemy = 0;
UINT32 guiPORTRAITICONS;
UINT32 guiPORTRAITICONS_NV; //legion
UINT32 guiPORTRAITICONS_GAS_MASK; //legion
//UINT32 guiPORTRAITICONS_NV; //legion
//UINT32 guiPORTRAITICONS_GAS_MASK; //legion
// WANNE: Additional face gear file for IMPs
//UINT32 guiPORTRAITICONS_NV_IMP;
//UINT32 guiPORTRAITICONS_GAS_MASK_IMP;
typedef struct
{
@@ -275,6 +279,10 @@ BOOLEAN InitializeTacticalInterface( )
{
VSURFACE_DESC vs_desc;
VOBJECT_DESC VObjectDesc;
UINT32 iCounter2;
char fileName[500];
// CHRISL: Setup default interface coords based on inventory system in use
if((UsingNewInventorySystem() == true))
@@ -414,7 +422,7 @@ BOOLEAN InitializeTacticalInterface( )
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
//legion 2 jazz
if (gGameExternalOptions.fShowTacticalFaceIcons == TRUE)
if (gGameSettings.fOptions[ TOPTION_SHOW_TACTICAL_FACE_ICONS ] == TRUE)
{
//additional face icons (legion 2)
if (gGameExternalOptions.bTacticalFaceIconStyle == 0)
@@ -457,15 +465,56 @@ BOOLEAN InitializeTacticalInterface( )
//legion
if (gGameExternalOptions.fShowTacticalFaceGear == TRUE)
if (gGameSettings.fOptions[ TOPTION_SHOW_TACTICAL_FACE_GEAR ] == TRUE)
{
FilenameForBPP("INTERFACE\\portraiticons_NV.sti", VObjectDesc.ImageFile);
/*
FilenameForBPP("INTERFACE\\portraiticons_NV.sti", VObjectDesc.ImageFile);
if( !AddVideoObject( &VObjectDesc, &guiPORTRAITICONS_NV ) )
AssertMsg(0, "Missing INTERFACE\\portraiticons_NV.sti" );
FilenameForBPP("INTERFACE\\portraiticons_GAS_MASK.sti", VObjectDesc.ImageFile);
FilenameForBPP("INTERFACE\\portraiticons_NV_IMP.sti", VObjectDesc.ImageFile);
if( !AddVideoObject( &VObjectDesc, &guiPORTRAITICONS_NV_IMP ) )
AssertMsg(0, "Missing INTERFACE\\portraiticons_NV_IMP.sti" );
FilenameForBPP("INTERFACE\\portraiticons_GAS_MASK.sti", VObjectDesc.ImageFile);
if( !AddVideoObject( &VObjectDesc, &guiPORTRAITICONS_GAS_MASK ) )
AssertMsg(0, "Missing INTERFACE\\portraiticons_GAS_MASK.sti" );
AssertMsg(0, "Missing INTERFACE\\portraiticons_GAS_MASK.sti" );
FilenameForBPP("INTERFACE\\portraiticons_GAS_MASK_IMP.sti", VObjectDesc.ImageFile);
if( !AddVideoObject( &VObjectDesc, &guiPORTRAITICONS_GAS_MASK_IMP ) )
AssertMsg(0, "Missing INTERFACE\\portraiticons_GAS_MASK_IMP.sti" );
*/
for( iCounter2 = 1; iCounter2 < MAXITEMS; iCounter2++ )
{
VObjectDesc.fCreateFlags = VSURFACE_CREATE_FROMFILE;
#define SCSTI ".STI"
if ( zNewFaceGear[iCounter2].Type > 0 )
{
strcpy(fileName, zNewFaceGear[iCounter2].szFile);
strcat(fileName, SCSTI);
strcpy(VObjectDesc.ImageFile, fileName);
CHECKF(AddVideoObject(&VObjectDesc,&zNewFaceGear[iCounter2].uiIndex));
}
}
for( iCounter2 = 1; iCounter2 < MAXITEMS; iCounter2++ )
{
VObjectDesc.fCreateFlags = VSURFACE_CREATE_FROMFILE;
#define SCSTI_IMP "_IMP.STI"
if ( zNewFaceGear[iCounter2].Type > 0 )
{
//IMP
strcpy(fileName, zNewFaceGear[iCounter2].szFile);
strcat(fileName, SCSTI_IMP);
strcpy(VObjectDesc.ImageFile, fileName);
CHECKF(AddVideoObject(&VObjectDesc,&zNewFaceGearIMP[iCounter2].uiIndex));
}
}
}
// LOAD RADIO
@@ -2202,17 +2251,10 @@ BOOLEAN DrawCTHIndicator()
// Select the color of the indicator circles
UINT16 usCApertureBar;
if (pSoldier->bDoAutofire && fAutofireBulletsMode)
{
// When autofire bullets mode is selected, the CTH display goes greyish. This indicates to the player
// that the aiming levels have been set, and further right-clicks will only add bullets to the volley.
usCApertureBar = Get16BPPColor( FROMRGB( 180, 180, 180 ) );
}
else
{
// Indicator changes color from red to yellow to green, based on how well the gun is aimed.
usCApertureBar = Get16BPPColor( FROMRGB( ColorsRed[gCTHDisplay.MuzzleSwayPercentage/10], ColorsGreen[gCTHDisplay.MuzzleSwayPercentage/10], 0 ) ); // Crosshair color shifts from red (longshot) to green (Accurate shot)
}
// CHRISL: Instead of shigting the color based on MuzzleSwayPercent, let's move this line and base it on the final iAperture value
// Indicator changes color from red to yellow to green, based on how well the gun is aimed.
//usCApertureBar = Get16BPPColor( FROMRGB( ColorsRed[gCTHDisplay.MuzzleSwayPercentage/10], ColorsGreen[gCTHDisplay.MuzzleSwayPercentage/10], 0 ) ); // Crosshair color shifts from red (longshot) to green (Accurate shot)
UINT16 usCApertureBorder = Get16BPPColor( FROMRGB( 10, 10, 10 ) ); // Boundaries in dark color.
@@ -2268,7 +2310,12 @@ BOOLEAN DrawCTHIndicator()
iAperture = ((100 - actualPct) * iAperture) / 100;
/////////////////////////////////////////////
// Factor in Gun Accuracy. Note that I may remove this at a later time.
// Factor in Weapon "Effective Range".
UINT16 sEffRange = Weapon[Item[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubClassIndex].usRange + GetRangeBonus(&(pSoldier->inv[ pSoldier->ubAttackingHand ]));
FLOAT iRangeRatio = __max(1.0f, (FLOAT)(d2DDistance / sEffRange));
/////////////////////////////////////////////
// Factor in Gun Accuracy.
INT16 sAccuracy = GetGunAccuracy( &(pSoldier->inv[ pSoldier->ubAttackingHand ]) );
@@ -2276,6 +2323,8 @@ BOOLEAN DrawCTHIndicator()
sAccuracy = __min(100, sAccuracy);
FLOAT iBulletDev = (gGameCTHConstants.MAX_BULLET_DEV * (100-sAccuracy)) / 100;
if( gGameCTHConstants.RANGE_EFFECTS_DEV == TRUE )
iBulletDev *= iRangeRatio;
iBulletDev *= iDistanceRatio;
// Since bullet dev is only affected by distance, we add it last as a flat modifier.
@@ -2283,6 +2332,28 @@ BOOLEAN DrawCTHIndicator()
iMaxAperture += iBulletDev;
iAperture += iBulletDev;
// CHRISL: Moved here so we can base the cursor color on the iAperture value
UINT8 iColorCode = 0;
if(iAperture < 3.0)
iColorCode = 9;
else if(iAperture < 6.0)
iColorCode = 8;
else if(iAperture < 9.0)
iColorCode = 7;
else if(iAperture < 12.0)
iColorCode = 6;
else if(iAperture < 16.0)
iColorCode = 5;
else if(iAperture < 20.0)
iColorCode = 4;
else if(iAperture < 25.0)
iColorCode = 3;
else if(iAperture < 30.0)
iColorCode = 2;
else if(iAperture < 40.0)
iColorCode = 1;
usCApertureBar = Get16BPPColor( FROMRGB( ColorsRed[iColorCode], ColorsGreen[iColorCode], 0 ) ); // Crosshair color shifts from red (longshot) to green (Accurate shot)
///////////////////////////////////////////////////////////////////////////////////////////////////
// HEADROCK HAM 4: Calculate Screen Positions
//
@@ -2446,6 +2517,53 @@ BOOLEAN DrawCTHIndicator()
MagRect.right = sCenter + (usTotalWidth / 2);
}
#ifdef JA2BETAVERSION
/////////////// SHOT APERTURE SIZE
{
// Create a pointer to the Frame Buffer which we are going to draw directly into.
SetFont( TINYFONT1 );
SetFontBackground( FONT_MCOLOR_BLACK );
SetFontForeground( FONT_MCOLOR_WHITE );
// Find coordinates, using the full string ("XX AP")
swprintf( pStr, L"%3.2f", iAperture );
FindFontCenterCoordinates( (INT16)APRect.left, (INT16)APRect.top-5, (INT16)APRect.right-(INT16)APRect.left, 5, pStr, TINYFONT1, &curX, &curY);
// Find width of this string.
UINT16 usTotalWidth = StringPixLength ( pStr, TINYFONT1 );
// Draw to screen
gprintfdirty( curX, curY, pStr );
mprintf( curX, curY, pStr);
// Redefine area size based on total width plus a margin of 2 pixels.
usTotalWidth = usTotalWidth + 6;
INT16 sCenter = (INT16)((APRect.right + APRect.left) / 2);
APRect.left = sCenter - (usTotalWidth / 2);
APRect.right = sCenter + (usTotalWidth / 2);
}
/////////////// DISTANCE APERTURE SIZE
{
SetFont( TINYFONT1 );
// Find coordinates, using full string ("X.X x")
swprintf( pStr, L"%3.2f", iMaxAperture );
FindFontCenterCoordinates( (INT16)MagRect.left, (INT16)MagRect.top-5, (INT16)MagRect.right-(INT16)MagRect.left, 5, pStr, TINYFONT1, &curX, &curY);
// Find width of this string.
UINT16 usTotalWidth = StringPixLength ( pStr, TINYFONT1 );
// Draw to screen
gprintfdirty( curX, curY, pStr );
mprintf( curX, curY, pStr);
// Redefine area size based on total width plus a margin of 2 pixels.
usTotalWidth = usTotalWidth + 6;
INT16 sCenter = (INT16)((MagRect.right + MagRect.left) / 2);
MagRect.left = sCenter - (usTotalWidth / 2);
MagRect.right = sCenter + (usTotalWidth / 2);
}
#endif
//////////////////// BURST/AUTO LABEL AND BULLETS
if (pSoldier->bDoBurst)
{
@@ -2826,96 +2944,99 @@ BOOLEAN DrawCTHIndicator()
INT32 Circ = 0;
Circ = (INT32)((iMaxAperture * RADIANS_IN_CIRCLE) * dVerticalBias);
// Draw outer circle
for (INT32 iCurPoint = 0; iCurPoint < Circ; iCurPoint++)
if(gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
{
curX = (INT16)(iMaxAperture * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)((iMaxAperture * dVerticalBias) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
INT16 firstX = curX;
INT16 firstY = curY;
// Draw outer circle
for (INT32 iCurPoint = 0; iCurPoint < Circ; iCurPoint++)
{
curX = (INT16)(iMaxAperture * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)((iMaxAperture * dVerticalBias) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
INT16 firstX = curX;
INT16 firstY = curY;
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBar );
// Draw a border circle which is 1 point wider
curX = (INT16)((iMaxAperture+1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)(((iMaxAperture * dVerticalBias)+1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
// Draw a border circle which is 1 point wider
curX = (INT16)((iMaxAperture+1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)(((iMaxAperture * dVerticalBias)+1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
if (curX != firstX || curY != firstY)
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
if (curX != firstX || curY != firstY)
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
// Draw a border circle which is 1 point narrower
curX = (INT16)((iMaxAperture-1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)(((iMaxAperture * dVerticalBias)-1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
// Draw a border circle which is 1 point narrower
curX = (INT16)((iMaxAperture-1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)(((iMaxAperture * dVerticalBias)-1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
if (curX != firstX || curY != firstY)
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
}
if (curX != firstX || curY != firstY)
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
}
Circ = (INT32)((iAperture * RADIANS_IN_CIRCLE) * dVerticalBias);
// Draw inner circle
for (INT32 iCurPoint = 0; iCurPoint < Circ; iCurPoint++)
{
curX = (INT16)(iAperture * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)((iAperture * dVerticalBias) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
INT16 firstX = curX;
INT16 firstY = curY;
Circ = (INT32)((iAperture * RADIANS_IN_CIRCLE) * dVerticalBias);
// Draw inner circle
for (INT32 iCurPoint = 0; iCurPoint < Circ; iCurPoint++)
{
curX = (INT16)(iAperture * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)((iAperture * dVerticalBias) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
INT16 firstX = curX;
INT16 firstY = curY;
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBar );
// Draw a border circle which is 1 point wider
curX = (INT16)((iAperture+1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)(((iAperture * dVerticalBias)+1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
// Draw a border circle which is 1 point wider
curX = (INT16)((iAperture+1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)(((iAperture * dVerticalBias)+1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
if (curX != firstX || curY != firstY)
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
if (curX != firstX || curY != firstY)
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
// Draw a border circle which is 1 point narrower
curX = (INT16)((iAperture-1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)(((iAperture * dVerticalBias)-1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
// Draw a border circle which is 1 point narrower
curX = (INT16)((iAperture-1) * cos((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
curY = (INT16)(((iAperture * dVerticalBias)-1) * sin((iCurPoint * RADIANS_IN_CIRCLE)/Circ));
if (curX != firstX || curY != firstY)
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
}
if (curX != firstX || curY != firstY)
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+curX, sStartScreenY+curY+(INT16)zOffset, usCApertureBorder );
}
// Aperture Crosshairs
for (INT16 cnt = (INT16)(iAperture); cnt <= (INT16)(iAperture + uiApertureBarLength); cnt++)
{
// Horizontal Aperture Crosshairs
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, sStartScreenY+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, sStartScreenY+(INT16)zOffset, usCApertureBar );
// Aperture Crosshairs
for (INT16 cnt = (INT16)(iAperture); cnt <= (INT16)(iAperture + uiApertureBarLength); cnt++)
{
// Horizontal Aperture Crosshairs
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, sStartScreenY+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, sStartScreenY+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY+1)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY-1)+(INT16)zOffset, usCApertureBar );
// Darker borders
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY+2)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY+2)+(INT16)zOffset, usCApertureBorder );
// Darker borders
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY+2)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY+2)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY-2)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY-2)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+cnt, (sStartScreenY-2)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-cnt, (sStartScreenY-2)+(INT16)zOffset, usCApertureBorder );
}
for (INT16 cnt = (INT16)(iAperture * dVerticalBias); cnt <= (INT16)((iAperture * dVerticalBias) + uiApertureBarLength); cnt++)
{
// Vertical Aperture Crosshairs
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
}
for (INT16 cnt = (INT16)(iAperture * dVerticalBias); cnt <= (INT16)((iAperture * dVerticalBias) + uiApertureBarLength); cnt++)
{
// Vertical Aperture Crosshairs
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBar );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-1, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBar );
// Darker borders
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+2, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+2, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
// Darker borders
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+2, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX+2, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-2, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-2, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-2, (sStartScreenY+cnt)+(INT16)zOffset, usCApertureBorder );
DrawCTHPixelToBuffer( ptrBuf, uiPitch, sLeft, sTop, sRight, sBottom, sStartScreenX-2, (sStartScreenY-cnt)+(INT16)zOffset, usCApertureBorder );
}
}
// Unlock the Frame Buffer.
+12 -2
View File
@@ -32,6 +32,12 @@ enum
NUM_ICONS
};
#define ACTIVATE_BUTTON 0
#define DEACTIVATE_BUTTON 1
#define ENABLE_BUTTON 2
#define DISABLE_BUTTON 3
#define UNLOAD_BUTTON 4
#define MAX_ENEMY_NAMES_CHARS 128
typedef struct
@@ -164,8 +170,12 @@ extern UINT32 guiITEMPOINTERHATCHES;
//legion
extern UINT32 guiPORTRAITICONS_NV; //legion: NV-Face Graphic
extern UINT32 guiPORTRAITICONS_GAS_MASK; //legion: GASMASK-Face Graphic
//extern UINT32 guiPORTRAITICONS_NV; //legion: NV-Face Graphic
//extern UINT32 guiPORTRAITICONS_GAS_MASK; //legion: GASMASK-Face Graphic
// WANNE: Face gear for IMPs in additional file
//extern UINT32 guiPORTRAITICONS_NV_IMP;
//extern UINT32 guiPORTRAITICONS_GAS_MASK_IMP;
extern MOUSE_REGION gViewportRegion;
extern MOUSE_REGION gRadarRegion;
+5 -4
View File
@@ -20,7 +20,7 @@ int gLastLBEUniqueID = 0;
extern UINT32 guiCurrentItemDescriptionScreen;
extern BOOLEAN fShowMapInventoryPool;
extern BOOLEAN AutoPlaceObjectInInventoryStash( OBJECTTYPE *pItemPtr, INT32 sGridNo );
//extern BOOLEAN AutoPlaceObjectInInventoryStash( OBJECTTYPE *pItemPtr, INT32 sGridNo );
bool IsSlotAnLBESlot(int slot)
{
@@ -205,7 +205,7 @@ BOOLEAN MoveItemsToActivePockets( SOLDIERTYPE *pSoldier, std::vector<INT8>& LBES
//DBrot: changed to bitwise comparison
UINT32 newPack = LoadBearingEquipment[Item[pObj->usItem].ubClassIndex].lbeCombo;
UINT32 chkPack = LoadBearingEquipment[Item[pSoldier->inv[i].usItem].ubClassIndex].lbeCombo;
if(newPack == 0 || (newPack & chkPack == 0))
if(newPack == 0 || (newPack & chkPack) == 0)
continue;
}
if(CanItemFitInPosition(pSoldier, &(pSoldier->inv[LBESlots[x]]), i, FALSE))
@@ -227,7 +227,8 @@ BOOLEAN MoveItemsToActivePockets( SOLDIERTYPE *pSoldier, std::vector<INT8>& LBES
{
if(pSoldier->inv[LBESlots[i]].exists() == false) // No item in pocket
continue;
if(guiCurrentItemDescriptionScreen == MAP_SCREEN && fShowMapInventoryPool)
AutoPlaceObjectToWorld(pSoldier, &pSoldier->inv[LBESlots[i]]);
/*if(guiCurrentItemDescriptionScreen == MAP_SCREEN && fShowMapInventoryPool)
{
AutoPlaceObjectInInventoryStash(&pSoldier->inv[LBESlots[i]], pSoldier->sGridNo);
}
@@ -235,7 +236,7 @@ BOOLEAN MoveItemsToActivePockets( SOLDIERTYPE *pSoldier, std::vector<INT8>& LBES
{
AddItemToPool( pSoldier->sGridNo, &pSoldier->inv[LBESlots[i]], 1, pSoldier->pathing.bLevel, 0 , -1 );
NotifySoldiersToLookforItems( );
}
}*/
DeleteObj(&pSoldier->inv[LBESlots[i]]);
}
+377 -201
View File
File diff suppressed because it is too large Load Diff
+12 -5
View File
@@ -64,6 +64,7 @@ UINT16 RandomMagazine( UINT16 usItem, UINT8 ubPercentStandard, UINT8 maxCoolness
UINT16 RandomMagazine( OBJECTTYPE * pGun, UINT8 ubPercentStandard, UINT8 maxCoolness );
extern BOOLEAN ReloadGun( SOLDIERTYPE * pSoldier, OBJECTTYPE * pGun, OBJECTTYPE * pAmmo, UINT32 subObject = 0 );
bool IsBackpackSlot(INT8 bSlot);
// CHRISL: Add new inventory version of ItemSlotLimit function
UINT8 ItemSlotLimit( OBJECTTYPE * pObject, INT16 bSlot, SOLDIERTYPE *pSoldier = NULL, BOOLEAN cntAttach = TRUE);
@@ -85,6 +86,9 @@ BOOLEAN ArmBomb( OBJECTTYPE * pObj, INT8 bSetting );
// "in the cursor", which should have memory allocated for it already
BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj );
BOOLEAN AutoPlaceObjectAnywhere(SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN fNewItem, INT8 bExcludeSlot = NO_SLOT);
BOOLEAN AutoPlaceObjectToWorld(SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, INT8 bVisible = TRUE);
// Send fNewItem to true to set off new item glow in inv panel
BOOLEAN AutoPlaceObject( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN fNewItem, INT8 bExcludeSlot = NO_SLOT );
@@ -272,6 +276,7 @@ INT32 GetCounterForceAccuracyModifier( OBJECTTYPE *pObj, UINT8 ubStance );
INT32 GetCounterForceFrequencyModifier( OBJECTTYPE *pObj, UINT8 ubStance );
INT32 GetTargetTrackingModifier( OBJECTTYPE *pObj, UINT8 ubStance );
INT32 GetAimLevelsModifier( OBJECTTYPE *pObj, UINT8 ubStance );
INT32 GetAimLevelsTraitModifier( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj );
// Returns the character's stance as 0/1/2.
INT8 GetStanceModifierRef( INT8 ubStance );
@@ -290,7 +295,7 @@ BOOLEAN HasFastBurst( OBJECTTYPE * pObj );
INT16 GetMagSizeBonus( OBJECTTYPE * pObj, UINT8 subObject = 0 );
// HEADROCK HAM 4: This function now calculates and returns the weapon's recoil as X/Y offsets.
void GetRecoil( OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *bRecoilY, UINT8 ubNumBullet );
void GetRecoil( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 *bRecoilX, INT8 *bRecoilY, UINT8 ubNumBullet );
void GetFlatRecoilModifier( OBJECTTYPE *pObj, INT8 *bRecoilModifierX, INT8 *bRecoilModifierY );
INT16 GetPercentRecoilModifier( OBJECTTYPE *pObj );
// HEADROCK HAM 4: This function returns whether the last bullet in a burst/autofire volley was a tracer.
@@ -382,19 +387,21 @@ INT16 GetAPBonus( OBJECTTYPE * pObj );
UINT16 GetFirstExplosiveOfType(UINT16 expType);
OBJECTTYPE* FindSunGogglesInInv( SOLDIERTYPE * pSoldier, BOOLEAN searchAllInventory = FALSE );
OBJECTTYPE* FindNightGogglesInInv( SOLDIERTYPE * pSoldier, BOOLEAN searchAllInventory = FALSE );
OBJECTTYPE* FindSunGogglesInInv( SOLDIERTYPE * pSoldier, INT8 * bSlot, BOOLEAN * isAttach, BOOLEAN searchAllInventory = FALSE );
OBJECTTYPE* FindNightGogglesInInv( SOLDIERTYPE * pSoldier, INT8 * bSlot, BOOLEAN * isAttach, BOOLEAN searchAllInventory = FALSE );
UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier, INT32 sGridNo);
// HEADROCK HAM 4: New functions to determine Scope and Laser factors on a weapon.
FLOAT GetHighestScopeMagnificationFactor( OBJECTTYPE *pObj );
FLOAT GetBestScopeMagnificationFactor( OBJECTTYPE *pObj, UINT32 uiRange );
FLOAT GetScopeMagnificationFactor( OBJECTTYPE *pObj, FLOAT uiRange );
FLOAT GetBestScopeMagnificationFactor( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, FLOAT uiRange );
FLOAT GetProjectionFactor( OBJECTTYPE *pObj );
FLOAT GetScopeRangeMultiplier( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, FLOAT d2DDistance );
INT32 GetGunAccuracy( OBJECTTYPE *pObj );
INT32 GetAccuracyModifier( OBJECTTYPE *pObj );
// HEADROCK HAM 4: Added range factor
UINT8 AllowedAimingLevelsNCTH( SOLDIERTYPE *pSoldier, INT32 sGridNo);
UINT8 GetAllowedAimingLevelsForItem( OBJECTTYPE *pObj, UINT8 ubStance );
UINT8 GetAllowedAimingLevelsForItem( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, UINT8 ubStance );
INT16 GetWornUrbanCamo( SOLDIERTYPE * pSoldier );
INT16 GetUrbanCamoBonus( OBJECTTYPE * pObj );
+457 -255
View File
@@ -3562,7 +3562,7 @@ UINT8 CalcChanceToGetThrough( BULLET * pBullet )
// HEADROCK HAM 4: Using new gravity constant from INI. See also a second change below.
if ((UsingNewCTHSystem() == false && pBullet->iLoop > pBullet->iRange * 2) ||
(UsingNewCTHSystem() == true && pBullet->iLoop > pBullet->iRange * gGameCTHConstants.GRAVITY_COEFFICIENT))
(UsingNewCTHSystem() == true && pBullet->iLoop > (INT32)(pBullet->iRange * gGameCTHConstants.RANGE_COEFFICIENT)))
{
// beyond max effective range, bullet starts to drop!
// since we're doing an increment based on distance, not time, the
@@ -4229,6 +4229,11 @@ INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY,
//if ( ubLoop == 0 )
if( ubShots == 1 )
{
// CHRISL: If we don't set the ddHorizAngle, at the very least, shooting by corners is impossible. Unfortunately, I don't know what other
// impacts these two lines will have. Headrock didn't include them when he originally wrote NCTH but they are in a similar location in the
// OCTH code. Hopefully no issues will result from this change.
ddHorizAngle = ddOrigHorizAngle;
ddVerticAngle = ddOrigVerticAngle;
// HEADROCK HAM 4: Firing increments no longer required here (NCTH)
// calculate by hand (well, without angles) to match LOS
pBullet->qIncrX = FloatToFixed( dDeltaX / (FLOAT)iDistance );
@@ -5871,8 +5876,7 @@ void MoveBullet( INT32 iBullet )
FLOAT dDistanceMoved = PythSpacesAway( pBullet->pFirer->sGridNo, pBullet->sGridNo ) * 10.0f;
// HEADROCK HAM 4: Now using an INI=set Gravity Constant.
// HEADROCK HAM 4: TODO: Should this also be changed to use the Gravity Coefficient?
if ( (dDistanceMoved > pBullet->iRange) )
if ( (dDistanceMoved > (FLOAT)pBullet->iRange*gGameCTHConstants.RANGE_COEFFICIENT) )
{
// beyond max effective range, bullet starts to drop!
// since we're doing an increment based on distance, not time, the
@@ -6502,6 +6506,7 @@ BOOLEAN CalculateLOSNormal( STRUCTURE *pStructure, INT8 bLOSX, INT8 bLOSY, INT8
void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT *dEndX, FLOAT *dEndY, FLOAT *dEndZ, OBJECTTYPE *pWeapon, UINT32 uiMuzzleSway, INT16 *sApertureRatio )
{
SOLDIERTYPE *pTarget = SimpleFindSoldier( iTargetGridNo, pShooter->bTargetLevel );
///////////////////////////////////////////
// Calculate shooter's coordinates
@@ -6651,12 +6656,14 @@ void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT
// Note that the Target Tracking formula only adjusts the muzzle along the X-Axis, I.E. moving the
// shot behind the target, never up or down.
SOLDIERTYPE *pTarget = SimpleFindSoldier( iTargetGridNo, pShooter->bTargetLevel );
if (pTarget)
{
CalcTargetMovementOffset( pShooter, pTarget, pWeapon, &dMuzzleOffsetX, ddOrigHorizAngle, (INT32)iAperture );
}
pShooter->dInitialMuzzleOffsetX = dMuzzleOffsetX;
pShooter->dInitialMuzzleOffsetY = dMuzzleOffsetY;
/////////////////////////////////////////////
// First shot in a burst/auto volley
@@ -6733,7 +6740,7 @@ void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT
UINT16 uiRange = GunRange(pWeapon, pShooter);
// Is the target beyond the gun's range?
if (d2DDistance > (FLOAT)uiRange)
if (d2DDistance > ((FLOAT)uiRange*gGameCTHConstants.RANGE_COEFFICIENT))
{
//////////////////////////////////////////////////////////////////////////////////////////
// STEP 5: Bullet Drop Compensation
@@ -6765,7 +6772,7 @@ void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT
// within that circle, and sends the bullet that way. Over greater distances, this can amount to
// several penalties, thus making accurate weapons essential for any long-range shot.
CalcBulletDeviation( pShooter, &dShotOffsetX, &dShotOffsetY, pWeapon, (UINT32)d2DDistance );
FLOAT iBulletDev = CalcBulletDeviation( pShooter, &dShotOffsetX, &dShotOffsetY, pWeapon, (UINT32)d2DDistance );
/////////////////////////////////////////////////////////////////////////////////////////////
// STEP 7: Limit Shot Angle
@@ -6776,6 +6783,7 @@ void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT
// result of too many modifiers by the previous functions. In addition, the INI value also
// affects accuracy of ALL shots in the game, and is enforced here a second time.
LimitImpactPointByFacing( pShooter, pTarget, &dShotOffsetX, &dShotOffsetY, dEndX, dEndY );
LimitImpactPointToMaxAperture( &dShotOffsetX, &dShotOffsetY, iDistanceAperture );
@@ -6802,9 +6810,9 @@ void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT
swprintf(szUpDown, L"down");
}
if (pShooter->bDoBurst == 1)
if (pShooter->bDoBurst == 0 || pShooter->bDoBurst == 1)
{
ScreenMsg( FONT_MCOLOR_LTRED, MSG_INTERFACE, L"%d. Shot aperture %2.1f, goes %2.1f %s and %2.1f %s", pShooter->bDoBurst, iAperture, dShotOffsetX, szLeftRight, dShotOffsetY, szUpDown );
ScreenMsg( FONT_MCOLOR_LTRED, MSG_INTERFACE, L"%d. Shot aperture %2.1f, Accuracy %2.1f, goes %2.1f %s and %2.1f %s", pShooter->bDoBurst, iAperture, iBulletDev, dShotOffsetX, szLeftRight, dShotOffsetY, szUpDown );
}
else
{
@@ -6846,43 +6854,42 @@ void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT
*dEndY += dSecondDeltaY;
*dEndZ = __max(-127, *dEndZ + (dShotOffsetY * 11.3f)); // Y, which represented up/down offset, is actually the Z axis in 3d game terms...
// These values are returned to the calling function, in this case UseGun(). That function then fires the bullet
// These values are returned to the calling function, in this case UseGunNCTH(). That function then fires the bullet
// directly at the intended coordinates.
}
FLOAT CalcProjectionFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2DDistance, UINT8 ubAimTime )
{
FLOAT iProjectionFactor = 1.0f;
FLOAT iTargetMagFactor = d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE;
if (ubAimTime > 0)
{
iProjectionFactor = GetProjectionFactor( pWeapon );
if (floor(iTargetMagFactor*10) > floor(iProjectionFactor*10.001))
{
iProjectionFactor -= (iTargetMagFactor - iProjectionFactor);
iProjectionFactor = __max(iProjectionFactor, 1.0f);
}
}
return iProjectionFactor;
}
FLOAT CalcMagFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2DDistance, UINT8 ubAimTime )
{
FLOAT iFinalMagFactor = 0;
FLOAT iScopeFactor = 0;
FLOAT iProjectionFactor = 0;
FLOAT iTargetMagFactor = d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE;
FLOAT rangeModifier = GetScopeRangeMultiplier(pShooter, pWeapon, d2DDistance);
if (ubAimTime > 0)
{
iScopeFactor = GetBestScopeMagnificationFactor( pWeapon, (UINT32)d2DDistance );
iProjectionFactor = GetProjectionFactor( pWeapon );
// Now calculate the optimal magnification that would be required for the target's current distance.
FLOAT iTargetMagFactor = d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE;
if (iTargetMagFactor > iProjectionFactor)
{
// Projection items, like lasers or red dot sights, work up to their "best" range without error.
// If the target is closer than that best range, the projection factor remains the same, helping
// all shots at the target be more accurate.
// However, if the target is further away, the projection begins to lose its effectiveness, becoming
// less useful until it loses all value.
iProjectionFactor -= (iTargetMagFactor - iProjectionFactor);
iProjectionFactor = __max(iProjectionFactor, 1.0f);
}
if (iTargetMagFactor < iScopeFactor)
{
// Scopes give their best Mag Factor at a certain distance and beyond that distance. If the target is
// closer however, it's the target's distance that determines the scope's mag factor. This makes scopes
// quite less useful at ranges closer than they are intended for.
iScopeFactor = iTargetMagFactor;
}
// The final factor is the largest of the two.
iScopeFactor = GetBestScopeMagnificationFactor( pShooter, pWeapon, d2DDistance );
iScopeFactor = __min(iScopeFactor, __max(1.0f, iTargetMagFactor/rangeModifier));
iProjectionFactor = CalcProjectionFactor(pShooter, pWeapon, d2DDistance, ubAimTime);
iFinalMagFactor = __max(iScopeFactor, iProjectionFactor);
}
else
@@ -6985,6 +6992,15 @@ void CalcTargetMovementOffset( SOLDIERTYPE *pShooter, SOLDIERTYPE *pTarget, OBJE
INT16 sDistanceMoved = (INT16)sqrt((double) (sDeltaX * sDeltaX) + (sDeltaY * sDeltaY));
sDistanceMoved /= CELL_X_SIZE; // convert to Tiles.
//CHRISL: The above all assumes that the target is actually still possibly moving at the same rate
// he was moving at before the end of his turn. But what happens if a target moves, stops and
// changes stance? We use usAnimState to figure out what stance we're currently in by looking at
// out current animation state. And I think usUIMovementMode tells us what animation state we
// last moved in. So if these two values are different, we should be able to assume that the target
// has stopped moving.
if (pTarget->usAnimState != pTarget->usUIMovementMode)
sDistanceMoved = 0;
if (sDistanceMoved == 0)
{
//Target hasn't moved. Simply abort the formula, as there will be no movement penalty anyway.
@@ -7129,7 +7145,7 @@ void CalcRangeCompensationOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetY,
// and how fast it is spinning along its axis will all determine how far it can go before this happens.
//
// The JA2 Bullet Mechanism already simulates this effect, by decreasing a bullet's vertical angle repeatedly
// once it crosses its "maximum range" (as defined by the weapon's Range property). The bullet falls to the
// once it crosses its "maximum range" (as defined by twice the weapon's Range property). The bullet falls to the
// ground with increasing rapidity, until it collides with the ground.
//
// NCTH uses this principle in reverse - allowing shooters to compensate for this effect and thereby increase
@@ -7149,7 +7165,7 @@ void CalcRangeCompensationOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetY,
// Avoid division by 0.
return;
}
if (usGunRange >= iRangeToTarget)
if ((usGunRange*gGameCTHConstants.RANGE_COEFFICIENT) >= iRangeToTarget)
{
return;
}
@@ -7164,7 +7180,7 @@ void CalcRangeCompensationOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetY,
// We now take the Range to Target and the Maximum Range for the bullet, and find the distance between them.
// This is how much distance the bullet has to cover while dropping out of the sky. In other words, we need to
// make the bullet fly this much longer than it would normally have.
INT32 iRangeDiff = (iRangeToTarget-usGunRange) / 10;
INT32 iRangeDiff = (iRangeToTarget-(UINT32)(usGunRange*gGameCTHConstants.RANGE_COEFFICIENT)) / 10;
// To know how much we need to raise our muzzle, what we do is calculate how far below the target the bullet would
// hit, assuming no muzzle adjustment, and pretending there's no ground to collide with. The result is equal to
@@ -7271,7 +7287,7 @@ void CalcMuzzleSway( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzl
*dMuzzleOffsetY += (dDeltaY * bUpDown) * dVerticalBias;
}
void CalcBulletDeviation( SOLDIERTYPE *pShooter, FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, OBJECTTYPE *pWeapon, UINT32 uiRange )
FLOAT CalcBulletDeviation( SOLDIERTYPE *pShooter, FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, OBJECTTYPE *pWeapon, UINT32 uiRange )
{
//////////////////////////////////////////////////////////////////////////////////////////////////
// HEADROCK HAM 4: New Shooting Mechanism, Bullet Deviation
@@ -7301,6 +7317,15 @@ void CalcBulletDeviation( SOLDIERTYPE *pShooter, FLOAT *dShotOffsetX, FLOAT *dSh
// We start by reading the gun's Accuracy value. We'll use that as the basis for everything else.
INT16 sAccuracy = GetGunAccuracy( pWeapon );
UINT16 sEffRange = Weapon[Item[pShooter->inv[pShooter->ubAttackingHand].usItem].ubClassIndex].usRange + GetRangeBonus(&(pShooter->inv[ pShooter->ubAttackingHand ]));
// WANNE: I got a CTD in a multiplayer test game, because sEffRange was 0 (division to zero).
// I don't know why this happend?
FLOAT iRangeRatio = 1.0f;
if (sEffRange > 0)
{
iRangeRatio = __max(1.0f, (FLOAT)(uiRange / sEffRange));
}
// This value can be anywhere between 0 and 100. Let's make sure.
sAccuracy = __max(0, sAccuracy);
@@ -7313,12 +7338,15 @@ void CalcBulletDeviation( SOLDIERTYPE *pShooter, FLOAT *dShotOffsetX, FLOAT *dSh
// deviation circle (100% radius), while a gun with accuracy 100 produces a minimal sized
// circle (actually, a dot with 0% radius).
FLOAT iBulletDev = (gGameCTHConstants.MAX_BULLET_DEV * (100-sAccuracy)) / 100;
if (gGameCTHConstants.RANGE_EFFECTS_DEV == TRUE)
iBulletDev *= iRangeRatio;
iBulletDev /= 2; // This compensates for the difference between CellXY and ScreenXY
// If the radius is 0, this gun's bullets are flawless, and will never deviate from where
// they were fired.
if (iBulletDev == 0)
{
return;
return (iBulletDev);
}
// So now, iBulletDev is a maximum deviation for any bullet coming out of this weapon.
@@ -7348,6 +7376,96 @@ void CalcBulletDeviation( SOLDIERTYPE *pShooter, FLOAT *dShotOffsetX, FLOAT *dSh
*dShotOffsetX += dDeltaX * bLeftRight;
*dShotOffsetY += dDeltaY * bUpDown;
return (iBulletDev);
}
void LimitImpactPointByFacing( SOLDIERTYPE *pShooter, SOLDIERTYPE *pTarget, FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FLOAT *dEndX, FLOAT *dEndY )
{
////////////////////////////////////////////////////////////////////////////////////////////
//
// CHRISL HAM 4: New Shooting Mechanism, Angle Limits by Facing
//
// One drawback of the new shooting mechanism is that it depends on the the JSD files being accurate. These
// files determine how an obstruction (like an enemy soldier) takes up space in a 3D tile. This is done by
// splitting a tile into 125 "cubes", stacked 5 x 5 x 5. Each "cube" is 2 units wide, 2 units deep and about
// 6 units tall. A standing merc in the JSD files is represented by a "plus sign" shaped construct that is
// 3 "cubes" tall, 3 "cubes" wide and 1 "cube" deep. A crouching soldier is 2 x 3 x 2 and a prone soldier is
// 1 x 3 x 5. This means if we're shooting at a standind target from the side, we effectively have 1/3 the
// chance to hit as we would a target that was facing us. Unfortunately, the graphical cursor can't display
// this information so it will appear as though you have the same chance of hitting regardless of the targets
// facing.
//
// As a result of the above, this function determines the targets facing compared to the shooters, and will
// reduce the Shot Offsets if the target isn't facing directly towards or away from the shooter. This isn't
// the most accurate solution but it's the best solution I can come up with at this time. The alternative is
// to let shots that appear to have no chance of missing (shooting aperture within the targets displayed body)
// actually miss an average of 2 in every 3 shots.
//
// I'm going to assume for the moment that the 1/3rd chance only occurs when a target is facing directly perpendicular
// to your facing. I don't know for sure if this is true or not, but it's the assumption I'm going to make.
//
////////////////////////////////////////////////////////////////////////////////////////////
UINT8 iShooterFacing = pShooter->ubDirection;
UINT8 iTargetFacing = pShooter->ubDirection;
FLOAT iDivisor = gGameCTHConstants.SIDE_FACING_DIVISOR;
if(pTarget)
iTargetFacing = pTarget->ubDirection;
switch (iTargetFacing)
{
case 0:
if(iShooterFacing == 2 || iShooterFacing == 6){
*dShotOffsetX /= iDivisor;
*dShotOffsetY /= iDivisor;
}
break;
case 1:
if(iShooterFacing == 3 || iShooterFacing == 7){
*dShotOffsetX /= iDivisor;
*dShotOffsetY /= iDivisor;
}
break;
case 2:
if(iShooterFacing == 0 || iShooterFacing == 4){
*dShotOffsetX /= iDivisor;
*dShotOffsetY /= iDivisor;
}
break;
case 3:
if(iShooterFacing == 1 || iShooterFacing == 5){
*dShotOffsetX /= iDivisor;
*dShotOffsetY /= iDivisor;
}
break;
case 4:
if(iShooterFacing == 2 || iShooterFacing == 6){
*dShotOffsetX /= iDivisor;
*dShotOffsetY /= iDivisor;
}
break;
case 5:
if(iShooterFacing == 3 || iShooterFacing == 7){
*dShotOffsetX /= iDivisor;
*dShotOffsetY /= iDivisor;
}
break;
case 6:
if(iShooterFacing == 0 || iShooterFacing == 4){
*dShotOffsetX /= iDivisor;
*dShotOffsetY /= iDivisor;
}
break;
case 7:
if(iShooterFacing == 1 || iShooterFacing == 5){
*dShotOffsetX /= iDivisor;
*dShotOffsetY /= iDivisor;
}
break;
default:
break;
}
}
void LimitImpactPointToMaxAperture( FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FLOAT dDistanceAperture )
@@ -7391,6 +7509,169 @@ void LimitImpactPointToMaxAperture( FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FL
}
}
UINT32 CalcCounterForceFrequency(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon)
{
INT8 traitLoop;
FLOAT iCounterForceFrequency = gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_AGI * EffectiveAgility(pShooter);
iCounterForceFrequency += gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_EXP_LEVEL * EffectiveExpLevel(pShooter) * 10;
// Average
FLOAT iDivisor = gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_AGI +
gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_EXP_LEVEL;
iCounterForceFrequency /= iDivisor;
// Bridge the gap to 100 with the help of the AUTO-WEAPONS skill
if(gGameOptions.fNewTraitSystem)
traitLoop = NUM_SKILL_TRAITS( pShooter, AUTO_WEAPONS_NT );
else
traitLoop = NUM_SKILL_TRAITS( pShooter, AUTO_WEAPS_OT );
for (INT32 x = 0; x < traitLoop; x++)
{
INT8 bDifference = (INT8)(100-iCounterForceFrequency);
bDifference = (INT8)(bDifference / gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_AUTO_WEAPONS_DIVISOR);
iCounterForceFrequency += bDifference;
}
// Percent Modifier from weapon and its attachments
iCounterForceFrequency += (iCounterForceFrequency * GetCounterForceFrequencyModifier( pWeapon, gAnimControl[ pShooter->usAnimState ].ubEndHeight )) / 100;
// Limit to 1-100.
iCounterForceFrequency = __min(100, iCounterForceFrequency);
iCounterForceFrequency = __max(1, iCounterForceFrequency);
// Invert value. Now 100 is bad, 1 is good.
iCounterForceFrequency = 100 - iCounterForceFrequency;
// Calculate frequency
UINT32 uiBulletsPer5AP = max(1,GetAutofireShotsPerFiveAPs( pWeapon ));
UINT32 uiCounterForceFrequency = __max(1, (UINT32)ceil((uiBulletsPer5AP * iCounterForceFrequency) / 100));
//CHRISL: For the time being, this is going to override the CFF function
uiBulletsPer5AP = GetAutofireShotsPerFiveAPs( pWeapon );
if(uiBulletsPer5AP < 1)
uiBulletsPer5AP = 3;
uiCounterForceFrequency = (UINT32)ceil((FLOAT)uiBulletsPer5AP / 2.0f);
return uiCounterForceFrequency;
}
FLOAT CalcCounterForceMax(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, UINT8 uiStance)
{
if(uiStance == 0)
uiStance = gAnimControl[ pShooter->usAnimState ].ubHeight;
FLOAT iCounterForceMax = gGameCTHConstants.RECOIL_MAX_COUNTER_STR * EffectiveStrength(pShooter);
iCounterForceMax += gGameCTHConstants.RECOIL_MAX_COUNTER_AGI * EffectiveAgility(pShooter);
iCounterForceMax += gGameCTHConstants.RECOIL_MAX_COUNTER_EXP_LEVEL * EffectiveExpLevel(pShooter) * 10;
FLOAT iDivisor = gGameCTHConstants.RECOIL_MAX_COUNTER_STR +
gGameCTHConstants.RECOIL_MAX_COUNTER_AGI +
gGameCTHConstants.RECOIL_MAX_COUNTER_EXP_LEVEL;
iCounterForceMax /= iDivisor;
// Add the effects from the weapon and its attachments (foregrip, for instance). This is applied as a percentage.
INT32 iModifier = GetCounterForceMaxModifier( pWeapon, uiStance );
iCounterForceMax += (iCounterForceMax * iModifier) / 100;
// Limit to 0-100.
//iCounterForceMax = __max(__min(iCounterForceMax, 100), 0);
// Use the result as a percentage of the maximum possible applicable force, as defined in the INI.
iCounterForceMax = (FLOAT)((iCounterForceMax * gGameCTHConstants.RECOIL_MAX_COUNTER_FORCE) / 100);
return iCounterForceMax;
}
UINT32 CalcCounterForceAccuracy(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, UINT32 uiRange, BOOLEAN fTracer, bool fAnticipate)
{
INT8 traitLoop;
FLOAT iCounterForceAccuracy = gGameCTHConstants.RECOIL_COUNTER_ACCURACY_DEX * EffectiveDexterity(pShooter);
iCounterForceAccuracy += gGameCTHConstants.RECOIL_COUNTER_ACCURACY_WIS * EffectiveWisdom(pShooter);
iCounterForceAccuracy += gGameCTHConstants.RECOIL_COUNTER_ACCURACY_AGI * EffectiveAgility(pShooter);
iCounterForceAccuracy += gGameCTHConstants.RECOIL_COUNTER_ACCURACY_EXP_LEVEL * EffectiveExpLevel(pShooter) * 10;
FLOAT iDivisor = gGameCTHConstants.RECOIL_COUNTER_ACCURACY_DEX +
gGameCTHConstants.RECOIL_COUNTER_ACCURACY_WIS +
gGameCTHConstants.RECOIL_COUNTER_ACCURACY_AGI +
gGameCTHConstants.RECOIL_COUNTER_ACCURACY_EXP_LEVEL;
iCounterForceAccuracy /= iDivisor;
// Add the effects from the weapon and its attachments. A foregrip or bipod are very useful for this.
// Attachment bonuses are applied as a percentage to the accuracy of the shooter.
INT32 iModifier = GetCounterForceAccuracyModifier( pWeapon, gAnimControl[ pShooter->usAnimState ].ubHeight );
UINT32 uiCounterForceAccuracy = (UINT32)(iCounterForceAccuracy + ((iCounterForceAccuracy * iModifier) / 100));
// Now add the effect of the AutoWeapons skill. It "bridges" a portion of the gap between shooter's actual accuracy
// and 100% accuracy. For instance, if the divisor is set to 2 in the INI, the first skill level will close 50% of
// the gap, the second skill level closes another 25%.
if(gGameOptions.fNewTraitSystem)
traitLoop = NUM_SKILL_TRAITS( pShooter, AUTO_WEAPONS_NT );
else
traitLoop = NUM_SKILL_TRAITS( pShooter, AUTO_WEAPS_OT );
for (INT32 x = 0; x < traitLoop; x++)
{
INT8 bDifference = 100-uiCounterForceAccuracy;
bDifference = (INT8)(bDifference / gGameCTHConstants.RECOIL_COUNTER_ACCURACY_AUTO_WEAPONS_DIVISOR);
uiCounterForceAccuracy += bDifference;
}
////////////////////////////////////////////////////////////////////
// Sight-range effects
// If we can't see the target, but buddies can see it, CF-Accuracy drops by 50%
// If we can't see the target and neither can buddies, CF-Accuracy drops by 75%
UINT8 ubTargetID = WhoIsThere2( pShooter->sTargetGridNo, pShooter->bTargetLevel ); // Target ubID
INT16 sDistVis = pShooter->GetMaxDistanceVisible(pShooter->sTargetGridNo, pShooter->bTargetLevel, CALC_FROM_ALL_DIRS ) * CELL_X_SIZE;
gbForceWeaponNotReady = true;
INT16 sDistVisNoScope = pShooter->GetMaxDistanceVisible(pShooter->sTargetGridNo, pShooter->bTargetLevel, CALC_FROM_ALL_DIRS ) * CELL_X_SIZE;
gbForceWeaponNotReady = false;
FLOAT scopeRangeMod = (float)sDistVis / (float)sDistVisNoScope;
INT32 iSightRange = 0;
if (ubTargetID != NOBODY)
iSightRange = SoldierToSoldierLineOfSightTest( pShooter, MercPtrs[ubTargetID], TRUE, NO_DISTANCE_LIMIT, pShooter->bAimShotLocation, false );
if (iSightRange == 0) { // didn't do a bodypart-based test or can't see specific body part aimed at
iSightRange = SoldierTo3DLocationLineOfSightTest( pShooter, pShooter->sTargetGridNo, pShooter->bTargetLevel, pShooter->bTargetCubeLevel, TRUE, NO_DISTANCE_LIMIT, false );
}
if (iSightRange == 0) { // Can't see the target but we still need to know what the sight range would be if we could so we can deal with cover penalties
iSightRange = SoldierToSoldierLineOfSightTest( pShooter, MercPtrs[ubTargetID], TRUE, NO_DISTANCE_LIMIT, pShooter->bAimShotLocation, false, true );
}
// Modify iSightRange for scope use
iSightRange = (INT32)(iSightRange / scopeRangeMod);
if (pShooter->aiData.bOppList[ubTargetID] != SEEN_CURRENTLY && gbPublicOpplist[pShooter->bTeam][ubTargetID] == SEEN_CURRENTLY)
iSightRange *= 2;
else if(pShooter->aiData.bOppList[ubTargetID] != SEEN_CURRENTLY && gbPublicOpplist[pShooter->bTeam][ubTargetID] != SEEN_CURRENTLY)
iSightRange *= 4;
// CHRISL: Divide physical range by sight range. Not the other way around. We wan't CFA to go down if someone appears to be further
// then they are because of terrain or the fact that we can't see them.
uiCounterForceAccuracy = (UINT32)(uiCounterForceAccuracy * (FLOAT)((FLOAT)uiRange / iSightRange));
// Was last bullet a tracer?
if (fTracer)
{
// Augment by a certain amount, mitigated by range
uiCounterForceAccuracy += (UINT32)gGameCTHConstants.RECOIL_COUNTER_ACCURACY_TRACER_BONUS;
}
if(fAnticipate)
{
uiCounterForceAccuracy -= (UINT32)(uiCounterForceAccuracy * gGameCTHConstants.RECOIL_COUNTER_ACCURACY_ANTICIPATION / 100);
}
// Limit to 0 to 100.
uiCounterForceAccuracy = __max(__min(uiCounterForceAccuracy, 100), 0);
// Invert. 0=good, 100-bad.
uiCounterForceAccuracy = 100-uiCounterForceAccuracy;
return uiCounterForceAccuracy;
}
void CalcPreRecoilOffset( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzleOffsetY, UINT32 uiRange )
{
//////////////////////////////////////////////////////////////////////////////////////
@@ -7422,6 +7703,39 @@ void CalcPreRecoilOffset( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT *dMu
// this soldier to actually consider using pre-recoil offset at all. This depends entirely
// on wisdom and experience.
// We can also anticipate the recoil of the weapon, which we should set here.
INT8 bGunRecoilX;
INT8 bGunRecoilY;
FLOAT dDistanceRatio = (FLOAT)(uiRange / gGameCTHConstants.NORMAL_RECOIL_DISTANCE);
FLOAT iCounterForceMax = CalcCounterForceMax(pShooter, pWeapon);
UINT32 uiCounterForceAccuracy = CalcCounterForceAccuracy(pShooter, pWeapon, uiRange, FALSE, true);
UINT32 uiCounterForceFrequency = CalcCounterForceFrequency(pShooter, pWeapon);
iCounterForceMax = iCounterForceMax * (100-uiCounterForceAccuracy) / 100;
GetRecoil( pShooter, pWeapon, &bGunRecoilX, &bGunRecoilY, 1 );
FLOAT iGunTotalRecoil = (FLOAT)bGunRecoilX + (FLOAT)bGunRecoilY;
FLOAT iIdealCounterForceX = 0.0;
FLOAT iIdealCounterForceY = 0.0;
if(iGunTotalRecoil != 0)
{
iIdealCounterForceX = __min( iCounterForceMax, (FLOAT)bGunRecoilX );
iIdealCounterForceY = __min( iCounterForceMax, (FLOAT)bGunRecoilY );
FLOAT iTotalCounterForce = sqrt((abs(iIdealCounterForceX)*abs(iIdealCounterForceX)) + (abs(iIdealCounterForceY)*abs(iIdealCounterForceY)));
if (iTotalCounterForce > iCounterForceMax)
{
FLOAT iRatio = iTotalCounterForce / iCounterForceMax;
if (iRatio != 0)
{
iIdealCounterForceX /= iRatio;
iIdealCounterForceY /= iRatio;
}
}
pShooter->dPrevCounterForceX = -iIdealCounterForceX;
pShooter->dPrevCounterForceY = -iIdealCounterForceY;
}
INT8 traitLoop;
FLOAT iCombinedSkill = gGameCTHConstants.PRE_RECOIL_WIS * EffectiveWisdom(pShooter);
iCombinedSkill += gGameCTHConstants.PRE_RECOIL_EXP_LEVEL * EffectiveExpLevel(pShooter) * 10;
@@ -7459,41 +7773,6 @@ void CalcPreRecoilOffset( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT *dMu
// shooter gets his chance to begin applying counter-force. He'll need to pre-compensate for this
// many bullets.
FLOAT iCounterForceFrequency = gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_AGI * EffectiveAgility(pShooter);
iCounterForceFrequency += gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_EXP_LEVEL * EffectiveExpLevel(pShooter) * 10;
// Average
iDivisor = gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_AGI +
gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_EXP_LEVEL;
iCounterForceFrequency /= iDivisor;
//CHRISL: TODO: STOMP need to include AUTO_WEAPS_OT here as well.
// Bridge the gap to 100 with the help of the AUTO-WEAPONS skill
if(gGameOptions.fNewTraitSystem)
traitLoop = NUM_SKILL_TRAITS( pShooter, AUTO_WEAPONS_NT );
else
traitLoop = NUM_SKILL_TRAITS( pShooter, AUTO_WEAPS_OT );
for (INT32 x = 0; x < traitLoop; x++)
{
INT8 bDifference = (INT8)(100-iCounterForceFrequency);
bDifference = (INT8)(bDifference / gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_AUTO_WEAPONS_DIVISOR);
iCounterForceFrequency += bDifference;
}
// Percent Modifier from weapon and its attachments
iCounterForceFrequency += (iCounterForceFrequency * GetCounterForceFrequencyModifier( pWeapon, gAnimControl[ pShooter->usAnimState ].ubEndHeight )) / 100;
// Limit to 0-100.
iCounterForceFrequency = __min(100, iCounterForceFrequency);
iCounterForceFrequency = __max(0, iCounterForceFrequency);
// Invert value. Now 100 is bad, 0 is good.
iCounterForceFrequency = 100 - iCounterForceFrequency;
// Calculate frequency
UINT32 uiBulletsPer5AP = GetAutofireShotsPerFiveAPs( pWeapon );
UINT32 uiCounterForceFrequency = __max(1, (UINT32)(iCounterForceFrequency * uiBulletsPer5AP) / 100);
// Also, it might be possible that we don't intend to fire that many bullets at all. So we want to figure out
// how many bullets are about to be fired, and adjust accordingly.
UINT32 uiIntendedBullets;
@@ -7512,17 +7791,15 @@ void CalcPreRecoilOffset( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT *dMu
uiIntendedBullets = __min( uiIntendedBullets, uiCounterForceFrequency );
// Now, let's figure out how much recoil this gun will put out during those first X bullets.
INT8 bGunRecoilX;
INT8 bGunRecoilY;
INT32 iTotalGunRecoilX = 0;
INT32 iTotalGunRecoilY = 0;
FLOAT iTotalGunRecoilX = 0;
FLOAT iTotalGunRecoilY = 0;
// For each bullet, add up its recoil.
for (UINT32 count=1; count <= uiIntendedBullets; count++)
{
GetRecoil( pWeapon, &bGunRecoilX, &bGunRecoilY, count );
iTotalGunRecoilX += bGunRecoilX;
iTotalGunRecoilY += bGunRecoilY;
GetRecoil( pShooter, pWeapon, &bGunRecoilX, &bGunRecoilY, count );
iTotalGunRecoilX += (bGunRecoilX + pShooter->dPrevCounterForceX);
iTotalGunRecoilY += (bGunRecoilY + pShooter->dPrevCounterForceY);
}
if (iTotalGunRecoilX == 0 && iTotalGunRecoilY == 0)
@@ -7545,17 +7822,16 @@ void CalcPreRecoilOffset( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT *dMu
INT8 bLeftRight = PreRandom(2)?(1):(-1);
// Apply random factor
dPreRecoilX = (iTotalGunRecoilX * -1) + (dPreRecoilX * bLeftRight);
dPreRecoilY = (iTotalGunRecoilY * -1) + (dPreRecoilY * bUpDown);
dPreRecoilX = iTotalGunRecoilX + (dPreRecoilX * bLeftRight);
dPreRecoilY = iTotalGunRecoilY + (dPreRecoilY * bUpDown);
// Apply distance ratio. The further away we are, the more compensation we need.
FLOAT dDistanceRatio = (FLOAT)(uiRange / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
dPreRecoilX *= dDistanceRatio;
dPreRecoilY *= dDistanceRatio;
// Finally, adjust our muzzle direction.
*dMuzzleOffsetX += dPreRecoilX;
*dMuzzleOffsetY += dPreRecoilY;
*dMuzzleOffsetX -= dPreRecoilX;
*dMuzzleOffsetY -= dPreRecoilY;
}
@@ -7578,15 +7854,18 @@ void CalcRecoilOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuz
// shooters might be overwhelmed and start firing towards the sky.
// Get X/Y recoil parameters from the gun.
INT8 traitLoop;
INT8 bGunRecoilX;
INT8 bGunRecoilY;
GetRecoil( pWeapon, &bGunRecoilX, &bGunRecoilY, pShooter->bDoBurst );
GetRecoil( pShooter, pWeapon, &bGunRecoilX, &bGunRecoilY, pShooter->bDoBurst-1 );
// If no recoil, then we shouldn't be here anyway.
if(bGunRecoilX == 0 && bGunRecoilY == 0)
return;
FLOAT iGunTotalRecoil = sqrt((FLOAT)(bGunRecoilX*bGunRecoilX) + (FLOAT)(bGunRecoilY*bGunRecoilY));
FLOAT iDistanceRatio = (FLOAT)((FLOAT)uiRange / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE);
FLOAT iDistanceRatio = (FLOAT)uiRange / (FLOAT)gGameCTHConstants.NORMAL_RECOIL_DISTANCE;
// These variables will hold the amount of X/Y force our shooter exerts to try to fight recoil.
FLOAT iAppliedCounterForceX;
@@ -7601,30 +7880,7 @@ void CalcRecoilOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuz
// Skilled shooters get this chance more often.
// Tracer fire also helps. Once a tracer bullet is fired, we get one free chance to alter our counter-force.
FLOAT iCounterForceFrequency = gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_AGI * EffectiveAgility(pShooter);
iCounterForceFrequency += gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_EXP_LEVEL * EffectiveExpLevel(pShooter) * 10;
FLOAT iDivisor = gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_AGI +
gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_EXP_LEVEL;
iCounterForceFrequency /= iDivisor;
//CHRISL: TODO: STOMP need to include AUTO_WEAPS_OT here as well.
if(gGameOptions.fNewTraitSystem)
traitLoop = NUM_SKILL_TRAITS( pShooter, AUTO_WEAPONS_NT );
else
traitLoop = NUM_SKILL_TRAITS( pShooter, AUTO_WEAPS_OT );
for (INT32 x = 0; x < traitLoop; x++)
{
INT8 bDifference = (INT8)(100-iCounterForceFrequency);
bDifference = (INT8)(bDifference / gGameCTHConstants.RECOIL_COUNTER_FREQUENCY_AUTO_WEAPONS_DIVISOR);
iCounterForceFrequency += bDifference;
}
UINT32 uiBulletsPer5AP = GetAutofireShotsPerFiveAPs( pWeapon );
UINT32 uiCounterForceFrequency = (UINT32)((iCounterForceFrequency * uiBulletsPer5AP) / 100);
// Flat Modifier from weapon and its attachments
uiCounterForceFrequency = __max(1, uiCounterForceFrequency + ((uiCounterForceFrequency * GetCounterForceFrequencyModifier( pWeapon, gAnimControl[ pShooter->usAnimState ].ubEndHeight )) / 100));
UINT32 uiCounterForceFrequency = CalcCounterForceFrequency(pShooter, pWeapon);
BOOLEAN fAdjustmentAllowed = FALSE;
if ((pShooter->bDoBurst-1)%uiCounterForceFrequency == 0)
@@ -7653,9 +7909,30 @@ void CalcRecoilOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuz
// Our shooter wants to apply just as much counter-force as necessary to keep the next offset as close to 0 on both
// axes.
// Instead of assuming we're on a uiCounterForceFrequency round, we need to verify exactly where we are in the uiCounterForceFrequency
// sequence.
INT32 uiIntendedBullets;
if ( pShooter->bDoAutofire > 0 )
{
// Autofire. The number of bullets to be fired equals to the value of bDoAutofire
uiIntendedBullets = pShooter->bDoAutofire;
}
else
{
// Burst. Get the number of shots-per-burst from the weapon.
uiIntendedBullets = Weapon[ pWeapon->usItem ].ubShotsPerBurst + GetBurstSizeBonus(pWeapon);
}
INT8 iRound = (pShooter->bDoBurst-1) % uiCounterForceFrequency;
if(iRound == 0)
iRound = uiCounterForceFrequency;
if((pShooter->bDoBurst - 1 + iRound) > uiIntendedBullets)
iRound = uiIntendedBullets - (pShooter->bDoBurst - 1);
// Add the two together to figure out where the next bullet is going to fly in relation to the target.
FLOAT dNextOffsetX = (FLOAT)(*dMuzzleOffsetX + ((bGunRecoilX * iDistanceRatio) * uiCounterForceFrequency) );
FLOAT dNextOffsetY = (FLOAT)(*dMuzzleOffsetY + ((bGunRecoilY * iDistanceRatio) * uiCounterForceFrequency) );
FLOAT dNextOffsetX = (FLOAT)(*dMuzzleOffsetX + (bGunRecoilX * iDistanceRatio) );
FLOAT dNextOffsetY = (FLOAT)(*dMuzzleOffsetY + (bGunRecoilY * iDistanceRatio) );
//FLOAT dNextOffsetX = (FLOAT)(*dMuzzleOffsetX + ((bGunRecoilX * iDistanceRatio) * uiCounterForceFrequency) );
//FLOAT dNextOffsetY = (FLOAT)(*dMuzzleOffsetY + ((bGunRecoilY * iDistanceRatio) * uiCounterForceFrequency) );
////////////////////////////////////////////////////////////////////////////
// Calculating recoil counter-force.
@@ -7678,113 +7955,43 @@ void CalcRecoilOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuz
// maximum counter-force that can be applied. By default, it is based primarily on the strength of the shooter,
// although agility is also helpful.
FLOAT iCounterForceMax = gGameCTHConstants.RECOIL_MAX_COUNTER_STR * EffectiveStrength(pShooter);
iCounterForceMax += gGameCTHConstants.RECOIL_MAX_COUNTER_AGI * EffectiveAgility(pShooter);
iCounterForceMax += gGameCTHConstants.RECOIL_MAX_COUNTER_EXP_LEVEL * EffectiveExpLevel(pShooter) * 10;
iDivisor = gGameCTHConstants.RECOIL_MAX_COUNTER_STR +
gGameCTHConstants.RECOIL_MAX_COUNTER_AGI +
gGameCTHConstants.RECOIL_MAX_COUNTER_EXP_LEVEL;
iCounterForceMax /= iDivisor;
// Add the effects from the weapon and its attachments (foregrip, for instance). This is applied as a percentage.
INT32 iModifier = GetCounterForceMaxModifier( pWeapon, gAnimControl[ pShooter->usAnimState ].ubHeight );
iCounterForceMax += (iCounterForceMax * iModifier) / 100;
// Limit to 0-100.
iCounterForceMax = __max(__min(iCounterForceMax, 100), 0);
// Use the result as a percentage of the maximum possible applicable force, as defined in the INI.
iCounterForceMax = (FLOAT)((iCounterForceMax * gGameCTHConstants.RECOIL_MAX_COUNTER_FORCE) / 100);
FLOAT iCounterForceMax = CalcCounterForceMax(pShooter, pWeapon);
// iCounterForceMax is now the absolute limit.
// STEP 2: Now let's determine how much counter-force would be ideal. If the gun isn't kicking too powerfully,
// and/or not too much recoil has built up from previous bullets, the shooter should potentially be able to compensate
// for ALL of it. However, in some cases, the shooter simply can't exert enough force to counter ALL recoil.
// Calculate Ideal X and limit to max force
FLOAT iIdealCounterForceX = 0.0;
iIdealCounterForceX = __min( iCounterForceMax, abs((dNextOffsetX / iDistanceRatio) / uiCounterForceFrequency ));
// Calculate Ideal Y and limit to max force
FLOAT iIdealCounterForceY = 0.0;
iIdealCounterForceY = __min( iCounterForceMax, abs((dNextOffsetY / iDistanceRatio) / uiCounterForceFrequency ));
// STEP 3: Now we need to determine how accurate the shooter is when applying counter-force. He won't always apply
// STEP 2: Now we need to determine how accurate the shooter is when applying counter-force. He won't always apply
// as much as necessary, and may sometimes apply too much. The ability to apply exactly (or close to exactly) the
// amount of force required is based on various skills, especially agility and dexterity. Wisdom and experience also
// help, and the AUTO_WEAPONS skill is invaluable. In addition, tracers (when actually fired) will boost the
// ability to compensate correctly by a certain amount.
FLOAT iCounterForceAccuracy = gGameCTHConstants.RECOIL_COUNTER_ACCURACY_DEX * EffectiveDexterity(pShooter);
iCounterForceAccuracy += gGameCTHConstants.RECOIL_COUNTER_ACCURACY_WIS * EffectiveWisdom(pShooter);
iCounterForceAccuracy += gGameCTHConstants.RECOIL_COUNTER_ACCURACY_AGI * EffectiveAgility(pShooter);
iCounterForceAccuracy += gGameCTHConstants.RECOIL_COUNTER_ACCURACY_EXP_LEVEL * EffectiveExpLevel(pShooter) * 10;
UINT32 uiCounterForceAccuracy = CalcCounterForceAccuracy(pShooter, pWeapon, uiRange, fTracer);
iDivisor = gGameCTHConstants.RECOIL_COUNTER_ACCURACY_DEX +
gGameCTHConstants.RECOIL_COUNTER_ACCURACY_WIS +
gGameCTHConstants.RECOIL_COUNTER_ACCURACY_AGI +
gGameCTHConstants.RECOIL_COUNTER_ACCURACY_EXP_LEVEL;
iCounterForceAccuracy /= iDivisor;
// STEP 3: Now let's determine how much counter-force would be ideal. If the gun isn't kicking too powerfully,
// and/or not too much recoil has built up from previous bullets, the shooter should potentially be able to compensate
// for ALL of it. However, in some cases, the shooter simply can't exert enough force to counter ALL recoil.
// ChrisL: Here we need a little change. As the above comment states, we do want to try and compensate for ALL recoil which makes sense.
// And it also makes sense that we try and compensate for any recoil we previously under-compensated for. But what we're actually doing
// is trying to compensate for all recoil AND bring our offsets back to 0x0 which makes autofire incredibly accurate regardless of what
// our shots initial accuracy was. So instead of trying to compensate down to 0x0, we'll instead try to compensate back to whatever our
// initial offsets were. However, since autofire should be a bit more accurate then single shot (since we're able to "walk" rounds to the
// target) we need to adjust the initial offsets a little, the more rounds we fire.
INT8 iImprovement = __min(100,(INT8)((pShooter->bDoBurst-1) / uiCounterForceFrequency) * (fTracer?gGameCTHConstants.RECOIL_COUNTER_INCREMENT_TRACER:gGameCTHConstants.RECOIL_COUNTER_INCREMENT));
// Add the effects from the weapon and its attachments. A foregrip or bipod are very useful for this.
// Attachment bonuses are applied as a percentage to the accuracy of the shooter.
iModifier = GetCounterForceAccuracyModifier( pWeapon, gAnimControl[ pShooter->usAnimState ].ubHeight );
UINT32 uiCounterForceAccuracy = (UINT32)(iCounterForceAccuracy + ((iCounterForceAccuracy * iModifier) / 100));
// Calculate Ideal X and limit to max force
//FLOAT iIdealCounterForceX = -(bGunRecoilX + (*dMuzzleOffsetX / iDistanceRatio / iRound) );
FLOAT iInitialOffsetX = pShooter->dInitialMuzzleOffsetX;
FLOAT iBestImprovementX = iInitialOffsetX * (((FLOAT)(100-uiCounterForceAccuracy)/gGameCTHConstants.RECOIL_COUNTER_ACCURACY_COMPENSATION)/100.0f);
FLOAT iTargetOffsetX = iInitialOffsetX - (iBestImprovementX * iImprovement / 100);
FLOAT iIdealCounterForceX = -(bGunRecoilX + ((*dMuzzleOffsetX - iTargetOffsetX) / iDistanceRatio / iRound));
// Now add the effect of the AutoWeapons skill. It "bridges" a portion of the gap between shooter's actual accuracy
// and 100% accuracy. For instance, if the divisor is set to 2 in the INI, the first skill level will close 50% of
// the gap, the second skill level closes another 25%.
if(gGameOptions.fNewTraitSystem)
traitLoop = NUM_SKILL_TRAITS( pShooter, AUTO_WEAPONS_NT );
else
traitLoop = NUM_SKILL_TRAITS( pShooter, AUTO_WEAPS_OT );
for (INT32 x = 0; x < traitLoop; x++)
{
INT8 bDifference = 100-uiCounterForceAccuracy;
bDifference = (INT8)(bDifference / gGameCTHConstants.RECOIL_COUNTER_ACCURACY_AUTO_WEAPONS_DIVISOR);
uiCounterForceAccuracy += bDifference;
}
////////////////////////////////////////////////////////////////////
// Sight-range effects
// If we can't see the target, but buddies can see it, CF-Accuracy drops by 50%
// If we can't see the target and neither can buddies, CF-Accuracy drops by 75%
UINT8 ubTargetID = WhoIsThere2( pShooter->sTargetGridNo, pShooter->bTargetLevel ); // Target ubID
INT32 iSightRange = -1;
if (ubTargetID != NOBODY)
{
iSightRange = SoldierToSoldierLineOfSightTest( pShooter, MercPtrs[ubTargetID], TRUE, NO_DISTANCE_LIMIT, pShooter->bAimShotLocation, false );
if (pShooter->aiData.bOppList[ubTargetID] != SEEN_CURRENTLY && gbPublicOpplist[pShooter->bTeam][ubTargetID] == SEEN_CURRENTLY)
{
iSightRange /= 2;
}
else if(pShooter->aiData.bOppList[ubTargetID] != SEEN_CURRENTLY && gbPublicOpplist[pShooter->bTeam][ubTargetID] != SEEN_CURRENTLY)
{
iSightRange /= 4;
}
}
if (iSightRange == -1) // didn't do a bodypart-based test
{
iSightRange = SoldierTo3DLocationLineOfSightTest( pShooter, pShooter->sTargetGridNo, pShooter->bTargetLevel, pShooter->bTargetCubeLevel, TRUE, NO_DISTANCE_LIMIT, false );
iSightRange /= 4;
}
uiCounterForceAccuracy = (UINT32)(uiCounterForceAccuracy * (FLOAT)((FLOAT)iSightRange / uiRange));
// Was last bullet a tracer?
if (fTracer)
{
// Augment by a certain amount, mitigated by range
uiCounterForceAccuracy += (UINT32)gGameCTHConstants.RECOIL_COUNTER_ACCURACY_TRACER_BONUS;
}
// Limit to 0 to 100.
uiCounterForceAccuracy = __max(__min(uiCounterForceAccuracy, 100), 0);
// Invert. 0=good, 100-bad.
uiCounterForceAccuracy = 100-uiCounterForceAccuracy;
// Calculate Ideal Y and limit to max force
//FLOAT iIdealCounterForceY = -(bGunRecoilY + (*dMuzzleOffsetY / iDistanceRatio / iRound) );
FLOAT iInitialOffsetY = pShooter->dInitialMuzzleOffsetY;
FLOAT iBestImprovementY = iInitialOffsetY * (((FLOAT)(100-uiCounterForceAccuracy)/gGameCTHConstants.RECOIL_COUNTER_ACCURACY_COMPENSATION)/100.0f);
FLOAT iTargetOffsetY = iInitialOffsetY - (iBestImprovementY * iImprovement / 100);
FLOAT iIdealCounterForceY = -(bGunRecoilY + ((*dMuzzleOffsetY - iTargetOffsetY) / iDistanceRatio / iRound));
// STEP 4: Find out whether the shooter is over-compensating or under-compensating, and by how much. Higher
// force-accuracy will decrease this deviation, generating a resulting counter-force that's closer to the ideal.
@@ -7795,67 +8002,71 @@ void CalcRecoilOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuz
// Randomize a deviation value.
INT32 uiCounterForceDeviationX = PreRandom(uiCounterForceAccuracy);
// Use as a percentage to the ideal counter force.
FLOAT iCounterForceDeviationX = (FLOAT)((uiCounterForceDeviationX * iIdealCounterForceX) / 100.0);
FLOAT iCounterForceDeviationX = (FLOAT)abs((uiCounterForceDeviationX * iIdealCounterForceX) / 100.0);
// Make sure there's always a little randomness - no one is THAT accurate unless the gun is producing really minimal
// amounts of recoil (or none).
iCounterForceDeviationX = __max(iCounterForceDeviationX, iGunTotalRecoil * gGameCTHConstants.RECOIL_COUNTER_ACCURACY_MIN_ERROR);
iCounterForceDeviationX = __max(iCounterForceDeviationX, abs(iIdealCounterForceX * gGameCTHConstants.RECOIL_COUNTER_ACCURACY_MIN_ERROR));
// Determine whether we're under- or over-compensating.
INT8 bUpDownX = PreRandom(2)?(1):(-1);
// A merc's current offset and skill (in the form of CFA) should give the merc some level of control when determining whether we
// over or under compensate. If a merc can "see" that he's been undercompensating too much, he's much more likely to overcompensate
// and vice versa
INT8 bUpDownX;
if(*dMuzzleOffsetX != 0 && PreRandom(100) <= (100-uiCounterForceAccuracy))
{ //merc realizes he's over/under compensated too much
// Current offset is high so merc is more likely to overcompensate
if(*dMuzzleOffsetX > 0)
bUpDownX = PreRandom(3)?(-1):(1);
// Current offset is low so merc is more likely to undercompensate
else if(*dMuzzleOffsetX < 0)
bUpDownX = PreRandom(3)?(1):(-1);
}
else
{ //merc doesn't realize he's over/under compensating
bUpDownX = PreRandom(2)?(1):(-1);
}
iCounterForceDeviationX *= bUpDownX;
// So now we have the ideal amount, and the randomal deviation from that amount. Let's add them up.
iAppliedCounterForceX = iIdealCounterForceX + iCounterForceDeviationX;
// Limit to the maximum applied force. Our shooter cannot exert more force than his personal maximum.
iAppliedCounterForceX = __min(iAppliedCounterForceX, iCounterForceMax);
//////////////////////////
// CALCULATE FOR Y
// Randomize a deviation value.
INT32 uiCounterForceDeviationY = PreRandom(uiCounterForceAccuracy);
// Use as a percentage to the ideal counter force.
FLOAT iCounterForceDeviationY = (FLOAT)((uiCounterForceDeviationY * iIdealCounterForceY) / 100.0);
FLOAT iCounterForceDeviationY = (FLOAT)abs((uiCounterForceDeviationY * iIdealCounterForceY) / 100.0);
// Make sure there's always a little randomness - no one is THAT accurate unless the gun is producing really minimal
// amounts of recoil (or none).
iCounterForceDeviationY = __max(iCounterForceDeviationY, __min(1, iGunTotalRecoil));
iCounterForceDeviationY = __max(iCounterForceDeviationY, abs(iIdealCounterForceY * gGameCTHConstants.RECOIL_COUNTER_ACCURACY_MIN_ERROR));
// Determine whether we're under- or over-compensating.
INT8 bUpDownY = PreRandom(2)?(1):(-1);
// A merc's current offset and skill (in the form of CFA) should give the merc some level of control when determining whether we
// over or under compensate. If a merc can "see" that he's been undercompensating too much, he's much more likely to overcompensate
// and vice versa
INT8 bUpDownY;
if(*dMuzzleOffsetY != 0 && PreRandom(100) <= (100-uiCounterForceAccuracy))
{ //merc realizes he's over/under compensated too much
// Current offset is high so merc is more likely to overcompensate
if(*dMuzzleOffsetY > 0)
bUpDownY = PreRandom(3)?(-1):(1);
// Current offset is low so merc is more likely to undercompensate
else if(*dMuzzleOffsetY < 0)
bUpDownY = PreRandom(3)?(1):(-1);
}
else
{ //merc doesn't realize he's over/under compensating
bUpDownY = PreRandom(2)?(1):(-1);
}
iCounterForceDeviationY *= bUpDownY;
// So now we have the ideal amount, and the randomal deviation from that amount. Let's add them up.
iAppliedCounterForceY = iIdealCounterForceY + iCounterForceDeviationY;
// Limit to the maximum applied force. Our shooter cannot exert more force than his personal maximum.
iAppliedCounterForceY = __min(iAppliedCounterForceY, iCounterForceMax);
/////////////////////////////
// Transfer unused force from one axis to the other.
if (iAppliedCounterForceX < iCounterForceMax &&
iAppliedCounterForceX > iIdealCounterForceX &&
iAppliedCounterForceY < iIdealCounterForceY )
{
// X is using more counter force than it actually needs. Y is not using as much force as it needs.
// Find out how much remainder force we can transfer to Y, and do so.
FLOAT iRemainder = iAppliedCounterForceX - iIdealCounterForceX;
iAppliedCounterForceX -= iRemainder;
iAppliedCounterForceY = __min(iCounterForceMax, __min(iIdealCounterForceY, iAppliedCounterForceY + iRemainder));
}
else if (iAppliedCounterForceY < iCounterForceMax &&
iAppliedCounterForceY > iIdealCounterForceY &&
iAppliedCounterForceX < iIdealCounterForceX )
{
// Y is using more counter force than it actually needs. X is not using as much force as it needs.
// Find out how much remainder force we can transfer to X, and do so.
FLOAT iRemainder = iAppliedCounterForceY - iIdealCounterForceY;
iIdealCounterForceY -= iRemainder;
iAppliedCounterForceX = __min(iCounterForceMax, __min(iIdealCounterForceX, iAppliedCounterForceX + iRemainder));
}
/////////////////////////////
// Use pythagorean to scale this to the max force allowed.
// We want to use pythagorean here so that we calculate the total "vector length" of recoil and compare that to CFM
FLOAT iTotalAppliedCounterForce = sqrt((iAppliedCounterForceX*iAppliedCounterForceX) + (iAppliedCounterForceY*iAppliedCounterForceY));
if (iTotalAppliedCounterForce > iCounterForceMax)
{
@@ -7866,16 +8077,7 @@ void CalcRecoilOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuz
iAppliedCounterForceY /= iRatio;
}
}
// Make sure it's the correct direction compared to where the gun is pulling.
if (dNextOffsetX > 0)
{
iAppliedCounterForceX *= (-1);
}
if (dNextOffsetY > 0)
{
iAppliedCounterForceY *= (-1);
}
// This works because sqrt((iACFX^2)+(iACFY^2)) should result in being less then or equal to CFM
// Record how much counter force was applied this time. It will be used for the next few shots until the
// shooter can recalculate.
+6 -1
View File
@@ -215,12 +215,17 @@ extern INT32 GetSpreadPattern( OBJECTTYPE * pObj );
// which completely redesigns the way we calculate and handle CTH for the purposes of firing weapons.
void AdjustTargetCenterPoint( SOLDIERTYPE *pShooter, INT32 iTargetGridNo, FLOAT *dEndX, FLOAT *dEndY, FLOAT *dEndZ, OBJECTTYPE *pWeapon, UINT32 uiMuzzleSway, INT16 *sApertureRatio );
FLOAT CalcMagFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2DDistance, UINT8 ubAimTime );
FLOAT CalcProjectionFactor( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT d2DDistance, UINT8 ubAimTime );
FLOAT CalcBasicAperture();
void CalcTargetMovementOffset( SOLDIERTYPE *pShooter, SOLDIERTYPE *pTarget, OBJECTTYPE *pWeapon, FLOAT *dMuzzleOffsetX, DOUBLE ddShootingAngle, INT32 iAperture );
void CalcRangeCompensationOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetY, INT32 iRangeToTarget, OBJECTTYPE *pWeapon );
void CalcMuzzleSway( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzleOffsetY, FLOAT iAperture );
void CalcBulletDeviation( SOLDIERTYPE *pShooter, FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, OBJECTTYPE *pWeapon, UINT32 uiRange );
FLOAT CalcBulletDeviation( SOLDIERTYPE *pShooter, FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, OBJECTTYPE *pWeapon, UINT32 uiRange );
void LimitImpactPointByFacing( SOLDIERTYPE *pShooter, SOLDIERTYPE *pTarget, FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FLOAT *dEndX, FLOAT *dEndY );
void LimitImpactPointToMaxAperture( FLOAT *dShotOffsetX, FLOAT *dShotOffsetY, FLOAT dDistanceAperture );
UINT32 CalcCounterForceFrequency(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon);
FLOAT CalcCounterForceMax(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, UINT8 uiStance = 0);
UINT32 CalcCounterForceAccuracy(SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, UINT32 uiRange, BOOLEAN fTracer, bool fAnticipate = false);
void CalcPreRecoilOffset( SOLDIERTYPE *pShooter, OBJECTTYPE *pWeapon, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzleOffsetY, UINT32 uiRange );
void CalcRecoilOffset( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzleOffsetY, OBJECTTYPE *pWeapon, UINT32 uiRange );
+6 -2
View File
@@ -479,7 +479,9 @@ void HandleHeliDrop( )
for ( cnt = gbCurDrop; cnt < gbNumHeliSeatsOccupied; cnt++ )
{
// Add merc to sector
MercPtrs[ gusHeliSeats[ cnt ] ]->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
//MercPtrs[ gusHeliSeats[ cnt ] ]->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
MercPtrs[ gusHeliSeats[ cnt ] ]->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
MercPtrs[ gusHeliSeats[ cnt ] ]->usStrategicInsertionData = gGameExternalOptions.iInitialMercArrivalLocation;
// HEADROCK HAM 3.5: Externalized!
UpdateMercInSector( MercPtrs[ gusHeliSeats[ cnt ] ], gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ );
@@ -615,7 +617,9 @@ void HandleHeliDrop( )
MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->EVENT_InitNewSoldierAnim( HELIDROP, 0 , FALSE );
// Change insertion code
MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
//MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->usStrategicInsertionData = gGameExternalOptions.iInitialMercArrivalLocation;
// HEADROCK HAM 3.5: Externalized!
UpdateMercInSector( MercPtrs[ gusHeliSeats[ gbCurDrop ] ], gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ );
+3 -1
View File
@@ -385,7 +385,9 @@ void MercArrivesCallback( UINT8 ubSoldierID )
else
{
// OK, otherwise, set them in north area, so once we load again, they are here.
pSoldier->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
//pSoldier->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
pSoldier->usStrategicInsertionData = gGameExternalOptions.iInitialMercArrivalLocation;
}
if ( pSoldier->ubStrategicInsertionCode != INSERTION_CODE_CHOPPER )
+1 -1
View File
@@ -2870,7 +2870,7 @@ BOOLEAN HandleAtNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving )
pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection );
SetFactTrue( FACT_SKYRIDER_CLOSE_TO_CHOPPER );
TriggerNPCRecord( SKYRIDER, 15 );
SetUpHelicopterForPlayer( 13, MAP_ROW_B );
SetUpHelicopterForPlayer( 13, MAP_ROW_B, SKYRIDER );
}
break;
+95 -18
View File
@@ -1217,6 +1217,14 @@ INT16 CalcAPsToBurstNoModifier( INT16 bBaseActionPoints, OBJECTTYPE * pObj )
INT16 CalcAPsToAutofire( INT16 bBaseActionPoints, OBJECTTYPE * pObj, UINT8 bDoAutofire )
{
//CHRISL: We send the actual number of rounds being fired in the bDoAutofire paramter. But that implies that it would take longer to fire the first round
// in an autofire sequence then it would take to fire a single round during a single fire sequence. That doesn't make any sense. It should only cost
// additional APs to fire rounds beyond the first in an autofire sequence. But rather then mess with all the locations that call this function, I'm going
// to simply adjust the parameter once we get to the function.
if(bDoAutofire > 1)
bDoAutofire -= 1;
else
return 0;
// INT8 bAttachPos;
INT32 aps=APBPConstants[AP_MAXIMUM] + 1;
if ( GetAutofireShotsPerFiveAPs (pObj) )
@@ -1340,7 +1348,7 @@ INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTur
// If the weapon has a scope, and the target is within eligible range for scope use
if ( (UsingNewCTHSystem() == false && IsScoped(&pSoldier->inv[HANDPOS]) && GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo ) >= GetMinRangeForAimBonus(&pSoldier->inv[HANDPOS]))
|| (UsingNewCTHSystem() == true && GetBestScopeMagnificationFactor(&pSoldier->inv[HANDPOS], GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo ) > 1.0 )) )
|| (UsingNewCTHSystem() == true && GetBestScopeMagnificationFactor(pSoldier, &pSoldier->inv[HANDPOS], (FLOAT)GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo ) > 1.0 )) )
{
// Add an individual cost for EACH click, as necessary.
@@ -1359,7 +1367,7 @@ INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTur
if (bAimTime > 6)
sAPCost += APBPConstants[AP_SEVENTH_CLICK_AIM_SCOPE];
if (bAimTime > 7)
sAPCost += APBPConstants[AP_EIGHTTH_CLICK_AIM_SCOPE];
sAPCost += APBPConstants[AP_EIGHTH_CLICK_AIM_SCOPE];
}
// Weapon has no scope or not within requried range. Apply regular AP costs.
@@ -2844,31 +2852,58 @@ INT16 GetAPsToClimbRoof( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown )
return(iAPsToClimb);
}
INT16 GetAPsToJumpThroughWindows( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown )
INT16 GetAPsToJumpWall( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown )
{
//return( GetAPsToChangeStance( pSoldier, ANIM_STAND ) + APBPConstants[AP_JUMPWINDOW] );
// SANDRO - STOMP traits - added a feature to reduce APs needed to jump through window for Martial Arts trait
UINT16 iAPsToJump = 0;
if ( HAS_SKILL_TRAIT( pSoldier, MARTIAL_ARTS_NT ) && gGameOptions.fNewTraitSystem )
iAPsToJump = max( 1, (INT16)(( APBPConstants[AP_JUMPWINDOW] * ( 100 - gSkillTraitValues.ubMAAPsClimbOrJumpReduction * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT )) / 100) + 0.5)); // -25% per trait
else
iAPsToJump = APBPConstants[AP_JUMPWINDOW];
// SANDRO - STOMP traits - added a feature to reduce APs needed to climb on or off roof for Martial Arts trait
UINT16 iAPsToClimb = 0;
if ( !fClimbDown )
{
if ( HAS_SKILL_TRAIT( pSoldier, MARTIAL_ARTS_NT ) && gGameOptions.fNewTraitSystem )
iAPsToClimb = max( 1, (INT16)((APBPConstants[AP_JUMPWALL] * ( 100 - gSkillTraitValues.ubMAAPsClimbOrJumpReduction * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT )) / 100) + 0.5)); // -25% per trait
else
iAPsToClimb = APBPConstants[AP_JUMPWALL];
// OK, add aps to goto stand stance...
iAPsToJump += GetAPsToChangeStance( pSoldier, ANIM_STAND );
iAPsToClimb += GetAPsToChangeStance( pSoldier, ANIM_STAND );
}
else
{
if ( HAS_SKILL_TRAIT( pSoldier, MARTIAL_ARTS_NT ) && gGameOptions.fNewTraitSystem )
iAPsToClimb = max( 1, (INT16)((APBPConstants[AP_JUMPOFFWALL] * ( 100 - gSkillTraitValues.ubMAAPsClimbOrJumpReduction * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT )) / 100) + 0.5)); // -25% per trait
else
iAPsToClimb = APBPConstants[AP_JUMPOFFWALL];
// Add aps to goto crouch
iAPsToJump += GetAPsToChangeStance( pSoldier, ANIM_CROUCH );
iAPsToClimb += GetAPsToChangeStance( pSoldier, ANIM_CROUCH );
}
return( iAPsToJump );
// A check if we don't go to zero somehow - SANDRO
if( iAPsToClimb < 1 )
iAPsToClimb = 1;
// return our value
return(iAPsToClimb);
}
INT16 GetAPsToJumpThroughWindows( SOLDIERTYPE *pSoldier, BOOLEAN fWithBackpack )
{
// STOMP traits - Martial Arts reduce APs spent for jumping obstacles
if ( !fWithBackpack )
{
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, MARTIAL_ARTS_NT ))
return( max( 1, (INT16)((APBPConstants[AP_JUMPWINDOW] * ( 100 - gSkillTraitValues.ubMAAPsClimbOrJumpReduction * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT )) / 100) + 0.5 ))); // -25% per trait
else
return( APBPConstants[AP_JUMPWINDOW] );
}
else
{
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, MARTIAL_ARTS_NT ))
return( max( 1, (INT16)((APBPConstants[AP_JUMPWINDOW] * ( 100 - gSkillTraitValues.ubMAAPsClimbOrJumpReduction * NUM_SKILL_TRAITS( pSoldier, MARTIAL_ARTS_NT )) / 100) + 0.5 ))); // -25% per trait
else
return( APBPConstants[AP_JUMPWINDOW] );
}
}
INT16 GetBPsToClimbRoof( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown )
@@ -2913,6 +2948,26 @@ INT16 GetAPsToJumpFence( SOLDIERTYPE *pSoldier, BOOLEAN fWithBackpack )
}
}
INT16 GetBPsToJumpWall( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown )
{
// SANDRO - STOMP traits - Athletics reduce breath points spent for moving
if ( !fClimbDown )
{
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, ATHLETICS_NT ))
return( APBPConstants[BP_JUMPWALL] * (100 - gSkillTraitValues.ubATBPsMovementReduction) / 100 );
else
return( APBPConstants[BP_JUMPWALL] );
}
else
{
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, ATHLETICS_NT ))
return( APBPConstants[BP_JUMPOFFWALL] * (100 - gSkillTraitValues.ubATBPsMovementReduction) / 100 );
else
return( APBPConstants[BP_JUMPOFFWALL] );
}
}
// SANDRO - added function to calculate BPs for jumping over fence
INT16 GetBPsToJumpFence( SOLDIERTYPE *pSoldier, BOOLEAN fWithBackpack )
{
@@ -2934,6 +2989,28 @@ INT16 GetBPsToJumpFence( SOLDIERTYPE *pSoldier, BOOLEAN fWithBackpack )
}
}
// SANDRO - added function to calculate BPs for jumping over fence
INT16 GetBPsToJumpThroughWindows( SOLDIERTYPE *pSoldier, BOOLEAN fWithBackpack )
{
// STOMP traits - Athletics reduce breath points spent for moving
if ( !fWithBackpack )
{
// WANNE: Yes, we use the jumpfence BPs, it is simpler for now :)
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, ATHLETICS_NT ))
return( APBPConstants[BP_JUMPFENCE] * (100 - gSkillTraitValues.ubATBPsMovementReduction) / 100 );
else
return( APBPConstants[BP_JUMPFENCE] );
}
else
{
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pSoldier, ATHLETICS_NT ))
return( APBPConstants[BP_JUMPFENCEBPACK] * (100 - gSkillTraitValues.ubATBPsMovementReduction) / 100 );
else
return( APBPConstants[BP_JUMPFENCEBPACK] );
}
}
INT16 GetAPsToCutFence( SOLDIERTYPE *pSoldier )
{
// OK, it's normally just cost, but add some if different stance...
@@ -3246,7 +3323,7 @@ INT32 CalcAPCostForAiming( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bAim
// If the weapon has a scope, and the target is within eligible range for scope use
if ( (UsingNewCTHSystem() == false && IsScoped(&pSoldier->inv[HANDPOS]) && GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sTargetGridNo ) >= GetMinRangeForAimBonus(&pSoldier->inv[HANDPOS]))
|| (UsingNewCTHSystem() == true && GetBestScopeMagnificationFactor(&pSoldier->inv[HANDPOS], GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sTargetGridNo ) > 1.0 )))
|| (UsingNewCTHSystem() == true && GetBestScopeMagnificationFactor(pSoldier, &pSoldier->inv[HANDPOS], (FLOAT)GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sTargetGridNo ) > 1.0 )))
{
// Add an individual cost for EACH click, as necessary.
@@ -3265,7 +3342,7 @@ INT32 CalcAPCostForAiming( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo, INT8 bAim
if (bAimTime > 6)
sAPCost += APBPConstants[AP_SEVENTH_CLICK_AIM_SCOPE];
if (bAimTime > 7)
sAPCost += APBPConstants[AP_EIGHTTH_CLICK_AIM_SCOPE];
sAPCost += APBPConstants[AP_EIGHTH_CLICK_AIM_SCOPE];
}
// Weapon has no scope or not within requried range. Apply regular AP costs.
+7 -2
View File
@@ -270,7 +270,7 @@
#define DEFAULT_APS 20
#define DEFAULT_AIMSKILL 80
*/
*/
//Just so the compiler will be able to use it in init.cpp, I'm a careful person. Gotthard 1/18/07
extern INT16 APBPConstants[TOTAL_APBP_VALUES];
@@ -330,7 +330,9 @@ INT16 GetAPsToReadyWeapon( SOLDIERTYPE *pSoldier, UINT16 usAnimState );
INT16 GetAPsToClimbRoof( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown );
INT16 GetBPsToClimbRoof( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown );
INT16 GetAPsToJumpThroughWindows( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown ); //Jump
INT16 GetAPsToJumpThroughWindows( SOLDIERTYPE *pSoldier, BOOLEAN fWithBackpack ); //Jump
INT16 GetBPsToJumpThroughWindows( SOLDIERTYPE *pSoldier, BOOLEAN fWithBackpack ); //Jump
// SANDRO - changed these 2
INT16 GetAPsToJumpFence( SOLDIERTYPE *pSoldier, BOOLEAN fWithBackpack );
INT16 GetBPsToJumpFence( SOLDIERTYPE *pSoldier, BOOLEAN fWithBackpack );
@@ -376,4 +378,7 @@ INT16 GetAPsToUntrapDoor( SOLDIERTYPE *pSoldier );
INT16 GetBasicAPsToPickupItem( SOLDIERTYPE *pSoldier );
INT16 GetAPsToDisarmMine( SOLDIERTYPE *pSoldier );
INT16 GetAPsToJumpWall( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown );
INT16 GetBPsToJumpWall( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown );
#endif
+17 -87
View File
@@ -1834,97 +1834,29 @@ void QueryRTX1Button( UINT32 *puiNewEvent )
{
fX1ButtonDown = FALSE;
if ( !_KeyDown( ALT ) && !_KeyDown( SHIFT ))
{
UIHandleChangeLevel( NULL );
}
else if( _KeyDown( SHIFT ) )
{
// WANNE: Jump through window?
if (gGameExternalOptions.fCanJumpThroughWindows == TRUE )
{
INT8 bDirection;
SOLDIERTYPE *lSoldier;
//dddokno êîä äëÿ îòëàäêè ïðûæêîâ ÷åðåç îêíî============================================={
//INT16 sGridNo;
//STRUCTURE * pStructure;
//
//GetMouseMapPos( &sGridNo );
//ScreenMsg( FONT_MCOLOR_LTYELLOW,0, L"gubMerkCanSeeThisTile=%d,gubWorldTileInLight=%d",gubMerkCanSeeThisTile[sGridNo],gubWorldTileInLight[sGridNo]);
//pStructure = gpWorldLevelData[sGridNo].pStructureHead;
//
//SOLDIERTYPE *pSoldier;
//GetSoldier( &pSoldier, gusSelectedSoldier );
//
//LEVELNODE *pNode = NULL; UINT32 uiTileType=0;
//pNode = gpWorldLevelData[ sGridNo ].pStructHead;
//
//GetTileType( pNode->usIndex, &uiTileType );
//
//CHAR8 errorBuf[511];
//
//sprintf(errorBuf, "Tile=%s at line %d",
//gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiTileType ], uiTileType);
//LiveMessage(errorBuf);
//if ( _stricmp( gTilesets[ giCurrentTilesetID ].TileSurfaceFilenames[ uiTileType ], "build_13.sti" ) == 0 )
//{
// UINT16 sNewIndex;
// GetTileIndexFromTypeSubIndex( gTileDatabase[ pNode->usIndex ].fType, uiTileType, (UINT16 *)&sNewIndex );
// //GetTileIndexFromTypeSubIndex( STRUCTURE_WALLNWINDOW, uiTileType, (UINT16 *)&sNewIndex );
//
// ScreenMsg( FONT_MCOLOR_LTYELLOW,0, L"13 found=%d,strID=%d",sNewIndex,pNode->usIndex);
//
// UINT16 pusSubIndex;
// GetSubIndexFromTileIndex( pNode->usIndex, (UINT16 *)&pusSubIndex );
// ScreenMsg( FONT_MCOLOR_LTYELLOW,0, L"subidx=%d",pusSubIndex);
// sprintf(errorBuf, "subidx= %d", pusSubIndex);
//LiveMessage(errorBuf);
//STRUCTURE *pBase;
//UINT16 pusSubIndex;
//pBase = FindStructure( sGridNo, STRUCTURE_WALLNWINDOW );
//pNode = FindLevelNodeBasedOnStructure( pBase->sGridNo, pBase );
//GetSubIndexFromTileIndex( pNode->usIndex, (UINT16 *)&pusSubIndex );
//ScreenMsg( FONT_MCOLOR_LTYELLOW,0, L"subidx=%d",pusSubIndex);
//}
//dddokno êîä äëÿ îòëàäêè ïðûæêîâ ÷åðåç îêíî============================================= }
//dddokno{
// ñòàðûé êîä îò ñêîðïèîíà. óäàëèòü çà íåíàäîáíîñòüþ--------------------------------------
//SOLDIERTYPE *pjSoldier;
//BOOLEAN fNearHeigherLevel;
//BOOLEAN fNearLowerLevel;
//INT8 bDirection;
//if ( GetSoldier( &pjSoldier, gusSelectedSoldier ) )
//{
// // CHRISL: Turn off manual jumping while wearing a backpack
// if(UsingNewInventorySystem() == true && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
// return;
// // Make sure the merc is not collapsed!
// if (!IsValidStance(pjSoldier, ANIM_CROUCH) )
// {
// if ( pjSoldier->bCollapsed && pjSoldier->bBreath < OKBREATH )
// {
// ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 4 ], pjSoldier->name );
// }
// return;
// }
//GetMercOknoDirection( pjSoldier->ubID, &fNearLowerLevel, &fNearHeigherLevel );
//if ( FindOknoDirection( pjSoldier, pjSoldier->sGridNo, pjSoldier->ubDirection, &bDirection ) )
// {
// BeginSoldierOkno( pjSoldier );
// }
//}
//dddokno{
// ñòàðûé êîä îò ñêîðïèîíà. óäàëèòü çà íåíàäîáíîñòüþ-------------------------------------
if ( GetSoldier( &lSoldier, gusSelectedSoldier ) )
{
if ( FindWindowJumpDirection( lSoldier, lSoldier->sGridNo, lSoldier->ubDirection, &bDirection ) )
{
lSoldier->BeginSoldierClimbWindow( );
}
}
}
}
else if (_KeyDown( ALT ) )
{
// Climb on roofs
SOLDIERTYPE *pjSoldier;
if ( GetSoldier( &pjSoldier, gusSelectedSoldier ) )
{
@@ -1954,9 +1886,7 @@ void QueryRTX1Button( UINT32 *puiNewEvent )
if ( FindFenceJumpDirection( pjSoldier, pjSoldier->sGridNo, pjSoldier->ubDirection, &bDirection ) )
pjSoldier->BeginSoldierClimbFence( );
}
}//else
}
}
}
}
+128 -38
View File
@@ -53,7 +53,8 @@
#include "Soldier Create.h"
#include "PATHAI.h"
#include "Points.h"
#include "InterfaceItemImages.h"
#include "InterfaceItemImages.h"
#include "Interface Enhanced.h"
#endif
#include "BuildDefines.h"
@@ -1047,10 +1048,11 @@ ATM:
//Evaluate:
EnableDisableShopkeeperButtons(SHOPKEEPER_SCREEN, ACTIVATE_BUTTON);
// guiSKI_EvaluateButtonImage = LoadButtonImage("INTERFACE\\TradeButtons.sti", -1,0,-1,1,-1 );
// guiSKI_TransactionButtonImage = UseLoadedButtonImage( guiSKI_EvaluateButtonImage, -1,0,-1,1,-1 );
guiSKI_TransactionButtonImage = LoadButtonImage("INTERFACE\\TradeButtons.sti", -1,0,-1,1,-1 );
guiSKI_DoneButtonImage = UseLoadedButtonImage( guiSKI_TransactionButtonImage, -1,0,-1,1,-1 );
//guiSKI_TransactionButtonImage = LoadButtonImage("INTERFACE\\TradeButtons.sti", -1,0,-1,1,-1 );
//guiSKI_DoneButtonImage = UseLoadedButtonImage( guiSKI_TransactionButtonImage, -1,0,-1,1,-1 );
/*
//Evaluate:
@@ -1065,30 +1067,30 @@ ATM:
*/
//Transaction button
guiSKI_TransactionButton = CreateIconAndTextButton( guiSKI_TransactionButtonImage, SKI_Text[SKI_TEXT_TRANSACTION], SKI_BUTTON_FONT,
SKI_BUTTON_COLOR, DEFAULT_SHADOW,
SKI_BUTTON_COLOR, DEFAULT_SHADOW,
TEXT_CJUSTIFIED,
SKI_TRANSACTION_BUTTON_X, SKI_TRANSACTION_BUTTON_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnSKI_TransactionButtonCallback);
SpecifyDisabledButtonStyle( guiSKI_TransactionButton, DISABLED_STYLE_HATCHED );
//guiSKI_TransactionButton = CreateIconAndTextButton( guiSKI_TransactionButtonImage, SKI_Text[SKI_TEXT_TRANSACTION], SKI_BUTTON_FONT,
// SKI_BUTTON_COLOR, DEFAULT_SHADOW,
// SKI_BUTTON_COLOR, DEFAULT_SHADOW,
// TEXT_CJUSTIFIED,
// SKI_TRANSACTION_BUTTON_X, SKI_TRANSACTION_BUTTON_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
// DEFAULT_MOVE_CALLBACK, BtnSKI_TransactionButtonCallback);
//SpecifyDisabledButtonStyle( guiSKI_TransactionButton, DISABLED_STYLE_HATCHED );
//if the dealer repairs, use the repair fast help text for the transaction button
if( armsDealerInfo[ gbSelectedArmsDealerID ].ubTypeOfArmsDealer == ARMS_DEALER_REPAIRS )
SetButtonFastHelpText( guiSKI_TransactionButton, SkiMessageBoxText[ SKI_REPAIR_TRANSACTION_BUTTON_HELP_TEXT ] );
else
SetButtonFastHelpText( guiSKI_TransactionButton, SkiMessageBoxText[ SKI_TRANSACTION_BUTTON_HELP_TEXT ] );
//if( armsDealerInfo[ gbSelectedArmsDealerID ].ubTypeOfArmsDealer == ARMS_DEALER_REPAIRS )
// SetButtonFastHelpText( guiSKI_TransactionButton, SkiMessageBoxText[ SKI_REPAIR_TRANSACTION_BUTTON_HELP_TEXT ] );
//else
// SetButtonFastHelpText( guiSKI_TransactionButton, SkiMessageBoxText[ SKI_TRANSACTION_BUTTON_HELP_TEXT ] );
//Done button
guiSKI_DoneButton = CreateIconAndTextButton( guiSKI_DoneButtonImage, SKI_Text[SKI_TEXT_DONE], SKI_BUTTON_FONT,
SKI_BUTTON_COLOR, DEFAULT_SHADOW,
SKI_BUTTON_COLOR, DEFAULT_SHADOW,
TEXT_CJUSTIFIED,
SKI_DONE_BUTTON_X, SKI_DONE_BUTTON_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH+10,
DEFAULT_MOVE_CALLBACK, BtnSKI_DoneButtonCallback);
SpecifyDisabledButtonStyle( guiSKI_DoneButton, DISABLED_STYLE_HATCHED );
SetButtonFastHelpText( guiSKI_DoneButton, SkiMessageBoxText[ SKI_DONE_BUTTON_HELP_TEXT ] );
//guiSKI_DoneButton = CreateIconAndTextButton( guiSKI_DoneButtonImage, SKI_Text[SKI_TEXT_DONE], SKI_BUTTON_FONT,
// SKI_BUTTON_COLOR, DEFAULT_SHADOW,
// SKI_BUTTON_COLOR, DEFAULT_SHADOW,
// TEXT_CJUSTIFIED,
// SKI_DONE_BUTTON_X, SKI_DONE_BUTTON_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH+10,
// DEFAULT_MOVE_CALLBACK, BtnSKI_DoneButtonCallback);
//SpecifyDisabledButtonStyle( guiSKI_DoneButton, DISABLED_STYLE_HATCHED );
//SetButtonFastHelpText( guiSKI_DoneButton, SkiMessageBoxText[ SKI_DONE_BUTTON_HELP_TEXT ] );
//Blanket the entire screen
@@ -1299,9 +1301,9 @@ BOOLEAN ExitShopKeeperInterface()
UnloadButtonImage( guiSKI_InvPageUpButtonImage );
UnloadButtonImage( guiSKI_InvPageDownButtonImage );
UnloadButtonImage( guiSKI_TransactionButtonImage );
//UnloadButtonImage( guiSKI_TransactionButtonImage );
// UnloadButtonImage( guiSKI_EvaluateButtonImage );
UnloadButtonImage( guiSKI_DoneButtonImage );
//UnloadButtonImage( guiSKI_DoneButtonImage );
//loop through the area and delete small faces
for(ubCnt=0; ubCnt<gubNumberMercsInArray; ubCnt++)
@@ -1314,8 +1316,9 @@ BOOLEAN ExitShopKeeperInterface()
//Evaluate:
// RemoveButton( guiSKI_EvaluateButton );
RemoveButton( guiSKI_TransactionButton );
RemoveButton( guiSKI_DoneButton );
EnableDisableShopkeeperButtons(SHOPKEEPER_SCREEN, DEACTIVATE_BUTTON);
//RemoveButton( guiSKI_TransactionButton );
//RemoveButton( guiSKI_DoneButton );
MSYS_RemoveRegion( &gSKI_EntireScreenMouseRegions);
@@ -1373,8 +1376,9 @@ void HandleShopKeeperInterface()
DisableSMPpanelButtonsWhenInShopKeeperInterface( FALSE );
DisableButton( guiSKI_InvPageUpButton );
DisableButton( guiSKI_InvPageDownButton );
DisableButton( guiSKI_TransactionButton );
DisableButton( guiSKI_DoneButton );
EnableDisableShopkeeperButtons(SHOPKEEPER_SCREEN, DISABLE_BUTTON);
//DisableButton( guiSKI_TransactionButton );
//DisableButton( guiSKI_DoneButton );
//make sure the buttons dont render
// ButtonList[ guiSKI_InvPageUpButton ]->uiFlags |= BUTTON_FORCE_UNDIRTY;
@@ -5548,6 +5552,82 @@ void EnableDisableDealersInventoryPageButtons()
}
}
void EnableDisableShopkeeperButtons(UINT32 uiCurrentItemDescriptionScreen, int bpAction)
{
if(uiCurrentItemDescriptionScreen != SHOPKEEPER_SCREEN)
return;
switch (bpAction)
{
case ACTIVATE_BUTTON:
if(guiSKI_TransactionButton != 0)
RemoveButton( guiSKI_TransactionButton );
if(guiSKI_TransactionButtonImage != 0)
UnloadButtonImage( guiSKI_TransactionButtonImage );
if(guiSKI_DoneButton != 0)
RemoveButton( guiSKI_DoneButton );
if(guiSKI_DoneButtonImage != 0)
UnloadButtonImage( guiSKI_DoneButtonImage );
guiSKI_TransactionButtonImage = LoadButtonImage("INTERFACE\\TradeButtons.sti", -1,0,-1,1,-1 );
guiSKI_DoneButtonImage = UseLoadedButtonImage( guiSKI_TransactionButtonImage, -1,0,-1,1,-1 );
guiSKI_TransactionButton = CreateIconAndTextButton( guiSKI_TransactionButtonImage, SKI_Text[SKI_TEXT_TRANSACTION], SKI_BUTTON_FONT,
SKI_BUTTON_COLOR, DEFAULT_SHADOW, SKI_BUTTON_COLOR, DEFAULT_SHADOW, TEXT_CJUSTIFIED,
SKI_TRANSACTION_BUTTON_X, SKI_TRANSACTION_BUTTON_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
DEFAULT_MOVE_CALLBACK, BtnSKI_TransactionButtonCallback);
SpecifyDisabledButtonStyle( guiSKI_TransactionButton, DISABLED_STYLE_HATCHED );
//if the dealer repairs, use the repair fast help text for the transaction button
if( armsDealerInfo[ gbSelectedArmsDealerID ].ubTypeOfArmsDealer == ARMS_DEALER_REPAIRS )
SetButtonFastHelpText( guiSKI_TransactionButton, SkiMessageBoxText[ SKI_REPAIR_TRANSACTION_BUTTON_HELP_TEXT ] );
else
SetButtonFastHelpText( guiSKI_TransactionButton, SkiMessageBoxText[ SKI_TRANSACTION_BUTTON_HELP_TEXT ] );
//Done button
guiSKI_DoneButton = CreateIconAndTextButton( guiSKI_DoneButtonImage, SKI_Text[SKI_TEXT_DONE], SKI_BUTTON_FONT,
SKI_BUTTON_COLOR, DEFAULT_SHADOW, SKI_BUTTON_COLOR, DEFAULT_SHADOW, TEXT_CJUSTIFIED,
SKI_DONE_BUTTON_X, SKI_DONE_BUTTON_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH+10,
DEFAULT_MOVE_CALLBACK, BtnSKI_DoneButtonCallback);
SpecifyDisabledButtonStyle( guiSKI_DoneButton, DISABLED_STYLE_HATCHED );
SetButtonFastHelpText( guiSKI_DoneButton, SkiMessageBoxText[ SKI_DONE_BUTTON_HELP_TEXT ] );
break;
case DEACTIVATE_BUTTON:
if(guiSKI_TransactionButton != 0)
RemoveButton( guiSKI_TransactionButton );
if(guiSKI_DoneButton != 0)
RemoveButton( guiSKI_DoneButton );
EnableDisableShopkeeperButtons(uiCurrentItemDescriptionScreen, UNLOAD_BUTTON);
guiSKI_TransactionButtonImage = 0;
guiSKI_TransactionButton = 0;
guiSKI_DoneButtonImage = 0;
guiSKI_DoneButton = 0;
break;
case ENABLE_BUTTON:
if(guiSKI_TransactionButton == 0 || guiSKI_DoneButton == 0)
{
EnableDisableShopkeeperButtons(uiCurrentItemDescriptionScreen, DEACTIVATE_BUTTON);
EnableDisableShopkeeperButtons(uiCurrentItemDescriptionScreen, ACTIVATE_BUTTON);
}
if(guiSKI_TransactionButton != 0)
EnableButton( guiSKI_TransactionButton );
if(guiSKI_DoneButton != 0)
EnableButton( guiSKI_DoneButton );
break;
case DISABLE_BUTTON:
if(guiSKI_TransactionButton != 0)
DisableButton( guiSKI_TransactionButton );
if(guiSKI_DoneButton != 0)
DisableButton( guiSKI_DoneButton );
break;
case UNLOAD_BUTTON:
if(guiSKI_TransactionButtonImage != 0)
UnloadButtonImage( guiSKI_TransactionButtonImage );
if(guiSKI_DoneButtonImage != 0)
UnloadButtonImage( guiSKI_DoneButtonImage );
break;
}
}
void EnableDisableEvaluateAndTransactionButtons()
{
UINT8 ubCnt;
@@ -5659,8 +5739,9 @@ void EnableDisableEvaluateAndTransactionButtons()
{
//Evaluate:
// DisableButton( guiSKI_EvaluateButton );
DisableButton( guiSKI_TransactionButton );
DisableButton( guiSKI_DoneButton );
EnableDisableShopkeeperButtons(SHOPKEEPER_SCREEN, DISABLE_BUTTON);
//DisableButton( guiSKI_TransactionButton );
//DisableButton( guiSKI_DoneButton );
}
else
{
@@ -6363,9 +6444,16 @@ void InitShopKeeperItemDescBox( OBJECTTYPE *pObject, UINT16 ubPocket, UINT8 ubFr
UINT16 ubSelectedInvSlot = ubPocket - gSelectArmsDealerInfo.ubFirstItemIndexOnPage;
sPosX = SKI_ARMS_DEALERS_INV_START_X; // + ( SKI_INV_OFFSET_X * ( ubSelectedInvSlot % SKI_NUM_ARMS_DEALERS_INV_COLS ) - ( 358 / 2 ) ) + SKI_INV_SLOT_WIDTH / 2;
sPosY = SKI_ARMS_DEALERS_INV_START_Y; // + ( ( SKI_INV_OFFSET_Y * ubSelectedInvSlot / SKI_NUM_ARMS_DEALERS_INV_COLS ) + 1 ) - ( 128 / 2 ) + SKI_INV_SLOT_HEIGHT / 2;
if(gGameSettings.fOptions[ TOPTION_ENHANCED_DESC_BOX ] == FALSE)
{
sPosX = SKI_ARMS_DEALERS_INV_START_X; // + ( SKI_INV_OFFSET_X * ( ubSelectedInvSlot % SKI_NUM_ARMS_DEALERS_INV_COLS ) - ( 358 / 2 ) ) + SKI_INV_SLOT_WIDTH / 2;
sPosY = SKI_ARMS_DEALERS_INV_START_Y; // + ( ( SKI_INV_OFFSET_Y * ubSelectedInvSlot / SKI_NUM_ARMS_DEALERS_INV_COLS ) + 1 ) - ( 128 / 2 ) + SKI_INV_SLOT_HEIGHT / 2;
}
else
{
sPosX = SCREEN_X_OFFSET + 2;
sPosY = SCREEN_Y_OFFSET + 146;
}
//if the start position + the height of the box is off the screen, reposition
if( sPosY < (0 + SCREEN_Y_OFFSET) )
@@ -6460,8 +6548,9 @@ void StartSKIDescriptionBox( void )
DisableButton( guiSKI_InvPageUpButton );
DisableButton( guiSKI_InvPageDownButton );
// DisableButton( guiSKI_EvaluateButton );
DisableButton( guiSKI_TransactionButton );
DisableButton( guiSKI_DoneButton );
EnableDisableShopkeeperButtons(SHOPKEEPER_SCREEN, DISABLE_BUTTON);
//DisableButton( guiSKI_TransactionButton );
//DisableButton( guiSKI_DoneButton );
/*
for (iCnt = 0; iCnt < NUM_SKI_ATM_BUTTONS; iCnt++)
DisableButton( guiSKI_AtmButton[ iCnt ] );
@@ -6509,8 +6598,9 @@ void DeleteShopKeeperItemDescBox()
EnableButton( guiSKI_InvPageUpButton );
EnableButton( guiSKI_InvPageDownButton );
EnableButton( guiSKI_TransactionButton );
EnableButton( guiSKI_DoneButton );
EnableDisableShopkeeperButtons(SHOPKEEPER_SCREEN, ENABLE_BUTTON);
//EnableButton( guiSKI_TransactionButton );
//EnableButton( guiSKI_DoneButton );
EnableDisableDealersInventoryPageButtons();
EnableDisableEvaluateAndTransactionButtons();
@@ -7588,7 +7678,7 @@ void BuildDoneWhenTimeString( CHAR16 sString[], UINT8 ubArmsDealer, INVENTORY_IN
for (DealerItemList::iterator iter = gArmsDealersInventory[ubArmsDealer].begin();
iter != gArmsDealersInventory[ubArmsDealer].end(); ++iter) {
if (iter->ItemIsInInventory() == true && iter->IsUnderRepair() == true) {
if (pObject->ItemObject == iter->object) {
if (pObject->ItemObject == iter->object && pObject->uiRepairDoneTime == iter->uiRepairDoneTime) {
pSpecial = &(*iter);
break;
}
+1 -1
View File
@@ -118,7 +118,7 @@ bool RepairmanItemQsortCompare(INVENTORY_IN_SLOT& pInvSlot1, INVENTORY_IN_SLOT&
void EnterShopKeeperInterfaceScreen( UINT8 ubArmsDealer );
void EnableDisableShopkeeperButtons(UINT32 uiCurrentItemDescriptionScreen, int bpAction);
void DrawHatchOnInventory( UINT32 uiSurface, UINT16 usPosX, UINT16 usPosY, UINT16 usWidth, UINT16 usHeight, UINT16 usColor = 0 );
BOOLEAN ShouldSoldierDisplayHatchOnItem( UINT8 ubProfileID, INT16 sSlotNum );
+114 -113
View File
@@ -3268,22 +3268,19 @@ void HandleKilledQuote( SOLDIERTYPE *pKilledSoldier, SOLDIERTYPE *pKillerSoldier
BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
{
BOOLEAN fBuddyJustDead = FALSE;
*pfMadeCorpse = FALSE;
if ( pSoldier->stats.bLife == 0 && !( pSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) )
{
// Haydent/send death info
if (is_networked)
{
if(pSoldier->bTeam==0) send_death(pSoldier);
else if(pSoldier->bTeam <6 && ((gTacticalStatus.ubTopMessageType == PLAYER_TURN_MESSAGE) || (gTacticalStatus.ubTopMessageType == PLAYER_INTERRUPT_MESSAGE)))send_death(pSoldier);
{
if(pSoldier->bTeam==0)
send_death(pSoldier);
else if(pSoldier->bTeam <6 && ((gTacticalStatus.ubTopMessageType == PLAYER_TURN_MESSAGE) || (gTacticalStatus.ubTopMessageType == PLAYER_INTERRUPT_MESSAGE)))
send_death(pSoldier);
}
// Cancel services here...
pSoldier->ReceivingSoldierCancelServices( );
pSoldier->GivingSoldierCancelServices( );
@@ -3348,129 +3345,133 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
ubAssister = pSoldier->ubNextToPreviousAttackerID;
}
}
//////////////////////////////////////////////////////////////
// IF this guy has an attacker and he's a good guy, play sound
if ( ubAttacker != NOBODY )
// WANNE: This should fix crash in a MP game, when someone quits playing
if ( (is_networked && pSoldier->ubAttackerID < 254) || !is_networked )
{
if ( MercPtrs[ pSoldier->ubAttackerID ]->bTeam == gbPlayerNum && gTacticalStatus.ubAttackBusyCount > 0 )
{
gTacticalStatus.fKilledEnemyOnAttack = TRUE;
gTacticalStatus.ubEnemyKilledOnAttack = pSoldier->ubID;
gTacticalStatus.ubEnemyKilledOnAttackLocation = pSoldier->sGridNo;
gTacticalStatus.bEnemyKilledOnAttackLevel = pSoldier->pathing.bLevel;
gTacticalStatus.ubEnemyKilledOnAttackKiller = ubAttacker;
// also check if we are in mapscreen, if so update soldier's list
if( guiCurrentScreen == MAP_SCREEN )
// IF this guy has an attacker and he's a good guy, play sound
if ( ubAttacker != NOBODY )
{
if ( MercPtrs[ pSoldier->ubAttackerID ]->bTeam == gbPlayerNum && gTacticalStatus.ubAttackBusyCount > 0 )
{
ReBuildCharactersList( );
gTacticalStatus.fKilledEnemyOnAttack = TRUE;
gTacticalStatus.ubEnemyKilledOnAttack = pSoldier->ubID;
gTacticalStatus.ubEnemyKilledOnAttackLocation = pSoldier->sGridNo;
gTacticalStatus.bEnemyKilledOnAttackLevel = pSoldier->pathing.bLevel;
gTacticalStatus.ubEnemyKilledOnAttackKiller = ubAttacker;
// also check if we are in mapscreen, if so update soldier's list
if( guiCurrentScreen == MAP_SCREEN )
{
ReBuildCharactersList( );
}
}
}
else if ( pSoldier->bVisible == TRUE )
{
// We were a visible enemy, say laugh!
if ( Random(3) == 0 && !CREATURE_OR_BLOODCAT( MercPtrs[ ubAttacker ] ) )
else if ( pSoldier->bVisible == TRUE )
{
MercPtrs[ ubAttacker ]->DoMercBattleSound( BATTLE_SOUND_LAUGH1 );
}
// We were a visible enemy, say laugh!
if ( Random(3) == 0 && !CREATURE_OR_BLOODCAT( MercPtrs[ ubAttacker ] ) )
{
MercPtrs[ ubAttacker ]->DoMercBattleSound( BATTLE_SOUND_LAUGH1 );
}
}
}
}
// Handle NPC Dead
HandleNPCTeamMemberDeath( pSoldier );
// if a friendly with a profile, increment kills
// militia also now track kills...
if ( ubAttacker != NOBODY )
{
if ( MercPtrs[ ubAttacker ]->bTeam == gbPlayerNum )
// Handle NPC Dead
HandleNPCTeamMemberDeath( pSoldier );
// if a friendly with a profile, increment kills
// militia also now track kills...
if ( ubAttacker != NOBODY )
{
// increment kills
/////////////////////////////////////////////////////////////////////////////////////
// SANDRO - experimental - more specific statistics of mercs
switch(pSoldier->ubSoldierClass)
if ( MercPtrs[ ubAttacker ]->bTeam == gbPlayerNum )
{
case SOLDIER_CLASS_ELITE :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsElites++;
break;
case SOLDIER_CLASS_ARMY :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsRegulars++;
break;
case SOLDIER_CLASS_ADMINISTRATOR :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsAdmins++;
break;
case SOLDIER_CLASS_CREATURE :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsCreatures++;
break;
default :
if ( CREATURE_OR_BLOODCAT( pSoldier ) )
// increment kills
/////////////////////////////////////////////////////////////////////////////////////
// SANDRO - experimental - more specific statistics of mercs
switch(pSoldier->ubSoldierClass)
{
case SOLDIER_CLASS_ELITE :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsElites++;
break;
case SOLDIER_CLASS_ARMY :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsRegulars++;
break;
case SOLDIER_CLASS_ADMINISTRATOR :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsAdmins++;
break;
case SOLDIER_CLASS_CREATURE :
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsCreatures++;
else if ( TANK( pSoldier ) )
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsTanks++;
else if ( pSoldier->bTeam == CIV_TEAM && !pSoldier->aiData.bNeutral && pSoldier->bSide != gbPlayerNum )
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsHostiles++;
break;
default :
if ( CREATURE_OR_BLOODCAT( pSoldier ) )
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsCreatures++;
else if ( TANK( pSoldier ) )
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsTanks++;
else if ( pSoldier->bTeam == CIV_TEAM && !pSoldier->aiData.bNeutral && pSoldier->bSide != gbPlayerNum )
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsHostiles++;
else
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsOthers++;
break;
}
//gMercProfiles[ MercPtrs[ pSoldier->ubAttackerID ]->ubProfile ].usKills++;
/////////////////////////////////////////////////////////////////////////////////////
gStrategicStatus.usPlayerKills++;
}
else if ( MercPtrs[ ubAttacker ]->bTeam == MILITIA_TEAM )
{
// get a kill! 2 points!
MercPtrs[ ubAttacker ]->ubMilitiaKills += 2;
}
}
if ( ubAssister != NOBODY && ubAssister != ubAttacker )
{
if ( MercPtrs[ ubAssister ]->bTeam == gbPlayerNum )
{
/////////////////////////////////////////////////////////////////////////////////////
// SANDRO - new mercs' records
if( MercPtrs[ ubAttacker ] != NULL )
{
if( MercPtrs[ ubAttacker ]->bTeam == gbPlayerNum )
gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].records.usAssistsMercs++;
else if ( MercPtrs[ ubAttacker ]->bTeam == MILITIA_TEAM )
gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].records.usAssistsMilitia++;
else
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsOthers++;
break;
}
//gMercProfiles[ MercPtrs[ pSoldier->ubAttackerID ]->ubProfile ].usKills++;
/////////////////////////////////////////////////////////////////////////////////////
gStrategicStatus.usPlayerKills++;
}
else if ( MercPtrs[ ubAttacker ]->bTeam == MILITIA_TEAM )
{
// get a kill! 2 points!
MercPtrs[ ubAttacker ]->ubMilitiaKills += 2;
}
}
if ( ubAssister != NOBODY && ubAssister != ubAttacker )
{
if ( MercPtrs[ ubAssister ]->bTeam == gbPlayerNum )
{
/////////////////////////////////////////////////////////////////////////////////////
// SANDRO - new mercs' records
if( MercPtrs[ ubAttacker ] != NULL )
{
if( MercPtrs[ ubAttacker ]->bTeam == gbPlayerNum )
gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].records.usAssistsMercs++;
else if ( MercPtrs[ ubAttacker ]->bTeam == MILITIA_TEAM )
gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].records.usAssistsMilitia++;
gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].records.usAssistsOthers++;
}
else
{
gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].records.usAssistsOthers++;
}
//gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].usAssists++;
/////////////////////////////////////////////////////////////////////////////////////
}
else
else if ( MercPtrs[ ubAssister ]->bTeam == MILITIA_TEAM )
{
gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].records.usAssistsOthers++;
// get an assist - 1 points
MercPtrs[ ubAssister ]->ubMilitiaKills += 1;
}
//gMercProfiles[ MercPtrs[ ubAssister ]->ubProfile ].usAssists++;
/////////////////////////////////////////////////////////////////////////////////////
}
else if ( MercPtrs[ ubAssister ]->bTeam == MILITIA_TEAM )
/*
// handle assist
// if killer is assister, don't increment
if ( pSoldier->ubPreviousAttackerID != NOBODY && pSoldier->ubPreviousAttackerID != pSoldier->ubAttackerID )
{
// get an assist - 1 points
MercPtrs[ ubAssister ]->ubMilitiaKills += 1;
if ( MercPtrs[ pSoldier->ubPreviousAttackerID ]->bTeam == gbPlayerNum )
{
gMercProfiles[ MercPtrs[ pSoldier->ubPreviousAttackerID ]->ubProfile ].usAssists++;
}
else if ( MercPtrs[ pSoldier->ubPreviousAttackerID ]->bTeam == MILITIA_TEAM )
{
// get an assist - 1 points
MercPtrs[ pSoldier->ubPreviousAttackerID ]->ubMilitiaKills += 1;
}
}
*/
}
/*
// handle assist
// if killer is assister, don't increment
if ( pSoldier->ubPreviousAttackerID != NOBODY && pSoldier->ubPreviousAttackerID != pSoldier->ubAttackerID )
{
if ( MercPtrs[ pSoldier->ubPreviousAttackerID ]->bTeam == gbPlayerNum )
{
gMercProfiles[ MercPtrs[ pSoldier->ubPreviousAttackerID ]->ubProfile ].usAssists++;
}
else if ( MercPtrs[ pSoldier->ubPreviousAttackerID ]->bTeam == MILITIA_TEAM )
{
// get an assist - 1 points
MercPtrs[ pSoldier->ubPreviousAttackerID ]->ubMilitiaKills += 1;
}
}
*/
}
if ( TurnSoldierIntoCorpse( pSoldier, TRUE, TRUE ) )
+156 -95
View File
@@ -2413,8 +2413,12 @@ BOOLEAN SOLDIERTYPE::CreateSoldierCommon( UINT8 ubBodyType, UINT16 usSoldierID,
// bad anims are: HOPFENCE,
// CLIMBDOWNROOF, FALLFORWARD_ROOF,FALLOFF, CLIMBUPROOF
if( !gfWorldLoaded &&
( usState == HOPFENCE ||
( usState == HOPFENCE || usState == JUMPWINDOWS ||
usState == CLIMBDOWNROOF ||
usState == JUMPDOWNWALL ||
usState == JUMPUPWALL ||
usState == FALLFORWARD_ROOF ||
usState == FALLOFF ||
usState == CLIMBUPROOF ) )
@@ -2992,6 +2996,33 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
return( TRUE );
}
}
if ( usNewState == JUMPUPWALL )
{
if ( this->ubPendingDirection != NO_PENDING_DIRECTION )
{
this->EVENT_SetSoldierDesiredDirection( this->ubPendingDirection );
this->ubPendingDirection = NO_PENDING_DIRECTION;
this->usPendingAnimation = JUMPUPWALL;
this->flags.fTurningUntilDone = TRUE;
this->SoldierGotoStationaryStance( );
return( TRUE );
}
}
if ( usNewState == JUMPDOWNWALL )
{
if ( this->ubPendingDirection != NO_PENDING_DIRECTION )
{
this->EVENT_SetSoldierDesiredDirection( this->ubPendingDirection );
this->ubPendingDirection = NO_PENDING_DIRECTION;
this->usPendingAnimation = JUMPDOWNWALL;
this->flags.bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
this->flags.fTurningUntilDone = TRUE;
this->SoldierGotoStationaryStance( );
return( TRUE );
}
}
// ATE: Don't raise/lower automatically if we are low on health,
// as our gun looks lowered anyway....
@@ -3229,7 +3260,7 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
}
// ATE: Patch hole for breath collapse for roofs, fences
if ( usNewState == CLIMBUPROOF || usNewState == CLIMBDOWNROOF || usNewState == HOPFENCE )
if ( usNewState == JUMPUPWALL || usNewState == JUMPDOWNWALL || usNewState == CLIMBUPROOF || usNewState == CLIMBDOWNROOF || usNewState == HOPFENCE || usNewState == JUMPWINDOWS)
{
// Check for breath collapse if a given animation like
if ( this->CheckForBreathCollapse( ) || this->bCollapsed )
@@ -3708,6 +3739,13 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
else
DeductPoints( this, GetAPsToJumpFence( this, FALSE ), GetBPsToJumpFence( this, FALSE ) );
break;
case JUMPWINDOWS:
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( this ) != ITEM_NOT_FOUND )
DeductPoints( this, GetAPsToJumpThroughWindows( this, TRUE ), GetBPsToJumpThroughWindows( this, TRUE ) );
else
DeductPoints( this, GetAPsToJumpThroughWindows( this, FALSE ), GetBPsToJumpThroughWindows( this, FALSE ) );
break;
// Deduct aps for falling down....
case FALLBACK_HIT_STAND:
@@ -3742,6 +3780,22 @@ BOOLEAN SOLDIERTYPE::EVENT_InitNewSoldierAnim( UINT16 usNewState, UINT16 usStart
DeductPoints( this, GetAPsToClimbRoof( this, FALSE), GetBPsToClimbRoof( this, FALSE) ); // changed by SANDRO
break;
case JUMPDOWNWALL:
// disable sight
gTacticalStatus.uiFlags |= DISALLOW_SIGHT;
DeductPoints( this, GetAPsToJumpWall( this, TRUE), GetBPsToJumpWall( this, TRUE) );
break;
case JUMPUPWALL:
// disable sight
gTacticalStatus.uiFlags |= DISALLOW_SIGHT;
DeductPoints( this, GetAPsToJumpWall( this, FALSE), GetBPsToJumpWall( this, FALSE) );
break;
case JUMP_OVER_BLOCKING_PERSON:
@@ -4311,6 +4365,17 @@ void SOLDIERTYPE::SetSoldierGridNo( INT32 sNewGridNo, BOOLEAN fForceRemove )
if(this->iLight!=(-1))
LightSpriteRoofStatus(this->iLight, FALSE );
}
if ( this->usAnimState == JUMPUPWALL )
{
if(this->iLight!=(-1))
LightSpriteRoofStatus(this->iLight, TRUE );
}
else if ( this->usAnimState == JUMPDOWNWALL )
{
if(this->iLight!=(-1))
LightSpriteRoofStatus(this->iLight, FALSE );
}
//JA2Gold:
//if the player wants the merc to cast the fake light AND it is night
@@ -6583,7 +6648,7 @@ void SOLDIERTYPE::EVENT_InternalSetSoldierDestination( UINT16 usNewDirection, BO
// OK, ATE: If we are side_stepping, calculate a NEW desired direction....
if ( this->bReverse && usAnimState == SIDE_STEP )
if ( this->bReverse && (usAnimState == SIDE_STEP || usAnimState == ROLL_PRONE_R || usAnimState == ROLL_PRONE_L) )
{
UINT8 ubPerpDirection;
@@ -6691,7 +6756,7 @@ INT8 MultiTiledTurnDirection( SOLDIERTYPE * pSoldier, INT8 bStartDirection, INT8
void EVENT_InternalSetSoldierDesiredDirection( SOLDIERTYPE *pSoldier, UINT8 ubNewDirection, BOOLEAN fInitalMove, UINT16 usAnimState )
{
//if ( usAnimState == WALK_BACKWARDS )
if ( pSoldier->bReverse && usAnimState != SIDE_STEP )
if ( pSoldier->bReverse && (usAnimState != SIDE_STEP && usAnimState != ROLL_PRONE_R && usAnimState != ROLL_PRONE_L) )
{
// OK, check if we are going to go in the exact opposite than our facing....
ubNewDirection = gOppositeDirection[ ubNewDirection ];
@@ -7245,6 +7310,19 @@ void SOLDIERTYPE::TurnSoldier( void )
HandleSystemNewAISituation( this, FALSE );
}
if ( this->flags.uiStatusFlags & SOLDIER_LOOK_NEXT_TURNSOLDIER )
{
if ( ( gAnimControl[ this->usAnimState ].uiFlags & ANIM_STATIONARY && this->usAnimState != JUMPUPWALL && this->usAnimState != JUMPDOWNWALL ) )
{
// HANDLE SIGHT!
HandleSight( this,SIGHT_LOOK | SIGHT_RADIO );
}
// Turn off!
this->flags.uiStatusFlags &= (~SOLDIER_LOOK_NEXT_TURNSOLDIER );
HandleSystemNewAISituation( this, FALSE );
}
if ( this->flags.fTurningToShoot )
@@ -8480,7 +8558,7 @@ void SOLDIERTYPE::BeginSoldierClimbFence( void )
void SOLDIERTYPE::BeginSoldierClimbWindow( void )
{
INT8 bDirection;
INT8 bDirection;
// Make sure we hop the correct fence to follow our path!
if (this->pathing.usPathIndex < this->pathing.usPathDataSize)
@@ -8500,59 +8578,55 @@ void SOLDIERTYPE::BeginSoldierClimbWindow( void )
this->flags.fTurningUntilDone = TRUE;
// ATE: Reset flag to go back to prone...
this->flags.bTurningFromPronePosition = TURNING_FROM_PRONE_OFF;
this->usPendingAnimation = HOPFENCE;
this->usPendingAnimation = JUMPWINDOWS; //HOPFENCE;
}
}
void SOLDIERTYPE::BeginSoldierFence( void )
void SOLDIERTYPE::BeginSoldierClimbWall( void )
{
INT8 bNewDirection;
UINT8 ubWhoIsThere;
if ( FindFenceDirection( this, this->sGridNo, this->ubDirection, &bNewDirection ) && ( this->pathing.bLevel == 0 ) )
if ( FindWallJumpDirection( this, this->sGridNo, this->ubDirection, &bNewDirection ) && ( this->pathing.bLevel == 0 ) )
{
if ( EnoughPoints( this, GetAPsToClimbRoof( this, FALSE ), 0, TRUE ) )
{
//Kaiden: Helps if we look where we are going before we try to climb on top of someone
ubWhoIsThere = WhoIsThere2( NewGridNo( this->sGridNo, (UINT16)DirectionInc(bNewDirection ) ), 1 );
if ( ubWhoIsThere != NOBODY && ubWhoIsThere != this->ubID )
{
return;
}
else
{
if (this->bTeam == gbPlayerNum)
ubWhoIsThere = WhoIsThere2( NewGridNo( this->sGridNo, (UINT16)DirectionInc(bNewDirection ) ), 1 );
if ( ubWhoIsThere != NOBODY && ubWhoIsThere != this->ubID )
{
SetUIBusy( this->ubID );
return;
}
else
{
if (this->bTeam == gbPlayerNum)
{
SetUIBusy( this->ubID );
}
this->sTempNewGridNo = NewGridNo( this->sGridNo, (UINT16)DirectionInc(bNewDirection ) );
this->sTempNewGridNo = NewGridNo( this->sGridNo, (UINT16)DirectionInc(bNewDirection ) );
this->ubPendingDirection = bNewDirection;
this->EVENT_InitNewSoldierAnim( CLIMBUPROOF, 0 , FALSE );
this->InternalReceivingSoldierCancelServices( FALSE );
this->InternalGivingSoldierCancelServices( FALSE );
this->BeginSoldierFenceUp( );
}
this->ubPendingDirection = bNewDirection;
this->EVENT_InitNewSoldierAnim( JUMPUPWALL, 0 , FALSE );
this->InternalReceivingSoldierCancelServices( FALSE );
this->InternalGivingSoldierCancelServices( FALSE );
// this->BeginSoldierClimbWallUp( );
}
}
}
}
void SOLDIERTYPE::BeginSoldierFenceUp( void )
void SOLDIERTYPE::BeginSoldierClimbWallUp( void )
{
INT8 bNewDirection;
UINT8 ubWhoIsThere;
if ( FindLowerLevelFence( this, this->sGridNo, this->ubDirection, &bNewDirection ) && ( this->pathing.bLevel > 0 ) )
if ( FindLowerLevelWall( this, this->sGridNo, this->ubDirection, &bNewDirection ) && ( this->pathing.bLevel > 0 ) )
{
if ( EnoughPoints( this, GetAPsToClimbRoof( this, TRUE ), 0, TRUE ) )
if ( EnoughPoints( this, GetAPsToJumpWall( this, TRUE ), 0, TRUE ) )
{
//Kaiden: Helps if we look where we are going before we try to climb on top of someone
ubWhoIsThere = WhoIsThere2( NewGridNo( this->sGridNo, (UINT16)DirectionInc(bNewDirection ) ), 0 );
@@ -8573,10 +8647,12 @@ void SOLDIERTYPE::BeginSoldierFenceUp( void )
bNewDirection = gTwoCDirection[ bNewDirection ];
this->ubPendingDirection = bNewDirection;
this->EVENT_InitNewSoldierAnim( CLIMBDOWNROOF, 0 , FALSE );
this->EVENT_InitNewSoldierAnim( JUMPDOWNWALL, 0 , FALSE );
this->InternalReceivingSoldierCancelServices( FALSE );
this->InternalGivingSoldierCancelServices( FALSE );
this->InternalGivingSoldierCancelServices( FALSE );
this->BeginSoldierClimbWall( );
}
}
@@ -8585,7 +8661,6 @@ void SOLDIERTYPE::BeginSoldierFenceUp( void )
}
//------------------------------------------------------------------------------------------
UINT32 SleepDartSuccumbChance( SOLDIERTYPE * pSoldier )
{
UINT32 uiChance;
@@ -9884,7 +9959,7 @@ void SOLDIERTYPE::BeginSoldierClimbDownRoof( void )
bNewDirection = gTwoCDirection[ bNewDirection ];
this->ubPendingDirection = bNewDirection;
this->EVENT_InitNewSoldierAnim( CLIMBDOWNROOF, 0 , FALSE );
this->EVENT_InitNewSoldierAnim( JUMPDOWNWALL, 0 , FALSE );
this->InternalReceivingSoldierCancelServices( FALSE );
this->InternalGivingSoldierCancelServices( FALSE );
@@ -11290,6 +11365,7 @@ void SOLDIERTYPE::EVENT_SoldierBeginFirstAid( INT32 sGridNo, UINT8 ubDirection )
if ( !fRefused )
{
/*
if ( CREATURE_OR_BLOODCAT( pTSoldier ) )
{
// nope!!
@@ -11297,6 +11373,8 @@ void SOLDIERTYPE::EVENT_SoldierBeginFirstAid( INT32 sGridNo, UINT8 ubDirection )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, Message[ STR_REFUSE_FIRSTAID_FOR_CREATURE ] );
}
else if ( !pTSoldier->aiData.bNeutral && pTSoldier->stats.bLife >= OKLIFE && pTSoldier->bSide != this->bSide )
*/
if ( !pTSoldier->aiData.bNeutral && pTSoldier->stats.bLife >= OKLIFE && pTSoldier->bSide != this->bSide )
{
fRefused = TRUE;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, Message[ STR_REFUSE_FIRSTAID ] );
@@ -11606,16 +11684,19 @@ UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT1
usLifeReturned = pVictim->iHealableInjury * (gSkillTraitValues.ubDOSurgeryHealPercentBase + gSkillTraitValues.ubDOSurgeryHealPercentOnTop * NUM_SKILL_TRAITS( this, DOCTOR_NT ))/100;
pVictim->iHealableInjury = 0;
//CHRISL: Why would we arbitrarily use all ubPtsLeft when a victim isn't bleeding? And why would the medical bag, which we have to use in order to
// do surgery, have any extra benefit? Plus, the medical back bonus can actually result in ubPtsLeft being HIGHER then it was before we healed the
// victim, which makes no sense.
// keep the rest of the points to bandaging if neccessary
if (pVictim->bBleeding > 0)
{
//if (pVictim->bBleeding > 0)
//{
ubPtsLeft = max(0, (ubPtsLeft - (usLifeReturned / 100)));
ubPtsLeft += (ubPtsLeft/2); // we use medical bag so add the bonus for that.
}
else
{
ubPtsLeft = 0;
}
// ubPtsLeft += (ubPtsLeft/2); // we use medical bag so add the bonus for that.
//}
//else
//{
// ubPtsLeft = 0;
//}
// We are finished !!!
this->fDoingSurgery = FALSE;
@@ -11709,9 +11790,9 @@ UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT1
pVictim->flags.fWarnedAboutBleeding = FALSE;
}
//CHRISL: If by some chance ubPtsLeft ends up being higher then uiActual, we'll end up with a huge value since uiActual is an unsigned variable.
// if there are any ptsLeft now, then we didn't actually get to use them
uiActual = max(0, (uiActual - ubPtsLeft));
uiActual = max(0, (INT32)(uiActual - ubPtsLeft));
// usedAPs equals (actionPts) * (%of possible points actually used)
uiUsedAPs = ( uiActual * uiAvailAPs ) / uiPossible;
@@ -12934,6 +13015,10 @@ void HandlePlacingRoofMarker( SOLDIERTYPE *pSoldier, INT32 sGridNo, BOOLEAN fSet
return;
}
//CHRISL: If sGridNo is -1, which can be the case if there is a dead merc still listed as part of a unit, crashes will occur
if ( sGridNo == -1 )
return;
if ( pSoldier->bTeam != gbPlayerNum )
{
//return;
@@ -12950,6 +13035,11 @@ void HandlePlacingRoofMarker( SOLDIERTYPE *pSoldier, INT32 sGridNo, BOOLEAN fSet
{
return;
}
if ( pSoldier->usAnimState == JUMPUPWALL && !fForce )
{
return;
}
if ( pRoofNode != NULL )
{
@@ -13622,6 +13712,9 @@ BOOLEAN SOLDIERTYPE::PlayerSoldierStartTalking( UINT8 ubTargetID, BOOLEAN fValid
//lal
// ATE; Check for normal civs...
BOOLEAN apsDeducted = FALSE;
if ( GetCivType( pTSoldier ) != CIV_TYPE_NA )
{
//lal
@@ -13634,14 +13727,19 @@ BOOLEAN SOLDIERTYPE::PlayerSoldierStartTalking( UINT8 ubTargetID, BOOLEAN fValid
{
// Deduct points from our guy....
DeductPoints( this, sAPCost, 0 );
apsDeducted = TRUE;
StartCivQuote( pTSoldier );
return( FALSE );
}
}
// WANNE: This fixes the bug, that APs for talking are not always deducted.
if (!apsDeducted)
{
DeductPoints( this, sAPCost, 0 );
apsDeducted = TRUE;
}
// Are we an EPC that is being escorted?
if ( pTSoldier->ubProfile != NO_PROFILE && pTSoldier->ubWhatKindOfMercAmI == MERC_TYPE__EPC )
@@ -13981,7 +14079,7 @@ void InternalPlaySoldierFootstepSound( SOLDIERTYPE * pSoldier )
// Determine if we are on the floor
if ( !( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) )
{
if ( pSoldier->usAnimState == HOPFENCE )
if ( pSoldier->usAnimState == HOPFENCE || pSoldier->usAnimState == JUMPWINDOWS)
{
bVolume = HIGHVOLUME;
}
@@ -14264,6 +14362,11 @@ void SetSoldierPersonalLightLevel( SOLDIERTYPE *pSoldier )
return;
}
if(gpWorldLevelData[pSoldier->sGridNo].pMercHead == NULL)
{
return;
}
//THe light level for the soldier
gpWorldLevelData[pSoldier->sGridNo].pMercHead->ubShadeLevel = 3;
gpWorldLevelData[pSoldier->sGridNo].pMercHead->ubSumLights = 5;
@@ -14271,56 +14374,14 @@ void SetSoldierPersonalLightLevel( SOLDIERTYPE *pSoldier )
gpWorldLevelData[pSoldier->sGridNo].pMercHead->ubNaturalShadeLevel = 5;
}
//---legion by JAzz---------------------------------------
void BeginSoldierFence( SOLDIERTYPE *pSoldier )
{
INT8 bNewDirection;
UINT8 ubWhoIsThere;
if ( FindFenceDirection( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) && ( pSoldier->pathing.bLevel == 0 ) )
{
if ( EnoughPoints( pSoldier, GetAPsToClimbRoof( pSoldier, FALSE ), 0, TRUE ) )
{
//Kaiden: Helps if we look where we are going before we try to climb on top of someone
ubWhoIsThere = WhoIsThere2( NewGridNo( pSoldier->sGridNo, (UINT16)DirectionInc(bNewDirection ) ), 1 );
if ( ubWhoIsThere != NOBODY && ubWhoIsThere != pSoldier->ubID )
{
return;
}
else
{
if (pSoldier->bTeam == gbPlayerNum)
{
SetUIBusy( pSoldier->ubID );
}
pSoldier->sTempNewGridNo = NewGridNo( pSoldier->sGridNo, (UINT16)DirectionInc(bNewDirection ) );
pSoldier->ubPendingDirection = bNewDirection;
pSoldier->EVENT_InitNewSoldierAnim( CLIMBUPROOF, 0 , FALSE );
pSoldier->InternalReceivingSoldierCancelServices( FALSE );
pSoldier->InternalGivingSoldierCancelServices( FALSE );
BeginSoldierFenceUp( pSoldier );
}
}
}
}
void BeginSoldierFenceUp( SOLDIERTYPE *pSoldier )
void BeginSoldierClimbWallUp( SOLDIERTYPE *pSoldier )
{
INT8 bNewDirection;
UINT8 ubWhoIsThere;
if ( FindLowerLevelFence( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) && ( pSoldier->pathing.bLevel > 0 ) )
if ( FindLowerLevelWall( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bNewDirection ) && ( pSoldier->pathing.bLevel > 0 ) )
{
if ( EnoughPoints( pSoldier, GetAPsToClimbRoof( pSoldier, TRUE ), 0, TRUE ) )
if ( EnoughPoints( pSoldier, GetAPsToJumpWall( pSoldier, TRUE ), 0, TRUE ) )
{
//Kaiden: Helps if we look where we are going before we try to climb on top of someone
ubWhoIsThere = WhoIsThere2( NewGridNo( pSoldier->sGridNo, (UINT16)DirectionInc(bNewDirection ) ), 0 );
@@ -14341,7 +14402,7 @@ void BeginSoldierFenceUp( SOLDIERTYPE *pSoldier )
bNewDirection = gTwoCDirection[ bNewDirection ];
pSoldier->ubPendingDirection = bNewDirection;
pSoldier->EVENT_InitNewSoldierAnim( CLIMBDOWNROOF, 0 , FALSE );
pSoldier->EVENT_InitNewSoldierAnim( JUMPDOWNWALL, 0 , FALSE );
pSoldier->InternalReceivingSoldierCancelServices( FALSE );
pSoldier->InternalGivingSoldierCancelServices( FALSE );
+7 -2
View File
@@ -34,6 +34,8 @@ extern UINT16 CivLastNames[MAXCIVLASTNAMES][10];
#define LOCKED_NO_NEWGRIDNO 2
// WANNE: Yes I know, we support up to 254 profiles, but because of compatibility, profile Id = 200
// is not a valid profil. We in MercProfiles.xml, the profile id = 200 should not be used!
#define NO_PROFILE 200
#define BATTLE_SND_LOWER_VOLUME 1
@@ -815,6 +817,9 @@ public:
// HEADROCK HAM 4: Two more values. These record the shooter's previous Counter Force applied on the gun.
FLOAT dPrevCounterForceX;
FLOAT dPrevCounterForceY;
// CHRISL: Track initial offsets for autofire
FLOAT dInitialMuzzleOffsetX;
FLOAT dInitialMuzzleOffsetY;
INT8 bTilesMoved;
FLOAT dNextBleed;
@@ -1258,9 +1263,9 @@ public:
void BeginTyingToFall( void );
//legion by Jazz
void BeginSoldierFence( void );
void BeginSoldierFenceUp( void );
void BeginSoldierClimbWall( void );
void BeginSoldierClimbWindow( void );
void BeginSoldierClimbWallUp( void );
void HandleAnimationProfile( UINT16 usAnimState, BOOLEAN fRemove );
void HandleSoldierTakeDamageFeedback( void );
+7 -5
View File
@@ -546,13 +546,15 @@ void DecideToAssignSniperOrders( SOLDIERCREATE_STRUCT * pp )
if ( pp->bOrders == STATIONARY || pp->bOrders == ONGUARD )
{
// 30% of anybody w/a scope and decent range being a sniper, 80% chance of a guy w/a sniper rifle being a sniper
if ( (GunRange(&pp->Inv[HANDPOS], NULL) >= 40 && IsScoped(&pp->Inv[HANDPOS]) && Random(100) < 30) || ( Weapon[pp->Inv[HANDPOS].usItem].ubWeaponType == GUN_SN_RIFLE && IsScoped(&pp->Inv[HANDPOS]) && Random(100) < 80 ) ) // SANDRO - added argument forGunRange
{
//CHRISL: Externalized values and added ability to restrict non-SR Snipers to Elite only
if(Weapon[pp->Inv[HANDPOS].usItem].ubWeaponType != GUN_SN_RIFLE && GunRange(&pp->Inv[HANDPOS], NULL) >= gGameExternalOptions.fAISniperRange && IsScoped(&pp->Inv[HANDPOS]) && Random(100) < gGameExternalOptions.fAISniperChance){
if((gGameExternalOptions.fAISniperElite == TRUE && pp->ubSoldierClass == SOLDIER_CLASS_ELITE) || gGameExternalOptions.fAISniperElite == FALSE)
pp->bOrders = SNIPER;
}
else if(Weapon[pp->Inv[HANDPOS].usItem].ubWeaponType == GUN_SN_RIFLE && IsScoped(&pp->Inv[HANDPOS]) && Random(100) < gGameExternalOptions.fAISniperChanceWithSR)
pp->bOrders = SNIPER;
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Sniper Created") );
}
DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("Sniper Created") );
}
}
+1 -1
View File
@@ -501,7 +501,7 @@ void OkayToUpgradeEliteToSpecialProfiledEnemy( SOLDIERCREATE_STRUCT *pp );
extern BOOLEAN gfProfiledEnemyAdded; //needs to be saved (used by the above function)
//Legion by Jazz
void BeginSoldierClimbUpOkno( SOLDIERTYPE *pSoldier );
//void BeginSoldierClimbUpOkno( SOLDIERTYPE *pSoldier );
void BeginSoldierFenceUp( SOLDIERTYPE *pSoldier );
//dnl ch27 240909
typedef enum
+2 -2
View File
@@ -1055,8 +1055,8 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
(*pCurrTotal)--;
ubMaxNum--;
}
else
return;
// else
// return;
}
(*pCurrSlots)--;
//With the decrementing of the slot vars in this manner, the chances increase so that all slots
+20 -1
View File
@@ -588,6 +588,8 @@ BOOLEAN LoadMercProfiles(void)
FileClose( fptr );
return(FALSE);
}
// WANNE: For the new WF merc, there is no entry in prof.dat, so we have to reset some flags manually!
if (uiLoop >= 170)
@@ -741,7 +743,24 @@ BOOLEAN LoadMercProfiles(void)
// ----- WANNE.PROFILE: New Profile Loading - BEGIN
if ( gGameExternalOptions.fReadProfileDataFromXML == FALSE )
{
{
// WANNE: If all 4 (Friendly, Direct, Threaten, Recruit) are not set, set them to 100.
// These 4 values cannot be edit in Proedit if Merc Index >= 75.
// If we set these to 100 (which means it is equal the leadership of the merc), we fix the bug that the 4 UB Merc (Stogie, Tex, Gaston, Biggins) cannot recruit NPCs or do special quests).
if (uiLoop >= FIRST_NPC)
{
if (gMercProfiles[ uiLoop ].usApproachFactor[0] == 0 &&
gMercProfiles[ uiLoop ].usApproachFactor[1] == 0 &&
gMercProfiles[ uiLoop ].usApproachFactor[2] == 0 &&
gMercProfiles[ uiLoop ].usApproachFactor[3] == 0)
{
gMercProfiles[ uiLoop ].usApproachFactor[0] = 100;
gMercProfiles[ uiLoop ].usApproachFactor[1] = 100;
gMercProfiles[ uiLoop ].usApproachFactor[2] = 100;
gMercProfiles[ uiLoop ].usApproachFactor[3] = 100;
}
}
// AIM und MERC ( 0 - 51 )
if (uiLoop < 51)
{
+5
View File
@@ -204,6 +204,11 @@ void UnMarkMovementReserved( SOLDIERTYPE *pSoldier )
{
return;
}
if ( pSoldier->usAnimState == JUMPWINDOWS && pSoldier->sReservedMovementGridNo != sNewGridNo )
{
return;
}
// For single-tiled mercs, unset this gridno
// See if we have one reserved!
+8
View File
@@ -24,6 +24,7 @@
// added by SANDRO
#include "SkillCheck.h"
#include "soldier profile type.h"
#include "Soldier macros.h"
#endif
//forward declarations of common classes to eliminate includes
@@ -54,6 +55,13 @@ void DrawMouseTooltip(void);
void SoldierTooltip( SOLDIERTYPE* pSoldier )
{
// WANNE: No tooltips on bloodcats, bugs, tanks, roboter
if ( CREATURE_OR_BLOODCAT( pSoldier ) || TANK ( pSoldier ) ||
AM_A_ROBOT( pSoldier))
{
return;
}
SGPRect aRect;
extern void GetSoldierScreenRect(SOLDIERTYPE*,SGPRect*);
GetSoldierScreenRect( pSoldier, &aRect );
+1 -1
View File
@@ -147,7 +147,7 @@ void PickBurstLocations( SOLDIERTYPE *pSoldier )
do
{
pSoldier->bDoAutofire++;
sAPCosts = CalcTotalAPsToAttack( pSoldier, gsBurstLocations[0].sGridNo, TRUE, 0);
sAPCosts = CalcTotalAPsToAttack( pSoldier, gsBurstLocations[0].sGridNo, TRUE, pSoldier->aiData.bShownAimTime);
}
while(EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire && gbNumBurstLocations >= pSoldier->bDoAutofire);
pSoldier->bDoAutofire--;
+12
View File
@@ -277,6 +277,18 @@ BOOLEAN AddCharacterToSquad( SOLDIERTYPE *pCharacter, INT8 bSquadValue )
SetGroupSectorValue( pCharacter->sSectorX, pCharacter->sSectorY, pCharacter->bSectorZ, SquadMovementGroups[ bSquadValue ] );
pCharacter->ubGroupID = SquadMovementGroups[ bSquadValue ];
}
else if( IsVehicle(pCharacter) )
{
INT32 iCounter = 0;
for( iCounter = 0; iCounter < ubNumberOfVehicles ; iCounter++ )
{
if(pVehicleList[ iCounter ].ubProfileID == pCharacter->ubProfile)
break;
}
//AddPlayerToGroup( pVehicleList[iCounter].ubMovementGroup, pCharacter );
SetGroupSectorValue( pCharacter->sSectorX, pCharacter->sSectorY, pCharacter->bSectorZ, pVehicleList[iCounter].ubMovementGroup );
pCharacter->ubGroupID = pVehicleList[iCounter].ubMovementGroup;
}
else
{
AddPlayerToGroup( SquadMovementGroups[ bSquadValue ], pCharacter );
+2 -2
View File
@@ -83,7 +83,7 @@ BOOLEAN IsOknoFencePresentAtGridno( INT32 sGridNo )
return( FALSE );
}
BOOLEAN IsLegionFencePresentAtGridno( INT32 sGridNo )
BOOLEAN IsLegionWallPresentAtGridno( INT32 sGridNo )
{
STRUCTURE * pStructure;
@@ -92,7 +92,7 @@ BOOLEAN IsLegionFencePresentAtGridno( INT32 sGridNo )
if ( pStructure )
{
if ( pStructure->fFlags & STRUCTURE_FENCE ) // && (pStructure->fFlags & STRUCTURE_SPECIAL))//&& !(pStructure->fFlags & STRUCTURE_SPECIAL) && ( pStructure->fFlags & STRUCTURE_OPEN ))
if ( pStructure->fFlags & STRUCTURE_FENCE && pStructure->fFlags & STRUCTURE_SPECIAL && pStructure->fFlags & STRUCTURE_WALL )
{
return( TRUE );
}
+1 -1
View File
@@ -50,6 +50,6 @@ BOOLEAN SetOpenableStructureToClosed( INT32 sGridNo, UINT8 ubLevel );
//Legion by Jazz
BOOLEAN IsJumpableWindowPresentAtGridNo( INT32 sGridNo , INT8 direction2 ); //legion 2 Windows
BOOLEAN IsLegionFencePresentAtGridno( INT32 sGridNo ); //legion 2 Fence
BOOLEAN IsLegionWallPresentAtGridno( INT32 sGridNo ); //legion 2 Fence
#endif
+10
View File
@@ -2839,6 +2839,16 @@ BOOLEAN AddDeadSoldierToUnLoadedSector( INT16 sMapX, INT16 sMapY, UINT8 bMapZ, S
//Add the soldiers items to an unloaded sector
AddWorldItemsToUnLoadedSector( sMapX, sMapY, bMapZ, sGridNo, uiNumberOfItems, pWorldItems, FALSE );
//CHRISL: Now that we've copied the dead soldiers items to pWorldItems, we need to actually remove the items from the dead soldier. Otherwise we have
// actually duplicated the items and there's a chance that these duplicated items will again find their way to sector.
for ( i = 0; i < pSoldier->inv.size(); i++ )
{
if( pSoldier->inv[ i ].exists() == true )
{
pSoldier->inv[i].initialize();
}
}
}
DropKeysInKeyRing( pSoldier, sGridNo, pSoldier->pathing.bLevel, 1, FALSE, 0, TRUE );
+9 -5
View File
@@ -39,7 +39,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;"
AdditionalOptions="/D _CRT_SECURE_NO_DEPRECATE"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;"
@@ -104,7 +104,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;"
AdditionalOptions="/D _CRT_SECURE_NO_DEPRECATE"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
RuntimeLibrary="0"
@@ -165,7 +165,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;"
AdditionalOptions="/D _CRT_SECURE_NO_DEPRECATE"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
RuntimeLibrary="0"
@@ -226,7 +226,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;"
AdditionalOptions="/D _CRT_SECURE_NO_DEPRECATE"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;_DEBUG;_LIB;"
@@ -291,7 +291,7 @@
/>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="/D &quot;_CRT_SECURE_NO_DEPRECATE&quot;"
AdditionalOptions="/D _CRT_SECURE_NO_DEPRECATE"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
@@ -1088,6 +1088,10 @@
RelativePath=".\XML_Merge.cpp"
>
</File>
<File
RelativePath=".\XML_NewFaceGear.cpp"
>
</File>
<File
RelativePath=".\XML_Opinions.cpp"
>
+4
View File
@@ -1091,6 +1091,10 @@
RelativePath="XML_Merge.cpp"
>
</File>
<File
RelativePath=".\XML_NewFaceGear.cpp"
>
</File>
<File
RelativePath=".\XML_Opinions.cpp"
>
+1
View File
@@ -211,6 +211,7 @@
<ClCompile Include="XML_Magazine.cpp" />
<ClCompile Include="XML_MercStartingGear.cpp" />
<ClCompile Include="XML_Merge.cpp" />
<ClCompile Include="XML_NewFaceGear.cpp" />
<ClCompile Include="XML_Opinions.cpp" />
<ClCompile Include="XML_Profiles.cpp" />
<ClCompile Include="XML_Qarray.cpp" />
+3
View File
@@ -599,5 +599,8 @@
<ClCompile Include="XML_Qarray.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="XML_NewFaceGear.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
+25 -22
View File
@@ -120,7 +120,8 @@ typedef struct
UINT8 ubFiller[16];
} TEAM_TURN_SAVE_STRUCT;
#define MIN_APS_TO_INTERRUPT 4
// WANNE: Moved to APBPConstants
//#define MIN_APS_TO_INTERRUPT 4
void ClearIntList( void )
{
@@ -1437,7 +1438,7 @@ BOOLEAN StandardInterruptConditionsMet( SOLDIERTYPE * pSoldier, UINT8 ubOpponent
}
// if soldier doesn't have enough APs
if ( pSoldier->bActionPoints < MIN_APS_TO_INTERRUPT )
if ( pSoldier->bActionPoints < APBPConstants[MIN_APS_TO_INTERRUPT] )
{
return( FALSE );
}
@@ -2123,27 +2124,29 @@ void DoneAddingToIntList( SOLDIERTYPE * pSoldier, BOOLEAN fChange, UINT8 ubInter
}
// INTERRUPT is calculated on the pure client
else if(gTacticalStatus.ubCurrentTeam == 0)//its our turn (we are moving)
{
#ifdef BETAVERSION
{
//// WANNE: Skip the interrupt (against enemy AI) on the pure client, when we are in a coop game!
//if (cGameType == MP_TYPE_COOP)
//{
// #ifdef BETAVERSION
// ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"interrupt for another team - pure client - skipping problematic interrupt");
// #endif
//}
//else
//{
send_interrupt( npSoldier );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"interrupt for another team - PROBLEMATIC");
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"interrupt for another team - pure client - skipping problematic interrupt");
#endif
/*
// Only send interrupt if we (the client) got interrupted
send_interrupt( npSoldier );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"interrupt for another team - PROBLEMATIC");
SOLDIERTYPE* pMerc = MercPtrs[ gusSelectedSoldier ];
//AdjustNoAPToFinishMove( pMerc, TRUE );
pMerc->HaultSoldierFromSighting(TRUE);
//pMerc->fTurningFromPronePosition = FALSE;// hmmm ??
FreezeInterfaceForEnemyTurn();
InitEnemyUIBar( 0, 0 );
fInterfacePanelDirty = DIRTYLEVEL2;
AddTopMessage( COMPUTER_INTERRUPT_MESSAGE, TeamTurnString[ nbTeam ] );
gTacticalStatus.fInterruptOccurred = TRUE;
*/
SOLDIERTYPE* pMerc = MercPtrs[ gusSelectedSoldier ];
//AdjustNoAPToFinishMove( pMerc, TRUE );
pMerc->HaultSoldierFromSighting(TRUE);
//pMerc->fTurningFromPronePosition = FALSE;// hmmm ??
FreezeInterfaceForEnemyTurn();
InitEnemyUIBar( 0, 0 );
fInterfacePanelDirty = DIRTYLEVEL2;
AddTopMessage( COMPUTER_INTERRUPT_MESSAGE, TeamTurnString[ nbTeam ] );
gTacticalStatus.fInterruptOccurred = TRUE;
//}
}
else
{
+303 -369
View File
@@ -152,7 +152,6 @@ extern UINT32 guiVObjectSize;
extern UINT32 guiVSurfaceSize;
extern BOOLEAN gfNextShotKills;
BOOLEAN fAutofireBulletsMode = FALSE; // HEADROCK HAM 4: Track whether we're adjusting aim or number of bullets
UINT32 guiSoldierFlags;
UINT32 guiUITargetSoldierId = NOBODY;
@@ -217,10 +216,10 @@ void TogglePlanningMode();
void SetBurstMode();
void ObliterateSector();
void RandomizeMercProfile();
void JumpFence();
void CreateNextCivType();
void ToggleCliffDebug();
void CreateCow();
void CreateBloodCat();
void CreatePlayerControlledCow();
void ToggleRealTimeConfirm();
void TestMeanWhile( INT32 iID );
@@ -648,8 +647,6 @@ void QueryTBLeftButton( UINT32 *puiNewEvent )
{
// ATE: Reset refine aim..
pSoldier->aiData.bShownAimTime = 0;
// HEADROCK HAM 4: Reset Autofire Bullets mode.
fAutofireBulletsMode = FALSE;
if ( gsCurrentActionPoints == 0 )
{
@@ -669,13 +666,6 @@ void QueryTBLeftButton( UINT32 *puiNewEvent )
case CONFIRM_ACTION_MODE:
// HEADROCK HAM 4: If in Autofire Mode, first click puts us in bullet adjust mode.
if (UsingNewCTHSystem() == true && GetSoldier( &pSoldier, gusSelectedSoldier ))
if (pSoldier->bDoAutofire && !fAutofireBulletsMode)
fAutofireBulletsMode = TRUE;
else
*puiNewEvent = CA_MERC_SHOOT;
else
*puiNewEvent = CA_MERC_SHOOT;
break;
@@ -2260,6 +2250,13 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
//EVENT_FireSoldierWeapon( MercPtrs[ gusSelectedSoldier ], sMapPos );
}
}
else if( fCtrl ) //toggle between the different npc debug modes
{
if ( CHEATER_CHEAT_LEVEL( ) )
{
CreateBloodCat();
}
}
else
ChangeCurrentSquad( 2 );
@@ -2582,23 +2579,37 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
case 'j':
if ( fShift )
{
INT8 bDirection;
if (gGameExternalOptions.fCanJumpThroughWindows == TRUE )
{
// WANNE: Jump through window?
if (gGameExternalOptions.fCanJumpThroughWindows == TRUE )
{
INT16 sAPCost;
INT16 sBPCost;
INT8 bDirection;
SOLDIERTYPE *lSoldier;
if ( GetSoldier( &lSoldier, gusSelectedSoldier ) )
{
if ( FindWindowJumpDirection( lSoldier, lSoldier->sGridNo, lSoldier->ubDirection, &bDirection ) )
{
lSoldier->BeginSoldierClimbWindow( );
}
if ( GetSoldier( &lSoldier, gusSelectedSoldier ) )
{
if ( FindWindowJumpDirection( lSoldier, lSoldier->sGridNo, lSoldier->ubDirection, &bDirection ) )
{
if((UsingNewInventorySystem() == true) && lSoldier->inv[BPACKPOCKPOS].exists() == true)
{
sAPCost = GetAPsToJumpThroughWindows( lSoldier, TRUE );
sBPCost = GetBPsToJumpThroughWindows( lSoldier, TRUE );
}
else
{
sAPCost = GetAPsToJumpFence( lSoldier, FALSE );
sBPCost = GetBPsToJumpFence( lSoldier, FALSE );
}
if (EnoughPoints(lSoldier, sAPCost, sBPCost, FALSE))
{
lSoldier->BeginSoldierClimbWindow( );
}
}
}
}
}
}
else if( fAlt )
{
if ( CHEATER_CHEAT_LEVEL( ) )
@@ -2615,56 +2626,13 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
}
#endif
}
//ddd{ óäàëèòü çàêîììåíòèðîâàííûé òåêñò çà íåíàäîáíîñòüþ.
// else if(_KeyDown( SHIFT ))
// {
//INT16 sGridNo;
//STRUCTURE * pStructure;
//GetMouseMapPos( &sGridNo );
//ScreenMsg( FONT_MCOLOR_LTYELLOW,0, L"gubMerkCanSeeThisTile=%d,gubWorldTileInLight=%d,los=%d",gubMerkCanSeeThisTile[sGridNo],gubWorldTileInLight[sGridNo],gGameSettings.ubSizeOfLOS);
//
// SOLDIERTYPE *pjSoldier;
// BOOLEAN fNearHeigherLevel;
// BOOLEAN fNearLowerLevel;
// INT8 bDirection;
// if ( GetSoldier( &pjSoldier, gusSelectedSoldier ) )
// {
// // CHRISL: Turn off manual jumping while wearing a backpack
// if(UsingNewInventorySystem() == true && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
// break;
// // Make sure the merc is not collapsed!
// if (!IsValidStance(pjSoldier, ANIM_CROUCH) )
// {
// if ( pjSoldier->bCollapsed && pjSoldier->bBreath < OKBREATH )
// {
// ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 4 ], pjSoldier->name );
// }
// break;
// }
// GetMercOknoDirection( pjSoldier->ubID, &fNearLowerLevel, &fNearHeigherLevel );
// if ( FindOknoDirection( pjSoldier, pjSoldier->sGridNo, pjSoldier->ubDirection, &bDirection ) )
// {
// BeginSoldierOkno( pjSoldier );
// }
// }
//}//ddd}
else
{
SOLDIERTYPE *pjSoldier;
if ( GetSoldier( &pjSoldier, gusSelectedSoldier ) )
{
// CHRISL: Turn off manual jumping while wearing a backpack
if(UsingNewInventorySystem() == true && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
break;
INT16 sAPCost;
INT16 sBPCost;
BOOLEAN fNearHeigherLevel;
BOOLEAN fNearLowerLevel;
INT8 bDirection;
@@ -2680,28 +2648,66 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
break;
}
// Climb on roof
GetMercClimbDirection( pjSoldier->ubID, &fNearLowerLevel, &fNearHeigherLevel );
if ( fNearLowerLevel )
{
pjSoldier->BeginSoldierClimbDownRoof( );
// No climbing when wearing a backpack!
if((UsingNewInventorySystem() == true) && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
return;
if ( EnoughPoints( pjSoldier, GetAPsToClimbRoof( pjSoldier, TRUE ), GetBPsToClimbRoof( pjSoldier, TRUE ), FALSE ) )
{
pjSoldier->BeginSoldierClimbDownRoof( );
}
}
if ( fNearHeigherLevel )
{
pjSoldier->BeginSoldierClimbUpRoof( );
// No climbing when wearing a backpack!
if((UsingNewInventorySystem() == true) && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
return;
if ( EnoughPoints( pjSoldier, GetAPsToClimbRoof( pjSoldier, FALSE ), GetBPsToClimbRoof( pjSoldier, FALSE ), FALSE ) )
{
pjSoldier->BeginSoldierClimbUpRoof( );
}
}
// Jump over fence
if ( FindFenceJumpDirection( pjSoldier, pjSoldier->sGridNo, pjSoldier->ubDirection, &bDirection ) )
{
pjSoldier->BeginSoldierClimbFence( );
if((UsingNewInventorySystem() == true) && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
{
sAPCost = GetAPsToJumpFence( pjSoldier, TRUE );
sBPCost = GetBPsToJumpFence( pjSoldier, TRUE );
}
else
{
sAPCost = GetAPsToJumpFence( pjSoldier, FALSE );
sBPCost = GetBPsToJumpFence( pjSoldier, FALSE );
}
if ( EnoughPoints( pjSoldier, sAPCost, sBPCost, FALSE ) )
{
pjSoldier->BeginSoldierClimbFence( );
}
}
if (gGameExternalOptions.fCanClimbOnWalls == TRUE )
{
if ( FindFenceDirection( pjSoldier, pjSoldier->sGridNo, pjSoldier->ubDirection, &bDirection ) )
{
pjSoldier->BeginSoldierFence( );
}
// Climb on walls
if (gGameExternalOptions.fCanClimbOnWalls == TRUE)
{
if ( FindWallJumpDirection( pjSoldier, pjSoldier->sGridNo, pjSoldier->ubDirection, &bDirection ) )
{
// No climbing when wearing a backpack!
if((UsingNewInventorySystem() == true) && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
return;
if ( EnoughPoints( pjSoldier, GetAPsToJumpWall( pjSoldier, FALSE ), GetBPsToJumpWall( pjSoldier, FALSE ), FALSE ) )
{
pjSoldier->BeginSoldierClimbWall( );
}
}
}
}
}
@@ -3210,6 +3216,8 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
SOLDIERTYPE *pSoldier = MercPtrs[ gusSelectedSoldier ];
BOOLEAN handFit = (CanItemFitInPosition(pSoldier, &pSoldier->inv[HANDPOS], GUNSLINGPOCKPOS, FALSE) || (pSoldier->inv[HANDPOS].exists() == false && pSoldier->inv[SECONDHANDPOS].exists() == false));
BOOLEAN slingFit = (CanItemFitInPosition(pSoldier, &pSoldier->inv[GUNSLINGPOCKPOS], HANDPOS, FALSE) || pSoldier->inv[GUNSLINGPOCKPOS].exists() == false);
if(Item[pSoldier->inv[GUNSLINGPOCKPOS].usItem].twohanded && pSoldier->inv[SECONDHANDPOS].exists() == true)
handFit = FALSE;
if( handFit == TRUE && slingFit == TRUE)
{
SwapObjs(&pSoldier->inv[HANDPOS], &pSoldier->inv[GUNSLINGPOCKPOS]);
@@ -3869,7 +3877,11 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
if ( fCtrl && fShift && fAlt && !is_networked)// ary-05/05/2009 : add forced turn mode
{
ToggleTurnMode();
}
}
else if ( fCtrl && fShift )
{
SaveGame( SAVE__TIMED_AUTOSAVE, L"Auto Save" );
}
else
{
//resort Team by ubID
@@ -4877,19 +4889,6 @@ void RandomizeMercProfile()
}
}
void JumpFence()
{
SOLDIERTYPE *pSoldier;
INT8 bDirection;
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
{
if ( FindFenceJumpDirection( pSoldier, pSoldier->sGridNo, pSoldier->ubDirection, &bDirection ) )
{
pSoldier->BeginSoldierClimbFence( );
}
}
}
void CreateNextCivType()
{
INT16 sWorldX, sWorldY;
@@ -4979,6 +4978,37 @@ void CreateCow()
}
}
void CreateBloodCat()
{
INT16 sWorldX, sWorldY;
SOLDIERCREATE_STRUCT MercCreateStruct;
INT32 usMapPos;
// Get Grid Corrdinates of mouse
if ( GetMouseWorldCoordsInCenter( &sWorldX, &sWorldY ) && GetMouseMapPos( &usMapPos ) )
{
INT8 iNewIndex;
MercCreateStruct.ubProfile = NO_PROFILE;
MercCreateStruct.sSectorX = gWorldSectorX;
MercCreateStruct.sSectorY = gWorldSectorY;
MercCreateStruct.bSectorZ = gbWorldSectorZ;
MercCreateStruct.bBodyType = BLOODCAT;
//MercCreateStruct.bTeam = SOLDIER_CREATE_AUTO_TEAM;
MercCreateStruct.bTeam = CREATURE_TEAM;
MercCreateStruct.sInsertionGridNo = usMapPos;
RandomizeNewSoldierStats( &MercCreateStruct );
if ( TacticalCreateSoldier( &MercCreateStruct, (UINT8 *)&iNewIndex ) )
{
AddSoldierToSector( iNewIndex );
// So we can see them!
AllTeamsLookForAll(NO_INTERRUPTS);
}
}
}
void CreatePlayerControlledCow()
{
INT16 sWorldX, sWorldY;
@@ -5834,105 +5864,106 @@ void SwapGoggles(SOLDIERTYPE *pTeamSoldier)
{
// WDS - Smart goggle switching
// NOTE: Investigate using GetItemVisionRangeBonus from Items.cpp???
if (gGameExternalOptions.smartGoggleSwitch)
// Look through the head slots and find any sort of goggle or an empty spot
OBJECTTYPE * pGoggles = 0;
int slotToUse = -1;
INT8 swapSlot = -1;
BOOLEAN isAttach = FALSE;
for (int headSlot = HEAD1POS; headSlot <= HEAD2POS; ++headSlot)
{
// Look through the head slots and find any sort of goggle or an empty spot
int slotToUse = -1;
for (int headSlot = HEAD1POS; headSlot <= HEAD2POS; ++headSlot)
if ( (Item[pTeamSoldier->inv[headSlot].usItem].brightlightvisionrangebonus != 0) )
{
if ( (Item[pTeamSoldier->inv[headSlot].usItem].brightlightvisionrangebonus != 0) )
{
slotToUse = headSlot;
break;
}
if ( (Item[pTeamSoldier->inv[headSlot].usItem].dayvisionrangebonus != 0) )
{
slotToUse = headSlot;
break;
}
else if ( (Item[pTeamSoldier->inv[headSlot].usItem].nightvisionrangebonus != 0) )
{
slotToUse = headSlot;
break;
}
else if ( (Item[pTeamSoldier->inv[headSlot].usItem].cavevisionrangebonus != 0) )
{
slotToUse = headSlot;
break;
}
else if (pTeamSoldier->inv[headSlot].exists() == false)
{
slotToUse = headSlot;
}
}
if (slotToUse == -1)
{
// No place to swap in a new goggle, give up
return;
}
// Find the best goggles for the current time of day anywhere in inventory
// silversurfer: also check if underground
OBJECTTYPE * pGoggles = 0;
if (DayTime() && pTeamSoldier->bSectorZ == 0)
{
pGoggles = FindSunGogglesInInv( pTeamSoldier, TRUE );
slotToUse = headSlot;
break;
}
else
if ( (Item[pTeamSoldier->inv[headSlot].usItem].dayvisionrangebonus != 0) )
{
pGoggles = FindNightGogglesInInv( pTeamSoldier, TRUE );
slotToUse = headSlot;
break;
}
else if ( (Item[pTeamSoldier->inv[headSlot].usItem].nightvisionrangebonus != 0) )
{
slotToUse = headSlot;
break;
}
else if ( (Item[pTeamSoldier->inv[headSlot].usItem].cavevisionrangebonus != 0) )
{
slotToUse = headSlot;
break;
}
else if (pTeamSoldier->inv[headSlot].exists() == false)
{
slotToUse = headSlot;
}
}
if (slotToUse == -1)
{
// No place to swap in a new goggle, give up
return;
}
if (pGoggles)
// Find the best goggles for the current time of day anywhere in inventory
// silversurfer: also check if underground
if (DayTime() && pTeamSoldier->bSectorZ == 0)
{
pGoggles = FindSunGogglesInInv( pTeamSoldier, &swapSlot, &isAttach, TRUE );
}
else
{
pGoggles = FindNightGogglesInInv( pTeamSoldier, &swapSlot, &isAttach, TRUE );
}
if (pGoggles)
{
// We need to check that pGoggles is compatible with whatever is in the other face slot
int otherFaceSlot = (slotToUse == HEAD1POS?HEAD2POS:HEAD1POS);
if(pTeamSoldier->inv[otherFaceSlot].exists() == true && !CompatibleFaceItem(pGoggles->usItem, pTeamSoldier->inv[otherFaceSlot].usItem))
pGoggles = NULL;
}
if (pGoggles)
{
// Now either swap or equip the best one that was found
if (pTeamSoldier->inv[slotToUse].exists())
{
// Now either swap or equip the best one that was found
if (pTeamSoldier->inv[slotToUse].exists())
{
if(CanItemFitInPosition(pTeamSoldier, &pTeamSoldier->inv[slotToUse], swapSlot, TRUE))
SwapObjs( pTeamSoldier, slotToUse, pGoggles, TRUE );
}
else
{
else if((pTeamSoldier->inv[HELMETPOS].exists()== true && pTeamSoldier->inv[HELMETPOS].AttachObject(pTeamSoldier, &pTeamSoldier->inv[slotToUse], FALSE)) ||
AutoPlaceObject(pTeamSoldier, &pTeamSoldier->inv[slotToUse], FALSE))
pGoggles->MoveThisObjectTo(pTeamSoldier->inv[slotToUse], 1, pTeamSoldier, slotToUse);
else
{
CHAR16 zTemp[ 100 ];
swprintf( zTemp, Message[ STR_CANNOT_ATTACH_ANY_SLOT ], ItemNames[ pTeamSoldier->inv[slotToUse].usItem ] );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, zTemp );
}
}
else
{
// No goggles to equip, should the current ones be unequiped?
if (pTeamSoldier->inv[slotToUse].exists())
pGoggles->MoveThisObjectTo(pTeamSoldier->inv[slotToUse], 1, pTeamSoldier, slotToUse);
}
}
else
{
// No goggles to equip, should the current ones be unequiped?
if (pTeamSoldier->inv[slotToUse].exists())
{
if ((DayTime() && Item[pTeamSoldier->inv[slotToUse].usItem].nightvisionrangebonus > 0 && pTeamSoldier->bSectorZ == 0) ||
((!DayTime() || pTeamSoldier->bSectorZ > 0) && (Item[pTeamSoldier->inv[slotToUse].usItem].brightlightvisionrangebonus > 0)))
{
if ((DayTime() && Item[pTeamSoldier->inv[slotToUse].usItem].nightvisionrangebonus > 0 && pTeamSoldier->bSectorZ == 0) ||
((!DayTime() || pTeamSoldier->bSectorZ > 0) && (Item[pTeamSoldier->inv[slotToUse].usItem].brightlightvisionrangebonus > 0)))
// It's day and we're wearing night goggles (or vice-versa), find a place to stash them
if (pTeamSoldier->inv[ HELMETPOS ].exists())
{
// It's day and we're wearing night goggles (or vice-versa), find a place to stash them
if (pTeamSoldier->inv[ HELMETPOS ].exists())
if (pTeamSoldier->inv[ HELMETPOS ].AttachObject( NULL, &pTeamSoldier->inv[slotToUse] ))
{
if (pTeamSoldier->inv[ HELMETPOS ].AttachObject( NULL, &pTeamSoldier->inv[slotToUse] ))
{
// It worked!
}
else
{
/* //If we're here we already know we can't attach, don't we?
// Try dumping it anywhere in inventory because it doesn't attach to the helmet
if (NASValidAttachment( pTeamSoldier->inv[slotToUse].usItem, pTeamSoldier->inv[HELMETPOS].usItem ) &&
pTeamSoldier->inv[slotToUse][0]->attachments.size() < MAX_ATTACHMENTS)
{
pTeamSoldier->inv[HELMETPOS].AttachObject( pTeamSoldier, &pTeamSoldier->inv[slotToUse], FALSE, 0 );
}
else
*/
//{
// Remove sungoggles.
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[slotToUse], FALSE);
//}
}
// It worked!
}
else
{
/* //again useless?
// Try dumping it anywhere in inventory given there's no helemt
/* //If we're here we already know we can't attach, don't we?
// Try dumping it anywhere in inventory because it doesn't attach to the helmet
if (NASValidAttachment( pTeamSoldier->inv[slotToUse].usItem, pTeamSoldier->inv[HELMETPOS].usItem ) &&
pTeamSoldier->inv[slotToUse][0]->attachments.size() < MAX_ATTACHMENTS)
{
@@ -5945,174 +5976,22 @@ void SwapGoggles(SOLDIERTYPE *pTeamSoldier)
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[slotToUse], FALSE);
//}
}
}
}
}
}
else
{
// Normal goggle switching
/* CHRISL - Adjusted this option to allow the game to search through Helmet attachments
as well as inventory positions.
*/
OBJECTTYPE * pObj;
OBJECTTYPE * pGoggles = NULL;
INT8 bSlot1;
int bestBonus;
bool itemFound = false;
//CHRISL: Before doing anything, we should look at both head slots to see if either slot has some sort of goggles
for(bSlot1 = HEAD1POS; bSlot1 <= HEAD2POS; bSlot1++)
{
if(Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus > 0)
itemFound = true;
if(Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus > 0)
itemFound = true;
}
//2 head slots
for (bSlot1 = HEAD1POS; bSlot1 <= HEAD2POS; bSlot1++)
{
// if wearing sungoggles
if ( Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus > 0 )
{
itemFound = true;
bestBonus = 0;
pGoggles = FindNightGogglesInInv( pTeamSoldier );
//search for better goggles on the helmet
if (pGoggles)
}
else
{
bestBonus = Item[pGoggles->usItem].nightvisionrangebonus;
}
//search helmet and vest
for(UINT8 gear = HELMETPOS; gear <= VESTPOS; gear++)
{
pObj = &(pTeamSoldier->inv[gear]);
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
/* //again useless?
// Try dumping it anywhere in inventory given there's no helemt
if (NASValidAttachment( pTeamSoldier->inv[slotToUse].usItem, pTeamSoldier->inv[HELMETPOS].usItem ) &&
pTeamSoldier->inv[slotToUse][0]->attachments.size() < MAX_ATTACHMENTS)
{
if ( Item[ iter->usItem ].nightvisionrangebonus > bestBonus && Item[ iter->usItem ].usItemClass == IC_FACE && iter->exists())
{
pGoggles = &(*iter);
bestBonus = Item[ iter->usItem ].nightvisionrangebonus;
}
}
}
if ( pGoggles )
{
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
break;
}
// HEADROCK HAM B2.8: If no goggles were found to switch to, the character will remove what they're
// wearing, to avoid situations where a character refuses to remove the wrong set of goggles and
// thus suffers a penalty.
else
{ //WarmSteel - This has become more complicated to check, it's better to just try and see if it works.
//if (NASValidAttachment( pTeamSoldier->inv[bSlot1].usItem, pTeamSoldier->inv[HELMETPOS].usItem ) &&
// pTeamSoldier->inv[bSlot1][0]->attachments.size() < MAX_ATTACHMENTS )
if (pTeamSoldier->inv[HELMETPOS].AttachObject( pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE, 0 ) )
{
//pTeamSoldier->inv[HELMETPOS].AttachObject( pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE, 0 );
break;
pTeamSoldier->inv[HELMETPOS].AttachObject( pTeamSoldier, &pTeamSoldier->inv[slotToUse], FALSE, 0 );
}
else
{
*/
//{
// Remove sungoggles.
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE);
break;
}
}
}
// else if wearing NVGs
else if(Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus > 0)
{
itemFound = true;
bestBonus = 0;
pGoggles = FindSunGogglesInInv( pTeamSoldier );
//search for better goggles on the helmet
if (pGoggles)
{
bestBonus = Item[pGoggles->usItem].brightlightvisionrangebonus;
}
//search helmet and vest
for(UINT8 gear = HELMETPOS; gear <= VESTPOS; gear++)
{
pObj = &(pTeamSoldier->inv[gear]);
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
if ( Item[ iter->usItem ].brightlightvisionrangebonus > bestBonus && Item[ iter->usItem ].usItemClass == IC_FACE )
{
pGoggles = &(*iter);
bestBonus = Item[ iter->usItem ].brightlightvisionrangebonus;
}
}
}
if ( pGoggles )
{
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
break;
}
// HEADROCK HAM B2.8: If no goggles were found to switch to, the character will remove what they're
// wearing, to avoid situations where a character refuses to remove the wrong set of goggles and
// thus suffers a penalty.
else
{ //WarmSteel - Again, better to just try and see if it works.
//if (NASValidAttachment( pTeamSoldier->inv[bSlot1].usItem, pTeamSoldier->inv[HELMETPOS].usItem ) &&
// pTeamSoldier->inv[bSlot1][0]->attachments.size() < MAX_ATTACHMENTS)
if (pTeamSoldier->inv[HELMETPOS].AttachObject( pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE, 0 ))
{
break;
}
else
{
// Remove nightgoggles.
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE);
break;
}
}
}
// else if not wearing anything and no goggles found
else if(itemFound == false && pTeamSoldier->inv[bSlot1].exists() == false)
{
bestBonus = 0;
// search helmet and vest for goggles of some kind
for(UINT8 gear = HELMETPOS; gear <= VESTPOS; gear++)
{
pObj = &(pTeamSoldier->inv[gear]);
for(attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
{
if(iter->exists()){
if(DayTime() == TRUE && Item[iter->usItem].brightlightvisionrangebonus > bestBonus && Item[iter->usItem].usItemClass == IC_FACE)
{
pGoggles = &(*iter);
bestBonus = Item[iter->usItem].brightlightvisionrangebonus;
}
else if(NightTime() == TRUE && Item[iter->usItem].nightvisionrangebonus > bestBonus && Item[iter->usItem].usItemClass == IC_FACE)
{
pGoggles = &(*iter);
bestBonus = Item[iter->usItem].nightvisionrangebonus;
}
}
}
if(pGoggles)
{
pGoggles->MoveThisObjectTo(pTeamSoldier->inv[bSlot1], 1, pTeamSoldier, bSlot1);
pObj->RemoveAttachment(pGoggles);
break;
}
}
if(pTeamSoldier->inv[bSlot1].exists() == false)
{
if(DayTime() == TRUE)
pGoggles = FindSunGogglesInInv( pTeamSoldier );
else
pGoggles = FindNightGogglesInInv( pTeamSoldier );
if(pGoggles)
{
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
break;
}
}
else
{
break;
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[slotToUse], FALSE);
//}
}
}
}
@@ -6140,6 +6019,8 @@ void SwapGogglesUniformly(SOLDIERTYPE *pTeamSoldier, BOOLEAN fToNightVision)
INT8 bSlot1;
int bestBonus;
bool itemFound = false;
INT8 swapSlot = -1;
BOOLEAN isAttach = FALSE;
//CHRISL: Before doing anything, we should look at both head slots to see if either slot has some sort of goggles
for(bSlot1 = HEAD1POS; bSlot1 <= HEAD2POS; bSlot1++)
@@ -6159,7 +6040,7 @@ void SwapGogglesUniformly(SOLDIERTYPE *pTeamSoldier, BOOLEAN fToNightVision)
{
itemFound = true;
bestBonus = 0;
pGoggles = FindNightGogglesInInv( pTeamSoldier );
pGoggles = FindNightGogglesInInv( pTeamSoldier, &swapSlot, &isAttach );
//search for better goggles on the helmet
if (pGoggles)
{
@@ -6207,7 +6088,7 @@ void SwapGogglesUniformly(SOLDIERTYPE *pTeamSoldier, BOOLEAN fToNightVision)
{
itemFound = true;
bestBonus = 0;
pGoggles = FindSunGogglesInInv( pTeamSoldier );
pGoggles = FindSunGogglesInInv( pTeamSoldier, &swapSlot, &isAttach );
//search for better goggles on the helmet
if (pGoggles)
{
@@ -6281,9 +6162,9 @@ void SwapGogglesUniformly(SOLDIERTYPE *pTeamSoldier, BOOLEAN fToNightVision)
if(pTeamSoldier->inv[bSlot1].exists() == false)
{
if(fToNightVision == FALSE)
pGoggles = FindSunGogglesInInv( pTeamSoldier );
pGoggles = FindSunGogglesInInv( pTeamSoldier, &swapSlot, &isAttach );
else
pGoggles = FindNightGogglesInInv( pTeamSoldier );
pGoggles = FindNightGogglesInInv( pTeamSoldier, &swapSlot, &isAttach );
if(pGoggles)
{
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
@@ -6612,50 +6493,52 @@ void QueryTBX1Button( UINT32 *puiNewEvent )
//*puiNewEvent = LC_LOOK;
fX1ButtonDown = FALSE;
if ( !_KeyDown( ALT ) && !_KeyDown( SHIFT ))
UIHandleChangeLevel( NULL );
{
UIHandleChangeLevel( NULL );
}
else if( _KeyDown( SHIFT ) )
{
// WANNE: Jump through window?
if (gGameExternalOptions.fCanJumpThroughWindows == TRUE )
{
INT16 sAPCost;
INT16 sBPCost;
SOLDIERTYPE *pjSoldier;
BOOLEAN fNearHeigherLevel;
BOOLEAN fNearLowerLevel;
INT8 bDirection;
if ( GetSoldier( &pjSoldier, gusSelectedSoldier ) )
{
// CHRISL: Turn off manual jumping while wearing a backpack
if(UsingNewInventorySystem() == true && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
return;
// Make sure the merc is not collapsed!
if (!IsValidStance(pjSoldier, ANIM_CROUCH) )
if ( FindWindowJumpDirection( pjSoldier, pjSoldier->sGridNo, pjSoldier->ubDirection, &bDirection ) )
{
if ( pjSoldier->bCollapsed && pjSoldier->bBreath < OKBREATH )
if((UsingNewInventorySystem() == true) && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, gzLateLocalizedString[ 4 ], pjSoldier->name );
sAPCost = GetAPsToJumpThroughWindows( pjSoldier, TRUE );
sBPCost = GetBPsToJumpThroughWindows( pjSoldier, TRUE );
}
else
{
sAPCost = GetAPsToJumpFence( pjSoldier, FALSE );
sBPCost = GetBPsToJumpFence( pjSoldier, FALSE );
}
return;
if (EnoughPoints(pjSoldier, sAPCost, sBPCost, FALSE))
{
pjSoldier->BeginSoldierClimbWindow();
}
}
GetMercOknoDirection( pjSoldier->ubID, &fNearLowerLevel, &fNearHeigherLevel );
if ( FindWindowJumpDirection( pjSoldier, pjSoldier->sGridNo, pjSoldier->ubDirection, &bDirection ) )
{
pjSoldier->BeginSoldierClimbWindow();
}
}
}
}
else if (_KeyDown( ALT ) )
{
SOLDIERTYPE *pjSoldier;
if ( GetSoldier( &pjSoldier, gusSelectedSoldier ) )
{
INT16 sAPCost;
INT16 sBPCost;
BOOLEAN fNearHeigherLevel;
BOOLEAN fNearLowerLevel;
INT8 bDirection;
// CHRISL: Turn off manual jumping while wearing a backpack
if(UsingNewInventorySystem() == true && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
return;
// Make sure the merc is not collapsed!
if (!IsValidStance(pjSoldier, ANIM_CROUCH) )
@@ -6665,23 +6548,74 @@ void QueryTBX1Button( UINT32 *puiNewEvent )
return;
}
// Climb on roofs
GetMercClimbDirection( pjSoldier->ubID, &fNearLowerLevel, &fNearHeigherLevel );
if ( fNearLowerLevel )
pjSoldier->BeginSoldierClimbDownRoof( );
{
// CHRISL: Turn off manual jumping while wearing a backpack
if(UsingNewInventorySystem() == true && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
return;
if ( EnoughPoints( pjSoldier, GetAPsToClimbRoof( pjSoldier, TRUE ), GetBPsToClimbRoof( pjSoldier, TRUE ), FALSE ) )
{
pjSoldier->BeginSoldierClimbDownRoof( );
}
}
if ( fNearHeigherLevel )
pjSoldier->BeginSoldierClimbUpRoof( );
if ( FindFenceJumpDirection( pjSoldier, pjSoldier->sGridNo, pjSoldier->ubDirection, &bDirection ) )
pjSoldier->BeginSoldierClimbFence( );
}
}//else
{
// No climbing when wearing a backpack!
if((UsingNewInventorySystem() == true) && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
return;
if ( EnoughPoints( pjSoldier, GetAPsToClimbRoof( pjSoldier, FALSE ), GetBPsToClimbRoof( pjSoldier, FALSE ), FALSE ) )
{
pjSoldier->BeginSoldierClimbUpRoof( );
}
}
// Jump over fence
if ( FindFenceJumpDirection( pjSoldier, pjSoldier->sGridNo, pjSoldier->ubDirection, &bDirection ) )
{
if((UsingNewInventorySystem() == true) && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
{
sAPCost = GetAPsToJumpFence( pjSoldier, TRUE );
sBPCost = GetBPsToJumpFence( pjSoldier, TRUE );
}
else
{
sAPCost = GetAPsToJumpFence( pjSoldier, FALSE );
sBPCost = GetBPsToJumpFence( pjSoldier, FALSE );
}
if ( EnoughPoints( pjSoldier, sAPCost, sBPCost, FALSE ) )
{
pjSoldier->BeginSoldierClimbFence( );
}
}
// Climb on walls
if (gGameExternalOptions.fCanClimbOnWalls == TRUE)
{
if ( FindWallJumpDirection( pjSoldier, pjSoldier->sGridNo, pjSoldier->ubDirection, &bDirection ) )
{
// No climbing when wearing a backpack!
if((UsingNewInventorySystem() == true) && pjSoldier->inv[BPACKPOCKPOS].exists() == true)
return;
if ( EnoughPoints( pjSoldier, GetAPsToJumpWall( pjSoldier, FALSE ), GetBPsToJumpWall( pjSoldier, FALSE ), FALSE ) )
{
pjSoldier->BeginSoldierClimbWall( );
}
}
}
}
}
}
}
}
void QueryTBX2Button( UINT32 *puiNewEvent )
{
INT32 sMapPos;
+32 -30
View File
@@ -383,12 +383,12 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
{
INT16 sCurAPCosts, sAPCosts;
sCurAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, 0);
sCurAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, pSoldier->aiData.bShownAimTime);
do
{
pSoldier->bDoAutofire++;
sAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, 0);
sAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, pSoldier->aiData.bShownAimTime);
}
while(EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) && sAPCosts == sCurAPCosts && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire);
pSoldier->bDoAutofire--;
@@ -543,12 +543,12 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
do
{
pSoldier->bDoAutofire++;
sAPCosts = CalcTotalAPsToAttack( pSoldier, gsBurstLocations[0].sGridNo, TRUE, 0);
sAPCosts = CalcTotalAPsToAttack( pSoldier, gsBurstLocations[0].sGridNo, TRUE, pSoldier->aiData.bShownAimTime);
}
while(EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire && gbNumBurstLocations >= pSoldier->bDoAutofire);
pSoldier->bDoAutofire--;
gsCurrentActionPoints = CalcTotalAPsToAttack( pSoldier, gsBurstLocations[0].sGridNo, TRUE, 0 );
gsCurrentActionPoints = CalcTotalAPsToAttack( pSoldier, gsBurstLocations[0].sGridNo, TRUE, pSoldier->aiData.bShownAimTime );
}
}
@@ -576,11 +576,13 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
}
else
{
//usCursor = ACTION_TARGETREDBURST_UICURSOR;
usCursor = ACTION_TARGETCONFIRMBURST_UICURSOR;
// HEADROCK HAM B1: Burst cursor now shows multiple CTH bars (one for each bullet)
// and also a Targetted Bodypart indicator.
if(pSoldier->bDoAutofire == 0 && gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
//if(pSoldier->bDoAutofire == 0 && gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
if(pSoldier->bDoAutofire == 0)
{
if(UsingNewCTHSystem() == true)
{
@@ -596,6 +598,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
uiHitChance = ChanceToHitApproximation( pSoldier, uiHitChance );
}
gfUICtHBar = TRUE;
gbCtHBurstCount = 0;
gCTHDisplay.MuzzleSwayPercentage = (gCTHDisplay.MuzzleSwayPercentage + uiHitChance)/2;
gCTHDisplay.iShooterGridNo = pSoldier->sGridNo;
gCTHDisplay.iTargetGridNo = usMapPos;
@@ -609,7 +612,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
pSoldier->bTargetLevel = bTempTargetLevel;
}
else
else if(gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
{
if (gGameExternalOptions.ubNewCTHBars == 1 || gGameExternalOptions.ubNewCTHBars == 2)
{
@@ -632,7 +635,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
// Calculate hit chance (using the current bDoBurst for burst-penalty calculations)
UINT32 uiHitChance;
uiHitChance = CalcChanceToHitGun( pSoldier, usMapPos, 0, pSoldier->bAimShotLocation );
uiHitChance = CalcChanceToHitGun( pSoldier, usMapPos, (INT8)(pSoldier->aiData.bShownAimTime ), pSoldier->bAimShotLocation );
// HEADROCK HAM B2.7: CTH approximation?
if (gGameExternalOptions.fApproximateCTH)
{
@@ -660,7 +663,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
pSoldier->bTargetLevel = (INT8) gsInterfaceLevel;
UINT32 uiHitChance;
uiHitChance = CalcChanceToHitGun( pSoldier, usMapPos, 0, pSoldier->bAimShotLocation );
uiHitChance = CalcChanceToHitGun( pSoldier, usMapPos, (INT8)(pSoldier->aiData.bShownAimTime ), pSoldier->bAimShotLocation );
// HEADROCK HAM B2.7: CTH approximation?
if (gGameExternalOptions.fApproximateCTH)
{
@@ -679,7 +682,8 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
// HEADROCK HAM B2: Now autofire will show both its starting CTH and the CTH of the last
// bullet in the volley.
else if(pSoldier->bDoAutofire > 0 && gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
//else if(pSoldier->bDoAutofire > 0 && gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
else if(pSoldier->bDoAutofire > 0)
{
if(UsingNewCTHSystem() == true)
{
@@ -703,6 +707,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
// Flag to tell the program to draw two CTH bars.
gfUICtHBar = TRUE;
gbCtHBurstCount = 0;
// Calculate distance to target
FLOAT dDeltaX = (FLOAT)(CenterX( pSoldier->sGridNo ) - CenterX( usMapPos ));
@@ -713,7 +718,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
pSoldier->bTargetLevel = bTempTargetLevel;
}
else
else if(gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
{
if (gGameExternalOptions.ubNewCTHBars == 1 || gGameExternalOptions.ubNewCTHBars == 3)
{
@@ -725,7 +730,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
UINT32 uiHitChance;
// Calculate CTH for the first bullet
uiHitChance = CalcChanceToHitGun( pSoldier, usMapPos, 0, pSoldier->bAimShotLocation );
uiHitChance = CalcChanceToHitGun( pSoldier, usMapPos, (INT8)(pSoldier->aiData.bShownAimTime ), pSoldier->bAimShotLocation );
// HEADROCK HAM B2.7: CTH approximation?
if (gGameExternalOptions.fApproximateCTH)
{
@@ -741,7 +746,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
UINT8 saveDoBurst = pSoldier->bDoBurst;
pSoldier->bDoBurst = pSoldier->bDoAutofire;
uiHitChance = CalcChanceToHitGun( pSoldier, usMapPos, 0, pSoldier->bAimShotLocation );
uiHitChance = CalcChanceToHitGun( pSoldier, usMapPos, (INT8)(pSoldier->aiData.bShownAimTime ), pSoldier->bAimShotLocation );
// HEADROCK HAM B2.7: CTH approximation?
if (gGameExternalOptions.fApproximateCTH)
{
@@ -766,7 +771,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
else
{
//DIGICRAB: Graphical CtH
if(gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
//if(gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
{
//AXP 29.03.2007: Rooftop CtH fix. Temporarily set soldier targetlevel to the real interface
//level (selected with TAB), so the first shot after switching TL is calculated correctly
@@ -799,6 +804,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
if(UsingNewCTHSystem() == true)
{
gfUICtHBar = TRUE;
gbCtHBurstCount = 0;
// CTH for the first bullet is entered into this array, and later displayed
gCTHDisplay.MuzzleSwayPercentage = (gCTHDisplay.MuzzleSwayPercentage + uiHitChance)/2;
@@ -815,7 +821,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos, BOOLEA
pSoldier->bTargetLevel = bTempTargetLevel;
if(UsingNewCTHSystem() == false)
if(UsingNewCTHSystem() == false && gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
{
gfUICtHBar = TRUE;
gbCtHBurstCount = 1;
@@ -2189,15 +2195,11 @@ void HandleLeftClickCursor( SOLDIERTYPE *pSoldier )
if ( gTacticalStatus.uiFlags & TURNBASED && (gTacticalStatus.uiFlags & INCOMBAT ) )
{
pSoldier->aiData.bShownAimTime = REFINE_AIM_1;
// HEADROCK HAM 4: Reset Bullet Count for Autofire
fAutofireBulletsMode = FALSE;
pSoldier->flags.fPauseAim = FALSE;
}
else
{
pSoldier->aiData.bShownAimTime = REFINE_AIM_1;
// HEADROCK HAM 4: Reset Bullet Count for Autofire
fAutofireBulletsMode = FALSE;
pSoldier->flags.fPauseAim = FALSE;
}
// Reset counter
@@ -2308,11 +2310,11 @@ void HandleRightClickAdjustCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos )
if(pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft > pSoldier->bDoAutofire )
{
//Calculate how many bullets we need to fire to add at least one more AP
sAPCosts = sCurAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, 0);
sAPCosts = sCurAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, pSoldier->aiData.bShownAimTime);
while(EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) && sAPCosts <= sCurAPCosts && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft > pSoldier->bDoAutofire) //Increment the bullet count until we run out of APs or we spend the whole AP
{
pSoldier->bDoAutofire++;
sAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, 0);
sAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, pSoldier->aiData.bShownAimTime);
}
//we've stepped over the border and used up one more ap, now let's make sure that it is spent to maximize the bullets
@@ -2322,12 +2324,12 @@ void HandleRightClickAdjustCursor( SOLDIERTYPE *pSoldier, INT32 usMapPos )
do
{
pSoldier->bDoAutofire++;
sAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, 0);
sAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, pSoldier->aiData.bShownAimTime);
}
while(EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) && sAPCosts == sCurAPCosts && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire);
pSoldier->bDoAutofire--;
sAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, 0);
sAPCosts = CalcTotalAPsToAttack( pSoldier, usMapPos, TRUE, pSoldier->aiData.bShownAimTime);
if(!EnoughPoints( pSoldier, sAPCosts, 0, FALSE )) //We've not enough points to fire those bullets
{
@@ -3180,11 +3182,11 @@ void HandleWheelAdjustCursor( SOLDIERTYPE *pSoldier, INT32 sMapPos, INT32 sDelta
if(pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft > pSoldier->bDoAutofire )
{
//Calculate how many bullets we need to fire to add at least one more AP
sAPCosts = sCurAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, 0);
sAPCosts = sCurAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, pSoldier->aiData.bShownAimTime);
while(EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) && sAPCosts <= sCurAPCosts && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft > pSoldier->bDoAutofire) //Increment the bullet count until we run out of APs or we spend the whole AP
{
pSoldier->bDoAutofire++;
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, 0);
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, pSoldier->aiData.bShownAimTime);
}
//we've stepped over the border and used up one more ap, now let's make sure that it is spent to maximize the bullets
@@ -3194,12 +3196,12 @@ void HandleWheelAdjustCursor( SOLDIERTYPE *pSoldier, INT32 sMapPos, INT32 sDelta
do
{
pSoldier->bDoAutofire+=sDelta;
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, 0);
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, pSoldier->aiData.bShownAimTime);
}
while(EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) && sAPCosts == sCurAPCosts && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire);
pSoldier->bDoAutofire--;
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, 0);
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, pSoldier->aiData.bShownAimTime);
if(!EnoughPoints( pSoldier, sAPCosts, 0, FALSE )) //We've not enough points to fire those bullets
{
@@ -3398,11 +3400,11 @@ void HandleWheelAdjustCursorWOAB( SOLDIERTYPE *pSoldier, INT32 sMapPos, INT32 sD
if(pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft > pSoldier->bDoAutofire )
{
//Calculate how many bullets we need to fire to add at least one more AP
sAPCosts = sCurAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, 0);
sAPCosts = sCurAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, pSoldier->aiData.bShownAimTime);
while(EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) && sAPCosts <= sCurAPCosts && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft > pSoldier->bDoAutofire) //Increment the bullet count until we run out of APs or we spend the whole AP
{
pSoldier->bDoAutofire++;
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, 0);
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, pSoldier->aiData.bShownAimTime);
}
//we've stepped over the border and used up one more ap, now let's make sure that it is spent to maximize the bullets
@@ -3412,12 +3414,12 @@ void HandleWheelAdjustCursorWOAB( SOLDIERTYPE *pSoldier, INT32 sMapPos, INT32 sD
do
{
pSoldier->bDoAutofire+=sDelta;
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, 0);
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, pSoldier->aiData.bShownAimTime);
}
while(EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) && sAPCosts == sCurAPCosts && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire);
pSoldier->bDoAutofire--;
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, 0);
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, pSoldier->aiData.bShownAimTime);
if(!EnoughPoints( pSoldier, sAPCosts, 0, FALSE )) //We've not enough points to fire those bullets
{
+2 -2
View File
@@ -3,10 +3,10 @@
#define REFINE_PUNCH_1 0
#define REFINE_PUNCH_2 6
#define REFINE_PUNCH_2 gGameExternalOptions.fEnhancedCloseCombatSystem ? gSkillTraitValues.ubModifierForAPsAddedOnAimedPunches : 6
#define REFINE_KNIFE_1 0
#define REFINE_KNIFE_2 6
#define REFINE_KNIFE_2 gGameExternalOptions.fEnhancedCloseCombatSystem ? gSkillTraitValues.ubModifierForAPsAddedOnAimedBladedAttackes : 6
UINT8 GetProperItemCursor( UINT8 ubSoldierID, UINT16 ubItemIndex, INT32 usMapPos, BOOLEAN fActivated );
+15 -1
View File
@@ -1049,6 +1049,20 @@ BOOLEAN CopyVehiclePathToSoldier( SOLDIERTYPE *pSoldier )
}
BOOLEAN IsVehicle(SOLDIERTYPE *pSoldier)
{
switch(pSoldier->ubProfile)
{
case PROF_HUMMER:
case PROF_ELDERODO:
case PROF_ICECREAM:
return(TRUE);
default:
return(FALSE);
}
return(FALSE);
}
BOOLEAN SetUpMvtGroupForVehicle( SOLDIERTYPE *pSoldier )
{
@@ -1428,7 +1442,7 @@ void SetDriver( INT32 iID, UINT8 ubID )
#ifdef JA2TESTVERSION
void VehicleTest( void )
{
SetUpHelicopterForPlayer( 9,1 );
SetUpHelicopterForPlayer( 9,1, SKYRIDER );
}
#endif
+3
View File
@@ -123,6 +123,9 @@ INT32 GetTravelTimeOfVehicle( INT32 iId );
// is this vehicle a valid one?
BOOLEAN VehicleIdIsValid( INT32 iId );
// Test whether a soldier is actually a vehicle
BOOLEAN IsVehicle(SOLDIERTYPE *pSoldier);
// set up vehicle mvt for this grunt involved
BOOLEAN SetUpMvtGroupForVehicle( SOLDIERTYPE *pSoldier );
+51 -40
View File
@@ -422,7 +422,8 @@ weaponStartElementHandle(void *userData, const XML_Char *name, const XML_Char **
strcmp(name, "ubAimLevels") == 0 ||// HEADROCK HAM 4: Allowed aiming levels for this gun.
strcmp(name, "bRecoilX") == 0 || // HEADROCK HAM 4:
strcmp(name, "bRecoilY") == 0 || // HEADROCK HAM 4:
strcmp(name, "ubRecoilDelay") == 0)) // HEADROCK HAM 4:
strcmp(name, "ubRecoilDelay") == 0 || // HEADROCK HAM 4:
strcmp(name, "Handling") == 0)) // CHRISL HAM 4:
{
pData->curElement = WEAPON_ELEMENT_WEAPON_PROPERY;
@@ -550,7 +551,7 @@ weaponEndElementHandle(void *userData, const XML_Char *name)
else if(strcmp(name, "ubMagSize") == 0)
{
pData->curElement = WEAPON_ELEMENT_WEAPON;
pData->curWeapon.ubMagSize = (UINT8) atol(pData->szCharData);
pData->curWeapon.ubMagSize = (UINT16) atol(pData->szCharData);
}
else if(strcmp(name, "usRange") == 0)
{
@@ -682,6 +683,11 @@ weaponEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = WEAPON_ELEMENT_WEAPON;
pData->curWeapon.ubRecoilDelay = (INT8) atol(pData->szCharData);
}
else if(strcmp(name, "Handling") == 0)
{
pData->curElement = WEAPON_ELEMENT_WEAPON;
pData->curWeapon.ubHandling = (UINT8) atol(pData->szCharData);
}
pData->maxReadDepth--;
}
@@ -839,9 +845,10 @@ BOOLEAN ReadInWeaponStats(STR fileName)
FilePrintf(hFile,"\t\t<APsToReloadManually>%d</APsToReloadManually>\r\n", Weapon[cnt].APsToReloadManually);
FilePrintf(hFile,"\t\t<ManualReloadSound>%d</ManualReloadSound>\r\n", Weapon[cnt].ManualReloadSound);
FilePrintf(hFile,"\t\t<ubAimLevels>%d</ubAimLevels>\r\n", Weapon[cnt].ubAimLevels);
FilePrintf(hFile,"\t\t<bRecoilX>%d<\bRecoilX>\r\n", Weapon[cnt].bRecoilX);
FilePrintf(hFile,"\t\t<bRecoilY>%d<\bRecoilY>\r\n", Weapon[cnt].bRecoilY);
FilePrintf(hFile,"\t\t<ubRecoilDelay>%d<\ubRecoilDelay>\r\n", Weapon[cnt].ubRecoilDelay);
FilePrintf(hFile,"\t\t<bRecoilX>%d</bRecoilX>\r\n", Weapon[cnt].bRecoilX);
FilePrintf(hFile,"\t\t<bRecoilY>%d</bRecoilY>\r\n", Weapon[cnt].bRecoilY);
FilePrintf(hFile,"\t\t<ubRecoilDelay>%d</ubRecoilDelay>\r\n", Weapon[cnt].ubRecoilDelay);
FilePrintf(hFile,"\t\t<Handling>%d</Handling>\r\n", Weapon[cnt].ubHandling);
FilePrintf(hFile,"\t</WEAPON>\r\n");
}
FilePrintf(hFile,"</WEAPONLIST>\r\n");
@@ -955,6 +962,7 @@ BOOLEAN WriteWeaponStats()
FilePrintf(hFile,"\t\t<NoSemiAuto>%d</NoSemiAuto>\r\n", Weapon[cnt].NoSemiAuto);
FilePrintf(hFile,"\t\t<ubAimLevels>%d</ubAimLevels>\r\n", Weapon[cnt].ubAimLevels );
FilePrintf(hFile,"\t\t<EasyUnjam>%d</EasyUnjam>\r\n", Weapon[cnt].EasyUnjam);
FilePrintf(hFile,"\t\t<Handling>%d</Handling>\r\n", Weapon[cnt].ubHandling);
@@ -3790,7 +3798,7 @@ BOOLEAN UseLauncher( SOLDIERTYPE *pSoldier, INT32 sTargetGridNo )
//sAPCost = MinAPsToAttack( pSoldier, sTargetGridNo, TRUE );
sAPCost = CalcTotalAPsToAttack( pSoldier, sTargetGridNo, FALSE, 0 );
sAPCost = CalcTotalAPsToAttack( pSoldier, sTargetGridNo, FALSE, pSoldier->aiData.bShownAimTime );
}
else
@@ -4589,16 +4597,20 @@ UINT32 CalcNewChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
// make sure the guy's actually got a weapon in his hand!
pInHand = &(pSoldier->inv[pSoldier->ubAttackingHand]);
usInHand = pSoldier->usAttackingWeapon;
gCTHDisplay.fMaxAimReached = FALSE;
// calculate actual range (in units, 10 units = 1 tile)
iRange = GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo );
FLOAT dDeltaX = (FLOAT)(CenterX( pSoldier->sGridNo ) - CenterX( sGridNo ));
FLOAT dDeltaY = (FLOAT)(CenterY( pSoldier->sGridNo ) - CenterY( sGridNo ));
FLOAT d2DDistance = sqrt((dDeltaX*dDeltaX)+(dDeltaY*dDeltaY));
// Find a target in the tile
ubTargetID = WhoIsThere2( sGridNo, pSoldier->bTargetLevel ); // Target ubID
pTarget = SimpleFindSoldier( sGridNo, pSoldier->bTargetLevel ); // Target Pointer
// Calculate how easy it is to handle this gun.
FLOAT iGunDifficulty = (FLOAT)(( Weapon[ usInHand ].ubReadyTime * (100 - GetPercentReadyTimeAPReduction(pInHand) )) / 100);
FLOAT iGunDifficulty = (FLOAT)(( Weapon[ usInHand ].ubHandling * (100 - GetPercentReadyTimeAPReduction(pInHand) )) / 100);
iGunDifficulty *= (FLOAT)(100 / APBPConstants[AP_MAXIMUM]); // Adjust for 100AP/25AP
FLOAT iGunBaseDifficulty = iGunDifficulty;
FLOAT iGunAimDifficulty = iGunDifficulty;
@@ -4648,6 +4660,10 @@ UINT32 CalcNewChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
iSightRange = 1;
}
}
// CHRISL: There are conditions where iSightRange can still return 0. If that happens, the result is that "impossible" shots are actually easier then
// simply "really hard" shots. As a result, if we can't see the target and we have a 0 sight range, we need to create an iSightRange based on iRange
if(iSightRange == 0)
iSightRange = __max((INT16)(sDistVis*1.5), iRange*2);
if(iSightRange > sDistVis)
fCantSeeTarget = true;
@@ -4940,7 +4956,7 @@ UINT32 CalcNewChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
/////////////////////////////////////////////
// Now apply Gun Difficulty to the Base Modifier.
iBaseModifier += iGunBaseDifficulty * gGameCTHConstants.BASE_DRAW_COST;
iBaseModifier -= iGunBaseDifficulty * gGameCTHConstants.BASE_DRAW_COST;
// INJURY
if (pSoldier->stats.bLife < pSoldier->stats.bLifeMax)
@@ -5062,7 +5078,7 @@ UINT32 CalcNewChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
}
// AGILITY OR EXPERIENCE
FLOAT iTempPenalty = __max((pTarget->stats.bExpLevel*10), pTarget->stats.bAgility);
FLOAT iTempPenalty = (FLOAT)__max((pTarget->stats.bExpLevel*10), pTarget->stats.bAgility);
iBaseModifier += (iTempPenalty * gGameCTHConstants.BASE_AGILE_TARGET) / 100;
}
@@ -5126,7 +5142,7 @@ UINT32 CalcNewChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
{
// Are we using a scope? If so, what's the range factor?
FLOAT iScopeMagFactor = GetBestScopeMagnificationFactor( pInHand, (UINT32)iRange );
FLOAT iScopeMagFactor = GetBestScopeMagnificationFactor( pSoldier, pInHand, d2DDistance );
//CHRISL: This does make sense but it effectively makes high powered scopes worthless if a target is actually visible. As an example, a Battle Scope
// is going to have a iScopeMagFactor of 7. With a "NORMAL_SHOOTING_DISTANCE" also of 7, we're going to end up with uiBestScopeRange of 49. That's
// effectilvey saying that any target within 490m is "too close" for the scope to be effective. That by itself isn't realistic. But in JA2 it's also
@@ -5140,16 +5156,7 @@ UINT32 CalcNewChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
// uiBestScopeRange value in half. This should allow a Battle Scope to reach full effeciency at 24 tiles and a Sniper scope will be fully effecient at
// 35 tiles. ACOG becomes fully effecient at 14 tiles and 2x is fully effeciency at 7 tiles (compared to 28 and 14 respectively). This does mean that a
// 2x scope reaches full effeciency at the same point as "scopeless" shooting, but I don't think this will be a serious problem.
FLOAT rangeModifier = gGameCTHConstants.SCOPE_RANGE_MULTIPLIER;
if( gGameOptions.fNewTraitSystem )
{
if(iScopeMagFactor > .5)
rangeModifier -= (NUM_SKILL_TRAITS( pSoldier, SNIPER_NT ) * 0.05f);
else
rangeModifier -= (NUM_SKILL_TRAITS( pSoldier, RANGER_NT ) * 0.05f);
}
else
rangeModifier -= (NUM_SKILL_TRAITS( pSoldier, PROF_SNIPER_OT ) * 0.05f);
FLOAT rangeModifier = GetScopeRangeMultiplier(pSoldier, pInHand, (FLOAT)iRange);
UINT32 uiBestScopeRange = (UINT32)(iScopeMagFactor * gGameCTHConstants.NORMAL_SHOOTING_DISTANCE * rangeModifier);
FLOAT iAimModifier = 0;
@@ -5247,7 +5254,7 @@ UINT32 CalcNewChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
// End Gun Handling modifiers
//////////////////////////////////////////
iAimModifier += gGameCTHConstants.AIM_DRAW_COST * iGunAimDifficulty;
iAimModifier -= gGameCTHConstants.AIM_DRAW_COST * iGunAimDifficulty;
// VISIBILITY
if (iRange > 0 && iSightRange > iRange)
@@ -5478,8 +5485,12 @@ UINT32 CalcNewChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTi
iMaxAimBonus += iScopePenalty;
}
iMaxAimBonus = __max(0, iMaxAimBonus); // can't get less than 0 points for aiming...
// Now let's find out how many CTH points we get per aiming level.
UINT8 ubAllowedAimingLevels = AllowedAimingLevels( pSoldier, sGridNo );
if(ubAimTime == ubAllowedAimingLevels)
gCTHDisplay.fMaxAimReached = TRUE;
FLOAT dAimFractionsDivisor = 0.0;
for (UINT8 cnt = 0; cnt < ubAllowedAimingLevels; cnt++)
{
@@ -5945,7 +5956,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
iMaxRange = GunRange( pInHand, pSoldier ); // SANDRO - added argument
else
iMaxRange = CELL_X_SIZE; // one tile
iCoverRange = iSightRange - iRange;
iCoverRange = __max(0,iSightRange - iRange);
iMinRange = iMaxRange / 10;
iAccRangeMod = iRange * Weapon[usInHand].bAccuracy / 100;
/////////////////////////////////////////////////////////////////////////////////////
@@ -5964,9 +5975,11 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
iSightRange -= ((gbSkillTraitBonus[ PROF_SNIPER_OT ] * NUM_SKILL_TRAITS( pSoldier, PROF_SNIPER_OT )) * iSightRange) /100;
}
if (iRange < GetMinRangeForAimBonus(pInHand) && iScopeVisionRangeBonus > 50){ // iSightRange penalty for using a high power scope within min range due to poor focus
iPenalty = 0;
for(UINT8 loop = 0; loop < ((GetMinRangeForAimBonus(pInHand) - iRange)/CELL_X_SIZE); loop++){
iSightRange += iSightRange * iScopeVisionRangeBonus / 100;
iPenalty += iSightRange * iScopeVisionRangeBonus / 100;
}
iSightRange += iPenalty;
}
if (iSightRange < 1) {
iSightRange = 1;
@@ -6026,8 +6039,14 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
// From for JA2.5: 3% bonus/penalty for each tile different from range NORMAL_RANGE.
if (!TANK(pSoldier)) // WANNE: No penalty on the tank
iPenalty = 3 * ( NORMAL_RANGE - iSightRange ) / CELL_X_SIZE;
if ( fCantSeeTarget )
if ( fCantSeeTarget ){
// CHRISL: There are conditions where iSightRange can still return 0. If that happens, the result is that "impossible" shots are actually easier then
// simply "really hard" shots. As a result, if we can't see the target and we have a 0 sight range, we should reevaluate the above penalty but use
// iRange instead of iSightRange, then include the unseen penalty.
if(iSightRange == 0)
iPenalty = (3 * ( NORMAL_RANGE - iRange ) / CELL_X_SIZE) - gGameExternalOptions.iPenaltyShootUnSeen;
iPenalty = min(iPenalty, -gGameExternalOptions.iPenaltyShootUnSeen);
}
iChance += iPenalty;
//CHRISL: We should probably include these target size penalties even if we can't see the target so that shooting a "hidden" head is harder then a "hidden" body
// if aiming at the head, reduce chance to hit
@@ -6424,7 +6443,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime,
if ( pSoldier->bDoBurst && pSoldier->bDoAutofire == 0 )
{
/*CHRISL: At this point in the calculation, Bipods, Foregrips and other "recoil stabalizing" bonuses should reduce the weapons "recoil penalty"
(BurstPenalty) by a percentage. This reduction should apply the the recoil per shot and not as a "flat" initial reduction. Later in the code,
(BurstPenalty) by a percentage. This reduction should apply to the recoil per shot and not as a "flat" initial reduction. Later in the code,
Bipods also grant their flat CTH bonus so we don't need to mess this that here*/
if(gGameExternalOptions.ubFlatAFTHBtoPrecentMultiplier)
{
@@ -10680,7 +10699,7 @@ UINT16 GetMagSize( OBJECTTYPE *pObj, UINT8 subObject )
UINT16 GetExpMagSize( OBJECTTYPE *pObj )
{
// DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("GetMagSize"));
UINT8 magSize = 0;
UINT16 magSize = 0;
if(Item[pObj->usItem].usItemClass & IC_EXPLOSV)
magSize = Explosive[Item[pObj->usItem].ubClassIndex].ubMagSize;
else
@@ -10731,7 +10750,7 @@ void EstimateBulletsLeft( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj )
UINT16 usExpLevel;
UINT16 usDexterity;
UINT16 usWisdom;
UINT8 ubMagSize = Weapon[pObj->usItem].ubMagSize;
UINT16 ubMagSize = Weapon[pObj->usItem].ubMagSize;
UINT16 usRealBulletCount = (*pObj)[0]->data.gun.ubGunShotsLeft;
UINT16 i = 0;
BOOLEAN fPsycho = FALSE;
@@ -10868,29 +10887,21 @@ void CalcMagFactorSimple( SOLDIERTYPE *pSoldier, FLOAT d2DDistance, INT16 bAimTi
FLOAT iHighestMagFactor = 0;
FLOAT iScopeFactor = 0;
FLOAT iProjectionFactor = 0;
FLOAT iTargetMagFactor = 0;
BOOLEAN isScopeBetter = FALSE;
// Calculate the optimal magnification that would be required for the target's current distance.
iTargetMagFactor = d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE;
FLOAT iTargetMagFactor = d2DDistance / gGameCTHConstants.NORMAL_SHOOTING_DISTANCE;
FLOAT rangeModifier = GetScopeRangeMultiplier(pSoldier, pWeapon, d2DDistance);
if (bAimTime > 0)
{
iScopeFactor = GetBestScopeMagnificationFactor( pWeapon, (UINT32)d2DDistance );
iScopeFactor = GetBestScopeMagnificationFactor( pSoldier, pWeapon, d2DDistance );
// Set a display variable
gCTHDisplay.ScopeMagFactor = iScopeFactor;
iScopeFactor = __min(iScopeFactor, iTargetMagFactor);
iProjectionFactor = GetProjectionFactor( pWeapon );
iScopeFactor = __min(iScopeFactor, __max(1.0f, iTargetMagFactor/rangeModifier));
iProjectionFactor = CalcProjectionFactor(pSoldier, pWeapon, d2DDistance, (UINT8)bAimTime);
// Set a display variable
gCTHDisplay.ProjectionFactor = iProjectionFactor;
// The final factor is the largest of the two.
if (iScopeFactor > iProjectionFactor)
isScopeBetter=TRUE;
iHighestMagFactor = __max( iScopeFactor, iProjectionFactor );
}
else
+2 -1
View File
@@ -270,7 +270,7 @@ typedef struct
UINT8 ubDeadliness; // comparative ratings of guns
INT8 bAccuracy; // accuracy or penalty used by OCTH
INT8 nAccuracy; // accuracy or penalty used by NCTH
UINT8 ubMagSize;
UINT16 ubMagSize;
UINT16 usRange;
UINT16 usReloadDelay;
UINT8 ubAttackVolume;
@@ -306,6 +306,7 @@ typedef struct
UINT8 ubAimLevels; // HEADROCK HAM 4: Dictates how many aiming levels this gun supports. If 0, the program
// chooses automatically based on the type of gun (see AllowedAimingLevels() ).
UINT8 ubHandling; // CHRISL HAM 4: This value replaces ubReadyTime for determining a weapons base handling characteristics.
} WEAPONTYPE;
typedef struct
+9 -2
View File
@@ -460,10 +460,17 @@ INT32 AddItemToWorld( INT32 sGridNo, OBJECTTYPE *pObject, UINT8 ubLevel, UINT16
// OJW - 20091002 - Explosives
if (is_networked && is_client)
{
SOLDIERTYPE* pSoldier = NULL;
if (soldierID == -1)
soldierID = gWorldItems[ iItemIndex ].object[0]->data.misc.ubBombOwner - 2; // undo the hack
{
if (gWorldItems[ iItemIndex ].object[0]->data.misc.ubBombOwner > 1)
{
soldierID = gWorldItems[ iItemIndex ].object[0]->data.misc.ubBombOwner - 2; // undo the hack
pSoldier = MercPtrs[ soldierID ];
}
}
SOLDIERTYPE* pSoldier = MercPtrs[ soldierID ];
if (pSoldier != NULL)
{
// if soldier is on our team, or is AI and we are the server
+5
View File
@@ -189,6 +189,8 @@ typedef PARSE_STAGE;
#define QUOTEARRAYFILENAME "MercQuote.xml"
#define FACEGEARFILENAME "FaceGear.xml"
extern BOOLEAN ReadInItemStats(STR fileName, BOOLEAN localizedVersion);
extern BOOLEAN WriteItemStats();
@@ -389,4 +391,7 @@ extern BOOLEAN WriteAimAvailability(STR fileName);
extern BOOLEAN WriteQarray(QARRAY_VALUES *pQarray, STR fileName);
extern BOOLEAN ReadInQarray(QARRAY_VALUES *pQarray, STR fileName);
extern BOOLEAN WriteFaceGear();
extern BOOLEAN ReadInFaceGear( FACE_GEAR_VALUES *pFaceGear, STR fileName );
#endif
+14
View File
@@ -204,6 +204,20 @@ MercStartingGearEndElementHandle(void *userData, const XML_Char *name)
if(pData->curIndex < pData->maxArraySize && pData->curGears < NUM_MERCSTARTINGGEAR_KITS)
{
pData->curArray[pData->curIndex][pData->curGears] = pData->curMercStartingGear; //write the armour into the table
//CHRISL: after writing the gearkit, we need to clear gear data so it won't inadvertantly be reused
pData->curMercStartingGear.PriceModifier = 0;
for(unsigned int i = 0; i < pData->curMercStartingGear.inv.size(); i++)
{
pData->curMercStartingGear.inv[i] = 0;
pData->curMercStartingGear.iStatus[i] = 0;
pData->curMercStartingGear.iDrop[i] = 0;
pData->curMercStartingGear.iNumber[i] = 0;
}
for(unsigned int i = 0; i < pData->curMercStartingGear.lbe.size(); i++)
{
pData->curMercStartingGear.lbe[i] = 0;
pData->curMercStartingGear.lStatus[i] = 0;
}
}
pData->curElement = ELEMENT;
+230
View File
@@ -0,0 +1,230 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include "sgp.h"
#include "Debug Control.h"
#include "expat.h"
#include "XML.h"
#include "Interface.h"
#include "Faces.h"
#endif
struct
{
PARSE_STAGE curElement;
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
FACE_GEAR_VALUES curFaceGear;
FACE_GEAR_VALUES * curArray;
UINT32 maxArraySize;
UINT32 curIndex;
UINT32 currentDepth;
UINT32 maxReadDepth;
}
typedef faceGearParseData;
BOOLEAN FaceGear_TextOnly;
static void XMLCALL
faceGearStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
{
faceGearParseData * pData = (faceGearParseData *)userData;
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
{
if(strcmp(name, "FACE_GEAR") == 0 && pData->curElement == ELEMENT_NONE)
{
pData->curElement = ELEMENT_LIST;
memset(pData->curArray,0,sizeof(FACE_GEAR_VALUES)*pData->maxArraySize);
pData->maxReadDepth++; //we are not skipping this element
}
else if(strcmp(name, "ITEM") == 0 && pData->curElement == ELEMENT_LIST)
{
pData->curElement = ELEMENT;
memset(&pData->curFaceGear,0,sizeof(FACE_GEAR_VALUES));
pData->maxReadDepth++; //we are not skipping this element
}
else if(pData->curElement == ELEMENT &&
(strcmp(name, "uiIndex") == 0 ||
strcmp(name, "Type") == 0 ||
strcmp(name, "szFile") == 0 ))
{
pData->curElement = ELEMENT_PROPERTY;
pData->maxReadDepth++; //we are not skipping this element
}
pData->szCharData[0] = '\0';
}
pData->currentDepth++;
}
static void XMLCALL
faceGearCharacterDataHandle(void *userData, const XML_Char *str, int len)
{
faceGearParseData * pData = (faceGearParseData *)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
faceGearEndElementHandle(void *userData, const XML_Char *name)
{
char temp;
faceGearParseData * pData = (faceGearParseData *)userData;
if(pData->currentDepth <= pData->maxReadDepth)
{
if(strcmp(name, "FACE_GEAR") == 0)
{
pData->curElement = ELEMENT_NONE;
}
else if(strcmp(name, "ITEM") == 0)
{
pData->curElement = ELEMENT_LIST;
if(pData->curFaceGear.uiIndex < pData->maxArraySize)
{
pData->curArray[pData->curFaceGear.uiIndex] = pData->curFaceGear;
}
}
else if(strcmp(name, "uiIndex") == 0)
{
pData->curElement = ELEMENT;
pData->curFaceGear.uiIndex = (UINT16) atol(pData->szCharData);
}
else if(strcmp(name, "Type") == 0)
{
pData->curElement = ELEMENT;
pData->curFaceGear.Type = (UINT16) atol(pData->szCharData);
}
else if(strcmp(name, "szFile") == 0 )
{
pData->curElement = ELEMENT;
if(MAX_FACE_GERA_CHARS >= strlen(pData->szCharData))
strcpy(pData->curFaceGear.szFile,pData->szCharData);
else
{
strncpy(pData->curFaceGear.szFile,pData->szCharData,MAX_FACE_GERA_CHARS);
pData->curFaceGear.szFile[MAX_FACE_GERA_CHARS] = '\0';
}
for(int i=0;i<min((int)strlen(pData->szCharData),MAX_FACE_GERA_CHARS);i++)
{
temp = pData->szCharData[i];
pData->curFaceGear.szFile[i] = temp;
}
}
pData->maxReadDepth--;
}
pData->currentDepth--;
}
BOOLEAN ReadInFaceGear( FACE_GEAR_VALUES *pFaceGear, STR fileName ) //, BOOLEAN localizedVersion)
{
HWFILE hFile;
UINT32 uiBytesRead;
UINT32 uiFSize;
CHAR8 * lpcBuffer;
XML_Parser parser = XML_ParserCreate(NULL);
faceGearParseData pData;
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading FaceGear.xml" );
// Open 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, faceGearStartElementHandle, faceGearEndElementHandle);
XML_SetCharacterDataHandler(parser, faceGearCharacterDataHandle);
memset(&pData,0,sizeof(pData));
pData.curArray = pFaceGear;
pData.maxArraySize = MAXITEMS;
XML_SetUserData(parser, &pData);
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
{
CHAR8 errorBuf[511];
sprintf(errorBuf, "XML Parser Error in FaceGear.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 WriteFaceGear()
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"writeFaceGear");
HWFILE hFile;
hFile = FileOpen( "TABLEDATA\\FaceGear out.xml", FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE );
if ( !hFile )
return( FALSE );
{
UINT32 cnt;
FilePrintf(hFile,"<FACE_GEAR>\r\n");
for(cnt = 0;cnt < MAXITEMS;cnt++)
{
FilePrintf(hFile,"\t<ITEM>\r\n");
FilePrintf(hFile,"\t\t<uiIndex>%d</uiIndex>\r\n",cnt);
FilePrintf(hFile,"\t\t<Type>%d</Type>\r\n", zNewFaceGear[cnt].Type);
FilePrintf(hFile,"\t\t<szFile></szFile>\r\n");
FilePrintf(hFile,"\t</ITEM>\r\n");
}
FilePrintf(hFile,"</FACE_GEAR>\r\n");
}
FileClose( hFile );
return( TRUE );
}
+15
View File
@@ -42,6 +42,19 @@ typedef struct
extern RPC_SMALL_FACE_VALUES gRPCSmallFaceValues[200];
extern UINT8 gubRPCSmallFaceProfileNum[200];
#define MAX_FACE_GERA_CHARS 500
typedef struct
{
UINT16 Type;
UINT32 uiIndex;
CHAR8 szFile[MAX_FACE_GERA_CHARS];
} FACE_GEAR_VALUES;
extern FACE_GEAR_VALUES zNewFaceGear[MAXITEMS];
extern FACE_GEAR_VALUES zNewFaceGearIMP[MAXITEMS];
#define FACE_AUTO_DISPLAY_BUFFER 0xFFFFF000
#define FACE_AUTO_RESTORE_BUFFER 0xFFFFFF00
#define FACE_NO_RESTORE_BUFFER 0xFFFFFFF0
@@ -239,6 +252,8 @@ void InternalShutupaYoFace( INT32 iFaceIndex, BOOLEAN fForce );
// If you still want the face in moemory but want to stop if from being displayed, or handled call
void SetAutoFaceInActive( INT32 iFaceIndex );
void SetCamoFace(SOLDIERTYPE * pSoldier);
// To set all currently allocated faces to either active or incactive, call these
void SetAllAutoFacesInactive( );
+5 -3
View File
@@ -2862,7 +2862,7 @@ void RemoveOneOpponent(SOLDIERTYPE *pSoldier)
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Oppcnt for %d (%s) tried to go below 0", pSoldier->ubID, pSoldier->name ) );
#ifdef JA2BETAVERSION
ScreenMsg( MSG_FONT_YELLOW, MSG_UI_FEEDBACK, L"Opponent counter dropped below 0 for person %d (%s). Please inform Sir-tech of this, and what has just been happening in the game.", pSoldier->ubID, pSoldier->name );
ScreenMsg( MSG_FONT_YELLOW, MSG_UI_FEEDBACK, L"Opponent counter dropped below 0 for person %d (%s). Please inform Sir-tech of this, and what has just been happening in the game.", pSoldier->ubID, pSoldier->name );
#endif
pSoldier->aiData.bOppCnt = 0;
}
@@ -5751,7 +5751,8 @@ void ProcessNoise(UINT8 ubNoiseMaker, INT32 sGridNo, INT8 bLevel, UINT8 ubTerrTy
if (pSoldier->aiData.bOppList[ubNoiseMaker] == SEEN_CURRENTLY)
{
// civilians care about gunshots even if they come from someone they can see
if ( !( pSoldier->aiData.bNeutral && ubNoiseType == NOISE_GUNFIRE ) )
// ChrisL: Crows will fly away if they hear any noise
if ( !( pSoldier->aiData.bNeutral && ubNoiseType == NOISE_GUNFIRE ) && pSoldier->ubBodyType != CROW )
{
continue; // then who cares whether he can also hear the guy?
}
@@ -6949,7 +6950,8 @@ void RecalculateOppCntsDueToNoLongerNeutral( SOLDIERTYPE * pSoldier )
if ( pOpponent->aiData.bOppList[pSoldier->ubID] == SEEN_CURRENTLY )
{
// have to add to opponent's oppcount as well since we just became non-neutral
AddOneOpponent( pOpponent );
//CHRISL: If we do this, Bloodcats get counted at opponents multiple times and never get removed from the OppCnt variable.
//AddOneOpponent( pOpponent );
}
}
}
+1
View File
@@ -5,6 +5,7 @@
#include "Soldier Control.h"
#define NUM_PROFILES 255 //170 new profiles by Jazz
#define NUM_PROFILES_v111 170
//tais: maximum amount of starting gear kits
#define NUM_MERCSTARTINGGEAR_KITS 5
#define FIRST_RPC 57