mirror of
https://github.com/1dot13/source.git
synced 2026-09-09 14:46:05 +02:00
*************************
* HAM 3.6 (by Headrock) * ************************* - Info: Needed GameDir files for HAM 3.6 are not committed yet to the SVN GameDir. Will do that in the next few days - For more infos on HAM 3.6 check out: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=244808&page=0&fpart=1 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@3323 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+7
-7
@@ -82,14 +82,13 @@ void ExitBoxing( void )
|
||||
CancelAIAction( pSoldier, TRUE );
|
||||
pSoldier->aiData.bAlertStatus = STATUS_GREEN;
|
||||
pSoldier->aiData.bUnderFire = 0;
|
||||
|
||||
// HEADROCK HAM 3.6: Make sure all boxers' APs have been reset to a reasonable number. Otherwise,
|
||||
// the AI combatant may fail several conditions in subsequent functions, and fail to leave the ring
|
||||
// as a result.
|
||||
if (pSoldier->bActionPoints < (APBPConstants[AP_MAXIMUM]*6)/10)
|
||||
{
|
||||
pSoldier->bActionPoints = (APBPConstants[AP_MAXIMUM]*6)/10;
|
||||
}
|
||||
// the AI combatant may fail several conditions in subsequent functions, and fail to leave the ring
|
||||
// as a result.
|
||||
if (pSoldier->bActionPoints < (APBPConstants[AP_MAXIMUM]*6)/10)
|
||||
{
|
||||
pSoldier->bActionPoints = (APBPConstants[AP_MAXIMUM]*6)/10;
|
||||
}
|
||||
|
||||
// if necessary, revive boxer so he can leave ring
|
||||
if (pSoldier->stats.bLife > 0 && (pSoldier->stats.bLife < OKLIFE || pSoldier->bBreath < OKBREATH ) )
|
||||
@@ -152,6 +151,7 @@ void BoxingPlayerDisqualified( SOLDIERTYPE * pOffender, INT8 bReason )
|
||||
|
||||
void TriggerEndOfBoxingRecord( SOLDIERTYPE * pSoldier )
|
||||
{
|
||||
// This trigger runs once for each boxer, so only when the SECOND boxer gets out will this function run in its entirely.
|
||||
// unlock UI
|
||||
guiPendingOverrideEvent = LU_ENDUILOCK;
|
||||
|
||||
|
||||
+109
-42
@@ -1080,17 +1080,17 @@ UINT16 SubpointsPerPoint(UINT8 ubStat, INT8 bExpLevel)
|
||||
{
|
||||
UINT16 usSubpointsPerPoint;
|
||||
|
||||
UINT16 HEALTH_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.ubHealthSubpointsToImprove;
|
||||
UINT16 STRENGTH_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.ubStrengthSubpointsToImprove;
|
||||
UINT16 DEXTERITY_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.ubDexteritySubpointsToImprove;
|
||||
UINT16 AGILITY_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.ubAgilitySubpointsToImprove;
|
||||
UINT16 WISDOM_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.ubWisdomSubpointsToImprove;
|
||||
UINT16 MARKSMANSHIP_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.ubMarksmanshipSubpointsToImprove;
|
||||
UINT16 MEDICAL_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.ubMedicalSubpointsToImprove;
|
||||
UINT16 MECHANICAL_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.ubMechanicalSubpointsToImprove;
|
||||
UINT16 LEADERSHIP_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.ubLeadershipSubpointsToImprove;
|
||||
UINT16 EXPLOSIVES_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.ubExplosivesSubpointsToImprove;
|
||||
UINT16 LEVEL_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.ubLevelSubpointsToImprove;
|
||||
UINT16 HEALTH_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.usHealthSubpointsToImprove;
|
||||
UINT16 STRENGTH_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.usStrengthSubpointsToImprove;
|
||||
UINT16 DEXTERITY_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.usDexteritySubpointsToImprove;
|
||||
UINT16 AGILITY_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.usAgilitySubpointsToImprove;
|
||||
UINT16 WISDOM_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.usWisdomSubpointsToImprove;
|
||||
UINT16 MARKSMANSHIP_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.usMarksmanshipSubpointsToImprove;
|
||||
UINT16 MEDICAL_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.usMedicalSubpointsToImprove;
|
||||
UINT16 MECHANICAL_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.usMechanicalSubpointsToImprove;
|
||||
UINT16 LEADERSHIP_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.usLeadershipSubpointsToImprove;
|
||||
UINT16 EXPLOSIVES_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.usExplosivesSubpointsToImprove;
|
||||
UINT16 LEVEL_SUBPOINTS_TO_IMPROVE = gGameExternalOptions.usLevelSubpointsToImprove;
|
||||
// figure out how many subpoints this type of stat needs to change
|
||||
switch (ubStat)
|
||||
{
|
||||
@@ -1299,16 +1299,47 @@ UINT8 CurrentPlayerProgressPercentage(void)
|
||||
{
|
||||
UINT32 uiCurrentIncome;
|
||||
UINT32 uiPossibleIncome;
|
||||
UINT8 ubCurrentProgress;
|
||||
UINT8 ubKillsPerPoint;
|
||||
UINT16 usKillsProgress;
|
||||
UINT16 usControlProgress;
|
||||
UINT16 usVisitProgress;
|
||||
// HEADROCK HAM 3: Changed to UINT16 to avoid overflow
|
||||
UINT16 usCurrentProgress;
|
||||
UINT16 ubKillsPerPoint;
|
||||
UINT16 usKillsProgress;
|
||||
UINT16 usControlProgress;
|
||||
UINT16 usVisitProgress;
|
||||
// HEADROCK HAM 3: Added a separate variable for Income Progress,
|
||||
// to enable comparing the results from each progress aspect SEPARATELY.
|
||||
UINT16 usIncomeProgress;
|
||||
// HEADROCK HAM 3: And another variable to contain the highest result so far.
|
||||
UINT16 usHighestProgress;
|
||||
// HEADROCK HAM 3: Four variables to hold the maximum attainable progress from each aspect.
|
||||
UINT16 usMaxKillsProgress;
|
||||
UINT16 usMaxIncomeProgress;
|
||||
UINT16 usMaxControlProgress;
|
||||
UINT16 usMaxVisitProgress;
|
||||
|
||||
|
||||
if( gfEditMode )
|
||||
return 0;
|
||||
|
||||
// HEADROCK HAM 3: If the alternate progress calculation is used, all four INI settings should be set to 100,
|
||||
// otherwise progress cannot ever reach 100...
|
||||
if (gGameExternalOptions.fAlternateProgressCalculation)
|
||||
{
|
||||
usMaxKillsProgress = 100;
|
||||
usMaxIncomeProgress = 100;
|
||||
usMaxControlProgress = 100;
|
||||
usMaxVisitProgress = 100;
|
||||
}
|
||||
// Else, set to INI-read values. Note that the rest of the function now reads these instead of referring
|
||||
// to the long variable names.
|
||||
else
|
||||
{
|
||||
usMaxKillsProgress = gGameExternalOptions.ubGameProgressPortionKills;
|
||||
usMaxIncomeProgress = gGameExternalOptions.ubGameProgressPortionIncome;
|
||||
usMaxControlProgress = gGameExternalOptions.ubGameProgressPortionControl;
|
||||
usMaxVisitProgress = gGameExternalOptions.ubGameProgressPortionVisited;
|
||||
}
|
||||
|
||||
|
||||
// figure out the player's current mine income
|
||||
uiCurrentIncome = PredictIncomeFromPlayerMines();
|
||||
|
||||
@@ -1316,36 +1347,56 @@ UINT8 CurrentPlayerProgressPercentage(void)
|
||||
uiPossibleIncome = CalcMaxPlayerIncomeFromMines();
|
||||
|
||||
// either of these indicates a critical failure of some sort
|
||||
Assert(uiPossibleIncome > 0);
|
||||
Assert(uiCurrentIncome <= uiPossibleIncome);
|
||||
|
||||
// HEADROCK HAM 3.6: No need to assert this. Max Income can potentially be 0 in modded games.
|
||||
// Assert(uiPossibleIncome > 0);
|
||||
|
||||
// HEADROCK HAM 3.6: It is now possible, with the help of facilities,
|
||||
// to make more money from mines than normally possible.
|
||||
// This assertion check is now obsolete.
|
||||
//Assert(uiCurrentIncome <= uiPossibleIncome);
|
||||
uiCurrentIncome = __min(uiPossibleIncome, uiCurrentIncome);
|
||||
|
||||
// for a rough guess as to how well the player is doing,
|
||||
// we'll take the current mine income / potential mine income as a percentage
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// HEADROCK HAM 3
|
||||
// Several changes have been made here to accomodate a new type of progress generation.
|
||||
// With this alternate system, the program determines the current progress from each of the
|
||||
// four aspects SEPARATELY. It then compares all of them, and only the HIGHEST one determines
|
||||
// our current progress. Please note that while some changes have been made, the ORIGINAL
|
||||
// progress control works EXACTLY THE SAME AS IT ALWAYS DID.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Kris: Make sure you don't divide by zero!!!
|
||||
if( uiPossibleIncome > 0)
|
||||
{
|
||||
ubCurrentProgress = (UINT8) ((uiCurrentIncome * gGameExternalOptions.ubGameProgressPortionIncome) / uiPossibleIncome);
|
||||
usIncomeProgress = (UINT8) ((uiCurrentIncome * usMaxIncomeProgress) / uiPossibleIncome);
|
||||
}
|
||||
else
|
||||
{
|
||||
ubCurrentProgress = 0;
|
||||
usIncomeProgress = 0;
|
||||
}
|
||||
|
||||
// kills per point depends on difficulty, and should match the ratios of starting enemy populations (730/1050/1500)
|
||||
// HEADROCK HAM 3: Externalized all four Kills-per-point ratios.
|
||||
switch( gGameOptions.ubDifficultyLevel )
|
||||
{
|
||||
case DIF_LEVEL_EASY:
|
||||
ubKillsPerPoint = 7;
|
||||
ubKillsPerPoint = gGameExternalOptions.usNumKillsPerProgressPointNovice;
|
||||
break;
|
||||
case DIF_LEVEL_MEDIUM:
|
||||
ubKillsPerPoint = 10;
|
||||
ubKillsPerPoint = gGameExternalOptions.usNumKillsPerProgressPointExperienced;
|
||||
break;
|
||||
case DIF_LEVEL_HARD:
|
||||
ubKillsPerPoint = 15;
|
||||
ubKillsPerPoint = gGameExternalOptions.usNumKillsPerProgressPointExpert;
|
||||
break;
|
||||
case DIF_LEVEL_INSANE:
|
||||
ubKillsPerPoint = 60; // Madd - uncertain whether this number is right
|
||||
ubKillsPerPoint = gGameExternalOptions.usNumKillsPerProgressPointInsane;
|
||||
break;
|
||||
default:
|
||||
Assert(FALSE);
|
||||
@@ -1354,43 +1405,60 @@ UINT8 CurrentPlayerProgressPercentage(void)
|
||||
}
|
||||
|
||||
usKillsProgress = gStrategicStatus.usPlayerKills / ubKillsPerPoint;
|
||||
if (usKillsProgress > gGameExternalOptions.ubGameProgressPortionKills)
|
||||
if (usKillsProgress > usMaxKillsProgress)
|
||||
{
|
||||
usKillsProgress = gGameExternalOptions.ubGameProgressPortionKills;
|
||||
usKillsProgress = usMaxKillsProgress;
|
||||
}
|
||||
|
||||
// add kills progress to income progress
|
||||
ubCurrentProgress += usKillsProgress;
|
||||
|
||||
|
||||
// 19 sectors in mining towns + 3 wilderness SAMs each count double. Balime & Meduna are extra and not required
|
||||
// HEADROCK HAM B1: Changed the next line, adding a call to a new function. This allows the weight of Sector
|
||||
// Control to be altered in JA2_OPTIONS.INI (Previously damaged the game's progress if set over 25... So I've
|
||||
// made this MOD-Friendly :D )
|
||||
// BTW, Balime and Meduna _ARE_ required. The function doesn't differentiate! Such carelessness. Tsk tsk tsk.
|
||||
|
||||
usControlProgress = gGameExternalOptions.ubGameProgressPortionControl * CalcImportantSectorControl() / CalcTotalImportantSectors();
|
||||
if (usControlProgress > gGameExternalOptions.ubGameProgressPortionControl)
|
||||
usControlProgress = usMaxControlProgress * CalcImportantSectorControl() / CalcTotalImportantSectors();
|
||||
if (usControlProgress > usMaxControlProgress)
|
||||
{
|
||||
usControlProgress = gGameExternalOptions.ubGameProgressPortionControl;
|
||||
usControlProgress = usMaxControlProgress;
|
||||
}
|
||||
|
||||
// add control progress
|
||||
ubCurrentProgress += usControlProgress;
|
||||
|
||||
// WDS: Adding more ways to progress in the game
|
||||
// Get a ratio of sectors visited to the total number of sectors
|
||||
// HEADROCK HAM B1: Fixed this so it doesn't count sectors that can't be visited. Allows progress to go to
|
||||
// 100 even if the map has some unvisitable sectors (heh, doesn't it always?)
|
||||
usVisitProgress = CountSurfaceSectorsVisited() * gGameExternalOptions.ubGameProgressPortionVisited / TotalVisitableSurfaceSectors();
|
||||
usVisitProgress = CountSurfaceSectorsVisited() * usMaxVisitProgress / TotalVisitableSurfaceSectors();
|
||||
|
||||
// add control progress
|
||||
ubCurrentProgress += usVisitProgress;
|
||||
// HEADROCK HAM 3: This bit is ugly for now, unless someone can optimize it for me.
|
||||
// When the "Alternate Progress Calculation" is activated, the program selects only the HIGHEST of the
|
||||
// progress controls, and sets that to be the current progress, disregarding any advances in the three
|
||||
// other fields.
|
||||
|
||||
return(ubCurrentProgress);
|
||||
if (gGameExternalOptions.fAlternateProgressCalculation)
|
||||
{
|
||||
usHighestProgress = __max(usKillsProgress, usControlProgress);
|
||||
usHighestProgress = __max(usHighestProgress, usIncomeProgress);
|
||||
usHighestProgress = __max(usHighestProgress, usVisitProgress);
|
||||
usCurrentProgress = usHighestProgress;
|
||||
}
|
||||
// Else, add them all up as normal (original progress calculation). This replaces all those lines I removed
|
||||
// above where progress was summed along the way.
|
||||
else
|
||||
{
|
||||
usCurrentProgress = usKillsProgress + usControlProgress + usIncomeProgress + usVisitProgress;
|
||||
}
|
||||
|
||||
// Add a static amount of points, as declared in the INI file.
|
||||
usCurrentProgress += gGameExternalOptions.ubGameProgressIncrement;
|
||||
|
||||
// And failsafes here. I'm not 100% sure about these though: I've never personally seen progress
|
||||
// values go over 100, and I don't think they SHOULD... Can the game handle values > 100? Should it?
|
||||
usCurrentProgress = __min(100, usCurrentProgress);
|
||||
// No less than 0, or the minimum set in the INI file.
|
||||
usCurrentProgress = __max(gGameExternalOptions.ubGameProgressMinimum, __max(0, usCurrentProgress));
|
||||
|
||||
return((UINT8)usCurrentProgress);
|
||||
}
|
||||
|
||||
|
||||
UINT8 HighestPlayerProgressPercentage(void)
|
||||
{
|
||||
if( gfEditMode )
|
||||
@@ -1399,7 +1467,6 @@ UINT8 HighestPlayerProgressPercentage(void)
|
||||
return(gStrategicStatus.ubHighestProgress);
|
||||
}
|
||||
|
||||
|
||||
// monitors the highest level of progress that player has achieved so far (checking hourly),
|
||||
// as opposed to his immediate situation (which may be worse if he's suffered a setback).
|
||||
void HourlyProgressUpdate(void)
|
||||
|
||||
@@ -556,7 +556,10 @@ void DisplayRangeToTarget( SOLDIERTYPE *pSoldier, INT16 sTargetGridNo )
|
||||
}
|
||||
pSoldier->bTargetLevel = bTempTargetLevel;
|
||||
|
||||
swprintf( zOutputString, gzDisplayCoverText[DC_MSG__GUN_RANGE_INFORMATION], usRange / 10, Weapon[ pSoldier->inv[HANDPOS].usItem ].usRange / 10, uiHitChance );
|
||||
// HEADROCK HAM 3.6: Calculate Gun Range using formula.
|
||||
UINT16 usGunRange = GunRange(&pSoldier->inv[HANDPOS]);
|
||||
|
||||
swprintf( zOutputString, gzDisplayCoverText[DC_MSG__GUN_RANGE_INFORMATION], usRange / 10, usGunRange / 10, uiHitChance );
|
||||
//Display the msg
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, zOutputString );
|
||||
}
|
||||
|
||||
+10
-9
@@ -37,6 +37,9 @@
|
||||
#include "Interface Items.h"
|
||||
#include "meanwhile.h"
|
||||
#include "Map Screen Interface.h"
|
||||
// HEADROCK HAM 3.2: Added two includes so that a function can read values of the Gun Range/hospital location
|
||||
#include "Campaign Types.h"
|
||||
#include "Strategic Event Handler.h"
|
||||
#endif
|
||||
|
||||
// Defines
|
||||
@@ -1256,7 +1259,6 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
|
||||
UINT16 usMaximumPts = 0;
|
||||
CHAR16 sString[ 32 ];
|
||||
UINT16 usTextWidth;
|
||||
BOOLEAN fAtGunRange = FALSE;
|
||||
BOOLEAN fShowNumber = FALSE;
|
||||
BOOLEAN fShowMaximum = FALSE;
|
||||
SOLDIERTYPE *pSoldier;
|
||||
@@ -1474,34 +1476,33 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
|
||||
|
||||
case TRAIN_SELF:
|
||||
case TRAIN_TOWN:
|
||||
// HEADROCK HAM 3.6: New assignment.
|
||||
case TRAIN_MOBILE:
|
||||
case TRAIN_TEAMMATE:
|
||||
case TRAIN_BY_OTHER:
|
||||
sIconIndex = 3;
|
||||
fDoIcon = TRUE;
|
||||
fShowNumber = TRUE;
|
||||
fShowMaximum = TRUE;
|
||||
// there could be bonus pts for training at gun range
|
||||
if ( ( MercPtrs[ pFace->ubSoldierID ]->sSectorX == 13) && (MercPtrs[ pFace->ubSoldierID ]->sSectorY == MAP_ROW_H) && (MercPtrs[ pFace->ubSoldierID ]->bSectorZ == 0) )
|
||||
{
|
||||
fAtGunRange = TRUE;
|
||||
}
|
||||
|
||||
switch( MercPtrs[ pFace->ubSoldierID ]->bAssignment )
|
||||
{
|
||||
case( TRAIN_SELF ):
|
||||
sPtsAvailable = GetSoldierTrainingPts( MercPtrs[ pFace->ubSoldierID ], MercPtrs[ pFace->ubSoldierID ]->bTrainStat, fAtGunRange, &usMaximumPts );
|
||||
sPtsAvailable = GetSoldierTrainingPts( MercPtrs[ pFace->ubSoldierID ], MercPtrs[ pFace->ubSoldierID ]->bTrainStat, &usMaximumPts );
|
||||
break;
|
||||
case( TRAIN_BY_OTHER ):
|
||||
sPtsAvailable = GetSoldierStudentPts( MercPtrs[ pFace->ubSoldierID ], MercPtrs[ pFace->ubSoldierID ]->bTrainStat, fAtGunRange, &usMaximumPts );
|
||||
sPtsAvailable = GetSoldierStudentPts( MercPtrs[ pFace->ubSoldierID ], MercPtrs[ pFace->ubSoldierID ]->bTrainStat, &usMaximumPts );
|
||||
break;
|
||||
// HEADROCK HAM 3.6: New assignment. Works just like Town Training.
|
||||
case( TRAIN_TOWN ):
|
||||
case( TRAIN_MOBILE ):
|
||||
sPtsAvailable = GetTownTrainPtsForCharacter( MercPtrs[ pFace->ubSoldierID ], &usMaximumPts );
|
||||
// divide both amounts by 10 to make the displayed numbers a little more user-palatable (smaller)
|
||||
sPtsAvailable = ( sPtsAvailable + 5 ) / 10;
|
||||
usMaximumPts = ( usMaximumPts + 5 ) / 10;
|
||||
break;
|
||||
case( TRAIN_TEAMMATE ):
|
||||
sPtsAvailable = GetBonusTrainingPtsDueToInstructor( MercPtrs[ pFace->ubSoldierID ], NULL , MercPtrs[ pFace->ubSoldierID ]->bTrainStat, fAtGunRange, &usMaximumPts );
|
||||
sPtsAvailable = GetBonusTrainingPtsDueToInstructor( MercPtrs[ pFace->ubSoldierID ], NULL , MercPtrs[ pFace->ubSoldierID ]->bTrainStat, &usMaximumPts );
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -526,15 +526,22 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel, UINT16 usHa
|
||||
|
||||
if((__min(pSoldier->bDoAutofire,pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft) - startAuto) > 0 && pSoldier->bTeam == OUR_TEAM)
|
||||
{
|
||||
// More than 1 round
|
||||
if (__min(pSoldier->bDoAutofire,pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft) - startAuto > 1)
|
||||
if (gGameExternalOptions.usBulletHideIntensity > 0)
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[ 62 ], pSoldier->name, __min(pSoldier->bDoAutofire,pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft) - startAuto );
|
||||
// HEADROCK HAM 3.5: Non-accurate assessment.
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113HAMMessage[ 2 ], pSoldier->name );
|
||||
}
|
||||
// 1 round
|
||||
else
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[ 63 ], pSoldier->name, __min(pSoldier->bDoAutofire,pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft) - startAuto );
|
||||
{// More than 1 round
|
||||
if (__min(pSoldier->bDoAutofire,pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft) - startAuto > 1)
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[ 62 ], pSoldier->name, __min(pSoldier->bDoAutofire,pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft) - startAuto );
|
||||
}
|
||||
// 1 round
|
||||
else
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, gzLateLocalizedString[ 63 ], pSoldier->name, __min(pSoldier->bDoAutofire,pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft) - startAuto );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1957,6 +1964,11 @@ void HandleSoldierPickupItem( SOLDIERTYPE *pSoldier, INT32 iItemIndex, INT16 sGr
|
||||
// OK, if an enemy, go directly ( skip menu )
|
||||
if ( pSoldier->bTeam != gbPlayerNum )
|
||||
{
|
||||
// HEADROCK HAM 3.5: On-screen message when militia pick up items.
|
||||
if ( pSoldier->bTeam == MILITIA_TEAM )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113HAMMessage[4], Item[gWorldItems[ pItemPool->iItemIndex ].object.usItem].szItemName );
|
||||
}
|
||||
SoldierGetItemFromWorld( pSoldier, iItemIndex, sGridNo, bZLevel, NULL );
|
||||
}
|
||||
else
|
||||
|
||||
@@ -296,16 +296,16 @@ UINT8 UsingEDBSystem()
|
||||
{
|
||||
if(guiCurrentScreen == MAP_SCREEN) //Strategic
|
||||
{
|
||||
if(gGameExternalOptions.fEnhancedDescriptionBox == 0)
|
||||
if(gGameExternalOptions.iEnhancedDescriptionBox == 0)
|
||||
return 1;
|
||||
if(gGameExternalOptions.fEnhancedDescriptionBox == 1)
|
||||
if(gGameExternalOptions.iEnhancedDescriptionBox == 1)
|
||||
return 1;
|
||||
}
|
||||
else //Tactical
|
||||
{
|
||||
if(gGameExternalOptions.fEnhancedDescriptionBox == 0)
|
||||
if(gGameExternalOptions.iEnhancedDescriptionBox == 0)
|
||||
return (UsingNewInventorySystem()==true?1:2);
|
||||
if(gGameExternalOptions.fEnhancedDescriptionBox == 2)
|
||||
if(gGameExternalOptions.iEnhancedDescriptionBox == 2)
|
||||
return (UsingNewInventorySystem()==true?1:2);
|
||||
}
|
||||
}
|
||||
@@ -856,8 +856,8 @@ void InitDescStatCoords()
|
||||
gWeaponStats[18].sX = 268; gWeaponStats[18].sY = 136; gWeaponStats[18].sValDx = 30; // 18) COL 4; ROW 1
|
||||
gWeaponStats[19].sX = 268; gWeaponStats[19].sY = 148; gWeaponStats[19].sValDx = 30; // 19) COL 4; ROW 2
|
||||
gWeaponStats[20].sX = 268; gWeaponStats[20].sY = 160; gWeaponStats[20].sValDx = 30; // 20) COL 4; ROW 3
|
||||
gWeaponStats[21].sX = 203; gWeaponStats[21].sY = 172; gWeaponStats[21].sValDx = 30; // 21) COL 3; ROW 4
|
||||
gWeaponStats[22].sX = 268; gWeaponStats[22].sY = 172; gWeaponStats[22].sValDx = 30; // 22) COL 4; ROW 4
|
||||
gWeaponStats[21].sX = 268; gWeaponStats[21].sY = 172; gWeaponStats[21].sValDx = 30; // 21) COL 4; ROW 4
|
||||
gWeaponStats[22].sX = 203; gWeaponStats[22].sY = 172; gWeaponStats[22].sValDx = 30; // 22) COL 3; ROW 4
|
||||
// EQUALS signs
|
||||
gWeaponStats[23].sX = 235; gWeaponStats[23].sY = 44; gWeaponStats[23].sValDx = 0; // 23) COL 1; ROW 1
|
||||
gWeaponStats[24].sX = 235; gWeaponStats[24].sY = 56; gWeaponStats[24].sValDx = 0; // 24) COL 1; ROW 2
|
||||
@@ -878,8 +878,8 @@ void InitDescStatCoords()
|
||||
gWeaponStats[39].sX = 300; gWeaponStats[39].sY = 136; gWeaponStats[39].sValDx = 0; // 39) COL 4; ROW 1
|
||||
gWeaponStats[40].sX = 300; gWeaponStats[40].sY = 148; gWeaponStats[40].sValDx = 0; // 40) COL 4; ROW 2
|
||||
gWeaponStats[41].sX = 300; gWeaponStats[41].sY = 160; gWeaponStats[41].sValDx = 0; // 41) COL 4; ROW 3
|
||||
gWeaponStats[42].sX = 235; gWeaponStats[42].sY = 172; gWeaponStats[42].sValDx = 0; // 42) COL 3; ROW 4
|
||||
gWeaponStats[43].sX = 300; gWeaponStats[43].sY = 172; gWeaponStats[43].sValDx = 0; // 43) COL 4; ROW 4
|
||||
gWeaponStats[42].sX = 300; gWeaponStats[42].sY = 172; gWeaponStats[42].sValDx = 0; // 42) COL 4; ROW 4
|
||||
gWeaponStats[43].sX = 235; gWeaponStats[43].sY = 172; gWeaponStats[43].sValDx = 0; // 43) COL 3; ROW 4
|
||||
// Nonregular locations for explosive radius values (COL 2; ROW 3)
|
||||
gWeaponStats[44].sX = 273; gWeaponStats[44].sY = 68; gWeaponStats[44].sValDx = 0; // 44) COL 2; ROW 3; LOC 1 - Starting Radius
|
||||
gWeaponStats[45].sX = 291; gWeaponStats[45].sY = 68; gWeaponStats[45].sValDx = 0; // 45) COL 2; ROW 3; LOC 2 - Single Radius
|
||||
@@ -5988,10 +5988,10 @@ void DrawMiscValues( OBJECTTYPE * gpItemDescObject )
|
||||
// HIDE MUZZLE FLASH
|
||||
// NO DATA SHOWN, icon either appears or does not appear.
|
||||
// HEADROCK HAM 3.5 - Fixed this, because the count needs to be increased to skip a line!
|
||||
if ( Item[ gpItemDescObject->usItem ].hidemuzzleflash > 0 && cnt<=27 )
|
||||
{
|
||||
cnt++;
|
||||
}
|
||||
if ( Item[ gpItemDescObject->usItem ].hidemuzzleflash > 0 && cnt<=27 )
|
||||
{
|
||||
cnt++;
|
||||
}
|
||||
|
||||
// BIPOD
|
||||
if ( Item[ gpItemDescObject->usItem ].bipod != 0 && cnt<=27 )
|
||||
|
||||
@@ -2508,8 +2508,22 @@ void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObjec
|
||||
// SetFontForeground( FONT_MCOLOR_DKGRAY );
|
||||
// break;
|
||||
//}
|
||||
|
||||
// HEADROCK HAM 3.4: Get estimate of bullets left.
|
||||
if ( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) )
|
||||
{
|
||||
// Soldier doesn't know.
|
||||
EstimateBulletsLeft( pSoldier, pObject );
|
||||
swprintf( pStr, L"%s", gBulletCount );
|
||||
}
|
||||
else
|
||||
{
|
||||
swprintf( pStr, L"%d", (*pObject)[iter]->data.gun.ubGunShotsLeft );
|
||||
}
|
||||
|
||||
//swprintf( pStr, L"%d", (*pObject)[iter]->data.gun.ubGunShotsLeft );
|
||||
//swprintf( pStr, L"%d", GetEstimateBulletsLeft(pSoldier, pObject) );
|
||||
|
||||
swprintf( pStr, L"%d", (*pObject)[iter]->data.gun.ubGunShotsLeft );
|
||||
if ( uiBuffer == guiSAVEBUFFER )
|
||||
{
|
||||
RestoreExternBackgroundRect( sNewX, sNewY, 20, 15 );
|
||||
@@ -2892,7 +2906,7 @@ BOOLEAN InternalInitItemDescriptionBox( OBJECTTYPE *pObject, INT16 sX, INT16 sY,
|
||||
//CHRISL: Initialize coords based on EDB/NIV settings
|
||||
InitDescStatCoords();
|
||||
InitEDBCoords();
|
||||
InitItemDescriptionBoxStartCoords( gGameExternalOptions.fEnhancedDescriptionBox );
|
||||
InitItemDescriptionBoxStartCoords( gGameExternalOptions.iEnhancedDescriptionBox );
|
||||
|
||||
//CHRISL: We only want this condition to be true when looking at MONEY. Not IC_MONEY since we can't actually split
|
||||
// things like gold nuggets or wallets.
|
||||
@@ -2974,10 +2988,33 @@ BOOLEAN InternalInitItemDescriptionBox( OBJECTTYPE *pObject, INT16 sX, INT16 sY,
|
||||
// Add button
|
||||
// if( guiCurrentScreen != MAP_SCREEN )
|
||||
//if( guiCurrentItemDescriptionScreen != MAP_SCREEN )
|
||||
|
||||
if ( GetMagSize(gpItemDescObject) <= 99 )
|
||||
swprintf( pStr, L"%d/%d", (*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunShotsLeft, GetMagSize(gpItemDescObject));
|
||||
{
|
||||
// HEADROCK HAM 3.4: "Bullet Hide" feature - bullet count only shown during combat if character is competent enough.
|
||||
if ( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) )
|
||||
{
|
||||
EstimateBulletsLeft( pSoldier, pObject );
|
||||
swprintf(pStr, L"%s/%d", gBulletCount, GetMagSize(gpItemDescObject) );
|
||||
}
|
||||
else
|
||||
{
|
||||
swprintf( pStr, L"%d/%d", (*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunShotsLeft, GetMagSize(gpItemDescObject));
|
||||
}
|
||||
}
|
||||
else
|
||||
swprintf( pStr, L"%d", (*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunShotsLeft );
|
||||
{
|
||||
// HEADROCK HAM 3.4: "Bullet Hide" feature - bullet count only shown during combat if character is competent enough.
|
||||
if ( (gTacticalStatus.uiFlags & TURNBASED) && (gTacticalStatus.uiFlags & INCOMBAT) )
|
||||
{
|
||||
EstimateBulletsLeft( pSoldier, pObject );
|
||||
swprintf( pStr, L"%s", gBulletCount );
|
||||
}
|
||||
else
|
||||
{
|
||||
swprintf( pStr, L"%d", (*gpItemDescObject)[ubStatusIndex]->data.gun.ubGunShotsLeft );
|
||||
}
|
||||
}
|
||||
|
||||
FilenameForBPP("INTERFACE\\infobox.sti", ubString);
|
||||
sForeColour = ITEMDESC_AMMO_FORE;
|
||||
|
||||
+181
-23
@@ -72,6 +72,8 @@
|
||||
#include "MessageBoxScreen.h"
|
||||
#include "wordwrap.h"
|
||||
#include "Boxing.h"
|
||||
// HEADROCK HAM 3.6: This is required for Stat Progress Bars
|
||||
#include "Campaign.h"
|
||||
#endif
|
||||
|
||||
//forward declarations of common classes to eliminate includes
|
||||
@@ -1532,27 +1534,27 @@ BOOLEAN InitializeSMPanelCoordsOld()
|
||||
SM_CAMMO_X = ( 428 + INTERFACE_START_X );
|
||||
SM_CAMMO_Y = ( 121 + INV_INTERFACE_START_Y );
|
||||
|
||||
SM_STATS_WIDTH = 30;
|
||||
SM_STATS_WIDTH = 16;
|
||||
SM_STATS_HEIGHT = 8 ;
|
||||
SM_AGI_X = ( 99 + INTERFACE_START_X );
|
||||
SM_AGI_X = ( 115 + INTERFACE_START_X );
|
||||
SM_AGI_Y = ( 7 + INV_INTERFACE_START_Y );
|
||||
SM_DEX_X = ( 99 + INTERFACE_START_X );
|
||||
SM_DEX_X = ( 115 + INTERFACE_START_X );
|
||||
SM_DEX_Y = ( 17 + INV_INTERFACE_START_Y );
|
||||
SM_STR_X = ( 99 + INTERFACE_START_X );
|
||||
SM_STR_X = ( 115 + INTERFACE_START_X );
|
||||
SM_STR_Y = ( 27 + INV_INTERFACE_START_Y );
|
||||
SM_CHAR_X = ( 99 + INTERFACE_START_X );
|
||||
SM_CHAR_X = ( 115 + INTERFACE_START_X );
|
||||
SM_CHAR_Y = ( 37 + INV_INTERFACE_START_Y );
|
||||
SM_WIS_X = ( 99 + INTERFACE_START_X );
|
||||
SM_WIS_X = ( 115 + INTERFACE_START_X );
|
||||
SM_WIS_Y = ( 47 + INV_INTERFACE_START_Y );
|
||||
SM_EXPLVL_X = ( 148 + INTERFACE_START_X );
|
||||
SM_EXPLVL_X = ( 163 + INTERFACE_START_X );
|
||||
SM_EXPLVL_Y = ( 7 + INV_INTERFACE_START_Y );
|
||||
SM_MRKM_X = ( 148 + INTERFACE_START_X );
|
||||
SM_MRKM_X = ( 163 + INTERFACE_START_X );
|
||||
SM_MRKM_Y = ( 17 + INV_INTERFACE_START_Y );
|
||||
SM_EXPL_X = ( 148 + INTERFACE_START_X );
|
||||
SM_EXPL_X = ( 163 + INTERFACE_START_X );
|
||||
SM_EXPL_Y = ( 27 + INV_INTERFACE_START_Y );
|
||||
SM_MECH_X = ( 148 + INTERFACE_START_X );
|
||||
SM_MECH_X = ( 163 + INTERFACE_START_X );
|
||||
SM_MECH_Y = ( 37 + INV_INTERFACE_START_Y );
|
||||
SM_MED_X = ( 148 + INTERFACE_START_X );
|
||||
SM_MED_X = ( 163 + INTERFACE_START_X );
|
||||
SM_MED_Y = ( 47 + INV_INTERFACE_START_Y );
|
||||
|
||||
MONEY_X = ( 460 + INTERFACE_START_X );
|
||||
@@ -1905,27 +1907,27 @@ BOOLEAN InitializeSMPanelCoordsNew()
|
||||
SM_CAMMO_X = ( 218 + INTERFACE_START_X );
|
||||
SM_CAMMO_Y = ( 49 + INV_INTERFACE_START_Y );
|
||||
|
||||
SM_STATS_WIDTH = 30;
|
||||
SM_STATS_WIDTH = 16;
|
||||
SM_STATS_HEIGHT = 8 ;
|
||||
SM_AGI_X = ( 101 + INTERFACE_START_X );
|
||||
SM_AGI_X = ( 115 + INTERFACE_START_X );
|
||||
SM_AGI_Y = ( 7 + INV_INTERFACE_START_Y );
|
||||
SM_DEX_X = ( 101 + INTERFACE_START_X );
|
||||
SM_DEX_X = ( 115 + INTERFACE_START_X );
|
||||
SM_DEX_Y = ( 17 + INV_INTERFACE_START_Y );
|
||||
SM_STR_X = ( 101 + INTERFACE_START_X );
|
||||
SM_STR_X = ( 115 + INTERFACE_START_X );
|
||||
SM_STR_Y = ( 27 + INV_INTERFACE_START_Y );
|
||||
SM_CHAR_X = ( 101 + INTERFACE_START_X );
|
||||
SM_CHAR_X = ( 115 + INTERFACE_START_X );
|
||||
SM_CHAR_Y = ( 37 + INV_INTERFACE_START_Y );
|
||||
SM_WIS_X = ( 101 + INTERFACE_START_X );
|
||||
SM_WIS_X = ( 115 + INTERFACE_START_X );
|
||||
SM_WIS_Y = ( 47 + INV_INTERFACE_START_Y );
|
||||
SM_EXPLVL_X = ( 150 + INTERFACE_START_X );
|
||||
SM_EXPLVL_X = ( 163 + INTERFACE_START_X );
|
||||
SM_EXPLVL_Y = ( 7 + INV_INTERFACE_START_Y );
|
||||
SM_MRKM_X = ( 150 + INTERFACE_START_X );
|
||||
SM_MRKM_X = ( 163 + INTERFACE_START_X );
|
||||
SM_MRKM_Y = ( 17 + INV_INTERFACE_START_Y );
|
||||
SM_EXPL_X = ( 150 + INTERFACE_START_X );
|
||||
SM_EXPL_X = ( 163 + INTERFACE_START_X );
|
||||
SM_EXPL_Y = ( 27 + INV_INTERFACE_START_Y );
|
||||
SM_MECH_X = ( 150 + INTERFACE_START_X );
|
||||
SM_MECH_X = ( 163 + INTERFACE_START_X );
|
||||
SM_MECH_Y = ( 37 + INV_INTERFACE_START_Y );
|
||||
SM_MED_X = ( 150 + INTERFACE_START_X );
|
||||
SM_MED_X = ( 163 + INTERFACE_START_X );
|
||||
SM_MED_Y = ( 47 + INV_INTERFACE_START_Y );
|
||||
|
||||
MONEY_X = ( 185 + INTERFACE_START_X );
|
||||
@@ -2495,6 +2497,133 @@ void RenderSMPanel( BOOLEAN *pfDirty )
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: "progress" bars showing how near the character is to "leveling up" in any stat. The bar
|
||||
// is displayed behind the current stat value, as see on the character's info panel.
|
||||
// This section draws TACTICAL info pages. Another section is in mapscreen.cpp and draws STRATEGIC info pages.
|
||||
// The feature is toggled by Options-Menu switch, and its color is determined in the INI files.
|
||||
if ( gGameSettings.fOptions[TOPTION_STAT_PROGRESS_BARS] )
|
||||
{
|
||||
UINT8 *pDestBuf;
|
||||
UINT32 uiDestPitchBYTES = 0;
|
||||
SGPRect ClipRect;
|
||||
UINT8 ubBarWidth;
|
||||
UINT16 usColor = Get16BPPColor( FROMRGB( gGameExternalOptions.ubStatProgressBarsRed, gGameExternalOptions.ubStatProgressBarsGreen, gGameExternalOptions.ubStatProgressBarsBlue ) );
|
||||
//pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
||||
pDestBuf = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES );
|
||||
|
||||
// AGI
|
||||
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sAgilityGain)
|
||||
{
|
||||
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sAgilityGain+1)) / SubpointsPerPoint(AGILAMT,0);
|
||||
ClipRect.iTop = (SM_AGI_Y-1);
|
||||
ClipRect.iBottom = (SM_AGI_Y-1) + SM_STATS_HEIGHT;
|
||||
ClipRect.iLeft = SM_AGI_X;
|
||||
ClipRect.iRight = SM_AGI_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// DEX
|
||||
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sDexterityGain)
|
||||
{
|
||||
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sDexterityGain+1)) / SubpointsPerPoint(DEXTAMT,0);
|
||||
ClipRect.iTop = (SM_DEX_Y-1);
|
||||
ClipRect.iBottom = (SM_DEX_Y-1) + SM_STATS_HEIGHT;
|
||||
ClipRect.iLeft = SM_DEX_X;
|
||||
ClipRect.iRight = SM_DEX_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// STR
|
||||
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sStrengthGain)
|
||||
{
|
||||
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sStrengthGain+1)) / SubpointsPerPoint(STRAMT,0);
|
||||
ClipRect.iTop = (SM_STR_Y-1);
|
||||
ClipRect.iBottom = (SM_STR_Y-1) + SM_STATS_HEIGHT;
|
||||
ClipRect.iLeft = SM_STR_X;
|
||||
ClipRect.iRight = SM_STR_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// WIS
|
||||
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sWisdomGain)
|
||||
{
|
||||
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sWisdomGain+1)) / SubpointsPerPoint(WISDOMAMT,0);
|
||||
ClipRect.iTop = (SM_WIS_Y-1);
|
||||
ClipRect.iBottom = (SM_WIS_Y-1) + SM_STATS_HEIGHT;
|
||||
ClipRect.iLeft = SM_WIS_X;
|
||||
ClipRect.iRight = SM_WIS_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// MRK
|
||||
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMarksmanshipGain)
|
||||
{
|
||||
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMarksmanshipGain+1)) / SubpointsPerPoint(MARKAMT,0);
|
||||
ClipRect.iTop = (SM_MRKM_Y-1);
|
||||
ClipRect.iBottom = (SM_MRKM_Y-1) + SM_STATS_HEIGHT;
|
||||
ClipRect.iLeft = SM_MRKM_X;
|
||||
ClipRect.iRight = SM_MRKM_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// LDR
|
||||
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sLeadershipGain)
|
||||
{
|
||||
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sLeadershipGain+1)) / SubpointsPerPoint(LDRAMT,0);
|
||||
ClipRect.iTop = (SM_CHAR_Y-1);
|
||||
ClipRect.iBottom = (SM_CHAR_Y-1) + SM_STATS_HEIGHT;
|
||||
ClipRect.iLeft = SM_CHAR_X;
|
||||
ClipRect.iRight = SM_CHAR_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// MECH
|
||||
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMechanicGain)
|
||||
{
|
||||
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMechanicGain+1)) / SubpointsPerPoint(MECHANAMT,0);
|
||||
ClipRect.iTop = (SM_MECH_Y-1);
|
||||
ClipRect.iBottom = (SM_MECH_Y-1) + SM_STATS_HEIGHT;
|
||||
ClipRect.iLeft = SM_MECH_X;
|
||||
ClipRect.iRight = SM_MECH_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// EXPLO
|
||||
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExplosivesGain)
|
||||
{
|
||||
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExplosivesGain+1)) / SubpointsPerPoint(EXPLODEAMT,0);
|
||||
ClipRect.iTop = (SM_EXPL_Y-1);
|
||||
ClipRect.iBottom = (SM_EXPL_Y-1) + SM_STATS_HEIGHT;
|
||||
ClipRect.iLeft = SM_EXPL_X;
|
||||
ClipRect.iRight = SM_EXPL_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// MED
|
||||
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMedicalGain)
|
||||
{
|
||||
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sMedicalGain+1)) / SubpointsPerPoint(MEDICALAMT,0);
|
||||
ClipRect.iTop = (SM_MED_Y-1);
|
||||
ClipRect.iBottom = (SM_MED_Y-1) + SM_STATS_HEIGHT;
|
||||
ClipRect.iLeft = SM_MED_X;
|
||||
ClipRect.iRight = SM_MED_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// EXPLEVEL
|
||||
if (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExpLevelGain)
|
||||
{
|
||||
ubBarWidth = (SM_STATS_WIDTH * (gMercProfiles[ gpSMCurrentMerc->ubProfile ].sExpLevelGain+1)) / SubpointsPerPoint(EXPERAMT, gpSMCurrentMerc->stats.bExpLevel);
|
||||
ClipRect.iTop = (SM_EXPLVL_Y-1);
|
||||
ClipRect.iBottom = (SM_EXPLVL_Y-1) + SM_STATS_HEIGHT;
|
||||
ClipRect.iLeft = SM_EXPLVL_X;
|
||||
ClipRect.iRight = SM_EXPLVL_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
UnLockVideoSurface( guiSAVEBUFFER );
|
||||
}
|
||||
|
||||
// Render faceplate
|
||||
//BltVideoObjectFromIndex( guiSAVEBUFFER, guiSMObjects2, 1, SM_SELMERC_NAMEPLATE_X, SM_SELMERC_NAMEPLATE_Y, VO_BLT_SRCTRANSPARENCY, NULL );
|
||||
//RestoreExternBackgroundRect( SM_SELMERC_NAMEPLATE_X, SM_SELMERC_NAMEPLATE_Y, SM_SELMERC_NAMEPLATE_WIDTH, SM_SELMERC_NAMEPLATE_HEIGHT );
|
||||
@@ -5433,7 +5562,36 @@ void MercFacePanelCallback( MOUSE_REGION * pRegion, INT32 iReason )
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleLocateSelectMerc( ubSoldierID, 0 );
|
||||
// HEADROCK HAM 3.5: Shift-Click a merc's face will add him to the current selection.
|
||||
if (!(gTacticalStatus.uiFlags & INCOMBAT) && _KeyDown( SHIFT ) )
|
||||
{
|
||||
if ( ! (MercPtrs[ ubSoldierID ]->flags.uiStatusFlags & SOLDIER_MULTI_SELECTED ) )
|
||||
{
|
||||
if ( OK_CONTROLLABLE_MERC( MercPtrs[ ubSoldierID ] ) && !( MercPtrs[ ubSoldierID ]->flags.uiStatusFlags & ( SOLDIER_VEHICLE | SOLDIER_PASSENGER | SOLDIER_DRIVER ) ) )
|
||||
{
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s added", MercPtrs[ ubSoldierID ]->name );
|
||||
MercPtrs[ gusSelectedSoldier ]->flags.uiStatusFlags |= SOLDIER_MULTI_SELECTED;
|
||||
MercPtrs[ ubSoldierID ]->flags.uiStatusFlags |= SOLDIER_MULTI_SELECTED;
|
||||
EndMultiSoldierSelection( TRUE );
|
||||
}
|
||||
}
|
||||
// A shift-click on a selected character will remove that character from the current selection.
|
||||
else
|
||||
{
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s removed", MercPtrs[ ubSoldierID ]->name );
|
||||
MercPtrs[ ubSoldierID ]->flags.uiStatusFlags &= (~SOLDIER_MULTI_SELECTED );
|
||||
if (ubSoldierID != gusSelectedSoldier)
|
||||
{
|
||||
MercPtrs[ gusSelectedSoldier ]->flags.uiStatusFlags |= SOLDIER_MULTI_SELECTED;
|
||||
}
|
||||
EndMultiSoldierSelection( TRUE );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s selected", MercPtrs[ ubSoldierID ]->name );
|
||||
HandleLocateSelectMerc( ubSoldierID, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
+180
-105
@@ -2680,15 +2680,21 @@ UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier )
|
||||
//ADB the weight of the object is already counting stacked objects, attachments, et al
|
||||
uiTotalWeight += CalculateObjectWeight(&pSoldier->inv[ubLoop]);
|
||||
}
|
||||
// for now, assume soldiers can carry 1/2 their strength in KGs without penalty.
|
||||
// instead of multiplying by 100 for percent, and then dividing by 10 to account
|
||||
// for weight units being in 10ths of kilos, not kilos... we just start with 10 instead of 100!
|
||||
// Every point over 80 counts double.
|
||||
ubStrengthForCarrying = EffectiveStrength( pSoldier );
|
||||
if ( ubStrengthForCarrying > 80 )
|
||||
{
|
||||
ubStrengthForCarrying += (ubStrengthForCarrying - 80);
|
||||
}
|
||||
uiPercent = (10 * uiTotalWeight) / ( ubStrengthForCarrying / 2 );
|
||||
|
||||
// for now, assume soldiers can carry 1/2 their strength in KGs without penalty.
|
||||
// instead of multiplying by 100 for percent, and then dividing by 10 to account
|
||||
// for weight units being in 10ths of kilos, not kilos... we just start with 10 instead of 100!
|
||||
|
||||
// HEADROCK HAM 3: STR required per 1/2 kilo has been externalized. Can someone tidy this up though? The
|
||||
// formula works great, but it's damn ugly now.
|
||||
uiPercent = (UINT32)(((FLOAT)10 * (FLOAT)gGameExternalOptions.iStrengthToLiftHalfKilo) * uiTotalWeight) / ( ubStrengthForCarrying / 2 );
|
||||
|
||||
return( uiPercent );
|
||||
|
||||
}
|
||||
@@ -3152,9 +3158,12 @@ BOOLEAN EmptyWeaponMagazine( OBJECTTYPE * pWeapon, OBJECTTYPE *pAmmo, UINT32 sub
|
||||
{
|
||||
CreateAmmo((*pWeapon)[subObject]->data.gun.usGunAmmoItem, pAmmo, (*pWeapon)[subObject]->data.gun.ubGunShotsLeft);
|
||||
|
||||
(*pWeapon)[subObject]->data.gun.ubGunShotsLeft = 0;
|
||||
(*pWeapon)[subObject]->data.gun.ubGunAmmoType = 0;
|
||||
//(*pWeapon)[subObject]->data.gun.usGunAmmoItem = 0; // leaving the ammo item the same for auto-reloading purposes
|
||||
(*pWeapon)[subObject]->data.gun.ubGunShotsLeft = 0;
|
||||
(*pWeapon)[subObject]->data.gun.ubGunAmmoType = 0;
|
||||
// HEADROCK HAM 3.5: Leaving the ammo inside the gun causes EDB stats to display values as though the magazine
|
||||
// still gives some effects (like autopen reduction, range bonus, etcetera). I'm going to try to work around
|
||||
// this issue.
|
||||
(*pWeapon)[subObject]->data.gun.usGunAmmoItem = 0; // leaving the ammo item the same for auto-reloading purposes
|
||||
|
||||
// Play some effects!
|
||||
usReloadSound = Weapon[ pWeapon->usItem ].sReloadSound;
|
||||
@@ -3174,13 +3183,20 @@ BOOLEAN EmptyWeaponMagazine( OBJECTTYPE * pWeapon, OBJECTTYPE *pAmmo, UINT32 sub
|
||||
}
|
||||
else
|
||||
{
|
||||
// HEADROCK HAM 3.5: Clear the ammo type and magazine on player command. This will remove all bonuses by
|
||||
// the ammo and allow viewing the gun's normal stats. It will also change the weapon's ammocolor back to grey.
|
||||
(*pWeapon)[subObject]->data.gun.ubGunAmmoType = 0;
|
||||
(*pWeapon)[subObject]->data.gun.usGunAmmoItem = 0;
|
||||
//CHRISL: Clear the contents of pAmmo just in case
|
||||
pAmmo->initialize();
|
||||
return( FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
INT8 FindAmmo( SOLDIERTYPE * pSoldier, UINT8 ubCalibre, UINT16 ubMagSize, INT8 bExcludeSlot )
|
||||
// HEADROCK HAM 3.3: Added an additional argument which helps the program pick a magazine
|
||||
// that matches the ammotype currently used in the weapon. This makes for much smarter
|
||||
// ammo selection.
|
||||
INT8 FindAmmo( SOLDIERTYPE * pSoldier, UINT8 ubCalibre, UINT16 ubMagSize, UINT8 ubAmmoType, INT8 bExcludeSlot )
|
||||
{
|
||||
INT8 bLoop;
|
||||
INT8 capLoop = 0;
|
||||
@@ -3211,7 +3227,10 @@ INT8 FindAmmo( SOLDIERTYPE * pSoldier, UINT8 ubCalibre, UINT16 ubMagSize, INT8 b
|
||||
{
|
||||
stackCap = __max(stackCap, pSoldier->inv[bLoop][i]->data.ubShotsLeft);
|
||||
}
|
||||
if(stackCap > curCap)
|
||||
// If found a similar-sized magazine to the best one found so far, but this new one
|
||||
// has the same ammotype as specified in the arguments, then this is a better choice!
|
||||
if(stackCap > curCap ||
|
||||
(stackCap == curCap && Magazine[pItem->ubClassIndex].ubAmmoType == ubAmmoType))
|
||||
{
|
||||
curCap = stackCap;
|
||||
capLoop = bLoop;
|
||||
@@ -3264,7 +3283,7 @@ INT8 FindAmmoToReload( SOLDIERTYPE * pSoldier, INT8 bWeaponIn, INT8 bExcludeSlot
|
||||
// return( bSlot );
|
||||
//}
|
||||
// look for any ammo that matches which is of the same calibre and magazine size
|
||||
bSlot = FindAmmo( pSoldier, Weapon[pObj->usItem].ubCalibre, GetMagSize(pObj), bExcludeSlot );
|
||||
bSlot = FindAmmo( pSoldier, Weapon[pObj->usItem].ubCalibre, GetMagSize(pObj), GetAmmoType(pObj), bExcludeSlot );
|
||||
if (bSlot != NO_SLOT)
|
||||
{
|
||||
return( bSlot );
|
||||
@@ -3272,7 +3291,7 @@ INT8 FindAmmoToReload( SOLDIERTYPE * pSoldier, INT8 bWeaponIn, INT8 bExcludeSlot
|
||||
else
|
||||
{
|
||||
// look for any ammo that matches which is of the same calibre (different size okay)
|
||||
return( FindAmmo( pSoldier, Weapon[pObj->usItem].ubCalibre, ANY_MAGSIZE, bExcludeSlot ) );
|
||||
return( FindAmmo( pSoldier, Weapon[pObj->usItem].ubCalibre, ANY_MAGSIZE, GetAmmoType(pObj), bExcludeSlot ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -3970,6 +3989,8 @@ void EjectAmmoAndPlace(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj)
|
||||
CreateAmmo((*pObj)[0]->data.gun.usGunAmmoItem, &gTempObject, (*pObj)[0]->data.gun.ubGunShotsLeft);
|
||||
(*pObj)[0]->data.gun.ubGunShotsLeft = 0;
|
||||
(*pObj)[0]->data.gun.usGunAmmoItem = NONE;
|
||||
// HEADROCK HAM 3.5: Clear ammo type
|
||||
(*pObj)[0]->data.gun.ubGunAmmoType = NONE;
|
||||
if ( pSoldier )
|
||||
{
|
||||
if ( !AutoPlaceObject( pSoldier, &gTempObject, FALSE ) )
|
||||
@@ -7104,7 +7125,7 @@ INT16 GetBurstToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance )
|
||||
bonus += BonusReduceMore( Item[pObj->usItem].bursttohitbonus, (*pObj)[0]->data.objectStatus );
|
||||
// HEADROCK HAM B2.5: A certain setting in the New Tracer System can turn auto/burst penalties off
|
||||
// entirely, to make up for "Tracer Bump".
|
||||
if ( gGameExternalOptions.iRealisticTracers != 1 )
|
||||
if ( gGameExternalOptions.ubRealisticTracers != 1 )
|
||||
bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].bursttohitbonus ;
|
||||
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
|
||||
@@ -7234,7 +7255,7 @@ INT16 GetAutoToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance )
|
||||
// HEADROCK HAM B2.5: This external setting determines whether autofire penalty is affected by
|
||||
// tracer ammo. At setting "1", it is disabled. This goes hand in hand with a new tracer effect that
|
||||
// "bumps" CTH up after firing a tracer bullet.
|
||||
if ( gGameExternalOptions.iRealisticTracers != 1 )
|
||||
if ( gGameExternalOptions.ubRealisticTracers != 1 )
|
||||
bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].autofiretohitbonus ;
|
||||
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
|
||||
@@ -7648,6 +7669,26 @@ UINT8 GetPercentTunnelVision( SOLDIERTYPE * pSoldier )
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.2: Further increase tunnel-vision for cowering characters.
|
||||
if (gGameExternalOptions.ubCoweringReducesSightRange == 1 || gGameExternalOptions.ubCoweringReducesSightRange == 3)
|
||||
{
|
||||
INT8 bTolerance = CalcSuppressionTolerance( pSoldier );
|
||||
|
||||
// Make sure character is cowering.
|
||||
if ( pSoldier->aiData.bShock >= bTolerance && gGameExternalOptions.ubMaxSuppressionShock > 0 &&
|
||||
bonus < 100 )
|
||||
{
|
||||
// Calculates a "Flat" tunnel vision percentage
|
||||
UINT8 ubNormalCoweringTunnelVision = (100 * pSoldier->aiData.bShock) / gGameExternalOptions.ubMaxSuppressionShock;
|
||||
|
||||
// Apply that percentage to the current tunnel vision
|
||||
UINT16 usActualCoweringTunnelVision = bonus + (((100-bonus) * ubNormalCoweringTunnelVision) / 100);
|
||||
|
||||
// At shock 0, tunnel vision remains unchanged. At full shock, tunnel vision is full (100%)
|
||||
bonus = __min(100,usActualCoweringTunnelVision);
|
||||
}
|
||||
}
|
||||
|
||||
if ( PTR_OURTEAM ) // Madd: adjust tunnel vision by difficulty level
|
||||
return( bonus );
|
||||
else
|
||||
@@ -8495,106 +8536,122 @@ INT16 GetMinRangeForAimBonus( OBJECTTYPE * pObj )
|
||||
UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier)
|
||||
{
|
||||
UINT8 aimLevels = 4;
|
||||
float iScopeBonus = 0;
|
||||
UINT16 usScopeBonus = 0;
|
||||
BOOLEAN allowed = TRUE;
|
||||
|
||||
// HEADROCK HAM B2.6: Dynamic aiming level restrictions based on gun type and attachments.
|
||||
if ( gGameExternalOptions.fDynamicAimingTime )
|
||||
{
|
||||
UINT16 weaponRange;
|
||||
UINT8 weaponType, maxAimForType, maxAimWithoutBipod;
|
||||
BOOLEAN fTwoHanded, fUsingBipod;
|
||||
|
||||
// Read weapon data
|
||||
fTwoHanded = Item[pSoldier->inv[pSoldier->ubAttackingHand].usItem].twohanded;
|
||||
weaponRange = Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].usRange + GetRangeBonus(&pSoldier->inv[pSoldier->ubAttackingHand]);
|
||||
weaponType = Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubWeaponType;
|
||||
fUsingBipod = FALSE;
|
||||
|
||||
maxAimWithoutBipod = 4;
|
||||
|
||||
// Define basic (no attachments), and absolute maximums
|
||||
if (weaponType == GUN_PISTOL || weaponType == GUN_M_PISTOL || (weaponType == GUN_SMG && fTwoHanded == 0) || fTwoHanded == 0)
|
||||
if ( gGameSettings.fOptions[TOPTION_AIM_LEVEL_RESTRICTION] ) // Options Menu setting.
|
||||
{
|
||||
// HEADROCK HAM B2.6: Dynamic aiming level restrictions based on gun type and attachments.
|
||||
// HEADROCK HAM 3.5: Revamped this - it was illogically constructed.
|
||||
if ( gGameExternalOptions.fDynamicAimingTime )
|
||||
{
|
||||
maxAimForType = 2;
|
||||
aimLevels = 1;
|
||||
maxAimWithoutBipod = 2;
|
||||
}
|
||||
else if (weaponType == GUN_SHOTGUN || weaponType == GUN_LMG || (weaponType == GUN_SMG && fTwoHanded == 1))
|
||||
{
|
||||
maxAimForType = 3;
|
||||
aimLevels = 2;
|
||||
maxAimWithoutBipod = 3;
|
||||
}
|
||||
else if ((weaponType == GUN_AS_RIFLE || weaponType == GUN_RIFLE || weaponType == GUN_SN_RIFLE) && weaponRange <= 500)
|
||||
{
|
||||
maxAimForType = 4;
|
||||
aimLevels = 2;
|
||||
maxAimWithoutBipod = 3;
|
||||
}
|
||||
else if ((weaponType == GUN_AS_RIFLE || weaponType == GUN_RIFLE || weaponType == GUN_SN_RIFLE) && weaponRange > 500)
|
||||
{
|
||||
maxAimForType = 8;
|
||||
aimLevels = 3;
|
||||
UINT16 weaponRange;
|
||||
UINT8 weaponType, maxAimForType, maxAimWithoutBipod;
|
||||
BOOLEAN fTwoHanded, fUsingBipod;
|
||||
|
||||
// Read weapon data
|
||||
fTwoHanded = Item[pSoldier->inv[pSoldier->ubAttackingHand].usItem].twohanded;
|
||||
weaponRange = Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].usRange + GetRangeBonus(&pSoldier->inv[pSoldier->ubAttackingHand]);
|
||||
weaponType = Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubWeaponType;
|
||||
fUsingBipod = FALSE;
|
||||
|
||||
maxAimWithoutBipod = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Define basic (no attachments), and absolute maximums
|
||||
if (weaponType == GUN_PISTOL || weaponType == GUN_M_PISTOL || fTwoHanded == 0)
|
||||
{
|
||||
maxAimForType = 2;
|
||||
aimLevels = 1;
|
||||
maxAimWithoutBipod = 2;
|
||||
}
|
||||
else if (weaponType == GUN_SHOTGUN || weaponType == GUN_LMG || weaponType == GUN_SMG)
|
||||
{
|
||||
maxAimForType = 3;
|
||||
aimLevels = 2;
|
||||
maxAimWithoutBipod = 3;
|
||||
}
|
||||
else if ((weaponType == GUN_AS_RIFLE || weaponType == GUN_RIFLE ) && weaponRange <= 500)
|
||||
{
|
||||
maxAimForType = 4;
|
||||
aimLevels = 2;
|
||||
maxAimWithoutBipod = 3;
|
||||
}
|
||||
else if (((weaponType == GUN_AS_RIFLE || weaponType == GUN_RIFLE) && weaponRange > 500) ||
|
||||
(weaponType == GUN_SN_RIFLE && weaponRange <= 500))
|
||||
{
|
||||
maxAimForType = 6;
|
||||
aimLevels = 3;
|
||||
maxAimWithoutBipod = 4;
|
||||
}
|
||||
else if (weaponType == GUN_SN_RIFLE && weaponRange > 500)
|
||||
{
|
||||
maxAimForType = 8;
|
||||
aimLevels = 4;
|
||||
maxAimWithoutBipod = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Determine whether a bipod is being used (prone)
|
||||
if (GetBipodBonus(&pSoldier->inv[pSoldier->ubAttackingHand])>0 && gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE )
|
||||
{
|
||||
fUsingBipod = TRUE;
|
||||
// Determine whether a bipod is being used (prone)
|
||||
if (GetBipodBonus(&pSoldier->inv[pSoldier->ubAttackingHand])>0 && gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE )
|
||||
{
|
||||
fUsingBipod = TRUE;
|
||||
}
|
||||
|
||||
usScopeBonus = ( GetMinRangeForAimBonus(&pSoldier->inv[pSoldier->ubAttackingHand]) * 10 ) / gGameExternalOptions.ubStraightSightRange;
|
||||
|
||||
if ( usScopeBonus >= 50 ) // Scope Min Range >= 7 Tiles
|
||||
{
|
||||
aimLevels *= 2;
|
||||
}
|
||||
|
||||
else if ( usScopeBonus >= 30 ) // Scope Min Range >= 4 Tiles
|
||||
{
|
||||
aimLevels = (UINT8)((float)(aimLevels+1) * (float)1.5);
|
||||
}
|
||||
|
||||
else if ( usScopeBonus >= 15 ) // Scope Min Range >= 2 Tiles
|
||||
{
|
||||
aimLevels = (UINT8)((float)(aimLevels+1) * (float)1.3);
|
||||
}
|
||||
|
||||
// Smaller scopes increase by one.
|
||||
else if ( usScopeBonus > 0 )
|
||||
{
|
||||
aimLevels++;
|
||||
}
|
||||
|
||||
// Make sure not over maximum allowed for weapon type.
|
||||
if (aimLevels > maxAimForType)
|
||||
{
|
||||
aimLevels = maxAimForType;
|
||||
}
|
||||
// Make sure not over maximum allowed without a bipod.
|
||||
if (!fUsingBipod)
|
||||
{
|
||||
aimLevels = __min(aimLevels, maxAimWithoutBipod);
|
||||
}
|
||||
}
|
||||
|
||||
iScopeBonus = ( (float)gGameExternalOptions.ubStraightSightRange * GetMinRangeForAimBonus(&pSoldier->inv[pSoldier->ubAttackingHand]) / 100 );
|
||||
|
||||
if ( iScopeBonus >= ( (float)gGameExternalOptions.ubStraightSightRange * 0.6) ) // >= 60% of sight range (~9 tiles by default)
|
||||
else // JA2 1.13 Basic aiming restrictions (8 levels for 10x scope, 6 levels for 7x scope)
|
||||
{
|
||||
aimLevels = (UINT8)((float)aimLevels * (float)2);
|
||||
}
|
||||
|
||||
else if ( iScopeBonus >= ( (float)gGameExternalOptions.ubStraightSightRange * 0.3) ) // >= 30% of sight range (~4 tiles by default)
|
||||
{
|
||||
aimLevels = (UINT8)((float)(aimLevels+1) * (float)1.5);
|
||||
}
|
||||
|
||||
// Smaller scopes increase by one.
|
||||
else if ( iScopeBonus > 0 )
|
||||
{
|
||||
aimLevels++;
|
||||
}
|
||||
|
||||
// Make sure not over maximum allowed for weapon type.
|
||||
if (aimLevels > maxAimForType)
|
||||
{
|
||||
aimLevels = maxAimForType;
|
||||
}
|
||||
// Make sure not over maximum allowed without a bipod.
|
||||
if (!fUsingBipod)
|
||||
{
|
||||
aimLevels = __min(aimLevels, maxAimWithoutBipod);
|
||||
}
|
||||
}
|
||||
else // JA2 1.13 Basic aiming restrictions (8 levels for 10x scope, 6 levels for 7x scope)
|
||||
{
|
||||
if ( gGameSettings.fOptions[TOPTION_AIM_LEVEL_RESTRICTION] && Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubWeaponType != GUN_RIFLE && Weapon[pSoldier->inv[pSoldier->ubAttackingHand].usItem].ubWeaponType != GUN_SN_RIFLE )
|
||||
allowed = FALSE;
|
||||
|
||||
if ( allowed && IsScoped( &pSoldier->inv[pSoldier->ubAttackingHand] ) )
|
||||
{
|
||||
iScopeBonus = ( (float)gGameExternalOptions.ubStraightSightRange * GetMinRangeForAimBonus(&pSoldier->inv[pSoldier->ubAttackingHand]) / 100 );
|
||||
|
||||
if ( iScopeBonus >= ( (float)gGameExternalOptions.ubStraightSightRange * 0.3) ) // >= 30% of sight range (~4 tiles by default)
|
||||
{
|
||||
aimLevels += 2;
|
||||
}
|
||||
|
||||
if ( iScopeBonus >= ( (float)gGameExternalOptions.ubStraightSightRange * 0.6) ) // >= 60% of sight range (~9 tiles by default)
|
||||
{
|
||||
aimLevels += 2;
|
||||
if ( !IsScoped( &pSoldier->inv[pSoldier->ubAttackingHand] ) )
|
||||
{
|
||||
// No scope. 4 Allowed.
|
||||
return (4);
|
||||
}
|
||||
|
||||
usScopeBonus = ( GetMinRangeForAimBonus(&pSoldier->inv[pSoldier->ubAttackingHand]) * 10 ) / gGameExternalOptions.ubStraightSightRange;
|
||||
|
||||
if ( usScopeBonus >= 50 ) // Scope Min Range >= 7 Tiles (Sniper Scope)
|
||||
{
|
||||
aimLevels += 2;
|
||||
}
|
||||
if ( usScopeBonus >= 30 ) // Scope Min Range >= 4 Tiles (Battle Scope)
|
||||
{
|
||||
aimLevels += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8883,3 +8940,21 @@ INT16 GetBasicStealthBonus( OBJECTTYPE * pObj )
|
||||
return( bonus );
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: This is meant to squash an exploit where a backpack can be moved to your hand to avoid AP penalties.
|
||||
INT8 FindBackpackOnSoldier( SOLDIERTYPE * pSoldier )
|
||||
{
|
||||
INT8 bLoop;
|
||||
|
||||
for (bLoop = 0; bLoop < NUM_INV_SLOTS ; bLoop++)
|
||||
{
|
||||
if (pSoldier->inv[bLoop].exists())
|
||||
{
|
||||
if (Item[pSoldier->inv[bLoop].usItem].usItemClass == IC_LBEGEAR &&
|
||||
LoadBearingEquipment[Item[pSoldier->inv[bLoop].usItem].ubClassIndex].lbeClass == BACKPACK)
|
||||
{
|
||||
return( bLoop );
|
||||
}
|
||||
}
|
||||
}
|
||||
return( ITEM_NOT_FOUND );
|
||||
}
|
||||
+3
-2
@@ -18,7 +18,7 @@ extern UINT8 SlotToPocket[7];
|
||||
|
||||
extern BOOLEAN WeaponInHand( SOLDIERTYPE * pSoldier );
|
||||
|
||||
INT8 FindAmmo( SOLDIERTYPE * pSoldier, UINT8 ubCalibre, UINT16 ubMagSize, INT8 bExcludeSlot );
|
||||
INT8 FindAmmo( SOLDIERTYPE * pSoldier, UINT8 ubCalibre, UINT16 ubMagSize, UINT8 ubAmmoType, INT8 bExcludeSlot );
|
||||
|
||||
INT8 FindBestWeaponIfCurrentIsOutOfRange(SOLDIERTYPE * pSoldier, INT8 bCurrentWeaponIndex, UINT16 bWantedRange);
|
||||
|
||||
@@ -343,7 +343,8 @@ INT16 GetDesertCamoBonus( OBJECTTYPE * pObj );
|
||||
INT16 GetWornSnowCamo( SOLDIERTYPE * pSoldier );
|
||||
INT16 GetSnowCamoBonus( OBJECTTYPE * pObj );
|
||||
|
||||
|
||||
// HEADROCK HAM 3.6: Looks for a backpack anywhere on this character.
|
||||
INT8 FindBackpackOnSoldier( SOLDIERTYPE * pSoldier );
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+47
-14
@@ -48,6 +48,8 @@
|
||||
#include "fresh_header.h"
|
||||
#include "test_space.h"
|
||||
#include "WorldDat.h"
|
||||
// HEADROCK HAM 3.6: This must be included, for testing whether Bloodcats and Enemies can see one another.
|
||||
#include "Campaign Types.h"
|
||||
|
||||
//forward declarations of common classes to eliminate includes
|
||||
class OBJECTTYPE;
|
||||
@@ -2009,20 +2011,47 @@ INT32 SoldierToSoldierLineOfSightTest( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE
|
||||
fOk = CalculateSoldierZPos( pStartSoldier, LOS_POS, &dStartZPos );
|
||||
CHECKF( fOk );
|
||||
|
||||
if ( gWorldSectorX == 5 && gWorldSectorY == MAP_ROW_N )
|
||||
// HEADROCK HAM 3.6: Location of static sectors externalized, and there can be more than one. Also, modders can
|
||||
// determine whether bloodcats really are blind to enemies here at all.
|
||||
UINT8 ubSectorID = SECTOR(gWorldSectorX,gWorldSectorY);
|
||||
UINT8 PlacementType = gBloodcatPlacements[ ubSectorID ][ 0 ].PlacementType;
|
||||
// Does sector contain a Bloodcat Garrison?
|
||||
if (PlacementType == BLOODCAT_PLACEMENT_STATIC)
|
||||
{
|
||||
// in the bloodcat arena sector, skip sight between army & bloodcats
|
||||
if ( pStartSoldier->bTeam == ENEMY_TEAM && pEndSoldier->bTeam == CREATURE_TEAM )
|
||||
// Are bloodcats set to forgo attacking enemies?
|
||||
if (gBloodcatPlacements[ ubSectorID ][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation == QUEENS_CIV_GROUP)
|
||||
{
|
||||
return( 0 );
|
||||
// skip sight between army & bloodcats
|
||||
if ( pStartSoldier->bTeam == ENEMY_TEAM && pEndSoldier->bTeam == CREATURE_TEAM && pEndSoldier->ubBodyType == BLOODCAT )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
if ( pStartSoldier->bTeam == CREATURE_TEAM && pStartSoldier->ubBodyType == BLOODCAT && pEndSoldier->bTeam == ENEMY_TEAM )
|
||||
{
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
if ( pStartSoldier->bTeam == CREATURE_TEAM && pEndSoldier->bTeam == ENEMY_TEAM )
|
||||
else if (gBloodcatPlacements[ ubSectorID ][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation > NON_CIV_GROUP)
|
||||
{
|
||||
return( 0 );
|
||||
// Bloodcats in this sector belong to a faction. They adhere to certain rules as a result.
|
||||
if ( pEndSoldier->bTeam == CREATURE_TEAM && pEndSoldier->ubBodyType == BLOODCAT && pStartSoldier->bSide != gbPlayerNum)
|
||||
{
|
||||
// Target is a bloodcat. He can't be spotted by civilians no matter what.
|
||||
{
|
||||
return ( 0 );
|
||||
}
|
||||
}
|
||||
else if ( pStartSoldier->bTeam == CREATURE_TEAM && pStartSoldier->ubBodyType == BLOODCAT )
|
||||
{
|
||||
// Source is a bloodcat. He can only spot player-side soldiers, and only if hostile.
|
||||
if ( pEndSoldier->bSide != gbPlayerNum || pStartSoldier->aiData.bNeutral )
|
||||
{
|
||||
return ( 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (pStartSoldier->flags.uiStatusFlags & SOLDIER_MONSTER)
|
||||
{
|
||||
// monsters use smell instead of sight!
|
||||
@@ -4002,11 +4031,11 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
|
||||
}
|
||||
// HEADROCK HAM B2.5: Set tracer effect on/off for individual bullets in a Tracer Magazine, as part of the
|
||||
// New Tracer System.
|
||||
else if (gGameExternalOptions.iRealisticTracers > 0 && gGameExternalOptions.iNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0)
|
||||
else if (gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0)
|
||||
&& AmmoTypes[ pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType ].tracerEffect )
|
||||
{
|
||||
UINT16 iBulletsLeft, iBulletsPerTracer;
|
||||
iBulletsPerTracer = gGameExternalOptions.iNumBulletsPerTracer;
|
||||
iBulletsPerTracer = gGameExternalOptions.ubNumBulletsPerTracer;
|
||||
iBulletsLeft = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunShotsLeft + pFirer->bDoBurst;
|
||||
|
||||
if ((((iBulletsLeft - (pFirer->bDoBurst - 1)) / iBulletsPerTracer) - ((iBulletsLeft - pFirer->bDoBurst) / iBulletsPerTracer)) == 1)
|
||||
@@ -4345,11 +4374,11 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
|
||||
pBullet->iDistanceLimit = iDistance;
|
||||
// HEADROCK HAM BETA2.5: New method for signifying whether a bullet is a tracer or not, using an individual
|
||||
// bullet structure flag. Hehehehe, I think this is kind of reverting to old code, isn't it?
|
||||
if (gGameExternalOptions.iRealisticTracers > 0 && gGameExternalOptions.iNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0)
|
||||
if (gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && (pFirer->bDoAutofire > 0 || pFirer->bDoBurst > 0)
|
||||
&& AmmoTypes[ pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType ].tracerEffect )
|
||||
{
|
||||
UINT16 iBulletsLeft, iBulletsPerTracer;
|
||||
iBulletsPerTracer = gGameExternalOptions.iNumBulletsPerTracer;
|
||||
iBulletsPerTracer = gGameExternalOptions.ubNumBulletsPerTracer;
|
||||
iBulletsLeft = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunShotsLeft + pFirer->bDoBurst;
|
||||
|
||||
// Is this specific bullet a tracer? - based on how many tracers there are per regular bullets in
|
||||
@@ -4686,9 +4715,13 @@ void MoveBullet( INT32 iBullet )
|
||||
|
||||
if ( IS_MERC_BODY_TYPE( MercPtrs[pStructure->usStructureID] ) )
|
||||
{
|
||||
// HEADROCK HAM 3.3: Externalized distance at which characters suffer from friendly suppression.
|
||||
// previously relied on minimum distance at which characters may suffer from friendly fire HITS.
|
||||
UINT16 MIN_DIST_FOR_SCARE_FRIENDS = gGameExternalOptions.usMinDistanceFriendlySuppression;
|
||||
|
||||
// apply suppression, regardless of friendly or enemy
|
||||
// except if friendly, not within a few tiles of shooter
|
||||
if ( MercPtrs[ pStructure->usStructureID ]->bSide != pBullet->pFirer->bSide || pBullet->iLoop > MIN_DIST_FOR_HIT_FRIENDS )
|
||||
if ( MercPtrs[ pStructure->usStructureID ]->bSide != pBullet->pFirer->bSide || pBullet->iLoop > MIN_DIST_FOR_SCARE_FRIENDS )
|
||||
{
|
||||
// buckshot has only a 1 in 2 chance of applying a suppression point
|
||||
if ( !(pBullet->usFlags & BULLET_FLAG_BUCKSHOT) || Random( 2 ) )
|
||||
@@ -4915,7 +4948,7 @@ void MoveBullet( INT32 iBullet )
|
||||
// HEADROCK HAM B2.5: Changed condition to read fTracer flag directly from bullet's struct.
|
||||
// This is for the New Tracer System.
|
||||
if (( pBullet->usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT /*| BULLET_FLAG_TRACER*/ ) )
|
||||
|| ((gGameExternalOptions.iRealisticTracers > 0 && gGameExternalOptions.iNumBulletsPerTracer > 0 && pBullet->fTracer == TRUE) || (gGameExternalOptions.iRealisticTracers == 0 && fTracer == TRUE)))
|
||||
|| ((gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && pBullet->fTracer == TRUE) || (gGameExternalOptions.ubRealisticTracers == 0 && fTracer == TRUE)))
|
||||
{
|
||||
INT8 bStepsPerMove = STEPS_FOR_BULLET_MOVE_TRAILS;
|
||||
|
||||
@@ -5205,7 +5238,7 @@ void MoveBullet( INT32 iBullet )
|
||||
// HEADROCK HAM B2.5: Changed condition to read fTracer flag directly from bullet's struct.
|
||||
// This is for the New Tracer System.
|
||||
if (( pBullet->usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT /*| BULLET_FLAG_TRACER */) )
|
||||
|| ((gGameExternalOptions.iRealisticTracers > 0 && gGameExternalOptions.iNumBulletsPerTracer > 0 && pBullet->fTracer == TRUE) || (gGameExternalOptions.iRealisticTracers == 0 && fTracer == TRUE)))
|
||||
|| ((gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && pBullet->fTracer == TRUE) || (gGameExternalOptions.ubRealisticTracers == 0 && fTracer == TRUE)))
|
||||
{
|
||||
INT8 bStepsPerMove = STEPS_FOR_BULLET_MOVE_TRAILS;
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "stdlib.h"
|
||||
#include "debug.h"
|
||||
//#include "soldier control.h"
|
||||
// HEADROCK HAM 3.5: Strange that this wasn't included.
|
||||
#include "GameSettings.h"
|
||||
#include "weapons.h"
|
||||
#include "handle items.h"
|
||||
#include "worlddef.h"
|
||||
@@ -39,6 +41,8 @@
|
||||
#include "Dialogue Control.h"
|
||||
#include "Music Control.h"
|
||||
#include "Tactical Save.h"
|
||||
// HEADROCK HAM 3.5: Need this to see if enemies present at starting sector
|
||||
#include "Overhead.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -476,7 +480,8 @@ void HandleHeliDrop( )
|
||||
{
|
||||
// Add merc to sector
|
||||
MercPtrs[ gusHeliSeats[ cnt ] ]->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
|
||||
UpdateMercInSector( MercPtrs[ gusHeliSeats[ cnt ] ], startingX, startingY, startingZ );
|
||||
// HEADROCK HAM 3.5: Externalized!
|
||||
UpdateMercInSector( MercPtrs[ gusHeliSeats[ cnt ] ], gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ );
|
||||
|
||||
// Check for merc arrives quotes...
|
||||
HandleMercArrivesQuotes( MercPtrs[ gusHeliSeats[ cnt ] ] );
|
||||
@@ -612,7 +617,8 @@ void HandleHeliDrop( )
|
||||
// Change insertion code
|
||||
MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
|
||||
|
||||
UpdateMercInSector( MercPtrs[ gusHeliSeats[ gbCurDrop ] ], startingX, startingY, startingZ );
|
||||
// HEADROCK HAM 3.5: Externalized!
|
||||
UpdateMercInSector( MercPtrs[ gusHeliSeats[ gbCurDrop ] ], gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ );
|
||||
//EVENT_SetSoldierPosition( MercPtrs[ gusHeliSeats[ gbCurDrop ] ], sWorldX, sWorldY );
|
||||
|
||||
// IF the first guy down, set squad!
|
||||
@@ -777,6 +783,11 @@ void HandleHeliDrop( )
|
||||
|
||||
// End
|
||||
fFadingHeliOut = TRUE;
|
||||
|
||||
// HEADROCK HAM 3.5: Update now, in case the LZ is still in a "RED" airspace sector. This is only
|
||||
// required if the sector is free of enemies... but still required. Will run immediately after the
|
||||
// helicopter is gone.
|
||||
UpdateAirspaceControl( );
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -812,13 +823,25 @@ void HandleFirstHeliDropOfGame( )
|
||||
CallAvailableEnemiesTo( gsGridNoSweetSpot );
|
||||
|
||||
// Move to header file...
|
||||
AddExtraItems( startingX, startingY, startingZ, true );
|
||||
// HEADROCK HAM 3.5: Externalized!
|
||||
AddExtraItems( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ, true );
|
||||
|
||||
// Say quote.....
|
||||
SayQuoteFromAnyBodyInSector( QUOTE_ENEMY_PRESENCE );
|
||||
|
||||
// Start music
|
||||
SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT );
|
||||
// HEADROCK HAM 3.5: Starting sector externalized - might not contain enemies at all!
|
||||
if (NumEnemyInSector( ) > 0)
|
||||
//if ( NumEnemiesInAnySector( gWorldSectorX, gWorldSectorY, 0 ) > 0 )
|
||||
{
|
||||
// Say quote.....
|
||||
SayQuoteFromAnyBodyInSector( QUOTE_ENEMY_PRESENCE );
|
||||
// Start music
|
||||
SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Say quote.....
|
||||
SayQuoteFromAnyBodyInSector( QUOTE_MERC_REACHED_DESTINATION );
|
||||
// Start music
|
||||
SetMusicMode( MUSIC_TACTICAL_NOTHING );
|
||||
}
|
||||
|
||||
gfFirstHeliRun = FALSE;
|
||||
|
||||
@@ -826,6 +849,7 @@ void HandleFirstHeliDropOfGame( )
|
||||
|
||||
// Send message to turn on ai again....
|
||||
CharacterDialogueWithSpecialEvent( 0, 0, 0, DIALOGUE_TACTICAL_UI , FALSE , FALSE , DIALOGUE_SPECIAL_EVENT_ENABLE_AI ,0, 0 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+17
-12
@@ -78,8 +78,9 @@ extern BOOLEAN gfFirstHeliRun;
|
||||
// ATE: Globals that dictate where the mercs will land once being hired
|
||||
// Default to Omerta
|
||||
// Saved in general saved game structure
|
||||
INT16 gsMercArriveSectorX = 9;
|
||||
INT16 gsMercArriveSectorY = 1;
|
||||
// HEADROCK HAM 3.5: Externalized coordinates
|
||||
INT16 gsMercArriveSectorX = gGameExternalOptions.ubDefaultArrivalSectorX;
|
||||
INT16 gsMercArriveSectorY = gGameExternalOptions.ubDefaultArrivalSectorY;
|
||||
|
||||
void CheckForValidArrivalSector( );
|
||||
|
||||
@@ -317,16 +318,20 @@ void MercArrivesCallback( UINT8 ubSoldierID )
|
||||
if (!is_networked)
|
||||
{
|
||||
// hayden - maybe you want to duke it out in omerta ;)
|
||||
if( !DidGameJustStart() && gsMercArriveSectorX == 9 && gsMercArriveSectorY == 1 )
|
||||
{
|
||||
//Mercs arriving in A9. This sector has been deemed as the always safe sector.
|
||||
//Seeing we don't support entry into a hostile sector (except for the beginning),
|
||||
//we will nuke any enemies in this sector first.
|
||||
if( gWorldSectorX != 9 || gWorldSectorY != 1 || gbWorldSectorZ )
|
||||
{
|
||||
EliminateAllEnemies( (UINT8)gsMercArriveSectorX, (UINT8)gsMercArriveSectorY );
|
||||
}
|
||||
}
|
||||
// HEADROCK HAM 3.5: Externalized starting (safe) sector
|
||||
// HEADROCK HAM 3.5: Actually, this is really ridiculous. Why should enemies at the LZ be eliminated at all?
|
||||
// I'm taking the initiative and removing this from the code. Mainly because it ends up interfering with
|
||||
// externalized LZs combined with other features like "Always Real Time" and "Forced Turn Based".
|
||||
//if( !DidGameJustStart() && gsMercArriveSectorX == gGameExternalOptions.ubDefaultArrivalSectorX && gsMercArriveSectorY == gGameExternalOptions.ubDefaultArrivalSectorY )
|
||||
// {
|
||||
// //Mercs arriving in A9. This sector has been deemed as the always safe sector.
|
||||
// //Seeing we don't support entry into a hostile sector (except for the beginning),
|
||||
// //we will nuke any enemies in this sector first.
|
||||
// if( gWorldSectorX != gGameExternalOptions.ubDefaultArrivalSectorX || gWorldSectorY != gGameExternalOptions.ubDefaultArrivalSectorY || gbWorldSectorZ )
|
||||
// {
|
||||
// EliminateAllEnemies( (UINT8)gsMercArriveSectorX, (UINT8)gsMercArriveSectorY );
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// This will update ANY soldiers currently schedules to arrive too
|
||||
|
||||
+39
-2
@@ -21,6 +21,8 @@
|
||||
#include "mapscreen.h"
|
||||
#include "Soldier macros.h"
|
||||
#include "Event Pump.h"
|
||||
// HEADROCK HAM 3.5: Added for facility effect on morale
|
||||
#include "Facilities.h"
|
||||
#endif
|
||||
|
||||
#include "connect.h"
|
||||
@@ -137,14 +139,19 @@ void DecayTacticalMorale( SOLDIERTYPE * pSoldier )
|
||||
|
||||
void DecayStrategicMorale( SOLDIERTYPE * pSoldier )
|
||||
{
|
||||
// HEADROCK HAM 3.5: Strategic Morale Mod no longer normalizes to 0 by default. In fact, a local facility can
|
||||
// cause normalization to another value (positive or negative!), based on the activity that the character is
|
||||
// currently performing. It can literally reduce morale to ridiculously low amounts if you don't watch your
|
||||
// assignments in some sectors.
|
||||
|
||||
// decay the modifier!
|
||||
if (pSoldier->aiData.bStrategicMoraleMod > 0)
|
||||
{
|
||||
pSoldier->aiData.bStrategicMoraleMod = __max( 0, pSoldier->aiData.bStrategicMoraleMod - (8 - pSoldier->aiData.bStrategicMoraleMod / 10) );
|
||||
pSoldier->aiData.bStrategicMoraleMod = __max( 0, pSoldier->aiData.bStrategicMoraleMod - (8 - (pSoldier->aiData.bStrategicMoraleMod / 10)) );
|
||||
}
|
||||
else
|
||||
{
|
||||
pSoldier->aiData.bStrategicMoraleMod = __min( 0, pSoldier->aiData.bStrategicMoraleMod + (6 + pSoldier->aiData.bStrategicMoraleMod / 10) );
|
||||
pSoldier->aiData.bStrategicMoraleMod = __min( 0, pSoldier->aiData.bStrategicMoraleMod + (6 + (pSoldier->aiData.bStrategicMoraleMod / 10)) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,6 +302,36 @@ void RefreshSoldierMorale( SOLDIERTYPE * pSoldier )
|
||||
|
||||
iActualMorale = __min( 100, iActualMorale );
|
||||
iActualMorale = __max( 0, iActualMorale );
|
||||
|
||||
UINT8 ubMaxMorale = 100;
|
||||
// HEADROCK HAM 3.5: Local facilities may decrease the total morale allowed.
|
||||
for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; cnt++)
|
||||
{
|
||||
if (gFacilityLocations[SECTOR(pSoldier->sSectorX, pSoldier->sSectorY)][cnt].fFacilityHere)
|
||||
{
|
||||
if (cnt == (UINT16)pSoldier->sFacilityTypeOperated && // Soldier is operating this facility
|
||||
GetSoldierFacilityAssignmentIndex( pSoldier ) != -1)
|
||||
{
|
||||
UINT8 ubFacilityType = (UINT8)cnt;
|
||||
UINT8 ubAssignmentType = GetSoldierFacilityAssignmentIndex( pSoldier );
|
||||
// Check this facility both for an assignment-specific AND ambient value. Use it if it's the lowest
|
||||
// encountered yet.
|
||||
ubMaxMorale = __min(ubMaxMorale, (UINT8)GetFacilityModifier(FACILITY_MAX_MORALE, ubFacilityType, ubAssignmentType ));
|
||||
}
|
||||
else // Soldier is not operating this facility
|
||||
{
|
||||
// Check this facility for an AMBIENT Maximum Morale limit. Use it if it's the lowest encountered yet.
|
||||
ubMaxMorale = __min(ubMaxMorale, (UINT8)GetFacilityModifier(FACILITY_MAX_MORALE, (UINT8)cnt, FAC_AMBIENT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ubMaxMorale > 0 && iActualMorale > ubMaxMorale)
|
||||
{
|
||||
// Normalize to Max Morale
|
||||
iActualMorale = (iActualMorale + ubMaxMorale) / 2;
|
||||
}
|
||||
|
||||
pSoldier->aiData.bMorale = (INT8) iActualMorale;
|
||||
|
||||
// update mapscreen as needed
|
||||
|
||||
@@ -265,8 +265,9 @@ enum WorldDirections
|
||||
|
||||
|
||||
// Starting Sector
|
||||
const int startingX = 9;
|
||||
const int startingY = 1;
|
||||
// HEADROCK HAM 3.5: Externalized.
|
||||
//UINT8 startingX = 9;
|
||||
//UINT8 startingY = 1;
|
||||
const int startingZ = 0;
|
||||
|
||||
|
||||
|
||||
+309
-168
@@ -180,6 +180,8 @@ void HandleEndDemoInCreatureLevel( );
|
||||
void DeathTimerCallback( void );
|
||||
void CaptureTimerCallback( void );
|
||||
|
||||
// HEADROCK HAM 3.6: Define now.
|
||||
void MilitiaChangesSides( void );
|
||||
|
||||
extern void CheckForAlertWhenEnemyDies( SOLDIERTYPE * pDyingSoldier );
|
||||
extern void PlaySoldierFootstepSound( SOLDIERTYPE *pSoldier );
|
||||
@@ -2224,6 +2226,22 @@ BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLE
|
||||
// better stop and reconsider what to do...
|
||||
SetNewSituation( pSoldier );
|
||||
ActionDone( pSoldier );
|
||||
|
||||
// HEADROCK HAM 3.6: Militia can now place flags when they spot landmines.
|
||||
if (gGameExternalOptions.fMilitiaPlaceBlueFlags &&
|
||||
pSoldier->bTeam == MILITIA_TEAM)
|
||||
{
|
||||
// This line causes the screen to focus on the gridno if it is not currently visible.
|
||||
// Is it desirable when militia spot mines? Probably not. Turned off for now.
|
||||
//LocateGridNo( sMineGridNo );
|
||||
|
||||
// Flash gridno
|
||||
ITEM_POOL *pItemPool = NULL;
|
||||
GetItemPool( sMineGridNo, &pItemPool, 0 );
|
||||
SetItemPoolLocator( pItemPool );
|
||||
// Add flag
|
||||
AddBlueFlag(sMineGridNo,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3593,7 +3611,17 @@ void HandleNPCTeamMemberDeath( SOLDIERTYPE *pSoldierOld )
|
||||
if ( pSoldierOld->ubAttackerID != NOBODY )
|
||||
{
|
||||
// also treat this as murder - but player will never be blamed for militia death he didn't cause
|
||||
HandleMurderOfCivilian( pSoldierOld, pSoldierOld->flags.fIntendedTarget );
|
||||
// HEADROCK HAM 3.6: Actually this function never runs for militia (see function for details)
|
||||
//HandleMurderOfCivilian( pSoldierOld, pSoldierOld->flags.fIntendedTarget );
|
||||
|
||||
// HEADROCK HAM 3.6: INI setting can cause militia to turn ONLY of they are killed intentionally
|
||||
if (pSoldierOld->flags.fIntendedTarget // Must be intentional
|
||||
&& gGameExternalOptions.ubCanMilitiaBecomeHostile > 0 // INI setting
|
||||
&& pSoldierOld->bSide == gbPlayerNum // Must not be hostile by now
|
||||
)
|
||||
{
|
||||
MilitiaChangesSides(); // Militia turn on you.
|
||||
}
|
||||
}
|
||||
|
||||
HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_NATIVE_KILLED, gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
||||
@@ -3854,7 +3882,12 @@ void MakeCivHostile( SOLDIERTYPE *pSoldier, INT8 bNewSide )
|
||||
}
|
||||
if ( pSoldier->aiData.bNeutral )
|
||||
{
|
||||
SetSoldierNonNeutral( pSoldier );
|
||||
// HEADROCK HAM 3.6: INI Setting decides whether non-combat civs can become hostile
|
||||
if (gGameExternalOptions.fCanTrueCiviliansBecomeHostile ||
|
||||
!IS_CIV_BODY_TYPE(pSoldier))
|
||||
{
|
||||
SetSoldierNonNeutral( pSoldier );
|
||||
}
|
||||
RecalculateOppCntsDueToNoLongerNeutral( pSoldier );
|
||||
}
|
||||
}
|
||||
@@ -3979,6 +4012,13 @@ SOLDIERTYPE * CivilianGroupMemberChangesSides( SOLDIERTYPE * pAttacked )
|
||||
gTacticalStatus.fCivGroupHostile[ pNewAttacked->ubCivilianGroup ] = CIV_GROUP_WILL_EVENTUALLY_BECOME_HOSTILE;
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: If this sector has affiliated bloodcats, make them all hostile.
|
||||
if ( gBloodcatPlacements[SECTOR(pNewAttacked->sSectorX,pNewAttacked->sSectorY)][0].PlacementType == BLOODCAT_PLACEMENT_STATIC &&
|
||||
gBloodcatPlacements[SECTOR(pNewAttacked->sSectorX,pNewAttacked->sSectorY)][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation == pNewAttacked->ubCivilianGroup )
|
||||
{
|
||||
MakeBloodcatsHostile();
|
||||
}
|
||||
|
||||
return( pNewAttacked );
|
||||
}
|
||||
|
||||
@@ -6203,26 +6243,27 @@ void DeathNoMessageTimerCallback( void )
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.5: This function needs a Z-Level argument!!! It is screwing up garrisons, when a battle is won underneath
|
||||
// a sector.
|
||||
void RemoveStaticEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
||||
{
|
||||
if (!bMapZ) // Battle ended Above-ground
|
||||
{
|
||||
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
|
||||
if (!bMapZ) // Battle ended Above-ground
|
||||
{
|
||||
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
|
||||
|
||||
pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = 0;
|
||||
pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
UNDERGROUND_SECTORINFO *pSectorInfo;
|
||||
|
||||
pSectorInfo = FindUnderGroundSector( sMapX, sMapY, bMapZ );
|
||||
pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = 0;
|
||||
pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = 0;
|
||||
}
|
||||
pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = 0;
|
||||
pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
UNDERGROUND_SECTORINFO *pSectorInfo;
|
||||
|
||||
pSectorInfo = FindUnderGroundSector( sMapX, sMapY, bMapZ );
|
||||
pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = 0;
|
||||
pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//!!!!
|
||||
//IMPORTANT NEW NOTE:
|
||||
//Whenever returning TRUE, make sure you clear gfBlitBattleSectorLocator;
|
||||
@@ -6383,6 +6424,9 @@ BOOLEAN CheckForEndOfBattle( BOOLEAN fAnEnemyRetreated )
|
||||
}
|
||||
|
||||
// Kill all enemies. Sometime even after killing all the enemies, there appeares "in battle" enemies in sector info
|
||||
// HEADROCK HAM 3.5: This has to take Z-Level into account, otherwise winning a battle underground will kill all
|
||||
// enemies in the sector above! We still need to run the function though, to prevent confusions with the
|
||||
// strategic screen, which is what it was doing only for aboveground. UNTIL NOW, muahaha.
|
||||
RemoveStaticEnemiesFromSectorInfo( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
||||
|
||||
|
||||
@@ -7221,15 +7265,20 @@ INT8 CalcSuppressionTolerance( SOLDIERTYPE * pSoldier )
|
||||
}
|
||||
}
|
||||
|
||||
if (bTolerance < gGameExternalOptions.iSuppressionToleranceMin)
|
||||
// HEADROCK HAM 3.2: This is actually a feature from HAM 2.9. It adds bonuses/penalties for nearby friends.
|
||||
if (gGameExternalOptions.fFriendliesAffectTolerance)
|
||||
{
|
||||
bTolerance = gGameExternalOptions.iSuppressionToleranceMin;
|
||||
bTolerance += CheckStatusNearbyFriendlies( pSoldier );
|
||||
}
|
||||
|
||||
if (bTolerance > gGameExternalOptions.iSuppressionToleranceMax)
|
||||
// HEADROCK HAM 3.3: Moving rapidly makes one less prone to suppression.
|
||||
if (gGameExternalOptions.ubTilesMovedPerBonusTolerancePoint > 0)
|
||||
{
|
||||
bTolerance = gGameExternalOptions.iSuppressionToleranceMax;
|
||||
bTolerance += pSoldier->bTilesMoved / gGameExternalOptions.ubTilesMovedPerBonusTolerancePoint;
|
||||
}
|
||||
|
||||
bTolerance = __max(bTolerance, gGameExternalOptions.ubSuppressionToleranceMin);
|
||||
bTolerance = __min(bTolerance, gGameExternalOptions.ubSuppressionToleranceMax);
|
||||
|
||||
return( bTolerance );
|
||||
}
|
||||
@@ -7239,163 +7288,154 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// HEADROCK HAM B2: This entire function has been completely revamped.
|
||||
// HEADROCK HAM 3.5: Revamped again.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// External options.
|
||||
BOOLEAN APS_SUPPRESSED = gGameExternalOptions.fSuppressionAPLossPerAttack;
|
||||
BOOLEAN APS_SUPPRESSED_TOTAL = gGameExternalOptions.fSuppressionAPLossPerTurn;
|
||||
//INT8 SUPPRESSION_AP_LIMIT = gGameExternalOptions.iMinAPLimitFromSuppression;
|
||||
INT8 MAXIMUM_SUPPRESSION_SHOCK = gGameExternalOptions.iMaxSuppressionShock;
|
||||
INT8 bTolerance;
|
||||
INT16 sClosestOpponent, sClosestOppLoc;
|
||||
UINT8 ubPointsLost, ubTotalPointsLost, ubNewStance;
|
||||
UINT32 uiLoop;
|
||||
// This function runs after very attack is completed. It calculates the number
|
||||
// of "Suppression Points" any character has received during the attack, and
|
||||
// inflicts various penalties accordingly.
|
||||
// The most important result of this function is AP loss.
|
||||
|
||||
SOLDIERTYPE * pSoldier;
|
||||
|
||||
INT8 bTolerance;
|
||||
INT16 sClosestOpponent, sClosestOppLoc;
|
||||
UINT8 ubPointsLost, ubNewStance;
|
||||
UINT32 uiLoop;
|
||||
UINT8 ubLoop2;
|
||||
// Flag to determine if the target is cowering (if allowed)
|
||||
BOOLEAN fCower;
|
||||
SOLDIERTYPE * pSoldier;
|
||||
BOOLEAN fCower;
|
||||
|
||||
// External options
|
||||
|
||||
// JA2_OPTIONS.INI
|
||||
INT8 MAXIMUM_SUPPRESSION_SHOCK = gGameExternalOptions.ubMaxSuppressionShock;
|
||||
|
||||
// APBPConstants.INI
|
||||
UINT16 usLimitSuppressionAPsLostPerAttack = APBPConstants[AP_MAX_SUPPRESSED];
|
||||
UINT16 usLimitSuppressionAPsLostPerTurn = APBPConstants[AP_MAX_TURN_SUPPRESSED];
|
||||
//HEADROCK HAM 3.5: Ratio between AP Loss and Suppression Shock
|
||||
UINT16 uiShockPerAPLossDivisor = APBPConstants[AP_SUPPRESSION_SHOCK_DIVISOR];
|
||||
|
||||
// Loop through every character.
|
||||
for (uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++)
|
||||
{
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: loop = %d, numslots = %d ",uiLoop, guiNumMercSlots));
|
||||
pSoldier = MercSlots[uiLoop];
|
||||
|
||||
// Has this character received any Suppression Points since the last attack?
|
||||
// HEADROCK: Suppression Points accumulate by bullets flying near the character. It includes
|
||||
// friendly fire at a certain distance. As of HAM 3.2, it also happens with nearby explosions.
|
||||
// The number of points accumulated resets to 0 at the end of this function.
|
||||
|
||||
if (pSoldier && IS_MERC_BODY_TYPE( pSoldier) && pSoldier->stats.bLife >= OKLIFE && pSoldier->ubSuppressionPoints > 0)
|
||||
{
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: soldier id = %d, life = %d, suppression points = %d",pSoldier->ubID,pSoldier->stats.bLife, pSoldier->ubSuppressionPoints));
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: calc suppression tolerance"));
|
||||
|
||||
// Calculate the character's tolerance to suppression. Helps reduce the severity of the penalties inflicted
|
||||
// during this function.
|
||||
bTolerance = CalcSuppressionTolerance( pSoldier );
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: figure out aps lost"));
|
||||
// multiply by 2, add 1 and divide by 2 to round off to nearest whole number
|
||||
// HEADROCK: Note that suppression points accumulate by bullets flying near the character. It includes
|
||||
// friendly fire at a certain distance. Also note that it may be reset either each attack or each turn
|
||||
// (based on new INI settings), which has a small effect on how suppression builds up (but nothing
|
||||
// major).
|
||||
|
||||
// This formula gives a linear increase in AP loss relative to Suppression Points. The most Suppression
|
||||
// Points we have, the most APs we're going to lose. Tolerance mitigates this by making the graph angle
|
||||
// more shallow.
|
||||
// The relation between AP Loss and Suppression Points is LINEAR.
|
||||
ubPointsLost = ( ( (pSoldier->ubSuppressionPoints * APBPConstants[AP_SUPPRESSION_MOD]) / (bTolerance + 6) ) * 2 + 1 ) / 2;
|
||||
|
||||
// HEADROCK HAM Beta 2.2: SuppressionEffectiveness acts as a percentage for the number of lost APs.
|
||||
ubPointsLost = ( ubPointsLost * gGameExternalOptions.iSuppressionEffectiveness ) / 100;
|
||||
// INI-Controlled intensity. SuppressionEffectiveness acts as a percentage applied to the number of lost APs.
|
||||
// To turn off the entire Suppression system, simply set the INI value to 0. (0% AP Loss)
|
||||
// The default is obviously 100%. You can increase or decrease it, at will.
|
||||
// PLEASE NOTE that AP loss governs ALL OTHER SUPPRESSION EFFECTS.
|
||||
ubPointsLost = ( ubPointsLost * gGameExternalOptions.sSuppressionEffectiveness ) / 100;
|
||||
|
||||
// reduce loss of APs based on stance
|
||||
// ATE: Taken out because we can possibly supress ourselves...
|
||||
//switch (gAnimControl[ pSoldier->usAnimState ].ubEndHeight)
|
||||
//{
|
||||
// case ANIM_PRONE:
|
||||
// ubPointsLost = ubPointsLost * 2 / 4;
|
||||
// break;
|
||||
// case ANIM_CROUCH:
|
||||
// ubPointsLost = ubPointsLost * 3 / 4;
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
//}
|
||||
|
||||
// cap the # of APs we can lose
|
||||
// HEADROCK HAM B2: This now reads an external value. 0 means no limit.
|
||||
if (APS_SUPPRESSED == TRUE)
|
||||
// This is an upper cap for the number of APs we can lose per attack.
|
||||
if (usLimitSuppressionAPsLostPerAttack > 0)
|
||||
{
|
||||
if (ubPointsLost > APBPConstants[AP_MAX_SUPPRESSED])
|
||||
if (ubPointsLost > usLimitSuppressionAPsLostPerAttack)
|
||||
{
|
||||
ubPointsLost = (UINT8)APBPConstants[AP_MAX_SUPPRESSED];
|
||||
ubPointsLost = __max(255,(UINT8)usLimitSuppressionAPsLostPerAttack);
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2: This makes sure that we never lose more APs than we're allowed per turn,
|
||||
if (APS_SUPPRESSED_TOTAL = TRUE)
|
||||
// This makes sure that we never lose more APs than we're allowed per turn.
|
||||
if (usLimitSuppressionAPsLostPerTurn > 0)
|
||||
{
|
||||
if (pSoldier->ubAPsLostToSuppression + ubPointsLost > APBPConstants[AP_MAX_TURN_SUPPRESSED])
|
||||
{
|
||||
ubPointsLost = APBPConstants[AP_MAX_TURN_SUPPRESSED] - pSoldier->ubAPsLostToSuppression;
|
||||
ubPointsLost = usLimitSuppressionAPsLostPerTurn - pSoldier->ubAPsLostToSuppression;
|
||||
}
|
||||
}
|
||||
// Keeps a number for later reference
|
||||
ubTotalPointsLost = ubPointsLost;
|
||||
|
||||
// Make sure we're suffering extra AP loss at all. If the number of APs we're supposed to lose now
|
||||
// is equal/higher to the number of APs we've already lost, it means we haven't actually gained any
|
||||
// suppression. This is very important, as this function runs EVERY TIME an attack, ANY attack, ends.
|
||||
// If the soldier hasn't suffered suppression since the last time this check ran, we'll hit the
|
||||
// "continue" command. Note that with a certain INI setting, this value is reset after each attack
|
||||
// or after each turn, but overall the function acts the same in both cases.
|
||||
if (pSoldier->ubAPsLostToSuppression >= ubPointsLost)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// APs actually lost will be the difference between the potential loss and the APs we've already lost
|
||||
// so far. Would theoretically equal 0 if we haven't suffered sufficient extra suppression this turn to
|
||||
// cause any AP loss, but then we would've already hit the "continue" command, above.
|
||||
ubPointsLost -= pSoldier->ubAPsLostToSuppression;
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: check for morale effects"));
|
||||
|
||||
// HEADROCK HAM B2: This nifty little bit gives suppression an "extra kick". Soldiers affected by
|
||||
// suppression (I.E. lost APs) will also suffer from SHOCK. This is similar to getting shot but
|
||||
// without the health/stamina loss - the soldier will lose 5% CTH for every point of shock they suffer.
|
||||
// Shock is sliced in half at the start of every turn. Also note that shock may cause "cowering", and
|
||||
// may also reduce any attacker's aim as well!
|
||||
if (gGameExternalOptions.fSuppressionShock)
|
||||
// This nifty little bit gives suppression an "extra kick". Soldiers affected by suppression (I.E. lost APs)
|
||||
// will also suffer from SHOCK. As shock accumulates, the soldier becomes less accurate and may find it
|
||||
// difficult to perform certain manual tasks. Additionally, he also becomes harder to hit, because the fear
|
||||
// causes him to hide as best as he can from incoming fire.
|
||||
// Shock is sliced in half at the start of every turn. Also note that shock may cause "cowering" (see below).
|
||||
if (gGameExternalOptions.usSuppressionShockEffect > 0)
|
||||
{
|
||||
// Can't get shock if we haven't lost APs.
|
||||
if (ubPointsLost > 0)
|
||||
{
|
||||
// Experienced and/or high-morale soldiers suffer less shock than others.
|
||||
INT8 bShockValue, bShockLimit;
|
||||
bShockLimit = MAXIMUM_SUPPRESSION_SHOCK - bTolerance;
|
||||
// the amount of shock received depends mainly on how many APs we've lost. 8 here is arbitrary,
|
||||
// as the shock loss can later be adjusted by the external modifier below.
|
||||
bShockValue = (bShockLimit * ubPointsLost) / 8;
|
||||
// Limit defined by INI.
|
||||
bShockLimit = MAXIMUM_SUPPRESSION_SHOCK;
|
||||
// The amount of shock received depends on how many APs we've lost - Every AP lost will cause one
|
||||
// point of shock. This is then divided by 4 if using the 100AP system.
|
||||
bShockValue = ubPointsLost / uiShockPerAPLossDivisor;
|
||||
|
||||
if (bShockValue < 0)
|
||||
bShockValue = 0;
|
||||
if (bShockLimit < 0)
|
||||
bShockLimit = 0;
|
||||
bShockValue = __max(0,bShockValue);
|
||||
bShockLimit = __max(0,bShockLimit);
|
||||
|
||||
// use external value to determine how effective SHOCK really is.
|
||||
bShockValue = (bShockValue * gGameExternalOptions.iSuppressionShockEffectiveness) / 100;
|
||||
bShockValue = (bShockValue * gGameExternalOptions.usSuppressionShockEffect) / 100;
|
||||
|
||||
// Make sure total shock doesn't go TOO high. Maximum is around 30 (for a CTH effect of -150!),
|
||||
// including previous shock from suppression and/or wounds. The Maximum is mitigated by
|
||||
// the character's experience and morale. The shock value can bump above that level
|
||||
// momentarily, for particularily lousy characters, rendering them practically incapable of firing
|
||||
// back effectively... But of course, it is halved once the character starts his next turn, so
|
||||
// shock at turnstart will usually be no higher than 15.
|
||||
// Make sure total shock doesn't go TOO high. Maximum is around 30, including previous shock
|
||||
// from suppression and/or wounds. It is possible to breach the maximum after a good suppressive
|
||||
// attack.
|
||||
|
||||
if ( pSoldier->aiData.bShock + bShockValue <= bShockLimit )
|
||||
{
|
||||
// Shock limit not yet breached. Add shock to character.
|
||||
pSoldier->aiData.bShock += bShockValue;
|
||||
pSoldier->aiData.bShock = __min(127, pSoldier->aiData.bShock + bShockValue);
|
||||
}
|
||||
else if ( pSoldier->aiData.bShock < bShockLimit ) // Shock limit will be breached.
|
||||
{
|
||||
// Original shock was lower than the limit, so add extra shock and breach the limit.
|
||||
pSoldier->aiData.bShock += bShockValue;
|
||||
pSoldier->aiData.bShock = __min(127, pSoldier->aiData.bShock + bShockValue);
|
||||
}
|
||||
// Else, original shock was already over the limit. No more shock is added.
|
||||
}
|
||||
}
|
||||
// HEADROCK: Untrained characters won't react well to being fired at (they'll keep standing), but if
|
||||
// Suppression Shock is activated, they may dive and "COWER" anyway. For this to happen, they must first
|
||||
// make a check to see if they are in enough shock to cower.
|
||||
// HEADROCK: Cowering is the panic that grips a character due to suffering too much suppression shock. If
|
||||
// enough shock has been accumulated, the soldier goes into this panic. Generally, cowering will cause
|
||||
// the character to drop a stance if he can, overriding other conditions for a stance-change (see below).
|
||||
// Cowering characters may become considerably easier to suppress with additional firepower. In other
|
||||
// words, if you're cowering, you've effectively turned from a bad-ass to a wimp.
|
||||
|
||||
fCower = false;
|
||||
if ( gGameExternalOptions.fSuppressionShock && gGameExternalOptions.iAimPenaltyPerTargetShock > 0 )
|
||||
if ( gGameExternalOptions.usSuppressionShockEffect > 0 )
|
||||
{
|
||||
if (pSoldier->aiData.bShock >= bTolerance)
|
||||
{ fCower = true; }
|
||||
{
|
||||
fCower = true;
|
||||
|
||||
// If cowering, increase suppression effectiveness by external percentage. If the setting is
|
||||
// over 100%, then the condition of cowering makes the character even MORE susceptible to suppression.
|
||||
if (gGameExternalOptions.usCowerEffectOnSuppression > 0)
|
||||
ubPointsLost = (ubPointsLost * gGameExternalOptions.usCowerEffectOnSuppression) / 100;
|
||||
|
||||
// If soldier is visible on-screen, report to player that they are cowering.
|
||||
if ( pSoldier->bVisible != -1 )
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113HAMMessage[0], pSoldier->name );
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2: If enemy cowers in fear, let the player know.
|
||||
if (fCower)
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113HAMMessage[0], pSoldier->name );
|
||||
// If cowering, increase suppression effectiveness by external percentage
|
||||
if (gGameExternalOptions.iCowerEffectOnSuppression > 0)
|
||||
ubPointsLost = (ubPointsLost * gGameExternalOptions.iCowerEffectOnSuppression) / 100;
|
||||
}
|
||||
// morale modifier
|
||||
// For every 2 APs lost, subtract morale by a certain value.
|
||||
// HEADROCK: Modified - now externalized to INI.
|
||||
// Suppression reduces morale. For every X APs lost, morale goes down by a point. X is defined by INI.
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: check for morale effects"));
|
||||
if (APBPConstants[AP_LOST_PER_MORALE_DROP] > 0 && ubPointsLost > 0)
|
||||
{
|
||||
for ( ubLoop2 = 0; ubLoop2 < (ubPointsLost / APBPConstants[AP_LOST_PER_MORALE_DROP]); ubLoop2++ )
|
||||
@@ -7408,34 +7448,24 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
|
||||
ubNewStance = 0;
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: check for reaction"));
|
||||
// merc may get to react
|
||||
// Headrock: apply suppression effectiveness percentage to this value.
|
||||
if ( (pSoldier->ubSuppressionPoints * gGameExternalOptions.iSuppressionEffectiveness) / 100 >= ( 130 / (6 + bTolerance) ) || fCower )
|
||||
|
||||
// HEADROCK HAM 3.5: Characters who have enough APs to drop WILL DROP. This is strictly for survival reasons,
|
||||
// because upright characters can easily get themselves killed. Soldiers drop stance for "free", using up
|
||||
// the APs that they've just lost to do so.
|
||||
|
||||
switch (gAnimControl[ pSoldier->usAnimState ].ubEndHeight)
|
||||
{
|
||||
// merc gets to use APs to react!
|
||||
switch (gAnimControl[ pSoldier->usAnimState ].ubEndHeight)
|
||||
{
|
||||
case ANIM_PRONE:
|
||||
// can't change stance below prone!
|
||||
break;
|
||||
case ANIM_CROUCH:
|
||||
if (ubTotalPointsLost >= APBPConstants[AP_PRONE] && IsValidStance( pSoldier, ANIM_PRONE ) )
|
||||
if (ubPointsLost >= APBPConstants[AP_PRONE] && IsValidStance( pSoldier, ANIM_PRONE ) && gAnimControl[ pSoldier->usAnimState ].ubEndHeight != ANIM_PRONE )
|
||||
{
|
||||
sClosestOpponent = ClosestKnownOpponent( pSoldier, &sClosestOppLoc, NULL );
|
||||
// HEADROCK: Added cowering.
|
||||
if (sClosestOpponent == NOWHERE || SpacesAway( pSoldier->sGridNo, sClosestOppLoc ) > 8 || fCower)
|
||||
{
|
||||
if (ubPointsLost < APBPConstants[AP_PRONE])
|
||||
{
|
||||
// Have to give APs back so that we can change stance without
|
||||
// losing more APs
|
||||
pSoldier->bActionPoints += (APBPConstants[AP_PRONE] - ubPointsLost);
|
||||
ubPointsLost = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ubPointsLost -= APBPConstants[AP_PRONE];
|
||||
}
|
||||
ubPointsLost -= APBPConstants[AP_PRONE];
|
||||
ubNewStance = ANIM_PRONE;
|
||||
}
|
||||
}
|
||||
@@ -7446,7 +7476,7 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
|
||||
// can't change stance here!
|
||||
break;
|
||||
}
|
||||
else if (ubTotalPointsLost >= (APBPConstants[AP_CROUCH] + APBPConstants[AP_PRONE]) && ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight != ANIM_PRONE ) && IsValidStance( pSoldier, ANIM_PRONE ) )
|
||||
else if (ubPointsLost >= (APBPConstants[AP_CROUCH] + APBPConstants[AP_PRONE]) && ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight != ANIM_PRONE ) && IsValidStance( pSoldier, ANIM_PRONE ) )
|
||||
{
|
||||
sClosestOpponent = ClosestKnownOpponent( pSoldier, &sClosestOppLoc, NULL );
|
||||
// HEADROCK: Added cowering.
|
||||
@@ -7469,19 +7499,40 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
|
||||
ubNewStance = ANIM_CROUCH;
|
||||
}
|
||||
}
|
||||
else if ( ubTotalPointsLost >= APBPConstants[AP_CROUCH] && ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight != ANIM_CROUCH ) && IsValidStance( pSoldier, ANIM_CROUCH ) )
|
||||
else if ( ubPointsLost >= APBPConstants[AP_CROUCH] && ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight != ANIM_CROUCH ) && IsValidStance( pSoldier, ANIM_CROUCH ) )
|
||||
{
|
||||
// crouch!
|
||||
ubNewStance = ANIM_CROUCH;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: reduce action points"));
|
||||
|
||||
// HEADROCK HAM 3.1: If this setting is enabled, it will show an on-screen message that tells us the
|
||||
// character has lost his entire next turn. This only fires once per turn, the moment a character drops
|
||||
// to the minimum AP limit.
|
||||
|
||||
if (gGameExternalOptions.fShowSuppressionShutdown)
|
||||
{
|
||||
// If we're about the hit the lower limit
|
||||
if (pSoldier->bActionPoints > APBPConstants[AP_MIN_LIMIT] && pSoldier->bActionPoints - ubPointsLost <= APBPConstants[AP_MIN_LIMIT])
|
||||
{
|
||||
// And soldier is visible
|
||||
if ( pSoldier->bVisible != -1 )
|
||||
{
|
||||
// "Soldier is pinned down!"
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113HAMMessage[1], pSoldier->name );
|
||||
// HEADROCK HAM 3.2: Added a radio locator!
|
||||
ShowRadioLocator( (UINT8)pSoldier->ubID, SHOW_LOCATOR_NORMAL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: reduce action points"));
|
||||
// Reduce action points!
|
||||
// HEADROCK HAM Beta 2.2: Enforce a minimum limit via INI.
|
||||
if (pSoldier->bActionPoints - ubPointsLost < APBPConstants[AP_MIN_LIMIT] )
|
||||
if (pSoldier->bActionPoints - ubPointsLost <= APBPConstants[AP_MIN_LIMIT] )
|
||||
{
|
||||
pSoldier->bActionPoints = APBPConstants[AP_MIN_LIMIT];
|
||||
}
|
||||
@@ -7492,7 +7543,7 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
|
||||
// Remember how many APs were lost. This prevents us from losing more and more APs without receiving
|
||||
// extra suppression. Note that a specific HAM setting will reset this value after every attack,
|
||||
// but also resets ubSuppressionPoints.
|
||||
pSoldier->ubAPsLostToSuppression = ubTotalPointsLost;
|
||||
pSoldier->ubAPsLostToSuppression = __min(255, pSoldier->ubAPsLostToSuppression + ubPointsLost);
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: check for quote"));
|
||||
if ( (pSoldier->flags.uiStatusFlags & SOLDIER_PC) && (pSoldier->ubSuppressionPoints > 8) && (pSoldier->ubID == ubTargetedMerc) )
|
||||
@@ -7554,17 +7605,11 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
|
||||
pSoldier->flags.fDontChargeAPsForStanceChange = TRUE;
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2: Optional fix for suppression. This clears up the value that measures suppression
|
||||
// accumulated so far. Previously, the value was NEVER cleared, which means that a character could
|
||||
// only be suppressed ONCE in the game (unless they die or get deleted).
|
||||
// With the setting at "2", these two values are cleared every turn. Therefore, suppression doesn't
|
||||
// accumulate at all, only its effects are cumulative. In the end, it functions almost the same as
|
||||
// clearing every turn, but I added this as an alternative.
|
||||
if (gGameExternalOptions.iClearSuppression == 2)
|
||||
{
|
||||
pSoldier->ubAPsLostToSuppression = 0;
|
||||
pSoldier->ubSuppressionPoints = 0;
|
||||
}
|
||||
// HEADROCK HAM 3.5: After sufficient testing, suppression clearing now works immediately at the end of
|
||||
// the attack. ubAPsLostToSuppression is only cleared at the end of the turn, but no longer plays a role
|
||||
// in affecting the number of APs lost, so it is largely irrelevant now.
|
||||
|
||||
pSoldier->ubSuppressionPoints = 0;
|
||||
|
||||
} // end of examining one soldier
|
||||
} // end of loop
|
||||
@@ -7617,8 +7662,14 @@ BOOLEAN ProcessImplicationsOfPCAttack( SOLDIERTYPE * pSoldier, SOLDIERTYPE ** pp
|
||||
|
||||
if ( (pTarget->bTeam == MILITIA_TEAM) && (pTarget->bSide == gbPlayerNum) )
|
||||
{
|
||||
// rebel militia attacked by the player!
|
||||
MilitiaChangesSides();
|
||||
// HEADROCK HAM 3.6: INI setting controls their response
|
||||
{
|
||||
if (gGameExternalOptions.ubCanMilitiaBecomeHostile == 2)
|
||||
{
|
||||
// rebel militia attacked by the player!
|
||||
MilitiaChangesSides();
|
||||
}
|
||||
}
|
||||
}
|
||||
// JA2 Gold: fix Slay
|
||||
else if ( (pTarget->bTeam == CIV_TEAM && pTarget->aiData.bNeutral) && pTarget->ubProfile == SLAY && pTarget->stats.bLife >= OKLIFE && CheckFact( 155, 0 ) == FALSE )
|
||||
@@ -7654,6 +7705,23 @@ BOOLEAN ProcessImplicationsOfPCAttack( SOLDIERTYPE * pSoldier, SOLDIERTYPE ** pp
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pTarget->bTeam == CREATURE_TEAM && pTarget->ubBodyType == BLOODCAT && pTarget->aiData.bNeutral)
|
||||
{
|
||||
// Attacked a bloodcat.
|
||||
MakeBloodcatsHostile();
|
||||
// Are bloodcats in this sector affiliated with a faction?
|
||||
if ( gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][0].PlacementType == BLOODCAT_PLACEMENT_STATIC &&
|
||||
gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation > NON_CIV_GROUP )
|
||||
{
|
||||
// Temporarily change bloodcat's civilian group
|
||||
UINT8 ubFaction = pTarget->ubCivilianGroup;
|
||||
pTarget->ubCivilianGroup = gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation;
|
||||
// Make entire faction hostile
|
||||
CivilianGroupMembersChangeSidesWithinProximity( pTarget );
|
||||
// Change back
|
||||
pTarget->ubCivilianGroup = ubFaction;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pTarget->ubProfile == CARMEN)// Carmen
|
||||
@@ -7692,6 +7760,14 @@ BOOLEAN ProcessImplicationsOfPCAttack( SOLDIERTYPE * pSoldier, SOLDIERTYPE ** pp
|
||||
// Firing at a civ in a civ group who isn't hostile... if anyone in that civ group can see this
|
||||
// going on they should become hostile.
|
||||
CivilianGroupMembersChangeSidesWithinProximity( pTarget );
|
||||
|
||||
// HEADROCK HAM 3.6: If there are bloodcats affiliated with his group...
|
||||
if ( gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][0].PlacementType == BLOODCAT_PLACEMENT_STATIC &&
|
||||
gBloodcatPlacements[SECTOR(pTarget->sSectorX,pTarget->sSectorY)][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation == pTarget->ubCivilianGroup )
|
||||
{
|
||||
// Make them hostile.
|
||||
MakeBloodcatsHostile();
|
||||
}
|
||||
}
|
||||
else if ( pTarget->bTeam == gbPlayerNum && !(gTacticalStatus.uiFlags & INCOMBAT) )
|
||||
{
|
||||
@@ -8150,17 +8226,6 @@ SOLDIERTYPE *InternalReduceAttackBusyCount( )
|
||||
pSoldier->flags.fGettingHit = FALSE;
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2: Optional fix for suppression. This clears up the value that measures suppression
|
||||
// accumulated so far. Previously, the value was NEVER cleared, which means that a character could
|
||||
// only be suppressed ONCE in the game (unless they die or get deleted).
|
||||
// With the setting at "2", these two values are cleared every turn. Therefore, suppression doesn't
|
||||
// accumulate at all, only its effects are cumulative. In the end, it functions almost the same as
|
||||
// clearing every turn, but I added this as an alternative.
|
||||
if (gGameExternalOptions.iClearSuppression == 2)
|
||||
{
|
||||
pSoldier->ubAPsLostToSuppression = 0;
|
||||
pSoldier->ubSuppressionPoints = 0;
|
||||
}
|
||||
if (pSoldier->ubAttackerID != NOBODY )
|
||||
{
|
||||
if (pSoldier->ubPreviousAttackerID != pSoldier->ubAttackerID)
|
||||
@@ -8822,3 +8887,79 @@ void RevealAllDroppedEnemyItems()
|
||||
AllSoldiersLookforItems( TRUE );
|
||||
|
||||
}
|
||||
|
||||
|
||||
// HEADROCK HAM 3.2: This function from HAM 2.9 makes a character look around himself and try to find friends. Dead
|
||||
// friends lower the result, while more friends (ESP good leaders) will raise the result. The result can then be used
|
||||
// for any purpose, although this was written specifically to alter a character's suppression tolerance.
|
||||
|
||||
INT8 CheckStatusNearbyFriendlies( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
SOLDIERTYPE * pLeader;
|
||||
UINT8 sModifier = 0;
|
||||
INT16 usEffectiveLeadership = 0;
|
||||
UINT16 usEffectiveRangeToLeader = 0;
|
||||
INT16 usBestLeader = 0;
|
||||
INT16 usFriendBonus = 0;
|
||||
|
||||
// Run through each friendly.
|
||||
for ( UINT8 iCounter = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID ; iCounter <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID ; iCounter ++ )
|
||||
{
|
||||
pLeader = MercPtrs[ iCounter ];
|
||||
// Make sure that character is alive, not too shocked, and conscious, and of higher experience level
|
||||
// than the character being suppressed.
|
||||
if (pLeader != pSoldier && pLeader->bActive && pLeader->aiData.bShock < pLeader->stats.bLeadership/5 &&
|
||||
pLeader->stats.bLife >= OKLIFE && pLeader->stats.bExpLevel >= pSoldier->stats.bExpLevel)
|
||||
{
|
||||
// Calculate character's leadership and range/3
|
||||
usEffectiveLeadership = ((EffectiveLeadership( pLeader ) - 25) / 15);
|
||||
usEffectiveRangeToLeader = PythSpacesAway( pSoldier->sGridNo, pLeader->sGridNo ) / 3;
|
||||
// If leader is within range of his leadership stat
|
||||
if (usEffectiveRangeToLeader <= usEffectiveLeadership+1)
|
||||
{
|
||||
// The difference in experience level is important!
|
||||
usEffectiveLeadership += (pLeader->stats.bExpLevel - pSoldier->stats.bExpLevel);
|
||||
// Reduce effective leadership with every 3 tiles of distance
|
||||
usEffectiveLeadership -= usEffectiveRangeToLeader-1;
|
||||
|
||||
// If this is the best leader we've seen so far,
|
||||
if (usEffectiveLeadership > usBestLeader)
|
||||
{
|
||||
// Set this as the best leader
|
||||
usBestLeader = usEffectiveLeadership;
|
||||
}
|
||||
// Friends within range always give at least one tolerance bonus point.
|
||||
usFriendBonus += 1;
|
||||
}
|
||||
}
|
||||
// Incapacitated or heavily suppressed friends will not be good for our tolerance!
|
||||
else if (pLeader != pSoldier && pLeader->bActive && (pLeader->aiData.bShock > pSoldier->aiData.bShock || pLeader->stats.bLife <= OKLIFE) )
|
||||
{
|
||||
usEffectiveRangeToLeader = PythSpacesAway( pSoldier->sGridNo, pLeader->sGridNo );
|
||||
// If they are no more than 5 tiles away,
|
||||
if (usEffectiveRangeToLeader <= 5)
|
||||
{
|
||||
// Penalty is based on the difference between experience levels, and the range between them,
|
||||
// and is never less than 1 point.
|
||||
usEffectiveLeadership = (pLeader->stats.bExpLevel - pSoldier->stats.bExpLevel) / __max(1,(usEffectiveRangeToLeader/2));
|
||||
usFriendBonus -= __max(1, usEffectiveLeadership);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we did find someone who's a good enough leader to help us out,
|
||||
if (usBestLeader > 0)
|
||||
{
|
||||
// Add his leadership bonus, minus the point we got for him before. He'll give at least one
|
||||
// point, like anybody else.
|
||||
usFriendBonus += __max(usBestLeader-1, 1);
|
||||
}
|
||||
|
||||
// Add no more than five points for nearby friends.
|
||||
usFriendBonus = __min(usFriendBonus, 5);
|
||||
usFriendBonus = __max(usFriendBonus, -5);
|
||||
sModifier += usFriendBonus;
|
||||
|
||||
return(sModifier);
|
||||
|
||||
}
|
||||
@@ -318,6 +318,8 @@ BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLE
|
||||
SOLDIERTYPE * ReduceAttackBusyCount( );
|
||||
// HEADROCK HAM B2.6: Made this public so it can be used elsewhere.
|
||||
INT8 CalcSuppressionTolerance( SOLDIERTYPE * pSoldier );
|
||||
// HEADROCK HAM 3.2: A new function for checking the condition of nearby friendlies and returning a modifier.
|
||||
INT8 CheckStatusNearbyFriendlies( SOLDIERTYPE *pSoldier );
|
||||
|
||||
void CommonEnterCombatModeCode( );
|
||||
|
||||
@@ -374,4 +376,6 @@ extern BOOLEAN gogglewarning;
|
||||
// will a sam site under the players control shoot down an airraid?
|
||||
BOOLEAN WillAirRaidBeStopped( INT16 sSectorX, INT16 sSectorY );
|
||||
|
||||
// HEADROCK HAM 3.5: Externalized for First Arrival enemy check
|
||||
extern UINT8 NumEnemyInSector();
|
||||
#endif
|
||||
+13
-13
@@ -3358,7 +3358,7 @@ INT32 FindBestPath(SOLDIERTYPE *s , INT16 sDestination, INT8 ubLevel, INT16 usMo
|
||||
case RUNNING:
|
||||
case ADULTMONSTER_WALKING:
|
||||
// save on casting
|
||||
if((UsingNewInventorySystem() == true) && s->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( s ) != ITEM_NOT_FOUND )
|
||||
//ubAPCost = ubAPCost * 10 / ( (UINT8) (RUNDIVISORBPACK * 10));
|
||||
ubAPCost = ubAPCost + APBPConstants[AP_MODIFIER_RUN] + APBPConstants[AP_MODIFIER_PACK];
|
||||
else
|
||||
@@ -3368,19 +3368,19 @@ INT32 FindBestPath(SOLDIERTYPE *s , INT16 sDestination, INT8 ubLevel, INT16 usMo
|
||||
break;
|
||||
case WALKING:
|
||||
case ROBOT_WALK:
|
||||
if((UsingNewInventorySystem() == true) && s->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( s ) != ITEM_NOT_FOUND )
|
||||
ubAPCost = (ubAPCost + APBPConstants[AP_MODIFIER_WALK] + APBPConstants[AP_MODIFIER_PACK]); //WALKCOSTBPACK);
|
||||
else
|
||||
ubAPCost = (ubAPCost + APBPConstants[AP_MODIFIER_WALK]); //WALKCOST);
|
||||
break;
|
||||
case SWATTING:
|
||||
if((UsingNewInventorySystem() == true) && s->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( s ) != ITEM_NOT_FOUND )
|
||||
ubAPCost = (ubAPCost + APBPConstants[AP_MODIFIER_SWAT] + APBPConstants[AP_MODIFIER_PACK]); //SWATCOSTBPACK);
|
||||
else
|
||||
ubAPCost = (ubAPCost + APBPConstants[AP_MODIFIER_SWAT]); //SWATCOST);
|
||||
break;
|
||||
case CRAWLING:
|
||||
if((UsingNewInventorySystem() == true) && s->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( s ) != ITEM_NOT_FOUND )
|
||||
ubAPCost = (ubAPCost + APBPConstants[AP_MODIFIER_CRAWL] + APBPConstants[AP_MODIFIER_PACK]); //CRAWLCOSTBPACK);
|
||||
else
|
||||
ubAPCost = (ubAPCost + APBPConstants[AP_MODIFIER_CRAWL]); //CRAWLCOST);
|
||||
@@ -4308,27 +4308,27 @@ INT16 PlotPath( SOLDIERTYPE *pSold, INT16 sDestGridno, INT8 bCopyRoute, INT8 bPl
|
||||
{
|
||||
case RUNNING:
|
||||
sPoints += sTileCost + sExtraCostStand + APBPConstants[AP_MODIFIER_RUN];
|
||||
if((UsingNewInventorySystem() == true) && pSold->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
case WALKING :
|
||||
sPoints += sTileCost + sExtraCostStand + APBPConstants[AP_MODIFIER_WALK];
|
||||
if((UsingNewInventorySystem() == true) && pSold->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
case SWATTING:
|
||||
sPoints += sTileCost + sExtraCostStand + APBPConstants[AP_MODIFIER_SWAT];
|
||||
if((UsingNewInventorySystem() == true) && pSold->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
case CRAWLING:
|
||||
sPoints += sTileCost + sExtraCostStand + APBPConstants[AP_MODIFIER_CRAWL];
|
||||
if((UsingNewInventorySystem() == true) && pSold->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
default :
|
||||
sPoints += sPoints + sTileCost;
|
||||
if((UsingNewInventorySystem() == true) && pSold->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
}
|
||||
@@ -4344,22 +4344,22 @@ INT16 PlotPath( SOLDIERTYPE *pSold, INT16 sDestGridno, INT8 bCopyRoute, INT8 bPl
|
||||
// CHRISL: Adjusted system to use different move costs while wearing a backpack
|
||||
// store WALK cost
|
||||
sPointsWalk += sTileCost + APBPConstants[AP_MODIFIER_WALK] + sExtraCostStand;
|
||||
if((UsingNewInventorySystem() == true) && pSold->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
sPointsWalk += APBPConstants[AP_MODIFIER_PACK];
|
||||
|
||||
// now get cost as if CRAWLING
|
||||
sPointsCrawl += sTileCost + APBPConstants[AP_MODIFIER_CRAWL] + sExtraCostCrawl;
|
||||
if((UsingNewInventorySystem() == true) && pSold->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
sPointsCrawl += APBPConstants[AP_MODIFIER_PACK];
|
||||
|
||||
// now get cost as if SWATTING
|
||||
sPointsSwat += sTileCost + APBPConstants[AP_MODIFIER_SWAT] + sExtraCostSwat;
|
||||
if((UsingNewInventorySystem() == true) && pSold->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
sPointsSwat += APBPConstants[AP_MODIFIER_PACK];
|
||||
|
||||
// now get cost as if RUNNING
|
||||
sPointsRun += sTileCost + APBPConstants[AP_MODIFIER_RUN] + sExtraCostStand;
|
||||
if((UsingNewInventorySystem() == true) && pSold->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
sPointsRun += APBPConstants[AP_MODIFIER_PACK];
|
||||
}
|
||||
|
||||
|
||||
+53
-35
@@ -337,7 +337,7 @@ INT16 ActionPointCost( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDir, UINT16 u
|
||||
case BLOODCAT_RUN:
|
||||
// CHRISL
|
||||
sPoints = sTileCost + APBPConstants[AP_MODIFIER_RUN];
|
||||
if((UsingNewInventorySystem() == true) && pSoldier->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSoldier ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
|
||||
@@ -351,7 +351,7 @@ INT16 ActionPointCost( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDir, UINT16 u
|
||||
case WALKING :
|
||||
// CHRISL
|
||||
sPoints = sTileCost + APBPConstants[AP_MODIFIER_WALK];
|
||||
if((UsingNewInventorySystem() == true) && pSoldier->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSoldier ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
|
||||
@@ -360,12 +360,12 @@ INT16 ActionPointCost( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDir, UINT16 u
|
||||
// CHRISL
|
||||
case SWATTING:
|
||||
sPoints = sTileCost + APBPConstants[AP_MODIFIER_SWAT];
|
||||
if((UsingNewInventorySystem() == true) && pSoldier->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSoldier ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
case CRAWLING:
|
||||
sPoints = sTileCost + APBPConstants[AP_MODIFIER_CRAWL];
|
||||
if((UsingNewInventorySystem() == true) && pSoldier->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSoldier ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
|
||||
@@ -423,7 +423,7 @@ INT16 EstimateActionPointCost( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDir,
|
||||
case BLOODCAT_RUN:
|
||||
// CHRISL
|
||||
sPoints = sTileCost + APBPConstants[AP_MODIFIER_RUN];
|
||||
if((UsingNewInventorySystem() == true) && pSoldier->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSoldier ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
|
||||
@@ -437,7 +437,7 @@ INT16 EstimateActionPointCost( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDir,
|
||||
// CHRISL
|
||||
case WALKING :
|
||||
sPoints = sTileCost + APBPConstants[AP_MODIFIER_WALK];
|
||||
if((UsingNewInventorySystem() == true) && pSoldier->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSoldier ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
|
||||
@@ -446,12 +446,12 @@ INT16 EstimateActionPointCost( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDir,
|
||||
// CHRISL
|
||||
case SWATTING:
|
||||
sPoints = sTileCost + APBPConstants[AP_MODIFIER_SWAT];
|
||||
if((UsingNewInventorySystem() == true) && pSoldier->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSoldier ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
case CRAWLING:
|
||||
sPoints = sTileCost + APBPConstants[AP_MODIFIER_CRAWL];
|
||||
if((UsingNewInventorySystem() == true) && pSoldier->inv[BPACKPOCKPOS].exists() == true)
|
||||
if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSoldier ) != ITEM_NOT_FOUND )
|
||||
sPoints += APBPConstants[AP_MODIFIER_PACK];
|
||||
break;
|
||||
|
||||
@@ -668,9 +668,11 @@ void DeductPoints( SOLDIERTYPE *pSoldier, INT16 sAPCost, INT32 iBPCost,BOOLEAN f
|
||||
pSoldier->bActionPoints -= (INT16)( (float)( pSoldier->sBreathRed + iBPCost - BREATH_RED_MAX )
|
||||
/ (float)( 5 * APBPConstants[BP_RATIO_RED_PTS_TO_NORMAL])
|
||||
* (float)(4 * (float)APBPConstants[AP_MAXIMUM] / 100));
|
||||
if ( pSoldier->bActionPoints < 0 )
|
||||
// HEADROCK HAM 3.1: This may be the problem with suppression - it limits the lower APs to 0, which breaks
|
||||
// suppression's negative values. Changed instances of "0" to the APBP constant.
|
||||
if ( pSoldier->bActionPoints < APBPConstants[AP_MIN_LIMIT] )
|
||||
{
|
||||
pSoldier->bActionPoints = 0;
|
||||
pSoldier->bActionPoints = APBPConstants[AP_MIN_LIMIT];
|
||||
}
|
||||
|
||||
pSoldier->sBreathRed = BREATH_RED_MAX;
|
||||
@@ -1130,46 +1132,63 @@ INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAddTur
|
||||
if (gGameExternalOptions.fIncreasedAimingCost )
|
||||
{
|
||||
// HEADROCK HAM B2.6: Changed the number of APs to attack when aiming.
|
||||
// HEADROCK HAM 3.1: Externalized the entire function to allow customization of each detail.
|
||||
if (bAimTime > 0)
|
||||
{
|
||||
GetAPChargeForShootOrStabWRTGunRaises( pSoldier, sGridNo, ubAddTurningCost, &fAddingTurningCost, &fAddingRaiseGunCost );
|
||||
if(fAddingRaiseGunCost == TRUE)
|
||||
{
|
||||
//CHRISL: I'm disabling this for now. Charging 1/2 ready cost for every shot isn't legitimate
|
||||
// but for the time being, we have no way to track whether we've previously aimed or not. Until
|
||||
// we do, this code shouldn't be used.
|
||||
// Add 1/2 ready cost (rounded up) for getting the sights up to the eye
|
||||
//sAPCost += ((Weapon[ usItemNum ].ubReadyTime * (100 - GetPercentReadyTimeAPReduction(&pSoldier->inv[HANDPOS])) / 100) + 1) / 2;
|
||||
// HEADROCK HAM 3: No idea what should come here... For now I've put my extra gun-raise costs
|
||||
// outside this IF (see below).
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3: One-time penalty: Add part of the weapon's Ready AP cost. Reinstated because
|
||||
// it's now externalized.
|
||||
if (gGameExternalOptions.ubFirstAimReadyCostDivisor > 0)
|
||||
{
|
||||
UINT16 usWeaponReadyTime;
|
||||
UINT8 ubReadyTimeDivisor;
|
||||
|
||||
usWeaponReadyTime = Weapon[ usItemNum ].ubReadyTime * (100 - GetPercentReadyTimeAPReduction(&pSoldier->inv[HANDPOS])) / 100;
|
||||
ubReadyTimeDivisor = gGameExternalOptions.ubFirstAimReadyCostDivisor;
|
||||
sAPCost += usWeaponReadyTime / ubReadyTimeDivisor;
|
||||
}
|
||||
|
||||
// Add regular aim time for the first 4 aiming actions.
|
||||
sAPCost += __min((bAimTime*APBPConstants[AP_CLICK_AIM]),(4*APBPConstants[AP_CLICK_AIM]));
|
||||
|
||||
// If the weapon has a scope, and the target is within eligible range for scope use
|
||||
|
||||
if ( IsScoped(&pSoldier->inv[HANDPOS])
|
||||
&& GetRangeInCellCoordsFromGridNoDiff( pSoldier->sGridNo, sGridNo ) >= GetMinRangeForAimBonus(&pSoldier->inv[HANDPOS]) )
|
||||
{
|
||||
// Add time to adjust eye to scope
|
||||
if (bAimTime > 0)
|
||||
{
|
||||
//CHRISL: I'm disabling this for now. Charging an extra "click" every time we use a scope
|
||||
// isn't legitimate. If we could track whether we previously used a scope on the current
|
||||
// target, that would be another matter. But for now, we can't, so this should be used.
|
||||
//sAPCost += APBPConstants[AP_CLICK_AIM];
|
||||
}
|
||||
// Add 2 APs for each aiming point between 5 and 6
|
||||
// Add an individual cost for EACH click, as necessary.
|
||||
|
||||
sAPCost += APBPConstants[AP_FIRST_CLICK_AIM_SCOPE];
|
||||
|
||||
if (bAimTime > 1)
|
||||
sAPCost += APBPConstants[AP_SECOND_CLICK_AIM_SCOPE];
|
||||
if (bAimTime > 2)
|
||||
sAPCost += APBPConstants[AP_THIRD_CLICK_AIM_SCOPE];
|
||||
if (bAimTime > 3)
|
||||
sAPCost += APBPConstants[AP_FOURTH_CLICK_AIM_SCOPE];
|
||||
if (bAimTime > 4)
|
||||
{
|
||||
sAPCost += __min(((bAimTime - 4) * APBPConstants[AP_CLICK_AIM] * 2), (4*APBPConstants[AP_CLICK_AIM]));
|
||||
}
|
||||
// Add 3 APs for each aiming point beyond 6.
|
||||
sAPCost += APBPConstants[AP_FIFTH_CLICK_AIM_SCOPE];
|
||||
if (bAimTime > 5)
|
||||
sAPCost += APBPConstants[AP_SIXTH_CLICK_AIM_SCOPE];
|
||||
if (bAimTime > 6)
|
||||
{
|
||||
sAPCost += (bAimTime - 6) * APBPConstants[AP_CLICK_AIM] * 3;
|
||||
}
|
||||
sAPCost += APBPConstants[AP_SEVENTH_CLICK_AIM_SCOPE];
|
||||
if (bAimTime > 7)
|
||||
sAPCost += APBPConstants[AP_EIGHTTH_CLICK_AIM_SCOPE];
|
||||
}
|
||||
|
||||
// Weapon has no scope or not within requried range. Apply regular AP costs.
|
||||
else
|
||||
{
|
||||
sAPCost += bAimTime * APBPConstants[AP_CLICK_AIM];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Regular cost system
|
||||
else
|
||||
{
|
||||
sAPCost += bAimTime * APBPConstants[AP_CLICK_AIM];
|
||||
@@ -1402,7 +1421,6 @@ INT16 BaseAPsToShootOrStab( INT16 bAPs, INT16 bAimSkill, OBJECTTYPE * pObj )
|
||||
//{
|
||||
// Top *= 100;
|
||||
//}
|
||||
|
||||
// WANNE : Fixed CTD that occurs when trowing item (grenade, throwing knife, ...)
|
||||
// with open description box in tactical
|
||||
INT16 baseAPsToShootOrStab = -1;
|
||||
|
||||
@@ -169,7 +169,8 @@ void HandleCrowLeave( SOLDIERTYPE *pSoldier );
|
||||
void HandleCrowFlyAway( SOLDIERTYPE *pSoldier );
|
||||
|
||||
// WDS - increase number of corpses
|
||||
#define MAX_ROTTING_CORPSES 250
|
||||
// HEADROCK HAM 3.6: Increase again (250->500).
|
||||
#define MAX_ROTTING_CORPSES 500
|
||||
|
||||
//extern ROTTING_CORPSE gRottingCorpse[ MAX_ROTTING_CORPSES ];
|
||||
extern std::vector<ROTTING_CORPSE> gRottingCorpse;
|
||||
|
||||
@@ -959,6 +959,7 @@ SOLDIERTYPE& SOLDIERTYPE::operator=(const OLDSOLDIERTYPE_101& src)
|
||||
|
||||
this->snowCamo = src.snowCamo;
|
||||
this->wornSnowCamo = src.wornSnowCamo;
|
||||
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -1794,6 +1795,9 @@ void HandleCrowShadowNewPosition( SOLDIERTYPE *pSoldier )
|
||||
|
||||
extern INT16 DynamicAdjustAPConstants(INT16 iniReadValue, INT16 iniDefaultValue, BOOLEAN reverse);
|
||||
|
||||
// This function calculates how many APs are added to a character's pool at the start of the round. The normal maximum
|
||||
// amount that can be added is 80% of the Maximum AP value, with the remaining 20% coming from APs reserved in the
|
||||
// previous round. See also CalcNewActionPoints()
|
||||
INT16 SOLDIERTYPE::CalcActionPoints( void )
|
||||
{
|
||||
INT16 ubPoints,ubMaxAPs;
|
||||
@@ -1850,8 +1854,11 @@ INT16 SOLDIERTYPE::CalcActionPoints( void )
|
||||
|
||||
// If resulting APs are below our permitted minimum, raise them to it!
|
||||
// HEADROCK: Enforce new minimums due to suppression. I should've done this neater though.
|
||||
if (ubPoints < APBPConstants[AP_MIN_LIMIT])
|
||||
ubPoints = APBPConstants[AP_MIN_LIMIT];
|
||||
// HEADROCK HAM 3.6: This was the wrong place to put AP_MIN_LIMIT. The value here should be AP_MINIMUM, which is
|
||||
// the minimum amount of APs a character can GAIN each turn on top of what he had last turn. AP_MIN_LIMIT has been
|
||||
// moved to CalcNewActionPoints() where it belongs.
|
||||
if (ubPoints < APBPConstants[AP_MINIMUM])
|
||||
ubPoints = APBPConstants[AP_MINIMUM];
|
||||
|
||||
// make sure action points doesn't exceed the permitted maximum
|
||||
ubMaxAPs = gubMaxActionPoints[ this->ubBodyType ];
|
||||
@@ -1975,6 +1982,10 @@ void SOLDIERTYPE::CalcNewActionPoints( void )
|
||||
}
|
||||
|
||||
this->bActionPoints += this->CalcActionPoints( );
|
||||
// HEADROCK HAM 3.6: This should've been here all along. This enforces an absolute minimum limit on APs, which
|
||||
// can be negative.
|
||||
if (this->bActionPoints < APBPConstants[AP_MIN_LIMIT])
|
||||
this->bActionPoints = APBPConstants[AP_MIN_LIMIT];
|
||||
|
||||
// Don't max out if we are drugged....
|
||||
if ( !GetDrugEffect( this, DRUG_TYPE_ADRENALINE ) )
|
||||
@@ -5511,7 +5522,9 @@ void SoldierGotHitGunFire( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sD
|
||||
{
|
||||
if ( gGameSettings.fOptions[ TOPTION_BLOOD_N_GORE ] )
|
||||
{
|
||||
if (SpacesAway( pSoldier->sGridNo, Menptr[ubAttackerID].sGridNo ) <= MAX_DISTANCE_FOR_MESSY_DEATH || (SpacesAway( pSoldier->sGridNo, Menptr[ubAttackerID].sGridNo ) <= MAX_BARRETT_DISTANCE_FOR_MESSY_DEATH && usWeaponIndex == BARRETT ))
|
||||
// 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 (SpacesAway( pSoldier->sGridNo, Menptr[ubAttackerID].sGridNo ) <= Weapon[usWeaponIndex].maxdistformessydeath || (SpacesAway( pSoldier->sGridNo, Menptr[ubAttackerID].sGridNo ) <= MAX_BARRETT_DISTANCE_FOR_MESSY_DEATH && usWeaponIndex == BARRETT ))
|
||||
if (SpacesAway( pSoldier->sGridNo, Menptr[ubAttackerID].sGridNo ) <= Weapon[usWeaponIndex].maxdistformessydeath)
|
||||
{
|
||||
sNewGridNo = NewGridNo( (INT16)pSoldier->sGridNo, (INT8)( DirectionInc( pSoldier->ubDirection ) ) );
|
||||
|
||||
@@ -5532,7 +5545,9 @@ void SoldierGotHitGunFire( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sD
|
||||
{
|
||||
if ( gGameSettings.fOptions[ TOPTION_BLOOD_N_GORE ] )
|
||||
{
|
||||
if (SpacesAway( pSoldier->sGridNo, Menptr[ubAttackerID].sGridNo ) <= MAX_DISTANCE_FOR_MESSY_DEATH || (SpacesAway( pSoldier->sGridNo, Menptr[ubAttackerID].sGridNo ) <= MAX_BARRETT_DISTANCE_FOR_MESSY_DEATH && usWeaponIndex == BARRETT ))
|
||||
// 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 (SpacesAway( pSoldier->sGridNo, Menptr[ubAttackerID].sGridNo ) <= Weapon[usWeaponIndex].maxdistformessydeath || (SpacesAway( pSoldier->sGridNo, Menptr[ubAttackerID].sGridNo ) <= MAX_BARRETT_DISTANCE_FOR_MESSY_DEATH && usWeaponIndex == BARRETT ))
|
||||
if (SpacesAway( pSoldier->sGridNo, Menptr[ubAttackerID].sGridNo ) <= Weapon[usWeaponIndex].maxdistformessydeath)
|
||||
{
|
||||
|
||||
// possibly play torso explosion anim!
|
||||
@@ -5581,6 +5596,11 @@ void SoldierGotHitGunFire( SOLDIERTYPE *pSoldier, UINT16 usWeaponIndex, INT16 sD
|
||||
|
||||
if ( fFallenOver )
|
||||
{
|
||||
// HEADROCK HAM 3.2: Critical legshots cost an extra number of APs, based on shot damage.
|
||||
if (gGameExternalOptions.fCriticalLegshotCausesAPLoss)
|
||||
{
|
||||
DeductPoints( pSoldier, APBPConstants[AP_LOSS_PER_LEGSHOT_DAMAGE]*sDamage, 0);
|
||||
}
|
||||
SoldierCollapse( pSoldier );
|
||||
return;
|
||||
}
|
||||
@@ -6613,25 +6633,24 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou
|
||||
this->CalcNewActionPoints( );
|
||||
|
||||
// HEADROCK HAM 3.6: If this soldier is in a "moving" animation, but has not moved any tiles
|
||||
// in the previous turn, then the player has apparently forgotten that he was moving.
|
||||
// In this case, abort the character's action.
|
||||
|
||||
// If hasn't moved since the start of last round
|
||||
// AND this function is being executed in Turn Based mode
|
||||
// AND character is a player-controlled merc
|
||||
if (!fFromRealTime && !this->bTilesMoved && this->bTeam == OUR_TEAM )
|
||||
{
|
||||
// but are doing a movement animation
|
||||
if ( !( gAnimControl[ this->usAnimState ].uiFlags & ANIM_STATIONARY ) )
|
||||
{
|
||||
// Stop the merc
|
||||
this->EVENT_StopMerc( this->sGridNo, this->ubDirection );
|
||||
this->pathing.sFinalDestination = NOWHERE;
|
||||
}
|
||||
// in the previous turn, then the player has apparently forgotten that he was moving.
|
||||
// In this case, abort the character's action.
|
||||
|
||||
// Reset destination
|
||||
//this->pathing.sFinalDestination = this->sGridNo;
|
||||
}
|
||||
// If hasn't moved since the start of last round
|
||||
// AND this function is being executed in Turn Based mode
|
||||
// AND character is a player-controlled merc
|
||||
if (!fFromRealTime && !this->bTilesMoved && this->bTeam == OUR_TEAM )
|
||||
{
|
||||
// but is doing a movement animation
|
||||
if ( !( gAnimControl[ this->usAnimState ].uiFlags & ANIM_STATIONARY ) )
|
||||
{
|
||||
// Stop the merc
|
||||
this->EVENT_StopMerc( this->sGridNo, this->ubDirection );
|
||||
// Reset destination
|
||||
//this->pathing.sFinalDestination = this->sGridNo;
|
||||
this->pathing.sFinalDestination = NOWHERE;
|
||||
}
|
||||
}
|
||||
|
||||
this->bTilesMoved = 0;
|
||||
|
||||
@@ -6711,15 +6730,11 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou
|
||||
this->usQuoteSaidExtFlags &= ( ~SOLDIER_QUOTE_SAID_EXT_CLOSE_CALL );
|
||||
this->bNumHitsThisTurn = 0;
|
||||
this->ubSuppressionPoints = 0;
|
||||
// HEADROCK HAM B2: Optional fix for suppression. This clears up the value that measures suppression
|
||||
// accumulated so far. Previously, the value was NEVER cleared, which means that a character could
|
||||
// only be suppressed ONCE in the game (unless they die or get deleted). There's really no reason to
|
||||
// keep this in an IF statement though, as it should, by all rights, erase itself each turn at the very
|
||||
// least to avoid the once-in-a-lifetime suppression problem.
|
||||
if (gGameExternalOptions.iClearSuppression == 1)
|
||||
{
|
||||
this->ubAPsLostToSuppression = 0;
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.5: After considerable testing, suppression is now cleared after every attack. Total APs lost
|
||||
// is cleared every turn (here) and only acts as reference now (no effect on AP loss).
|
||||
this->ubAPsLostToSuppression = 0;
|
||||
|
||||
this->flags.fCloseCall = FALSE;
|
||||
|
||||
this->ubMovementNoiseHeard = 0;
|
||||
|
||||
@@ -277,6 +277,28 @@ enum
|
||||
#define SOLDIER_CLASS_ENEMY( bSoldierClass ) ( ( bSoldierClass >= SOLDIER_CLASS_ADMINISTRATOR ) && ( bSoldierClass <= SOLDIER_CLASS_ARMY ) )
|
||||
#define SOLDIER_CLASS_MILITIA( bSoldierClass ) ( ( bSoldierClass >= SOLDIER_CLASS_GREEN_MILITIA ) && ( bSoldierClass <= SOLDIER_CLASS_ELITE_MILITIA ) )
|
||||
|
||||
// Types of uniforms available
|
||||
enum
|
||||
{
|
||||
UNIFORM_ENEMY_ADMIN = 0,
|
||||
UNIFORM_ENEMY_TROOP,
|
||||
UNIFORM_ENEMY_ELITE,
|
||||
UNIFORM_MILITIA_ROOKIE,
|
||||
UNIFORM_MILITIA_REGULAR,
|
||||
UNIFORM_MILITIA_ELITE,
|
||||
NUM_UNIFORMS,
|
||||
};
|
||||
|
||||
// enum of uniform pieces
|
||||
typedef struct
|
||||
{
|
||||
PaletteRepID vest;
|
||||
PaletteRepID pants;
|
||||
}UNIFORMCOLORS;
|
||||
|
||||
// HEADROCK HAM 3.6: Uniform colors for the different soldier classes
|
||||
extern UNIFORMCOLORS gUniformColors[NUM_UNIFORMS];
|
||||
|
||||
// This macro should be used whenever we want to see if someone is neutral
|
||||
// IF WE ARE CONSIDERING ATTACKING THEM. Creatures & bloodcats will attack neutrals
|
||||
// but they can't attack empty vehicles!!
|
||||
@@ -1021,7 +1043,6 @@ public:
|
||||
|
||||
UINT32 uiTimeSoldierWillArrive;
|
||||
|
||||
|
||||
INT8 bVehicleUnderRepairID;
|
||||
INT32 iTimeCanSignElsewhere;
|
||||
INT8 bHospitalPriceModifier;
|
||||
@@ -1050,7 +1071,11 @@ public:
|
||||
INT8 snowCamo;
|
||||
INT8 wornSnowCamo;
|
||||
|
||||
INT16 filler;
|
||||
// HEADROCK HAM 3.6: Added integer tracking the facility this character is using.
|
||||
INT16 sFacilityTypeOperated;
|
||||
// HEADROCK HAM 3.6: I'm removing this filler to make room for the above variable. I'm very worried though,
|
||||
// I don't know if this is a good idea at all...
|
||||
//INT16 filler;
|
||||
|
||||
char endOfPOD; // marker for end of POD (plain old data)
|
||||
|
||||
|
||||
+40
-14
@@ -667,7 +667,17 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 *
|
||||
{
|
||||
if ( gTacticalStatus.fCivGroupHostile[ Soldier.ubCivilianGroup ] == CIV_GROUP_HOSTILE )
|
||||
{
|
||||
Soldier.aiData.bNeutral = FALSE;
|
||||
// HEADROCK HAM 3.6: Flag to prevent non-combat civilians from becoming hostile and forcing
|
||||
// you to kill them...
|
||||
if (!gGameExternalOptions.fCanTrueCiviliansBecomeHostile &&
|
||||
(Soldier.ubBodyType >= FATCIV && Soldier.ubBodyType <= CRIPPLECIV ))
|
||||
{
|
||||
Soldier.aiData.bNeutral = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
Soldier.aiData.bNeutral = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1211,34 +1221,47 @@ void GeneratePaletteForSoldier( SOLDIERTYPE *pSoldier, UINT8 ubSoldierClass )
|
||||
// OK, After skin, hair we could have a forced color scheme.. use here if so
|
||||
switch( ubSoldierClass )
|
||||
{
|
||||
// HEADROCK HAM 3.6: Now reads default colors from XML.
|
||||
case SOLDIER_CLASS_ADMINISTRATOR:
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, "YELLOWVEST" );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, "GREENPANTS" );
|
||||
//SET_PALETTEREP_ID( pSoldier->VestPal, "YELLOWVEST" );
|
||||
//SET_PALETTEREP_ID( pSoldier->PantsPal, "GREENPANTS" );
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, gUniformColors[ UNIFORM_ENEMY_ADMIN ].vest );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, gUniformColors[ UNIFORM_ENEMY_ADMIN ].pants );
|
||||
pSoldier->ubSoldierClass = ubSoldierClass;
|
||||
return;
|
||||
case SOLDIER_CLASS_ELITE:
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, "BLACKSHIRT" );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, "BLACKPANTS" );
|
||||
//SET_PALETTEREP_ID( pSoldier->VestPal, "BLACKSHIRT" );
|
||||
//SET_PALETTEREP_ID( pSoldier->PantsPal, "BLACKPANTS" );
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, gUniformColors[ UNIFORM_ENEMY_ELITE ].vest );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, gUniformColors[ UNIFORM_ENEMY_ELITE ].pants );
|
||||
pSoldier->ubSoldierClass = ubSoldierClass;
|
||||
return;
|
||||
case SOLDIER_CLASS_ARMY:
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, "REDVEST" );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, "GREENPANTS" );
|
||||
//SET_PALETTEREP_ID( pSoldier->VestPal, "REDVEST" );
|
||||
//SET_PALETTEREP_ID( pSoldier->PantsPal, "GREENPANTS" );
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, gUniformColors[ UNIFORM_ENEMY_TROOP ].vest );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, gUniformColors[ UNIFORM_ENEMY_TROOP ].pants );
|
||||
pSoldier->ubSoldierClass = ubSoldierClass;
|
||||
return;
|
||||
case SOLDIER_CLASS_GREEN_MILITIA:
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, "GREENVEST" );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, "BEIGEPANTS" );
|
||||
//SET_PALETTEREP_ID( pSoldier->VestPal, "GREENVEST" );
|
||||
//SET_PALETTEREP_ID( pSoldier->PantsPal, "BEIGEPANTS" );
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, gUniformColors[ UNIFORM_MILITIA_ROOKIE ].vest );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, gUniformColors[ UNIFORM_MILITIA_ROOKIE ].pants );
|
||||
pSoldier->ubSoldierClass = ubSoldierClass;
|
||||
return;
|
||||
case SOLDIER_CLASS_REG_MILITIA:
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, "JEANVEST" );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, "BEIGEPANTS" );
|
||||
//SET_PALETTEREP_ID( pSoldier->VestPal, "JEANVEST" );
|
||||
//SET_PALETTEREP_ID( pSoldier->PantsPal, "BEIGEPANTS" );
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, gUniformColors[ UNIFORM_MILITIA_REGULAR ].vest );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, gUniformColors[ UNIFORM_MILITIA_REGULAR ].pants );
|
||||
pSoldier->ubSoldierClass = ubSoldierClass;
|
||||
return;
|
||||
case SOLDIER_CLASS_ELITE_MILITIA:
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, "BLUEVEST" );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, "BEIGEPANTS" );
|
||||
//SET_PALETTEREP_ID( pSoldier->VestPal, "BLUEVEST" );
|
||||
//SET_PALETTEREP_ID( pSoldier->PantsPal, "BEIGEPANTS" );
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, gUniformColors[ UNIFORM_MILITIA_ELITE ].vest );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, gUniformColors[ UNIFORM_MILITIA_ELITE ].pants );
|
||||
pSoldier->ubSoldierClass = ubSoldierClass;
|
||||
return;
|
||||
case SOLDIER_CLASS_MINER:
|
||||
@@ -1561,6 +1584,7 @@ void InitSoldierStruct( SOLDIERTYPE *pSoldier )
|
||||
pSoldier->uiXRayActivatedTime = 0;
|
||||
pSoldier->bBulletsLeft = 0;
|
||||
pSoldier->bVehicleUnderRepairID = -1;
|
||||
pSoldier->sFacilityTypeOperated = -1; // HEADROCK HAM 3.6: Facility Operated
|
||||
}
|
||||
|
||||
|
||||
@@ -1973,7 +1997,9 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
|
||||
|
||||
case BLOODCAT:
|
||||
pp->bExpLevel = 5 + bExpLevelModifier;
|
||||
if( SECTOR( gWorldSectorX, gWorldSectorY ) == SEC_I16 )
|
||||
// HEADROCK HAM 3.6: There can be several lairs now. Find out if this one is.
|
||||
UINT8 PlacementType = gBloodcatPlacements[ SECTOR(gWorldSectorX, gWorldSectorY) ][0].PlacementType;
|
||||
if( PlacementType == BLOODCAT_PLACEMENT_LAIR )
|
||||
{
|
||||
pp->bExpLevel += gGameOptions.ubDifficultyLevel;
|
||||
}
|
||||
|
||||
@@ -1915,8 +1915,7 @@ void AddSoldierInitListBloodcats()
|
||||
{ //This map has no bloodcat placements, so don't waste CPU time.
|
||||
return;
|
||||
}
|
||||
|
||||
if( pSector->bBloodCatPlacements )
|
||||
else
|
||||
{ //We don't yet know the number of bloodcat placements in this sector so
|
||||
//count them now, and permanently record it.
|
||||
INT8 bBloodCatPlacements = 0;
|
||||
@@ -1929,7 +1928,18 @@ void AddSoldierInitListBloodcats()
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
if( bBloodCatPlacements != pSector->bBloodCatPlacements &&
|
||||
// No placements on the map itself?
|
||||
if( !bBloodCatPlacements )
|
||||
{
|
||||
// Don't place!
|
||||
return;
|
||||
}
|
||||
// HEADROCK HAM 3.6: Check has been changed completely. We now use whichever value is lower - the ones we've
|
||||
// set from XML, or the ones existing on the map. Either could override the other, if it is lower.
|
||||
pSector->bBloodCatPlacements = __min(bBloodCatPlacements, pSector->bBloodCatPlacements);
|
||||
pSector->bBloodCats = __min(pSector->bBloodCats, pSector->bBloodCatPlacements);
|
||||
|
||||
/*if( bBloodCatPlacements != pSector->bBloodCatPlacements &&
|
||||
ubSectorID != SEC_I16 && ubSectorID != SEC_N5 )
|
||||
{
|
||||
#ifdef JA2BETAVERSION
|
||||
@@ -1938,18 +1948,21 @@ void AddSoldierInitListBloodcats()
|
||||
pSector->bBloodCatPlacements, gWorldSectorY + 'A' - 1, gWorldSectorX, bBloodCatPlacements );
|
||||
DoScreenIndependantMessageBox( str, MSG_BOX_FLAG_OK, NULL );
|
||||
#endif
|
||||
// WANNE: Fix by Headrock
|
||||
// HEADROCK HAM 3.5: This "solution" is extremely silly, as it prevents legal placement of bloodcats
|
||||
// on the map if any discrepancy is encountered, which limits modders severely. Also, because the
|
||||
// pSector->bBloodCatPlacements value is hardcoded, there is virtually no way for modders to increase
|
||||
// the number of bloodcats on their own.
|
||||
//pSector->bBloodCatPlacements = bBloodCatPlacements;
|
||||
//pSector->bBloodCats = -1;
|
||||
|
||||
// A better solution is to limit the number of bloodcats on the map based on whichever is lower - the
|
||||
// hardcode, or the map-read value.
|
||||
pSector->bBloodCatPlacements = __min(bBloodCatPlacements, pSector->bBloodCatPlacements);
|
||||
pSector->bBloodCats = __min(pSector->bBloodCats, pSector->bBloodCatPlacements);
|
||||
|
||||
if( !bBloodCatPlacements )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
if( pSector->bBloodCats > 0 )
|
||||
{ //Add them to the world now...
|
||||
@@ -2565,5 +2578,11 @@ void AddSoldierInitListMilitiaOnEdge( UINT8 ubStrategicInsertionCode, UINT8 ubNu
|
||||
}
|
||||
UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, 0 );
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.2: Experimental, militia reinforcements arrive with 0 APs.
|
||||
if (gGameExternalOptions.ubReinforcementsFirstTurnFreeze == 1 || gGameExternalOptions.ubReinforcementsFirstTurnFreeze == 3)
|
||||
{
|
||||
pSoldier->bActionPoints = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,6 +447,13 @@ BOOLEAN LoadMercProfiles(void)
|
||||
gMercProfiles[ uiLoop ].bHatedCount[1] = gMercProfiles[ uiLoop ].bHatedTime[1];
|
||||
gMercProfiles[ uiLoop ].bLearnToHateCount = gMercProfiles[ uiLoop ].bLearnToHateTime;
|
||||
gMercProfiles[ uiLoop ].bLearnToLikeCount = gMercProfiles[ uiLoop ].bLearnToLikeTime;
|
||||
|
||||
if (gGameExternalOptions.fReadProfileDataFromXML)
|
||||
{
|
||||
// HEADROCK PROFEX: Overwrite data read from PROF.DAT with data read from XML
|
||||
OverwriteMercProfileWithXMLData( uiLoop );
|
||||
OverwriteMercOpinionsWithXMLData( uiLoop );
|
||||
}
|
||||
}
|
||||
|
||||
// SET SOME DEFAULT LOCATIONS FOR STARTING NPCS
|
||||
@@ -1664,3 +1671,96 @@ BOOLEAN IsProfileIdAnAimOrMERCMerc( UINT8 ubProfileID )
|
||||
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
void OverwriteMercProfileWithXMLData( UINT32 uiLoop )
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// HEADROCK PROFEX: Profile Externalization
|
||||
//
|
||||
// This is a complete hack which is meant for temporary use until a better system
|
||||
// can be implemented. This bit OVERWRITES data accumulated so far, by drawing
|
||||
// new data from XML. This allows making PROEDIT obsolete.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
wcscpy(gMercProfiles[ uiLoop ].zName, tempProfiles[ uiLoop ].zName) ;
|
||||
wcscpy(gMercProfiles[ uiLoop ].zNickname, tempProfiles[ uiLoop ].zNickname) ;
|
||||
|
||||
gMercProfiles[ uiLoop ].ubFaceIndex = tempProfiles[ uiLoop ].ubFaceIndex ;
|
||||
gMercProfiles[ uiLoop ].usEyesX = tempProfiles[ uiLoop ].usEyesX ;
|
||||
gMercProfiles[ uiLoop ].usEyesY = tempProfiles[ uiLoop ].usEyesY ;
|
||||
gMercProfiles[ uiLoop ].usMouthX = tempProfiles[ uiLoop ].usMouthX ;
|
||||
gMercProfiles[ uiLoop ].usMouthY = tempProfiles[ uiLoop ].usMouthY ;
|
||||
gMercProfiles[ uiLoop ].uiEyeDelay = tempProfiles[ uiLoop ].uiEyeDelay ;
|
||||
gMercProfiles[ uiLoop ].uiMouthDelay = tempProfiles[ uiLoop ].uiMouthDelay ;
|
||||
gMercProfiles[ uiLoop ].uiBlinkFrequency = tempProfiles[ uiLoop ].uiBlinkFrequency ;
|
||||
gMercProfiles[ uiLoop ].uiExpressionFrequency = tempProfiles[ uiLoop ].uiExpressionFrequency ;
|
||||
|
||||
strcpy(gMercProfiles[ uiLoop ].PANTS, tempProfiles[ uiLoop ].PANTS) ;
|
||||
strcpy(gMercProfiles[ uiLoop ].VEST, tempProfiles[ uiLoop ].VEST) ;
|
||||
strcpy(gMercProfiles[ uiLoop ].SKIN, tempProfiles[ uiLoop ].SKIN) ;
|
||||
strcpy(gMercProfiles[ uiLoop ].HAIR, tempProfiles[ uiLoop ].HAIR) ;
|
||||
|
||||
gMercProfiles[ uiLoop ].bSex = tempProfiles[ uiLoop ].bSex ;
|
||||
gMercProfiles[ uiLoop ].ubBodyType = tempProfiles[ uiLoop ].ubBodyType ;
|
||||
gMercProfiles[ uiLoop ].uiBodyTypeSubFlags = tempProfiles[ uiLoop ].uiBodyTypeSubFlags ;
|
||||
|
||||
gMercProfiles[ uiLoop ].bAttitude = tempProfiles[ uiLoop ].bAttitude ;
|
||||
gMercProfiles[ uiLoop ].bPersonalityTrait = tempProfiles[ uiLoop ].bPersonalityTrait ;
|
||||
gMercProfiles[ uiLoop ].ubNeedForSleep = tempProfiles[ uiLoop ].ubNeedForSleep ;
|
||||
|
||||
gMercProfiles[ uiLoop ].bReputationTolerance = tempProfiles[ uiLoop ].bReputationTolerance ;
|
||||
gMercProfiles[ uiLoop ].bDeathRate = tempProfiles[ uiLoop ].bDeathRate ;
|
||||
|
||||
gMercProfiles[ uiLoop ].bLifeMax = tempProfiles[ uiLoop ].bLifeMax ;
|
||||
gMercProfiles[ uiLoop ].bLife = tempProfiles[ uiLoop ].bLife ;
|
||||
gMercProfiles[ uiLoop ].bStrength = tempProfiles[ uiLoop ].bStrength ;
|
||||
gMercProfiles[ uiLoop ].bAgility = tempProfiles[ uiLoop ].bAgility ;
|
||||
gMercProfiles[ uiLoop ].bDexterity = tempProfiles[ uiLoop ].bDexterity ;
|
||||
gMercProfiles[ uiLoop ].bWisdom = tempProfiles[ uiLoop ].bWisdom ;
|
||||
gMercProfiles[ uiLoop ].bMarksmanship = tempProfiles[ uiLoop ].bMarksmanship ;
|
||||
gMercProfiles[ uiLoop ].bExplosive = tempProfiles[ uiLoop ].bExplosive ;
|
||||
gMercProfiles[ uiLoop ].bLeadership = tempProfiles[ uiLoop ].bLeadership ;
|
||||
gMercProfiles[ uiLoop ].bMedical = tempProfiles[ uiLoop ].bMedical ;
|
||||
gMercProfiles[ uiLoop ].bMechanical = tempProfiles[ uiLoop ].bMechanical ;
|
||||
gMercProfiles[ uiLoop ].bExpLevel = tempProfiles[ uiLoop ].bExpLevel ;
|
||||
|
||||
gMercProfiles[ uiLoop ].bEvolution = tempProfiles[ uiLoop ].bEvolution ;
|
||||
gMercProfiles[ uiLoop ].bSkillTrait = tempProfiles[ uiLoop ].bSkillTrait ;
|
||||
gMercProfiles[ uiLoop ].bSkillTrait2 = tempProfiles[ uiLoop ].bSkillTrait2 ;
|
||||
|
||||
memcpy( &(gMercProfiles[ uiLoop ].bBuddy), &(tempProfiles[ uiLoop ].bBuddy), 5 * sizeof (INT8));
|
||||
gMercProfiles[ uiLoop ].bLearnToLike = tempProfiles[ uiLoop ].bLearnToLike ;
|
||||
gMercProfiles[ uiLoop ].bLearnToLikeTime = tempProfiles[ uiLoop ].bLearnToLikeTime ;
|
||||
|
||||
memcpy( &(gMercProfiles[ uiLoop ].bHated), &(tempProfiles[ uiLoop ].bHated), 5 * sizeof (INT8));
|
||||
memcpy( &(gMercProfiles[ uiLoop ].bHatedTime), &(tempProfiles[ uiLoop ].bHatedTime), 5 * sizeof (INT8));
|
||||
gMercProfiles[ uiLoop ].bLearnToHate = tempProfiles[ uiLoop ].bLearnToHate ;
|
||||
gMercProfiles[ uiLoop ].bLearnToHateTime = tempProfiles[ uiLoop ].bLearnToHateTime ;
|
||||
|
||||
gMercProfiles[ uiLoop ].sSalary = tempProfiles[ uiLoop ].sSalary ;
|
||||
gMercProfiles[ uiLoop ].uiWeeklySalary = tempProfiles[ uiLoop ].uiWeeklySalary ;
|
||||
gMercProfiles[ uiLoop ].uiBiWeeklySalary = tempProfiles[ uiLoop ].uiBiWeeklySalary ;
|
||||
gMercProfiles[ uiLoop ].bMedicalDeposit = tempProfiles[ uiLoop ].bMedicalDeposit ;
|
||||
gMercProfiles[ uiLoop ].sMedicalDepositAmount = tempProfiles[ uiLoop ].sMedicalDepositAmount ;
|
||||
gMercProfiles[ uiLoop ].usOptionalGearCost = tempProfiles[ uiLoop ].usOptionalGearCost ;
|
||||
|
||||
gMercProfiles[ uiLoop ].bArmourAttractiveness = tempProfiles[ uiLoop ].bArmourAttractiveness ;
|
||||
gMercProfiles[ uiLoop ].bMainGunAttractiveness = tempProfiles[ uiLoop ].bMainGunAttractiveness ;
|
||||
|
||||
memcpy( &(gMercProfiles[ uiLoop ].usApproachFactor), &(tempProfiles[ uiLoop ].usApproachFactor), 4 * sizeof (UINT16));
|
||||
if (tempProfiles[ uiLoop ].fGoodGuy)
|
||||
{
|
||||
gMercProfiles[ uiLoop ].ubMiscFlags3 |= PROFILE_MISC_FLAG3_GOODGUY;
|
||||
}
|
||||
}
|
||||
|
||||
void OverwriteMercOpinionsWithXMLData( UINT32 uiLoop )
|
||||
{
|
||||
UINT8 cnt;
|
||||
|
||||
for (cnt=0; cnt<75; cnt++ )
|
||||
{
|
||||
gMercProfiles[ uiLoop ].bMercOpinion[cnt] = tempProfiles[ uiLoop ].bMercOpinion[cnt] ;
|
||||
}
|
||||
}
|
||||
@@ -197,4 +197,90 @@ SOLDIERTYPE * SwapLarrysProfiles( SOLDIERTYPE * pSoldier );
|
||||
|
||||
BOOLEAN DoesNPCOwnBuilding( SOLDIERTYPE *pSoldier, INT16 sGridNo );
|
||||
|
||||
// HEADROCK PROFEX: Temporary array for merc profile data, read from XML
|
||||
typedef struct
|
||||
{
|
||||
CHAR16 zName[NAME_LENGTH];
|
||||
CHAR16 zNickname[ NICKNAME_LENGTH ];
|
||||
UINT8 ubFaceIndex;
|
||||
UINT16 usEyesX;
|
||||
UINT16 usEyesY;
|
||||
UINT16 usMouthX;
|
||||
UINT16 usMouthY;
|
||||
UINT32 uiEyeDelay;
|
||||
UINT32 uiMouthDelay;
|
||||
UINT32 uiBlinkFrequency;
|
||||
UINT32 uiExpressionFrequency;
|
||||
|
||||
PaletteRepID PANTS;
|
||||
PaletteRepID VEST;
|
||||
PaletteRepID SKIN;
|
||||
PaletteRepID HAIR;
|
||||
|
||||
INT8 bSex;
|
||||
UINT8 ubBodyType;
|
||||
UINT32 uiBodyTypeSubFlags;
|
||||
|
||||
INT8 bAttitude;
|
||||
INT8 bPersonalityTrait;
|
||||
UINT8 ubNeedForSleep;
|
||||
|
||||
INT8 bReputationTolerance;
|
||||
INT8 bDeathRate;
|
||||
|
||||
INT8 bLifeMax;
|
||||
INT8 bLife;
|
||||
INT8 bStrength;
|
||||
INT8 bAgility;
|
||||
INT8 bDexterity;
|
||||
INT8 bWisdom;
|
||||
INT8 bMarksmanship;
|
||||
INT8 bExplosive;
|
||||
INT8 bLeadership;
|
||||
INT8 bMedical;
|
||||
INT8 bMechanical;
|
||||
|
||||
INT8 bExpLevel;
|
||||
|
||||
INT8 bEvolution;
|
||||
INT8 bSkillTrait;
|
||||
INT8 bSkillTrait2;
|
||||
|
||||
INT8 bBuddy[5];
|
||||
INT8 bLearnToLike;
|
||||
INT8 bLearnToLikeTime;
|
||||
|
||||
INT8 bHated[5];
|
||||
INT8 bHatedTime[5];
|
||||
INT8 bLearnToHate;
|
||||
INT8 bLearnToHateTime;
|
||||
|
||||
INT16 sSalary;
|
||||
UINT32 uiWeeklySalary;
|
||||
UINT32 uiBiWeeklySalary;
|
||||
INT8 bMedicalDeposit;
|
||||
UINT16 sMedicalDepositAmount;
|
||||
UINT16 usOptionalGearCost;
|
||||
|
||||
INT8 bArmourAttractiveness;
|
||||
INT8 bMainGunAttractiveness;
|
||||
|
||||
// This boolean DOES NOT EXIST in gMercProfiles - it is part of a flag set called ubMiscFlags. This code
|
||||
// reads the boolean and applies the flag to that flagset, if true.
|
||||
BOOLEAN fGoodGuy;
|
||||
|
||||
UINT16 usApproachFactor[4];
|
||||
|
||||
INT8 bMercOpinion[75];
|
||||
|
||||
} TEMPPROFILETYPE;
|
||||
|
||||
extern TEMPPROFILETYPE tempProfiles[NUM_PROFILES+1];
|
||||
|
||||
extern BOOLEAN WriteMercProfiles();
|
||||
extern BOOLEAN WriteMercOpinions();
|
||||
|
||||
void OverwriteMercProfileWithXMLData( UINT32 uiLoop );
|
||||
void OverwriteMercOpinionsWithXMLData( UINT32 uiLoop );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2646,6 +2646,30 @@ BOOLEAN SetSectorFlag( INT16 sMapX, INT16 sMapY, UINT8 bMapZ, UINT32 uiFlagToSet
|
||||
{
|
||||
if( uiFlagToSet == SF_ALREADY_VISITED )
|
||||
{
|
||||
|
||||
// HEADROCK HAM 3.5: This is no longer required at all.
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
// HEADROCK HAM 3.4: Externalized. Hidden facilities listed on the facility array will be
|
||||
// added to the sector info now, upon the first visit.
|
||||
|
||||
/*for(UINT32 cnt=0; (gFacilityLocations[cnt].uiSectorID >= 0 && gFacilityLocations[cnt].uiSectorID <= 256); cnt++ )
|
||||
{
|
||||
// Does the current record match the current sector?
|
||||
if (gFacilityLocations[cnt].uiSectorID == SECTOR( sMapX, sMapY ))
|
||||
{
|
||||
// Is the current record set to be revealed?
|
||||
if (gFacilityLocations[cnt].fHidden == 1)
|
||||
{
|
||||
// Reveal the facility.
|
||||
SectorInfo[ SECTOR( sMapX, sMapY) ].uiFacilitiesFlags |= (1 << (gFacilityLocations[cnt].uiFacilityType - 1));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
// HEADROCK HAM 3.4: Externalized.
|
||||
/*
|
||||
// do certain things when particular sectors are visited
|
||||
if ( ( sMapX == TIXA_SECTOR_X ) && ( sMapY == TIXA_SECTOR_Y ) )
|
||||
{
|
||||
@@ -2660,7 +2684,7 @@ BOOLEAN SetSectorFlag( INT16 sMapX, INT16 sMapY, UINT8 bMapZ, UINT32 uiFlagToSet
|
||||
SectorInfo[ SEC_H14 ].uiFacilitiesFlags |= SFCF_GUN_RANGE;
|
||||
SectorInfo[ SEC_I13 ].uiFacilitiesFlags |= SFCF_GUN_RANGE;
|
||||
SectorInfo[ SEC_I14 ].uiFacilitiesFlags |= SFCF_GUN_RANGE;
|
||||
}
|
||||
}*/
|
||||
|
||||
if ( !GetSectorFlagStatus( sMapX, sMapY, bMapZ, SF_ALREADY_VISITED ) )
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Version="8,00"
|
||||
Name="Tactical_2005Express"
|
||||
ProjectGUID="{D4BDA6AD-9B61-4953-892D-DA3F8CC7E096}"
|
||||
RootNamespace="Tactical_2005Express"
|
||||
@@ -600,6 +600,10 @@
|
||||
RelativePath=".\XML.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Profiles.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
@@ -994,6 +998,14 @@
|
||||
RelativePath=".\XML_Merge.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Opinions.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Profiles.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_SectorLoadscreens.cpp"
|
||||
>
|
||||
|
||||
@@ -603,6 +603,10 @@
|
||||
RelativePath="XML.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Profiles.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
@@ -995,6 +999,14 @@
|
||||
RelativePath="XML_Merge.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Opinions.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Profiles.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="XML_SectorLoadscreens.cpp"
|
||||
>
|
||||
|
||||
+21
-3
@@ -48,6 +48,8 @@
|
||||
#include "NPC.h"
|
||||
#endif
|
||||
|
||||
// HEADROCK HAM 3.2: Gamesettings.h for external modifications to team turns.
|
||||
#include "GameSettings.h"
|
||||
#include "Reinforcement.h"
|
||||
#include "fresh_header.h"
|
||||
//forward declarations of common classes to eliminate includes
|
||||
@@ -315,9 +317,15 @@ void EndTurn( UINT8 ubNextTeam )
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPossiblePendingEnemiesToBattle();
|
||||
|
||||
AddPossiblePendingMilitiaToBattle();
|
||||
// HEADROCK HAM 3.2: Experimental fix to force reinforcements enter battle with 0 APs.
|
||||
if (gGameExternalOptions.ubReinforcementsFirstTurnFreeze != 1 && gGameExternalOptions.ubReinforcementsFirstTurnFreeze != 2)
|
||||
{
|
||||
AddPossiblePendingEnemiesToBattle();
|
||||
}
|
||||
if (gGameExternalOptions.ubReinforcementsFirstTurnFreeze != 1 && gGameExternalOptions.ubReinforcementsFirstTurnFreeze != 3)
|
||||
{
|
||||
AddPossiblePendingMilitiaToBattle();
|
||||
}
|
||||
|
||||
// InitEnemyUIBar( );
|
||||
|
||||
@@ -337,6 +345,16 @@ void EndTurn( UINT8 ubNextTeam )
|
||||
|
||||
if(is_server || !is_client) BeginTeamTurn( gTacticalStatus.ubCurrentTeam );
|
||||
|
||||
// HEADROCK HAM 3.2: Experimental fix to force reinforcements enter battle with 0 APs.
|
||||
if (gGameExternalOptions.ubReinforcementsFirstTurnFreeze == 1 || gGameExternalOptions.ubReinforcementsFirstTurnFreeze == 2)
|
||||
{
|
||||
AddPossiblePendingEnemiesToBattle();
|
||||
}
|
||||
if (gGameExternalOptions.ubReinforcementsFirstTurnFreeze == 1 || gGameExternalOptions.ubReinforcementsFirstTurnFreeze == 3)
|
||||
{
|
||||
AddPossiblePendingMilitiaToBattle();
|
||||
}
|
||||
|
||||
BetweenTurnsVisibilityAdjustments();
|
||||
}
|
||||
}
|
||||
|
||||
+295
-125
@@ -1259,9 +1259,11 @@ void GetTBMousePositionInput( UINT32 *puiNewEvent )
|
||||
}
|
||||
|
||||
usOldMapPos = sMapPos;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GetPolledKeyboardInput( UINT32 *puiNewEvent )
|
||||
{
|
||||
static BOOLEAN fShifted = FALSE;
|
||||
@@ -1406,6 +1408,7 @@ void GetPolledKeyboardInput( UINT32 *puiNewEvent )
|
||||
|
||||
fEndDown = FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -3390,9 +3393,20 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
|
||||
}
|
||||
for (bLoop=gTacticalStatus.Team[gbPlayerNum].bFirstID, pTeamSoldier=MercPtrs[bLoop]; bLoop <= gTacticalStatus.Team[gbPlayerNum].bLastID; bLoop++, pTeamSoldier++)
|
||||
{
|
||||
if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) && pTeamSoldier->bAssignment == CurrentSquad( ) && !AM_A_ROBOT( pTeamSoldier ) )
|
||||
// HEADROCK HAM 3.5: When this INI setting is enabled, ALL mercs in the current sector will do a goggle swap.
|
||||
if (gGameExternalOptions.fGoggleSwapAffectsAllMercsInSector)
|
||||
{
|
||||
SwapGogglesUniformly(pTeamSoldier, fToNightVision);
|
||||
if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) && pTeamSoldier->sSectorX == gWorldSectorX && pTeamSoldier->sSectorY == gWorldSectorY && pTeamSoldier->bSectorZ == gbWorldSectorZ && !AM_A_ROBOT( pTeamSoldier ) )
|
||||
{
|
||||
SwapGogglesUniformly(pTeamSoldier, fToNightVision);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) && pTeamSoldier->bAssignment == CurrentSquad( ) && !AM_A_ROBOT( pTeamSoldier ) )
|
||||
{
|
||||
SwapGogglesUniformly(pTeamSoldier, fToNightVision);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3400,9 +3414,20 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
|
||||
{
|
||||
for (bLoop=gTacticalStatus.Team[gbPlayerNum].bFirstID, pTeamSoldier=MercPtrs[bLoop]; bLoop <= gTacticalStatus.Team[gbPlayerNum].bLastID; bLoop++, pTeamSoldier++)
|
||||
{
|
||||
if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) && pTeamSoldier->bAssignment == CurrentSquad( ) && !AM_A_ROBOT( pTeamSoldier ) )
|
||||
// HEADROCK HAM 3.5: When this INI setting is enabled, ALL mercs in the current sector will do a goggle swap.
|
||||
if (gGameExternalOptions.fGoggleSwapAffectsAllMercsInSector)
|
||||
{
|
||||
SwapGoggles(pTeamSoldier);
|
||||
if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) && pTeamSoldier->sSectorX == gWorldSectorX && pTeamSoldier->sSectorY == gWorldSectorY && pTeamSoldier->bSectorZ == gbWorldSectorZ && !AM_A_ROBOT( pTeamSoldier ) )
|
||||
{
|
||||
SwapGoggles(pTeamSoldier);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) && pTeamSoldier->bAssignment == CurrentSquad( ) && !AM_A_ROBOT( pTeamSoldier ) )
|
||||
{
|
||||
SwapGoggles(pTeamSoldier);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3772,11 +3797,11 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
|
||||
//if the display cover or line of sight is being displayed
|
||||
if( _KeyDown( END ) || _KeyDown( DEL ) )
|
||||
{
|
||||
//f( _KeyDown( DEL ) )
|
||||
//ChangeSizeOfDisplayCover( gGameSettings.ubSizeOfDisplayCover + 1 );
|
||||
//if( _KeyDown( DEL ) )
|
||||
// ChangeSizeOfDisplayCover( gGameSettings.ubSizeOfDisplayCover + 1 );
|
||||
|
||||
//if( _KeyDown( END ) )
|
||||
//ChangeSizeOfLOS( gGameSettings.ubSizeOfLOS + 1 );
|
||||
// ChangeSizeOfLOS( gGameSettings.ubSizeOfLOS + 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4019,10 +4044,10 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
|
||||
if( _KeyDown( END ) || _KeyDown( DEL ) )
|
||||
{
|
||||
//if( _KeyDown( DEL ) )
|
||||
//ChangeSizeOfDisplayCover( gGameSettings.ubSizeOfDisplayCover - 1 );
|
||||
// ChangeSizeOfDisplayCover( gGameSettings.ubSizeOfDisplayCover - 1 );
|
||||
|
||||
//if( _KeyDown( END ) )
|
||||
//ChangeSizeOfLOS( gGameSettings.ubSizeOfLOS - 1 );
|
||||
// ChangeSizeOfLOS( gGameSettings.ubSizeOfLOS - 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5712,149 +5737,274 @@ bool BadGoggles(SOLDIERTYPE *pTeamSoldier) {
|
||||
|
||||
void SwapGoggles(SOLDIERTYPE *pTeamSoldier)
|
||||
{
|
||||
/* CHRISL - Adjusted this option to allow the game to search through Helmet attachments
|
||||
as well as inventory positions.
|
||||
*/
|
||||
OBJECTTYPE * pObj;
|
||||
OBJECTTYPE * pGoggles = NULL;
|
||||
INT8 bSlot1;
|
||||
int bestBonus;
|
||||
bool itemFound = false;
|
||||
//CHRISL: Before doing anything, we should look at both head slots to see if either slot has some sort of goggles
|
||||
for(bSlot1 = HEAD1POS; bSlot1 <= HEAD2POS; bSlot1++)
|
||||
// WDS - Smart goggle switching
|
||||
// NOTE: Investigate using GetItemVisionRangeBonus from Items.cpp???
|
||||
if (gGameExternalOptions.smartGoggleSwitch)
|
||||
{
|
||||
if(Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus > 0)
|
||||
itemFound = true;
|
||||
if(Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus > 0)
|
||||
itemFound = true;
|
||||
}
|
||||
//2 head slots
|
||||
for (bSlot1 = HEAD1POS; bSlot1 <= HEAD2POS; bSlot1++)
|
||||
{
|
||||
// if wearing sungoggles
|
||||
if ( Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus > 0 )
|
||||
// Look through the head slots and find any sort of goggle or an empty spot
|
||||
int slotToUse = -1;
|
||||
|
||||
for (int headSlot = HEAD1POS; headSlot <= HEAD2POS; ++headSlot)
|
||||
{
|
||||
itemFound = true;
|
||||
bestBonus = 0;
|
||||
pGoggles = FindNightGogglesInInv( pTeamSoldier );
|
||||
//search for better goggles on the helmet
|
||||
if (pGoggles)
|
||||
if ( (Item[pTeamSoldier->inv[headSlot].usItem].brightlightvisionrangebonus > 0) )
|
||||
{
|
||||
bestBonus = Item[pGoggles->usItem].nightvisionrangebonus;
|
||||
}
|
||||
//search helmet and vest
|
||||
for(UINT8 gear = HELMETPOS; gear <= VESTPOS; gear++)
|
||||
{
|
||||
pObj = &(pTeamSoldier->inv[gear]);
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
|
||||
{
|
||||
if ( Item[ iter->usItem ].nightvisionrangebonus > bestBonus && Item[ iter->usItem ].usItemClass == IC_FACE )
|
||||
{
|
||||
pGoggles = &(*iter);
|
||||
bestBonus = Item[ iter->usItem ].nightvisionrangebonus;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( pGoggles )
|
||||
{
|
||||
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
|
||||
slotToUse = headSlot;
|
||||
break;
|
||||
}
|
||||
// HEADROCK HAM B2.8: If no goggles were found to switch to, the character will remove what they're
|
||||
// wearing, to avoid situations where a character refuses to remove the wrong set of goggles and
|
||||
// thus suffers a penalty.
|
||||
else
|
||||
}
|
||||
else if ( (Item[pTeamSoldier->inv[headSlot].usItem].nightvisionrangebonus > 0) )
|
||||
{
|
||||
// Remove sungoggles.
|
||||
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE);
|
||||
slotToUse = headSlot;
|
||||
break;
|
||||
}
|
||||
else if (pTeamSoldier->inv[headSlot].exists() == false)
|
||||
{
|
||||
slotToUse = headSlot;
|
||||
}
|
||||
}
|
||||
// else if wearing NVGs
|
||||
else if(Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus > 0)
|
||||
|
||||
if (slotToUse == -1)
|
||||
{
|
||||
itemFound = true;
|
||||
bestBonus = 0;
|
||||
pGoggles = FindSunGogglesInInv( pTeamSoldier );
|
||||
//search for better goggles on the helmet
|
||||
if (pGoggles)
|
||||
// No place to swap in a new goggle, give up
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the best goggles for the current time of day anywhere in inventory
|
||||
OBJECTTYPE * pGoggles = 0;
|
||||
if (DayTime())
|
||||
{
|
||||
pGoggles = FindSunGogglesInInv( pTeamSoldier, TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
pGoggles = FindNightGogglesInInv( pTeamSoldier, TRUE );
|
||||
}
|
||||
|
||||
if (pGoggles)
|
||||
{
|
||||
// Now either swap or equip the best one that was found
|
||||
if (pTeamSoldier->inv[slotToUse].exists())
|
||||
{
|
||||
bestBonus = Item[pGoggles->usItem].brightlightvisionrangebonus;
|
||||
SwapObjs( pTeamSoldier, slotToUse, pGoggles, TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
pGoggles->MoveThisObjectTo(pTeamSoldier->inv[slotToUse], 1, pTeamSoldier, slotToUse);
|
||||
}
|
||||
//search helmet and vest
|
||||
for(UINT8 gear = HELMETPOS; gear <= VESTPOS; gear++)
|
||||
}
|
||||
else
|
||||
{
|
||||
// No goggles to equip, should the current ones be unequiped?
|
||||
if (pTeamSoldier->inv[slotToUse].exists())
|
||||
{
|
||||
pObj = &(pTeamSoldier->inv[gear]);
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
|
||||
if ((DayTime() && (Item[pTeamSoldier->inv[slotToUse].usItem].nightvisionrangebonus > 0)) ||
|
||||
(!DayTime() && (Item[pTeamSoldier->inv[slotToUse].usItem].brightlightvisionrangebonus > 0)))
|
||||
{
|
||||
if ( Item[ iter->usItem ].brightlightvisionrangebonus > bestBonus && Item[ iter->usItem ].usItemClass == IC_FACE )
|
||||
// It's day and we're wearing night goggles (or vice-versa), find a place to stash them
|
||||
if (pTeamSoldier->inv[ HELMETPOS ].exists())
|
||||
{
|
||||
pGoggles = &(*iter);
|
||||
bestBonus = Item[ iter->usItem ].brightlightvisionrangebonus;
|
||||
if (pTeamSoldier->inv[ HELMETPOS ].AttachObject( NULL, &pTeamSoldier->inv[slotToUse] ))
|
||||
{
|
||||
// It worked!
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try dumping it anywhere in inventory because it doesn't attach to the helmet
|
||||
if (ValidAttachment( pTeamSoldier->inv[slotToUse].usItem, pTeamSoldier->inv[HELMETPOS].usItem ) &&
|
||||
pTeamSoldier->inv[slotToUse][0]->attachments.size() < MAX_ATTACHMENTS)
|
||||
{
|
||||
pTeamSoldier->inv[HELMETPOS].AttachObject( pTeamSoldier, &pTeamSoldier->inv[slotToUse], FALSE, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove sungoggles.
|
||||
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[slotToUse], FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try dumping it anywhere in inventory given there's no helemt
|
||||
if (ValidAttachment( pTeamSoldier->inv[slotToUse].usItem, pTeamSoldier->inv[HELMETPOS].usItem ) &&
|
||||
pTeamSoldier->inv[slotToUse][0]->attachments.size() < MAX_ATTACHMENTS)
|
||||
{
|
||||
pTeamSoldier->inv[HELMETPOS].AttachObject( pTeamSoldier, &pTeamSoldier->inv[slotToUse], FALSE, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove sungoggles.
|
||||
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[slotToUse], FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( pGoggles )
|
||||
{
|
||||
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
|
||||
break;
|
||||
}
|
||||
// HEADROCK HAM B2.8: If no goggles were found to switch to, the character will remove what they're
|
||||
// wearing, to avoid situations where a character refuses to remove the wrong set of goggles and
|
||||
// thus suffers a penalty.
|
||||
else
|
||||
{
|
||||
// Remove nightgoggles.
|
||||
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// else if not wearing anything and no goggles found
|
||||
else if(itemFound == false && pTeamSoldier->inv[bSlot1].exists() == false)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal goggle switching
|
||||
/* CHRISL - Adjusted this option to allow the game to search through Helmet attachments
|
||||
as well as inventory positions.
|
||||
*/
|
||||
OBJECTTYPE * pObj;
|
||||
OBJECTTYPE * pGoggles = NULL;
|
||||
INT8 bSlot1;
|
||||
int bestBonus;
|
||||
bool itemFound = false;
|
||||
//CHRISL: Before doing anything, we should look at both head slots to see if either slot has some sort of goggles
|
||||
for(bSlot1 = HEAD1POS; bSlot1 <= HEAD2POS; bSlot1++)
|
||||
{
|
||||
bestBonus = 0;
|
||||
// search helmet and vest for goggles of some kind
|
||||
for(UINT8 gear = HELMETPOS; gear <= VESTPOS; gear++)
|
||||
if(Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus > 0)
|
||||
itemFound = true;
|
||||
if(Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus > 0)
|
||||
itemFound = true;
|
||||
}
|
||||
//2 head slots
|
||||
for (bSlot1 = HEAD1POS; bSlot1 <= HEAD2POS; bSlot1++)
|
||||
{
|
||||
// if wearing sungoggles
|
||||
if ( Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus > 0 )
|
||||
{
|
||||
pObj = &(pTeamSoldier->inv[gear]);
|
||||
for(attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
|
||||
itemFound = true;
|
||||
bestBonus = 0;
|
||||
pGoggles = FindNightGogglesInInv( pTeamSoldier );
|
||||
//search for better goggles on the helmet
|
||||
if (pGoggles)
|
||||
{
|
||||
if(DayTime() == TRUE && Item[iter->usItem].brightlightvisionrangebonus > bestBonus && Item[iter->usItem].usItemClass == IC_FACE)
|
||||
bestBonus = Item[pGoggles->usItem].nightvisionrangebonus;
|
||||
}
|
||||
//search helmet and vest
|
||||
for(UINT8 gear = HELMETPOS; gear <= VESTPOS; gear++)
|
||||
{
|
||||
pObj = &(pTeamSoldier->inv[gear]);
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
|
||||
{
|
||||
pGoggles = &(*iter);
|
||||
bestBonus = Item[iter->usItem].brightlightvisionrangebonus;
|
||||
}
|
||||
else if(NightTime() == TRUE && Item[iter->usItem].nightvisionrangebonus > bestBonus && Item[iter->usItem].usItemClass == IC_FACE)
|
||||
{
|
||||
pGoggles = &(*iter);
|
||||
bestBonus = Item[iter->usItem].nightvisionrangebonus;
|
||||
if ( Item[ iter->usItem ].nightvisionrangebonus > bestBonus && Item[ iter->usItem ].usItemClass == IC_FACE )
|
||||
{
|
||||
pGoggles = &(*iter);
|
||||
bestBonus = Item[ iter->usItem ].nightvisionrangebonus;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pGoggles)
|
||||
{
|
||||
pGoggles->MoveThisObjectTo(pTeamSoldier->inv[bSlot1], 1, pTeamSoldier, bSlot1);
|
||||
pObj->RemoveAttachment(pGoggles);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(pTeamSoldier->inv[bSlot1].exists() == false)
|
||||
{
|
||||
if(DayTime() == TRUE)
|
||||
pGoggles = FindSunGogglesInInv( pTeamSoldier );
|
||||
else
|
||||
pGoggles = FindNightGogglesInInv( pTeamSoldier );
|
||||
if(pGoggles)
|
||||
if ( pGoggles )
|
||||
{
|
||||
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
|
||||
break;
|
||||
}
|
||||
// HEADROCK HAM B2.8: If no goggles were found to switch to, the character will remove what they're
|
||||
// wearing, to avoid situations where a character refuses to remove the wrong set of goggles and
|
||||
// thus suffers a penalty.
|
||||
else
|
||||
{
|
||||
if (ValidAttachment( pTeamSoldier->inv[bSlot1].usItem, pTeamSoldier->inv[HELMETPOS].usItem ) &&
|
||||
pTeamSoldier->inv[bSlot1][0]->attachments.size() < MAX_ATTACHMENTS)
|
||||
{
|
||||
pTeamSoldier->inv[HELMETPOS].AttachObject( pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE, 0 );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove sungoggles.
|
||||
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
// else if wearing NVGs
|
||||
else if(Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus > 0)
|
||||
{
|
||||
break;
|
||||
itemFound = true;
|
||||
bestBonus = 0;
|
||||
pGoggles = FindSunGogglesInInv( pTeamSoldier );
|
||||
//search for better goggles on the helmet
|
||||
if (pGoggles)
|
||||
{
|
||||
bestBonus = Item[pGoggles->usItem].brightlightvisionrangebonus;
|
||||
}
|
||||
//search helmet and vest
|
||||
for(UINT8 gear = HELMETPOS; gear <= VESTPOS; gear++)
|
||||
{
|
||||
pObj = &(pTeamSoldier->inv[gear]);
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
|
||||
{
|
||||
if ( Item[ iter->usItem ].brightlightvisionrangebonus > bestBonus && Item[ iter->usItem ].usItemClass == IC_FACE )
|
||||
{
|
||||
pGoggles = &(*iter);
|
||||
bestBonus = Item[ iter->usItem ].brightlightvisionrangebonus;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( pGoggles )
|
||||
{
|
||||
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
|
||||
break;
|
||||
}
|
||||
// HEADROCK HAM B2.8: If no goggles were found to switch to, the character will remove what they're
|
||||
// wearing, to avoid situations where a character refuses to remove the wrong set of goggles and
|
||||
// thus suffers a penalty.
|
||||
else
|
||||
{
|
||||
if (ValidAttachment( pTeamSoldier->inv[bSlot1].usItem, pTeamSoldier->inv[HELMETPOS].usItem ) &&
|
||||
pTeamSoldier->inv[bSlot1][0]->attachments.size() < MAX_ATTACHMENTS)
|
||||
{
|
||||
pTeamSoldier->inv[HELMETPOS].AttachObject( pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE, 0 );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove nightgoggles.
|
||||
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// else if not wearing anything and no goggles found
|
||||
else if(itemFound == false && pTeamSoldier->inv[bSlot1].exists() == false)
|
||||
{
|
||||
bestBonus = 0;
|
||||
// search helmet and vest for goggles of some kind
|
||||
for(UINT8 gear = HELMETPOS; gear <= VESTPOS; gear++)
|
||||
{
|
||||
pObj = &(pTeamSoldier->inv[gear]);
|
||||
for(attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
|
||||
{
|
||||
if(DayTime() == TRUE && Item[iter->usItem].brightlightvisionrangebonus > bestBonus && Item[iter->usItem].usItemClass == IC_FACE)
|
||||
{
|
||||
pGoggles = &(*iter);
|
||||
bestBonus = Item[iter->usItem].brightlightvisionrangebonus;
|
||||
}
|
||||
else if(NightTime() == TRUE && Item[iter->usItem].nightvisionrangebonus > bestBonus && Item[iter->usItem].usItemClass == IC_FACE)
|
||||
{
|
||||
pGoggles = &(*iter);
|
||||
bestBonus = Item[iter->usItem].nightvisionrangebonus;
|
||||
}
|
||||
}
|
||||
if(pGoggles)
|
||||
{
|
||||
pGoggles->MoveThisObjectTo(pTeamSoldier->inv[bSlot1], 1, pTeamSoldier, bSlot1);
|
||||
pObj->RemoveAttachment(pGoggles);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(pTeamSoldier->inv[bSlot1].exists() == false)
|
||||
{
|
||||
if(DayTime() == TRUE)
|
||||
pGoggles = FindSunGogglesInInv( pTeamSoldier );
|
||||
else
|
||||
pGoggles = FindNightGogglesInInv( pTeamSoldier );
|
||||
if(pGoggles)
|
||||
{
|
||||
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fCharacterInfoPanelDirty = TRUE;
|
||||
fTeamPanelDirty = TRUE;
|
||||
fInterfacePanelDirty = DIRTYLEVEL2;
|
||||
@@ -5922,9 +6072,18 @@ void SwapGogglesUniformly(SOLDIERTYPE *pTeamSoldier, BOOLEAN fToNightVision)
|
||||
}
|
||||
else if (Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus <= 0)
|
||||
{
|
||||
// Remove sungoggles.
|
||||
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE);
|
||||
break;
|
||||
if (ValidAttachment( pTeamSoldier->inv[bSlot1].usItem, pTeamSoldier->inv[HELMETPOS].usItem ) &&
|
||||
pTeamSoldier->inv[bSlot1][0]->attachments.size() < MAX_ATTACHMENTS)
|
||||
{
|
||||
pTeamSoldier->inv[HELMETPOS].AttachObject( pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE, 0 );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove nightgoggles.
|
||||
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5961,9 +6120,18 @@ void SwapGogglesUniformly(SOLDIERTYPE *pTeamSoldier, BOOLEAN fToNightVision)
|
||||
}
|
||||
else if (Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus <= 0)
|
||||
{
|
||||
// Remove nightgoggles.
|
||||
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE);
|
||||
break;
|
||||
if (ValidAttachment( pTeamSoldier->inv[bSlot1].usItem, pTeamSoldier->inv[HELMETPOS].usItem ) &&
|
||||
pTeamSoldier->inv[bSlot1][0]->attachments.size() < MAX_ATTACHMENTS)
|
||||
{
|
||||
pTeamSoldier->inv[HELMETPOS].AttachObject( pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE, 0 );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove nightgoggles.
|
||||
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6038,6 +6206,8 @@ void SeperateItems()
|
||||
CreateAmmo(gWorldItems[ uiLoop ].object[x]->data.gun.usGunAmmoItem, &gTempObject, gWorldItems[ uiLoop ].object[x]->data.gun.ubGunShotsLeft);
|
||||
gWorldItems[ uiLoop ].object[x]->data.gun.ubGunShotsLeft = 0;
|
||||
gWorldItems[ uiLoop ].object[x]->data.gun.usGunAmmoItem = NONE;
|
||||
// HEADROCK HAM 3.5: Clear ammo type
|
||||
gWorldItems[ uiLoop ].object[x]->data.gun.ubGunAmmoType = NONE;
|
||||
|
||||
// put it on the ground
|
||||
AddItemToPool( gWorldItems[ uiLoop ].sGridNo, &gTempObject, 1, gWorldItems[ uiLoop ].ubLevel, WORLD_ITEM_REACHABLE , -1 );
|
||||
|
||||
+12
-10
@@ -387,8 +387,10 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT16 sMapPos, BOOLEAN
|
||||
pSoldier->bDoAutofire++;
|
||||
sAPCosts = CalcTotalAPsToAttack( pSoldier, sMapPos, TRUE, 0);
|
||||
}
|
||||
|
||||
while(EnoughPoints( pSoldier, sAPCosts, 0, FALSE ) && sAPCosts == sCurAPCosts && pSoldier->inv[ pSoldier->ubAttackingHand ][0]->data.gun.ubGunShotsLeft >= pSoldier->bDoAutofire);
|
||||
pSoldier->bDoAutofire--;
|
||||
|
||||
}
|
||||
|
||||
gfUIAutofireBulletCount = TRUE;
|
||||
@@ -579,7 +581,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT16 sMapPos, BOOLEAN
|
||||
// and also a Targetted Bodypart indicator.
|
||||
if(pSoldier->bDoAutofire == 0 && gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
|
||||
{
|
||||
if (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 2)
|
||||
if (gGameExternalOptions.ubNewCTHBars == 1 || gGameExternalOptions.ubNewCTHBars == 2)
|
||||
{
|
||||
// Burst mode only
|
||||
OBJECTTYPE * pInHand;
|
||||
@@ -648,7 +650,7 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT16 sMapPos, BOOLEAN
|
||||
|
||||
else if(pSoldier->bDoAutofire > 0 && gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
|
||||
{
|
||||
if (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3)
|
||||
if (gGameExternalOptions.ubNewCTHBars == 1 || gGameExternalOptions.ubNewCTHBars == 3)
|
||||
{
|
||||
gbCtHBurstCount = 1;
|
||||
|
||||
@@ -1412,9 +1414,9 @@ void DetermineCursorBodyLocation( UINT8 ubSoldierID, BOOLEAN fDisplay, BOOLEAN f
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
// HEADROCK: This'll toggle whether the bodypart targetting indicator shows up in the burst/auto
|
||||
// CTH cursors.
|
||||
else if ( pSoldier->bDoBurst && !pSoldier->bDoAutofire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 2) )
|
||||
else if ( pSoldier->bDoBurst && !pSoldier->bDoAutofire && (gGameExternalOptions.ubNewCTHBars == 1 || gGameExternalOptions.ubNewCTHBars == 2) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
else if ( pSoldier->bDoBurst && pSoldier->bDoAutofire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3) )
|
||||
else if ( pSoldier->bDoBurst && pSoldier->bDoAutofire && (gGameExternalOptions.ubNewCTHBars == 1 || gGameExternalOptions.ubNewCTHBars == 3) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
return;
|
||||
}
|
||||
@@ -1441,9 +1443,9 @@ void DetermineCursorBodyLocation( UINT8 ubSoldierID, BOOLEAN fDisplay, BOOLEAN f
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
// HEADROCK: This'll toggle whether the bodypart targetting indicator shows up in the burst/auto
|
||||
// CTH cursors.
|
||||
else if ( pSoldier->bDoBurst && !pSoldier->bDoAutofire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 2) )
|
||||
else if ( pSoldier->bDoBurst && !pSoldier->bDoAutofire && (gGameExternalOptions.ubNewCTHBars == 1 || gGameExternalOptions.ubNewCTHBars == 2) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
else if ( pSoldier->bDoBurst && pSoldier->bDoAutofire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3) )
|
||||
else if ( pSoldier->bDoBurst && pSoldier->bDoAutofire && (gGameExternalOptions.ubNewCTHBars == 1 || gGameExternalOptions.ubNewCTHBars == 3) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
break;
|
||||
|
||||
@@ -1453,9 +1455,9 @@ void DetermineCursorBodyLocation( UINT8 ubSoldierID, BOOLEAN fDisplay, BOOLEAN f
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
// HEADROCK: This'll toggle whether the bodypart targetting indicator shows up in the burst/auto
|
||||
// CTH cursors.
|
||||
else if ( pSoldier->bDoBurst && !pSoldier->bDoAutofire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 2) )
|
||||
else if ( pSoldier->bDoBurst && !pSoldier->bDoAutofire && (gGameExternalOptions.ubNewCTHBars == 1 || gGameExternalOptions.ubNewCTHBars == 2) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
else if ( pSoldier->bDoBurst && pSoldier->bDoAutofire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3) )
|
||||
else if ( pSoldier->bDoBurst && pSoldier->bDoAutofire && (gGameExternalOptions.ubNewCTHBars == 1 || gGameExternalOptions.ubNewCTHBars == 3) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
break;
|
||||
|
||||
@@ -1465,9 +1467,9 @@ void DetermineCursorBodyLocation( UINT8 ubSoldierID, BOOLEAN fDisplay, BOOLEAN f
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
// HEADROCK: This'll toggle whether the bodypart targetting indicator shows up in the burst/auto
|
||||
// CTH cursors.
|
||||
else if ( pSoldier->bDoBurst && !pSoldier->bDoAutofire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 2) )
|
||||
else if ( pSoldier->bDoBurst && !pSoldier->bDoAutofire && (gGameExternalOptions.ubNewCTHBars == 1 || gGameExternalOptions.ubNewCTHBars == 2) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
else if ( pSoldier->bDoBurst && pSoldier->bDoAutofire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3) )
|
||||
else if ( pSoldier->bDoBurst && pSoldier->bDoAutofire && (gGameExternalOptions.ubNewCTHBars == 1 || gGameExternalOptions.ubNewCTHBars == 3) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
+12
-1
@@ -310,7 +310,18 @@ INT32 AddVehicleToList( INT16 sMapX, INT16 sMapY, INT16 sGridNo, UINT8 ubType )
|
||||
Assert( 0 );
|
||||
}
|
||||
|
||||
pGroup->ubTransportationMask = (UINT8)iMvtTypes[ ubType ];
|
||||
|
||||
// HEADROCK HAM 3.1: An INI setting allows us to turn the Hummer into a true offroad vehicle. It will use the
|
||||
// "TRUCK" type movement, which allows it to go into mild non-road terrain. I wish I could come with a more
|
||||
// subtle method than this crude override, but this is what I've got at the moment.
|
||||
if (gGameExternalOptions.fHumveeOffroad && ubType == HUMMER)
|
||||
{
|
||||
pGroup->ubTransportationMask = TRUCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
pGroup->ubTransportationMask = (UINT8)iMvtTypes[ ubType ];
|
||||
}
|
||||
|
||||
// ARM: setup group movement defaults
|
||||
pGroup->ubSectorX = ( UINT8 ) sMapX;
|
||||
|
||||
+267
-70
@@ -1740,9 +1740,9 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT16 sTargetGridNo )
|
||||
// uiHitChance = MINCHANCETOHIT;
|
||||
//else
|
||||
// uiHitChance -= 30;
|
||||
if(uiHitChance <= (UINT16)(__max(30, gGameExternalOptions.iMinimumCTH + 30)))
|
||||
if(uiHitChance <= (UINT16)(__max(30, gGameExternalOptions.ubMinimumCTH + 30)))
|
||||
{
|
||||
uiHitChance = gGameExternalOptions.iMinimumCTH ;
|
||||
uiHitChance = gGameExternalOptions.ubMinimumCTH ;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3564,13 +3564,16 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
bool highPowerScope = false;
|
||||
UINT32 pScope;
|
||||
|
||||
// HEADROCK HAM 3.5: Variable holds total autofire penalty.
|
||||
INT16 sTotalAutofirePenalty = 0;
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcChanceToHitGun"));
|
||||
|
||||
if ( pSoldier->stats.bMarksmanship == 0 )
|
||||
{
|
||||
// HEADROCK: (HAM) Altered to accept external arguments
|
||||
// return( MINCHANCETOHIT );
|
||||
return( gGameExternalOptions.iMinimumCTH );
|
||||
return( gGameExternalOptions.ubMinimumCTH );
|
||||
}
|
||||
|
||||
// make sure the guy's actually got a weapon in his hand!
|
||||
@@ -3766,54 +3769,8 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
iPenalty /= 2 * NUM_SKILL_TRAITS( pSoldier, AUTO_WEAPS );
|
||||
}
|
||||
iChance -= iPenalty;
|
||||
// HEADROCK HAM B2.5: One of every X bullets in a tracer magazine is a tracer round, which will
|
||||
// bump the CTH up by a certain amount.
|
||||
|
||||
if (AmmoTypes[(*pInHand)[0]->data.gun.ubGunAmmoType].tracerEffect == 1 && gGameExternalOptions.iRealisticTracers > 0 )
|
||||
{
|
||||
UINT16 iBulletsLeft, iTracersFired, iBulletsPerTracer, iBulletsSinceLastTracer;
|
||||
UINT8 cnt;
|
||||
UINT16 iAutoPenaltySinceLastTracer;
|
||||
iTracersFired = 0;
|
||||
iBulletsPerTracer = gGameExternalOptions.iNumBulletsPerTracer;
|
||||
|
||||
// Calculate number of bullets left right before firing this bullet
|
||||
if (fCalculateCTHDuringGunfire)
|
||||
{
|
||||
iBulletsLeft = (*pInHand)[0]->data.gun.ubGunShotsLeft + (pSoldier->bDoBurst - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
iBulletsLeft = (*pInHand)[0]->data.gun.ubGunShotsLeft;
|
||||
}
|
||||
|
||||
iBulletsSinceLastTracer = 0;
|
||||
for (cnt=0;cnt<pSoldier->bDoBurst;cnt++)
|
||||
{
|
||||
iBulletsSinceLastTracer++;
|
||||
if ((( iBulletsLeft - (cnt - 1) ) / iBulletsPerTracer) - ((iBulletsLeft - cnt) / iBulletsPerTracer) == 1)
|
||||
{
|
||||
iBulletsSinceLastTracer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
iTracersFired = ((iBulletsLeft+1) / iBulletsPerTracer) - (((iBulletsLeft+1) - (pSoldier->bDoBurst)) / iBulletsPerTracer);
|
||||
|
||||
if ( iTracersFired > 0 )
|
||||
{
|
||||
// Correct all autofire penalty so far
|
||||
iBonus = iPenalty;
|
||||
// Add Tracer Bump if previous bullet was a tracer
|
||||
//if (iBulletsSinceLastTracer == 0)
|
||||
iBonus += (gGameExternalOptions.iCTHBumpPerTracer * iTracersFired);
|
||||
// Calculate penalty since last tracer was fired
|
||||
iAutoPenaltySinceLastTracer = GetAutoPenalty(pInHand, gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE) * iBulletsSinceLastTracer;
|
||||
// Add penalty to bonus.
|
||||
iBonus -= iAutoPenaltySinceLastTracer;
|
||||
|
||||
iChance += iBonus;
|
||||
}
|
||||
}
|
||||
// HEADROCK HAM 3.5: Store the penalty
|
||||
sTotalAutofirePenalty = iPenalty;
|
||||
}
|
||||
|
||||
//ADB we need to calculate the distance visible and SoldierTo...LOSTests that we want to
|
||||
@@ -4046,7 +4003,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
// and in shock, they are harder to hit! This represents a target that's cowering as close
|
||||
// to the ground (and as close to any possible cover, like a small dune or a fold of earth
|
||||
// or anything like that).
|
||||
if ( gGameExternalOptions.iAimPenaltyPerTargetShock > 0 )
|
||||
if ( gGameExternalOptions.ubAimPenaltyPerTargetShock > 0 )
|
||||
{
|
||||
// HEADROCK HAM B2.1 : This value determines how much penalty the target's shock-value gives the shooter.
|
||||
// As of HAM B2.3: There's a maximum range at which 100% penalty is given.
|
||||
@@ -4058,7 +4015,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
UINT16 MIN_RANGE_FOR_FULL_COWER;
|
||||
UINT16 MAX_TARGET_COWERING_PENALTY;
|
||||
|
||||
AIM_PENALTY_PER_TARGET_SHOCK = gGameExternalOptions.iAimPenaltyPerTargetShock;
|
||||
AIM_PENALTY_PER_TARGET_SHOCK = gGameExternalOptions.ubAimPenaltyPerTargetShock;
|
||||
MIN_RANGE_FOR_FULL_COWER = gGameExternalOptions.usMinRangeForFullCoweringPenalty;
|
||||
MAX_TARGET_COWERING_PENALTY = gGameExternalOptions.usMaxTargetCoweringPenalty;
|
||||
|
||||
@@ -4201,6 +4158,88 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
*/
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.5: Moved this here for now.
|
||||
// HEADROCK HAM B2.5: One of every X bullets in a tracer magazine is a tracer round, which will
|
||||
// bump the CTH up by a certain amount.
|
||||
|
||||
if (AmmoTypes[(*pInHand)[0]->data.gun.ubGunAmmoType].tracerEffect == 1 && gGameExternalOptions.ubRealisticTracers > 0 )
|
||||
{
|
||||
UINT16 iBulletsLeft, iTracersFired, iBulletsPerTracer, iBulletsSinceLastTracer;
|
||||
UINT8 cnt;
|
||||
//UINT16 iAutoPenaltySinceLastTracer;
|
||||
iTracersFired = 0;
|
||||
iBulletsPerTracer = gGameExternalOptions.ubNumBulletsPerTracer;
|
||||
|
||||
// Calculate number of bullets left right before firing this bullet
|
||||
if (fCalculateCTHDuringGunfire)
|
||||
{
|
||||
iBulletsLeft = (*pInHand)[0]->data.gun.ubGunShotsLeft + (pSoldier->bDoBurst - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
iBulletsLeft = (*pInHand)[0]->data.gun.ubGunShotsLeft;
|
||||
}
|
||||
|
||||
iBulletsSinceLastTracer = 0;
|
||||
for (cnt=0;cnt<pSoldier->bDoBurst;cnt++)
|
||||
{
|
||||
iBulletsSinceLastTracer++;
|
||||
if ((( iBulletsLeft - (cnt - 1) ) / iBulletsPerTracer) - ((iBulletsLeft - cnt) / iBulletsPerTracer) == 1)
|
||||
{
|
||||
iBulletsSinceLastTracer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
iTracersFired = ((iBulletsLeft+1) / iBulletsPerTracer) - (((iBulletsLeft+1) - (pSoldier->bDoBurst)) / iBulletsPerTracer);
|
||||
|
||||
if ( iTracersFired > 0 )
|
||||
{
|
||||
// HEADROCK HAM 3.5: I'm going to revise this - my current system makes no sense at all. What was I
|
||||
// thinking?!
|
||||
|
||||
// Correct all autofire penalty so far
|
||||
//iBonus = iPenalty;
|
||||
|
||||
// Add Tracer Bump if previous bullet was a tracer
|
||||
//iBonus += (gGameExternalOptions.ubCTHBumpPerTracer * iTracersFired);
|
||||
iBonus = (gGameExternalOptions.ubCTHBumpPerTracer * iTracersFired);
|
||||
|
||||
// Calculate penalty since last tracer was fired
|
||||
UINT8 ubAutoPenaltySinceLastTracer = GetAutoPenalty(pInHand, gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE) * iBulletsSinceLastTracer;
|
||||
if ( HAS_SKILL_TRAIT( pSoldier, AUTO_WEAPS ) )
|
||||
{
|
||||
ubAutoPenaltySinceLastTracer /= 2 * NUM_SKILL_TRAITS( pSoldier, AUTO_WEAPS );
|
||||
}
|
||||
// Add penalty to bonus.
|
||||
//iBonus -= iAutoPenaltySinceLastTracer;
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// HEADROCK HAM 3.5: Limit maximum bonus by range.
|
||||
|
||||
INT16 sBaseChance = iChance + sTotalAutofirePenalty;
|
||||
|
||||
// We don't want to enforce a limit unless the tracers have actually put us over the original CtH.
|
||||
if (sBaseChance <= iChance+iBonus) // Base_Chance without AutoPen, less or equal to Current_Chance plus tracer bumps
|
||||
{
|
||||
// store lowest: Chance+Tracer bumps, or Range-enforced limit
|
||||
INT16 sChanceLimit = __min(iChance+iBonus, sBaseChance+(((iRange-100) / CELL_X_SIZE) * gGameExternalOptions.ubRangeDifficultyAimingWithTracers));
|
||||
// store highest: Chance Delta or base CtH
|
||||
//sChanceDelta = __max(sChanceDelta, sBaseChance);
|
||||
|
||||
// iBonus is the distance between the enforced limit (if any) and the current chance with all penalties so far.
|
||||
// But it can't be negative, 'cause it's a bonus.
|
||||
iBonus = __max(0,sChanceLimit - iChance);
|
||||
// Add autopenalty since last tracer
|
||||
if (iBulletsSinceLastTracer < iBulletsPerTracer)
|
||||
{
|
||||
iBonus -= ubAutoPenaltySinceLastTracer;
|
||||
}
|
||||
|
||||
}
|
||||
iChance += iBonus;
|
||||
}
|
||||
}
|
||||
|
||||
// adjust for roof/not on roof
|
||||
if ( pSoldier->pathing.bLevel == 0 )
|
||||
{
|
||||
@@ -4407,7 +4446,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
// bump the minimum back to 1, where X = the Divisor value. So a divisor value of 50 gives a 1/50
|
||||
// chance of getting some actual chance to hit despite the 0 minimum. The overall total would then
|
||||
// be an effective CTH of only 1/5000 (50 chances to get a 1 out of 100 CTH, hehehe)
|
||||
if (iChance <= gGameExternalOptions.iMinimumCTH)
|
||||
if (iChance <= gGameExternalOptions.ubMinimumCTH)
|
||||
{
|
||||
if ( TANK( pSoldier ) )
|
||||
{
|
||||
@@ -4416,10 +4455,10 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
}
|
||||
else
|
||||
{
|
||||
iChance = gGameExternalOptions.iMinimumCTH;
|
||||
if ( gGameExternalOptions.iMinimumCTH == 0 )
|
||||
iChance = gGameExternalOptions.ubMinimumCTH;
|
||||
if ( gGameExternalOptions.ubMinimumCTH == 0 )
|
||||
{
|
||||
if ( PreRandom( gGameExternalOptions.iMinimumCTHDivisor ) == (gGameExternalOptions.iMinimumCTHDivisor - 1) )
|
||||
if ( PreRandom( gGameExternalOptions.usMinimumCTHDivisor ) == (gGameExternalOptions.usMinimumCTHDivisor - 1) )
|
||||
{
|
||||
iChance = 1;
|
||||
}
|
||||
@@ -4431,8 +4470,8 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
// HEADROCK (HAM): Externalized maximum to JA2_OPTIONS.INI
|
||||
// if (iChance > MAXCHANCETOHIT)
|
||||
// iChance = MAXCHANCETOHIT;
|
||||
if (iChance > gGameExternalOptions.iMaximumCTH)
|
||||
iChance = gGameExternalOptions.iMaximumCTH;
|
||||
if (iChance > gGameExternalOptions.ubMaximumCTH)
|
||||
iChance = gGameExternalOptions.ubMaximumCTH;
|
||||
}
|
||||
|
||||
// NumMessage("ChanceToHit = ",chance);
|
||||
@@ -4778,7 +4817,9 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
{
|
||||
case AIM_SHOT_HEAD:
|
||||
// is the blow deadly enough for an instant kill?
|
||||
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 ))
|
||||
// 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 )
|
||||
{
|
||||
if (iImpactForCrits > MIN_DAMAGE_FOR_INSTANT_KILL && iImpactForCrits < pTarget->stats.bLife)
|
||||
{
|
||||
@@ -4825,7 +4866,9 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
// normal damage to torso
|
||||
// is the blow deadly enough for an instant kill?
|
||||
// since this value is much lower than the others, it only applies at short range...
|
||||
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 ))
|
||||
// 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 )
|
||||
{
|
||||
if (iImpact > MIN_DAMAGE_FOR_INSTANT_KILL && iImpact < pTarget->stats.bLife)
|
||||
{
|
||||
@@ -4919,6 +4962,17 @@ INT32 BulletImpact( SOLDIERTYPE *pFirer, SOLDIERTYPE * pTarget, UINT8 ubHitLocat
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_HEAD_HIT], pTarget->name );
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.2: Critical headshots may now cause blindness, based on shot damage.
|
||||
if (gGameExternalOptions.ubChanceBlindedByHeadshot)
|
||||
{
|
||||
if (PreRandom(gGameExternalOptions.ubChanceBlindedByHeadshot) == 0)
|
||||
{
|
||||
if (pTarget->bBlindedCounter < iImpact / 10 )
|
||||
pTarget->bBlindedCounter = iImpact / 10;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case AIM_SHOT_TORSO:
|
||||
if (PreRandom( 1 ) == 0 && !(pTarget->flags.uiStatusFlags & SOLDIER_MONSTER) )
|
||||
@@ -5489,17 +5543,17 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi
|
||||
// MAKE SURE CHANCE TO HIT IS WITHIN DEFINED LIMITS
|
||||
// HEADROCK: I urinate on your Defined Limits! Power Rangers, Externalize!
|
||||
// Disclaimer: No offense meant, all in good fun ;)
|
||||
if (iChance < gGameExternalOptions.iMinimumCTH)
|
||||
if (iChance < gGameExternalOptions.ubMinimumCTH)
|
||||
{
|
||||
iChance = gGameExternalOptions.iMinimumCTH;
|
||||
iChance = gGameExternalOptions.ubMinimumCTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
// HEADROCK (HAM): Externalized maximum to JA2_OPTIONS.INI
|
||||
//if (iChance > MAXCHANCETOHIT)
|
||||
// iChance = MAXCHANCETOHIT;
|
||||
if (iChance > gGameExternalOptions.iMaximumCTH)
|
||||
iChance = gGameExternalOptions.iMaximumCTH;
|
||||
if (iChance > gGameExternalOptions.ubMaximumCTH)
|
||||
iChance = gGameExternalOptions.ubMaximumCTH;
|
||||
}
|
||||
|
||||
//NumMessage("ChanceToStab = ",chance);
|
||||
@@ -5955,17 +6009,23 @@ UINT32 CalcThrownChanceToHit(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTi
|
||||
// reduce iChance to hit DIRECTLY by the item's working condition
|
||||
iChance = (iChance * WEAPON_STATUS_MOD(pSoldier->inv[HANDPOS][0]->data.objectStatus)) / 100;
|
||||
|
||||
// HEADROCK HAM 3.2: External divisor for CTH with mortars, now that they are more prevalent in the battlefield.
|
||||
if ( Item[ usHandItem ].mortar )
|
||||
{
|
||||
iChance = iChance / gGameExternalOptions.ubMortarCTHDivisor;
|
||||
}
|
||||
|
||||
// What's with all these defined limits? Let's think out of the box for a minute, shall we?
|
||||
// HEADROCK (HAM): externalized, effective immediately.
|
||||
if (iChance < gGameExternalOptions.iMinimumCTH)
|
||||
iChance = gGameExternalOptions.iMinimumCTH;
|
||||
if (iChance < gGameExternalOptions.ubMinimumCTH)
|
||||
iChance = gGameExternalOptions.ubMinimumCTH;
|
||||
else
|
||||
{
|
||||
// HEADROCK (HAM): Externalized maximum to JA2_OPTIONS.INI
|
||||
//if (iChance > MAXCHANCETOHIT)
|
||||
// iChance = MAXCHANCETOHIT;
|
||||
if (iChance > gGameExternalOptions.iMaximumCTH)
|
||||
iChance = gGameExternalOptions.iMaximumCTH;
|
||||
if (iChance > gGameExternalOptions.ubMaximumCTH)
|
||||
iChance = gGameExternalOptions.ubMaximumCTH;
|
||||
}
|
||||
|
||||
|
||||
@@ -6163,7 +6223,7 @@ UINT8 GetAutofireShotsPerFiveAPs( OBJECTTYPE *pObj )
|
||||
// HEADROCK HAM B2.6: Added overall modifier
|
||||
if (Weapon[ pObj->usItem ].bAutofireShotsPerFiveAP > 0)
|
||||
{
|
||||
return __max((Weapon[ pObj->usItem ].bAutofireShotsPerFiveAP + gGameExternalOptions.iAutofireBulletsPer5APModifier), 0);
|
||||
return __max((Weapon[ pObj->usItem ].bAutofireShotsPerFiveAP + gGameExternalOptions.bAutofireBulletsPer5APModifier), 0);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
@@ -6176,6 +6236,13 @@ UINT16 GetMagSize( OBJECTTYPE *pObj )
|
||||
return Weapon[ pObj->usItem ].ubMagSize + GetMagSizeBonus(pObj);
|
||||
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.3: Function to get a weapon's current ammotype.
|
||||
UINT8 GetAmmoType( OBJECTTYPE *pObj )
|
||||
{
|
||||
return (*pObj)[0]->data.gun.ubGunAmmoType;
|
||||
}
|
||||
|
||||
bool WeaponReady(SOLDIERTYPE * pSoldier)
|
||||
{
|
||||
#ifdef ROBOT_ALWAYS_READY
|
||||
@@ -6198,9 +6265,139 @@ INT8 GetAPsToReload( OBJECTTYPE *pObj )
|
||||
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.4: Estimates the number of bullets left in the gun. For use during combat.
|
||||
|
||||
CHAR16 gBulletCount[10]; // This is a global containing the bullet count string
|
||||
void EstimateBulletsLeft( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj )
|
||||
{
|
||||
|
||||
UINT16 usExpLevel;
|
||||
UINT16 usDexterity;
|
||||
UINT16 usWisdom;
|
||||
UINT8 ubMagSize = Weapon[pObj->usItem].ubMagSize;
|
||||
UINT16 usRealBulletCount = (*pObj)[0]->data.gun.ubGunShotsLeft;
|
||||
UINT16 i = 0;
|
||||
BOOLEAN fPsycho = FALSE;
|
||||
INT16 sEffectiveSkill;
|
||||
INT8 bDeviation = 0;
|
||||
|
||||
// HEADROCK HAM 3.5: Bugfix, failsafe
|
||||
if ( pSoldier == NULL )
|
||||
{
|
||||
// No soldier... Return true count.
|
||||
swprintf(gBulletCount, L"%d", usRealBulletCount);
|
||||
return;
|
||||
}
|
||||
|
||||
usExpLevel = EffectiveExpLevel(pSoldier);
|
||||
usDexterity = EffectiveDexterity(pSoldier);
|
||||
usWisdom = EffectiveWisdom(pSoldier);
|
||||
|
||||
if ( gGameExternalOptions.usBulletHideIntensity <= 0 )
|
||||
{
|
||||
// Feature is disabled. Print the real bullet count.
|
||||
swprintf(gBulletCount, L"%d", usRealBulletCount);
|
||||
return;
|
||||
}
|
||||
|
||||
// Is this Soldier a psycho?
|
||||
if ( pSoldier->ubProfile != NO_PROFILE && gMercProfiles[ pSoldier->ubProfile ].bPersonalityTrait == PSYCHO )
|
||||
{
|
||||
fPsycho = TRUE;
|
||||
}
|
||||
|
||||
// High EXP Level, Wisdom and Dexterity required for any estimation to be possible.
|
||||
// When Experience goes up, the required WIS+DEX goes down.
|
||||
// At ExpLevel 1 -> WIS+DEX must be > 180. A high requirement!
|
||||
// At ExpLevel 2 -> WIS+DEX must be > 160.
|
||||
// ...
|
||||
// At ExpLevel 5 -> WIS+DEX must be > 100. Most characters have already attained estimation ability by now.
|
||||
// At ExpLevel 10 -> WIS+DEX must be > 0, which is always.
|
||||
if ( (usWisdom + usDexterity) < (200 - (usExpLevel * 20)) )
|
||||
{
|
||||
// Soldier is not skilled enough to know how many bullets are left in the gun. Print a "??" indicating that
|
||||
// the real bullet count may be anywhere between empty and full.
|
||||
swprintf(gBulletCount, L"%s", L"??");
|
||||
return;
|
||||
}
|
||||
else // Soldier good enough for at least a rough estimate.
|
||||
{
|
||||
// HEADROCK HAM 3.5: Moved this here. If the character fails the above requirement, he shouldn't even know if the
|
||||
// gun is empty or full.
|
||||
//-------------------------
|
||||
// If the magazine is empty or full, he knows it automatically.
|
||||
if (usRealBulletCount == ubMagSize)
|
||||
{
|
||||
// Magazine is fresh. Let the soldier know this.
|
||||
swprintf(gBulletCount, L"%d", usRealBulletCount);
|
||||
return;
|
||||
}
|
||||
if (usRealBulletCount == 0)
|
||||
{
|
||||
// Magazine is empty, so it will also show as empty.
|
||||
swprintf(gBulletCount, L"%d", usRealBulletCount);
|
||||
return;
|
||||
}
|
||||
//-------------------------
|
||||
|
||||
// Let's see by how much we've beaten the requirement!
|
||||
sEffectiveSkill = ( (usWisdom + usDexterity) - (200 - (usExpLevel * 20)) ) / 2;
|
||||
}
|
||||
// So from now on we've got the sEffectiveSkill value, which can go from 0 to 100
|
||||
// This value represents getting better in all three stats (WIS,DEX,EXP), because as
|
||||
// they go up the result of the calculation above also goes up. Having a particularly high
|
||||
// value in any of the three stats, in fact, reduces the need to have high values in others.
|
||||
//
|
||||
// The higher your EXP level, the less WIS+DEX you need for an accurate estimate, so even
|
||||
// inept characters will eventually be able to make a fair estimate, provided the EXP
|
||||
// level goes high enough.
|
||||
//
|
||||
// On the other hand, WIS and DEX work together. In fact, it is the average of these
|
||||
// skills that determines how soon you can start estimating, and how good your estimation gets
|
||||
// as you gain levels. So while one high skill can bring better estimates sooner, it requires
|
||||
// both skills to be improved for a really good estimate.
|
||||
//
|
||||
// The range of sEffectiveSkill is 0 to 100
|
||||
//``````````````````````````````````````````
|
||||
|
||||
// Psychos are eligible for an estimate just the same as any other character. But the trait reduces
|
||||
// effective skill by 10, so It'll take them longer before they can get a good estimate.
|
||||
sEffectiveSkill -= (fPsycho * (10));
|
||||
|
||||
sEffectiveSkill = __max(0, sEffectiveSkill);
|
||||
sEffectiveSkill = __min(100, sEffectiveSkill);
|
||||
|
||||
// Now, we invert the effective skill
|
||||
bDeviation = 100-sEffectiveSkill; // range is still 0-100, but lower is better
|
||||
// Use this as a percentage, and figure out the deviation based on magazine size and current bullet. The nearer
|
||||
// you get to the bottom of a magazine, the harder it is to accurately estimate how many bullets are in there.
|
||||
bDeviation = ((ubMagSize - usRealBulletCount) * (bDeviation * bDeviation)) / 10000;
|
||||
|
||||
// Add externalized difficulty modifier
|
||||
bDeviation = (bDeviation * gGameExternalOptions.usBulletHideIntensity) / 100;
|
||||
|
||||
// If the deviation surpasses the character's EXP level, then he/she is not able to know how many bullets are
|
||||
// left in the gun, but can still give a rough estimate. There are currently three estimate stages - High, Mid,
|
||||
// and Low.
|
||||
if (bDeviation > usExpLevel)
|
||||
{
|
||||
if (usRealBulletCount >= (ubMagSize*2)/3)
|
||||
{
|
||||
swprintf(gBulletCount, L"%s", L"?H");
|
||||
}
|
||||
else if (usRealBulletCount < (ubMagSize*2)/3 && usRealBulletCount >= ubMagSize/3)
|
||||
{
|
||||
swprintf(gBulletCount, L"%s", L"?M");
|
||||
}
|
||||
else if (usRealBulletCount < ubMagSize/3)
|
||||
{
|
||||
swprintf(gBulletCount, L"%s", L"?L");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Default - return true count.
|
||||
swprintf(gBulletCount, L"%d", usRealBulletCount);
|
||||
return;
|
||||
|
||||
}
|
||||
@@ -391,9 +391,14 @@ UINT8 GetBurstPenalty( OBJECTTYPE *pObj, BOOLEAN fProneStance = FALSE );
|
||||
UINT8 GetAutoPenalty( OBJECTTYPE *pObj, BOOLEAN fProneStance = FALSE );
|
||||
UINT8 GetShotsPerBurst( OBJECTTYPE *pObj );
|
||||
UINT16 GetMagSize( OBJECTTYPE *pObj );
|
||||
UINT8 GetAmmoType( OBJECTTYPE *pObj );
|
||||
bool WeaponReady(SOLDIERTYPE * pSoldier);
|
||||
INT8 GetAPsToReload( OBJECTTYPE *pObj );
|
||||
|
||||
// HEADROCK HAM 3.4: Estimate bullets left in gun. Returns an "errorcode" telling the calling function if the check
|
||||
// was successful and to what degree.
|
||||
void EstimateBulletsLeft( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObj );
|
||||
extern CHAR16 gBulletCount[10];
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -125,6 +125,23 @@ typedef PARSE_STAGE;
|
||||
#define LAPTOPFLORISTLOCATIONFILENAME "Laptop\\FloristPositions.xml"
|
||||
#define LAPTOPFUNERALLOCATIONFILENAME "Laptop\\FuneralPositions.xml"
|
||||
|
||||
// HEADROCK HAM 3.4: Facility Locations [2009-05-19]
|
||||
#define SECTORFACILITIESFILENAME "Map\\Facilities.xml"
|
||||
// HEADROCK HAM 3.4: Dynamic Roaming Restrictions [2009-05-19]
|
||||
#define DYNAMICROAMINGFILENAME "Map\\DynamicRestrictions.xml"
|
||||
// HEADROCK HAM 3.5: Facility Types [2009-06-14]
|
||||
#define FACILITYTYPESFILENAME "Map\\FacilityTypes.xml"
|
||||
// HEADROCK HAM 3.6: Sector Names [2009-07-27]
|
||||
#define SECTORNAMESFILENAME "Map\\SectorNames.xml"
|
||||
// HEADROCK PROFEX: Merc Profiles [2009-07-27]
|
||||
#define MERCPROFILESFILENAME "MercProfiles.xml"
|
||||
// HEADROCK PROFEX: Merc Opinions [2009-07-27]
|
||||
#define MERCOPINIONSFILENAME "MercOpinions.xml"
|
||||
// HEADROCK HAM 3.6: Bloodcat Placements [2009-07-31]
|
||||
#define BLOODCATPLACEMENTSFILENAME "Map\\BloodcatPlacements.xml"
|
||||
// HEADROCK HAM 3.6: Uniform Colors [2009-09-29]
|
||||
#define UNIFORMCOLORSFILENAME "Army\\UniformColors.xml"
|
||||
|
||||
extern BOOLEAN ReadInItemStats(STR fileName, BOOLEAN localizedVersion);
|
||||
extern BOOLEAN WriteItemStats();
|
||||
|
||||
@@ -260,4 +277,29 @@ extern BOOLEAN ReadInFloristLocations(STR fileName);
|
||||
|
||||
//Gotthard: Laptop Funeral Locations
|
||||
extern BOOLEAN ReadInFuneralLocations(STR fileName);
|
||||
|
||||
// HEADROCK HAM 3.4: Sector Facility Locations
|
||||
extern BOOLEAN ReadInSectorFacilities(STR fileName);
|
||||
|
||||
// HEADROCK HAM 3.4: Dynamic Roaming Restrictions
|
||||
extern BOOLEAN ReadInDynamicRoamingRestrictions(STR fileName);
|
||||
|
||||
// HEADROCK HAM 3.5: Facility Types and bonuses
|
||||
extern BOOLEAN ReadInFacilityTypes(STR fileName);
|
||||
|
||||
// HEADROCK HAM 3.6: Customized Sector Names
|
||||
extern BOOLEAN ReadInSectorNames(STR fileName);
|
||||
|
||||
// HEADROCK PROFEX: Merc Profiles
|
||||
extern BOOLEAN ReadInMercProfiles(STR fileName);
|
||||
|
||||
// HEADROCK PROFEX: Merc Opinions
|
||||
extern BOOLEAN ReadInMercOpinions(STR fileName);
|
||||
|
||||
// HEADROCK HAM 3.6: Customized Bloodcat Placements
|
||||
extern BOOLEAN ReadInBloodcatPlacements(STR fileName);
|
||||
|
||||
// HEADROCK HAM 3.6: Customized Uniform Colors
|
||||
extern BOOLEAN ReadInUniforms(STR fileName);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,899 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// HEADROCK PROFEX: PROFile EXternalization
|
||||
//
|
||||
// This file handles all reading from Merc Profiles.XML. It offers an external
|
||||
// alternative to PROEDIT. Values that have no current use in the game were
|
||||
// EXCLUDED. If you wish to add them simply follow the example set here. You
|
||||
// can read MERCPROFILESTRUCT in the file "soldier profile type.h" to see
|
||||
// all profile data. Add the ones you want to externalize to TEMPPROFILESTRUCT
|
||||
// in "Soldier Profile.h", and then add the appropriate lines where needed,
|
||||
// in this file, following my example.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Tactical All.h"
|
||||
#else
|
||||
#include "sgp.h"
|
||||
#include "Debug Control.h"
|
||||
#include "expat.h"
|
||||
#include "gamesettings.h"
|
||||
#include "XML.h"
|
||||
#include "Soldier Profile.h"
|
||||
#endif
|
||||
|
||||
//#define MAX_PROFILE_NAME_LENGTH 30
|
||||
|
||||
struct
|
||||
{
|
||||
PARSE_STAGE curElement;
|
||||
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
|
||||
TEMPPROFILETYPE curProfile;
|
||||
UINT32 maxArraySize;
|
||||
UINT32 curIndex;
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
}
|
||||
typedef profileParseData;
|
||||
|
||||
//TEMPPROFILETYPE tempProfiles[NUM_PROFILES+1];
|
||||
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
opinionStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
profileParseData * pData = (profileParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
if(strcmp(name, "MERCOPINIONS") == 0 && pData->curElement == ELEMENT_NONE)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(strcmp(name, "OPINION") == 0 && pData->curElement == ELEMENT_LIST)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
//DebugMsg(TOPIC_JA2, DBG_LEVEL_3,"MergeStartElementHandle: setting memory for curMerge");
|
||||
|
||||
memset(&pData->curProfile,0,sizeof(TEMPPROFILETYPE));
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
|
||||
//pData->curIndex++;
|
||||
}
|
||||
else if(pData->curElement == ELEMENT &&
|
||||
(strcmp(name, "zNickname") == 0 ||
|
||||
strcmp(name, "uiIndex") == 0 ||
|
||||
strcmp(name, "Opinion0") == 0 ||
|
||||
strcmp(name, "Opinion1") == 0 ||
|
||||
strcmp(name, "Opinion2") == 0 ||
|
||||
strcmp(name, "Opinion3") == 0 ||
|
||||
strcmp(name, "Opinion4") == 0 ||
|
||||
strcmp(name, "Opinion5") == 0 ||
|
||||
strcmp(name, "Opinion6") == 0 ||
|
||||
strcmp(name, "Opinion7") == 0 ||
|
||||
strcmp(name, "Opinion8") == 0 ||
|
||||
strcmp(name, "Opinion9") == 0 ||
|
||||
strcmp(name, "Opinion10") == 0 ||
|
||||
strcmp(name, "Opinion11") == 0 ||
|
||||
strcmp(name, "Opinion12") == 0 ||
|
||||
strcmp(name, "Opinion13") == 0 ||
|
||||
strcmp(name, "Opinion14") == 0 ||
|
||||
strcmp(name, "Opinion15") == 0 ||
|
||||
strcmp(name, "Opinion16") == 0 ||
|
||||
strcmp(name, "Opinion17") == 0 ||
|
||||
strcmp(name, "Opinion18") == 0 ||
|
||||
strcmp(name, "Opinion19") == 0 ||
|
||||
strcmp(name, "Opinion20") == 0 ||
|
||||
strcmp(name, "Opinion21") == 0 ||
|
||||
strcmp(name, "Opinion22") == 0 ||
|
||||
strcmp(name, "Opinion23") == 0 ||
|
||||
strcmp(name, "Opinion24") == 0 ||
|
||||
strcmp(name, "Opinion25") == 0 ||
|
||||
strcmp(name, "Opinion26") == 0 ||
|
||||
strcmp(name, "Opinion27") == 0 ||
|
||||
strcmp(name, "Opinion28") == 0 ||
|
||||
strcmp(name, "Opinion29") == 0 ||
|
||||
strcmp(name, "Opinion30") == 0 ||
|
||||
strcmp(name, "Opinion31") == 0 ||
|
||||
strcmp(name, "Opinion32") == 0 ||
|
||||
strcmp(name, "Opinion33") == 0 ||
|
||||
strcmp(name, "Opinion34") == 0 ||
|
||||
strcmp(name, "Opinion35") == 0 ||
|
||||
strcmp(name, "Opinion36") == 0 ||
|
||||
strcmp(name, "Opinion37") == 0 ||
|
||||
strcmp(name, "Opinion38") == 0 ||
|
||||
strcmp(name, "Opinion39") == 0 ||
|
||||
strcmp(name, "Opinion40") == 0 ||
|
||||
strcmp(name, "Opinion41") == 0 ||
|
||||
strcmp(name, "Opinion42") == 0 ||
|
||||
strcmp(name, "Opinion43") == 0 ||
|
||||
strcmp(name, "Opinion44") == 0 ||
|
||||
strcmp(name, "Opinion45") == 0 ||
|
||||
strcmp(name, "Opinion46") == 0 ||
|
||||
strcmp(name, "Opinion47") == 0 ||
|
||||
strcmp(name, "Opinion48") == 0 ||
|
||||
strcmp(name, "Opinion49") == 0 ||
|
||||
strcmp(name, "Opinion50") == 0 ||
|
||||
strcmp(name, "Opinion51") == 0 ||
|
||||
strcmp(name, "Opinion52") == 0 ||
|
||||
strcmp(name, "Opinion53") == 0 ||
|
||||
strcmp(name, "Opinion54") == 0 ||
|
||||
strcmp(name, "Opinion55") == 0 ||
|
||||
strcmp(name, "Opinion56") == 0 ||
|
||||
strcmp(name, "Opinion57") == 0 ||
|
||||
strcmp(name, "Opinion58") == 0 ||
|
||||
strcmp(name, "Opinion59") == 0 ||
|
||||
strcmp(name, "Opinion60") == 0 ||
|
||||
strcmp(name, "Opinion61") == 0 ||
|
||||
strcmp(name, "Opinion62") == 0 ||
|
||||
strcmp(name, "Opinion63") == 0 ||
|
||||
strcmp(name, "Opinion64") == 0 ||
|
||||
strcmp(name, "Opinion65") == 0 ||
|
||||
strcmp(name, "Opinion66") == 0 ||
|
||||
strcmp(name, "Opinion67") == 0 ||
|
||||
strcmp(name, "Opinion68") == 0 ||
|
||||
strcmp(name, "Opinion69") == 0 ||
|
||||
strcmp(name, "Opinion70") == 0 ||
|
||||
strcmp(name, "Opinion71") == 0 ||
|
||||
strcmp(name, "Opinion72") == 0 ||
|
||||
strcmp(name, "Opinion73") == 0 ||
|
||||
strcmp(name, "Opinion74") == 0
|
||||
))
|
||||
{
|
||||
pData->curElement = ELEMENT_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
opinionCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
profileParseData * pData = (profileParseData *)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
|
||||
opinionEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
profileParseData * pData = (profileParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
||||
{
|
||||
if(strcmp(name, "MERCOPINIONS") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_NONE;
|
||||
}
|
||||
else if(strcmp(name, "OPINION") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
if(pData->curIndex < pData->maxArraySize)
|
||||
{
|
||||
|
||||
// Write data into a temporary array that holds profiles. We will later copy data from that
|
||||
// temp array into the REAL profile array, one item at a time, replacing PROF.DAT data.
|
||||
memcpy( &(tempProfiles[pData->curIndex].bMercOpinion), &(pData->curProfile.bMercOpinion), 75 * sizeof(INT8) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
else if(strcmp(name, "zNickname") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
// Just a formality
|
||||
}
|
||||
|
||||
else if(strcmp(name, "uiIndex") == 0)
|
||||
{
|
||||
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
// Sets new index for writing.
|
||||
pData->curIndex = (UINT32) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion0") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[0] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion1") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[1] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion2") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[2] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion3") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[3] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion4") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[4] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion5") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[5] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion6") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[6] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion7") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[7] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion8") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[8] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion9") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[9] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion10") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[10] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion11") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[11] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion12") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[12] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion13") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[13] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion14") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[14] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion15") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[15] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion16") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[16] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion17") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[17] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion18") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[18] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion19") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[19] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion20") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[20] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion21") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[21] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion22") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[22] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion23") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[23] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion24") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[24] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion25") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[25] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion26") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[26] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion27") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[27] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion28") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[28] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion29") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[29] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion30") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[30] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion31") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[31] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion32") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[32] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion33") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[33] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion34") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[34] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion35") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[35] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion36") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[36] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion37") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[37] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion38") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[38] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion39") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[39] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion40") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[40] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion41") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[41] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion42") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[42] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion43") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[43] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion44") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[44] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion45") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[45] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion46") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[46] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion47") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[47] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion48") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[48] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion49") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[49] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion50") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[50] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion51") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[51] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion52") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[52] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion53") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[53] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion54") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[54] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion55") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[55] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion56") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[56] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion57") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[57] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion58") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[58] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion59") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[59] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion60") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[60] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion61") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[61] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion62") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[62] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion63") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[63] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion64") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[64] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion65") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[65] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion66") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[66] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion67") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[67] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion68") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[68] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion69") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[69] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion70") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[70] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion71") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[71] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion72") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[72] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion73") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[73] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Opinion74") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
pData->curProfile.bMercOpinion[74] = (INT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
BOOLEAN ReadInMercOpinions(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
profileParseData pData;
|
||||
|
||||
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading MercOpinions.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, opinionStartElementHandle, opinionEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, opinionCharacterDataHandle);
|
||||
|
||||
|
||||
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 MercProfiles.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
|
||||
LiveMessage(errorBuf);
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
|
||||
|
||||
XML_ParserFree(parser);
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
BOOLEAN WriteMercOpinions()
|
||||
{
|
||||
HWFILE hFile;
|
||||
|
||||
//Debug code; make sure that what we got from the file is the same as what's there
|
||||
// Open a new file
|
||||
hFile = FileOpen( "TABLEDATA\\MercOpinions out.xml", FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE );
|
||||
if ( !hFile )
|
||||
return( FALSE );
|
||||
|
||||
{
|
||||
UINT32 cnt;
|
||||
|
||||
FilePrintf(hFile,"<MERCOPINIONS>\r\n");
|
||||
for(cnt = 0;cnt < NUM_PROFILES ;cnt++)
|
||||
{
|
||||
|
||||
FilePrintf(hFile,"\t<OPINION>\r\n");
|
||||
|
||||
FilePrintf(hFile,"\t\t<uiIndex>%d</uiIndex>\r\n", cnt);
|
||||
|
||||
//////////////////////////////
|
||||
// Write Character's Nickname
|
||||
|
||||
FilePrintf(hFile,"\t\t<zNickname>");
|
||||
|
||||
STR16 szRemainder = gMercProfiles[cnt].zNickname; //the remaining string to be output (for making valid XML)
|
||||
|
||||
while(szRemainder[0] != '\0')
|
||||
{
|
||||
//UINT32 uiCharLoc = wcscspn(szRemainder,L"&<>\'\"\0");
|
||||
UINT32 uiCharLoc = wcscspn(szRemainder,L"&<>\0");
|
||||
CHAR16 invChar = szRemainder[uiCharLoc];
|
||||
|
||||
if(uiCharLoc)
|
||||
{
|
||||
szRemainder[uiCharLoc] = '\0';
|
||||
FilePrintf(hFile,"%S",szRemainder);
|
||||
szRemainder[uiCharLoc] = invChar;
|
||||
}
|
||||
|
||||
szRemainder += uiCharLoc;
|
||||
|
||||
switch(invChar)
|
||||
{
|
||||
case '&':
|
||||
FilePrintf(hFile,"&");
|
||||
szRemainder++;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
FilePrintf(hFile,"<");
|
||||
szRemainder++;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
FilePrintf(hFile,">");
|
||||
szRemainder++;
|
||||
break;
|
||||
|
||||
//case '\'':
|
||||
// FilePrintf(hFile,"'");
|
||||
// szRemainder++;
|
||||
//break;
|
||||
|
||||
//case '\"':
|
||||
// FilePrintf(hFile,""");
|
||||
// szRemainder++;
|
||||
//break;
|
||||
}
|
||||
}
|
||||
|
||||
FilePrintf(hFile,"</zNickname>\r\n");
|
||||
|
||||
UINT8 cnt_b = 0;
|
||||
for (cnt_b = 0; cnt_b < 75; cnt_b++)
|
||||
{
|
||||
FilePrintf(hFile,"\t\t<Opinion%d>%d</Opinion%d>\r\n", cnt_b, gMercProfiles[ cnt ].bMercOpinion[cnt_b], cnt_b);
|
||||
}
|
||||
|
||||
|
||||
FilePrintf(hFile,"\t</OPINION>\r\n");
|
||||
}
|
||||
FilePrintf(hFile,"</MERCOPINIONS>\r\n");
|
||||
}
|
||||
FileClose( hFile );
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -396,4 +396,4 @@ int FindSpreadPatternIndex( const STR strName )
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
}
|
||||
@@ -474,7 +474,7 @@ void AddMissileTrail( BULLET *pBullet, FIXEDPT qCurrX, FIXEDPT qCurrY, FIXEDPT q
|
||||
// The condition now reads that flag and creates a lightshow only for tracer bullets. This flag is only
|
||||
// used if the new Tracer System is on.
|
||||
//if (fTracer == TRUE)
|
||||
if ((gGameExternalOptions.iRealisticTracers > 0 && gGameExternalOptions.iNumBulletsPerTracer > 0 && pBullet->fTracer == TRUE) || (gGameExternalOptions.iRealisticTracers == 0 && fTracer == TRUE))
|
||||
if ((gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && pBullet->fTracer == TRUE) || (gGameExternalOptions.ubRealisticTracers == 0 && fTracer == TRUE))
|
||||
{
|
||||
if ( pBullet->iLoop < 5 )
|
||||
{
|
||||
@@ -525,7 +525,7 @@ void AddMissileTrail( BULLET *pBullet, FIXEDPT qCurrX, FIXEDPT qCurrY, FIXEDPT q
|
||||
// The condition now reads that flag and creates a lightshow only for tracer bullets. This flag is only
|
||||
// used if the new Tracer System is on.
|
||||
// else if (fTracer == TRUE)
|
||||
else if ((gGameExternalOptions.iRealisticTracers > 0 && gGameExternalOptions.iNumBulletsPerTracer > 0 && pBullet->fTracer == TRUE) || (gGameExternalOptions.iRealisticTracers == 0 && fTracer == TRUE))
|
||||
else if ((gGameExternalOptions.ubRealisticTracers > 0 && gGameExternalOptions.ubNumBulletsPerTracer > 0 && pBullet->fTracer == TRUE) || (gGameExternalOptions.ubRealisticTracers == 0 && fTracer == TRUE))
|
||||
{
|
||||
INT16 sXPos, sYPos;
|
||||
|
||||
|
||||
+63
-17
@@ -58,7 +58,8 @@
|
||||
#define WE_SEE_WHAT_MILITIA_SEES_AND_VICE_VERSA
|
||||
|
||||
extern void SetSoldierAniSpeed( SOLDIERTYPE *pSoldier );
|
||||
void MakeBloodcatsHostile( void );
|
||||
// HEADROCK HAM 3.6: Moved to header
|
||||
//void MakeBloodcatsHostile( void );
|
||||
|
||||
void OurNoise( UINT8 ubNoiseMaker, INT16 sGridNo, INT8 bLevel, UINT8 ubTerrType, UINT8 ubVolume, UINT8 ubNoiseType );
|
||||
void TheirNoise(UINT8 ubNoiseMaker, INT16 sGridNo, INT8 bLevel, UINT8 ubTerrType, UINT8 ubVolume, UINT8 ubNoiseType );
|
||||
@@ -490,7 +491,9 @@ void HandleBestSightingPositionInRealtime( void )
|
||||
// get rid of the item under cursor (we gotta react FAST)
|
||||
CancelItemPointer();
|
||||
// select (and center screen on) the merc who saw the enemy
|
||||
if (gusSelectedSoldier != (UINT16)MercPtrs[gubBestToMakeSighting[ 0 ]]->ubID)
|
||||
// HEADROCK HAM 3.6: A much-requested toggle.
|
||||
if (gusSelectedSoldier != (UINT16)MercPtrs[gubBestToMakeSighting[ 0 ]]->ubID &&
|
||||
!gGameExternalOptions.fNoAutoFocusChangeInRealtimeSneak)
|
||||
SelectSoldier (MercPtrs[gubBestToMakeSighting[ 0 ]]->ubID, false, true);
|
||||
// if not quiet, emit a message warning the player
|
||||
if (!gGameExternalOptions.fQuietRealTimeSneak)
|
||||
@@ -1251,6 +1254,19 @@ INT16 DistanceVisible( SOLDIERTYPE *pSoldier, INT8 bFacingDir, INT8 bSubjectDir,
|
||||
if (!sideViewLimit)
|
||||
{
|
||||
sDistVisible += sDistVisible * GetTotalVisionRangeBonus(pSoldier, bLightLevel) / 100;
|
||||
|
||||
// HEADROCK HAM 3.2: Further reduce sightrange for cowering characters.
|
||||
if (gGameExternalOptions.ubCoweringReducesSightRange == 1 || gGameExternalOptions.ubCoweringReducesSightRange == 2)
|
||||
{
|
||||
INT8 bTolerance = CalcSuppressionTolerance( pSoldier );
|
||||
|
||||
// Make sure character is cowering.
|
||||
if ( pSoldier->aiData.bShock >= bTolerance && gGameExternalOptions.ubMaxSuppressionShock > 0 &&
|
||||
sDistVisible > 0 )
|
||||
{
|
||||
sDistVisible = __max(1,(sDistVisible * (gGameExternalOptions.ubMaxSuppressionShock - pSoldier->aiData.bShock)) / gGameExternalOptions.ubMaxSuppressionShock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2299,7 +2315,13 @@ void ManSeesMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT16 sOppGridno,
|
||||
}
|
||||
else if ( pOpponent->ubBodyType == BLOODCAT && pOpponent->aiData.bNeutral)
|
||||
{
|
||||
MakeBloodcatsHostile();
|
||||
// HEADROCK HAM 3.6: If bloodcats are set as affiliated with civilians, do not trigger hostilities.
|
||||
if ( gBloodcatPlacements[SECTOR(pSoldier->sSectorX, pSoldier->sSectorY)][ 0 ].PlacementType != BLOODCAT_PLACEMENT_STATIC ||
|
||||
gBloodcatPlacements[SECTOR(pSoldier->sSectorX, pSoldier->sSectorY)][ gGameOptions.ubDifficultyLevel - 1 ].ubFactionAffiliation == NON_CIV_GROUP ||
|
||||
gBloodcatPlacements[SECTOR(pSoldier->sSectorX, pSoldier->sSectorY)][ gGameOptions.ubDifficultyLevel - 1 ].ubFactionAffiliation == QUEENS_CIV_GROUP )
|
||||
{
|
||||
MakeBloodcatsHostile();
|
||||
}
|
||||
/*
|
||||
SetSoldierNonNeutral( pOpponent );
|
||||
RecalculateOppCntsDueToNoLongerNeutral( pOpponent );
|
||||
@@ -5608,20 +5630,44 @@ void ProcessNoise(UINT8 ubNoiseMaker, INT16 sGridNo, INT8 bLevel, UINT8 ubTerrTy
|
||||
break;
|
||||
}
|
||||
|
||||
if ( gWorldSectorX == 5 && gWorldSectorY == MAP_ROW_N )
|
||||
// HEADROCK HAM 3.6: Bloodcat "static" sectors have been externalized, and there can be more than one.
|
||||
// Also, there's a toggle that determines whether or not bloodcats can sense enemies in this sector.
|
||||
UINT8 ubSectorID = SECTOR(gWorldSectorX, gWorldSectorY);
|
||||
UINT8 PlacementType = gBloodcatPlacements[ ubSectorID ][0].PlacementType;
|
||||
|
||||
if (PlacementType == BLOODCAT_PLACEMENT_STATIC)
|
||||
{
|
||||
// in the bloodcat arena sector, skip noises between army & bloodcats
|
||||
if ( pSoldier->bTeam == ENEMY_TEAM && MercPtrs[ ubNoiseMaker ]->bTeam == CREATURE_TEAM )
|
||||
if (gBloodcatPlacements[ ubSectorID ][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation == QUEENS_CIV_GROUP)
|
||||
{
|
||||
continue;
|
||||
// skip noises between army & bloodcats
|
||||
if ( pSoldier->bTeam == ENEMY_TEAM && MercPtrs[ ubNoiseMaker ]->ubBodyType == BLOODCAT && MercPtrs[ ubNoiseMaker ]->bTeam == CREATURE_TEAM )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ( pSoldier->bTeam == CREATURE_TEAM && pSoldier->ubBodyType == BLOODCAT && MercPtrs[ ubNoiseMaker ]->bTeam == ENEMY_TEAM )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ( pSoldier->bTeam == CREATURE_TEAM && MercPtrs[ ubNoiseMaker ]->bTeam == ENEMY_TEAM )
|
||||
else if (gBloodcatPlacements[ ubSectorID ][ gGameOptions.ubDifficultyLevel-1 ].ubFactionAffiliation > NON_CIV_GROUP)
|
||||
{
|
||||
continue;
|
||||
if ( MercPtrs[ ubNoiseMaker ]->ubBodyType == BLOODCAT && MercPtrs[ ubNoiseMaker ]->bTeam == CREATURE_TEAM && pSoldier->bSide != gbPlayerNum)
|
||||
{
|
||||
// Target is a bloodcat. He can't be heard by civilians no matter what.
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ( pSoldier->bTeam == CREATURE_TEAM && pSoldier->ubBodyType == BLOODCAT )
|
||||
{
|
||||
// Source is a bloodcat. He can only hear player-side soldiers, and only if hostile.
|
||||
if ( MercPtrs[ ubNoiseMaker ]->bSide != gbPlayerNum || pSoldier->aiData.bNeutral )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -7253,12 +7299,12 @@ void MakeBloodcatsHostile( void )
|
||||
{
|
||||
if ( pSoldier->ubBodyType == BLOODCAT && pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 )
|
||||
{
|
||||
SetSoldierNonNeutral( pSoldier );
|
||||
RecalculateOppCntsDueToNoLongerNeutral( pSoldier );
|
||||
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
||||
{
|
||||
CheckForPotentialAddToBattleIncrement( pSoldier );
|
||||
}
|
||||
SetSoldierNonNeutral( pSoldier );
|
||||
RecalculateOppCntsDueToNoLongerNeutral( pSoldier );
|
||||
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
||||
{
|
||||
CheckForPotentialAddToBattleIncrement( pSoldier );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -151,4 +151,6 @@ extern INT8 gbLightSighting[1][16];
|
||||
|
||||
BOOLEAN SoldierHasLimitedVision(SOLDIERTYPE * pSoldier);
|
||||
|
||||
// HEADROCK HAM 3.6: Moved here from cpp
|
||||
void MakeBloodcatsHostile( void );
|
||||
#endif
|
||||
Reference in New Issue
Block a user