mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
HAM5.5b2 merged in!
Notes: -There may still be bugs!! (In fact, I almost guarantee it -- there's -Ammo box code added to HR's crate code -Splitting a crate/box also automatically refills half empty magazines -new pathing arrows for map screen not included -code for scouts to know where enemies are going doesn't appear to work... but i'm not sure it was completed. -lots of gobledy gook (chinese?) comments turned back to english -also added Bob's popups -other languages besides english still need to have there language.cpp files updated with array changes -AI enhancements by Warmsteel (reloading, suppression, roaming, avoiding gas, and other fixes) git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5181 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+4
-2
@@ -2257,13 +2257,15 @@ void LoadCTHConstants()
|
||||
//Kaiden: Setting Ja2_Options.ini file to be read
|
||||
CIniReader iniReader(CTH_COEFFICIENTS_FILE);
|
||||
|
||||
gGameCTHConstants.NORMAL_SHOOTING_DISTANCE = iniReader.ReadInteger("General","NORMAL_SHOOTING_DISTANCE",100, 10, 10000);
|
||||
gGameCTHConstants.NORMAL_SHOOTING_DISTANCE = iniReader.ReadInteger("General","NORMAL_SHOOTING_DISTANCE", 70, 10, 10000);
|
||||
gGameCTHConstants.DEGREES_MAXIMUM_APERTURE = iniReader.ReadFloat("General", "DEGREES_MAXIMUM_APERTURE", 15.0, 0.0, 22.5);
|
||||
gGameCTHConstants.RANGE_COEFFICIENT = iniReader.ReadFloat("General", "RANGE_COEFFICIENT", 2.0, 0.001f, 100.0);
|
||||
gGameCTHConstants.GRAVITY_COEFFICIENT = iniReader.ReadFloat("General", "GRAVITY_COEFFICIENT", 1.0, 0.001f, 100.0);
|
||||
gGameCTHConstants.VERTICAL_BIAS = iniReader.ReadFloat("General", "VERTICAL_BIAS", 1.0f, 0.01f, 2.0f);
|
||||
gGameCTHConstants.SCOPE_RANGE_MULTIPLIER = iniReader.ReadFloat("General", "SCOPE_RANGE_MULTIPLIER", 0.7f, 0.5f, 1.5f);
|
||||
gGameCTHConstants.SIDE_FACING_DIVISOR = iniReader.ReadFloat("General", "SIDE_FACING_DIVISOR", 2.0, 1.0f, 10.0f);
|
||||
// HEADROCK HAM 5: Basic chance to lose condition point when firing
|
||||
gGameCTHConstants.BASIC_RELIABILITY_ODDS = iniReader.ReadInteger("General", "BASIC_RELIABILITY_ODDS", 15, 0, 100);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Coefficients for factors affecting Base CTH
|
||||
@@ -2370,7 +2372,7 @@ void LoadCTHConstants()
|
||||
gGameCTHConstants.RECOIL_MAX_COUNTER_FORCE = iniReader.ReadFloat("Shooting Mechanism","RECOIL_MAX_COUNTER_FORCE",5.0, 0.0, 100.0);
|
||||
gGameCTHConstants.RECOIL_MAX_COUNTER_CROUCH = iniReader.ReadFloat("Shooting Mechanism","RECOIL_MAX_COUNTER_CROUCH",10.0, -100.0, 100.0);
|
||||
gGameCTHConstants.RECOIL_MAX_COUNTER_PRONE = iniReader.ReadFloat("Shooting Mechanism","RECOIL_MAX_COUNTER_PRONE",25.0, -100.0, 100.0);
|
||||
gGameCTHConstants.RECOIL_COUNTER_ACCURACY_MIN_ERROR = iniReader.ReadFloat("Shooting Mechanism","RECOIL_COUNTER_ACCURACY_MIN",0.2f, 0.0, 100.0);
|
||||
gGameCTHConstants.RECOIL_COUNTER_ACCURACY_MIN_ERROR = iniReader.ReadFloat("Shooting Mechanism","RECOIL_COUNTER_ACCURACY_MIN_ERROR",0.2f, 0.0, 100.0);
|
||||
gGameCTHConstants.RECOIL_COUNTER_ACCURACY_DEX = iniReader.ReadFloat("Shooting Mechanism","RECOIL_COUNTER_ACCURACY_DEX",3.0, 0.0, 100.0);
|
||||
gGameCTHConstants.RECOIL_COUNTER_ACCURACY_WIS = iniReader.ReadFloat("Shooting Mechanism","RECOIL_COUNTER_ACCURACY_WIS",1.0, 0.0, 100.0);
|
||||
gGameCTHConstants.RECOIL_COUNTER_ACCURACY_AGI = iniReader.ReadFloat("Shooting Mechanism","RECOIL_COUNTER_ACCURACY_AGI",1.0, 0.0, 100.0);
|
||||
|
||||
@@ -1345,6 +1345,7 @@ typedef struct
|
||||
FLOAT VERTICAL_BIAS; // This float can be used to reduce the chance of missing too far upwards or downwards (compared to left/right).
|
||||
FLOAT SCOPE_RANGE_MULTIPLIER; // Adjusts the minimum effective range of scopes
|
||||
FLOAT SIDE_FACING_DIVISOR; // Deals with a visual error in NCTH relating to shooting at a target who is facing directly perpendicular to the shooters facing.
|
||||
UINT16 BASIC_RELIABILITY_ODDS; // Determines the base chance to lose one condition point when firing a gun.
|
||||
|
||||
FLOAT BASE_EXP; // Importance of Experience for BASE CTH
|
||||
FLOAT BASE_MARKS; // Importance of Marksmanship for BASE CTH
|
||||
|
||||
@@ -367,6 +367,11 @@ BOOLEAN LoadExternalGameplayData(STR directoryName)
|
||||
strcat(fileName, ATTACHMENTCOMBOMERGESFILENAME);
|
||||
SGP_THROW_IFFALSE(ReadInAttachmentComboMergeStats(fileName),ATTACHMENTCOMBOMERGESFILENAME);
|
||||
|
||||
// HEADROCK HAM 5: Read item transformation
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, ITEMTRANSFORMATIONSFILENAME);
|
||||
SGP_THROW_IFFALSE(ReadInTransformationStats(fileName),ITEMTRANSFORMATIONSFILENAME);
|
||||
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, EXPLOSIVESFILENAME);
|
||||
SGP_THROW_IFFALSE(ReadInExplosiveStats(fileName),EXPLOSIVESFILENAME);
|
||||
@@ -386,6 +391,12 @@ BOOLEAN LoadExternalGameplayData(STR directoryName)
|
||||
strcat(fileName, LBEPOCKETFILENAME);
|
||||
SGP_THROW_IFFALSE(ReadInLBEPocketStats(fileName,FALSE),LBEPOCKETFILENAME);
|
||||
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
LBEPocketPopup.clear();
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, LBEPOCKETPOPUPFILENAME);
|
||||
SGP_THROW_IFFALSE(ReadInLBEPocketPopups(fileName),LBEPOCKETPOPUPFILENAME);
|
||||
|
||||
//CHRISL: Simple localization
|
||||
// Same setup as what Madd used for items.xml
|
||||
|
||||
@@ -643,6 +654,13 @@ BOOLEAN LoadExternalGameplayData(STR directoryName)
|
||||
strcat(fileName, SECTORNAMESFILENAME);
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName));
|
||||
SGP_THROW_IFFALSE(ReadInSectorNames(fileName,FALSE,0), SECTORNAMESFILENAME);
|
||||
|
||||
// HEADROCK HAM 5: Read in Coolness by Sector
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, COOLNESSBYSECTORFILENAME);
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName));
|
||||
SGP_THROW_IFFALSE(ReadInCoolnessBySector(fileName), COOLNESSBYSECTORFILENAME);
|
||||
|
||||
#ifndef ENGLISH
|
||||
AddLanguagePrefix(fileName);
|
||||
if ( FileExists(fileName) )
|
||||
|
||||
+2
-1
@@ -5714,7 +5714,8 @@ BOOLEAN LoadSavedGame( int ubSavedGameID )
|
||||
// HEADROCK HAM B1: Re-Adjust Dynamic Roaming Militia restrictions
|
||||
if (gGameExternalOptions.fDynamicRestrictRoaming)
|
||||
{
|
||||
AdjustRoamingRestrictions();
|
||||
// HEADROCK HAM 5: New flag tells us to also recheck restriced sectors.
|
||||
AdjustRoamingRestrictions( TRUE );
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.5: Tells the rest of the program whether we've got mercs working on detecting enemy units.
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
// #include "Strategic AI.h"
|
||||
#include "interface Dialogue.h"
|
||||
#include "AIInternals.h" // added by SANDRO
|
||||
#include "Bullets.h" // HEADROCK HAM 5, for use with Bullet Impact.
|
||||
#endif
|
||||
|
||||
#include "Reinforcement.h"
|
||||
@@ -4414,7 +4415,8 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget )
|
||||
else
|
||||
ubLocation = AIM_SHOT_TORSO;
|
||||
ubAccuracy = (UINT8)((usAttack - usDefence + PreRandom( usDefence - pTarget->usDefence ) )/10);
|
||||
iImpact = BulletImpact( pAttacker->pSoldier, pTarget->pSoldier, ubLocation, ubImpact, ubAccuracy, NULL );
|
||||
// HEADROCK HAM 5: Added argument
|
||||
iImpact = BulletImpact( pAttacker->pSoldier, NULL, pTarget->pSoldier, ubLocation, ubImpact, ubAccuracy, NULL );
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SANDRO - increased mercs' offense/deffense rating
|
||||
if (pAttacker->uiFlags & CELL_MERC && gGameExternalOptions.sMercsAutoresolveOffenseBonus != 0)
|
||||
|
||||
@@ -28,8 +28,12 @@
|
||||
// Also include Town Militia for checks regarding Mobile Militia Restrictions
|
||||
#include "Town Militia.h"
|
||||
// Also include Quests, for checking whether a fact is true.
|
||||
#include "Quests.h"
|
||||
#include "Quests.h"
|
||||
// HEADROCK HAM 5: Required for inventory filter popup
|
||||
#include "popup_callback.h"
|
||||
#include "popup_class.h"
|
||||
#endif
|
||||
|
||||
#include "connect.h"
|
||||
|
||||
#ifdef JA2UB
|
||||
@@ -91,6 +95,13 @@ BOOLEAN fZoomFlag = FALSE;
|
||||
//BOOLEAN fCursorIsOnMapScrollButtons = FALSE;
|
||||
//BOOLEAN fDisabledMapBorder = FALSE;
|
||||
|
||||
// HEADROCK HAM 5: Externed here to be able to forgo redrawing the map inventory.
|
||||
extern POPUP* gMapInventoryFilterPopup;
|
||||
extern BOOLEAN gfMapInventoryFilterPopupVisible;
|
||||
extern BOOLEAN gfQueueRecreateMapInventoryFilterMenu;
|
||||
extern UINT32 guiMapInvenFilterButton[ 9 ];
|
||||
extern void CreateMapInventoryFilterMenu( );
|
||||
|
||||
|
||||
// buttons & button images
|
||||
// HEADROCK HAM 4: Increase both arrays by one to accomodate new Mobile Restrictions button
|
||||
@@ -210,17 +221,29 @@ void RenderMapBorder( void )
|
||||
}
|
||||
*/
|
||||
|
||||
// HEADROCK HAM 5: Do not redraw if the filter menu is open.
|
||||
if( fShowMapInventoryPool )
|
||||
{
|
||||
// render background, then leave
|
||||
BlitInventoryPoolGraphic( );
|
||||
if (gfMapInventoryFilterPopupVisible)
|
||||
{
|
||||
if (gfQueueRecreateMapInventoryFilterMenu)
|
||||
{
|
||||
ButtonList[guiMapInvenFilterButton[ 0 ]]->uiFlags |= (BUTTON_CLICKED_ON);
|
||||
CreateMapInventoryFilterMenu();
|
||||
}
|
||||
gMapInventoryFilterPopup->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
// render background, then leave
|
||||
BlitInventoryPoolGraphic( );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// get and blt border
|
||||
GetVideoObject(&hHandle, guiMapBorder );
|
||||
// HEADROCK HAM 4: Load different map border depending on whether we want to display the mobile militia button or not.
|
||||
|
||||
if (gGameExternalOptions.gfAllowMilitiaGroups)
|
||||
{
|
||||
BltVideoObject( guiSAVEBUFFER , hHandle, 1, xResOffset + MAP_BORDER_X, MAP_BORDER_Y, VO_BLT_SRCTRANSPARENCY,NULL );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,9 @@
|
||||
|
||||
// whether we are showing the inventory pool graphic
|
||||
extern BOOLEAN fShowMapInventoryPool;
|
||||
// HEADROCK HAM 5: Flag telling us whether we've already redrawn the screen to show
|
||||
// sector inventory sale prices.
|
||||
extern UINT8 gubRenderedMapInventorySalePrices;
|
||||
|
||||
// load inventory pool graphic
|
||||
BOOLEAN LoadInventoryPoolGraphic( void );
|
||||
@@ -21,6 +24,8 @@ void RemoveInventoryPoolGraphic( void );
|
||||
|
||||
// blit the inventory graphic
|
||||
void BlitInventoryPoolGraphic( void );
|
||||
// HEADROCK HAM 5: Blit map inventory slots
|
||||
void BlitInventoryPoolSlotGraphics( void );
|
||||
|
||||
// which buttons in map invneotyr panel?
|
||||
void HandleButtonStatesWhileMapInventoryActive( void );
|
||||
@@ -52,6 +57,8 @@ extern INT32 sObjectSourceGridNo;
|
||||
extern INT32 iCurrentInventoryPoolPage;
|
||||
extern INT32 iLastInventoryPoolPage;
|
||||
extern BOOLEAN fMapInventoryItemCompatable[ ];
|
||||
// HEADROCK HAM 5: Same idea as above, this flags items as being candidates for appearing in Zoomed mode.
|
||||
extern BOOLEAN gfMapInventoryItemToZoom[ ];
|
||||
extern INT32 MAP_INVENTORY_POOL_SLOT_COUNT;
|
||||
|
||||
BOOLEAN IsMapScreenWorldItemInvisibleInMapInventory( WORLDITEM *pWorldItem );
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -98,6 +98,7 @@ void RestoreClipRegionToFullScreenForRectangle( UINT32 uiDestPitchBYTES );
|
||||
|
||||
// show the icons for people in motion
|
||||
void ShowPeopleInMotion( INT16 sX, INT16 sY );
|
||||
void ShowEnemyGroupsInMotion( INT16 sX, INT16 sY);
|
||||
|
||||
// last sector in helicopter's path
|
||||
INT16 GetLastSectorOfHelicoptersPath( void );
|
||||
@@ -159,7 +160,9 @@ enum {
|
||||
enum {
|
||||
KNOWS_NOTHING = 0,
|
||||
KNOWS_THEYRE_THERE,
|
||||
KNOWS_THEYRE_THERE_AND_WHERE_GOING,
|
||||
KNOWS_HOW_MANY,
|
||||
KNOWS_HOW_MANY_AND_WHERE_GOING,
|
||||
};
|
||||
|
||||
|
||||
@@ -273,7 +276,8 @@ extern UINT32 guiBULLSEYE;
|
||||
|
||||
// character between sector icons
|
||||
extern UINT32 guiCHARBETWEENSECTORICONS;
|
||||
extern UINT32 guiCHARBETWEENSECTORICONSCLOSE;
|
||||
// HEADROCK HAM 5: Enemies Between Sectors icons
|
||||
extern UINT32 guiENEMYBETWEENSECTORICONS;
|
||||
|
||||
// the viewable map bound region
|
||||
extern SGPRect MapScreenRect;
|
||||
@@ -296,6 +300,9 @@ extern INT8 bSelectedContractChar;
|
||||
// map arrows graphical index value
|
||||
extern UINT32 guiMAPCURSORS;
|
||||
|
||||
// HEADROCK HAM 5: New pathing arrows may replace the above eventually, but for now a separate variable will do.
|
||||
extern UINT32 guiMapPathingArrows;
|
||||
|
||||
// has temp path for character path or helicopter been already drawn
|
||||
extern BOOLEAN fTempPathAlreadyDrawn;
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ UINT16 sTotalButtonWidth = 0;
|
||||
extern BOOLEAN fMapScreenBottomDirty;
|
||||
//extern UINT8 gubMonsterMineInfestation[];
|
||||
|
||||
// HEADROCK HAM 5: Must be externed here for correct sector name display
|
||||
extern CHAR16 gzSectorNames[256][4][MAX_SECTOR_NAME_LENGTH];
|
||||
|
||||
// create the town/mine info box
|
||||
void CreateTownInfoBox( void );
|
||||
@@ -294,43 +296,96 @@ void AddTextToTownBox( void )
|
||||
|
||||
usTownSectorIndex = SECTOR( bCurrentTownMineSectorX, bCurrentTownMineSectorY );
|
||||
|
||||
switch( usTownSectorIndex )
|
||||
AssertGE(usTownSectorIndex, 0);
|
||||
AssertLT(usTownSectorIndex,256);
|
||||
|
||||
////////////////////////////////////
|
||||
// HEADROCK HAM 5:
|
||||
// Read and verify XML sector names
|
||||
BOOLEAN fSectorHasXMLNames = TRUE;
|
||||
CHAR16 zUnexplored[MAX_SECTOR_NAME_LENGTH];
|
||||
CHAR16 zExplored[MAX_SECTOR_NAME_LENGTH];
|
||||
|
||||
wcscpy( zUnexplored, gzSectorNames[ usTownSectorIndex ][0] );
|
||||
wcscpy( zExplored, gzSectorNames[ usTownSectorIndex ][2] );
|
||||
|
||||
if (zUnexplored[0] == 0 || zExplored[0] == 0)
|
||||
{
|
||||
case SEC_B13:
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ DRASSEN_AIRPORT_SITE ] );
|
||||
break;
|
||||
case SEC_F8:
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ CAMBRIA_HOSPITAL_SITE ] );
|
||||
break;
|
||||
case SEC_J9: //Tixa
|
||||
//if( !fFoundTixa )
|
||||
if( gfHiddenTown[ TIXA ] == FALSE )
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ SAND ] );
|
||||
else
|
||||
AddMonoString( &hStringHandle, pTownNames[ TIXA ] );
|
||||
break;
|
||||
case SEC_K4: //Orta
|
||||
//if( !fFoundOrta )
|
||||
if( gfHiddenTown[ ORTA ] == FALSE )
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ SWAMP ] );
|
||||
else
|
||||
AddMonoString( &hStringHandle, pTownNames[ ORTA ] );
|
||||
break;
|
||||
case SEC_N3:
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ MEDUNA_AIRPORT_SITE ] );
|
||||
break;
|
||||
default:
|
||||
if( usTownSectorIndex == SEC_N4 && fSamSiteFound[ SAM_SITE_FOUR ] )
|
||||
{ //Meduna's SAM site
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ MEDUNA_SAM_SITE ] );
|
||||
}
|
||||
else
|
||||
{ // town name
|
||||
swprintf( wString, L"%s", pTownNames[ ubTownId ] );
|
||||
AddMonoString( &hStringHandle, wString );
|
||||
}
|
||||
break;
|
||||
fSectorHasXMLNames = FALSE;
|
||||
}
|
||||
|
||||
if (fSectorHasXMLNames) // ABOVE GROUND XML
|
||||
{
|
||||
// HEADROCK HAM 3.6: The program can now read custom names from XML for all above-ground sectors.
|
||||
// In the event that a specific name or set of names is missing, the program generates a default
|
||||
// name as it always has.
|
||||
// I've also updated the SAM Site sectors to rely on SamSite.XML data.
|
||||
|
||||
BOOLEAN fVisited = (SectorInfo[ usTownSectorIndex ].uiFlags & SF_ALREADY_VISITED);
|
||||
BOOLEAN fSAMSiteKnown = FALSE;
|
||||
|
||||
// Test for known SAM Site at this location
|
||||
for (UINT16 x=0; x < MAX_NUMBER_OF_SAMS; x++)
|
||||
{
|
||||
if ( pSamList[x] == usTownSectorIndex )
|
||||
{
|
||||
if ( fSamSiteFound[ x ] )
|
||||
{
|
||||
fSAMSiteKnown = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fVisited || fSAMSiteKnown)
|
||||
{
|
||||
AddMonoString( &hStringHandle, zExplored );
|
||||
}
|
||||
else
|
||||
{
|
||||
AddMonoString( &hStringHandle, zUnexplored );
|
||||
}
|
||||
}
|
||||
else // ABOVE GROUND HARDCODED
|
||||
{
|
||||
switch( usTownSectorIndex )
|
||||
{
|
||||
case SEC_B13:
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ DRASSEN_AIRPORT_SITE ] );
|
||||
break;
|
||||
case SEC_F8:
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ CAMBRIA_HOSPITAL_SITE ] );
|
||||
break;
|
||||
case SEC_J9: //Tixa
|
||||
//if( !fFoundTixa )
|
||||
if( gfHiddenTown[ TIXA ] == FALSE )
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ SAND ] );
|
||||
else
|
||||
AddMonoString( &hStringHandle, pTownNames[ TIXA ] );
|
||||
break;
|
||||
case SEC_K4: //Orta
|
||||
//if( !fFoundOrta )
|
||||
if( gfHiddenTown[ ORTA ] == FALSE )
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ SWAMP ] );
|
||||
else
|
||||
AddMonoString( &hStringHandle, pTownNames[ ORTA ] );
|
||||
break;
|
||||
case SEC_N3:
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ MEDUNA_AIRPORT_SITE ] );
|
||||
break;
|
||||
default:
|
||||
if( usTownSectorIndex == SEC_N4 && fSamSiteFound[ SAM_SITE_FOUR ] )
|
||||
{ //Meduna's SAM site
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ MEDUNA_SAM_SITE ] );
|
||||
}
|
||||
else
|
||||
{ // town name
|
||||
swprintf( wString, L"%s", pTownNames[ ubTownId ] );
|
||||
AddMonoString( &hStringHandle, wString );
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// blank line
|
||||
AddMonoString( &hStringHandle, L"" );
|
||||
|
||||
@@ -523,31 +578,83 @@ void AddTextToBlankSectorBox( void )
|
||||
// get the sector value
|
||||
usSectorValue = SECTOR( bCurrentTownMineSectorX, bCurrentTownMineSectorY );
|
||||
|
||||
switch( usSectorValue )
|
||||
{
|
||||
case SEC_D2: //Chitzena SAM
|
||||
if( !fSamSiteFound[ SAM_SITE_ONE ] )
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ TROPICS ] );
|
||||
else
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ TROPICS_SAM_SITE ] );
|
||||
break;
|
||||
case SEC_D15: //Drassen SAM
|
||||
if( !fSamSiteFound[ SAM_SITE_TWO ] )
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ SPARSE ] );
|
||||
else
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ SPARSE_SAM_SITE ] );
|
||||
break;
|
||||
case SEC_I8: //Cambria SAM
|
||||
if( !fSamSiteFound[ SAM_SITE_THREE ] )
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ SAND ] );
|
||||
else
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ SAND_SAM_SITE ] );
|
||||
break;
|
||||
// SAM Site 4 in Meduna is within town limits, so it's handled in AddTextToTownBox()
|
||||
AssertGE(usSectorValue, 0);
|
||||
AssertLT(usSectorValue,256);
|
||||
|
||||
default:
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ ( SectorInfo[ usSectorValue ].ubTraversability[ 4 ] ) ] );
|
||||
break;
|
||||
////////////////////////////////////
|
||||
// HEADROCK HAM 5:
|
||||
// Read and verify XML sector names
|
||||
BOOLEAN fSectorHasXMLNames = TRUE;
|
||||
CHAR16 zUnexplored[MAX_SECTOR_NAME_LENGTH];
|
||||
CHAR16 zExplored[MAX_SECTOR_NAME_LENGTH];
|
||||
|
||||
wcscpy( zUnexplored, gzSectorNames[ usSectorValue ][0] );
|
||||
wcscpy( zExplored, gzSectorNames[ usSectorValue ][2] );
|
||||
|
||||
if (zUnexplored[0] == 0 || zExplored[0] == 0)
|
||||
{
|
||||
fSectorHasXMLNames = FALSE;
|
||||
}
|
||||
|
||||
if (fSectorHasXMLNames) // ABOVE GROUND XML
|
||||
{
|
||||
// HEADROCK HAM 3.6: The program can now read custom names from XML for all above-ground sectors.
|
||||
// In the event that a specific name or set of names is missing, the program generates a default
|
||||
// name as it always has.
|
||||
// I've also updated the SAM Site sectors to rely on SamSite.XML data.
|
||||
|
||||
BOOLEAN fVisited = (SectorInfo[ usSectorValue ].uiFlags & SF_ALREADY_VISITED);
|
||||
BOOLEAN fSAMSiteKnown = FALSE;
|
||||
|
||||
// Test for known SAM Site at this location
|
||||
for (UINT16 x=0; x < MAX_NUMBER_OF_SAMS; x++)
|
||||
{
|
||||
if ( pSamList[x] == usSectorValue )
|
||||
{
|
||||
if ( fSamSiteFound[ x ] )
|
||||
{
|
||||
fSAMSiteKnown = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fVisited || fSAMSiteKnown)
|
||||
{
|
||||
AddMonoString( &hStringHandle, zExplored );
|
||||
}
|
||||
else
|
||||
{
|
||||
AddMonoString( &hStringHandle, zUnexplored );
|
||||
}
|
||||
}
|
||||
else // ABOVE GROUND HARDCODED
|
||||
{
|
||||
switch( usSectorValue )
|
||||
{
|
||||
case SEC_D2: //Chitzena SAM
|
||||
if( !fSamSiteFound[ SAM_SITE_ONE ] )
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ TROPICS ] );
|
||||
else
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ TROPICS_SAM_SITE ] );
|
||||
break;
|
||||
case SEC_D15: //Drassen SAM
|
||||
if( !fSamSiteFound[ SAM_SITE_TWO ] )
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ SPARSE ] );
|
||||
else
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ SPARSE_SAM_SITE ] );
|
||||
break;
|
||||
case SEC_I8: //Cambria SAM
|
||||
if( !fSamSiteFound[ SAM_SITE_THREE ] )
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ SAND ] );
|
||||
else
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ SAND_SAM_SITE ] );
|
||||
break;
|
||||
// SAM Site 4 in Meduna is within town limits, so it's handled in AddTextToTownBox()
|
||||
|
||||
default:
|
||||
AddMonoString( &hStringHandle, pLandTypeStrings[ ( SectorInfo[ usSectorValue ].ubTraversability[ 4 ] ) ] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// blank line
|
||||
@@ -723,7 +830,9 @@ void AddCommonInfoToBox(void)
|
||||
wcscpy(wString, pwMiscSectorStrings[ 3 ] );
|
||||
break;
|
||||
|
||||
// HEADROCK HAM 5: New Case
|
||||
case KNOWS_THEYRE_THERE:
|
||||
case KNOWS_THEYRE_THERE_AND_WHERE_GOING:
|
||||
// if there are any there
|
||||
if ( ubNumEnemies > 0 )
|
||||
{
|
||||
@@ -737,7 +846,9 @@ void AddCommonInfoToBox(void)
|
||||
}
|
||||
break;
|
||||
|
||||
// HEADROCK HAM 5: New case
|
||||
case KNOWS_HOW_MANY:
|
||||
case KNOWS_HOW_MANY_AND_WHERE_GOING:
|
||||
// show exactly how many
|
||||
if (numEnemiesOnMap != ubNumEnemies)
|
||||
swprintf( wString, L"%d (%d)", numEnemiesOnMap, ubNumEnemies );
|
||||
|
||||
@@ -71,7 +71,8 @@ UINT8 gubManualRestrictMilitia[ 256 ];
|
||||
// HEADROCK HAM B1: Alternate array keeps track of dynamically unrestricted sectors
|
||||
BOOLEAN gDynamicRestrictMilitia[ 256 ];
|
||||
// HEADROCK HAM B1: Function that dynamically unrestricts sectors as we take over towns.
|
||||
extern void AdjustRoamingRestrictions();
|
||||
// HEADROCK HAM 5: New flag tells us to also recheck restriced sectors.
|
||||
extern void AdjustRoamingRestrictions( BOOLEAN fRecheck );
|
||||
|
||||
DYNAMICRESTRICTIONS gDynamicRestrictions[5001];
|
||||
|
||||
@@ -2167,7 +2168,8 @@ void MilitiaFollowPlayer( INT16 sMapX, INT16 sMapY, INT16 sDMapX, INT16 sDMapY )
|
||||
}
|
||||
}*/
|
||||
|
||||
void AdjustRoamingRestrictions()
|
||||
// HEADROCK HAM 5: New flag tells us to also recheck restriced sectors.
|
||||
void AdjustRoamingRestrictions( BOOLEAN fRecheck )
|
||||
{
|
||||
UINT32 uiCapturedTownsFlag = 0;
|
||||
UINT16 cnt = 0;
|
||||
@@ -2203,7 +2205,19 @@ void AdjustRoamingRestrictions()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM 5: All restricted sectors are checked to see they aren't manually-permitted.
|
||||
if (fRecheck)
|
||||
{
|
||||
for (cnt = 0; cnt < 256; cnt++)
|
||||
{
|
||||
if (gDynamicRestrictMilitia[cnt] == FALSE)
|
||||
{
|
||||
gubManualRestrictMilitia[cnt] = MANUAL_MOBILE_RESTRICTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// HEADROCK HAM B2.7: This is a copy of an existing function that generates possible movement directions for militia.
|
||||
|
||||
@@ -25,7 +25,8 @@ BOOLEAN MoveOneBestMilitiaMan(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMa
|
||||
void MilitiaFollowPlayer( INT16 sMapX, INT16 sMapY, INT16 sDMapX, INT16 sDMapY );
|
||||
|
||||
// HEADROCK HAM B1: Changes the allowed militia sectors
|
||||
extern void AdjustRoamingRestrictions();
|
||||
// HEADROCK HAM 5: New flag tells us to also recheck restriced sectors.
|
||||
extern void AdjustRoamingRestrictions( BOOLEAN fRecheck );
|
||||
// HEADROCK HAM 4: Yet ANOTHER array, this one holds player-set restrictions. It interacts with the dynamic one below.
|
||||
extern UINT8 gubManualRestrictMilitia[ 256 ];
|
||||
// HEADROCK HAM B1: Alternate array keeps track of dynamically unrestricted sectors
|
||||
|
||||
@@ -656,7 +656,9 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
|
||||
// adjust the chance for what we know about the sector
|
||||
if( WhatPlayerKnowsAboutEnemiesInSector( gubPBSectorX, gubPBSectorY ) == KNOWS_NOTHING )
|
||||
iChance += 20;
|
||||
else if( WhatPlayerKnowsAboutEnemiesInSector( gubPBSectorX, gubPBSectorY ) == KNOWS_THEYRE_THERE )
|
||||
// HEADROCK HAM 5: Added new possible value...
|
||||
else if( WhatPlayerKnowsAboutEnemiesInSector( gubPBSectorX, gubPBSectorY ) == KNOWS_THEYRE_THERE ||
|
||||
WhatPlayerKnowsAboutEnemiesInSector( gubPBSectorX, gubPBSectorY ) == KNOWS_THEYRE_THERE_AND_WHERE_GOING )
|
||||
iChance += 5;
|
||||
//if( GetSectorFlagStatus( gubPBSectorX, gubPBSectorY, 0, SF_ALREADY_VISITED ) == TRUE )
|
||||
// iChance -= 10; // if we already visited this sector
|
||||
@@ -1246,7 +1248,7 @@ void RenderPreBattleInterface()
|
||||
if( gubEnemyEncounterCode == CREATURE_ATTACK_CODE ||
|
||||
gubEnemyEncounterCode == BLOODCAT_AMBUSH_CODE ||
|
||||
gubEnemyEncounterCode == ENTERING_BLOODCAT_LAIR_CODE ||
|
||||
WhatPlayerKnowsAboutEnemiesInSector( gubPBSectorX, gubPBSectorY ) != KNOWS_HOW_MANY )
|
||||
WhatPlayerKnowsAboutEnemiesInSector( gubPBSectorX, gubPBSectorY ) < KNOWS_HOW_MANY ) // HEADROCK HAM 5: New case above this one...
|
||||
{
|
||||
// don't know how many
|
||||
swprintf( str, L"?" );
|
||||
|
||||
@@ -587,7 +587,8 @@ void MercDailyUpdate()
|
||||
// HEADROCK HAM B1: Run a function to redefine Roaming Militia Restrictions.
|
||||
if (gGameExternalOptions.fDynamicRestrictRoaming)
|
||||
{
|
||||
AdjustRoamingRestrictions();
|
||||
// HEADROCK HAM 5: New flag tells us to also recheck restriced sectors.
|
||||
AdjustRoamingRestrictions( FALSE );
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: Pay debt for operating Facilities today. If can't be paid, apply loyalty hit.
|
||||
|
||||
@@ -69,7 +69,8 @@ class SOLDIERTYPE;
|
||||
extern UINT32 guiLastTacticalRealTime;
|
||||
|
||||
// the delay for a group about to arrive
|
||||
#define ABOUT_TO_ARRIVE_DELAY 5
|
||||
// HEADROCK HAM 5: 5 minutes? Make it 30. 5 minutes tend to pass in an instant while unpaused...
|
||||
#define ABOUT_TO_ARRIVE_DELAY 30
|
||||
|
||||
GROUP *gpGroupList;
|
||||
|
||||
|
||||
@@ -1859,7 +1859,8 @@ void CheckIfEntireTownHasBeenLiberated( INT8 bTownId, INT16 sSectorX, INT16 sSec
|
||||
// HEADROCK HAM B1: Run a function to redefine Roaming Militia Restrictions on city capture.
|
||||
if (gGameExternalOptions.fDynamicRestrictRoaming)
|
||||
{
|
||||
AdjustRoamingRestrictions();
|
||||
// HEADROCK HAM 5: New flag tells us to also recheck restriced sectors.
|
||||
AdjustRoamingRestrictions( FALSE );
|
||||
}
|
||||
|
||||
// set flag even for towns where you can't train militia, useful for knowing Orta/Tixa were previously controlled
|
||||
|
||||
@@ -126,6 +126,7 @@
|
||||
<ClCompile Include="UndergroundInit.cpp" />
|
||||
<ClCompile Include="XML_Army.cpp" />
|
||||
<ClCompile Include="XML_Bloodcats.cpp" />
|
||||
<ClCompile Include="XML_CoolnessBySector.cpp" />
|
||||
<ClCompile Include="XML_DynamicRestrictions.cpp" />
|
||||
<ClCompile Include="XML_ExtraItems.cpp" />
|
||||
<ClCompile Include="XML_Facilities.cpp" />
|
||||
|
||||
@@ -335,5 +335,8 @@
|
||||
<ClCompile Include="MapScreen Quotes.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_CoolnessBySector.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,169 @@
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Strategic All.h"
|
||||
#include "XML.h"
|
||||
#else
|
||||
#include "builddefines.h"
|
||||
#include <stdio.h>
|
||||
#include "XML.h"
|
||||
#include "expat.h"
|
||||
#include "string.h"
|
||||
#include "Campaign Types.h"
|
||||
#include "FileMan.h"
|
||||
#include "MemMan.h"
|
||||
#include "Debug Control.h"
|
||||
#include "mapscreen.h"
|
||||
|
||||
#include "Soldier Create.cpp"
|
||||
#endif
|
||||
|
||||
#define MAX_CHAR_DATA_LENGTH 500
|
||||
|
||||
extern UINT32 gCoolnessBySector[256];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PARSE_STAGE curElement;
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
INT32 iCurCoolness;
|
||||
UINT32 uiRowNumber;
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
} SectorCoolnessParseData;
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
SectorCoolnessStartElementHandle(void *userData, const XML_Char *name, const char **atts)
|
||||
{
|
||||
SectorCoolnessParseData * pData = (SectorCoolnessParseData *) userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
|
||||
if(strcmp(name, "COOLNESS_BY_SECTOR") == 0 && pData->curElement == ELEMENT_NONE)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(strcmp(name, "MAP_ROW") == 0 && pData->curElement == ELEMENT_LIST)
|
||||
{
|
||||
UINT32 uiAttrIndex;
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
for(uiAttrIndex = 0;atts[uiAttrIndex] != NULL;uiAttrIndex += 2)
|
||||
if(strcmp(atts[uiAttrIndex], "row") == 0)
|
||||
{
|
||||
pData->uiRowNumber = atol(atts[uiAttrIndex+1]);
|
||||
break;
|
||||
}
|
||||
|
||||
if(atts[uiAttrIndex] != NULL && pData->uiRowNumber < MAP_WORLD_Y)
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
SectorCoolnessCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
SectorCoolnessParseData * pData = (SectorCoolnessParseData *) 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
|
||||
SectorCoolnessEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
SectorCoolnessParseData * pData = (SectorCoolnessParseData *) userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
||||
{
|
||||
if(strcmp(name, "COOLNESS_BY_SECTOR") == 0 && pData->curElement == ELEMENT_LIST)
|
||||
{
|
||||
pData->curElement = ELEMENT_NONE;
|
||||
}
|
||||
else if(strcmp(name, "MAP_ROW") == 0 && pData->curElement == ELEMENT)
|
||||
{
|
||||
STR8 curBuffer = pData->szCharData + strspn(pData->szCharData," \t\n\r");
|
||||
UINT32 curCellIndex = 0;
|
||||
UINT32 curNumber;
|
||||
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
while(curBuffer[0] != '\0')
|
||||
{
|
||||
sscanf( curBuffer,"%d",&curNumber);
|
||||
|
||||
gCoolnessBySector[SECTOR(curCellIndex+1, pData->uiRowNumber) ] = curNumber;
|
||||
|
||||
curCellIndex++;
|
||||
curBuffer += strcspn(curBuffer," \t\n\r\0");
|
||||
curBuffer += strspn(curBuffer," \t\n\r");
|
||||
}
|
||||
}
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN ReadInCoolnessBySector(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
SectorCoolnessParseData pData;
|
||||
|
||||
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, SectorCoolnessStartElementHandle, SectorCoolnessEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, SectorCoolnessCharacterDataHandle);
|
||||
|
||||
|
||||
memset(&pData,0,sizeof(pData));
|
||||
XML_SetUserData(parser, &pData);
|
||||
|
||||
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
|
||||
{
|
||||
CHAR8 errorBuf[511];
|
||||
sprintf(errorBuf, "XML Parser Error in CoolnessBySector.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;
|
||||
}
|
||||
+129
-21
@@ -1016,7 +1016,7 @@ void MapscreenMarkButtonsDirty();
|
||||
extern BOOLEAN CanRedistributeMilitiaInSector( INT16 sClickedSectorX, INT16 sClickedSectorY, INT8 bClickedTownId );
|
||||
|
||||
extern INT32 GetNumberOfMercsInUpdateList( void );
|
||||
extern INT32 SellItem( OBJECTTYPE& object, BOOLEAN useModifier = TRUE );
|
||||
extern INT32 SellItem( OBJECTTYPE& object, BOOLEAN fAll, BOOLEAN useModifier = TRUE );
|
||||
void DeleteAllItemsInInventoryPool();
|
||||
|
||||
#ifdef JA2UB
|
||||
@@ -1066,18 +1066,21 @@ void BeginSellAllCallBack( UINT8 bExitValue )
|
||||
fMapPanelDirty = TRUE;
|
||||
gpItemPointer = &gItemPointer;
|
||||
// Sell Item
|
||||
iPrice += SellItem( gItemPointer );
|
||||
// HEADROCK HAM 5: Added argument
|
||||
iPrice += SellItem( gItemPointer, TRUE );
|
||||
gpItemPointer = NULL;
|
||||
fMapInventoryItem = FALSE;
|
||||
if (iPrice == 0) {
|
||||
iPrice = 1;
|
||||
}
|
||||
// HEADROCK HAM 5: Sale of $0 now re-enabled.
|
||||
//if (iPrice == 0) {
|
||||
// iPrice = 1;
|
||||
//}
|
||||
anythingSold = true;
|
||||
HandleButtonStatesWhileMapInventoryActive();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(anythingSold == true)
|
||||
// HEADROCK HAM 5: No transaction if no money.
|
||||
if(anythingSold == true && iPrice > 0)
|
||||
AddTransactionToPlayersBook( SOLD_ITEMS, 0, GetWorldTotalMin(), iPrice );
|
||||
}
|
||||
}
|
||||
@@ -4761,6 +4764,18 @@ UINT32 MapScreenHandle(void)
|
||||
FilenameForBPP("INTERFACE\\mapcursr.sti", VObjectDesc.ImageFile);
|
||||
CHECKF(AddVideoObject(&VObjectDesc, &guiMAPCURSORS));
|
||||
|
||||
// HEADROCK HAM 5: New pathing arrows may replace the above eventually, but for now a separate variable will do.
|
||||
VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE;
|
||||
|
||||
if (iResolution == 0)
|
||||
FilenameForBPP("INTERFACE\\map_pathing_arrows_640.sti", VObjectDesc.ImageFile);
|
||||
else if (iResolution == 1)
|
||||
FilenameForBPP("INTERFACE\\map_pathing_arrows_800.sti", VObjectDesc.ImageFile);
|
||||
else if (iResolution == 2)
|
||||
FilenameForBPP("INTERFACE\\map_pathing_arrows_1024.sti", VObjectDesc.ImageFile);
|
||||
|
||||
CHECKF(AddVideoObject(&VObjectDesc, &guiMapPathingArrows));
|
||||
|
||||
VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE;
|
||||
FilenameForBPP("INTERFACE\\Mine_1.sti", VObjectDesc.ImageFile);
|
||||
CHECKF(AddVideoObject(&VObjectDesc, &guiSubLevel1));
|
||||
@@ -4908,20 +4923,42 @@ UINT32 MapScreenHandle(void)
|
||||
}
|
||||
|
||||
VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE;
|
||||
FilenameForBPP("INTERFACE\\merc_between_sector_icons.sti", VObjectDesc.ImageFile);
|
||||
// HEADROCK HAM 5.4: Larger icons for merc movement
|
||||
if (iResolution >= _640x480 && iResolution < _800x600)
|
||||
FilenameForBPP("INTERFACE\\merc_between_sector_icons_640.sti", VObjectDesc.ImageFile);
|
||||
else if (iResolution < _1024x768)
|
||||
FilenameForBPP("INTERFACE\\merc_between_sector_icons_800.sti", VObjectDesc.ImageFile);
|
||||
else
|
||||
FilenameForBPP("INTERFACE\\merc_between_sector_icons_1024.sti", VObjectDesc.ImageFile);
|
||||
|
||||
CHECKF(AddVideoObject(&VObjectDesc, &guiCHARBETWEENSECTORICONS));
|
||||
|
||||
// HEADROCK HAM 5.1: Enemies between sectors
|
||||
VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE;
|
||||
FilenameForBPP("INTERFACE\\merc_mvt_green_arrows.sti", VObjectDesc.ImageFile);
|
||||
CHECKF(AddVideoObject(&VObjectDesc, &guiCHARBETWEENSECTORICONSCLOSE));
|
||||
|
||||
if (iResolution >= _640x480 && iResolution < _800x600)
|
||||
FilenameForBPP("INTERFACE\\enemy_between_sector_icons_640.sti", VObjectDesc.ImageFile);
|
||||
else if (iResolution < _1024x768)
|
||||
FilenameForBPP("INTERFACE\\enemy_between_sector_icons_800.sti", VObjectDesc.ImageFile);
|
||||
else
|
||||
FilenameForBPP("INTERFACE\\enemy_between_sector_icons_1024.sti", VObjectDesc.ImageFile);
|
||||
|
||||
CHECKF(AddVideoObject(&VObjectDesc, &guiENEMYBETWEENSECTORICONS));
|
||||
|
||||
VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE;
|
||||
FilenameForBPP("INTERFACE\\GreenArr.sti", VObjectDesc.ImageFile);
|
||||
CHECKF(AddVideoObject(&VObjectDesc, &guiLEVELMARKER));
|
||||
|
||||
VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE;
|
||||
FilenameForBPP("INTERFACE\\Helicop.sti", VObjectDesc.ImageFile);
|
||||
|
||||
// HEADROCK HAM 5: Resolution-dependent icon
|
||||
if (iResolution >= _640x480 && iResolution < _800x600)
|
||||
FilenameForBPP("INTERFACE\\Helicopter_Map_Icon_640.sti", VObjectDesc.ImageFile);
|
||||
else if (iResolution < _1024x768)
|
||||
FilenameForBPP("INTERFACE\\Helicopter_Map_Icon_800.sti", VObjectDesc.ImageFile);
|
||||
else
|
||||
FilenameForBPP("INTERFACE\\Helicopter_Map_Icon_1024.sti", VObjectDesc.ImageFile);
|
||||
|
||||
CHECKF(AddVideoObject(&VObjectDesc, &guiHelicopterIcon));
|
||||
|
||||
VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE;
|
||||
@@ -4933,7 +4970,6 @@ UINT32 MapScreenHandle(void)
|
||||
CHECKF(AddVideoObject(&VObjectDesc, &guiMapBorderHeliSectors));
|
||||
|
||||
|
||||
|
||||
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
|
||||
FilenameForBPP("INTERFACE\\secondary_gun_hidden.sti", VObjectDesc.ImageFile);
|
||||
CHECKF( AddVideoObject( &VObjectDesc, &guiSecItemHiddenVO ) );
|
||||
@@ -5602,14 +5638,23 @@ UINT32 MapScreenHandle(void)
|
||||
// is there a description to be displayed?
|
||||
// BOB : if we're displaying the attachment popup, don't redraw the IDB
|
||||
if (giActiveAttachmentPopup > -1)
|
||||
{
|
||||
gItemDescAttachmentPopups[giActiveAttachmentPopup]->show();
|
||||
}
|
||||
// HEADROCK HAM 5: So... we need a separate case for each popup that we have? That's not too bright.
|
||||
else if (gfItemDescTransformPopupVisible)
|
||||
{
|
||||
gItemDescTransformPopup->show();
|
||||
}
|
||||
else
|
||||
RenderItemDescriptionBox( );
|
||||
{
|
||||
RenderItemDescriptionBox( );
|
||||
}
|
||||
|
||||
// render clock
|
||||
// WANNE: Renders the clock in the strategy screen
|
||||
RenderClock(CLOCK_X, CLOCK_Y);
|
||||
|
||||
|
||||
#ifdef JA2TESTVERSION
|
||||
if( !gfWorldLoaded )
|
||||
{
|
||||
@@ -8195,9 +8240,38 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM 5: Alt alone shows sale prices on items in the sector inventory.
|
||||
if (fShowMapInventoryPool)
|
||||
{
|
||||
if (fAlt)
|
||||
{
|
||||
if ( _KeyDown( SHIFT ) )
|
||||
{
|
||||
if (gubRenderedMapInventorySalePrices < 2)
|
||||
{
|
||||
gubRenderedMapInventorySalePrices = 2;
|
||||
fMapPanelDirty = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gubRenderedMapInventorySalePrices == 0 ||
|
||||
gubRenderedMapInventorySalePrices == 2 )
|
||||
{
|
||||
gubRenderedMapInventorySalePrices = 1;
|
||||
fMapPanelDirty = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleDefaultEvent(&InputEvent);
|
||||
if (gubRenderedMapInventorySalePrices)
|
||||
{
|
||||
gubRenderedMapInventorySalePrices = 0;
|
||||
fMapPanelDirty = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8360,6 +8434,8 @@ INT32 iCounter2 = 0;
|
||||
DeleteVideoObjectFromIndex(guiSubLevel3);
|
||||
DeleteVideoObjectFromIndex( guiSleepIcon );
|
||||
DeleteVideoObjectFromIndex(guiMAPCURSORS);
|
||||
// HEADROCK HAM 5: New pathing arrows may replace the above eventually, but for now a separate variable will do.
|
||||
DeleteVideoObjectFromIndex(guiMapPathingArrows);
|
||||
//DeleteVideoObjectFromIndex(guiMAPBORDER);
|
||||
DeleteVideoObjectFromIndex(guiCHARLIST);
|
||||
//DeleteVideoObjectFromIndex(guiCORNERADDONS);
|
||||
@@ -8377,7 +8453,8 @@ INT32 iCounter2 = 0;
|
||||
DeleteVideoObjectFromIndex(guiORTAICON);
|
||||
DeleteVideoObjectFromIndex(guiTIXAICON);
|
||||
DeleteVideoObjectFromIndex( guiCHARBETWEENSECTORICONS );
|
||||
DeleteVideoObjectFromIndex( guiCHARBETWEENSECTORICONSCLOSE );
|
||||
// HEADROCK HAM 5.1: Enemies between sectors arrows
|
||||
DeleteVideoObjectFromIndex( guiENEMYBETWEENSECTORICONS );
|
||||
DeleteVideoObjectFromIndex( guiLEVELMARKER );
|
||||
DeleteVideoObjectFromIndex( guiMapBorderEtaPopUp );
|
||||
|
||||
@@ -8866,7 +8943,9 @@ void PollRightButtonInMapView( UINT32 *puiNewEvent )
|
||||
// HEADROCK HAM 4: Toggle Militia Restrictions manually. This occurs when the Mobile Restrictions
|
||||
// view is turned on. Each click advances the sector's classification by 1. If max is reached,
|
||||
// loops back to start.
|
||||
if ( fShowMobileRestrictionsFlag == TRUE )
|
||||
// HEADROCK HAM 5: Whoops, disallow changing restrictions for sectors that are
|
||||
// not accessible to militia to begin with.
|
||||
if ( fShowMobileRestrictionsFlag == TRUE && gDynamicRestrictMilitia[ SECTOR( sMapX, sMapY ) ] == TRUE)
|
||||
{
|
||||
// Restrict more.
|
||||
if ( gubManualRestrictMilitia[ SECTOR( sMapX, sMapY ) ] > MANUAL_MOBILE_NO_ENTER )
|
||||
@@ -9343,9 +9422,15 @@ void MAPInvClickCallback( MOUSE_REGION *pRegion, INT32 iReason )
|
||||
// If we do not have an item in hand, start moving it
|
||||
if ( gpItemPointer == NULL )
|
||||
{
|
||||
// Return if empty
|
||||
|
||||
if ( pSoldier->inv[ uiHandPos ].exists() == false )
|
||||
{
|
||||
if ( _KeyDown(CTRL) ){
|
||||
PocketPopupFull( pSoldier, uiHandPos ); // if ctrl is pressed, display all options
|
||||
} else {
|
||||
PocketPopupDefault( pSoldier, uiHandPos ); // display pocket-specific options
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9446,7 +9531,17 @@ void MAPInvClickCallback( MOUSE_REGION *pRegion, INT32 iReason )
|
||||
// it's an attempt to attach; bring up the inventory panel
|
||||
if ( !InItemDescriptionBox( ) )
|
||||
{
|
||||
MAPInternalInitItemDescriptionBox( &(pSoldier->inv[ uiHandPos ]), 0, pSoldier );
|
||||
// HEADROCK HAM 5: Sector Inventory Item Desc Box no longer accessible during combat.
|
||||
|
||||
if( gTacticalStatus.uiFlags & INCOMBAT )
|
||||
{
|
||||
DoScreenIndependantMessageBox( New113HAMMessage[ 23 ], MSG_BOX_FLAG_OK, NULL );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
MAPInternalInitItemDescriptionBox( &(pSoldier->inv[ uiHandPos ]), 0, pSoldier );
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -9456,8 +9551,18 @@ void MAPInvClickCallback( MOUSE_REGION *pRegion, INT32 iReason )
|
||||
// TOO PAINFUL TO DO!! --CC
|
||||
if ( !InItemDescriptionBox( ) )
|
||||
{
|
||||
bJustOpenedItemDescPanel = true; // OJW - 20090319 - fix merging on mapscreen - see top of function
|
||||
MAPInternalInitItemDescriptionBox( &(pSoldier->inv[ uiHandPos ]), 0, pSoldier );
|
||||
// HEADROCK HAM 5: Sector Inventory Item Desc Box no longer accessible during combat.
|
||||
|
||||
if( gTacticalStatus.uiFlags & INCOMBAT )
|
||||
{
|
||||
DoScreenIndependantMessageBox( New113HAMMessage[ 24 ], MSG_BOX_FLAG_OK, NULL );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
bJustOpenedItemDescPanel = true; // OJW - 20090319 - fix merging on mapscreen - see top of function
|
||||
MAPInternalInitItemDescriptionBox( &(pSoldier->inv[ uiHandPos ]), 0, pSoldier );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -13046,6 +13151,8 @@ INT32 iCounter2 = 0;
|
||||
{
|
||||
DeleteMapBottomGraphics( );
|
||||
DeleteVideoObjectFromIndex( guiMAPCURSORS );
|
||||
// HEADROCK HAM 5: New pathing arrows may replace the above eventually, but for now a separate variable will do.
|
||||
DeleteVideoObjectFromIndex(guiMapPathingArrows);
|
||||
DeleteVideoObjectFromIndex( guiSleepIcon );
|
||||
|
||||
//DeleteVideoObjectFromIndex(guiMAPBORDER);
|
||||
@@ -13069,7 +13176,8 @@ INT32 iCounter2 = 0;
|
||||
DeleteVideoObjectFromIndex(guiORTAICON);
|
||||
DeleteVideoObjectFromIndex(guiTIXAICON);
|
||||
DeleteVideoObjectFromIndex( guiCHARBETWEENSECTORICONS );
|
||||
DeleteVideoObjectFromIndex( guiCHARBETWEENSECTORICONSCLOSE );
|
||||
// HEADROCK HAM 5.1: Enemies between sectors arrows
|
||||
DeleteVideoObjectFromIndex( guiENEMYBETWEENSECTORICONS );
|
||||
DeleteVideoObjectFromIndex( guiLEVELMARKER );
|
||||
DeleteVideoObjectFromIndex( guiMapBorderEtaPopUp );
|
||||
DeleteVideoObjectFromIndex( guiSecItemHiddenVO );
|
||||
|
||||
@@ -50,17 +50,17 @@ static UINT16 CrouchedShootRocketScript[MAX_FRAMES_PER_ANIM] =
|
||||
{757,1,2,3,4,5,6,7,8,9,10,11,12,470,430,13,14,15,16,477,17,18,19,20,753,499,999,0,0,0,0};
|
||||
static UINT16 SwatWithKnifeScript[MAX_FRAMES_PER_ANIM] =
|
||||
//{1,2,3,4,5,6,7,703,8,9,10,11,704,12,13,14,15,16,17,18,19,501,999,0,0,0,0};
|
||||
{5,703,6,7,8,9,10,11,704,12,13,14,15,16,501,999,0,0,0,0};//такая последовательность предлагается в джа2бин
|
||||
{5,703,6,7,8,9,10,11,704,12,13,14,15,16,501,999,0,0,0,0};//such a sequence is available in dzha2bin
|
||||
static UINT16 SwatBackWithKnifeScript[MAX_FRAMES_PER_ANIM] =
|
||||
{16,15,14,13,12,704,11,10,9,8,7,6,703,5,501,999,0,0,0,0};
|
||||
|
||||
static UINT16 SwatBackWithNothingScript[MAX_FRAMES_PER_ANIM] =
|
||||
{16,15,14,13,12,704,11,10,9,8,7,6,703,5,501,999,0,0,0,0};
|
||||
|
||||
//хз, может понадобится править цифры. скрипт кидания гранат
|
||||
//xs, may need to edit the numbers. throwing grenades script
|
||||
static UINT16 ThrowGrenadeStanceAnimationScript[MAX_FRAMES_PER_ANIM] = { 1,2,3,4,5,6,7,8,9,10,460,11,12,13,14,15,16,17,18,19,442,601,999,0,0,0,0 };
|
||||
static UINT16 LobGrenadeStanceAnimationScript[MAX_FRAMES_PER_ANIM] = { 1,2,3,4,5,6,7,8,9,10,460,11,12,13,14,15,16,17,18,19,442,601,999,0,0,0,0 };
|
||||
//перекат
|
||||
//Rolls
|
||||
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 };
|
||||
|
||||
@@ -1781,10 +1781,10 @@ void InitAnimationSurfacesPerBodytype( )
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ SWATTING_WK ] = BGMSWKNIFE;
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ SWAT_BACKWARDS_WK ] = BGMSWKNIFE;
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ SWAT_BACKWARDS_NOTHING ] = BGMNOTHING_SWAT;
|
||||
//кидание гранаты
|
||||
//Throwing Grenades
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ THROW_GRENADE_STANCE ] = BGMSTHRG;
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ LOB_GRENADE_STANCE ] = BGMSLOBG;
|
||||
//перекат
|
||||
//Rolling
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ ROLL_PRONE_L ] = BGMROLL_PR;
|
||||
gubAnimSurfaceIndex[ BIGMALE ][ ROLL_PRONE_R ] = BGMROLL_PR;
|
||||
|
||||
@@ -2182,10 +2182,10 @@ void InitAnimationSurfacesPerBodytype( )
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ SWATTING_WK ] = RGMSWKNIFE;
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ SWAT_BACKWARDS_WK ] = RGMSWKNIFE;
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ SWAT_BACKWARDS_NOTHING ] = RGMNOTHING_SWAT;
|
||||
//кидание гранаты
|
||||
//Throwing Grenades
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ THROW_GRENADE_STANCE ] = RGMSTHRG;
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ LOB_GRENADE_STANCE ] = RGMSLOBG;
|
||||
//перекат
|
||||
//Rolling
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ ROLL_PRONE_L ] = RGMROLL_PR;
|
||||
gubAnimSurfaceIndex[ STOCKYMALE ][ ROLL_PRONE_R ] = RGMROLL_PR;
|
||||
|
||||
@@ -2562,10 +2562,10 @@ void InitAnimationSurfacesPerBodytype( )
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ SWAT_BACKWARDS_NOTHING ] = RGFNOTHING_SWAT;
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ SWATTING_WK ] = RGFSWKNIFE;
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ SWAT_BACKWARDS_WK ] = RGFSWKNIFE;
|
||||
//кидание гранаты
|
||||
//Throwing Grenades
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ THROW_GRENADE_STANCE ] = RGFSTHRG;
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ LOB_GRENADE_STANCE ] = RGFSLOBG;
|
||||
//перекта
|
||||
//Rolling
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ ROLL_PRONE_L ] = RGFROLL_PR;
|
||||
gubAnimSurfaceIndex[ REGFEMALE ][ ROLL_PRONE_R ] = RGFROLL_PR;
|
||||
|
||||
@@ -3247,8 +3247,7 @@ BOOLEAN LoadAnimationStateInstructions( )
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
//ddd патамушта вылетает при превышении 320 значения ;(
|
||||
//придется мастерить вспомогательный массив, потом копировать его содержимое в гусаниминст
|
||||
//ddd Trick for loading more than 320 animation files (?)
|
||||
UINT16 fuckTheBoundz[320][100];
|
||||
|
||||
//Read in block
|
||||
@@ -3265,7 +3264,7 @@ BOOLEAN LoadAnimationStateInstructions( )
|
||||
memcpy(gusAnimInst[i],fuckTheBoundz[i],sizeof(fuckTheBoundz[i]));
|
||||
//gusAnimInst[i][0] = fuckTheBoundz[i][0];
|
||||
|
||||
//! для перегонки джа2бин в читаемый вид
|
||||
// For conversion into readable format (?)
|
||||
// char gS[22];
|
||||
// UINT32 uiNumBytesWritten = 64000;
|
||||
// int ggg[MAX_ANIMATIONS][MAX_FRAMES_PER_ANIM];
|
||||
@@ -3837,7 +3836,7 @@ UINT16 DetermineSoldierAnimationSurface( SOLDIERTYPE *pSoldier, UINT16 usAnimSta
|
||||
|
||||
if ( usAltAnimSurface != INVALID_ANIMATION )
|
||||
{
|
||||
//ddd{ сюда ставить альтернативную анимашку для выстрела из пистолета
|
||||
//ddd Put alternative pistol-shot animations here
|
||||
/*if ( usAnimSurface == BGMSTANDAIM2 )
|
||||
{
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
// Defines
|
||||
// #######################################################
|
||||
#define MAX_ANIMATIONS 350 //!!!!!ddd пока добавил 30 лишних словтов под анимашки.
|
||||
#define MAX_ANIMATIONS 350 //!!!!!ddd added 30 new animations
|
||||
#define MAX_FRAMES_PER_ANIM 100
|
||||
#define MAX_RANDOM_ANIMS_PER_BODYTYPE 8
|
||||
|
||||
@@ -548,9 +548,9 @@ enum AnimationStates
|
||||
SWATTING_WK,
|
||||
SWAT_BACKWARDS_WK,
|
||||
SWAT_BACKWARDS_NOTHING,
|
||||
THROW_GRENADE_STANCE, //ddd для бабы анимации нет - используем стандартную
|
||||
THROW_GRENADE_STANCE, //ddd Currently no animation for women. Using the standard.
|
||||
LOB_GRENADE_STANCE,
|
||||
//перекатты
|
||||
//Prone rolls
|
||||
ROLL_PRONE_R,
|
||||
ROLL_PRONE_L,
|
||||
|
||||
|
||||
@@ -518,15 +518,15 @@ BGMWITHSTONE,
|
||||
BGMSWKNIFE,
|
||||
RGFSWKNIFE,
|
||||
RGMSWKNIFE,
|
||||
//кидание гранаты стоя с выд. чеки
|
||||
//Launch grenade (?)
|
||||
BGMSTHRG,
|
||||
RGFSTHRG,
|
||||
RGMSTHRG,
|
||||
//кидание гранаты стоя с выд. чеки близкое расст
|
||||
//Lob grenade
|
||||
BGMSLOBG,
|
||||
RGFSLOBG,
|
||||
RGMSLOBG,
|
||||
//внаглую стырил код у терапевта!
|
||||
//Roll while prone
|
||||
RGMROLL_PR,
|
||||
BGMROLL_PR,
|
||||
RGFROLL_PR,
|
||||
|
||||
@@ -57,6 +57,7 @@ typedef struct
|
||||
UINT8 ubTilesPerUpdate;
|
||||
UINT16 usClockTicksPerUpdate;
|
||||
SOLDIERTYPE *pFirer;
|
||||
INT32 sOrigGridNo; // HEADROCK HAM 5.1: Original tile does not necessarily have to be the pFirer's tile
|
||||
INT32 sTargetGridNo;
|
||||
INT16 sHitBy;
|
||||
INT32 iImpact;
|
||||
@@ -73,6 +74,8 @@ typedef struct
|
||||
// the bullet animation functions to create a lightpath for this bullet. This means now all bullets in a tracer
|
||||
// magazine will cause a lightshow (that's the intended result).
|
||||
BOOLEAN fTracer;
|
||||
// HEADROCK HAM 5: Fragments. They are handled slightly differently by the bullet functions.
|
||||
BOOLEAN fFragment;
|
||||
} BULLET;
|
||||
|
||||
extern UINT32 guiNumBullets;
|
||||
@@ -82,6 +85,8 @@ void RemoveBullet( INT32 iBullet );
|
||||
void StopBullet( INT32 iBullet );
|
||||
void UpdateBullets( );
|
||||
BULLET *GetBulletPtr( INT32 iBullet );
|
||||
INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iImpact, INT16 sHitBy, UINT8 * pubSpecial );
|
||||
|
||||
|
||||
void DeleteAllBullets( );
|
||||
|
||||
|
||||
+1047
-400
File diff suppressed because it is too large
Load Diff
+1984
-6
File diff suppressed because it is too large
Load Diff
@@ -169,6 +169,19 @@ public:
|
||||
OBJECTTYPE ItemPointerInfo;
|
||||
};
|
||||
|
||||
// HEADROCK HAM 5: Enums for big-item display attachment asterisks.
|
||||
enum
|
||||
{
|
||||
ATTACHMENT_NONE,
|
||||
ATTACHMENT_GENERAL,
|
||||
ATTACHMENT_GL,
|
||||
ATTACHMENT_RECOILREDUCTION,
|
||||
ATTACHMENT_OPTICAL,
|
||||
};
|
||||
|
||||
// HEADROCK HAM 5: Asterisks for use with big item images
|
||||
extern UINT32 guiAttachmentAsterisks;
|
||||
|
||||
// Itempickup stuff
|
||||
BOOLEAN InitializeItemPickupMenu( SOLDIERTYPE *pSoldier, INT32 sGridNo, ITEM_POOL *pItemPool, INT16 sScreenX, INT16 sScreenY, INT8 bZLevel );
|
||||
void RenderItemPickupMenu( );
|
||||
@@ -211,6 +224,8 @@ BOOLEAN HandleCompatibleAmmoUI( SOLDIERTYPE *pSoldier, INT8 bInvPos, BOOLEAN fOn
|
||||
|
||||
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 );
|
||||
// HEADROCK HAM 5: Drawing a large item pic with extra data.
|
||||
void MAPINVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObject, UINT32 uiItemGraphicNum, INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, BOOLEAN fOutline, INT16 sOutlineColor );
|
||||
// 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
|
||||
@@ -313,7 +328,36 @@ extern INT32 giActiveAttachmentPopup; // the attachment popup to display in maps
|
||||
extern POPUP* gEquipPopups[NUM_INV_SLOTS]; // popup list for attachment slots
|
||||
extern INT32 giActiveEquipPopup; // the attachment popup to display in mapscreen
|
||||
|
||||
// HEADROCK HAM 5: Item Transformation Popup
|
||||
extern POPUP* gItemDescTransformPopup;
|
||||
extern BOOLEAN gfItemDescTransformPopupInitialized;
|
||||
extern BOOLEAN gfItemDescTransformPopupVisible;
|
||||
|
||||
// BOB : duh...
|
||||
void DoAttachment( UINT8 subObject, INT32 iItemPos );
|
||||
|
||||
// THE_BOB (AKA BOB): ammo box/mag popups
|
||||
void PocketPopupFull( SOLDIERTYPE *pSoldier, INT16 sPocket ); // displays all suported options
|
||||
void PocketPopupDefault( SOLDIERTYPE *pSoldier, INT16 sPocket ); // displays only pocket-specific (predefined) options
|
||||
|
||||
POPUP * createPopupForPocket( SOLDIERTYPE *pSoldier, INT16 sPocket ); // creates a popup positioned next to the pocket
|
||||
|
||||
// THE_BOB
|
||||
extern UINT16 gsPocketUnderCursor;
|
||||
|
||||
|
||||
void addArmorToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addLBEToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addWeaponsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addWeaponGroupsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addGrenadesToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addBombsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addFaceGearToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addAmmoToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
|
||||
void addRifleGrenadesToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addRocketAmmoToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addMiscToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addKitsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2531,7 +2531,15 @@ void RenderSMPanel( BOOLEAN *pfDirty )
|
||||
}
|
||||
}
|
||||
|
||||
RenderItemDescriptionBox( );
|
||||
// HEADROCK HAM 5: Test for active Transform Popup
|
||||
if (gfItemDescTransformPopupVisible)
|
||||
{
|
||||
gItemDescTransformPopup->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
RenderItemDescriptionBox( );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -545,4 +545,16 @@ void RenderSoldierFace( SOLDIERTYPE *pSoldier, INT16 sFaceX, INT16 sFaceY, BOOLE
|
||||
|
||||
}
|
||||
|
||||
// HEADROCK HAM 5: This function draws a rectangle around the item image in the zoomed inventory
|
||||
void DrawItemOutlineZoomedInventory( INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, INT16 sColor, UINT32 uiBuffer )
|
||||
{
|
||||
UINT32 uiDestPitchBYTES;
|
||||
UINT8 *pDestBuf;
|
||||
|
||||
pDestBuf = LockVideoSurface( uiBuffer, &uiDestPitchBYTES );
|
||||
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
|
||||
|
||||
RectangleDraw( TRUE, sX, sY, sWidth, sHeight, sColor, pDestBuf );
|
||||
|
||||
UnLockVideoSurface( uiBuffer );
|
||||
}
|
||||
|
||||
@@ -23,5 +23,8 @@ BOOLEAN LoadCarPortraitValues( void );
|
||||
// get rid of the loaded portraits for cars
|
||||
void UnLoadCarPortraits( void );
|
||||
|
||||
// HEADROCK HAM 5: Helper for zoomed inventory
|
||||
void DrawItemOutlineZoomedInventory( INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, INT16 sColor, UINT32 uiBuffer );
|
||||
|
||||
|
||||
#endif
|
||||
@@ -128,6 +128,7 @@ void DestroyLBE(OBJECTTYPE* pObj)
|
||||
|
||||
void MoveItemsInSlotsToLBE( SOLDIERTYPE *pSoldier, std::vector<INT8>& LBESlots, LBENODE* pLBE, OBJECTTYPE* pObj)
|
||||
{
|
||||
|
||||
for(unsigned int i=0; i<LBESlots.size(); i++) // Go through default pockets one by one
|
||||
{
|
||||
if(pSoldier->inv[LBESlots[i]].exists() == false) // No item in this pocket
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#include "types.h"
|
||||
#include <vector>
|
||||
#include <list>
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
#include <map>
|
||||
#include "popup_definition.h"
|
||||
|
||||
//if the number of slots are ever changed, the loading / saving checksum should use this value to make conversion easier
|
||||
#define NUM_ORIGINAL_INV_SLOTS 19
|
||||
@@ -264,6 +267,20 @@ extern std::list<LBENODE> LBEArray;
|
||||
#define OLD_MAX_ATTACHMENTS_101 4
|
||||
#define OLD_MAX_OBJECTS_PER_SLOT_101 8
|
||||
|
||||
// HEADROCK HAM 5: Define Self-Transformations
|
||||
// Have to define this early on, because this struct is used in OBJECTTYPE
|
||||
#define MAX_NUM_TRANSFORMATION_RESULTS 10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 usItem;
|
||||
UINT16 usResult[MAX_NUM_TRANSFORMATION_RESULTS];
|
||||
UINT16 usAPCost;
|
||||
INT32 iBPCost;
|
||||
CHAR16 szMenuRowText[50];
|
||||
CHAR16 szTooltipText[300];
|
||||
} TransformInfoStruct;
|
||||
|
||||
namespace Version101
|
||||
{
|
||||
//union was originally unnamed
|
||||
@@ -526,6 +543,8 @@ public:
|
||||
BOOLEAN AttachObjectOAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttachment, BOOLEAN playSound = TRUE, UINT8 subObject = 0);
|
||||
BOOLEAN AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttachment, BOOLEAN playSound = TRUE, UINT8 subObject = 0, INT32 iItemPos = -1, BOOLEAN fRemoveProhibited = TRUE, std::vector<UINT16> usAttachmentSlotIndexVector = std::vector<UINT16>());
|
||||
BOOLEAN RemoveAttachment( OBJECTTYPE* pAttachment, OBJECTTYPE * pNewObj = NULL, UINT8 subObject = 0, SOLDIERTYPE * pSoldier = NULL, BOOLEAN fForceInseperable = FALSE, BOOLEAN fRemoveProhibited = TRUE);
|
||||
// HEADROCK HAM 5: Object Transformation
|
||||
BOOLEAN TransformObject( SOLDIERTYPE * pSoldier, UINT8 ubStatusIndex, TransformInfoStruct * Transform, OBJECTTYPE *pParent );
|
||||
|
||||
//see comments in .cpp
|
||||
static void DeleteMe(OBJECTTYPE** ppObject);
|
||||
@@ -590,6 +609,17 @@ extern OBJECTTYPE gTempObject;
|
||||
#define IC_BOBBY_GUN ( IC_GUN | IC_LAUNCHER )
|
||||
#define IC_BOBBY_MISC ( IC_GRENADE | IC_BOMB | IC_MISC | IC_MEDKIT | IC_KIT | IC_BLADE | IC_THROWING_KNIFE | IC_PUNCH | IC_FACE | IC_LBEGEAR )
|
||||
|
||||
// HEADROCK HAM 5: Inventory Filter Types
|
||||
#define IC_MAPFILTER_GUN ( IC_GUN | IC_LAUNCHER )
|
||||
#define IC_MAPFILTER_AMMO ( IC_AMMO )
|
||||
#define IC_MAPFILTER_EXPLOSV ( IC_GRENADE | IC_BOMB )
|
||||
#define IC_MAPFILTER_MELEE ( IC_BLADE | IC_PUNCH | IC_THROWN | IC_THROWING_KNIFE )
|
||||
#define IC_MAPFILTER_KIT ( IC_KIT | IC_MEDKIT | IC_APPLIABLE )
|
||||
#define IC_MAPFILTER_LBE ( IC_LBEGEAR | IC_BELTCLIP )
|
||||
#define IC_MAPFILTER_ARMOR ( IC_ARMOUR | IC_FACE )
|
||||
#define IC_MAPFILTER_MISC ( IC_TENTACLES | IC_KEY | IC_MISC | IC_MONEY | IC_NONE )
|
||||
#define IC_MAPFILTER_ALL ( IC_MAPFILTER_GUN | IC_MAPFILTER_AMMO | IC_MAPFILTER_EXPLOSV | IC_MAPFILTER_MELEE | IC_MAPFILTER_KIT | IC_MAPFILTER_LBE | IC_MAPFILTER_ARMOR | IC_MAPFILTER_MISC )
|
||||
|
||||
// Chrisl: Define attachment classes
|
||||
#define AC_DEFAULT1 0x00000001 //1
|
||||
#define AC_BARREL 0x00000002 //2
|
||||
@@ -904,6 +934,10 @@ public:
|
||||
};
|
||||
#define SIZEOF_POCKETTYPE offsetof( POCKETTYPE, POD )
|
||||
extern std::vector<POCKETTYPE> LBEPocketType;
|
||||
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
extern std::map<UINT8,popupDef> LBEPocketPopup;
|
||||
|
||||
typedef enum ePOCKET_TYPE
|
||||
{
|
||||
NO_POCKET_TYPE = 0,
|
||||
@@ -1445,6 +1479,9 @@ typedef struct
|
||||
UINT32 uiIndex;
|
||||
} ComboMergeInfoStruct;
|
||||
|
||||
// HEADROCK HAM 5: Defining this here because we need MAXITEMS. The struct is defined earlier.
|
||||
extern TransformInfoStruct Transform[MAXITEMS+1];
|
||||
|
||||
extern ComboMergeInfoStruct AttachmentComboMerge[MAXITEMS+1];
|
||||
BOOLEAN EXPLOSIVE_GUN(UINT16 x );
|
||||
|
||||
|
||||
+384
-19
@@ -55,6 +55,9 @@
|
||||
#include "debug control.h"
|
||||
|
||||
#include "math.h"
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
#include <map>
|
||||
#include "popup_definition.h"
|
||||
#endif
|
||||
|
||||
#ifdef JA2UB
|
||||
@@ -72,9 +75,19 @@ class SOLDIERTYPE;
|
||||
void SetNewItem( SOLDIERTYPE *pSoldier, UINT8 ubInvPos, BOOLEAN fNewItem );
|
||||
|
||||
extern SOLDIERTYPE *gpItemDescSoldier;
|
||||
// HEADROCK HAM 5: We need access to these values for item transformation purposes
|
||||
extern BOOLEAN gfItemDescObjectIsAttachment;
|
||||
extern OBJECTTYPE *gpItemDescObject;
|
||||
extern OBJECTTYPE *gpItemDescPrevObject;
|
||||
extern OBJECTTYPE *gpItemDescOrigAttachmentObject;
|
||||
extern OBJECTTYPE gCloneItemDescObject;
|
||||
extern BOOLEAN fShowMapInventoryPool;
|
||||
extern UINT32 guiCurrentItemDescriptionScreen;
|
||||
extern BOOLEAN AutoPlaceObjectInInventoryStash( OBJECTTYPE *pItemPtr, INT32 sGridNo );
|
||||
// HEADROCK HAM 5: Also need these to trigger Map Inventory changes appropriately.
|
||||
extern BOOLEAN fMapInventoryZoom;
|
||||
// HEADROCK HAM 5: And this, for checking whether an item is in the pool.
|
||||
extern std::vector<WORLDITEM> pInventoryPoolList;
|
||||
|
||||
UINT16 OldWayOfCalculatingScopeBonus(SOLDIERTYPE *pSoldier);
|
||||
// weight units are 100g each
|
||||
@@ -1154,6 +1167,8 @@ ComboMergeInfoStruct AttachmentComboMerge[MAXITEMS+1];// =
|
||||
// {NOTHING, {NOTHING, NOTHING}, NOTHING },
|
||||
//};
|
||||
|
||||
// HEADROCK HAM 5: Item Transformations table, containing all possible Transformations.
|
||||
TransformInfoStruct Transform[MAXITEMS+1];
|
||||
|
||||
UINT16 IncompatibleAttachments[MAXATTACHMENTS][2];// =
|
||||
//{
|
||||
@@ -1223,6 +1238,9 @@ std::vector<LBETYPE> LoadBearingEquipment;
|
||||
std::vector<POCKETTYPE> LBEPocketType;
|
||||
//TODO make the indices of this a define, because I do not know what is a large pocket (I guess 3)
|
||||
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
std::map<UINT8,popupDef> LBEPocketPopup;
|
||||
|
||||
//POCKETTYPE LBEPocketType[MAXITEMS+1]; //=
|
||||
//{
|
||||
// { /* Blank Entry */ 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
|
||||
@@ -4761,7 +4779,8 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
|
||||
|
||||
//WarmSteel - Replaced this with one that also checks default attachments, otherwise you could not replace built-in bonuses with default inseperable attachments.
|
||||
//RemoveProhibitedAttachments(pSoldier, this, usResult);
|
||||
ReInitMergedItem(pSoldier, this, usOldItem);
|
||||
// HEADROCK HAM 5: Added argument for statusindex.
|
||||
ReInitMergedItem(pSoldier, this, usOldItem, 0);
|
||||
|
||||
//AutoPlaceObject( pAttachment );
|
||||
//ADB ubWeight has been removed, see comments in OBJECTTYPE
|
||||
@@ -4866,7 +4885,7 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
|
||||
|
||||
//WarmSteel - Replaced this with one that also checks default attachments, otherwise you could not replace built-in bonuses with default inseperable attachments.
|
||||
//RemoveProhibitedAttachments(pSoldier, this, usResult);
|
||||
ReInitMergedItem(pSoldier, this, usOldItem);
|
||||
ReInitMergedItem(pSoldier, this, usOldItem, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -4923,7 +4942,8 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
|
||||
|
||||
//WarmSteel - Replaced this with one that also checks default attachments, otherwise you could not replace built-in bonuses with default inseperable attachments.
|
||||
//RemoveProhibitedAttachments(pSoldier, this, usResult);
|
||||
ReInitMergedItem(pSoldier, this, usOldItem);
|
||||
// HEADROCK HAM 5: Added argument for statusindex.
|
||||
ReInitMergedItem(pSoldier, this, usOldItem, subObject);
|
||||
|
||||
if ( ubType != TREAT_ARMOUR )
|
||||
{
|
||||
@@ -5296,7 +5316,9 @@ void RemoveProhibitedAttachments(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16
|
||||
//WarmSteel - Needed for merges, because the new items don't get their new default attachments.
|
||||
//This does the same as RemoveProhibitedAttachments but is a bit more thorough at it.
|
||||
//This is at the risk that items move around if more than one slot is valid, but since this is used for "new" guns after merges, that's acceptable.
|
||||
void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem){
|
||||
// HEADROCK HAM 5: Added argument for statusindex.
|
||||
void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem, UINT8 ubStatusIndex)
|
||||
{
|
||||
|
||||
attachmentList tempAttachList;
|
||||
attachmentList tempSlotChangingAttachList;
|
||||
@@ -5304,18 +5326,18 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
UINT8 slotCount;
|
||||
std::vector<UINT16> usAttachmentSlotIndexVector = GetItemSlots(pObj);
|
||||
|
||||
if( !(*pObj)[0]->attachments.empty() ){
|
||||
if( !(*pObj)[ubStatusIndex]->attachments.empty() ){
|
||||
//Have to take all attachments off, because of possible incompatibilities with the default attachments (can't NOT attach a default attachment because some stupid item already attached is incompatible with it).
|
||||
|
||||
//Delete all default inseperable attachments from the old gun.
|
||||
//This is safe UNLESS the inseparable default attachments is not the only attachment of the same kind on the gun.
|
||||
//I can't think of any reason why this would happen, and if it does the worst that can happen is your attachment disappearing.
|
||||
for(slotCount = 0; slotCount < (*pObj)[0]->attachments.size(); slotCount++){
|
||||
UINT16 usAttach = (*pObj)[0]->GetAttachmentAtIndex(slotCount)->usItem;
|
||||
for(slotCount = 0; slotCount < (*pObj)[ubStatusIndex]->attachments.size(); slotCount++){
|
||||
UINT16 usAttach = (*pObj)[ubStatusIndex]->GetAttachmentAtIndex(slotCount)->usItem;
|
||||
if(Item[usAttach].inseparable){
|
||||
for(UINT16 cnt = 0; cnt < MAX_DEFAULT_ATTACHMENTS && Item[usOldItem].defaultattachments[cnt] != 0; cnt++){
|
||||
if(Item[usOldItem].defaultattachments[cnt] == usAttach){
|
||||
(*pObj)[0]->RemoveAttachmentAtIndex(slotCount);
|
||||
(*pObj)[ubStatusIndex]->RemoveAttachmentAtIndex(slotCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -5323,36 +5345,38 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
}
|
||||
slotCount = 0;
|
||||
//Put all other attachments into a temporary storage, so we can try to re-attach later.
|
||||
for(attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); iter++, slotCount++) {
|
||||
for(attachmentList::iterator iter = (*pObj)[ubStatusIndex]->attachments.begin(); iter != (*pObj)[ubStatusIndex]->attachments.end(); iter++, slotCount++) {
|
||||
if(iter->exists()){
|
||||
UINT16 cnt = 0;
|
||||
tempAttachList.push_back((*iter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//clear the attachment list, we've saved the attachments somewhere safe now.
|
||||
(*pObj)[0]->attachments.clear();
|
||||
(*pObj)[ubStatusIndex]->attachments.clear();
|
||||
|
||||
//Make sure the attachment slot data is correct.
|
||||
//std::vector<UINT16> tempItemSlots = GetItemSlots(pObj);
|
||||
(*pObj)[0]->attachments.resize(usAttachmentSlotIndexVector.size());
|
||||
(*pObj)[ubStatusIndex]->attachments.resize(usAttachmentSlotIndexVector.size());
|
||||
//pObj->usAttachmentSlotIndexVector = tempItemSlots;
|
||||
|
||||
|
||||
//Now add all default attachments, but add them with the same status as the gun. We don't want to make repairing guns easy :)
|
||||
for(UINT16 cnt = 0; cnt < MAX_DEFAULT_ATTACHMENTS && Item[pObj->usItem].defaultattachments[cnt] != 0; cnt++){
|
||||
//Only add inseparable default attachments, because they are likely "part" of the gun.
|
||||
if(Item[Item[pObj->usItem].defaultattachments[cnt]].inseparable){
|
||||
static OBJECTTYPE defaultAttachment;
|
||||
CreateItem(Item [ pObj->usItem ].defaultattachments[cnt],(*pObj)[0]->data.objectStatus,&defaultAttachment);
|
||||
AssertMsg(pObj->AttachObject(NULL,&defaultAttachment, FALSE, 0, -1, FALSE), "A default attachment could not be attached after merging, this should not be possible.");
|
||||
CreateItem(Item [ pObj->usItem ].defaultattachments[cnt],(*pObj)[ubStatusIndex]->data.objectStatus,&defaultAttachment);
|
||||
AssertMsg(pObj->AttachObject(NULL,&defaultAttachment, FALSE, ubStatusIndex, -1, FALSE), "A default attachment could not be attached after merging, this should not be possible.");
|
||||
}
|
||||
}
|
||||
|
||||
//First re-attach any slot-changing attachments.
|
||||
for (attachmentList::iterator iter = tempSlotChangingAttachList.begin(); iter != tempSlotChangingAttachList.end();) {
|
||||
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE )){
|
||||
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, ubStatusIndex )){
|
||||
//This seems to be rather valid. Can't be 100% sure though.
|
||||
if(pObj->AttachObject(NULL, &(*iter), FALSE)){
|
||||
if(pObj->AttachObject(NULL, &(*iter), FALSE, ubStatusIndex)){
|
||||
//Ok now we can be sure, lets remove this object so we don't try to drop it later.
|
||||
iter = tempSlotChangingAttachList.erase(iter);
|
||||
} else {
|
||||
@@ -5365,9 +5389,9 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
|
||||
//Time to re-attach the other attachments, if we can. I am the king of copy pasta.
|
||||
for (attachmentList::iterator iter = tempAttachList.begin(); iter != tempAttachList.end();) {
|
||||
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE)){
|
||||
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, ubStatusIndex)){
|
||||
//This seems to be rather valid. Can't be 100% sure though.
|
||||
if(pObj->AttachObject(NULL, &(*iter), FALSE)){
|
||||
if(pObj->AttachObject(NULL, &(*iter), FALSE, ubStatusIndex)){
|
||||
//Ok now we can be sure, lets remove this object so we don't try to drop it later.
|
||||
iter = tempAttachList.erase(iter);
|
||||
} else {
|
||||
@@ -5385,7 +5409,9 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
if (pSoldier) {
|
||||
if ( !AutoPlaceObject( pSoldier, &(*iter), FALSE ) )
|
||||
{ // put it on the ground
|
||||
AddItemToPool( pSoldier->sGridNo, &(*iter), 1, pSoldier->pathing.bLevel, 0 , -1 );
|
||||
// HEADROCK HAM 5: A much more suitable function. Works in both tactical and mapscreen!
|
||||
AutoPlaceObjectToWorld( pSoldier, &(*iter), true );
|
||||
//AddItemToPool( pSoldier->sGridNo, &(*iter), 1, pSoldier->pathing.bLevel, 0 , -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5397,11 +5423,14 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
if (pSoldier) {
|
||||
if ( !AutoPlaceObject( pSoldier, &(*iter), FALSE ) )
|
||||
{ // put it on the ground
|
||||
AddItemToPool( pSoldier->sGridNo, &(*iter), 1, pSoldier->pathing.bLevel, 0 , -1 );
|
||||
// HEADROCK HAM 5: A much more suitable function. Works in both tactical and mapscreen!
|
||||
AutoPlaceObjectToWorld( pSoldier, &(*iter), true );
|
||||
//AddItemToPool( pSoldier->sGridNo, &(*iter), 1, pSoldier->pathing.bLevel, 0 , -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EjectAmmoAndPlace(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT8 subObject)
|
||||
@@ -12597,3 +12626,339 @@ FLOAT GetItemCooldownFactor( OBJECTTYPE * pObj )
|
||||
|
||||
return cooldownfactor;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HEADROCK HAM 5: Item Transformation.
|
||||
// Item Transformation is a new way to interact with items. Where Merges combine two items into one, a Transformation
|
||||
// can turn one item into another item, or into more than one item.
|
||||
// To instigate a Transformation, the player uses a menu to choose the desired effect. Then the program comes here to
|
||||
// see how it's done.
|
||||
// The instructions for performing a specific transformation are drawn from XML and fed into this function as a pointer.
|
||||
// They tell us what items will result from this transformation, as well as the APBP cost.
|
||||
|
||||
BOOLEAN OBJECTTYPE::TransformObject( SOLDIERTYPE * pSoldier, UINT8 ubStatusIndex, TransformInfoStruct * Transform, OBJECTTYPE *pParent )
|
||||
{
|
||||
// The argument "Transform" is a pointer to an entry in the Transformation Data array. By looking at the pointer we
|
||||
// can determine all the data we need. Therefore, this pointer must not be null!
|
||||
AssertMsg( Transform != NULL, String( "OBJECTTYPE::TransformObject attempt with invalid Transformation data." ) );
|
||||
|
||||
// Booleans to track what happened during the transformation.
|
||||
BOOLEAN fSplit = FALSE;
|
||||
BOOLEAN fDropped = FALSE;
|
||||
BOOLEAN fRemoved = FALSE;
|
||||
BOOLEAN fItemInPool = FALSE;
|
||||
|
||||
// This boolean tracks whether we've managed to place an item in a soldier's inventory.
|
||||
BOOLEAN fFoundPlaceInInventory = FALSE;
|
||||
|
||||
// Constants for storing details about the original item.
|
||||
OBJECTTYPE TempItem;
|
||||
UINT16 usOrigItem = this->usItem;
|
||||
UINT32 uiOrigClass = Item[this->usItem].usItemClass;
|
||||
UINT8 ubOrigNumObjects = this->ubNumberOfObjects;
|
||||
|
||||
UINT16 usAPCost = 0;
|
||||
INT32 iBPCost = 0;
|
||||
|
||||
// An array to store all result items.
|
||||
UINT16 usResult[MAX_NUM_TRANSFORMATION_RESULTS];
|
||||
UINT32 iNumResults = 0;
|
||||
|
||||
// Start reading transformation data with APBP costs.
|
||||
usAPCost = Transform->usAPCost;
|
||||
iBPCost = Transform->iBPCost;
|
||||
|
||||
// Check whether our soldier can afford this transformation!
|
||||
if (!EnoughPoints( pSoldier, (INT16)usAPCost, iBPCost, true ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Soldier can afford the transformation. Deduct APBP as necessary.
|
||||
DeductPoints( pSoldier, (INT16)usAPCost, iBPCost, false );
|
||||
}
|
||||
|
||||
// Read all result items for this transformation. Record them into an array.
|
||||
for (UINT32 curResult = 0; curResult < MAX_NUM_TRANSFORMATION_RESULTS; curResult++)
|
||||
{
|
||||
if (Transform->usResult[curResult] > 0)
|
||||
{
|
||||
usResult[curResult] = Transform->usResult[curResult];
|
||||
// Count the number of valid result items
|
||||
iNumResults++;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no result items, the Transformation is illegal - we need at least one resulting item!
|
||||
AssertMsg( iNumResults, String( "OBJECTTYPE::TransformObject attempting to transform an object which has no resulting items defined!" ) );
|
||||
|
||||
if (iNumResults > 1)
|
||||
{
|
||||
fSplit = TRUE;
|
||||
}
|
||||
|
||||
// Play a gun-cocking sound, it's the best one we've got ATM.
|
||||
PlayJA2Sample( ATTACH_TO_GUN, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
||||
|
||||
// Before we continue, lets check whether our object is in the sector inventory.
|
||||
// Is the sector inventory open?
|
||||
if (fShowMapInventoryPool)
|
||||
{
|
||||
// Is our object currently in the pool?
|
||||
for (UINT32 x = 0; x < pInventoryPoolList.size(); x++)
|
||||
{
|
||||
if (pInventoryPoolList[x].object.exists())
|
||||
{
|
||||
if (&(pInventoryPoolList[x].object) == this)
|
||||
{
|
||||
// Aha! In that case, all transformations will be done directly at the sector pool,
|
||||
// with multiple results ending on the ground rather than in the inventory.
|
||||
fItemInPool = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// The Transformation itself
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// We're going to do the transformation in steps, going hierarchially down from the item's own attachments,
|
||||
// to itsself, then its parents, and finally resulting items and unrelated inventory.
|
||||
// Note that we'll need to change the item's usItem property several times during this process, so lets
|
||||
// record its original usItem now.
|
||||
UINT16 usOldItem = this->usItem;
|
||||
|
||||
// STEP 1: Attachments and subsidiary objects.
|
||||
|
||||
// First of all, if the original item is a gun, we'll need to see if it can hold the same magazine after the
|
||||
// transformation. If it can't, the magazine will be ejected immediately into the soldier's inventory.
|
||||
|
||||
// Is this a gun, AND does it have any ammo loaded?
|
||||
if ( Item[this->usItem].usItemClass == IC_GUN && (*this)[ubStatusIndex]->data.gun.usGunAmmoItem != NONE && (*this)[ubStatusIndex]->data.gun.ubGunShotsLeft > 0 )
|
||||
{
|
||||
// Is the resulting item not a gun, OR is the resulting item of a different caliber, OR is the resulting item's
|
||||
// magazine too small?
|
||||
if ( Item[usResult[0]].usItemClass != IC_GUN || Weapon[Item[usResult[0]].ubClassIndex].ubCalibre != Weapon[Item[this->usItem].ubClassIndex].ubCalibre || (*this)[ubStatusIndex]->data.gun.ubGunShotsLeft > Weapon[Item[usResult[0]].ubClassIndex].ubMagSize )
|
||||
{
|
||||
// item types/calibers/magazines don't match, spit out old ammo
|
||||
EjectAmmoAndPlace(pSoldier, this);
|
||||
}
|
||||
}
|
||||
|
||||
// STEP 2: Check the item's attachments to see whether they still fit.
|
||||
// We'll have to fool this function into thinking we've already changed the item.
|
||||
// Note that this function automatically drops invalid attachments to the ground.
|
||||
this->usItem = usResult[0];
|
||||
// Repeat for each object in the stack.
|
||||
for ( UINT8 x = 0; x < this->ubNumberOfObjects; x++ )
|
||||
{
|
||||
ReInitMergedItem(pSoldier, this, usOldItem, x);
|
||||
}
|
||||
this->usItem = usOldItem;
|
||||
|
||||
//RemoveProhibitedAttachments(pSoldier, this, usOldItem);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// TRANSFORM
|
||||
this->usItem = usResult[0];
|
||||
// Record the new itemclass
|
||||
UINT32 uiNewClass = Item[this->usItem].usItemClass;
|
||||
// Make a clone of this object, so that we can point the DescBox to it later if we run into any problems.
|
||||
gCloneItemDescObject = *(this);
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////
|
||||
// Placement checks
|
||||
|
||||
// Is the item an attachment? If so, check its parent to see if it's still compatible.
|
||||
if (pParent != NULL)
|
||||
{
|
||||
// When transforming an attachment, "THIS" is actually a copy of the object, called Object2. So transforming
|
||||
// "this" would only yield, at most, a superficial change (Description Box will change). The attachment item
|
||||
// itself will not change at all.
|
||||
|
||||
// Lets change the attachment item directly, then.
|
||||
gpItemDescOrigAttachmentObject->usItem = usResult[0];
|
||||
// Make a copy of it, so we know what data it contained.
|
||||
OBJECTTYPE pClone = *gpItemDescOrigAttachmentObject;
|
||||
|
||||
// Test the parent now. See whether all attachments are still valid on it.
|
||||
ReInitMergedItem(pSoldier, pParent, pParent->usItem, ubStatusIndex);
|
||||
|
||||
gpItemDescOrigAttachmentObject = NULL;
|
||||
|
||||
// After reiniting the attachments on the parent, "this" still exists, but the actual object is gone.
|
||||
// Lets look through the parent's attachments list, and see if we can find it again.
|
||||
UINT8 ubNewAttachmentsIndex = 0;
|
||||
for(attachmentList::iterator iter = (*pParent)[ubStatusIndex]->attachments.begin(); iter != (*pParent)[ubStatusIndex]->attachments.end(); iter++, ubNewAttachmentsIndex++)
|
||||
{
|
||||
if(iter->exists())
|
||||
{
|
||||
// Compare it to the clone we made earlier.
|
||||
if (*(iter) == pClone)
|
||||
{
|
||||
// Yes, here it is!
|
||||
gpItemDescOrigAttachmentObject = (*pParent)[ubStatusIndex]->GetAttachmentAtIndex( ubNewAttachmentsIndex );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Have we failed to find our item on the reinited parent?
|
||||
if (gpItemDescOrigAttachmentObject == NULL)
|
||||
{
|
||||
// It has been removed. Lets reset all the Description Box extra variables.
|
||||
// Note that by doing this, we actually trigger closing the description box later down the line.
|
||||
pParent = NULL;
|
||||
gfItemDescObjectIsAttachment = NULL;
|
||||
gpItemDescPrevObject = NULL;
|
||||
fRemoved = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Our object is not an attachment. If it is on a soldier, it may still not fit in the pocket where
|
||||
// it is currently placed, so lets see if we have to move it.
|
||||
else if (!fItemInPool)
|
||||
{
|
||||
for (INT8 bPocket = HELMETPOS; bPocket < NUM_INV_SLOTS; bPocket++)
|
||||
{
|
||||
if (&(pSoldier->inv[bPocket]) == this)
|
||||
{
|
||||
// Found our item. Does it fit in this slot?
|
||||
if (!CanItemFitInPosition(pSoldier, this, bPocket, FALSE) )
|
||||
{
|
||||
if (!AutoPlaceObject( pSoldier, this, TRUE ))
|
||||
{
|
||||
fDropped = TRUE;
|
||||
|
||||
AutoPlaceObjectToWorld( pSoldier, this, TRUE );
|
||||
|
||||
//Unfortunately the above function will not erase the item in tactical mode, so lets
|
||||
//double-check.
|
||||
if (pSoldier->inv[bPocket].exists() )
|
||||
{
|
||||
DeleteObj( &(pSoldier->inv[bPocket]) );
|
||||
}
|
||||
}
|
||||
// Whatever we've done with it, THIS is no longer a valid item, so lets
|
||||
// fool the desc box by switching it with the clone.
|
||||
gpItemDescObject = &gCloneItemDescObject;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If either the new or old items were LBEs, lets check the entire LBE inventory for item-size compatibility!
|
||||
//if (uiOrigClass & IC_LBEGEAR || uiNewClass & IC_LBEGEAR )
|
||||
if (!fItemInPool)
|
||||
{
|
||||
for (INT8 bPocket = HELMETPOS; bPocket < NUM_INV_SLOTS; bPocket++)
|
||||
{
|
||||
if (pSoldier->inv[bPocket].exists())
|
||||
{
|
||||
// Found an item. Does it still fit inside its own slot?
|
||||
if (!CanItemFitInPosition(pSoldier, &(pSoldier->inv[bPocket]), bPocket, FALSE) )
|
||||
{
|
||||
if (!AutoPlaceObject( pSoldier, &(pSoldier->inv[bPocket]), TRUE ))
|
||||
{
|
||||
fDropped = TRUE;
|
||||
|
||||
AutoPlaceObjectToWorld( pSoldier, &(pSoldier->inv[bPocket]), TRUE );
|
||||
|
||||
//Unfortunately the above function will not erase the item in tactical mode, so lets
|
||||
//double-check.
|
||||
if (pSoldier->inv[bPocket].exists() )
|
||||
{
|
||||
DeleteObj( &(pSoldier->inv[bPocket]) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// Multiple Results
|
||||
//
|
||||
// If the item has several transformation results defined, that means we're going to split it into two or
|
||||
// more items.
|
||||
|
||||
// We actually start with any results above the first. This occurs if the item is split into two or more other
|
||||
// items. We'll try to place them in the pSoldier's inventory if possible, otherwise they are dumped to the
|
||||
// sector pool.
|
||||
|
||||
// Iterate through the results array we've constructed earlier.
|
||||
for (UINT32 x = 1; x < iNumResults; x++)
|
||||
{
|
||||
for (UINT32 y = 0; y < ubOrigNumObjects; y++)
|
||||
{
|
||||
// Create the result item. Set its condition to match that of the original.
|
||||
CreateItem( usResult[x], (*this)[ubStatusIndex]->data.objectStatus, &gTempObject );
|
||||
|
||||
if (!fItemInPool)
|
||||
{
|
||||
// Try placing it in the soldier's invnetory.
|
||||
if (!AutoPlaceObject( pSoldier, &gTempObject, TRUE ))
|
||||
{
|
||||
// Failed to find a place in the inventory. Dump to sector pool.
|
||||
AutoPlaceObjectToWorld( pSoldier, &gTempObject, true );
|
||||
|
||||
fDropped = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AutoPlaceObjectToWorld( pSoldier, &gTempObject, true );
|
||||
}
|
||||
|
||||
// Cleanup after the autoplace has to occur in tactical mode.
|
||||
if (gTempObject.exists())
|
||||
{
|
||||
DeleteObj( &(gTempObject) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check the soldier to see how his stats have changed as a result of altering his gear.
|
||||
ApplyEquipmentBonuses(pSoldier);
|
||||
|
||||
if (fItemInPool && fSplit)
|
||||
{
|
||||
CHAR16 pStr[500];
|
||||
// Item was split apart. Since it was in the sector inventory, it's common sense that all results
|
||||
// are in the sector inventory as well, so no need to report anything extra.
|
||||
swprintf( pStr, gzTransformationMessage[ 1 ], Item[usOrigItem].szItemName, pSoldier->name );
|
||||
ScreenMsg( FONT_ORANGE, MSG_INTERFACE, pStr );
|
||||
}
|
||||
else if (fSplit || fDropped)
|
||||
{
|
||||
CHAR16 pStr[500];
|
||||
if (fSplit && !fDropped)
|
||||
{
|
||||
// Item was split apart, but all subitems remained in the inventory.
|
||||
swprintf( pStr, gzTransformationMessage[ 2 ], Item[usOrigItem].szItemName, pSoldier->name );
|
||||
ScreenMsg( FONT_ORANGE, MSG_INTERFACE, pStr );
|
||||
}
|
||||
else if (fDropped && !fSplit)
|
||||
{
|
||||
// Either the item itself or another item has been dropped to the sector inventory due to lack of
|
||||
// space.
|
||||
swprintf( pStr, gzTransformationMessage[ 3 ], pSoldier->name );
|
||||
DoScreenIndependantMessageBox( pStr, MSG_BOX_FLAG_OK, NULL );
|
||||
}
|
||||
else if (fDropped && fSplit)
|
||||
{
|
||||
// Item was split apart. Either the item itself or another item has been dropped to the sector
|
||||
// inventory due to lack of space.
|
||||
swprintf( pStr, gzTransformationMessage[ 4 ], Item[usOrigItem].szItemName, pSoldier->name );
|
||||
DoScreenIndependantMessageBox( pStr, MSG_BOX_FLAG_OK, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
// Signal a successful transformation.
|
||||
return TRUE;
|
||||
}
|
||||
+2
-1
@@ -111,7 +111,8 @@ void RemoveInvObject( SOLDIERTYPE *pSoldier, UINT16 usItem );
|
||||
void InitItemAttachments(OBJECTTYPE* pObj);
|
||||
std::vector<UINT16> GetItemSlots(OBJECTTYPE* pObj, UINT8 subObject = 0, BOOLEAN fAttachment = FALSE);
|
||||
void RemoveProhibitedAttachments(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usItem, BOOLEAN fOnlyRemoveWhenSlotsChange = 1);
|
||||
void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem);
|
||||
// HEADROCK HAM 5: Added argument for statusindex.
|
||||
void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem, UINT8 ubStatusIndex);
|
||||
void EjectAmmoAndPlace(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT8 subObject = 0);
|
||||
|
||||
BOOLEAN CanItemFitInVehicle( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj, INT8 bPos, BOOLEAN fDoingPlacement );
|
||||
|
||||
+997
-360
File diff suppressed because it is too large
Load Diff
+6
-1
@@ -67,6 +67,8 @@ INT8 ChanceToGetThrough( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT d
|
||||
INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usHandItem, INT16 sHitBy, BOOLEAN fBuckshot, BOOLEAN fFake );
|
||||
// HEADROCK HAM 4: Changed the name of one argument to avoid confusion with the new CTH system.
|
||||
INT8 FireBulletGivenTargetNCTH( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usHandItem, INT16 sApertureRatio, BOOLEAN fBuckshot, BOOLEAN fFake );
|
||||
// HEADROCK HAM 5: Function for fragments ejected from an explosion.
|
||||
INT8 FireFragmentGivenTarget( SOLDIERTYPE * pThrower, FLOAT dStartX, FLOAT dStartY, FLOAT dStartZ, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usExplosiveItem );
|
||||
|
||||
#define CALC_FROM_ALL_DIRS -1
|
||||
#define CALC_FROM_WANTED_DIR -2
|
||||
@@ -223,11 +225,14 @@ void CalcMuzzleSway( SOLDIERTYPE *pShooter, FLOAT *dMuzzleOffsetX, FLOAT *dMuzzl
|
||||
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);
|
||||
// HEADROCK HAM 5: Removed and replaced by continuously-variable CF
|
||||
// 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 );
|
||||
// HEADROCK HAM 5: New function, completely replaces the Counter Force Frequency check.
|
||||
FLOAT CalcCounterForceChange( SOLDIERTYPE * pShooter, UINT32 uiCounterForceAccuracy, FLOAT dCounterForceMax, FLOAT dMuzzleOffset, INT8 bRecoil, FLOAT dPrevCounterForce, UINT32 uiIntendedBullets );
|
||||
|
||||
// HEADROCK HAM 4: Required for shooting mechanic
|
||||
extern INT8 EffectiveMarksmanship( SOLDIERTYPE * pSoldier );
|
||||
|
||||
@@ -1077,8 +1077,8 @@ BOOLEAN CheckIfRadioIsEquipped( void )
|
||||
|
||||
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) )
|
||||
{
|
||||
bSlot = FindObj( pSoldier, EXTENDEDEAR );
|
||||
//bSlot = FindHearingAid(pSoldier);
|
||||
//bSlot = FindObj( pSoldier, EXTENDEDEAR );
|
||||
bSlot = FindHearingAid(pSoldier);
|
||||
//ScreenMsg( FONT_WHITE, MSG_INTERFACE, L"Position: %d", bSlot );
|
||||
}
|
||||
|
||||
|
||||
@@ -2692,7 +2692,6 @@ INT16 GetAPsToAutoReload( SOLDIERTYPE * pSoldier )
|
||||
{
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
pObj = pSoldier->GetUsedWeapon( &(pSoldier->inv[SECONDHANDPOS]) );
|
||||
|
||||
bExcludeSlot = NO_SLOT;
|
||||
bSlot2 = NO_SLOT;
|
||||
|
||||
|
||||
+25
-11
@@ -80,10 +80,11 @@ class SOLDIERTYPE;
|
||||
#define DROP_LENGTH_CHANGE_RATE 0.1f
|
||||
#define DROP_LENGTH_RAND 2.0f
|
||||
|
||||
#define BASE_DROP_SPEED 7.0f
|
||||
#define DROP_SPEED_RANGE 3.5f
|
||||
#define DROP_SPEED_CHANGE_RATE 0.1f
|
||||
#define DROP_SPEED_RAND 5.0f
|
||||
// HEADROCK HAM 5 X: Externalized for snow.
|
||||
FLOAT BASE_DROP_SPEED;
|
||||
FLOAT DROP_SPEED_RANGE;
|
||||
FLOAT DROP_SPEED_CHANGE_RATE;
|
||||
FLOAT DROP_SPEED_RAND;
|
||||
|
||||
UINT32 guiMaxRainDrops = 79;
|
||||
|
||||
@@ -203,11 +204,18 @@ void ResetRain()
|
||||
pRainDrops = NULL;
|
||||
}
|
||||
|
||||
// Rain
|
||||
BASE_DROP_SPEED = 7.0f;
|
||||
DROP_SPEED_RANGE = 3.5f;
|
||||
DROP_SPEED_CHANGE_RATE = 0.1f;
|
||||
DROP_SPEED_RAND = 5.0f;
|
||||
|
||||
guiCurrMaxAmountOfRainDrops = 0;
|
||||
}
|
||||
|
||||
void GenerateRainDropsList()
|
||||
{
|
||||
// HEADROCK HAM 5 XMAS: More snow than rain.
|
||||
guiCurrMaxAmountOfRainDrops = (UINT32)(BASE_MAXIMUM_DROPS) * gbCurrentRainIntensity;
|
||||
|
||||
pRainDrops = (TRainDrop *)MemAlloc( sizeof( TRainDrop ) * guiCurrMaxAmountOfRainDrops );
|
||||
@@ -415,6 +423,7 @@ void RenderRainOnSurface()
|
||||
|
||||
if( !pCurr->fAlive )continue;
|
||||
|
||||
// Rain
|
||||
LineDraw( TRUE, (int)pCurr->fpX, (int)pCurr->fpY, (int)pCurr->fpX + (int)pCurr->fpEndRelX, (int)(pCurr->fpY + pCurr->fpEndRelY), sDropsColor, pDestBuf );
|
||||
}
|
||||
|
||||
@@ -427,14 +436,19 @@ void GenerateRainMaximums()
|
||||
{
|
||||
fpMinDropAngleOfFalling = 45;
|
||||
fpMaxDropAngleOfFalling = 135;
|
||||
}else
|
||||
if( Random( 2 ) )
|
||||
}
|
||||
else
|
||||
{
|
||||
fpMinDropAngleOfFalling = 20;
|
||||
fpMaxDropAngleOfFalling = 70;
|
||||
}else{
|
||||
fpMinDropAngleOfFalling = 110;
|
||||
fpMaxDropAngleOfFalling = 160;
|
||||
if( Random( 2 ) )
|
||||
{
|
||||
fpMinDropAngleOfFalling = 20;
|
||||
fpMaxDropAngleOfFalling = 70;
|
||||
}
|
||||
else
|
||||
{
|
||||
fpMinDropAngleOfFalling = 110;
|
||||
fpMaxDropAngleOfFalling = 160;
|
||||
}
|
||||
}
|
||||
|
||||
fpCurrDropAngleOfFalling = fpMinDropAngleOfFalling + Random( (UINT32)(fpMaxDropAngleOfFalling - fpMinDropAngleOfFalling) );
|
||||
|
||||
@@ -74,6 +74,8 @@
|
||||
#define MAX_PALACE_DISTANCE 20
|
||||
|
||||
INT8 bNumSquadleadersInArmy = 0; // added by SANDRO
|
||||
// HEADROCK HAM 5: Read target coolness by sector
|
||||
UINT32 gCoolnessBySector[256];
|
||||
|
||||
OLD_SOLDIERCREATE_STRUCT_101::OLD_SOLDIERCREATE_STRUCT_101() {
|
||||
initialize();
|
||||
@@ -3237,8 +3239,8 @@ UINT8 GetLocationModifier( UINT8 ubSoldierClass )
|
||||
INT16 sSectorX, sSectorY, sSectorZ;
|
||||
#ifdef JA2UB
|
||||
#else
|
||||
INT8 bTownId;
|
||||
UINT8 ubPalaceDistance;
|
||||
//INT8 bTownId;
|
||||
//UINT8 ubPalaceDistance;
|
||||
#endif
|
||||
BOOLEAN fSuccess;
|
||||
|
||||
@@ -3372,6 +3374,13 @@ UINT8 GetLocationModifier( UINT8 ubSoldierClass )
|
||||
break;
|
||||
}
|
||||
#else
|
||||
// HEADROCK HAM 5:
|
||||
// The calculation has been replaced with an XML table.
|
||||
|
||||
ubLocationModifier = gCoolnessBySector[SECTOR(sSectorX, sSectorY)];
|
||||
|
||||
/*
|
||||
|
||||
// ignore sSectorZ - treat any underground enemies as if they were on the surface!
|
||||
bTownId = GetTownIdForSector( sSectorX, sSectorY );
|
||||
|
||||
@@ -3401,6 +3410,8 @@ UINT8 GetLocationModifier( UINT8 ubSoldierClass )
|
||||
|
||||
// adjust for distance from Queen's palace (P3) (0 to +30)
|
||||
ubLocationModifier = ( ( MAX_PALACE_DISTANCE - ubPalaceDistance ) * DIFF_FACTOR_PALACE_DISTANCE ) / MAX_PALACE_DISTANCE;
|
||||
*/
|
||||
|
||||
#endif
|
||||
return( ubLocationModifier );
|
||||
}
|
||||
|
||||
@@ -207,8 +207,10 @@
|
||||
<ClCompile Include="XML_HiddenNames.cpp" />
|
||||
<ClCompile Include="XML_IMPItemChoices.cpp" />
|
||||
<ClCompile Include="XML_IncompatibleAttachments.cpp" />
|
||||
<ClCompile Include="XML_ItemAdjustments.cpp" />
|
||||
<ClCompile Include="XML_Launchable.cpp" />
|
||||
<ClCompile Include="XML_LBEPocket.cpp" />
|
||||
<ClCompile Include="XML_LBEPocketPopup.cpp" />
|
||||
<ClCompile Include="XML_LoadBearingEquipment.cpp" />
|
||||
<ClCompile Include="XML_Magazine.cpp" />
|
||||
<ClCompile Include="XML_MercStartingGear.cpp" />
|
||||
|
||||
@@ -611,5 +611,11 @@
|
||||
<ClCompile Include="Ja25_Tactical.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_LBEPocketPopup.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XML_ItemAdjustments.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+251
-102
@@ -1747,9 +1747,19 @@ BOOLEAN UseGunNCTH( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
OBJECTTYPE* pA= &(*iter);
|
||||
if ( (*pA)[0]->data.objectStatus >=USABLE)
|
||||
{
|
||||
INT8 bAmmoReliability = Item[(*pObjAttHand)[0]->data.gun.usGunAmmoItem].bReliability;
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 *
|
||||
(Item[ iter->usItem ].bReliability + bAmmoReliability), 0);
|
||||
INT16 ammoReliability = Item[(*pObjAttHand)[0]->data.gun.usGunAmmoItem].bReliability;
|
||||
// HEADROCK HAM 5: Variable base chance
|
||||
if ( UsingNewCTHSystem() == true)
|
||||
{
|
||||
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
|
||||
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
|
||||
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * (Item[ iter->usItem ].bReliability + ammoReliability) );
|
||||
uiDepreciateTest = max(0, uiDepreciateTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDepreciateTest = max(0,BASIC_DEPRECIATE_CHANCE + 3 * (Item[ iter->usItem ].bReliability + ammoReliability));
|
||||
}
|
||||
if ( !PreRandom( uiDepreciateTest ) && ( (*pObjAttHand)[0]->data.objectStatus > 1) )
|
||||
(*pA)[0]->data.objectStatus--;
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"rel =%d ",Item[ iter->usItem ].bReliability );
|
||||
@@ -2107,8 +2117,18 @@ BOOLEAN UseGunNCTH( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
//}
|
||||
|
||||
// Flugente FTW 1: Added a malus to reliability for overheated guns
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * GetReliability( pObjAttHand ) - iOverheatReliabilityMalus, 0);
|
||||
|
||||
// HEADROCK HAM 5: Variable NCTH base change
|
||||
if ( UsingNewCTHSystem() == true)
|
||||
{
|
||||
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
|
||||
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
|
||||
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * GetReliability( &(pSoldier->inv[pSoldier->ubAttackingHand]) - iOverheatReliabilityMalus) );
|
||||
uiDepreciateTest = max(0, uiDepreciateTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * GetReliability( pObjAttHand ) - iOverheatReliabilityMalus, 0);
|
||||
}
|
||||
if ( !PreRandom( uiDepreciateTest ) && ( (*pObjAttHand)[0]->data.objectStatus > 1) )
|
||||
{
|
||||
(*pObjAttHand)[0]->data.objectStatus--;
|
||||
@@ -2284,9 +2304,19 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
OBJECTTYPE* pA= &(*iter);
|
||||
if ( (*pA)[0]->data.objectStatus >=USABLE)
|
||||
{
|
||||
INT8 bAmmoReliability = Item[(*pObjUsed)[0]->data.gun.usGunAmmoItem].bReliability;
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 *
|
||||
(Item[ iter->usItem ].bReliability + bAmmoReliability), 0);
|
||||
INT16 ammoReliability = Item[(*pObjUsed)[0]->data.gun.usGunAmmoItem].bReliability;
|
||||
// HEADROCK HAM 5: Variable base chance
|
||||
if ( UsingNewCTHSystem() == true )
|
||||
{
|
||||
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
|
||||
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
|
||||
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * (Item[ iter->usItem ].bReliability + ammoReliability) );
|
||||
uiDepreciateTest = __max(0, uiDepreciateTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDepreciateTest = __max(0,BASIC_DEPRECIATE_CHANCE + 3 * (Item[ iter->usItem ].bReliability + ammoReliability));
|
||||
}
|
||||
if ( !PreRandom( uiDepreciateTest ) && ( (*pObjUsed)[0]->data.objectStatus > 1) )
|
||||
(*pA)[0]->data.objectStatus--;
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"rel =%d ",Item[ iter->usItem ].bReliability );
|
||||
@@ -2675,7 +2705,17 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
|
||||
*/
|
||||
|
||||
// Flugente FTW 1: Added a malus to reliability for overheated guns
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * ( GetReliability( pObjUsed ) ) - iOverheatReliabilityMalus, 0);
|
||||
if ( UsingNewCTHSystem() == true )
|
||||
{
|
||||
UINT16 usBaseChance = gGameCTHConstants.BASIC_RELIABILITY_ODDS;
|
||||
FLOAT dReliabilityRatio = 3.0f * ((FLOAT)usBaseChance / (FLOAT)BASIC_DEPRECIATE_CHANCE); // Compare original odds to new odds.
|
||||
uiDepreciateTest = usBaseChance + (INT16)( dReliabilityRatio * GetReliability( &(pSoldier->inv[ pSoldier->ubAttackingHand ])) - iOverheatReliabilityMalus);
|
||||
uiDepreciateTest = max(0, uiDepreciateTest);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDepreciateTest = max( BASIC_DEPRECIATE_CHANCE + 3 * ( GetReliability( pObjUsed ) ) - iOverheatReliabilityMalus, 0);
|
||||
}
|
||||
|
||||
if ( !PreRandom( uiDepreciateTest ) && ( (*pObjUsed)[0]->data.objectStatus > 1) )
|
||||
{
|
||||
@@ -4003,14 +4043,27 @@ void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 s
|
||||
MakeNoise( ubAttackerID, pTargetSoldier->sGridNo, pTargetSoldier->pathing.bLevel, gpWorldLevelData[pTargetSoldier->sGridNo].ubTerrainID, Weapon[ usWeaponIndex ].ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
|
||||
// CALLAHAN START BUGFIX
|
||||
if ( EXPLOSIVE_GUN( usWeaponIndex ) || AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
|
||||
// Provisions for Fragments, which are resulting from a different weapon than the one we are holding in our hand.
|
||||
UINT8 ubAmmoType = 0;
|
||||
if ( pObj->usItem == usWeaponIndex )
|
||||
{
|
||||
ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Must be a fragment.
|
||||
ubAmmoType = Explosive[Item[usWeaponIndex].ubClassIndex].ubFragType;
|
||||
usWeaponIndex = 1; // Set to default gun.
|
||||
}
|
||||
|
||||
if ( EXPLOSIVE_GUN( usWeaponIndex ) || AmmoTypes[ubAmmoType].explosionSize > 1)
|
||||
// CALLAHAN END BUGFIX
|
||||
{
|
||||
// Reduce attacker count!
|
||||
//TODO: Madd --- I don't think this code will ever get called for the HE ammo -- the EXPLOSIVE_GUN check filters out regular guns
|
||||
// marke test mag ammo type: pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.ubGunAmmoType
|
||||
// 2cond 'or' added
|
||||
if ( Item[usWeaponIndex].rocketlauncher || AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1 )
|
||||
if ( Item[usWeaponIndex].rocketlauncher || AmmoTypes[ubAmmoType].explosionSize > 1 )
|
||||
{
|
||||
if ( Item[usWeaponIndex].singleshotrocketlauncher )
|
||||
{
|
||||
@@ -4032,15 +4085,16 @@ void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 s
|
||||
pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
}
|
||||
else if ( AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
|
||||
else if ( AmmoTypes[ubAmmoType].explosionSize > 1)
|
||||
{
|
||||
// re-routed the Highexplosive value to define exposion type
|
||||
IgniteExplosion( ubAttackerID, sXPos, sYPos, 0, GETWORLDINDEXFROMWORLDCOORDS( sYPos, sXPos ), AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].highExplosive , pTargetSoldier->pathing.bLevel );
|
||||
IgniteExplosion( ubAttackerID, sXPos, sYPos, 0, GETWORLDINDEXFROMWORLDCOORDS( sYPos, sXPos ), AmmoTypes[ubAmmoType].highExplosive , pTargetSoldier->pathing.bLevel );
|
||||
// pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
}
|
||||
else // tank cannon
|
||||
{
|
||||
// HEADROCK HAM 5 TODO: TANK_SHELL!
|
||||
IgniteExplosion( ubAttackerID, sXPos, sYPos, 0, GETWORLDINDEXFROMWORLDCOORDS( sYPos, sXPos ), TANK_SHELL, pTargetSoldier->pathing.bLevel );
|
||||
}
|
||||
|
||||
@@ -4088,10 +4142,29 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
pObj = MercPtrs[ ubAttackerID ]->GetUsedWeapon( &MercPtrs [ ubAttackerID ]->inv[MercPtrs[ubAttackerID]->ubAttackingHand] );
|
||||
|
||||
if ( fStopped && ubAttackerID != NOBODY )
|
||||
// Get attacker
|
||||
if (ubAttackerID != NOBODY)
|
||||
{
|
||||
pAttacker = MercPtrs[ ubAttackerID ];
|
||||
}
|
||||
|
||||
// HEADROCK HAM 5: Define differently for fragments
|
||||
UINT8 ubHitVolume = 0;
|
||||
UINT8 ubAmmoType = 0;
|
||||
|
||||
if (pBullet->fFragment)
|
||||
{
|
||||
ubHitVolume = 1;
|
||||
ubAmmoType = Explosive[Item[pBullet->fromItem].ubClassIndex].ubFragType;
|
||||
}
|
||||
else
|
||||
{
|
||||
ubHitVolume = Weapon[usWeaponIndex].ubHitVolume;
|
||||
ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
|
||||
}
|
||||
|
||||
if ( fStopped && ubAttackerID != NOBODY )
|
||||
{
|
||||
if ( pAttacker->ubOppNum != NOBODY )
|
||||
{
|
||||
// if it was another team shooting at someone under our control
|
||||
@@ -4124,11 +4197,11 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
|
||||
if (sZPos > WALL_HEIGHT)
|
||||
{
|
||||
MakeNoise( ubAttackerID, sGridNo, 1, gpWorldLevelData[sGridNo].ubTerrainID, Weapon[ usWeaponIndex ].ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
MakeNoise( ubAttackerID, sGridNo, 1, gpWorldLevelData[sGridNo].ubTerrainID, ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeNoise( ubAttackerID, sGridNo, 0, gpWorldLevelData[sGridNo].ubTerrainID, Weapon[ usWeaponIndex ].ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
MakeNoise( ubAttackerID, sGridNo, 0, gpWorldLevelData[sGridNo].ubTerrainID, ubHitVolume, NOISE_BULLET_IMPACT );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4146,30 +4219,35 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
// Reduce attacker count!
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - end of LAW fire") );
|
||||
// FreeUpAttacker( ubAttackerID );
|
||||
if ( Item[usWeaponIndex].singleshotrocketlauncher )
|
||||
// HEADROCK HAM 5: Fragments fired by such weapons should not explode.
|
||||
if ( pBullet->fFragment == false)
|
||||
{
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, C1, (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
}
|
||||
// changed too to use 2 flag to determine
|
||||
else if ( !Item[usWeaponIndex].singleshotrocketlauncher && Item[usWeaponIndex].rocketlauncher)
|
||||
//there shouldn't be a way to enter here with an UnderBarrel weapon, so retaining original code :JMich
|
||||
{
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("StructureHit: RPG7 item: %d, Ammo: %d",pAttacker->inv[HANDPOS].usItem , pAttacker->inv[HANDPOS][0]->data.gun.usGunAmmoItem ) );
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem , (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
|
||||
//This is just to make multishot launchers work in semi auto. It's not really a permanent solution because it still doesn't allow autofire, but it will do for now.
|
||||
OBJECTTYPE * pLaunchable = FindLaunchableAttachment( &(pAttacker->inv[pAttacker->ubAttackingHand ]), pAttacker->inv[pAttacker->ubAttackingHand ].usItem );
|
||||
if(pLaunchable){
|
||||
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = pLaunchable->usItem;
|
||||
} else {
|
||||
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
if ( Item[usWeaponIndex].singleshotrocketlauncher )
|
||||
{
|
||||
// HEADROCK HAM 5 TODO: C1!!!
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, C1, (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
}
|
||||
// changed too to use 2 flag to determine
|
||||
else if ( !Item[usWeaponIndex].singleshotrocketlauncher && Item[usWeaponIndex].rocketlauncher)
|
||||
//there shouldn't be a way to enter here with an UnderBarrel weapon, so retaining original code :JMich
|
||||
{
|
||||
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("StructureHit: RPG7 item: %d, Ammo: %d",pAttacker->inv[HANDPOS].usItem , pAttacker->inv[HANDPOS][0]->data.gun.usGunAmmoItem ) );
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem , (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
|
||||
//This is just to make multishot launchers work in semi auto. It's not really a permanent solution because it still doesn't allow autofire, but it will do for now.
|
||||
OBJECTTYPE * pLaunchable = FindLaunchableAttachment( &(pAttacker->inv[pAttacker->ubAttackingHand ]), pAttacker->inv[pAttacker->ubAttackingHand ].usItem );
|
||||
if(pLaunchable){
|
||||
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = pLaunchable->usItem;
|
||||
} else {
|
||||
pAttacker->inv[pAttacker->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
}
|
||||
else if ( AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
|
||||
{
|
||||
// re-routed the Highexplosive value to define exposion type
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, AmmoTypes[ (*pObj)[0]->data.gun.ubGunAmmoType].highExplosive , (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
// pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
}
|
||||
else if ( AmmoTypes[(*pObj)[0]->data.gun.ubGunAmmoType].explosionSize > 1)
|
||||
{
|
||||
// re-routed the Highexplosive value to define exposion type
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, AmmoTypes[ (*pObj)[0]->data.gun.ubGunAmmoType].highExplosive , (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
// pSoldier->inv[pSoldier->ubAttackingHand ][0]->data.gun.usGunAmmoItem = NONE;
|
||||
}
|
||||
|
||||
// Moved here to make sure ABC stays >0 until everything done
|
||||
@@ -4184,6 +4262,7 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
//DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - end of TANK fire") );
|
||||
//FreeUpAttacker( ubAttackerID );
|
||||
|
||||
// HEADROCK HAM 5 TODO: Tank shell!!
|
||||
IgniteExplosion( ubAttackerID, CenterX( sGridNo ), CenterY( sGridNo ), 0, sGridNo, TANK_SHELL, (INT8)( sZPos >= WALL_HEIGHT ) );
|
||||
//FreeUpAttacker( (UINT8) ubAttackerID );
|
||||
|
||||
@@ -4202,67 +4281,83 @@ void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UIN
|
||||
DamageStructure( pStructure, (UINT8)iImpact, STRUCTURE_DAMAGE_GUNFIRE, sGridNo, sXPos, sYPos, ubAttackerID );
|
||||
}
|
||||
|
||||
switch( Weapon[ usWeaponIndex ].ubWeaponClass )
|
||||
// HEADROCK HAM 5: Fragments are not fired from guns, so they need a special case.
|
||||
if (pBullet->fFragment == false)
|
||||
{
|
||||
case HANDGUNCLASS:
|
||||
case RIFLECLASS:
|
||||
case SHOTGUNCLASS:
|
||||
case SMGCLASS:
|
||||
case MGCLASS:
|
||||
switch( Weapon[ usWeaponIndex ].ubWeaponClass )
|
||||
{
|
||||
case HANDGUNCLASS:
|
||||
case RIFLECLASS:
|
||||
case SHOTGUNCLASS:
|
||||
case SMGCLASS:
|
||||
case MGCLASS:
|
||||
|
||||
// Guy has missed, play random sound
|
||||
if ( MercPtrs[ ubAttackerID ]->bTeam == gbPlayerNum )
|
||||
{
|
||||
if ( !MercPtrs[ ubAttackerID ]->bDoBurst )
|
||||
// Guy has missed, play random sound
|
||||
if ( MercPtrs[ ubAttackerID ]->bTeam == gbPlayerNum )
|
||||
{
|
||||
if ( Random( 40 ) == 0 )
|
||||
if ( !MercPtrs[ ubAttackerID ]->bDoBurst )
|
||||
{
|
||||
MercPtrs[ ubAttackerID ]->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
|
||||
if ( Random( 40 ) == 0 )
|
||||
{
|
||||
MercPtrs[ ubAttackerID ]->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//fDoMissForGun = TRUE;
|
||||
//break;
|
||||
fDoMissForGun = TRUE;
|
||||
break;
|
||||
//fDoMissForGun = TRUE;
|
||||
//break;
|
||||
fDoMissForGun = TRUE;
|
||||
break;
|
||||
|
||||
case MONSTERCLASS:
|
||||
case MONSTERCLASS:
|
||||
|
||||
DoSpecialEffectAmmoMiss( ubAttackerID, sGridNo, sXPos, sYPos, sZPos, FALSE, TRUE, iBullet );
|
||||
|
||||
RemoveBullet( iBullet );
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - monster attack hit structure") );
|
||||
// FreeUpAttacker( (UINT8) ubAttackerID );
|
||||
|
||||
//PlayJA2Sample( SPIT_RICOCHET , RATE_11025, uiMissVolume, 1, SoundDir( sGridNo ) );
|
||||
break;
|
||||
|
||||
case KNIFECLASS:
|
||||
|
||||
// When it hits the ground, leave on map...
|
||||
if ( Item[ usWeaponIndex ].usItemClass == IC_THROWING_KNIFE )
|
||||
{
|
||||
// OK, have we hit ground?
|
||||
if ( usStructureID == INVALID_STRUCTURE_ID )
|
||||
{
|
||||
// Add item
|
||||
CreateItem( usWeaponIndex, bWeaponStatus, &gTempObject );
|
||||
|
||||
AddItemToPool( sGridNo, &gTempObject, -1 , 0, 0, -1 );
|
||||
|
||||
// Make team look for items
|
||||
NotifySoldiersToLookforItems( );
|
||||
}
|
||||
|
||||
if ( !fHitSameStructureAsBefore )
|
||||
{
|
||||
PlayJA2Sample( MISS_KNIFE, RATE_11025, uiMissVolume, 1, SoundDir( sGridNo ) );
|
||||
}
|
||||
DoSpecialEffectAmmoMiss( ubAttackerID, sGridNo, sXPos, sYPos, sZPos, FALSE, TRUE, iBullet );
|
||||
|
||||
RemoveBullet( iBullet );
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - knife attack hit structure") );
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - monster attack hit structure") );
|
||||
// FreeUpAttacker( (UINT8) ubAttackerID );
|
||||
}
|
||||
|
||||
//PlayJA2Sample( SPIT_RICOCHET , RATE_11025, uiMissVolume, 1, SoundDir( sGridNo ) );
|
||||
break;
|
||||
|
||||
case KNIFECLASS:
|
||||
|
||||
// When it hits the ground, leave on map...
|
||||
if ( Item[ usWeaponIndex ].usItemClass == IC_THROWING_KNIFE )
|
||||
{
|
||||
// OK, have we hit ground?
|
||||
if ( usStructureID == INVALID_STRUCTURE_ID )
|
||||
{
|
||||
// Add item
|
||||
CreateItem( usWeaponIndex, bWeaponStatus, &gTempObject );
|
||||
|
||||
AddItemToPool( sGridNo, &gTempObject, -1 , 0, 0, -1 );
|
||||
|
||||
// Make team look for items
|
||||
NotifySoldiersToLookforItems( );
|
||||
}
|
||||
|
||||
if ( !fHitSameStructureAsBefore )
|
||||
{
|
||||
PlayJA2Sample( MISS_KNIFE, RATE_11025, uiMissVolume, 1, SoundDir( sGridNo ) );
|
||||
}
|
||||
|
||||
RemoveBullet( iBullet );
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("@@@@@@@ Freeing up attacker - knife attack hit structure") );
|
||||
// FreeUpAttacker( (UINT8) ubAttackerID );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( sZPos == 0 )
|
||||
{
|
||||
PlayJA2Sample( MISS_G2 , RATE_11025, 5, 1, SoundDir( sGridNo ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayJA2Sample( MISS_1 + Random(8), RATE_11025, 5, 1, SoundDir( sGridNo ) );
|
||||
}
|
||||
RemoveBullet( iBullet );
|
||||
}
|
||||
|
||||
if ( fDoMissForGun )
|
||||
@@ -8442,8 +8537,24 @@ INT32 TotalArmourProtection( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 u
|
||||
return( iTotalProtection );
|
||||
}
|
||||
|
||||
INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iOrigImpact, INT16 sHitBy, UINT8 * pubSpecial )
|
||||
// HEADROCK HAM 5: Added argument the bullet!
|
||||
INT32 BulletImpact( SOLDIERTYPE *pFirer, BULLET *pBullet, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iOrigImpact, INT16 sHitBy, UINT8 * pubSpecial )
|
||||
{
|
||||
UINT16 usAttackingWeapon = 0;
|
||||
INT32 sOrigGridNo = 0;
|
||||
BOOLEAN fFragment = FALSE;
|
||||
if (pBullet == NULL)
|
||||
{
|
||||
usAttackingWeapon = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType;
|
||||
sOrigGridNo = pFirer->sGridNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
usAttackingWeapon = pBullet->fromItem;
|
||||
sOrigGridNo = pBullet->sOrigGridNo;
|
||||
fFragment = pBullet->fFragment;
|
||||
}
|
||||
|
||||
INT32 iImpact, iFluke, iBonus, iImpactForCrits = 0;
|
||||
INT8 bStatLoss = 0;
|
||||
UINT8 ubAmmoType;
|
||||
@@ -8452,17 +8563,21 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
// in MoveBullet.
|
||||
|
||||
// Set a few things up:
|
||||
if ( Item[ pFirer->usAttackingWeapon ].usItemClass == IC_THROWING_KNIFE )
|
||||
if ( Item[ usAttackingWeapon ].usItemClass == IC_THROWING_KNIFE )
|
||||
{
|
||||
ubAmmoType = AMMO_KNIFE;
|
||||
}
|
||||
else
|
||||
// HEADROCK HAM 5: Added provisions for fragments, which are not fired from the weapon in your hand.
|
||||
else if ( fFragment == FALSE )
|
||||
{
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
OBJECTTYPE* pObj = pFirer->GetUsedWeapon( &pFirer->inv[pFirer->ubAttackingHand] );
|
||||
|
||||
ubAmmoType = (*pObj)[0]->data.gun.ubGunAmmoType;
|
||||
}
|
||||
else
|
||||
{
|
||||
ubAmmoType = Explosive[Item[usAttackingWeapon].ubClassIndex].ubFragType;
|
||||
}
|
||||
|
||||
if ( TANK( pTarget ) )
|
||||
{
|
||||
@@ -8569,7 +8684,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
}
|
||||
|
||||
// Sniper trait adds bonus damage per aim click
|
||||
if (HAS_SKILL_TRAIT( pFirer, SNIPER_NT ) && (pFirer->aiData.bAimTime >= gSkillTraitValues.ubSNDamageBonusFromNumClicks))
|
||||
if (HAS_SKILL_TRAIT( pFirer, SNIPER_NT ) && (pFirer->aiData.bAimTime >= gSkillTraitValues.ubSNDamageBonusFromNumClicks) && !fFragment)
|
||||
{
|
||||
iImpact += (INT32)(iImpact * (pFirer->aiData.bAimTime - gSkillTraitValues.ubSNDamageBonusFromNumClicks + 1) * gSkillTraitValues.ubSNDamageBonusPerClick * NUM_SKILL_TRAITS( pFirer, SNIPER_NT ))/100; // +5% per trait
|
||||
}
|
||||
@@ -8593,8 +8708,15 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
else if (pTarget->ubSoldierClass == SOLDIER_CLASS_ELITE && gGameExternalOptions.sEnemyEliteDamageResistance != 0)
|
||||
iImpact -= ((iImpact * gGameExternalOptions.sEnemyEliteDamageResistance) /100);
|
||||
|
||||
|
||||
iImpact = max( 1, iImpact);
|
||||
// HEADROCK HAM 5.1: Oh sandro, you rendered zerominimumdamage moot...
|
||||
if ( AmmoTypes[ubAmmoType].zeroMinimumDamage )
|
||||
{
|
||||
iImpact = __max( 0, iImpact );
|
||||
}
|
||||
else
|
||||
{
|
||||
iImpact = __max( 1, iImpact);
|
||||
}
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -8622,7 +8744,15 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
case MIKE:
|
||||
// Only 1/2 of the bonus
|
||||
iImpact -= (INT32)(iImpact * gGameExternalOptions.usSpecialNPCStronger / 200);
|
||||
iImpact = max( 1, iImpact);
|
||||
// HEADROCK HAM 5.1: Oh sandro, you rendered zerominimumdamage moot...
|
||||
if ( AmmoTypes[ubAmmoType].zeroMinimumDamage )
|
||||
{
|
||||
iImpact = __max( 0, iImpact );
|
||||
}
|
||||
else
|
||||
{
|
||||
iImpact = __max( 1, iImpact);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -8631,7 +8761,16 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// STOMP traits - Bodybuilding damage resistance
|
||||
if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pTarget, BODYBUILDING_NT ) )
|
||||
iImpact = max( 1, (INT32)(iImpact * (100 - gSkillTraitValues.ubBBDamageResistance) / 100));
|
||||
// HEADROCK HAM 5.1: Oh sandro, you rendered zerominimumdamage moot...
|
||||
if ( AmmoTypes[ubAmmoType].zeroMinimumDamage )
|
||||
{
|
||||
iImpact = __max( 0, (INT32)(iImpact * (100 - gSkillTraitValues.ubBBDamageResistance) / 100));
|
||||
}
|
||||
else
|
||||
{
|
||||
iImpact = __max( 1, (INT32)(iImpact * (100 - gSkillTraitValues.ubBBDamageResistance) / 100));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AdjustImpactByHitLocation( iImpact, ubHitLocation, &iImpact, &iImpactForCrits );
|
||||
@@ -8642,7 +8781,8 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
// is the blow deadly enough for an instant kill?
|
||||
// HEADROCK HAM 3.6: Reattached "Max Distance For Messy Death" tag from the XML! God knows why it wasn't attached when they MADE THAT TAG.
|
||||
//if ( PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= MAX_DISTANCE_FOR_MESSY_DEATH || (PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= MAX_BARRETT_DISTANCE_FOR_MESSY_DEATH && pFirer->usAttackingWeapon == BARRETT ))
|
||||
if ( PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= Weapon[ pFirer->usAttackingWeapon ].maxdistformessydeath )
|
||||
// HEADROCK HAM 5.1: Using usAttackingWeapon
|
||||
if ( PythSpacesAway( sOrigGridNo, pTarget->sGridNo ) <= Weapon[ usAttackingWeapon ].maxdistformessydeath )
|
||||
{
|
||||
if (iImpactForCrits > MIN_DAMAGE_FOR_INSTANT_KILL && iImpactForCrits < pTarget->stats.bLife)
|
||||
{
|
||||
@@ -8695,7 +8835,8 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
// since this value is much lower than the others, it only applies at short range...
|
||||
// HEADROCK HAM 3.6: Reattached "Max Distance For Messy Death" tag from the XML! God knows why it wasn't attached when they MADE THAT TAG.
|
||||
//if ( PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= MAX_DISTANCE_FOR_MESSY_DEATH || (PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= MAX_BARRETT_DISTANCE_FOR_MESSY_DEATH && pFirer->usAttackingWeapon == BARRETT ))
|
||||
if ( PythSpacesAway( pFirer->sGridNo, pTarget->sGridNo ) <= Weapon[ pFirer->usAttackingWeapon ].maxdistformessydeath )
|
||||
// HEADROCK HAM 5.1: Using usAttackingWeapon
|
||||
if ( PythSpacesAway( sOrigGridNo, pTarget->sGridNo ) <= Weapon[ usAttackingWeapon ].maxdistformessydeath )
|
||||
{
|
||||
if (iImpact > MIN_DAMAGE_FOR_INSTANT_KILL && iImpact < pTarget->stats.bLife)
|
||||
{
|
||||
@@ -8741,7 +8882,7 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
if( !IsAutoResolveActive() )
|
||||
{
|
||||
|
||||
if ( AmmoTypes[ubAmmoType].knife && pFirer->aiData.bOppList[ pTarget->ubID ] == SEEN_CURRENTLY )
|
||||
if ( AmmoTypes[ubAmmoType].knife && pFirer->aiData.bOppList[ pTarget->ubID ] == SEEN_CURRENTLY && !fFragment )
|
||||
{
|
||||
// is this a stealth attack?
|
||||
if ( pTarget->aiData.bOppList[ pFirer->ubID ] == NOT_HEARD_OR_SEEN && !CREATURE_OR_BLOODCAT( pTarget )
|
||||
@@ -8793,10 +8934,18 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
|
||||
if (iImpactForCrits > 0 && iImpactForCrits < pTarget->stats.bLife && !(pTarget->flags.uiStatusFlags & SOLDIER_MONSTER) ) // not to monsters - SANDRO
|
||||
{
|
||||
UINT32 uiCritChance = (iImpactForCrits / 2) + (pFirer->aiData.bAimTime * 5);
|
||||
UINT32 uiCritChance = 0;
|
||||
if (fFragment)
|
||||
{
|
||||
uiCritChance = (iImpactForCrits / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
uiCritChance = (iImpactForCrits / 2) + (pFirer->aiData.bAimTime * 5);
|
||||
}
|
||||
BOOLEAN fMaliciousHit = FALSE;
|
||||
// SANDRO - Malicious characters inflict stat loss more often
|
||||
if ( gGameOptions.fNewTraitSystem && pFirer->ubProfile != NO_PROFILE )
|
||||
if ( gGameOptions.fNewTraitSystem && pFirer->ubProfile != NO_PROFILE && !fFragment)
|
||||
{
|
||||
if ( gMercProfiles[ pFirer->ubProfile ].bCharacterTrait == CHAR_TRAIT_MALICIOUS )
|
||||
{
|
||||
|
||||
+6
-1
@@ -358,6 +358,11 @@ typedef struct
|
||||
UINT16 ubDuration;
|
||||
UINT16 ubStartRadius;
|
||||
UINT8 ubMagSize;
|
||||
BOOLEAN fExplodeOnImpact; // HEADROCK HAM 5: Flag for impact explosives.
|
||||
UINT16 usNumFragments; // HEADROCK HAM 5.1: Fragmenting Explosive Data
|
||||
UINT8 ubFragType;
|
||||
UINT16 ubFragDamage;
|
||||
UINT16 ubFragRange;
|
||||
} EXPLOSIVETYPE;
|
||||
|
||||
//GLOBALS
|
||||
@@ -381,7 +386,7 @@ extern BOOLEAN FireWeapon( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo );
|
||||
extern void WeaponHit( UINT16 usSoldierID, UINT16 usWeaponIndex, INT16 sDamage, INT16 sBreathLoss, UINT16 usDirection, INT16 sXPos, INT16 sYPos, INT16 sZPos, INT16 sRange , UINT8 ubAttackerID, BOOLEAN fHit, UINT8 ubSpecial, UINT8 ubHitLocation );
|
||||
extern void StructureHit( INT32 iBullet, UINT16 usWeaponIndex, INT16 bWeaponStatus, UINT8 ubAttackerID, UINT16 sXPos, INT16 sYPos, INT16 sZPos, UINT16 usStructureID, INT32 iImpact, BOOLEAN fStopped );
|
||||
extern void WindowHit( INT32 sGridNo, UINT16 usStructureID, BOOLEAN fBlowWindowSouth, BOOLEAN fLargeForce );
|
||||
extern INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocation, INT32 iImpact, INT16 sHitBy, UINT8 * pubSpecial );
|
||||
// HEADROCK HAM 5.1: Moved to Bullets.h
|
||||
extern BOOLEAN InRange( SOLDIERTYPE *pSoldier, INT32 sGridNo );
|
||||
extern void ShotMiss( UINT8 ubAttackerID, INT32 iBullet );
|
||||
extern UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 ubAimTime, UINT8 ubAimPos );
|
||||
|
||||
@@ -60,6 +60,8 @@ typedef PARSE_STAGE;
|
||||
#define COMPATIBLEFACEITEMSFILENAME "CompatibleFaceItems.xml"
|
||||
#define MERGESFILENAME "Merges.xml"
|
||||
#define ATTACHMENTCOMBOMERGESFILENAME "AttachmentComboMerges.xml"
|
||||
// HEADROCK HAM 5: Item Transformations Filename
|
||||
#define ITEMTRANSFORMATIONSFILENAME "Item_Transformations.xml"
|
||||
#define MAGAZINESFILENAME "Magazines.xml"
|
||||
#define ARMOURSFILENAME "Armours.xml"
|
||||
#define EXPLOSIVESFILENAME "Explosives.xml"
|
||||
@@ -74,6 +76,9 @@ typedef PARSE_STAGE;
|
||||
// CHRISL:
|
||||
#define LOADBEARINGEQUIPMENTFILENAME "LoadBearingEquipment.xml"
|
||||
#define LBEPOCKETFILENAME "Pockets.xml"
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
#define LBEPOCKETPOPUPFILENAME "PocketPopups.xml"
|
||||
|
||||
#define MERCSTARTINGGEARFILENAME "MercStartingGear.xml"
|
||||
|
||||
#ifdef JA2UB
|
||||
@@ -161,6 +166,8 @@ typedef PARSE_STAGE;
|
||||
#define FACILITYTYPESFILENAME "Map\\FacilityTypes.xml"
|
||||
// HEADROCK HAM 3.6: Sector Names [2009-07-27]
|
||||
#define SECTORNAMESFILENAME "Map\\SectorNames.xml"
|
||||
// HEADROCK HAM 5: Coolness by Sector [2011-11-19]
|
||||
#define COOLNESSBYSECTORFILENAME "Map\\CoolnessBySector.xml"
|
||||
// HEADROCK PROFEX: Merc Profiles [2009-07-27]
|
||||
#define MERCPROFILESFILENAME "MercProfiles.xml"
|
||||
// HEADROCK PROFEX: Merc Opinions [2009-07-27]
|
||||
@@ -267,6 +274,9 @@ extern BOOLEAN WriteMergeStats();
|
||||
extern BOOLEAN ReadInAttachmentComboMergeStats(STR fileName);
|
||||
extern BOOLEAN WriteAttachmentComboMergeStats();
|
||||
|
||||
// HEADROCK HAM 5: Item Transformation XML reader
|
||||
extern BOOLEAN ReadInTransformationStats(STR fileName);
|
||||
|
||||
extern BOOLEAN ReadInArmourStats(STR fileName);
|
||||
extern BOOLEAN WriteArmourStats();
|
||||
|
||||
@@ -277,6 +287,9 @@ extern BOOLEAN WritelbeEquipmentStats();
|
||||
extern BOOLEAN ReadInLBEPocketStats(STR fileName, BOOLEAN localizedVersion);
|
||||
extern BOOLEAN WriteLBEPocketEquipmentStats();
|
||||
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
extern BOOLEAN ReadInLBEPocketPopups(STR fileName);
|
||||
|
||||
extern BOOLEAN ReadInMercStartingGearStats(STR fileName);
|
||||
extern BOOLEAN WriteMercStartingGearStats();
|
||||
|
||||
@@ -391,6 +404,9 @@ extern BOOLEAN ReadInFacilityTypes(STR fileName, BOOLEAN localizedVersion);
|
||||
// HEADROCK HAM 3.6: Customized Sector Names
|
||||
extern BOOLEAN ReadInSectorNames(STR fileName, BOOLEAN localizedVersion, INT8 Level );
|
||||
|
||||
// HEADROCK HAM 5: Coolness by Sectors
|
||||
extern BOOLEAN ReadInCoolnessBySector(STR fileName );
|
||||
|
||||
// HEADROCK PROFEX: Merc Profiles
|
||||
extern BOOLEAN ReadInMercProfiles(STR fileName, BOOLEAN localizedVersion);
|
||||
|
||||
|
||||
@@ -57,7 +57,12 @@ explosiveStartElementHandle(void *userData, const XML_Char *name, const XML_Char
|
||||
strcmp(name, "ubStartRadius") == 0 ||
|
||||
strcmp(name, "ubMagSize") == 0 ||
|
||||
strcmp(name, "ubDuration") == 0 ||
|
||||
strcmp(name, "ubAnimationID") == 0 ))
|
||||
strcmp(name, "ubAnimationID") == 0 ||
|
||||
strcmp(name, "fExplodeOnImpact") == 0 ||// HEADROCK HAM 5: Explode on impact flag
|
||||
strcmp(name, "usNumFragments") == 0 || // HEADROCK HAM 5.1: Fragmenting explosive data
|
||||
strcmp(name, "ubFragType") == 0 ||
|
||||
strcmp(name, "ubFragDamage") == 0 ||
|
||||
strcmp(name, "ubFragRange") == 0 ))
|
||||
{
|
||||
pData->curElement = ELEMENT_PROPERTY;
|
||||
|
||||
@@ -159,6 +164,37 @@ explosiveEndElementHandle(void *userData, const XML_Char *name)
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curExplosive.ubDuration = (UINT8) atol(pData->szCharData);
|
||||
}
|
||||
// HEADROCK HAM 5: Flag for "Explosion on Impact"
|
||||
else if(strcmp(name, "fExplodeOnImpact") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curExplosive.fExplodeOnImpact = (BOOLEAN) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
// HEADROCK HAM 5.1: Four tags for Fragmenting Explosives
|
||||
else if(strcmp(name, "usNumFragments") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curExplosive.usNumFragments = (UINT16) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "ubFragType") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curExplosive.ubFragType = (UINT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "ubFragDamage") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curExplosive.ubFragDamage = (UINT16) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "ubFragRange") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curExplosive.ubFragRange = (UINT16) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
@@ -262,6 +298,7 @@ BOOLEAN WriteExplosiveStats()
|
||||
FilePrintf(hFile,"\t\t<ubDuration>%d</ubDuration>\r\n", Explosive[cnt].ubDuration );
|
||||
FilePrintf(hFile,"\t\t<ubStartRadius>%d</ubStartRadius>\r\n", Explosive[cnt].ubStartRadius );
|
||||
FilePrintf(hFile,"\t\t<ubMagSize>%d</ubMagSize>\r\n", Explosive[cnt].ubMagSize );
|
||||
FilePrintf(hFile,"\t\t<fExplodeOnImpact>%d</fExplodeOnImpact>\r\n", (UINT8)Explosive[cnt].fExplodeOnImpact );
|
||||
|
||||
FilePrintf(hFile,"\t</EXPLOSIVE>\r\n");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Tactical All.h"
|
||||
#else
|
||||
#include "sgp.h"
|
||||
#include "overhead.h"
|
||||
#include "weapons.h"
|
||||
#include "Debug Control.h"
|
||||
#include "expat.h"
|
||||
#include "gamesettings.h"
|
||||
#include "XML.h"
|
||||
#include "Item Types.h"
|
||||
#endif
|
||||
|
||||
struct
|
||||
{
|
||||
PARSE_STAGE curElement;
|
||||
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
|
||||
TransformInfoStruct curTransform;
|
||||
UINT32 maxArraySize;
|
||||
UINT32 curIndex;
|
||||
UINT32 curResultIndex;
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
}
|
||||
typedef transformParseData;
|
||||
|
||||
static void XMLCALL
|
||||
transformStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
transformParseData * pData = (transformParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
if(strcmp(name, "TRANSFORMATIONS_LIST") == 0 && pData->curElement == ELEMENT_NONE)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
// Reset all transformation indexes to -1, indicating they are "Not Taken"
|
||||
for (UINT16 x = 0; x < MAXITEMS; x++)
|
||||
{
|
||||
Transform[x].usItem = -1;
|
||||
}
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(strcmp(name, "TRANSFORM") == 0 && pData->curElement == ELEMENT_LIST)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
// Reset values
|
||||
pData->curTransform.usItem = -1;
|
||||
for (UINT8 x = 0; x < MAX_NUM_TRANSFORMATION_RESULTS; x++)
|
||||
{
|
||||
pData->curTransform.usResult[x] = 0;
|
||||
}
|
||||
pData->curTransform.usAPCost = 0;
|
||||
swprintf(pData->curTransform.szMenuRowText, L"");
|
||||
swprintf(pData->curTransform.szTooltipText, L"");
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
pData->curIndex++;
|
||||
pData->curResultIndex = 0;
|
||||
}
|
||||
else if(pData->curElement == ELEMENT &&
|
||||
(strcmp(name, "usItem") == 0 ||
|
||||
strcmp(name, "usResult") == 0 ||
|
||||
strcmp(name, "usAPCost") == 0 ||
|
||||
strcmp(name, "iBPCost") == 0 ||
|
||||
strcmp(name, "szMenuRowText") == 0 ||
|
||||
strcmp(name, "szTooltipText") == 0))
|
||||
{
|
||||
pData->curElement = ELEMENT_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
transformCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
transformParseData * pData = (transformParseData *)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
|
||||
transformEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
transformParseData * pData = (transformParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
||||
{
|
||||
if(strcmp(name, "TRANSFORMATIONS_LIST") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_NONE;
|
||||
}
|
||||
else if(strcmp(name, "TRANSFORM") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
if(pData->curIndex < pData->maxArraySize)
|
||||
{
|
||||
//DebugMsg(TOPIC_JA2, DBG_LEVEL_3,"MergeStartElementHandle: writing merge to array");
|
||||
Transform[pData->curIndex].usItem = pData->curTransform.usItem; //write the merge into the table
|
||||
for (INT32 x = 0; x < MAX_NUM_TRANSFORMATION_RESULTS; x++)
|
||||
{
|
||||
Transform[pData->curIndex].usResult[x] = pData->curTransform.usResult[x];
|
||||
}
|
||||
Transform[pData->curIndex].usAPCost = pData->curTransform.usAPCost;
|
||||
Transform[pData->curIndex].iBPCost = pData->curTransform.iBPCost;
|
||||
wcscpy( Transform[pData->curIndex].szMenuRowText, pData->curTransform.szMenuRowText );
|
||||
wcscpy( Transform[pData->curIndex].szTooltipText, pData->curTransform.szTooltipText );
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, "usItem") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
INT16 usItem = (INT16) atol(pData->szCharData);
|
||||
if (usItem <= 0)
|
||||
{
|
||||
AssertMsg( 0, String( "Item_Transformations.XML error: Entry #%d missing proper <usItem> tag!", pData->curIndex ) );
|
||||
}
|
||||
pData->curTransform.usItem = usItem;
|
||||
}
|
||||
else if(strcmp(name, "usResult") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curTransform.usResult[pData->curResultIndex] = (UINT16) atol(pData->szCharData);
|
||||
pData->curResultIndex++;
|
||||
}
|
||||
else if(strcmp(name, "usAPCost") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curTransform.usAPCost = (UINT16) atol(pData->szCharData);
|
||||
pData->curTransform.usAPCost = (UINT16)DynamicAdjustAPConstants(pData->curTransform.usAPCost, pData->curTransform.usAPCost);
|
||||
}
|
||||
else if(strcmp(name, "iBPCost") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curTransform.iBPCost = (INT32) atol(pData->szCharData);
|
||||
}
|
||||
else if(strcmp(name, "szMenuRowText") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curTransform.szMenuRowText, sizeof(pData->curTransform.szMenuRowText)/sizeof(pData->curTransform.szMenuRowText[0]) );
|
||||
pData->curTransform.szMenuRowText[sizeof(pData->curTransform.szMenuRowText)/sizeof(pData->curTransform.szMenuRowText[0]) - 1] = '\0';
|
||||
}
|
||||
else if(strcmp(name, "szTooltipText") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curTransform.szTooltipText, sizeof(pData->curTransform.szTooltipText)/sizeof(pData->curTransform.szTooltipText[0]) );
|
||||
pData->curTransform.szTooltipText[sizeof(pData->curTransform.szTooltipText)/sizeof(pData->curTransform.szTooltipText[0]) - 1] = '\0';
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
BOOLEAN ReadInTransformationStats(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
transformParseData pData;
|
||||
|
||||
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading Item_Transformations.xml" );
|
||||
|
||||
// Open merges 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, transformStartElementHandle, transformEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, transformCharacterDataHandle);
|
||||
|
||||
|
||||
memset(&pData,0,sizeof(pData));
|
||||
pData.maxArraySize = MAXITEMS;
|
||||
pData.curIndex = -1;
|
||||
|
||||
XML_SetUserData(parser, &pData);
|
||||
|
||||
|
||||
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
|
||||
{
|
||||
CHAR8 errorBuf[511];
|
||||
|
||||
sprintf(errorBuf, "XML Parser Error in Item_Transformations.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 );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,496 @@
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Tactical All.h"
|
||||
#else
|
||||
#include "sgp.h"
|
||||
#include "popup_class.h"
|
||||
#include "popup_definition.h"
|
||||
#include "Debug Control.h"
|
||||
#include "expat.h"
|
||||
#include "XML.h"
|
||||
#include "GameSettings.h"
|
||||
#endif
|
||||
|
||||
// namespace'd because of name collision with POPUP class def
|
||||
namespace POPUP_PARSE {
|
||||
enum
|
||||
{
|
||||
OUTSIDE_POCKET_LIST = 0,
|
||||
POCKET_LIST,
|
||||
|
||||
POCKET,
|
||||
POCKET_PROPERTY, // for reading pocket id
|
||||
|
||||
POPUP,
|
||||
POPUP_PROPERTY, // unused
|
||||
// for root-level popup
|
||||
OPTION,
|
||||
OPTION_PROPERTY,
|
||||
GENERATOR,
|
||||
GENERATOR_PROPERTY,
|
||||
|
||||
SUBMENU,
|
||||
SUBMENU_PROPERTY,
|
||||
// for submenus
|
||||
SUBMENU_OPTION,
|
||||
SUBMENU_OPTION_PROPERTY,
|
||||
SUBMENU_GENERATOR,
|
||||
SUBMENU_GENERATOR_PROPERTY
|
||||
}
|
||||
typedef POPUP_PARSE_STAGE;
|
||||
}
|
||||
|
||||
|
||||
struct
|
||||
{
|
||||
POPUP_PARSE::POPUP_PARSE_STAGE curElement;
|
||||
UINT8 curSubPopupLevel;
|
||||
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
|
||||
// popupDef and its pocket number
|
||||
UINT8 curPocketId;
|
||||
popupDef *curPocketPopup;
|
||||
|
||||
// for reading in options to popups and subPopups
|
||||
//popupDefOption *curPocketPopupOption; // not really used
|
||||
WCHAR curPocketPopupOptionName[128];
|
||||
UINT16 curPocketPopupOptionCallback;
|
||||
UINT16 curPocketPopupOptionAvail;
|
||||
|
||||
// for reading in subPopups
|
||||
popupDefSubPopupOption *curPocketSubPopupOption[POPUP_MAX_SUB_POPUPS];
|
||||
WCHAR curPocketSubPopupOptionName[POPUP_MAX_SUB_POPUPS][128];
|
||||
|
||||
// for reading in content generator references
|
||||
popupDefContentGenerator *curPocketPopupGenerator; // not really used
|
||||
UINT16 curPocketPopupGeneratorId;
|
||||
|
||||
popupDef * curArray;
|
||||
|
||||
UINT32 maxArraySize;
|
||||
UINT32 curIndex;
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
}
|
||||
typedef pocketPopupParseData;
|
||||
|
||||
// maps generator name strings found in XML to generator IDs used by the function that binds them
|
||||
static UINT16 mapGeneratorNameToId( CHAR8 * name ){
|
||||
|
||||
if( strcmp(name,"dummy") == 0 ){
|
||||
return popupGenerators::dummy;
|
||||
} else if( strcmp(name,"addArmor") == 0 ){
|
||||
return popupGenerators::addArmor;
|
||||
} else if( strcmp(name,"addLBE") == 0 ){
|
||||
return popupGenerators::addLBE;
|
||||
} else if( strcmp(name,"addWeapons") == 0 ){
|
||||
return popupGenerators::addWeapons;
|
||||
} else if( strcmp(name,"addWeaponGroups") == 0 ){
|
||||
return popupGenerators::addWeaponGroups;
|
||||
} else if( strcmp(name,"addGrenades") == 0 ){
|
||||
return popupGenerators::addGrenades;
|
||||
} else if( strcmp(name,"addBombs") == 0 ){
|
||||
return popupGenerators::addBombs;
|
||||
} else if( strcmp(name,"addFaceGear") == 0 ){
|
||||
return popupGenerators::addFaceGear;
|
||||
} else if( strcmp(name,"addAmmo") == 0 ){
|
||||
return popupGenerators::addAmmo;
|
||||
} else if( strcmp(name,"addRifleGrenades") == 0 ){
|
||||
return popupGenerators::addRifleGrenades;
|
||||
} else if( strcmp(name,"addRocketAmmo") == 0 ){
|
||||
return popupGenerators::addRocketAmmo;
|
||||
} else if( strcmp(name,"addMisc") == 0 ){
|
||||
return popupGenerators::addMisc;
|
||||
} else if( strcmp(name,"addKits") == 0 ){
|
||||
return popupGenerators::addKits;
|
||||
} else return 0; // includes 'none'
|
||||
|
||||
}
|
||||
|
||||
// maps option callback name strings found in XML to callback IDs used by the function that binds them
|
||||
static UINT16 mapCallbackNameToId( CHAR8 * name ){
|
||||
|
||||
if( strcmp(name,"dummy") == 0 ){
|
||||
return 1;
|
||||
} else return 0; // includes 'none'
|
||||
|
||||
}
|
||||
|
||||
// maps option availability check function name strings found in XML to their IDs used by the function that binds them
|
||||
static UINT16 mapAvailNameToId( CHAR8 * name ){
|
||||
|
||||
if( strcmp(name,"dummy") == 0 ){
|
||||
return 1;
|
||||
} else return 0; // includes 'none'
|
||||
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
pocketPopupStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
pocketPopupParseData * pData = (pocketPopupParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
if(strcmp(name, "POCKETPOPUPS") == 0 && pData->curElement == ELEMENT_NONE)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POCKET_LIST;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(strcmp(name, "POCKET") == 0 && pData->curElement == ELEMENT_LIST)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POCKET;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
// TODO: assert if there's no dangling subpopup here, broken XML might cause trouble
|
||||
pData->curSubPopupLevel = 0; // we're in a new pocket now, so reset the subpopup level
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::POCKET &&
|
||||
(strcmp(name, "pIndex") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POCKET_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::POCKET &&
|
||||
(strcmp(name, "popup") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POPUP;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
pData->curPocketPopup = new popupDef();
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::POPUP && // popup options (not in submenu)
|
||||
(strcmp(name, "option") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::OPTION;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::OPTION && // popup option attributes (not in submenu)
|
||||
( strcmp(name, "name") == 0
|
||||
|| strcmp(name, "action") == 0
|
||||
|| strcmp(name, "availCheck") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::OPTION_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::POPUP && // content generators (not in submenu)
|
||||
(strcmp(name, "generator") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::GENERATOR;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::GENERATOR && // content generator attributes (not in submenu)
|
||||
( strcmp(name, "id") == 0 ) )
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::GENERATOR_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::POPUP && // submenu (first)
|
||||
(strcmp(name, "subMenu") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU;
|
||||
|
||||
// TODO: assert that this is the first submenu
|
||||
pData->curSubPopupLevel = 1; // we're still at popup level so this must be the first subpopup
|
||||
pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ] = new popupDefSubPopupOption();
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::SUBMENU && // submenu (deep)
|
||||
(strcmp(name, "subMenu") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU;
|
||||
|
||||
pData->curSubPopupLevel++;
|
||||
pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ] = new popupDefSubPopupOption();
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::SUBMENU && // submenu attributes
|
||||
( strcmp(name, "name") == 0 ) )
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::SUBMENU && // popup options (submenu)
|
||||
(strcmp(name, "option") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_OPTION;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::SUBMENU_OPTION && // popup option attributes (submenu)
|
||||
( strcmp(name, "name") == 0
|
||||
|| strcmp(name, "action") == 0
|
||||
|| strcmp(name, "availCheck") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_OPTION_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::SUBMENU && // content generators (submenu)
|
||||
(strcmp(name, "generator") == 0 ))
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_GENERATOR;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == POPUP_PARSE::SUBMENU_GENERATOR && // content generator attributes (submenu)
|
||||
( strcmp(name, "id") == 0 ) )
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_GENERATOR_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
pocketPopupCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
pocketPopupParseData * pData = (pocketPopupParseData *)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
|
||||
pocketPopupEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
pocketPopupParseData * pData = (pocketPopupParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth)
|
||||
{
|
||||
if(strcmp(name, "POCKETPOPUPS") == 0)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::OUTSIDE_POCKET_LIST;
|
||||
}
|
||||
else if(strcmp(name, "POCKET") == 0)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POCKET_LIST;
|
||||
|
||||
// done with the pocket
|
||||
// nothing to do because we already saved the popup when closing <popup> tag
|
||||
|
||||
}
|
||||
else if(strcmp(name, "pIndex") == 0)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POCKET;
|
||||
pData->curPocketId = (UINT8) atol(pData->szCharData); // got pocket index
|
||||
}
|
||||
else if(strcmp(name, "popup") == 0)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POCKET;
|
||||
// done with the popup definition
|
||||
LBEPocketPopup[ pData->curPocketId ] = *pData->curPocketPopup; // place the popup definition in pocket popup index
|
||||
}
|
||||
else if(strcmp(name, "subMenu") == 0)
|
||||
{
|
||||
|
||||
// done with the subpopup definition
|
||||
|
||||
// rename the current option, we should've collected a name for it by now
|
||||
pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ]->rename( new std::wstring( pData->curPocketSubPopupOptionName[ pData->curSubPopupLevel-1 ] ) );
|
||||
|
||||
if( pData->curSubPopupLevel == 1 ){ // at first submenu level, add the current menu to the base popup
|
||||
pData->curElement = POPUP_PARSE::POPUP;
|
||||
|
||||
pData->curPocketPopup->addSubPopup( pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ] );
|
||||
pData->curSubPopupLevel = 0;
|
||||
} else { // deep in submenu tree, add the current submenu to the one above
|
||||
pData->curElement = POPUP_PARSE::SUBMENU;
|
||||
|
||||
pData->curPocketSubPopupOption[ pData->curSubPopupLevel - 2 ]->getSubDef()->addSubPopup( pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ] );
|
||||
pData->curSubPopupLevel--;
|
||||
}
|
||||
|
||||
}
|
||||
else if( pData->curElement == POPUP_PARSE::OPTION && strcmp(name, "option") == 0) // option (popup)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POPUP;
|
||||
// done with the option
|
||||
pData->curPocketPopup->addOption( new std::wstring( pData->curPocketPopupOptionName ), pData->curPocketPopupOptionCallback, pData->curPocketPopupOptionAvail );
|
||||
}
|
||||
else if( pData->curElement == POPUP_PARSE::SUBMENU_OPTION && strcmp(name, "option") == 0) // option (sub-popup)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU;
|
||||
// done with the option
|
||||
pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ]->getSubDef()->addOption( new std::wstring( pData->curPocketPopupOptionName ), pData->curPocketPopupOptionCallback, pData->curPocketPopupOptionAvail );
|
||||
}
|
||||
else if( pData->curElement == POPUP_PARSE::GENERATOR && strcmp(name, "generator") == 0) // generator (popup)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::POPUP;
|
||||
// done with the generator
|
||||
pData->curPocketPopup->addGenerator( pData->curPocketPopupGeneratorId );
|
||||
}
|
||||
else if( pData->curElement == POPUP_PARSE::SUBMENU_GENERATOR && strcmp(name, "generator") == 0) // generator (sub-popup)
|
||||
{
|
||||
pData->curElement = POPUP_PARSE::SUBMENU;
|
||||
// done with the generator
|
||||
pData->curPocketSubPopupOption[ pData->curSubPopupLevel-1 ]->getSubDef()->addGenerator( pData->curPocketPopupGeneratorId );
|
||||
}
|
||||
else if(strcmp(name, "name") == 0)
|
||||
{
|
||||
switch( pData->curElement ){
|
||||
case POPUP_PARSE::OPTION_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::OPTION;
|
||||
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curPocketPopupOptionName, sizeof(pData->curPocketPopupOptionName)/sizeof(pData->curPocketPopupOptionName[0]) );
|
||||
pData->curPocketPopupOptionName[sizeof(pData->curPocketPopupOptionName)/sizeof(pData->curPocketPopupOptionName[0]) - 1] = '\0';
|
||||
|
||||
break;
|
||||
|
||||
case POPUP_PARSE::SUBMENU_OPTION_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_OPTION;
|
||||
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curPocketPopupOptionName, sizeof(pData->curPocketPopupOptionName)/sizeof(pData->curPocketPopupOptionName[0]) );
|
||||
pData->curPocketPopupOptionName[sizeof(pData->curPocketPopupOptionName)/sizeof(pData->curPocketPopupOptionName[0]) - 1] = '\0';
|
||||
|
||||
break;
|
||||
|
||||
case POPUP_PARSE::SUBMENU_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::SUBMENU;
|
||||
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->curPocketSubPopupOptionName[pData->curSubPopupLevel-1], sizeof(pData->curPocketSubPopupOptionName[pData->curSubPopupLevel-1])/sizeof(pData->curPocketSubPopupOptionName[pData->curSubPopupLevel-1][0]) );
|
||||
pData->curPocketSubPopupOptionName[pData->curSubPopupLevel-1][sizeof(pData->curPocketSubPopupOptionName[pData->curSubPopupLevel-1])/sizeof(pData->curPocketSubPopupOptionName[pData->curSubPopupLevel-1][0]) - 1] = '\0';
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, "action") == 0)
|
||||
{
|
||||
switch( pData->curElement ){
|
||||
case POPUP_PARSE::OPTION_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::OPTION;
|
||||
break;
|
||||
|
||||
case POPUP_PARSE::SUBMENU_OPTION_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_OPTION;
|
||||
break;
|
||||
}
|
||||
|
||||
pData->curPocketPopupOptionCallback = mapCallbackNameToId(pData->szCharData);
|
||||
}
|
||||
else if(strcmp(name, "availCheck") == 0)
|
||||
{
|
||||
switch( pData->curElement ){
|
||||
case POPUP_PARSE::OPTION_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::OPTION;
|
||||
break;
|
||||
|
||||
case POPUP_PARSE::SUBMENU_OPTION_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_OPTION;
|
||||
break;
|
||||
}
|
||||
|
||||
pData->curPocketPopupOptionAvail = mapAvailNameToId(pData->szCharData);
|
||||
}
|
||||
else if(strcmp(name, "id") == 0)
|
||||
{
|
||||
switch( pData->curElement ){
|
||||
case POPUP_PARSE::GENERATOR_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::GENERATOR;
|
||||
break;
|
||||
|
||||
case POPUP_PARSE::SUBMENU_GENERATOR_PROPERTY:
|
||||
pData->curElement = POPUP_PARSE::SUBMENU_GENERATOR;
|
||||
break;
|
||||
}
|
||||
|
||||
pData->curPocketPopupGeneratorId = mapGeneratorNameToId(pData->szCharData);
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN ReadInLBEPocketPopups(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
pocketPopupParseData pData;
|
||||
|
||||
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading pocketPopups.xml" );
|
||||
|
||||
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, pocketPopupStartElementHandle, pocketPopupEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, pocketPopupCharacterDataHandle);
|
||||
|
||||
|
||||
memset(&pData,0,sizeof(pData));
|
||||
XML_SetUserData(parser, &pData);
|
||||
|
||||
XML_SetUserData(parser, &pData);
|
||||
|
||||
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
|
||||
{
|
||||
CHAR8 errorBuf[511];
|
||||
|
||||
sprintf(errorBuf, "XML Parser Error in Pocket.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
|
||||
LiveMessage(errorBuf);
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
// dummy popup
|
||||
|
||||
popupDef* popup = new popupDef();
|
||||
popup->addOption(new std::wstring(L"Option one"),NULL,NULL);
|
||||
popup->addOption(new std::wstring(L"Option two"),NULL,NULL);
|
||||
popup->addOption(new std::wstring(L"Option three"),NULL,NULL);
|
||||
|
||||
LBEPocketPopup[5] = *popup;
|
||||
*/
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
|
||||
|
||||
XML_ParserFree(parser);
|
||||
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
+17
-5
@@ -31,7 +31,8 @@
|
||||
#endif
|
||||
|
||||
// Defines
|
||||
#define NUM_BULLET_SLOTS 50
|
||||
// HEADROCK HAM 5: Increasing... with the hope of making spectacular fragmenting explosives.
|
||||
#define NUM_BULLET_SLOTS 200
|
||||
|
||||
|
||||
// GLOBAL FOR FACES LISTING
|
||||
@@ -105,7 +106,11 @@ INT32 CreateBullet( UINT8 ubFirerID, BOOLEAN fFake, UINT16 usFlags,UINT16 fromIt
|
||||
{
|
||||
pBullet->fReal = TRUE;
|
||||
// gBullets[ iBullet ].pFirer->bBulletsLeft++;
|
||||
gTacticalStatus.ubAttackBusyCount++;
|
||||
// HEADROCK HAM 5: Do not create for explosives.
|
||||
if (!(Item[fromItem].usItemClass & IC_EXPLOSV))
|
||||
{
|
||||
gTacticalStatus.ubAttackBusyCount++;
|
||||
}
|
||||
DebugAttackBusy( String( "Creating a new bullet for %d. ABC now %d\n", ubFirerID, gTacticalStatus.ubAttackBusyCount) );
|
||||
}
|
||||
|
||||
@@ -201,7 +206,11 @@ void RemoveBullet( INT32 iBullet )
|
||||
// DebugAttackBusy( String( "Deleting a bullet for %d. Total count now %d\n", gBullets[ iBullet].ubFirerID, gBullets[ iBullet ].pFirer->bBulletsLeft) );
|
||||
// Nah, just decrement the attack busy count and be done with it
|
||||
DebugAttackBusy( String( "Deleting a bullet for %d.\n", gBullets[ iBullet].ubFirerID ) );
|
||||
ReduceAttackBusyCount( );
|
||||
// HEADROCK HAM 5: Fragments do not need reducing.
|
||||
if (gBullets[iBullet].fFragment == false)
|
||||
{
|
||||
ReduceAttackBusyCount( );
|
||||
}
|
||||
|
||||
// if ( gBullets[ iBullet ].usFlags & ( BULLET_FLAG_KNIFE ) )
|
||||
// {
|
||||
@@ -233,7 +242,8 @@ void RemoveBullet( INT32 iBullet )
|
||||
|
||||
void LocateBullet( INT32 iBulletIndex )
|
||||
{
|
||||
if ( gGameSettings.fOptions[ TOPTION_SHOW_MISSES ] )
|
||||
// HEADROCK HAM 5: Do not track fragments. There are too many of them.
|
||||
if ( gGameSettings.fOptions[ TOPTION_SHOW_MISSES ] && gBullets[ iBulletIndex ].fFragment == false)
|
||||
{
|
||||
// Check if a bad guy fired!
|
||||
if ( gBullets[ iBulletIndex ].ubFirerID != NOBODY )
|
||||
@@ -353,6 +363,7 @@ void UpdateBullets( )
|
||||
ManLooksForOtherTeams(gBullets[ uiCount ].pFirer);
|
||||
}
|
||||
*/
|
||||
|
||||
else
|
||||
{
|
||||
pNode = AddStructToTail( gBullets[ uiCount ].sGridNo, BULLETTILE1 );
|
||||
@@ -364,7 +375,8 @@ void UpdateBullets( )
|
||||
pNode->sRelativeZ = (INT16) CONVERT_HEIGHTUNITS_TO_PIXELS( FIXEDPT_TO_INT32( gBullets[ uiCount ].qCurrZ ) );
|
||||
|
||||
//afp-start - add new tail /tracer
|
||||
if (gGameSettings.fOptions[TOPTION_ALTERNATE_BULLET_GRAPHICS])
|
||||
// HEADROCK HAM 5: No tail for fragments.
|
||||
if (gGameSettings.fOptions[TOPTION_ALTERNATE_BULLET_GRAPHICS] && gBullets[ uiCount ].fFragment == false)
|
||||
{
|
||||
if ((lastX != 0) || (lastY != 0))
|
||||
{
|
||||
|
||||
@@ -2095,6 +2095,8 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
|
||||
// WANNE.TANK: Choose cannon or rocket
|
||||
UINT16 usHandItem = pSoldier->inv[HANDPOS].usItem;
|
||||
|
||||
INT8 bSlot;
|
||||
|
||||
if (TANK(pSoldier))
|
||||
{
|
||||
// No cannon selected to fire
|
||||
@@ -2790,6 +2792,16 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier)
|
||||
break;
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
case AI_ACTION_RELOAD_GUN:
|
||||
bSlot = FindAmmoToReload( pSoldier, pSoldier->aiData.usActionData, NO_SLOT );
|
||||
if(bSlot != NO_SLOT)
|
||||
{
|
||||
ReloadGun( pSoldier, &(pSoldier->inv[pSoldier->aiData.usActionData]), &(pSoldier->inv[bSlot]) );
|
||||
ActionDone( pSoldier );
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
#ifdef BETAVERSION
|
||||
NumMessage("ExecuteAction - Illegal action type = ",pSoldier->aiData.bAction);
|
||||
|
||||
+107
-41
@@ -1726,31 +1726,20 @@ BOOLEAN InWaterGasOrSmoke( SOLDIERTYPE *pSoldier, INT32 sGridNo )
|
||||
// smoke
|
||||
if (gpWorldLevelData[sGridNo].ubExtFlags[ pSoldier->pathing.bLevel ] & MAPELEMENT_EXT_SMOKE)
|
||||
{
|
||||
return( TRUE );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// tear/mustard gas
|
||||
if((gpWorldLevelData[sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & (MAPELEMENT_EXT_TEARGAS|MAPELEMENT_EXT_MUSTARDGAS)) && !DoesSoldierWearGasMask(pSoldier))//dnl ch40 200909
|
||||
return(TRUE);
|
||||
if ( gpWorldLevelData[sGridNo].ubExtFlags[ pSoldier->pathing.bLevel ] & MAPELEMENT_EXT_BURNABLEGAS )
|
||||
{
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
return InGas( pSoldier, sGridNo );
|
||||
}
|
||||
|
||||
BOOLEAN InGasOrSmoke( SOLDIERTYPE *pSoldier, INT32 sGridNo )
|
||||
{
|
||||
// smoke/tear/mustard gas
|
||||
if((gpWorldLevelData[sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & (MAPELEMENT_EXT_SMOKE|MAPELEMENT_EXT_TEARGAS|MAPELEMENT_EXT_MUSTARDGAS)) && !DoesSoldierWearGasMask(pSoldier))//dnl ch40 230909
|
||||
return(TRUE);
|
||||
if ( gpWorldLevelData[sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_BURNABLEGAS )
|
||||
{
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
// smoke
|
||||
if (gpWorldLevelData[sGridNo].ubExtFlags[ pSoldier->pathing.bLevel ] & MAPELEMENT_EXT_SMOKE)
|
||||
return TRUE;
|
||||
|
||||
return InGas(pSoldier,sGridNo);
|
||||
}
|
||||
|
||||
|
||||
@@ -1761,25 +1750,28 @@ INT16 InWaterOrGas(SOLDIERTYPE *pSoldier, INT32 sGridNo)
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
// tear/mustard gas
|
||||
if((gpWorldLevelData[sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & (MAPELEMENT_EXT_TEARGAS|MAPELEMENT_EXT_MUSTARDGAS)) && !DoesSoldierWearGasMask(pSoldier))//dnl ch40 200909
|
||||
return(TRUE);
|
||||
if ( gpWorldLevelData[sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_BURNABLEGAS )
|
||||
{
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
return (INT16)InGas( pSoldier, sGridNo );
|
||||
}
|
||||
|
||||
BOOLEAN InGas( SOLDIERTYPE *pSoldier, INT32 sGridNo )
|
||||
{
|
||||
// tear/mustard gas
|
||||
if((gpWorldLevelData[sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & (MAPELEMENT_EXT_TEARGAS|MAPELEMENT_EXT_MUSTARDGAS)) && !DoesSoldierWearGasMask(pSoldier))//dnl ch40 200909
|
||||
return(TRUE);
|
||||
if ( gpWorldLevelData[sGridNo].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_BURNABLEGAS )
|
||||
{
|
||||
return( TRUE );
|
||||
{//WarmSteel - One square away from gas is still considered in gas, because it could expand any moment.
|
||||
//Note: this only works for gas that expands with one tile, but hey it's better than nothing!
|
||||
int iNeighbourGridNo;
|
||||
for(int iDir = 0; iDir < NUM_WORLD_DIRECTIONS; ++iDir)
|
||||
{
|
||||
iNeighbourGridNo = sGridNo + DirectionInc(iDir);
|
||||
if(!TileIsOutOfBounds(iNeighbourGridNo))
|
||||
{
|
||||
// tear/mustard gas
|
||||
if((gpWorldLevelData[iNeighbourGridNo].ubExtFlags[pSoldier->pathing.bLevel] & (MAPELEMENT_EXT_TEARGAS|MAPELEMENT_EXT_MUSTARDGAS)) && !DoesSoldierWearGasMask(pSoldier))//dnl ch40 200909
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
if ( gpWorldLevelData[iNeighbourGridNo].ubExtFlags[pSoldier->pathing.bLevel] & MAPELEMENT_EXT_BURNABLEGAS )
|
||||
{
|
||||
return( TRUE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
@@ -2249,6 +2241,7 @@ INT32 CalcManThreatValue( SOLDIERTYPE *pEnemy, INT32 sMyGrid, UINT8 ubReduceForC
|
||||
|
||||
INT16 RoamingRange(SOLDIERTYPE *pSoldier, INT32 * pusFromGridNo)
|
||||
{
|
||||
BOOL OppPosKnown = FALSE;
|
||||
if ( CREATURE_OR_BLOODCAT( pSoldier ) )
|
||||
{
|
||||
if ( pSoldier->aiData.bAlertStatus == STATUS_BLACK )
|
||||
@@ -2269,6 +2262,19 @@ INT16 RoamingRange(SOLDIERTYPE *pSoldier, INT32 * pusFromGridNo)
|
||||
*pusFromGridNo = pSoldier->aiData.sPatrolGrid[0];
|
||||
}
|
||||
|
||||
//Do we know about any opponent?
|
||||
for(UINT16 oppID = 0; oppID < MAX_NUM_SOLDIERS; oppID++)
|
||||
{
|
||||
if ( pSoldier->aiData.bOppList[oppID] != NOT_HEARD_OR_SEEN && gbPublicOpplist[pSoldier->bTeam][oppID] != NOT_HEARD_OR_SEEN)
|
||||
{
|
||||
OppPosKnown = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Externalize if people want?
|
||||
BOOL fLessRestrictiveRoaming = TRUE;
|
||||
|
||||
switch (pSoldier->aiData.bOrders)
|
||||
{
|
||||
// JA2 GOLD: give non-NPCs a 5 tile roam range for cover in combat when being shot at
|
||||
@@ -2281,16 +2287,68 @@ INT16 RoamingRange(SOLDIERTYPE *pSoldier, INT32 * pusFromGridNo)
|
||||
return( 5 );
|
||||
}
|
||||
case ONGUARD: return( 5 );
|
||||
case CLOSEPATROL: return( 15 );
|
||||
case RNDPTPATROL:
|
||||
case POINTPATROL: return(10 ); // from nextPatrolGrid, not whereIWas
|
||||
case FARPATROL: if (pSoldier->aiData.bAlertStatus < STATUS_RED)
|
||||
case CLOSEPATROL: if (pSoldier->aiData.bAlertStatus < STATUS_RED)
|
||||
{
|
||||
return( 25 );
|
||||
return( 5 );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( 50 );
|
||||
if(!OppPosKnown || !fLessRestrictiveRoaming)
|
||||
{
|
||||
return( 15 );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( 30 );
|
||||
//return( MAX_ROAMING_RANGE );
|
||||
}
|
||||
}
|
||||
case POINTPATROL: if (pSoldier->aiData.bAlertStatus < STATUS_RED)
|
||||
{
|
||||
return( 10 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!OppPosKnown || !fLessRestrictiveRoaming)
|
||||
{
|
||||
return( 20 );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( 40 );
|
||||
//return( MAX_ROAMING_RANGE );
|
||||
}
|
||||
} // from nextPatrolGrid, not whereIWas
|
||||
case RNDPTPATROL: if (pSoldier->aiData.bAlertStatus < STATUS_RED)
|
||||
{
|
||||
return( 10 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!OppPosKnown || !fLessRestrictiveRoaming)
|
||||
{
|
||||
return( 20 );
|
||||
}
|
||||
else
|
||||
{
|
||||
//return( 40 );
|
||||
return( MAX_ROAMING_RANGE );
|
||||
}
|
||||
}// from nextPatrolGrid, not whereIWas
|
||||
case FARPATROL: if (pSoldier->aiData.bAlertStatus < STATUS_RED)
|
||||
{
|
||||
return( 15 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!OppPosKnown || !fLessRestrictiveRoaming)
|
||||
{
|
||||
return( 30 );
|
||||
}
|
||||
else
|
||||
{
|
||||
return( MAX_ROAMING_RANGE );
|
||||
}
|
||||
}
|
||||
case ONCALL: if (pSoldier->aiData.bAlertStatus < STATUS_RED)
|
||||
{
|
||||
@@ -2298,7 +2356,15 @@ INT16 RoamingRange(SOLDIERTYPE *pSoldier, INT32 * pusFromGridNo)
|
||||
}
|
||||
else
|
||||
{
|
||||
return( 30 );
|
||||
if(!OppPosKnown || !fLessRestrictiveRoaming)
|
||||
{
|
||||
return( 30 );
|
||||
}
|
||||
else
|
||||
{
|
||||
//return(50);
|
||||
return( MAX_ROAMING_RANGE );
|
||||
}
|
||||
}
|
||||
case SEEKENEMY: *pusFromGridNo = pSoldier->sGridNo; // from current position!
|
||||
return(MAX_ROAMING_RANGE);
|
||||
|
||||
@@ -349,7 +349,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
|
||||
continue; // next opponent
|
||||
|
||||
// calculate chance to REALLY hit: shoot accurately AND get past cover
|
||||
ubChanceToReallyHit = (ubBestChanceToHit * ubChanceToGetThrough) / 100;
|
||||
ubChanceToReallyHit = (UINT8)ceil((ubBestChanceToHit * ubChanceToGetThrough) / 100.0f);
|
||||
|
||||
// if we can't REALLY hit at all
|
||||
if (ubChanceToReallyHit == 0)
|
||||
|
||||
+41
-15
@@ -2100,7 +2100,7 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("DecideActionRed: soldier orders = %d",pSoldier->aiData.bOrders));
|
||||
|
||||
// if we have absolutely no action points, we can't do a thing under RED!
|
||||
if (!pSoldier->bActionPoints)
|
||||
if ( pSoldier->bActionPoints <= 0 ) //Action points can be negative
|
||||
{
|
||||
pSoldier->aiData.usActionData = NOWHERE;
|
||||
return(AI_ACTION_NONE);
|
||||
@@ -2163,7 +2163,8 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
}
|
||||
}
|
||||
|
||||
if(WearGasMaskIfAvailable(pSoldier))//dnl ch40 200909
|
||||
//Only put mask on in gas
|
||||
if(bInGas && WearGasMaskIfAvailable(pSoldier))//dnl ch40 200909
|
||||
bInGas = InGasOrSmoke(pSoldier, pSoldier->sGridNo);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -2464,22 +2465,46 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
return(AI_ACTION_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//RELOADING
|
||||
|
||||
// WarmSteel - Because of suppression fire, we need enough ammo to even consider suppressing
|
||||
// This means we need to reload. Also reload if we're just plainly low on bullets.
|
||||
if(BestShot.bWeaponIn != NO_SLOT
|
||||
&& ((pSoldier->inv[BestShot.bWeaponIn][0]->data.gun.ubGunShotsLeft < gGameExternalOptions.ubAISuppressionMinimumAmmo && GetMagSize(&pSoldier->inv[BestShot.bWeaponIn]) >= gGameExternalOptions.ubAISuppressionMinimumMagSize)
|
||||
|| pSoldier->inv[BestShot.bWeaponIn][0]->data.gun.ubGunShotsLeft < (UINT8)(GetMagSize(&pSoldier->inv[BestShot.bWeaponIn]) / 4) ))
|
||||
{
|
||||
// HEADROCK HAM 5: Fixed an issue where no ammo was found, leading to a crash when overloading the
|
||||
// inventory vector (bAmmoSlot = -1...)
|
||||
INT8 bAmmoSlot = FindAmmoToReload( pSoldier, BestShot.bWeaponIn, NO_SLOT );
|
||||
if (bAmmoSlot > -1)
|
||||
{
|
||||
OBJECTTYPE * pAmmo = &(pSoldier->inv[bAmmoSlot]);
|
||||
if((*pAmmo)[0]->data.ubShotsLeft > pSoldier->inv[BestShot.bWeaponIn][0]->data.gun.ubGunShotsLeft && GetAPsToReloadGunWithAmmo( pSoldier, &(pSoldier->inv[BestShot.bWeaponIn]), pAmmo ) <= (INT16)pSoldier->bActionPoints)
|
||||
{
|
||||
pSoldier->aiData.usActionData = BestShot.bWeaponIn;
|
||||
return AI_ACTION_RELOAD_GUN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//SUPPRESSION FIRE
|
||||
|
||||
CheckIfShotPossible(pSoldier,&BestShot,TRUE);
|
||||
CheckIfShotPossible(pSoldier,&BestShot,TRUE); //WarmSteel - No longer returns 0 when there IS actually a chance to hit.
|
||||
|
||||
//must have a small chance to hit and the opponent must be on the ground (can't suppress guys on the roof)
|
||||
// HEADROCK HAM BETA2.4: Adjusted this for a random chance to suppress regardless of chance. This augments
|
||||
// current revamp of suppression fire.
|
||||
BOOLEAN fEnableAIAutofire = FALSE;
|
||||
|
||||
// CHRISL: Changed from a simple flag to two externalized values for more modder control over AI suppression
|
||||
if ( BestShot.bWeaponIn != -1 && (GetMagSize(&pSoldier->inv[BestShot.bWeaponIn]) >= gGameExternalOptions.ubAISuppressionMinimumMagSize && pSoldier->inv[BestShot.bWeaponIn][0]->data.gun.ubGunShotsLeft >= gGameExternalOptions.ubAISuppressionMinimumAmmo) && ( ( BestShot.ubPossible && BestShot.ubChanceToReallyHit < 50 ) || (BestShot.ubPossible && BestShot.ubChanceToReallyHit < (INT16)PreRandom(100)) && Menptr[BestShot.ubOpponent].pathing.bLevel == 0 && pSoldier->aiData.bOrders != SNIPER ))
|
||||
fEnableAIAutofire = TRUE;
|
||||
|
||||
if (fEnableAIAutofire)
|
||||
// WarmSteel - Don't *always* try to suppress when under 50 CTH
|
||||
if ( BestShot.bWeaponIn != -1
|
||||
&& BestShot.ubPossible
|
||||
&& GetMagSize(&pSoldier->inv[BestShot.bWeaponIn]) >= gGameExternalOptions.ubAISuppressionMinimumMagSize
|
||||
&& pSoldier->inv[BestShot.bWeaponIn][0]->data.gun.ubGunShotsLeft >= gGameExternalOptions.ubAISuppressionMinimumAmmo
|
||||
&& BestShot.ubChanceToReallyHit < (INT16)(PreRandom(100) - 50)
|
||||
&& Menptr[BestShot.ubOpponent].pathing.bLevel == 0
|
||||
&& pSoldier->aiData.bOrders != SNIPER )
|
||||
{
|
||||
// then do it!
|
||||
|
||||
@@ -2522,9 +2547,9 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
// Make sure we decided to fire at least one shot!
|
||||
ubBurstAPs = CalcAPsToAutofire( pSoldier->CalcActionPoints(), &(pSoldier->inv[BestShot.bWeaponIn]), pSoldier->bDoAutofire );
|
||||
|
||||
// minimum 10 bullets
|
||||
// minimum 5 bullets //WarmSteel: 5 bullets sounds reasonable, no?
|
||||
// Hmmm, automatic suppression? Howcome we don't get this?
|
||||
if (pSoldier->bDoAutofire >= 10 && pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs )
|
||||
if (pSoldier->bDoAutofire >= 5 && pSoldier->bActionPoints >= BestShot.ubAPCost + ubBurstAPs )
|
||||
{
|
||||
pSoldier->aiData.bAimTime = 0;
|
||||
pSoldier->bDoBurst = 1;
|
||||
@@ -3203,8 +3228,8 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
guiRedHelpTimeTotal += (uiEndTime - uiStartTime);
|
||||
guiRedHelpCounter++;
|
||||
#endif
|
||||
|
||||
if (!TileIsOutOfBounds(sClosestFriend))
|
||||
//WarmSteel - Dont try if we're already quite close to our friend
|
||||
if (!TileIsOutOfBounds(sClosestFriend) && PythSpacesAway(pSoldier->sGridNo, sClosestFriend) > pSoldier->GetMaxDistanceVisible(sClosestFriend, 0, CALC_FROM_ALL_DIRS ))
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// GO DIRECTLY TOWARDS CLOSEST FRIEND UNDER FIRE OR WHO LAST RADIOED
|
||||
@@ -3900,8 +3925,9 @@ INT16 ubMinAPCost;
|
||||
}
|
||||
}
|
||||
|
||||
if(WearGasMaskIfAvailable(pSoldier))//dnl ch40 200909
|
||||
bInGas = InGasOrSmoke(pSoldier, pSoldier->sGridNo);
|
||||
//Only put mask on in gas
|
||||
if(bInGas && WearGasMaskIfAvailable(pSoldier))//dnl ch40 200909
|
||||
bInGas = InGasOrSmoke(pSoldier, pSoldier->sGridNo);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// IF GASSED, OR REALLY TIRED (ON THE VERGE OF COLLAPSING), TRY TO RUN AWAY
|
||||
|
||||
@@ -651,7 +651,8 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
||||
// HEADROCK HAM 3.6: This doesn't take into account the 100AP system. Adjusting.
|
||||
// Please note, I used a calculation that may have a better representation in some global variable.
|
||||
//iMaxMoveTilesLeft = __max( 0, pSoldier->bActionPoints - MinAPsToStartMovement( pSoldier, usMovementMode ) );
|
||||
iMaxMoveTilesLeft = __max( 0, (pSoldier->bActionPoints - MinAPsToStartMovement( pSoldier, usMovementMode ) / (APBPConstants[AP_MAXIMUM]/25)) );
|
||||
// WarmSteel - Bugfix: wrong parentheses
|
||||
iMaxMoveTilesLeft = __max( 0, (pSoldier->bActionPoints - MinAPsToStartMovement( pSoldier, usMovementMode )) / (APBPConstants[AP_MAXIMUM] / 25) );
|
||||
|
||||
//NumMessage("In BLACK, maximum tiles to move left = ",maxMoveTilesLeft);
|
||||
|
||||
@@ -799,7 +800,17 @@ INT32 FindBestNearbyCover(SOLDIERTYPE *pSoldier, INT32 morale, INT32 *piPercentB
|
||||
//PopMessage(tempstr);
|
||||
}
|
||||
|
||||
iCurrentCoverValue -= (iCurrentCoverValue / 10) * NumberOfTeamMatesAdjacent( pSoldier, pSoldier->sGridNo );
|
||||
// reduce cover for each person adjacent to this gridno who is on our team,
|
||||
// by 10% (so locations next to several people will be very much frowned upon
|
||||
if ( iCurrentCoverValue >= 0 )
|
||||
{
|
||||
iCurrentCoverValue -= (iCurrentCoverValue / 10) * NumberOfTeamMatesAdjacent( pSoldier, pSoldier->sGridNo );
|
||||
}
|
||||
else
|
||||
{
|
||||
// when negative, must add a negative to decrease the total
|
||||
iCurrentCoverValue += (iCurrentCoverValue / 10) * NumberOfTeamMatesAdjacent( pSoldier, pSoldier->sGridNo );
|
||||
}
|
||||
|
||||
#ifdef DEBUGCOVER
|
||||
// AINumMessage("Search Range = ",iSearchRange);
|
||||
|
||||
@@ -98,6 +98,8 @@ typedef enum
|
||||
AI_ACTION_OFFER_SURRENDER, // offer surrender to the player
|
||||
AI_ACTION_RAISE_GUN,
|
||||
AI_ACTION_STEAL_MOVE, // added by SANDRO
|
||||
|
||||
AI_ACTION_RELOAD_GUN,
|
||||
} ActionType;
|
||||
|
||||
|
||||
|
||||
@@ -103,6 +103,9 @@ BOOLEAN ExpAffect( INT32 sBombGridNo, INT32 sGridNo, UINT32 uiDist, UINT16 usIte
|
||||
// Flashbang effect on soldier
|
||||
UINT8 DetermineFlashbangEffect( SOLDIERTYPE *pSoldier, INT8 ubExplosionDir, BOOLEAN fInBuilding);
|
||||
|
||||
// HEADROCK HAM 5.1: Explosion Fragments launcher
|
||||
void FireFragments( SOLDIERTYPE * pThrower, INT16 sX, INT16 sY, INT16 sZ, UINT16 usItem );
|
||||
|
||||
extern INT8 gbSAMGraphicList[ MAX_NUMBER_OF_SAMS ];
|
||||
extern void AddToShouldBecomeHostileOrSayQuoteList( UINT8 ubID );
|
||||
extern void RecompileLocalMovementCostsForWall( INT32 sGridNo, UINT8 ubOrientation );
|
||||
@@ -338,12 +341,17 @@ void InternalIgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32
|
||||
ExpParams.bLevel = bLevel;
|
||||
|
||||
GenerateExplosion( &ExpParams );
|
||||
|
||||
// HEADROCK HAM 5.1: Launch fragments from the explosion.
|
||||
if (Explosive[ Item[ usItem ].ubClassIndex ].usNumFragments > 0 )
|
||||
{
|
||||
// HEADROCK HAM 5: Deactivated until the release of HAM 5.1.
|
||||
FireFragments( MercPtrs[ubOwner], sX, sY, sZ, usItem );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void IgniteExplosion( UINT8 ubOwner, INT16 sX, INT16 sY, INT16 sZ, INT32 sGridNo, UINT16 usItem, INT8 bLevel )
|
||||
{
|
||||
InternalIgniteExplosion( ubOwner, sX, sY, sZ, sGridNo, usItem, TRUE, bLevel );
|
||||
@@ -4349,6 +4357,43 @@ UINT8 DetermineFlashbangEffect( SOLDIERTYPE *pSoldier, INT8 ubExplosionDir, BOOL
|
||||
return ( FIRE_WEAPON_BLINDED_AND_DEAFENED );
|
||||
}
|
||||
|
||||
|
||||
// HEADROCK HAM 5.1: This handles launching fragments out of an explosion. The number of fragments is read from
|
||||
// the Explosives.XML file, and they each have a set amount of damage and range as well. They are currently
|
||||
// fired at completely random trajectories.
|
||||
void FireFragments( SOLDIERTYPE * pThrower, INT16 sX, INT16 sY, INT16 sZ, UINT16 usItem )
|
||||
{
|
||||
UINT16 usNumFragments = Explosive[Item[usItem].ubClassIndex].usNumFragments;
|
||||
UINT16 ubFragRange = Explosive[Item[usItem].ubClassIndex].ubFragRange;
|
||||
|
||||
AssertMsg( ubFragRange > 0 , "Fragmentation data lacks range property!" );
|
||||
|
||||
for (UINT16 x = 0; x < usNumFragments; x++)
|
||||
{
|
||||
FLOAT dRandomX = ((FLOAT)Random(2000) / 1000.0f) - 1.0f;
|
||||
FLOAT dRandomY = ((FLOAT)Random(2000) / 1000.0f) - 1.0f;
|
||||
FLOAT dRandomZ = ((FLOAT)Random(2000) / 1000.0f) - 1.0f;
|
||||
|
||||
FLOAT dDeltaX = (dRandomX * ubFragRange);
|
||||
FLOAT dDeltaY = (dRandomY * ubFragRange);
|
||||
FLOAT dDeltaZ = ((dRandomZ * 25.6f) * 50 );
|
||||
|
||||
FLOAT dRangeMultiplier = 10; // Arbitrary, but gives good results.
|
||||
|
||||
FLOAT dEndX = (FLOAT)(sX + (dDeltaX * dRangeMultiplier));
|
||||
FLOAT dEndY = (FLOAT)(sY + (dDeltaY * dRangeMultiplier));
|
||||
FLOAT dEndZ = (FLOAT)(sZ + (dDeltaZ * dRangeMultiplier));
|
||||
|
||||
// Add some randomness to the start coordinates as well, so that not all fragments fly from the same point
|
||||
// in space.
|
||||
FLOAT dStartX = (FLOAT)sX + (dRandomX * ((FLOAT)Random(4)+1.0f));
|
||||
FLOAT dStartY = (FLOAT)sY + (dRandomY * ((FLOAT)Random(4)+1.0f));
|
||||
FLOAT dStartZ = (FLOAT)sZ + (dRandomZ * ((FLOAT)Random(4)+1.0f));
|
||||
|
||||
FireFragmentGivenTarget( pThrower, dStartX, dStartY, dStartZ, dEndX, dEndY, dEndZ, usItem );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JA2UB
|
||||
|
||||
//-- UB
|
||||
|
||||
+68
-70
@@ -546,45 +546,43 @@ void DecaySmokeEffects( UINT32 uiTime )
|
||||
|
||||
if ( pSmoke->fAllocated )
|
||||
{
|
||||
if ( pSmoke->bFlags & SMOKE_EFFECT_ON_ROOF )
|
||||
{
|
||||
bLevel = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bLevel = 0;
|
||||
}
|
||||
|
||||
|
||||
// Do things differently for combat /vs realtime
|
||||
// always try to update during combat
|
||||
if (gTacticalStatus.uiFlags & INCOMBAT )
|
||||
{
|
||||
fUpdate = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ATE: Do this every so ofte, to acheive the effect we want...
|
||||
if ( ( uiTime - pSmoke->uiTimeOfLastUpdate ) > 10 )
|
||||
if ( pSmoke->bFlags & SMOKE_EFFECT_ON_ROOF )
|
||||
{
|
||||
fUpdate = TRUE;
|
||||
bLevel = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bLevel = 0;
|
||||
}
|
||||
|
||||
usNumUpdates = ( UINT16 ) ( ( uiTime - pSmoke->uiTimeOfLastUpdate ) / 10 );
|
||||
}
|
||||
}
|
||||
// Do things differently for combat /vs realtime
|
||||
// always try to update during combat
|
||||
if (gTacticalStatus.uiFlags & INCOMBAT )
|
||||
{
|
||||
fUpdate = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ATE: Do this every so ofte, to acheive the effect we want...
|
||||
if ( ( uiTime - pSmoke->uiTimeOfLastUpdate ) > 10 )
|
||||
{
|
||||
fUpdate = TRUE;
|
||||
usNumUpdates = ( UINT16 ) ( ( uiTime - pSmoke->uiTimeOfLastUpdate ) / 10 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( fUpdate )
|
||||
{
|
||||
if ( fUpdate )
|
||||
{
|
||||
pSmoke->uiTimeOfLastUpdate = uiTime;
|
||||
|
||||
for ( cnt2 = 0; cnt2 < usNumUpdates; cnt2++ )
|
||||
{
|
||||
pSmoke->bAge++;
|
||||
|
||||
for ( cnt2 = 0; cnt2 < usNumUpdates; cnt2++ )
|
||||
{
|
||||
pSmoke->bAge++;
|
||||
|
||||
if ( pSmoke->bAge == 1 )
|
||||
{
|
||||
// ATE: At least mark for update!
|
||||
pSmoke->bFlags |= SMOKE_EFFECT_MARK_FOR_UPDATE;
|
||||
// ATE: At least mark for update!
|
||||
pSmoke->bFlags |= SMOKE_EFFECT_MARK_FOR_UPDATE;
|
||||
fSpreadEffect = FALSE;
|
||||
}
|
||||
else
|
||||
@@ -592,41 +590,41 @@ void DecaySmokeEffects( UINT32 uiTime )
|
||||
fSpreadEffect = TRUE;
|
||||
}
|
||||
|
||||
if ( fSpreadEffect )
|
||||
{
|
||||
// if this cloud remains effective (duration not reached)
|
||||
if ( pSmoke->bAge <= pSmoke->ubDuration)
|
||||
{
|
||||
// ATE: Only mark now and increse radius - actual drawing is done
|
||||
// in another pass cause it could
|
||||
// just get erased...
|
||||
pSmoke->bFlags |= SMOKE_EFFECT_MARK_FOR_UPDATE;
|
||||
if ( fSpreadEffect )
|
||||
{
|
||||
// if this cloud remains effective (duration not reached)
|
||||
if ( pSmoke->bAge <= pSmoke->ubDuration)
|
||||
{
|
||||
// ATE: Only mark now and increse radius - actual drawing is done
|
||||
// in another pass cause it could
|
||||
// just get erased...
|
||||
pSmoke->bFlags |= SMOKE_EFFECT_MARK_FOR_UPDATE;
|
||||
|
||||
// calculate the new cloud radius
|
||||
// cloud expands by 1 every turn outdoors, and every other turn indoors
|
||||
// calculate the new cloud radius
|
||||
// cloud expands by 1 every turn outdoors, and every other turn indoors
|
||||
|
||||
// ATE: If radius is < maximun, increase radius, otherwise keep at max
|
||||
if ( pSmoke->ubRadius < Explosive[ Item[ pSmoke->usItem ].ubClassIndex ].ubRadius )
|
||||
{
|
||||
pSmoke->ubRadius++;
|
||||
// ATE: If radius is < maximun, increase radius, otherwise keep at max
|
||||
if ( pSmoke->ubRadius < Explosive[ Item[ pSmoke->usItem ].ubClassIndex ].ubRadius )
|
||||
{
|
||||
pSmoke->ubRadius++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// deactivate tear gas cloud (use last known radius)
|
||||
SpreadEffect( pSmoke->sGridNo, pSmoke->ubRadius, pSmoke->usItem, pSmoke->ubOwner, ERASE_SPREAD_EFFECT, bLevel, cnt );
|
||||
pSmoke->fAllocated = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// deactivate tear gas cloud (use last known radius)
|
||||
SpreadEffect( pSmoke->sGridNo, pSmoke->ubRadius, pSmoke->usItem, pSmoke->ubOwner, ERASE_SPREAD_EFFECT, bLevel, cnt );
|
||||
pSmoke->fAllocated = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// damage anyone standing in cloud
|
||||
SpreadEffect( pSmoke->sGridNo, pSmoke->ubRadius, pSmoke->usItem, pSmoke->ubOwner, REDO_SPREAD_EFFECT, bLevel, cnt );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( cnt = 0; cnt < guiNumSmokeEffects; cnt++ )
|
||||
@@ -635,22 +633,22 @@ void DecaySmokeEffects( UINT32 uiTime )
|
||||
|
||||
if ( pSmoke->fAllocated )
|
||||
{
|
||||
if ( pSmoke->bFlags & SMOKE_EFFECT_ON_ROOF )
|
||||
{
|
||||
bLevel = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bLevel = 0;
|
||||
}
|
||||
if ( pSmoke->bFlags & SMOKE_EFFECT_ON_ROOF )
|
||||
{
|
||||
bLevel = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bLevel = 0;
|
||||
}
|
||||
|
||||
// if this cloud remains effective (duration not reached)
|
||||
if ( pSmoke->bFlags & SMOKE_EFFECT_MARK_FOR_UPDATE )
|
||||
// if this cloud remains effective (duration not reached)
|
||||
if ( pSmoke->bFlags & SMOKE_EFFECT_MARK_FOR_UPDATE )
|
||||
{
|
||||
SpreadEffect( pSmoke->sGridNo, pSmoke->ubRadius, pSmoke->usItem, pSmoke->ubOwner, TRUE, bLevel, cnt );
|
||||
pSmoke->bFlags &= (~SMOKE_EFFECT_MARK_FOR_UPDATE);
|
||||
pSmoke->bFlags &= (~SMOKE_EFFECT_MARK_FOR_UPDATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AllTeamsLookForAll( TRUE );
|
||||
|
||||
@@ -44,6 +44,8 @@ extern UINT32 guiNumSmokeEffects;
|
||||
INT8 GetSmokeEffectOnTile( INT32 sGridNo, INT8 bLevel );
|
||||
|
||||
// Decays all smoke effects...
|
||||
// HEADROCK HAM 5: New argument here tells the decay function to only process clouds belonging to one team.
|
||||
// -1 = all teams.
|
||||
void DecaySmokeEffects( UINT32 uiTime );
|
||||
|
||||
// Add smoke to gridno
|
||||
|
||||
+26
-17
@@ -220,7 +220,14 @@ void EnvironmentController( BOOLEAN fCheckForLights )
|
||||
{
|
||||
if ( guiRainLoop == NO_SAMPLE )
|
||||
{
|
||||
guiRainLoop = PlayJA2Ambient( RAIN_1, BTNVOLUME, 0 );
|
||||
if (guiEnvWeather & WEATHER_FORECAST_THUNDERSHOWERS )
|
||||
{
|
||||
guiRainLoop = PlayJA2Ambient( RAIN_1, 140, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
guiRainLoop = PlayJA2Ambient( RAIN_1, 70, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,24 +714,26 @@ void EnvBeginRainStorm( UINT8 ubIntensity )
|
||||
{
|
||||
gfDoLighting = TRUE;
|
||||
|
||||
#ifdef JA2TESTVERSION
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Starting Rain...." );
|
||||
#endif
|
||||
#ifdef JA2TESTVERSION
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_TESTVERSION, L"Starting Rain...." );
|
||||
#endif
|
||||
|
||||
// First turn off whatever rain it is, then turn on the requested rain
|
||||
guiEnvWeather &= ~(WEATHER_FORECAST_THUNDERSHOWERS | WEATHER_FORECAST_SHOWERS);
|
||||
// First turn off whatever rain it is, then turn on the requested rain
|
||||
guiEnvWeather &= ~(WEATHER_FORECAST_THUNDERSHOWERS | WEATHER_FORECAST_SHOWERS);
|
||||
|
||||
if ( ubIntensity == 1 )
|
||||
{
|
||||
// Turn on rain storms
|
||||
guiEnvWeather |= WEATHER_FORECAST_THUNDERSHOWERS;
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_STORM_STARTED] );
|
||||
}
|
||||
else
|
||||
{
|
||||
guiEnvWeather |= WEATHER_FORECAST_SHOWERS;
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_RAIN_STARTED] );
|
||||
}
|
||||
if ( ubIntensity == 1 )
|
||||
{
|
||||
// Turn on rain storms
|
||||
guiEnvWeather |= WEATHER_FORECAST_THUNDERSHOWERS;
|
||||
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_STORM_STARTED] );
|
||||
}
|
||||
else
|
||||
{
|
||||
guiEnvWeather |= WEATHER_FORECAST_SHOWERS;
|
||||
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_RAIN_STARTED] );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,7 +62,8 @@ class SOLDIERTYPE;
|
||||
|
||||
#define GET_OBJECT_LEVEL( z ) ( (INT8)( ( z + 10 ) / HEIGHT_UNITS ) )
|
||||
//#define OBJECT_DETONATE_ON_IMPACT( object ) ( ( object->Obj.usItem == MORTAR_SHELL ) ) // && ( object->ubActionCode == THROW_ARM_ITEM || pObject->fTestObject ) )
|
||||
#define OBJECT_DETONATE_ON_IMPACT( object ) ( ( Item[object->Obj.usItem].usItemClass == IC_BOMB ) ) // && ( object->ubActionCode == THROW_ARM_ITEM || pObject->fTestObject ) )
|
||||
// HEADROCK HAM 5: Enabled "Explode on Impact" flag for explosive items
|
||||
#define OBJECT_DETONATE_ON_IMPACT( object ) ( ( Item[object->Obj.usItem].usItemClass == IC_BOMB ) || ( Explosive[Item[object->Obj.usItem].ubClassIndex ].fExplodeOnImpact ) ) // && ( object->ubActionCode == THROW_ARM_ITEM || pObject->fTestObject ) )
|
||||
|
||||
|
||||
#define MAX_INTEGRATIONS 8
|
||||
|
||||
@@ -345,7 +345,7 @@ bool Loc::ExportStrings()
|
||||
ExportSection(props, L"TooltipStrings", Loc::gzTooltipStrings, 0, TEXT_NUM_STR_TT);
|
||||
ExportSection(props, L"New113Message", Loc::New113Message, 0, TEXT_NUM_MSG113);
|
||||
|
||||
ExportSection(props, L"New113HAMMessage", Loc::New113HAMMessage, 0, 22);
|
||||
ExportSection(props, L"New113HAMMessage", Loc::New113HAMMessage, 0, 25);
|
||||
ExportSection(props, L"New113MERCMercMail", Loc::New113MERCMercMailTexts, 0, 4);
|
||||
ExportSection(props, L"New113AIMMercMail", Loc::New113AIMMercMailTexts, 0, 16);
|
||||
ExportSection(props, L"MissingIMPSkills", Loc::MissingIMPSkillsDescriptions, 0, 2);
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@
|
||||
#include "WCheck.h"
|
||||
#include "Render Dirty.h"
|
||||
|
||||
#define MAX_POPUP_BOX_COUNT 20
|
||||
#define MAX_POPUP_BOX_STRING_COUNT 50 // worst case = 45: move menu with 20 soldiers, each on different squad + overhead
|
||||
#define MAX_POPUP_BOX_COUNT 32
|
||||
#define MAX_POPUP_BOX_STRING_COUNT 128 // worst case = 45: move menu with 20 soldiers, each on different squad + overhead
|
||||
|
||||
// PopUpBox Flags
|
||||
#define POPUP_BOX_FLAG_CLIP_TEXT 1
|
||||
|
||||
+10
-4
@@ -322,6 +322,10 @@ extern STR16 gzFacilityRiskResultStrings[];
|
||||
// HEADROCK HAM 4: Text for the new CTH indicator.
|
||||
extern STR16 gzNCTHlabels[];
|
||||
|
||||
// HEADROCK HAM 5: Messages for automatic sector inventory sorting.
|
||||
extern STR16 gzMapInventorySortingMessage[];
|
||||
extern STR16 gzMapInventoryFilterOptions[];
|
||||
|
||||
enum
|
||||
{
|
||||
ANTIHACKERSTR_EXITGAME,
|
||||
@@ -624,14 +628,14 @@ extern STR16 gzUDBButtonTooltipText[ 3 ];
|
||||
extern STR16 gzUDBHeaderTooltipText[ 4 ];
|
||||
extern STR16 gzUDBGenIndexTooltipText[ 4 ];
|
||||
extern STR16 gzUDBAdvIndexTooltipText[ 5 ];
|
||||
extern STR16 szUDBGenWeaponsStatsTooltipText[ 22 ];
|
||||
extern STR16 szUDBGenWeaponsStatsExplanationsTooltipText[ 22 ];
|
||||
extern STR16 szUDBGenWeaponsStatsTooltipText[ 23 ];
|
||||
extern STR16 szUDBGenWeaponsStatsExplanationsTooltipText[ 23 ];
|
||||
extern STR16 szUDBGenArmorStatsTooltipText[ 3 ];
|
||||
extern STR16 szUDBGenArmorStatsExplanationsTooltipText[ 3 ];
|
||||
extern STR16 szUDBGenAmmoStatsTooltipText[ 4 ]; // Flugente Overheating Weapons: 3->4
|
||||
extern STR16 szUDBGenAmmoStatsExplanationsTooltipText[ 4 ];
|
||||
extern STR16 szUDBGenExplosiveStatsTooltipText[ 18 ];
|
||||
extern STR16 szUDBGenExplosiveStatsExplanationsTooltipText[ 18 ];
|
||||
extern STR16 szUDBGenExplosiveStatsTooltipText[ 22 ];
|
||||
extern STR16 szUDBGenExplosiveStatsExplanationsTooltipText[ 22 ];
|
||||
extern STR16 szUDBGenSecondaryStatsTooltipText[ 26 ];
|
||||
extern STR16 szUDBGenSecondaryStatsExplanationsTooltipText[ 26 ];
|
||||
extern STR16 szUDBAdvStatsTooltipText[ 56 ]; // Flugente Overheating Weapons: 48->56
|
||||
@@ -2101,6 +2105,8 @@ enum
|
||||
TEXT_NUM_MSG113,
|
||||
};
|
||||
|
||||
extern STR16 gzTransformationMessage[];
|
||||
|
||||
//CHRISL: NewInv messages
|
||||
extern STR16 NewInvMessage[];
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
<ClInclude Include="PopUpBox.h" />
|
||||
<ClInclude Include="popup_callback.h" />
|
||||
<ClInclude Include="popup_class.h" />
|
||||
<ClInclude Include="popup_definition.h" />
|
||||
<ClInclude Include="Quantize Wrap.h" />
|
||||
<ClInclude Include="Quantize.h" />
|
||||
<ClInclude Include="Slider.h" />
|
||||
@@ -98,6 +99,7 @@
|
||||
<ClCompile Include="Music Control.cpp" />
|
||||
<ClCompile Include="PopUpBox.cpp" />
|
||||
<ClCompile Include="popup_class.cpp" />
|
||||
<ClCompile Include="popup_definition.cpp" />
|
||||
<ClCompile Include="Quantize Wrap.cpp" />
|
||||
<ClCompile Include="Quantize.cpp" />
|
||||
<ClCompile Include="Slider.cpp" />
|
||||
|
||||
@@ -159,6 +159,9 @@
|
||||
<ClInclude Include="KeyMap.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="popup_definition.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="_ChineseText.cpp">
|
||||
@@ -338,5 +341,8 @@
|
||||
<ClCompile Include="KeyMap.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="popup_definition.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+97
-24
@@ -870,7 +870,7 @@ STR16 pPasteMercPlacementText[] =
|
||||
{
|
||||
L"Placement not pasted as no placement is saved in buffer.",
|
||||
L"Placement pasted.",
|
||||
L"Placement not pasted as the maximum number of placements for this team is reached.",
|
||||
L"Placement not pasted as the maximum number of placements for this team has been reached.",
|
||||
};
|
||||
|
||||
//editscreen.cpp
|
||||
@@ -2471,11 +2471,13 @@ CHAR16 gWeaponStatsDesc[][ 17 ] =
|
||||
// HEADROCK: Several arrays of tooltip text for new Extended Description Box
|
||||
// Please note, several of these are artificially inflated to 19 entries to help fix a complication with
|
||||
// changing item type while watching its description box
|
||||
// HEADROCK HAM 5: Apparently this isn't used anymore... see the next array.
|
||||
STR16 gzWeaponStatsFasthelp[ 32 ] =
|
||||
{
|
||||
L"Accuracy",
|
||||
L"Damage",
|
||||
L"Range",
|
||||
L"", //3
|
||||
L"Aiming Levels",
|
||||
L"Aiming Modifier",
|
||||
L"Average Best Laser Range",
|
||||
@@ -2485,7 +2487,6 @@ STR16 gzWeaponStatsFasthelp[ 32 ] =
|
||||
L"Repair Ease",
|
||||
L"Min. Range for Aiming Bonus",
|
||||
L"To-Hit Modifier",
|
||||
L"", //12
|
||||
L"APs to ready",
|
||||
L"APs to fire Single",
|
||||
L"APs to fire Burst",
|
||||
@@ -2509,18 +2510,18 @@ STR16 gzWeaponStatsFasthelp[ 32 ] =
|
||||
|
||||
STR16 gzWeaponStatsFasthelpTactical[ 32 ] =
|
||||
{
|
||||
L"Accuracy",
|
||||
L"Damage",
|
||||
L"Range",
|
||||
L"Aiming Levels",
|
||||
L"Aiming Modifier",
|
||||
L"Average Best Laser Range",
|
||||
L"Flash Suppression",
|
||||
L"Loudness (lower is better)",
|
||||
L"Reliability",
|
||||
L"Repair Ease",
|
||||
L"Min. Range for Aiming Bonus",
|
||||
L"To-Hit Modifier",
|
||||
L"|R|a|n|g|e\n \nThe effective range of this weapon. Attacking from\nbeyond this range will lead to massive penalties.\n \nHigher is better.",
|
||||
L"|D|a|m|a|g|e\n \nThis is the damage potential of the weapon.\nIt will usually deliver this much damage\n(or close to it) to any unprotected target.\n \nHigher is better.",
|
||||
L"|A|c|c|u|r|a|c|y\n \nThis is an innate Chance-to-Hit Bonus (or\npenalty!) given by this gun due to its\nparticular good (or bad) design.\n \nHigher is better.",
|
||||
L"|A|i|m|i|n|g |L|e|v|e|l|s\n \nThis is the maximum number of aiming clicks allowed\nwhen using this gun.\n \nEach aiming-click will make an attack more\naccurate.\n \nHigher is better.",
|
||||
L"|A|i|m|i|n|g |M|o|d|i|f|i|e|r\n \nA flat modifier, which alters the effectiveness\nof each aiming click you make while using this\nweapon.\n \nHigher is better.",
|
||||
L"|M|i|n|. |R|a|n|g|e |f|o|r |A|i|m|i|n|g |B|o|n|u|s\n \nThe minimum range-to-target required before this\nweapon can make use of its Aiming Modifier.\n \nIf the target is closer than this many tiles,\naiming clicks will stay at their default\neffectiveness.\n \nLower is better.",
|
||||
L"|T|o|-|H|i|t |M|o|d|i|f|i|e|r\n \nA flat modifier to Chance-to-Hit with any\nattack made using this weapon.\n \nHigher is better.",
|
||||
L"|B|e|s|t |L|a|s|e|r |R|a|n|g|e\n \nThe range (in tiles) at which the laser installed\non this weapon will be at its full effectiveness.\n \nWhen attacking a target beyond this range, the\nlaser will provide a smaller bonus or none at all.\n \nHigher is better.",
|
||||
L"|F|l|a|s|h |S|u|p|p|r|e|s|s|i|o|n\n \nWhen this icon appears, it means that the gun\ndoes not make a flash when it fires. This helps the\nshooter remain concealed.",
|
||||
L"|L|o|u|d|n|e|s|s\n \nAttacks made with this weapon can be heard up to\nthe listed distance (in tiles).\n \nLower is better.\n(unless deliberately trying to draw in enemies...)",
|
||||
L"|R|e|l|i|a|b|i|l|i|t|y\n \nThis value indicates (in general) how quickly\nthis weapon will degrade when used in combat.\n \nHigher is better.",
|
||||
L"|R|e|p|a|i|r |E|a|s|e\n \nThis value indicates how quickly this weapon can\nbe repaired (by a mercenary set to Repair duty).\n \nHigher is better.",
|
||||
L"", //12
|
||||
L"APs to ready",
|
||||
L"APs to fire Single",
|
||||
@@ -3188,6 +3189,23 @@ STR16 pMapScreenInvenButtonHelpText[] =
|
||||
L"Next (|.)", // next page
|
||||
L"Previous (|,)", // previous page
|
||||
L"Exit Sector Inventory (|E|s|c)", // exit sector inventory
|
||||
L"Zoom Inventory", // HEAROCK HAM 5: Inventory Zoom Button
|
||||
L"Stack and merge items", // HEADROCK HAM 5: Stack and Merge
|
||||
L"|L|e|f|t |C|l|i|c|k: Sort ammo into crates; |R|i|g|h|t |C|l|i|c|k: Sort ammo into boxes", // HEADROCK HAM 5: Sort ammo
|
||||
// 6 - 10
|
||||
L"Remove all item attachments", // HEADROCK HAM 5: Separate Attachments
|
||||
L"Eject ammo from all weapons", //HEADROCK HAM 5: Eject Ammo
|
||||
L"|L|e|f|t |C|l|i|c|k: Show all items; |R|i|g|h|t |C|l|i|c|k: Hide all items", // HEADROCK HAM 5: Filter Button
|
||||
L"|L|e|f|t |C|l|i|c|k: Toggle Guns; |R|i|g|h|t |C|l|i|c|k|: Show only Guns", // HEADROCK HAM 5: Filter Button
|
||||
L"|L|e|f|t |C|l|i|c|k: Toggle Ammunition; |R|i|g|h|t |C|l|i|c|k: Show only Ammunition", // HEADROCK HAM 5: Filter Button
|
||||
// 11 - 15
|
||||
L"|L|e|f|t |C|l|i|c|k: Toggle Explosives; |R|i|g|h|t |C|l|i|c|k: Show only Explosives", // HEADROCK HAM 5: Filter Button
|
||||
L"|L|e|f|t |C|l|i|c|k: Toggle Melee Weapons; |R|i|g|h|t |C|l|i|c|k: Show only Melee Weapons", // HEADROCK HAM 5: Filter Button
|
||||
L"|L|e|f|t |C|l|i|c|k: Toggle Armor; |R|i|g|h|t |C|l|i|c|k: Show only Armor", // HEADROCK HAM 5: Filter Button
|
||||
L"|L|e|f|t |C|l|i|c|k: Toggle LBEs; |R|i|g|h|t |C|l|i|c|k: Show only LBEs", // HEADROCK HAM 5: Filter Button
|
||||
L"|L|e|f|t |C|l|i|c|k: Toggle Kits; |R|i|g|h|t |C|l|i|c|k: Show only Kits", // HEADROCK HAM 5: Filter Button
|
||||
// 16 - 20
|
||||
L"|L|e|f|t |C|l|i|c|k: Toggle Misc. Items; |R|i|g|h|t |C|l|i|c|k: Show only Misc. Items", // HEADROCK HAM 5: Filter Button
|
||||
};
|
||||
|
||||
STR16 pMapScreenBottomFastHelp[] =
|
||||
@@ -6121,7 +6139,26 @@ STR16 New113HAMMessage[] =
|
||||
L"Daily Expenses",
|
||||
// 21 - 25
|
||||
L"Insufficient funds to pay all enlisted militia! %d militia have disbanded and returned home.",
|
||||
L"To examine an item's stats during combat, you must pick it up manually first.", // HAM 5
|
||||
L"To attach an item to another item during combat, you must pick them both up first.", // HAM 5
|
||||
L"To merge two items during combat, you must pick them both up first.", // HAM 5
|
||||
};
|
||||
|
||||
// HEADROCK HAM 5: Text dealing exclusively with Item Transformations.
|
||||
STR16 gzTransformationMessage[] =
|
||||
{
|
||||
L"No available adjustments",
|
||||
L"%s was split into several parts.",
|
||||
L"%s was split into several parts. Check %s's inventory for the resulting items.",
|
||||
L"Due to lack of inventory space after transformation, some of %s's items have been dropped to the ground.",
|
||||
L"%s was split into several parts. Due to a lack of inventory space, %s has had to drop a few items to the ground.",
|
||||
L"Do you wish to adjust all %d items in this stack? (To transform only one item, remove it from the stack first)",
|
||||
// 6 - 10
|
||||
L"Split Crate into Inventory",
|
||||
L"Split into %d-rd Mags",
|
||||
L"%s was split into %d Magazines containing %d rounds each.",
|
||||
L"%s was split into %s's inventory.",
|
||||
L"There is insufficient room in %s's inventory to fit any magazines of this caliber!",
|
||||
};
|
||||
|
||||
// WANNE: This hardcoded text should not be used anymore in the game, because we now have those texts externalized in the "TableData\Email\EmailMercLevelUp.xml" file!
|
||||
@@ -6790,6 +6827,7 @@ STR16 szUDBGenWeaponsStatsTooltipText[]=
|
||||
L"|A|c|c|u|r|a|c|y",
|
||||
L"|D|a|m|a|g|e",
|
||||
L"|R|a|n|g|e",
|
||||
L"|H|a|n|d|l|i|n|g |D|i|f|f|i|c|u|l|t|y",
|
||||
L"|A|l|l|o|w|e|d |A|i|m|i|n|g |L|e|v|e|l|s",
|
||||
L"|S|c|o|p|e |M|a|g|n|i|f|i|c|a|t|i|o|n |F|a|c|t|o|r",
|
||||
L"|P|r|o|j|e|c|t|i|o|n |F|a|c|t|o|r",
|
||||
@@ -6799,15 +6837,14 @@ STR16 szUDBGenWeaponsStatsTooltipText[]=
|
||||
L"|R|e|p|a|i|r |E|a|s|e",
|
||||
L"|M|i|n|. |R|a|n|g|e |f|o|r |A|i|m|i|n|g |B|o|n|u|s",
|
||||
L"|T|o|-|H|i|t |M|o|d|i|f|i|e|r",
|
||||
L"", // (12)
|
||||
L"|A|P|s |t|o |R|e|a|d|y",
|
||||
L"|A|P|s |t|o |A|t|t|a|c|k",
|
||||
L"|A|P|s |t|o |B|u|r|s|t",
|
||||
L"|A|P|s |t|o |A|u|t|o|f|i|r|e",
|
||||
L"|A|P|s |t|o |R|e|l|o|a|d",
|
||||
L"|A|P|s |t|o |R|e|c|h|a|m|b|e|r",
|
||||
L"|L|a|t|e|r|a|l |R|e|c|o|i|l",
|
||||
L"|V|e|r|t|i|c|a|l |R|e|c|o|i|l",
|
||||
L"|L|a|t|e|r|a|l |R|e|c|o|i|l", // No longer used
|
||||
L"|T|o|t|a|l |R|e|c|o|i|l",
|
||||
L"|A|u|t|o|f|i|r|e |B|u|l|l|e|t|s |p|e|r |5 |A|P|s",
|
||||
};
|
||||
|
||||
@@ -6816,6 +6853,7 @@ STR16 szUDBGenWeaponsStatsExplanationsTooltipText[]=
|
||||
L"\n \nDetermines whether bullets fired by\nthis gun will stray far from where\nit is pointed.\n \nScale: 0-100.\nHigher is better.",
|
||||
L"\n \nDetermines the average amount of damage done\nby bullets fired from this weapon, before\ntaking into account armor or armor-penetration.\n \nHigher is better.",
|
||||
L"\n \nThe maximum distance (in tiles) that\nbullets fired from this gun will travel\nbefore they begin dropping towards the\nground.\n \nHigher is better.",
|
||||
L"\n \nDetermines the difficulty of holding and firing\nthis gun.\n \nHigher Handling Difficulty results in lower\nchance-to-hit - when aimed and especially when\nunaimed.\n \nLower is better.",
|
||||
L"\n \nThis is the number of Extra Aiming\nLevels you can add when aiming this gun.\n \nThe FEWER aiming levels are allowed, the MORE\nbonus each aiming level gives you. Therefore,\nhaving FEWER levels makes the gun faster to aim,\nwithout making it any less accurate.\n \nLower is better.",
|
||||
L"\n \nWhen greater than 1.0, will proportionally reduce\naiming errors at a distance.\n \nRemember that high scope magnification is detrimental\nwhen the target is too close!\n \nA value of 1.0 means no scope is installed.",
|
||||
L"\n \nProportionally reduces aiming errors at a distance.\n \nThis effect works up to a given distance,\nthen begins to dissipate and eventually\ndisappears at sufficient range.\n \nHigher is better.",
|
||||
@@ -6825,15 +6863,14 @@ STR16 szUDBGenWeaponsStatsExplanationsTooltipText[]=
|
||||
L"\n \nDetermines how difficult it is to repair this weapon.\n \nHigher is better.",
|
||||
L"\n \nThe minimum range at which a scope can provide it's aimBonus.",
|
||||
L"\n \nTo hit modifier granted by laser sights.",
|
||||
L"", // (12)
|
||||
L"\n \nThe number of APs required to bring this\nweapon up to firing stance.\n \nOnce the weapon is raised, you may fire repeatedly\nwithout paying this cost again.\n \nA weapon is automatically 'Unreadied' if its\nwielder performs any action other than\nfiring or turning.\n \nLower is better.",
|
||||
L"\n \nThe number of APs required to perform\na single attack with this weapon.\n \nFor guns, this is the cost of firing\na single shot without extra aiming.\n \nIf this icon is greyed-out, single-shots\n are not possible with this weapon.\n \nLower is better.",
|
||||
L"\n \nThe number of APs required to fire\na burst.\n \nThe number of bullets fired in each burst is\ndetermined by the weapon itself, and indicated\nby the number of bullets shown on this icon.\n \nIf this icon is greyed-out, burst fire\nis not possible with this weapon.\n \nLower is better.",
|
||||
L"\n \nThe number of APs required to fire\nan Autofire Volley of three bullets.\n \nIf you wish to fire more than 3 bullets,\nyou will need to pay extra APs.\n \nIf this icon is greyed-out, autofire\nis not possible with this weapon.\n \nLower is better.",
|
||||
L"\n \nThe number of APs required to reload\nthis weapon.\n \nLower is better.",
|
||||
L"\n \nThe number of APs required to rechamber this weapon\nbetween each and every shot fired.\n \nLower is better.",
|
||||
L"\n \nThe distance this weapon's muzzle will shift\nhorizontally between each and every bullet in a\nburst or autofire volley.\n \nPositive numbers indicate shifting to the right.\nNegative numbers indicate shifting to the left.\n \nCloser to 0 is better.",
|
||||
L"\n \nThe distance this weapon's muzzle will shift\nvertically between each and every bullet in a\nburst or autofire volley.\n \nPositive numbers indicate shifting upwards.\nNegative numbers indicate shifting downwards.\n \nCloser to 0 is better.",
|
||||
L"\n \nThe distance this weapon's muzzle will shift\nhorizontally between each and every bullet in a\nburst or autofire volley.\n \nPositive numbers indicate shifting to the right.\nNegative numbers indicate shifting to the left.\n \nCloser to 0 is better.", // No longer used
|
||||
L"\n \nThe total distance this weapon's muzzle will shift\nbetween each and every bullet in a burst or\nautofire volley, if no Counter Force is applied.\n \nLower is better.", // HEADROCK HAM 5: Altered to reflect unified number.
|
||||
L"\n \nIndicates the number of bullets that will be added\nto an autofire volley for every extra 5 APs\nyou spend.\n \nHigher is better.",
|
||||
};
|
||||
|
||||
@@ -6871,6 +6908,7 @@ STR16 szUDBGenExplosiveStatsTooltipText[]=
|
||||
{
|
||||
L"|D|a|m|a|g|e",
|
||||
L"|S|t|u|n |D|a|m|a|g|e",
|
||||
L"|E|x|p|l|o|d|e|s |o|n| |I|m|p|a|c|t", // HEADROCK HAM 5
|
||||
L"|B|l|a|s|t |R|a|d|i|u|s",
|
||||
L"|S|t|u|n |B|l|a|s|t |R|a|d|i|u|s",
|
||||
L"|N|o|i|s|e |B|l|a|s|t |R|a|d|i|u|s",
|
||||
@@ -6885,6 +6923,11 @@ STR16 szUDBGenExplosiveStatsTooltipText[]=
|
||||
L"|S|m|o|k|e |E|n|d |R|a|d|i|u|s",
|
||||
L"|I|n|c|e|n|d|i|a|r|y |E|n|d |R|a|d|i|u|s",
|
||||
L"|E|f|f|e|c|t |D|u|r|a|t|i|o|n",
|
||||
// HEADROCK HAM 5: Fragmentation
|
||||
L"|N|u|m|b|e|r |o|f |F|r|a|g|m|e|n|t|s",
|
||||
L"|D|a|m|a|g|e |p|e|r |F|r|a|g|m|e|n|t",
|
||||
L"|F|r|a|g|m|e|n|t |R|a|n|g|e",
|
||||
// HEADROCK HAM 5: End Fragmentations
|
||||
L"|L|o|u|d|n|e|s|s",
|
||||
L"|V|o|l|a|t|i|l|i|t|y",
|
||||
};
|
||||
@@ -6893,6 +6936,7 @@ STR16 szUDBGenExplosiveStatsExplanationsTooltipText[]=
|
||||
{
|
||||
L"\n \nThe amount of damage caused by this explosive.\n \nNote that blast-type explosives deliver this damage\nonly once (when they go off), while prolonged effect\nexplosives deliver this amount of damage every turn until the\neffect dissipates.\n \nHigher is better.",
|
||||
L"\n \nThe amount of non-lethal (stun) damage caused\nby this explosive.\n \nNote that blast-type explosives deliver their damage\nonly once (when they go off), while prolonged effect\nexplosives deliver this amount of stun damage every\nturn until the effect dissipates.\n \nHigher is better.",
|
||||
L"\n \nThis explosive will not bounce around -\nit will explode as soon as it hits any obstacle.", // HEADROCK HAM 5
|
||||
L"\n \nThis is the radius of the explosive blast caused by\nthis explosive item.\n \nTargets will suffer less damage the further they are\nfrom the center of the explosion.\n \nHigher is better.",
|
||||
L"\n \nThis is the radius of the stun-blast caused by\nthis explosive item.\n \nTargets will suffer less damage the further they are\nfrom the center of the blast.\n \nHigher is better.",
|
||||
L"\n \nThis is the distance that the noise from this\ntrap will travel. Soldiers within this distance\nare likely to hear the noise and be alerted.\n \nHigher is better.",
|
||||
@@ -6907,8 +6951,14 @@ STR16 szUDBGenExplosiveStatsExplanationsTooltipText[]=
|
||||
L"\n \nThis is the final radius of the smoke released\nby this explosive item before it dissipates.\n \nEnemies caught within the radius will suffer\nthe listed damage and stun-damage each turn\n(if any), unless wearing a gas mask. More importantly,\nanyone inside the cloud becomes extremely difficult to spot,\nand also loses a large chunk of sight-range themselves.\n \nAlso note the start radius and duration\nof the effect.\n \nHigher is better.",
|
||||
L"\n \nThis is the final radius of the flames caused\nby this explosive item before they dissipate.\n \nEnemies caught within the radius will suffer\nthe listed damage and stun-damage each turn.\n \nAlso note the start radius and duration of the effect.\n \nHigher is better.",
|
||||
L"\n \nThis is the duration of the explosive effect.\n \nEach turn, the radius of the effect will grow by\none tile in every direction, until reaching\nthe listed End Radius.\n \nOnce the duration has been reached, the effect\ndissipates completely.\n \nNote that light-type explosives become SMALLER\nover time, unlike other effects.\n \nHigher is better.",
|
||||
// HEADROCK HAM 5: Fragmentation
|
||||
L"\n \nThis is the number of fragments that will\nbe ejected from the explosion.\n \nFragments are similar to bullets, and may hit\nanyone who's close enough to the explosion.\n \nHigher is better.",
|
||||
L"\n \nThe potential amount of damage caused by each\nfragment ejected from the explosion.\n \nHigher is better.",
|
||||
L"\n \nThis is the average range to which fragments\nfrom this explosion will fly.\n \nSome fragments may end up further away, or fail\nto cover the distance altogether.\n \nHigher is better.",
|
||||
// HEADROCK HAM 5: End Fragmentations
|
||||
L"\n \nThis is the distance (in Tiles) within which\nsoldiers and mercs will hear the explosion when\nit goes off.\n \nEnemies hearing the explosion will be alerted to your\npresence.\n \nLower is better.",
|
||||
L"\n \nThis value represents a chance (out of 100) for this\nexplosive to spontaneously explode whenever it is damaged\n(for instance, when other explosions go off nearby).\n \nCarrying highly-volatile explosives into combat\nis therefore extremely risky and should be avoided.\n \nScale: 0-100.\nLower is better.",
|
||||
|
||||
};
|
||||
|
||||
STR16 szUDBGenSecondaryStatsTooltipText[]=
|
||||
@@ -7025,10 +7075,10 @@ STR16 szUDBAdvStatsTooltipText[]=
|
||||
L"|C|o|o|l|d|o|w|n |F|a|c|t|o|r",
|
||||
L"|J|a|m |T|r|e|s|h|o|l|d",
|
||||
L"|D|a|m|a|g|e |T|r|e|s|h|o|l|d",
|
||||
L"|T|e|m|p|e|r|a|t|u|r|e |M|o|d|i|f|i|c|a|t|o|r",
|
||||
L"|C|o|o|l|d|o|w|n |M|o|d|i|f|i|c|a|t|o|r",
|
||||
L"|J|a|m |T|r|e|s|h|o|l|d |M|o|d|i|f|i|c|a|t|o|r",
|
||||
L"|D|a|m|a|g|e |T|r|e|s|h|o|l|d |M|o|d|i|f|i|c|a|t|o|r",
|
||||
L"|T|e|m|p|e|r|a|t|u|r|e |M|o|d|i|f|i|e|r",
|
||||
L"|C|o|o|l|d|o|w|n |M|o|d|i|f|i|e|r",
|
||||
L"|J|a|m |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
|
||||
L"|D|a|m|a|g|e |T|h|r|e|s|h|o|l|d |M|o|d|i|f|i|e|r",
|
||||
};
|
||||
|
||||
// Alternate tooltip text for weapon Advanced Stats. Just different wording, nothing spectacular.
|
||||
@@ -7158,6 +7208,29 @@ STR16 gzNCTHlabels[]=
|
||||
// HEADROCK HAM 4: End new UDB texts and tooltips
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
// HEADROCK HAM 5: Screen messages for sector inventory sorting reports.
|
||||
STR16 gzMapInventorySortingMessage[] =
|
||||
{
|
||||
L"Finished sorting ammo into crates in sector %c%d.",
|
||||
L"Finished removing attachments from items in sector %c%d.",
|
||||
L"Finished ejecting ammo from weapons in sector %c%d.",
|
||||
L"Finished stacking and merging all items in sector %c%d.",
|
||||
};
|
||||
|
||||
STR16 gzMapInventoryFilterOptions[] =
|
||||
{
|
||||
L"Show all",
|
||||
L"Guns",
|
||||
L"Ammo",
|
||||
L"Explosives",
|
||||
L"Melee Weapons",
|
||||
L"Armor",
|
||||
L"LBE",
|
||||
L"Kits",
|
||||
L"Misc. Items",
|
||||
L"Hide all",
|
||||
};
|
||||
|
||||
// Flugente FTW 1: Temperature-based text similar to HAM 4's condition-based text.
|
||||
STR16 gTemperatureDesc[] =
|
||||
{
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
#ifndef POPUP_CALLBACK_CLASS
|
||||
#define POPUP_CALLBACK_CLASS
|
||||
|
||||
#include "sgp.h"
|
||||
|
||||
class popupCallback;
|
||||
|
||||
template <typename R, typename P1> class popupCallbackFunction;
|
||||
template <typename R, typename P1, typename P2> class popupCallbackFunction2;
|
||||
|
||||
class popupCallback{
|
||||
public:
|
||||
@@ -14,6 +17,172 @@
|
||||
virtual bool call(void) = 0;
|
||||
};
|
||||
|
||||
// returns something, takes three parameters
|
||||
|
||||
template<typename R,typename P1,typename P2,typename P3>
|
||||
class popupCallbackFunction3: public popupCallback{
|
||||
protected:
|
||||
R (*fun)(P1,P2,P3);
|
||||
P1 param_1;
|
||||
P2 param_2;
|
||||
P3 param_3;
|
||||
public:
|
||||
popupCallbackFunction3(void);
|
||||
popupCallbackFunction3(void * newFun, P1 param, P2 param2, P3 param3);
|
||||
virtual void bind(void * newFun);
|
||||
virtual bool call(void);
|
||||
};
|
||||
|
||||
template<typename R,typename P1,typename P2,typename P3>
|
||||
popupCallbackFunction3<R,P1,P2,P3>::popupCallbackFunction3(void){
|
||||
this->fun = 0;
|
||||
this->param_1 = P1();
|
||||
this->param_2 = P2();
|
||||
this->param_3 = P3();
|
||||
};
|
||||
|
||||
template<typename R,typename P1,typename P2,typename P3>
|
||||
popupCallbackFunction3<R,P1,P2,P3>::popupCallbackFunction3(void * newFun, P1 param, P2 param2, P3 param3){
|
||||
this->fun = static_cast< R(*)(P1,P2,P3)>(newFun);
|
||||
this->param_1 = param;
|
||||
this->param_2 = param2;
|
||||
this->param_3 = param3;
|
||||
};
|
||||
|
||||
template<typename R,typename P1,typename P2,typename P3>
|
||||
void popupCallbackFunction3<R,P1,P2,P3>::bind(void * newFun){
|
||||
this->fun = static_cast< R(*)(P1,P2,P3)>(newFun);
|
||||
};
|
||||
|
||||
template<typename R,typename P1,typename P2,typename P3>
|
||||
bool popupCallbackFunction3<R,P1,P2,P3>::call(void){
|
||||
return (bool)(this->fun)(this->param_1,this->param_2,this->param_3);
|
||||
};
|
||||
|
||||
// three params, no return val
|
||||
|
||||
template<typename P1,typename P2,typename P3>
|
||||
class popupCallbackFunction3<void,typename P1,typename P2,typename P3>: public popupCallback{
|
||||
protected:
|
||||
void (*fun)(P1,P2,P3);
|
||||
P1 param_1;
|
||||
P2 param_2;
|
||||
P3 param_3;
|
||||
public:
|
||||
popupCallbackFunction3(void);
|
||||
popupCallbackFunction3(void * newFun, P1 param, P2 param2, P3 param3);
|
||||
virtual void bind(void * newFun);
|
||||
virtual bool call(void);
|
||||
};
|
||||
|
||||
template<typename P1,typename P2,typename P3>
|
||||
popupCallbackFunction3<void,P1,P2,P3>::popupCallbackFunction3(void){
|
||||
this->fun = 0;
|
||||
this->param_1 = P1();
|
||||
this->param_2 = P2();
|
||||
this->param_3 = P3();
|
||||
};
|
||||
|
||||
template<typename P1,typename P2,typename P3>
|
||||
popupCallbackFunction3<void,P1,P2,P3>::popupCallbackFunction3(void * newFun, P1 param, P2 param2, P3 param3){
|
||||
this->fun = static_cast< void(*)(P1,P2,P3)>(newFun);
|
||||
this->param_1 = param;
|
||||
this->param_2 = param2;
|
||||
this->param_3 = param3;
|
||||
};
|
||||
|
||||
template<typename P1,typename P2,typename P3>
|
||||
void popupCallbackFunction3<void,P1,P2,P3>::bind(void * newFun){
|
||||
this->fun = static_cast< void(*)(P1,P2,P3)>(newFun);
|
||||
};
|
||||
|
||||
template<typename P1,typename P2,typename P3>
|
||||
bool popupCallbackFunction3<void,P1,P2,P3>::call(void){
|
||||
(this->fun)(this->param_1,this->param_2,this->param_3);
|
||||
return 1;
|
||||
};
|
||||
|
||||
// returns something, takes two parameters
|
||||
|
||||
template<typename R,typename P1,typename P2>
|
||||
class popupCallbackFunction2: public popupCallback{
|
||||
protected:
|
||||
R (*fun)(P1,P2);
|
||||
P1 param_1;
|
||||
P2 param_2;
|
||||
public:
|
||||
popupCallbackFunction2(void);
|
||||
popupCallbackFunction2(void * newFun, P1 param, P2 param2);
|
||||
virtual void bind(void * newFun);
|
||||
virtual bool call(void);
|
||||
};
|
||||
|
||||
template<typename R,typename P1,typename P2>
|
||||
popupCallbackFunction2<R,P1,P2>::popupCallbackFunction2(void){
|
||||
this->fun = 0;
|
||||
this->param_1 = P1();
|
||||
this->param_2 = P2();
|
||||
};
|
||||
|
||||
template<typename R,typename P1,typename P2>
|
||||
popupCallbackFunction2<R,P1,P2>::popupCallbackFunction2(void * newFun, P1 param, P2 param2){
|
||||
this->fun = static_cast< R(*)(P1,P2)>(newFun);
|
||||
this->param_1 = param;
|
||||
this->param_2 = param2;
|
||||
};
|
||||
|
||||
template<typename R,typename P1,typename P2>
|
||||
void popupCallbackFunction2<R,P1,P2>::bind(void * newFun){
|
||||
this->fun = static_cast< R(*)(P1,P2)>(newFun);
|
||||
};
|
||||
|
||||
template<typename R,typename P1,typename P2>
|
||||
bool popupCallbackFunction2<R,P1,P2>::call(void){
|
||||
return (bool)(this->fun)(this->param_1,this->param_2);
|
||||
};
|
||||
|
||||
// two params, no return val
|
||||
|
||||
template<typename P1,typename P2>
|
||||
class popupCallbackFunction2<void, typename P1,typename P2>: public popupCallback{
|
||||
protected:
|
||||
void (*fun)(P1,P2);
|
||||
P1 param_1;
|
||||
P2 param_2;
|
||||
public:
|
||||
popupCallbackFunction2(void);
|
||||
popupCallbackFunction2(void * newFun, P1 param, P2 param2);
|
||||
virtual void bind(void * newFun);
|
||||
virtual bool call(void);
|
||||
};
|
||||
|
||||
template<typename P1,typename P2>
|
||||
popupCallbackFunction2<void,P1,P2>::popupCallbackFunction2(void){
|
||||
this->fun = 0;
|
||||
this->param_1 = P1();
|
||||
this->param_2 = P2();
|
||||
};
|
||||
|
||||
template<typename P1,typename P2>
|
||||
popupCallbackFunction2<void,P1,P2>::popupCallbackFunction2(void * newFun, P1 param, P2 param2){
|
||||
this->fun = static_cast< void(*)(P1,P2)>(newFun);
|
||||
this->param_1 = param;
|
||||
this->param_2 = param2;
|
||||
};
|
||||
|
||||
template<typename P1,typename P2>
|
||||
void popupCallbackFunction2<void,P1,P2>::bind(void * newFun){
|
||||
this->fun = static_cast< void(*)(P1,P2)>(newFun);
|
||||
};
|
||||
|
||||
template<typename P1,typename P2>
|
||||
bool popupCallbackFunction2<void,P1,P2>::call(void){
|
||||
(this->fun)(this->param_1,this->param_2);
|
||||
return 1;
|
||||
};
|
||||
|
||||
// returns something, takes one parameter
|
||||
|
||||
template <typename R, typename P1>
|
||||
class popupCallbackFunction : public popupCallback{
|
||||
protected:
|
||||
|
||||
+222
-23
@@ -119,6 +119,18 @@ POPUP_OPTION::POPUP_OPTION(void)
|
||||
this->action = 0;
|
||||
this->avail = 0;
|
||||
this->hover = 0;
|
||||
|
||||
// set highlight color
|
||||
this->color_highlight = FONT_WHITE;
|
||||
|
||||
// unhighlighted color
|
||||
this->color_foreground = FONT_LTGREEN;
|
||||
|
||||
// background color
|
||||
this->color_background = FONT_BLACK;
|
||||
|
||||
// shaded color..for darkened text
|
||||
this->color_shade = FONT_GRAY7 ;
|
||||
}
|
||||
|
||||
POPUP_OPTION::~POPUP_OPTION(void)
|
||||
@@ -136,11 +148,23 @@ POPUP_OPTION::POPUP_OPTION(std::wstring *newName, popupCallback * newFunction)
|
||||
this->action = newFunction;
|
||||
this->avail = 0;
|
||||
this->hover = 0;
|
||||
|
||||
// set highlight color
|
||||
this->color_highlight = FONT_WHITE;
|
||||
|
||||
// unhighlighted color
|
||||
this->color_foreground = FONT_LTGREEN;
|
||||
|
||||
// background color
|
||||
this->color_background = FONT_BLACK;
|
||||
|
||||
// shaded color..for darkened text
|
||||
this->color_shade = FONT_GRAY7 ;
|
||||
}
|
||||
|
||||
BOOLEAN POPUP_OPTION::setName( WCHAR* newName )
|
||||
BOOLEAN POPUP_OPTION::setName( std::wstring * newName )
|
||||
{
|
||||
this->name = newName;
|
||||
this->name = *newName;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -170,6 +194,8 @@ BOOLEAN POPUP_OPTION::checkAvailability()
|
||||
{
|
||||
if (this->avail != 0)
|
||||
return ( this->avail->call() == true );
|
||||
else if ( this->action == 0 ) // options with no action are always shaded
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
@@ -211,12 +237,19 @@ BOOLEAN POPUP_OPTION::forceRun()
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
// constructor
|
||||
POPUP_SUB_POPUP_OPTION::POPUP_SUB_POPUP_OPTION(void) : POPUP_OPTION()
|
||||
POPUP_SUB_POPUP_OPTION::POPUP_SUB_POPUP_OPTION(void) : POPUP_OPTION(new wstring(L"Unnamed subPopup"),NULL) //TODO: possible memmory leak!
|
||||
{
|
||||
this->parent = NULL;
|
||||
this->initSubPopup();
|
||||
}
|
||||
|
||||
POPUP_SUB_POPUP_OPTION::POPUP_SUB_POPUP_OPTION(wstring* newName, const POPUP * parent) : POPUP_OPTION(newName, 0)
|
||||
POPUP_SUB_POPUP_OPTION::POPUP_SUB_POPUP_OPTION(wstring* name) : POPUP_OPTION(name, NULL)
|
||||
{
|
||||
this->parent = NULL;
|
||||
this->initSubPopup();
|
||||
}
|
||||
|
||||
POPUP_SUB_POPUP_OPTION::POPUP_SUB_POPUP_OPTION(wstring* newName, const POPUP * parent) : POPUP_OPTION(newName, NULL)
|
||||
{
|
||||
this->parent = parent;
|
||||
this->initSubPopup();
|
||||
@@ -230,10 +263,13 @@ POPUP_SUB_POPUP_OPTION::~POPUP_SUB_POPUP_OPTION(void)
|
||||
|
||||
void POPUP_SUB_POPUP_OPTION::showPopup()
|
||||
{
|
||||
// check if it's available at this time
|
||||
if ( this->checkAvailability() )
|
||||
// check if it's available at this time, if there is an avail function set
|
||||
if ( !this->AvailabilityFunctionSet() || this->checkAvailability() )
|
||||
{
|
||||
if (!this->customPositionSet) this->positionSubPopup();
|
||||
if (!this->customPositionSet || this->customRule == POPUP_POSITION_RELATIVE) {
|
||||
this->positionSubPopup();
|
||||
}
|
||||
|
||||
this->subPopup->show();
|
||||
}
|
||||
}
|
||||
@@ -247,10 +283,14 @@ void POPUP_SUB_POPUP_OPTION::positionSubPopup()
|
||||
{
|
||||
INT16 x,y;
|
||||
|
||||
// x = this->parent->Position.iX + this->parent->Dimensions.iLeft + this->parent->Dimensions.iRight + 10;
|
||||
x = this->parent->X + this->parent->Dimensions.iLeft + this->parent->Dimensions.iRight + 10;
|
||||
// y = this->parent->Position.iY + 10;
|
||||
y = this->parent->Y + 10;
|
||||
if( this->customPositionSet )
|
||||
{
|
||||
x = this->parent->X + this->parent->Dimensions.iLeft + this->parent->Dimensions.iRight + this->customX;
|
||||
y = this->parent->Y + this->customY;
|
||||
} else {
|
||||
x = this->parent->X + this->parent->Dimensions.iLeft + this->parent->Dimensions.iRight + 10;
|
||||
y = this->parent->Y + 10;
|
||||
}
|
||||
|
||||
this->subPopup->setPosition(x,y);
|
||||
}
|
||||
@@ -263,20 +303,62 @@ BOOLEAN POPUP_SUB_POPUP_OPTION::run()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN POPUP_SUB_POPUP_OPTION::setPopupPosition(UINT16 x, UINT16 y, UINT8 positioningRule){
|
||||
BOOLEAN POPUP_SUB_POPUP_OPTION::setPopupPosition(UINT16 x, UINT16 y, INT8 positioningRule){
|
||||
this->customPositionSet = true;
|
||||
|
||||
if (positioningRule != POPUP_POSITION_RELATIVE){
|
||||
return this->subPopup->setPosition(x,y,positioningRule);
|
||||
} else {
|
||||
return this->subPopup->setPosition(this->parent->X + x, this->parent->Y + y,POPUP_POSITION_TOP_LEFT);
|
||||
this->customX = x;
|
||||
this->customY = y;
|
||||
this->customRule = positioningRule;
|
||||
return this->subPopup->setPosition(this->parent->X + this->parent->Dimensions.iRight + x, this->parent->Y + y,POPUP_POSITION_TOP_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void shadeOpenSubPopup( POPUP_SUB_POPUP_OPTION * opt ){
|
||||
// make the option yellow while its open
|
||||
SetCurrentBox( opt->parent->getBoxId() );
|
||||
SetStringForeground( opt->stringHandle, FONT_YELLOW);
|
||||
}
|
||||
|
||||
extern void RenderTeamRegionBackground();
|
||||
static void unShadeOpenSubPopup( POPUP_SUB_POPUP_OPTION * opt ){
|
||||
// restore the option's color
|
||||
SetCurrentBox( opt->parent->getBoxId() );
|
||||
SetStringForeground( opt->stringHandle, FONT_LTGREEN);
|
||||
|
||||
// if in mapscreen, redraw the UI
|
||||
if( guiCurrentScreen == MAP_SCREEN ){
|
||||
fTeamPanelDirty = TRUE;
|
||||
fMapPanelDirty = TRUE;
|
||||
RenderTeamRegionBackground();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void POPUP_SUB_POPUP_OPTION::initSubPopup()
|
||||
{
|
||||
this->subPopup = new POPUP( (CHAR*) wstring(this->name).c_str() );
|
||||
this->subPopup->setCallback(POPUP_CALLBACK_SHOW,new popupCallbackFunction<void,POPUP_SUB_POPUP_OPTION*>( &shadeOpenSubPopup, this ));
|
||||
this->subPopup->setCallback(POPUP_CALLBACK_HIDE,new popupCallbackFunction<void,POPUP_SUB_POPUP_OPTION*>( &unShadeOpenSubPopup, this ));
|
||||
|
||||
this->customPositionSet = false;
|
||||
|
||||
// set highlight color
|
||||
this->color_highlight = FONT_WHITE;
|
||||
|
||||
// unhighlighted color
|
||||
this->color_foreground = FONT_LTGREEN;
|
||||
|
||||
// background color
|
||||
this->color_background = FONT_BLACK;
|
||||
|
||||
// shaded color..for darkened text
|
||||
this->color_shade = FONT_GRAY7 ;
|
||||
}
|
||||
|
||||
void POPUP_SUB_POPUP_OPTION::destroySubPopup()
|
||||
@@ -508,7 +590,7 @@ BOOLEAN POPUP::addOption(POPUP_OPTION &option)
|
||||
if (this->optionCount < POPUP_MAX_OPTIONS)
|
||||
{
|
||||
this->options.push_back( &option );
|
||||
optionCount++;
|
||||
this->optionCount++;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
@@ -536,6 +618,19 @@ POPUP * POPUP::addSubMenuOption(wstring * name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL POPUP::addSubMenuOption( POPUP_SUB_POPUP_OPTION* sub )
|
||||
{
|
||||
if (this->subPopupOptionCount < POPUP_MAX_SUB_POPUPS)
|
||||
{
|
||||
sub->parent = this;
|
||||
this->subPopupOptions.push_back( sub );
|
||||
this->subPopupOptionCount++;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
POPUP_SUB_POPUP_OPTION * POPUP::getSubPopupOption(UINT8 n)
|
||||
{
|
||||
if (n < this->subPopupOptions.size() && this->subPopupOptions[n])
|
||||
@@ -544,6 +639,59 @@ POPUP_SUB_POPUP_OPTION * POPUP::getSubPopupOption(UINT8 n)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void POPUP::recalculateWidth(void){
|
||||
|
||||
this->Dimensions.iRight = this->getCurrentWidth();
|
||||
|
||||
}
|
||||
|
||||
INT16 POPUP::getCurrentWidth(void){
|
||||
INT16 longestString = 0, longestStringTmp;
|
||||
|
||||
CHAR16 sString[ 128 ];
|
||||
|
||||
if (this->subPopupOptionCount > 0)
|
||||
|
||||
for(std::vector<POPUP_SUB_POPUP_OPTION*>::iterator cOption=this->subPopupOptions.begin(); cOption != this->subPopupOptions.end(); ++cOption)
|
||||
{
|
||||
swprintf( sString, (*cOption)->name.c_str() );
|
||||
longestStringTmp = StringPixLength( sString, MAP_SCREEN_FONT);
|
||||
if( longestString < longestStringTmp ) longestString = longestStringTmp;
|
||||
}
|
||||
|
||||
if (this->optionCount > 0)
|
||||
for(std::vector<POPUP_OPTION*>::iterator cOption=this->options.begin(); cOption != this->options.end(); ++cOption)
|
||||
{
|
||||
swprintf( sString, (*cOption)->name.c_str() );
|
||||
longestStringTmp = StringPixLength( sString, MAP_SCREEN_FONT);
|
||||
if( longestString < longestStringTmp ) longestString = longestStringTmp;
|
||||
}
|
||||
|
||||
return longestString + 10; // 10+ marginLeft(6) + marginRight(4)
|
||||
}
|
||||
|
||||
INT16 POPUP::getCurrentHeight(void){
|
||||
|
||||
// linespace = 2; margin = 6+4
|
||||
return ( this->optionCount + this->subPopupOptionCount ) * ( GetFontHeight(MAP_SCREEN_FONT) + 2 ) +10;
|
||||
|
||||
}
|
||||
|
||||
SGPRect POPUP::getBoxDimensions(){
|
||||
SGPRect tmp;
|
||||
|
||||
GetBoxSize( this->boxId, &tmp );
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
SGPPoint POPUP::getBoxPosition(){
|
||||
SGPPoint tmp;
|
||||
|
||||
GetBoxPosition( this->boxId, &tmp );
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
BOOLEAN POPUP::setPosition(UINT16 x, UINT16 y, UINT8 positioningRule )
|
||||
{
|
||||
@@ -616,6 +764,10 @@ BOOLEAN POPUP::show()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void POPUP::hideAfter(){
|
||||
this->hideAfterRun = TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN POPUP::hide()
|
||||
{
|
||||
if (!this->PopupVisible) {
|
||||
@@ -659,12 +811,22 @@ BOOLEAN POPUP::hide()
|
||||
|
||||
BOOLEAN POPUP::callOption(int optIndex)
|
||||
{
|
||||
this->hideAfterRun = FALSE;
|
||||
|
||||
if ( this->optionCount > 0
|
||||
&& optIndex < 32
|
||||
&& optIndex < POPUP_MAX_OPTIONS
|
||||
&& optIndex < optionCount
|
||||
&& optIndex >= 0)
|
||||
{
|
||||
return this->options[optIndex]->run();
|
||||
BOOLEAN callbackStatus = this->options[optIndex]->run();
|
||||
|
||||
if(!this->hideAfterRun)
|
||||
{
|
||||
return callbackStatus;
|
||||
} else
|
||||
{
|
||||
return this->hide();
|
||||
}
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
@@ -857,6 +1019,8 @@ void POPUP::AddSubPopupStrings()
|
||||
|
||||
// make sure it is unhighlighted
|
||||
UnHighLightLine(hStringHandle);
|
||||
// update options string handle for setting colors
|
||||
(*cOption)->stringHandle = hStringHandle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -874,12 +1038,15 @@ void POPUP::AddOptionStrings()
|
||||
|
||||
// make sure it is unhighlighted
|
||||
UnHighLightLine(hStringHandle);
|
||||
// update options string handle for setting colors
|
||||
(*cOption)->stringHandle = hStringHandle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void POPUP::UpdateTextProperties()
|
||||
{
|
||||
|
||||
// set font type
|
||||
SetBoxFont(this->boxId, MAP_SCREEN_FONT);
|
||||
|
||||
@@ -895,9 +1062,30 @@ void POPUP::UpdateTextProperties()
|
||||
// shaded color..for darkened text
|
||||
SetBoxShade( this->boxId, FONT_GRAY7 );
|
||||
|
||||
// is this for the second row ?
|
||||
// alt shaded color
|
||||
SetBoxSecondaryShade( this->boxId, FONT_YELLOW );
|
||||
|
||||
|
||||
if (this->subPopupOptionCount > 0)
|
||||
for(std::vector<POPUP_SUB_POPUP_OPTION*>::iterator cOption=this->subPopupOptions.begin(); cOption != this->subPopupOptions.end(); ++cOption)
|
||||
{
|
||||
SetStringForeground( (*cOption)->stringHandle, (*cOption)->color_foreground);
|
||||
SetStringBackground( (*cOption)->stringHandle, (*cOption)->color_background);
|
||||
SetStringHighLight( (*cOption)->stringHandle, (*cOption)->color_highlight);
|
||||
SetStringShade( (*cOption)->stringHandle, (*cOption)->color_shade);
|
||||
}
|
||||
|
||||
|
||||
if (this->optionCount > 0)
|
||||
for(std::vector<POPUP_OPTION*>::iterator cOption=this->options.begin(); cOption != this->options.end(); ++cOption)
|
||||
{
|
||||
SetStringForeground( (*cOption)->stringHandle, (*cOption)->color_foreground);
|
||||
SetStringBackground( (*cOption)->stringHandle, (*cOption)->color_background);
|
||||
SetStringHighLight( (*cOption)->stringHandle, (*cOption)->color_highlight);
|
||||
SetStringShade( (*cOption)->stringHandle, (*cOption)->color_shade);
|
||||
}
|
||||
|
||||
|
||||
// resize box to text
|
||||
ResizeBoxToText( this->boxId );
|
||||
}
|
||||
@@ -1294,6 +1482,7 @@ void POPUP::MenuBtnCallBack( MOUSE_REGION * pRegion, INT32 iReason )
|
||||
&& iValue >= 0
|
||||
&& this->subPopupOptions[iValue] != NULL)
|
||||
{
|
||||
this->recalculateWidth();
|
||||
this->subPopupOptions[iValue]->run();
|
||||
}
|
||||
}
|
||||
@@ -1349,24 +1538,34 @@ void POPUP::MenuMvtCallBack(MOUSE_REGION * pRegion, INT32 iReason )
|
||||
|
||||
void POPUP::HandleShadingOfLines( void )
|
||||
{
|
||||
UINT8 i = 0;
|
||||
|
||||
// check if valid
|
||||
if( ( this->PopupVisible == FALSE ) || ( this->boxId == - 1 ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//for (i=0; i < this->optionCount; i++)
|
||||
UINT8 i = 0;
|
||||
// subPopups with no options are shaded
|
||||
for(std::vector<POPUP_SUB_POPUP_OPTION*>::iterator cOption=this->subPopupOptions.begin(); cOption != this->subPopupOptions.end(); ++cOption)
|
||||
{
|
||||
if ( (*cOption)->subPopup->optionCount + (*cOption)->subPopup->subPopupOptionCount > 0 )
|
||||
UnShadeStringInBox( this->boxId, i);
|
||||
else
|
||||
ShadeStringInBox( this->boxId, i);
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
// shade strings past the this->subPopupOptionCount offset
|
||||
for(std::vector<POPUP_OPTION*>::iterator cOption=this->options.begin(); cOption != this->options.end(); ++cOption)
|
||||
{
|
||||
if ( (*cOption)->checkAvailability() )
|
||||
UnShadeStringInBox( this->boxId, i+this->subPopupOptionCount); // workaround - sub-popups don't check
|
||||
else // for availability
|
||||
UnShadeStringInBox( this->boxId, i+this->subPopupOptionCount);
|
||||
else
|
||||
ShadeStringInBox( this->boxId, i+this->subPopupOptionCount);
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+31
-12
@@ -1,12 +1,13 @@
|
||||
#ifndef POPUP_CLASS
|
||||
#define POPUP_CLASS
|
||||
|
||||
#include <vector>
|
||||
#include "popup_callback.h"
|
||||
#include "types.h"
|
||||
#include "sgp.h"
|
||||
|
||||
#define MAX_POPUPS 8
|
||||
#define POPUP_MAX_SUB_POPUPS 2
|
||||
#define POPUP_MAX_OPTIONS 32
|
||||
#define MAX_POPUPS 32
|
||||
#define POPUP_MAX_SUB_POPUPS 24
|
||||
#define POPUP_MAX_OPTIONS 96
|
||||
#define MAX_REGIONS_IN_INDEX MAX_POPUPS*POPUP_MAX_OPTIONS*POPUP_MAX_SUB_POPUPS
|
||||
|
||||
#define REGION_SUB_POPUP 1
|
||||
@@ -30,7 +31,7 @@
|
||||
#define POPUP_POSITION_BOTTOM_RIGHT 3 // user defined point (position) is the bottom right corner of the popup
|
||||
#define POPUP_POSITION_BOTTOM_LEFT 4 // user defined point (position) is the bottom left corner of the popup
|
||||
|
||||
#define POPUP_POSITION_RELATIVE 0 // only used for sub-popups, left corner is relative to parent popup's point of origin
|
||||
#define POPUP_POSITION_RELATIVE -1 // only used for sub-popups, left corner is relative to parent popup's point of origin
|
||||
|
||||
class POPUP_OPTION;
|
||||
class POPUP_SUB_POPUP_OPTION;
|
||||
@@ -69,7 +70,7 @@
|
||||
POPUP_OPTION(std::wstring* name, popupCallback* newFunction); // constructor
|
||||
~POPUP_OPTION(); // destructor
|
||||
// setup
|
||||
BOOLEAN setName(WCHAR* name);
|
||||
BOOLEAN setName(std::wstring * name);
|
||||
BOOLEAN setAction(popupCallback*fun);
|
||||
BOOLEAN setAvail(popupCallback *fun);
|
||||
BOOLEAN setHover(popupCallback *fun);
|
||||
@@ -89,6 +90,13 @@
|
||||
popupCallback * action;
|
||||
popupCallback * avail;
|
||||
popupCallback * hover;
|
||||
|
||||
UINT8 color_foreground;
|
||||
UINT8 color_background;
|
||||
UINT8 color_highlight;
|
||||
UINT8 color_shade;
|
||||
|
||||
UINT32 stringHandle;
|
||||
};
|
||||
|
||||
|
||||
@@ -110,12 +118,12 @@
|
||||
void destroySubPopup();
|
||||
void positionSubPopup();
|
||||
|
||||
BOOLEAN setPopupPosition(UINT16 x, UINT16 y, UINT8 positioningRule = POPUP_POSITION_RELATIVE );
|
||||
BOOLEAN setPopupPosition(UINT16 x, UINT16 y, INT8 positioningRule = POPUP_POSITION_RELATIVE );
|
||||
|
||||
BOOLEAN customPositionSet;
|
||||
INT32 customX;
|
||||
INT32 customY;
|
||||
UINT8 customRule;
|
||||
UINT32 customX;
|
||||
UINT32 customY;
|
||||
INT8 customRule;
|
||||
|
||||
POPUP * subPopup;
|
||||
const POPUP * parent;
|
||||
@@ -140,6 +148,7 @@
|
||||
BOOLEAN delOption(UINT8 optIndex);
|
||||
|
||||
POPUP* addSubMenuOption(std::wstring * name);
|
||||
BOOL addSubMenuOption(POPUP_SUB_POPUP_OPTION* sub);
|
||||
/*INT16 findFreeSubMenuOptionIndex();*/
|
||||
POPUP_SUB_POPUP_OPTION * getSubPopupOption(UINT8 n);
|
||||
|
||||
@@ -148,18 +157,26 @@
|
||||
// usage
|
||||
BOOLEAN show(void);
|
||||
BOOLEAN hide(void);
|
||||
void hideAfter(void); // called by options, closes popup after running callback
|
||||
BOOLEAN toggle(void);
|
||||
BOOLEAN refresh(void);
|
||||
BOOLEAN forceDraw(void);
|
||||
BOOLEAN callOption(int optIndex);
|
||||
|
||||
INT32 getBoxId(){
|
||||
INT32 getBoxId() const {
|
||||
return this->boxId;
|
||||
}
|
||||
|
||||
// gets the final dimensions/position of the box, works only after it has been displayed
|
||||
SGPRect getBoxDimensions();
|
||||
SGPPoint getBoxPosition();
|
||||
|
||||
BOOLEAN setCallback(UINT8 type, popupCallback * callback);
|
||||
BOOLEAN isCallbackSet(UINT8 type);
|
||||
void recalculateWidth(void);
|
||||
INT16 getCurrentWidth(void); // calculated the width based on the longest option name
|
||||
|
||||
INT16 getCurrentHeight(void);
|
||||
/////////////////////////
|
||||
// public variables
|
||||
public:
|
||||
@@ -178,6 +195,7 @@
|
||||
void setInitialValues(void);
|
||||
BOOLEAN addToIndex( void );
|
||||
BOOLEAN removeFromIndex( void );
|
||||
BOOLEAN hideAfterRun;
|
||||
|
||||
// Box init functions
|
||||
BOOLEAN CreateDestroyPopUpBoxes(void);
|
||||
@@ -202,6 +220,7 @@
|
||||
void AdjustMouseRegions( void );
|
||||
|
||||
void RepositionMouseRegions( void );
|
||||
|
||||
public:
|
||||
// MSYS Callbacks
|
||||
void MenuMvtCallBack(MOUSE_REGION * pRegion, INT32 iReason );
|
||||
@@ -258,7 +277,7 @@
|
||||
INT32 boxId;
|
||||
|
||||
// which corner of the popup should be aligned with the supplied coordinates ?
|
||||
UINT8 positioningRule;
|
||||
INT8 positioningRule;
|
||||
|
||||
|
||||
// the x,y position of the pop up in tactical
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
#include "popup_class.h"
|
||||
#include "popup_callback.h"
|
||||
#include "sgp.h"
|
||||
|
||||
#include "popup_definition.h"
|
||||
#include "Interface Items.h"
|
||||
|
||||
// for getting psoldier
|
||||
#include "Map Screen Interface.h"
|
||||
#include "Map Screen Interface Map.h"
|
||||
#include "Overhead.h"
|
||||
|
||||
//////////////////////////////////////
|
||||
// popupDef
|
||||
//////////////////////////////////////
|
||||
|
||||
popupDef::popupDef(){}
|
||||
|
||||
popupDef::~popupDef(){
|
||||
for(std::vector<popupDefContent*>::iterator content=this->content.begin(); content != this->content.end(); ++content)
|
||||
{
|
||||
delete *content;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL popupDef::applyToBox(POPUP* popup){
|
||||
for(std::vector<popupDefContent*>::iterator content=this->content.begin(); content != this->content.end(); ++content)
|
||||
{
|
||||
if ( (*content)->addToBox( popup ) != TRUE ) return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL popupDef::addOption(std::wstring* name, UINT16 callbackId, UINT16 availId){
|
||||
// TODO: check for vaid callbacl/avail ID
|
||||
|
||||
this->content.push_back( new popupDefOption(name,callbackId,availId) );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
popupDef * popupDef::addSubPopup(std::wstring* name){
|
||||
|
||||
popupDefSubPopupOption * sub = new popupDefSubPopupOption(name);
|
||||
|
||||
this->content.push_back( sub );
|
||||
|
||||
return sub->getSubDef();
|
||||
}
|
||||
|
||||
BOOL popupDef::addSubPopup(popupDefSubPopupOption* sub){
|
||||
// TODO: add check for max options
|
||||
this->content.push_back( sub );
|
||||
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
BOOL popupDef::addGenerator(UINT16 id){
|
||||
// TODO: check for valid generator id
|
||||
|
||||
this->content.push_back( new popupDefContentGenerator(id) );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
// popupDefContent
|
||||
//////////////////////////////////////
|
||||
|
||||
popupDefContent::popupDefContent(){}
|
||||
popupDefContent::~popupDefContent(){}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
// popupDefOption helpers
|
||||
//////////////////////////////////////
|
||||
|
||||
static BOOL setPopupDefCallback( POPUP_OPTION * opt, UINT16 callbackId ){
|
||||
|
||||
// TODO
|
||||
opt->setAction(NULL);
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
static BOOL setPopupDefAvail( POPUP_OPTION * opt, UINT16 callbackId ){
|
||||
|
||||
// TODO
|
||||
opt->setAvail(NULL);
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// popupDefOption
|
||||
//////////////////////////////////////
|
||||
/* defined in header file
|
||||
popupDefOption::popupDefOption(){}
|
||||
popupDefOption::popupDefOption( std::wstring* name, UINT16 callbackId, UINT16 availId ){}
|
||||
|
||||
~popupDefOption::popupDefOption(){}
|
||||
*/
|
||||
BOOL popupDefOption::addToBox(POPUP * popup){
|
||||
|
||||
POPUP_OPTION * opt = new POPUP_OPTION();
|
||||
|
||||
opt->setName( this->name );
|
||||
if ( !setPopupDefCallback(opt, this->callbackId)
|
||||
|| !setPopupDefAvail(opt, this->availId) )
|
||||
{
|
||||
delete opt;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return popup->addOption(*opt);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
// popupDefSubPopupOption
|
||||
//////////////////////////////////////
|
||||
/* defined in header file
|
||||
popupDefSubPopupOption::popupDefSubPopupOption(){}
|
||||
popupDefSubPopupOption::popupDefSubPopupOption( std::wstring* name ){}
|
||||
|
||||
popupDefSubPopupOption::~popupDefSubPopupOption(){}
|
||||
*/
|
||||
BOOL popupDefSubPopupOption::addToBox(POPUP * popup){
|
||||
|
||||
POPUP_SUB_POPUP_OPTION * sub = new POPUP_SUB_POPUP_OPTION( this->name );
|
||||
|
||||
if( !this->content->applyToBox( sub->subPopup ) ){
|
||||
delete sub;
|
||||
return false;
|
||||
}
|
||||
|
||||
return popup->addSubMenuOption(sub);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
// popupDefContentGenerator helpers
|
||||
//////////////////////////////////////
|
||||
|
||||
/*
|
||||
void addArmorToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addLBEToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addWeaponsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addWeaponGroupsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addGrenadesToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addBombsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addFaceGearToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addAmmoToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
|
||||
void addRifleGrenadesToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addRocketAmmoToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
void addDrugsToPocketPopup( SOLDIERTYPE *pSoldier, INT16 sPocket, POPUP* popup );
|
||||
*/
|
||||
|
||||
static BOOL applyPopupContentGenerator( POPUP * popup, UINT16 generatorId ){
|
||||
|
||||
SOLDIERTYPE *pSoldier;
|
||||
GetSoldier( &pSoldier, gCharactersList[ bSelectedInfoChar ].usSolID );
|
||||
|
||||
switch(generatorId){
|
||||
case popupGenerators::dummy:
|
||||
popup->addOption(new std::wstring( L"Dummy generator" ),NULL);
|
||||
break;
|
||||
|
||||
case popupGenerators::addArmor:
|
||||
addArmorToPocketPopup( pSoldier, gsPocketUnderCursor, popup );
|
||||
break;
|
||||
case popupGenerators::addLBE:
|
||||
addLBEToPocketPopup( pSoldier, gsPocketUnderCursor, popup );
|
||||
break;
|
||||
case popupGenerators::addWeapons:
|
||||
addWeaponsToPocketPopup( pSoldier, gsPocketUnderCursor, popup );
|
||||
break;
|
||||
case popupGenerators::addWeaponGroups:
|
||||
addWeaponGroupsToPocketPopup( pSoldier, gsPocketUnderCursor, popup );
|
||||
break;
|
||||
case popupGenerators::addGrenades:
|
||||
addGrenadesToPocketPopup( pSoldier, gsPocketUnderCursor, popup );
|
||||
break;
|
||||
case popupGenerators::addBombs:
|
||||
addBombsToPocketPopup( pSoldier, gsPocketUnderCursor, popup );
|
||||
break;
|
||||
case popupGenerators::addFaceGear:
|
||||
addFaceGearToPocketPopup( pSoldier, gsPocketUnderCursor, popup );
|
||||
break;
|
||||
case popupGenerators::addAmmo:
|
||||
addAmmoToPocketPopup( pSoldier, gsPocketUnderCursor, popup );
|
||||
break;
|
||||
case popupGenerators::addRifleGrenades:
|
||||
addRifleGrenadesToPocketPopup( pSoldier, gsPocketUnderCursor, popup );
|
||||
break;
|
||||
case popupGenerators::addRocketAmmo:
|
||||
addRocketAmmoToPocketPopup( pSoldier, gsPocketUnderCursor, popup );
|
||||
break;
|
||||
case popupGenerators::addMisc:
|
||||
addMiscToPocketPopup( pSoldier, gsPocketUnderCursor, popup );
|
||||
break;
|
||||
case popupGenerators::addKits:
|
||||
addKitsToPocketPopup( pSoldier, gsPocketUnderCursor, popup );
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
// popupDefContentGenerator
|
||||
//////////////////////////////////////
|
||||
/* defined in header file
|
||||
popupDefContentGenerator::popupDefContentGenerator(){}
|
||||
popupDefContentGenerator::popupDefContentGenerator( UINT16 generatorId ){}
|
||||
|
||||
popupDefContentGenerator::~popupDefContentGenerator(){}
|
||||
*/
|
||||
|
||||
BOOL popupDefContentGenerator::addToBox(POPUP * popup){
|
||||
|
||||
return applyPopupContentGenerator( popup, this->generatorId );
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
#ifndef POPUP_DEFINITION
|
||||
#define POPUP_DEFINITION
|
||||
|
||||
#include "sgp.h"
|
||||
#include "popup_class.h"
|
||||
#include "popup_callback.h"
|
||||
|
||||
namespace popupGenerators{
|
||||
|
||||
enum{
|
||||
dummy = 1,
|
||||
addArmor,
|
||||
addLBE,
|
||||
addWeapons,
|
||||
addWeaponGroups,
|
||||
addGrenades,
|
||||
addBombs,
|
||||
addFaceGear,
|
||||
addAmmo,
|
||||
addRifleGrenades,
|
||||
addRocketAmmo,
|
||||
addMisc,
|
||||
addKits
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
class popupDef;
|
||||
class popupDefContent;
|
||||
|
||||
class popupDefOption;
|
||||
class popupDefSubPopupOption;
|
||||
class popupDefContentGenerator;
|
||||
|
||||
class popupDef{
|
||||
public:
|
||||
popupDef();
|
||||
~popupDef();
|
||||
|
||||
BOOL applyToBox(POPUP* popup);
|
||||
|
||||
BOOL addOption(std::wstring* name, UINT16 callbackId, UINT16 availId);
|
||||
|
||||
popupDef * addSubPopup(std::wstring* name);
|
||||
BOOL addSubPopup(popupDefSubPopupOption* sub);
|
||||
|
||||
BOOL addGenerator(UINT16 id);
|
||||
protected:
|
||||
std::vector<popupDefContent*> content;
|
||||
};
|
||||
|
||||
class popupDefContent{
|
||||
public:
|
||||
popupDefContent();
|
||||
~popupDefContent();
|
||||
|
||||
virtual BOOL addToBox(POPUP * popup) = 0;
|
||||
|
||||
};
|
||||
|
||||
class popupDefOption : public popupDefContent{
|
||||
public:
|
||||
popupDefOption() : name( new std::wstring(L"Unnamed Option") ), callbackId(0), availId(0){};
|
||||
popupDefOption( std::wstring* name, UINT16 callbackId, UINT16 availId ) : name( name ), callbackId(callbackId), availId(availId){};
|
||||
|
||||
~popupDefOption(){ delete this->name; };
|
||||
|
||||
BOOL addToBox(POPUP * popup);
|
||||
|
||||
protected:
|
||||
std::wstring* name;
|
||||
UINT16 callbackId;
|
||||
UINT16 availId;
|
||||
|
||||
};
|
||||
|
||||
class popupDefSubPopupOption : public popupDefContent{
|
||||
public:
|
||||
popupDefSubPopupOption() : name( new std::wstring(L"Unnamed Submenu") ){ this->content = new popupDef(); };
|
||||
popupDefSubPopupOption( std::wstring* name ) : name( name ){ this->content = new popupDef(); };
|
||||
|
||||
~popupDefSubPopupOption(){ delete this->name; delete this->content; };
|
||||
|
||||
BOOL addToBox(POPUP * popup);
|
||||
void rename( std::wstring* name ){
|
||||
delete this->name; // lets just hope nothing else was using this string. TODO: use smart pointer
|
||||
this->name = name;
|
||||
};
|
||||
popupDef * getSubDef(){ return this->content; };
|
||||
|
||||
protected:
|
||||
std::wstring* name;
|
||||
popupDef * content;
|
||||
};
|
||||
|
||||
class popupDefContentGenerator: public popupDefContent{
|
||||
public:
|
||||
popupDefContentGenerator() : generatorId(0){};
|
||||
popupDefContentGenerator( UINT16 generatorId ) : generatorId( generatorId ){};
|
||||
|
||||
~popupDefContentGenerator();
|
||||
|
||||
BOOL addToBox(POPUP * popup);
|
||||
|
||||
protected:
|
||||
UINT16 generatorId;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user