mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +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:
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Version="8,00"
|
||||
Name="Editor_2005Express"
|
||||
ProjectGUID="{60D793F2-90B4-43C9-83B5-221EE11B37E6}"
|
||||
RootNamespace="Editor_2005Express"
|
||||
|
||||
+254
-71
@@ -172,6 +172,7 @@ BOOLEAN LoadGameSettings()
|
||||
gGameSettings.fOptions[TOPTION_LOW_CPU_USAGE] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_LOW_CPU_USAGE" , FALSE );
|
||||
gGameSettings.fOptions[TOPTION_ENHANCED_DESC_BOX] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_ENHANCED_DESC_BOX" , FALSE );
|
||||
gGameSettings.fOptions[TOPTION_TOGGLE_TURN_MODE] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_TOGGLE_TURN_MODE" , FALSE );
|
||||
gGameSettings.fOptions[TOPTION_STAT_PROGRESS_BARS] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_STAT_PROGRESS_BARS" , FALSE ); // HEADROCK HAM 3.6: Progress Bars
|
||||
gGameSettings.fOptions[TOPTION_CHEAT_MODE_OPTIONS_HEADER] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_CHEAT_MODE_OPTIONS_HEADER" , FALSE );
|
||||
gGameSettings.fOptions[TOPTION_FORCE_BOBBY_RAY_SHIPMENTS] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_FORCE_BOBBY_RAY_SHIPMENTS" , FALSE );
|
||||
gGameSettings.fOptions[TOPTION_CHEAT_MODE_OPTIONS_END] = iniReader.ReadBoolean("JA2 Game Settings","TOPTION_CHEAT_MODE_OPTIONS_END" , FALSE );
|
||||
@@ -342,6 +343,7 @@ BOOLEAN SaveGameSettings()
|
||||
settings << "TOPTION_LOW_CPU_USAGE = " << (gGameSettings.fOptions[TOPTION_LOW_CPU_USAGE] ? "TRUE" : "FALSE" ) << endl;
|
||||
settings << "TOPTION_ENHANCED_DESC_BOX = " << (gGameSettings.fOptions[TOPTION_ENHANCED_DESC_BOX] ? "TRUE" : "FALSE" ) << endl;
|
||||
settings << "TOPTION_TOGGLE_TURN_MODE = " << (gGameSettings.fOptions[TOPTION_TOGGLE_TURN_MODE] ? "TRUE" : "FALSE" ) << endl;
|
||||
settings << "TOPTION_STAT_PROGRESS_BARS = " << (gGameSettings.fOptions[TOPTION_STAT_PROGRESS_BARS] ? "TRUE" : "FALSE" ) << endl; // HEADROCK HAM 3.6: Progress Bars
|
||||
settings << "TOPTION_CHEAT_MODE_OPTIONS_HEADER = " << (gGameSettings.fOptions[TOPTION_CHEAT_MODE_OPTIONS_HEADER] ? "TRUE" : "FALSE" ) << endl;
|
||||
settings << "TOPTION_FORCE_BOBBY_RAY_SHIPMENTS = " << (gGameSettings.fOptions[TOPTION_FORCE_BOBBY_RAY_SHIPMENTS] ? "TRUE" : "FALSE" ) << endl;
|
||||
settings << "TOPTION_CHEAT_MODE_OPTIONS_END = " << (gGameSettings.fOptions[TOPTION_CHEAT_MODE_OPTIONS_END] ? "TRUE" : "FALSE" ) << endl;
|
||||
@@ -448,6 +450,11 @@ void InitGameSettings()
|
||||
|
||||
// arynn
|
||||
gGameSettings.fOptions[ TOPTION_TOGGLE_TURN_MODE ] = FALSE;
|
||||
|
||||
// HEADROCK HAM 3.6:
|
||||
gGameSettings.fOptions[ TOPTION_STAT_PROGRESS_BARS ] = FALSE;
|
||||
|
||||
// arynn: Cheat/Debug Menu
|
||||
gGameSettings.fOptions[ TOPTION_CHEAT_MODE_OPTIONS_HEADER ] = FALSE;
|
||||
gGameSettings.fOptions[ TOPTION_FORCE_BOBBY_RAY_SHIPMENTS ] = FALSE; // force all pending Bobby Ray shipments
|
||||
gGameSettings.fOptions[ TOPTION_CHEAT_MODE_OPTIONS_END ] = FALSE;
|
||||
@@ -745,6 +752,7 @@ void LoadGameExternalOptions()
|
||||
gGameExternalOptions.ubMovementEffectiveness = iniReader.ReadInteger("JA2 Tactical Settings", "MOVEMENT_EFFECTIVENESS", 50, 0, 100);
|
||||
gGameExternalOptions.ubCoverDisplayUpdateWait = iniReader.ReadInteger("JA2 Tactical Settings", "COVER_DISPLAY_UPDATE_WAIT", 500, -1, 10000);
|
||||
|
||||
|
||||
//################# Rain Settings ##################
|
||||
|
||||
// Rain settings
|
||||
@@ -929,9 +937,10 @@ void LoadGameExternalOptions()
|
||||
|
||||
gGameExternalOptions.guiCreateEachNHours = iniReader.ReadInteger("JA2 Gameplay Settings","CREATE_EACH_N_HOURS",24, 1, 96);
|
||||
gGameExternalOptions.guiDivOfOriginalMilitia = iniReader.ReadInteger("JA2 Gameplay Settings","DIV_OF_ORIGINAL_MILITIA",4, 1, 100);
|
||||
gGameExternalOptions.guiMinMilitiaSquadSize = iniReader.ReadInteger("JA2 Gameplay Settings","MINIMUM_MILITIA_SQUAD_SIZE",5, 1, CODE_MAXIMUM_NUMBER_OF_REBELS);
|
||||
gGameExternalOptions.guiMaxMilitiaSquadSize = iniReader.ReadInteger("JA2 Gameplay Settings","MAXIMUM_MILITIA_SQUAD_SIZE",20, gGameExternalOptions.guiMinMilitiaSquadSize, CODE_MAXIMUM_NUMBER_OF_REBELS);
|
||||
gGameExternalOptions.guiMaxMilitiaSquadSizeBattle = gGameExternalOptions.guiMaxMilitiaSquadSize;
|
||||
// HEADROCK HAM 3.6: These settings are REDUNDANT.
|
||||
//gGameExternalOptions.guiMinMilitiaSquadSize = iniReader.ReadInteger("JA2 Gameplay Settings","MINIMUM_MILITIA_SQUAD_SIZE",5, 1, CODE_MAXIMUM_NUMBER_OF_REBELS);
|
||||
//gGameExternalOptions.guiMaxMilitiaSquadSize = iniReader.ReadInteger("JA2 Gameplay Settings","MAXIMUM_MILITIA_SQUAD_SIZE",20, gGameExternalOptions.guiMinMilitiaSquadSize, CODE_MAXIMUM_NUMBER_OF_REBELS);
|
||||
//gGameExternalOptions.guiMaxMilitiaSquadSizeBattle = gGameExternalOptions.guiMaxMilitiaSquadSize;
|
||||
|
||||
gGameExternalOptions.iMaxMilitiaPerSector = iniReader.ReadInteger("JA2 Gameplay Settings","MAX_MILITIA_PER_SECTOR",20, 1, CODE_MAXIMUM_NUMBER_OF_REBELS);
|
||||
gGameExternalOptions.iTrainingSquadSize = iniReader.ReadInteger("JA2 Gameplay Settings","MAX_TRAINING_SQUAD_SIZE",10, 1, CODE_MAXIMUM_NUMBER_OF_REBELS);
|
||||
@@ -961,9 +970,11 @@ void LoadGameExternalOptions()
|
||||
gGameExternalOptions.ubTrainingSkillMax = iniReader.ReadInteger("JA2 Gameplay Settings","TRAINING_SKILL_MAX",100, 0, 100);
|
||||
gGameExternalOptions.ubSelfTrainingDivisor = iniReader.ReadInteger("JA2 Gameplay Settings","SELF_TRAINING_DIVISOR",1000, 1, 10000);
|
||||
gGameExternalOptions.ubInstructedTrainingDivisor = iniReader.ReadInteger("JA2 Gameplay Settings","INSTRUCTED_TRAINING_DIVISOR",3000, 1, 10000);
|
||||
gGameExternalOptions.ubGunRangeTrainingBonus = iniReader.ReadInteger("JA2 Gameplay Settings","GUN_RANGE_TRAINING_BONUS",25, 0, 100);
|
||||
// HEADROCK HAM 3.5: No longer necessary
|
||||
//gGameExternalOptions.ubGunRangeTrainingBonus = iniReader.ReadInteger("JA2 Gameplay Settings","GUN_RANGE_TRAINING_BONUS",25, 0, 100);
|
||||
gGameExternalOptions.ubTownMilitiaTrainingRate = iniReader.ReadInteger("JA2 Gameplay Settings","MILITIA_TRAINING_RATE",4, 1, 10);
|
||||
gGameExternalOptions.ubMaxMilitiaTrainersPerSector = iniReader.ReadInteger("JA2 Gameplay Settings","MAX_MILITIA_TRAINERS_PER_SECTOR",2, 1, gGameExternalOptions.ubGameMaximumNumberOfPlayerMercs);
|
||||
// HEADROCK HAM 3.5: No longer necessary
|
||||
//gGameExternalOptions.ubMaxMilitiaTrainersPerSector = iniReader.ReadInteger("JA2 Gameplay Settings","MAX_MILITIA_TRAINERS_PER_SECTOR",2, 1, gGameExternalOptions.ubGameMaximumNumberOfPlayerMercs);
|
||||
gGameExternalOptions.ubTeachBonusToTrain = iniReader.ReadInteger("JA2 Gameplay Settings","TEACH_BONUS_TO_TRAIN",30, 0, 100);
|
||||
gGameExternalOptions.ubRpcBonusToTrainMilitia = iniReader.ReadInteger("JA2 Gameplay Settings","RPC_BONUS_TO_TRAIN_MILITIA",10, 0, 100);
|
||||
gGameExternalOptions.ubMinSkillToTeach = iniReader.ReadInteger("JA2 Gameplay Settings","MIN_RATING_TO_TEACH",25, 0, 100);
|
||||
@@ -1008,62 +1019,55 @@ void LoadGameExternalOptions()
|
||||
gGameExternalOptions.fRestrictFemaleEnemiesExceptElite = iniReader.ReadBoolean("JA2 Gameplay Settings","RESTRICT_FEMALE_ENEMIES_EXCEPT_ELITE",FALSE);
|
||||
|
||||
// HEADROCK: Use Enhanced Item Description Box?
|
||||
gGameExternalOptions.fEnhancedDescriptionBox = iniReader.ReadInteger("JA2 Gameplay Settings","USE_ENHANCED_DESCRIPTION_BOX",0, 0, 2);
|
||||
gGameExternalOptions.iEnhancedDescriptionBox = iniReader.ReadInteger("JA2 Gameplay Settings","USE_ENHANCED_DESCRIPTION_BOX",0, 0, 2);
|
||||
|
||||
// WANNE: Always use prof.dat??
|
||||
gGameExternalOptions.fAlwaysUseProfDat = iniReader.ReadBoolean("JA2 Gameplay Settings", "ALWAYS_USE_PROF_DAT", FALSE);
|
||||
|
||||
// HEADROCK HAM B2.4
|
||||
gGameExternalOptions.iMineIncomePercentage = iniReader.ReadInteger("JA2 HAM Settings","MINE_INCOME_PERCENTAGE", 100, 1, 1000);
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// JA2 HAM Settings
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// HEADROCK HAM B1: Set % of mine income, where 100% = normal
|
||||
gGameExternalOptions.usMineIncomePercentage = iniReader.ReadInteger("JA2 HAM Settings","MINE_INCOME_PERCENTAGE", 100, 1, 1000);
|
||||
|
||||
// HEADROCK HAM B1: Set minimum and maximum CTH
|
||||
gGameExternalOptions.iMaximumCTH = iniReader.ReadInteger("JA2 HAM Settings","MAXIMUM_POSSIBLE_CTH",99);
|
||||
gGameExternalOptions.ubMaximumCTH = iniReader.ReadInteger("JA2 HAM Settings","MAXIMUM_POSSIBLE_CTH", 99, 1, 100);
|
||||
|
||||
gGameExternalOptions.iMinimumCTH = iniReader.ReadInteger("JA2 HAM Settings","MINIMUM_POSSIBLE_CTH",0);
|
||||
gGameExternalOptions.ubMinimumCTH = iniReader.ReadInteger("JA2 HAM Settings","MINIMUM_POSSIBLE_CTH", 1, 0, 99);
|
||||
|
||||
// HEADROCK HAM B1: Set minimum CTH at fraction between 0 and 1 ( MINCTH = 1/(100*divisor) ) Note Minimum above must be 0.
|
||||
gGameExternalOptions.iMinimumCTHDivisor = iniReader.ReadInteger("JA2 HAM Settings","MINIMUM_CTH_DIVISOR",100);
|
||||
gGameExternalOptions.usMinimumCTHDivisor = iniReader.ReadInteger("JA2 HAM Settings","MINIMUM_CTH_DIVISOR", 100, 1, 250);
|
||||
|
||||
// HEADROCK HAM B1: Allow restricted militia to move through visited sectors?
|
||||
gGameExternalOptions.bUnrestrictVisited = iniReader.ReadBoolean("JA2 HAM Settings","ALLOW_RESTRICTED_MILITIA_THROUGH_VISITED_SECTORS",FALSE);
|
||||
gGameExternalOptions.fUnrestrictVisited = iniReader.ReadBoolean("JA2 HAM Settings","ALLOW_RESTRICTED_MILITIA_THROUGH_VISITED_SECTORS", FALSE);
|
||||
|
||||
gGameExternalOptions.bDynamicRestrictRoaming = iniReader.ReadBoolean("JA2 HAM Settings","ALLOW_DYNAMIC_RESTRICTED_ROAMING",TRUE);
|
||||
|
||||
// HEADROCK HAM B2: Reset suppression counter. 0 = never (oldskool), 1 = Every turn, 2 = Every attack.
|
||||
gGameExternalOptions.iClearSuppression = iniReader.ReadInteger("JA2 HAM Settings","CLEAR_SUPPRESSION_COUNTER",1);
|
||||
// HEADROCK HAM B1: Allow dynamic restrictions?
|
||||
gGameExternalOptions.fDynamicRestrictRoaming = iniReader.ReadBoolean("JA2 HAM Settings","ALLOW_DYNAMIC_RESTRICTED_ROAMING", TRUE);
|
||||
|
||||
// HEADROCK HAM B2.1: This controls how effective suppression is, by increasing the number of ubSuppressionPoints accumulated by combatants (percentage);
|
||||
gGameExternalOptions.iSuppressionEffectiveness = iniReader.ReadInteger("JA2 HAM Settings","SUPPRESSION_EFFECTIVENESS",0);
|
||||
gGameExternalOptions.sSuppressionEffectiveness = iniReader.ReadInteger("JA2 HAM Settings","SUPPRESSION_EFFECTIVENESS", 0, 0, 1000);
|
||||
|
||||
// HEADROCK HAM B2: MAXIMUM number of APs that can be lost to suppression in a given turn (0=unlimited)
|
||||
gGameExternalOptions.fSuppressionAPLossPerTurn = iniReader.ReadBoolean("JA2 HAM Settings","LIMITED_SUPPRESSION_AP_LOSS_PER_TURN",TRUE);
|
||||
|
||||
// HEADROCK HAM B2: MAXIMUM number of APs that can be lost to suppression in a given attack (0=unlimited)
|
||||
gGameExternalOptions.fSuppressionAPLossPerAttack = iniReader.ReadBoolean("JA2 HAM Settings","LIMITED_SUPPRESSION_AP_LOSS_PER_ATTACK",TRUE);
|
||||
|
||||
gGameExternalOptions.iSuppressionToleranceMax = iniReader.ReadInteger("JA2 HAM Settings","SUPPRESSION_TOLERANCE_MAX", 18, 1, 24);
|
||||
gGameExternalOptions.iSuppressionToleranceMin = iniReader.ReadInteger("JA2 HAM Settings","SUPPRESSION_TOLERANCE_MIN", 1, 0, 24);
|
||||
|
||||
// HEADROCK HAM B2: Suppression Shock ON/OFF
|
||||
gGameExternalOptions.fSuppressionShock = iniReader.ReadBoolean("JA2 HAM Settings","SUPPRESSION_SHOCK",FALSE);
|
||||
gGameExternalOptions.ubSuppressionToleranceMax = iniReader.ReadInteger("JA2 HAM Settings","SUPPRESSION_TOLERANCE_MAX", 18, 1, 24);
|
||||
gGameExternalOptions.ubSuppressionToleranceMin = iniReader.ReadInteger("JA2 HAM Settings","SUPPRESSION_TOLERANCE_MIN", 1, 0, 24);
|
||||
|
||||
// HEADROCK HAM B2: Suppression Shock effectiveness (percentage, 100 = "normal", 0 = deactivated. Range 0-65535)
|
||||
gGameExternalOptions.iSuppressionShockEffectiveness = iniReader.ReadInteger("JA2 HAM Settings","SUPPRESSION_SHOCK_EFFECTIVENESS",0);
|
||||
gGameExternalOptions.usSuppressionShockEffect = iniReader.ReadInteger("JA2 HAM Settings","SUPPRESSION_SHOCK_EFFECTIVENESS", 100, 0, 1000);
|
||||
|
||||
// HEADROCK HAM B2.1: CTH penalty given by a "Cowering" target to any enemy shooter.
|
||||
gGameExternalOptions.iAimPenaltyPerTargetShock = iniReader.ReadInteger("JA2 HAM Settings","AIM_PENALTY_PER_TARGET_SHOCK",0);
|
||||
gGameExternalOptions.ubAimPenaltyPerTargetShock = iniReader.ReadInteger("JA2 HAM Settings","AIM_PENALTY_PER_TARGET_SHOCK", 5, 0, 100 );
|
||||
|
||||
// HEADROCK HAM B2.3: A "cowering" soldier is twice as susceptible to suppression.
|
||||
gGameExternalOptions.iCowerEffectOnSuppression = iniReader.ReadInteger("JA2 HAM Settings","COWER_EFFECT_ON_SUPPRESSION",0);
|
||||
gGameExternalOptions.usCowerEffectOnSuppression = iniReader.ReadInteger("JA2 HAM Settings","COWER_EFFECT_ON_SUPPRESSION", 150, 0, 1000 );
|
||||
|
||||
// HEADROCK HAM B2.5: Turn on Realistic Tracers. 0 = off (regular tracers). 1 = Fully realistic tracers. 2 = Tracer Bump + 1.13 Autofire Penalty Reduction
|
||||
gGameExternalOptions.iRealisticTracers = iniReader.ReadInteger("JA2 HAM Settings","REALISTIC_TRACERS",0);
|
||||
gGameExternalOptions.ubRealisticTracers = iniReader.ReadInteger("JA2 HAM Settings","REALISTIC_TRACERS", 0, 0, 2);
|
||||
|
||||
// HEADROCK HAM B2.5: Realistic tracers - one of every X bullets in a tracer magazines will be a tracer bullet. 0 = off (JA2 normal)
|
||||
gGameExternalOptions.iNumBulletsPerTracer = __max(iniReader.ReadInteger("JA2 HAM Settings","NUM_BULLETS_PER_TRACER",1),1);
|
||||
gGameExternalOptions.ubNumBulletsPerTracer = __max(iniReader.ReadInteger("JA2 HAM Settings","NUM_BULLETS_PER_TRACER", 5, 1, 255),1);
|
||||
|
||||
// HEADROCK HAM B2.5: Realistic tracers - CTH increased by this amount whenever a tracer is fired. 0 = off.
|
||||
gGameExternalOptions.iCTHBumpPerTracer = iniReader.ReadInteger("JA2 HAM Settings","CTH_BUMP_PER_TRACER",0);
|
||||
gGameExternalOptions.ubCTHBumpPerTracer = iniReader.ReadInteger("JA2 HAM Settings","CTH_BUMP_PER_TRACER", 30, 0, 100 );
|
||||
|
||||
// HEADROCK HAM B2.6: Increased aiming costs?
|
||||
gGameExternalOptions.fIncreasedAimingCost = iniReader.ReadBoolean("JA2 HAM Settings","INCREASED_AIM_COST", FALSE);
|
||||
@@ -1076,33 +1080,33 @@ void LoadGameExternalOptions()
|
||||
gGameExternalOptions.iMovementEffectOnAiming = (float)iniReader.ReadDouble("JA2 HAM Settings","MOVEMENT_EFFECT_ON_AIMING", 1.5, 0.0, 255.0);
|
||||
|
||||
// HEADROCK HAM B2.6: Autofire Bullets/5AP modifier
|
||||
gGameExternalOptions.iAutofireBulletsPer5APModifier = iniReader.ReadInteger("JA2 HAM Settings","AUTOFIRE_BULLETS_PER_5AP_MODIFIER", 0);
|
||||
gGameExternalOptions.bAutofireBulletsPer5APModifier = iniReader.ReadInteger("JA2 HAM Settings","AUTOFIRE_BULLETS_PER_5AP_MODIFIER", 0, -100, 100 );
|
||||
|
||||
// HEADROCK HAM B2.6/B1: Adjustable "luck" factor in Auto-Resolve
|
||||
//gGameExternalOptions.iAutoResolveLuckFactor = (float)(__max(iniReader.ReadFloat("JA2 HAM Settings","AUTORESOLVE_LUCK_FACTOR", 2.0),1.0));
|
||||
gGameExternalOptions.iAutoResolveLuckFactor = (float)(__max(iniReader.ReadDouble("JA2 HAM Settings","AUTORESOLVE_LUCK_FACTOR", 2.0, 0.0, 255.0),1.0));
|
||||
|
||||
// HEADROCK HAM B2.6: Adjustable maximum for Suppression Shock effect. This has the added effect of reducing overall susceptibility to shock and may render some enemies unshockable.
|
||||
gGameExternalOptions.iMaxSuppressionShock = iniReader.ReadInteger("JA2 HAM Settings","MAXIMUM_SUPPRESSION_SHOCK", 0);
|
||||
gGameExternalOptions.ubMaxSuppressionShock = iniReader.ReadInteger("JA2 HAM Settings","MAXIMUM_SUPPRESSION_SHOCK", 30, 0, 200 );
|
||||
|
||||
// HEADROCK HAM B2.6/2/1: Toggle new Burst/Auto CTH bars: 0=neither, 1=both, 2=Burst, 3=Auto
|
||||
gGameExternalOptions.iNewCTHBars = iniReader.ReadInteger("JA2 HAM Settings","NEW_BURST-AUTO_CTH_BARS", 0);
|
||||
gGameExternalOptions.ubNewCTHBars = iniReader.ReadInteger("JA2 HAM Settings","NEW_BURST-AUTO_CTH_BARS", 0, 0, 3);
|
||||
|
||||
// HEADROCK HAM B2.6: Toggle whether AI checks for larger magazine when wanting to suppress at a distance
|
||||
gGameExternalOptions.fIncreaseAISuppressionFire = iniReader.ReadBoolean("JA2 HAM Settings","INCREASE_AI_WILLINGNESS_TO_SUPPRESS", FALSE);
|
||||
|
||||
// HEADROCK HAM B2.7: Change the speed of skill progression. (defaults set to JA2 normal)
|
||||
gGameExternalOptions.ubHealthSubpointsToImprove = __max(1,iniReader.ReadInteger("JA2 HAM Settings","HEALTH_SUBPOINTS_TO_IMPROVE", 50));
|
||||
gGameExternalOptions.ubStrengthSubpointsToImprove = __max(1,iniReader.ReadInteger("JA2 HAM Settings","STRENGTH_SUBPOINTS_TO_IMPROVE", 50));
|
||||
gGameExternalOptions.ubDexteritySubpointsToImprove = __max(1,iniReader.ReadInteger("JA2 HAM Settings","DEXTERITY_SUBPOINTS_TO_IMPROVE", 50));
|
||||
gGameExternalOptions.ubAgilitySubpointsToImprove = __max(1,iniReader.ReadInteger("JA2 HAM Settings","AGILITY_SUBPOINTS_TO_IMPROVE", 50));
|
||||
gGameExternalOptions.ubWisdomSubpointsToImprove = __max(1,iniReader.ReadInteger("JA2 HAM Settings","WISDOM_SUBPOINTS_TO_IMPROVE", 50));
|
||||
gGameExternalOptions.ubMarksmanshipSubpointsToImprove = __max(1,iniReader.ReadInteger("JA2 HAM Settings","MARKSMANSHIP_SUBPOINTS_TO_IMPROVE", 25));
|
||||
gGameExternalOptions.ubMedicalSubpointsToImprove = __max(1,iniReader.ReadInteger("JA2 HAM Settings","MEDICAL_SUBPOINTS_TO_IMPROVE", 25));
|
||||
gGameExternalOptions.ubMechanicalSubpointsToImprove = __max(1,iniReader.ReadInteger("JA2 HAM Settings","MECHANICAL_SUBPOINTS_TO_IMPROVE", 25));
|
||||
gGameExternalOptions.ubExplosivesSubpointsToImprove = __max(1,iniReader.ReadInteger("JA2 HAM Settings","EXPLOSIVES_SUBPOINTS_TO_IMPROVE", 25));
|
||||
gGameExternalOptions.ubLeadershipSubpointsToImprove = __max(1,iniReader.ReadInteger("JA2 HAM Settings","LEADERSHIP_SUBPOINTS_TO_IMPROVE", 25));
|
||||
gGameExternalOptions.ubLevelSubpointsToImprove = __max(1,__min(iniReader.ReadInteger("JA2 HAM Settings","LEVEL_SUBPOINTS_TO_IMPROVE", 350), 6500));
|
||||
gGameExternalOptions.usHealthSubpointsToImprove = iniReader.ReadInteger("JA2 HAM Settings","HEALTH_SUBPOINTS_TO_IMPROVE", 50, 1, 1000 );
|
||||
gGameExternalOptions.usStrengthSubpointsToImprove = iniReader.ReadInteger("JA2 HAM Settings","STRENGTH_SUBPOINTS_TO_IMPROVE", 50, 1, 1000 );
|
||||
gGameExternalOptions.usDexteritySubpointsToImprove = iniReader.ReadInteger("JA2 HAM Settings","DEXTERITY_SUBPOINTS_TO_IMPROVE", 50, 1, 1000 );
|
||||
gGameExternalOptions.usAgilitySubpointsToImprove = iniReader.ReadInteger("JA2 HAM Settings","AGILITY_SUBPOINTS_TO_IMPROVE", 50, 1, 1000 );
|
||||
gGameExternalOptions.usWisdomSubpointsToImprove = iniReader.ReadInteger("JA2 HAM Settings","WISDOM_SUBPOINTS_TO_IMPROVE", 50, 1, 1000 );
|
||||
gGameExternalOptions.usMarksmanshipSubpointsToImprove = iniReader.ReadInteger("JA2 HAM Settings","MARKSMANSHIP_SUBPOINTS_TO_IMPROVE", 25, 1, 1000 );
|
||||
gGameExternalOptions.usMedicalSubpointsToImprove = iniReader.ReadInteger("JA2 HAM Settings","MEDICAL_SUBPOINTS_TO_IMPROVE", 25, 1, 1000 );
|
||||
gGameExternalOptions.usMechanicalSubpointsToImprove = iniReader.ReadInteger("JA2 HAM Settings","MECHANICAL_SUBPOINTS_TO_IMPROVE", 25, 1, 1000 );
|
||||
gGameExternalOptions.usExplosivesSubpointsToImprove = iniReader.ReadInteger("JA2 HAM Settings","EXPLOSIVES_SUBPOINTS_TO_IMPROVE", 25, 1, 1000 );
|
||||
gGameExternalOptions.usLeadershipSubpointsToImprove = iniReader.ReadInteger("JA2 HAM Settings","LEADERSHIP_SUBPOINTS_TO_IMPROVE", 25, 1, 1000 );
|
||||
gGameExternalOptions.usLevelSubpointsToImprove = iniReader.ReadInteger("JA2 HAM Settings","LEVEL_SUBPOINTS_TO_IMPROVE", 350, 1, 6500);
|
||||
|
||||
// HEADROCK HAM B2.7: When turned on, this will give a CTH approximation instead of an exact value, on CTH Bars and "F" key feedback.
|
||||
gGameExternalOptions.fApproximateCTH = iniReader.ReadBoolean("JA2 HAM Settings","APPROXIMATE_CTH", FALSE);
|
||||
@@ -1110,42 +1114,208 @@ void LoadGameExternalOptions()
|
||||
// HEADROCK HAM B2.7: Augmented Roaming Militia code - turn this to TRUE to allow militia free travel through San Mona, Tixa, Orta, Omerta, and Estoni.
|
||||
gGameExternalOptions.fAllowMilitiaMoveThroughMinorCities = iniReader.ReadBoolean("JA2 HAM Settings","ALLOW_MILITIA_MOVE_THROUGH_MINOR_CITIES", FALSE);
|
||||
|
||||
// HEADROCK HAM B2.7: Smarter Roaming Militia Generator will generate Roamers in any available city perimeter square, allowing us to avoid "wasting" training sessions more easily.
|
||||
gGameExternalOptions.fSmartRoamingMilitiaGenerator = iniReader.ReadBoolean("JA2 HAM Settings","SMART_ROAMING_MILITIA_GENERATOR", FALSE);
|
||||
|
||||
// HEADROCK HAM B2.7: When "TRUE", Roaming Militia will be created on a 25% Veteran, 25% Regular, 50% green basis. If new militia is placed into a full group, it will upgrade greens/regulars in that group.
|
||||
gGameExternalOptions.fDiverseRoamingMilitiaGroups = iniReader.ReadBoolean("JA2 HAM Settings","DIVERSE_ROAMING_MILITIA_GROUPS", FALSE);
|
||||
|
||||
// HEADROCK HAM B2.8: This setting controls whether militia will try to join up into the largest groups they can, or average out the size of the groups to cover more territory.
|
||||
gGameExternalOptions.ubRoamingMilitiaSpreadsOutChance = iniReader.ReadInteger("JA2 HAM Settings","ROAMING_MILITIA_SPREADOUT_CHANCE", 0);
|
||||
|
||||
// HEADROCK HAM B2.8: These are new cowering penalty divisors that help us determine how effective cowering is in different stances and when the shooter is targetting different bodyparts
|
||||
gGameExternalOptions.ubCoweringPenaltyDivisorProne = __max(1,iniReader.ReadInteger("JA2 HAM Settings","CTH_PENALTY_FOR_COWERING_PRONE_TARGET_DIVISOR", 1));
|
||||
gGameExternalOptions.ubCoweringPenaltyDivisorCrouchedHead = __max(1,iniReader.ReadInteger("JA2 HAM Settings","CTH_PENALTY_FOR_COWERING_CROUCHED_TARGET_HEAD_DIVISOR", 3));
|
||||
gGameExternalOptions.ubCoweringPenaltyDivisorCrouchedTorso = __max(1,iniReader.ReadInteger("JA2 HAM Settings","CTH_PENALTY_FOR_COWERING_CROUCHED_TARGET_TORSO_DIVISOR", 4));
|
||||
gGameExternalOptions.ubCoweringPenaltyDivisorCrouchedLegs = __max(1,iniReader.ReadInteger("JA2 HAM Settings","CTH_PENALTY_FOR_COWERING_CROUCHED_TARGET_LEGS_DIVISOR", 5));
|
||||
gGameExternalOptions.ubCoweringPenaltyDivisorProne = iniReader.ReadInteger("JA2 HAM Settings","CTH_PENALTY_FOR_COWERING_PRONE_TARGET_DIVISOR", 1, 1, 100 );
|
||||
gGameExternalOptions.ubCoweringPenaltyDivisorCrouchedHead = iniReader.ReadInteger("JA2 HAM Settings","CTH_PENALTY_FOR_COWERING_CROUCHED_TARGET_HEAD_DIVISOR", 3, 1, 100);
|
||||
gGameExternalOptions.ubCoweringPenaltyDivisorCrouchedTorso = iniReader.ReadInteger("JA2 HAM Settings","CTH_PENALTY_FOR_COWERING_CROUCHED_TARGET_TORSO_DIVISOR", 4, 1, 100);
|
||||
gGameExternalOptions.ubCoweringPenaltyDivisorCrouchedLegs = iniReader.ReadInteger("JA2 HAM Settings","CTH_PENALTY_FOR_COWERING_CROUCHED_TARGET_LEGS_DIVISOR", 5, 1, 100);
|
||||
|
||||
// HEADROCK HAM B2.8: This is the maximum range at which a target gives out the full CTH penalty for cowering. At lower range, it'll give proportionally less penalty.
|
||||
gGameExternalOptions.usMinRangeForFullCoweringPenalty = __max(10,iniReader.ReadInteger("JA2 HAM Settings","MIN_RANGE_FOR_FULL_COWERING_TARGET_PENALTY", 300));
|
||||
gGameExternalOptions.usMinRangeForFullCoweringPenalty = iniReader.ReadInteger("JA2 HAM Settings","MIN_RANGE_FOR_FULL_COWERING_TARGET_PENALTY", 300, 10, 10000 );
|
||||
|
||||
// HEADROCK HAM B2.8: Absolute maximum CTH penalty from target/shooter cowering
|
||||
gGameExternalOptions.usMaxShooterCoweringPenalty = __max(1,iniReader.ReadInteger("JA2 HAM Settings","MAX_SHOOTER_COWERING_PENALTY", 0));
|
||||
gGameExternalOptions.usMaxTargetCoweringPenalty = __max(1,iniReader.ReadInteger("JA2 HAM Settings","MAX_TARGET_COWERING_PENALTY", 0));
|
||||
gGameExternalOptions.usMaxShooterCoweringPenalty = iniReader.ReadInteger("JA2 HAM Settings","MAX_SHOOTER_COWERING_PENALTY", 0, 0, 250 );
|
||||
gGameExternalOptions.usMaxTargetCoweringPenalty = iniReader.ReadInteger("JA2 HAM Settings","MAX_TARGET_COWERING_PENALTY", 0, 0, 250 );
|
||||
|
||||
// HEADROCK HAM B2.8: If this is turned on, Militia will drop their equipment similar to enemies, IF killed by non-player character.
|
||||
gGameExternalOptions.ubMilitiaDropEquipment = iniReader.ReadInteger("JA2 HAM Settings","MILITIA_DROP_EQUIPMENT", 0);
|
||||
// HEADROCK HAM B2.8: At "1", Militia will drop their equipment similar to enemies, IF killed by non-player character. At "2" they drop whenever killed.
|
||||
gGameExternalOptions.ubMilitiaDropEquipment = iniReader.ReadInteger("JA2 HAM Settings","MILITIA_DROP_EQUIPMENT", 0, 0, 2 );
|
||||
|
||||
// HEADROCK HAM B2.8: New Trainer Relations: 2 = Trainees will go to sleep when their trainer goes to sleep. 3 = Trainer will go to sleep if all trainees are asleep. 1 = Both. 0 = Neither.
|
||||
gGameExternalOptions.ubSmartTrainingSleep = iniReader.ReadInteger("JA2 HAM Settings","SMART_TRAINING-SLEEP_HANDLER", 0);
|
||||
gGameExternalOptions.ubSmartTrainingSleep = iniReader.ReadInteger("JA2 HAM Settings","SMART_TRAINING-SLEEP_HANDLER", 0, 0, 3);
|
||||
|
||||
// HEADROCK HAM B2.8: New Trainer Relations: 2 = Trainees will wake up when their trainer wakes up. 3 = Trainer will wake up if all trainees wake up. 1 = Both. 0 = Neither.
|
||||
gGameExternalOptions.ubSmartTrainingWake = iniReader.ReadInteger("JA2 HAM Settings","SMART_TRAINING-WAKE_HANDLER", 0);
|
||||
gGameExternalOptions.ubSmartTrainingWake = iniReader.ReadInteger("JA2 HAM Settings","SMART_TRAINING-WAKE_HANDLER", 0, 0, 3);
|
||||
|
||||
// HEADROCK HAM B2.8: New Trainer Relations: 2 = Trainers will rest if no trainees available. 3 = Trainees will rest if no trainers available (not recommended). 1 = Both. 0 = Neither.
|
||||
gGameExternalOptions.ubSmartTrainingRest = iniReader.ReadInteger("JA2 HAM Settings","SMART_TRAINING_REST", 0);
|
||||
gGameExternalOptions.ubSmartTrainingRest = iniReader.ReadInteger("JA2 HAM Settings","SMART_TRAINING_REST", 0, 0, 3);
|
||||
|
||||
// WANNE: HEADROCK HAM 3: Bobby Rays attachment tooltips
|
||||
gGameExternalOptions.fBobbyRayTooltipsShowAttachments = iniReader.ReadBoolean("JA2 HAM Settings","BOBBY_RAY_TOOLTIPS_SHOW_POSSIBLE_ATTACHMENTS", FALSE);
|
||||
// HEADROCK HAM 3: Externalized ratio between Weight and Strength. This value determines how many strength points we need to lift 0.5kg with no encumberance.
|
||||
gGameExternalOptions.iStrengthToLiftHalfKilo = (float)iniReader.ReadDouble("JA2 HAM Settings","STRENGTH_TO_LIFT_HALF_KILO", 1.0, 0.1, 100.0);
|
||||
|
||||
// HEADROCK HAM 3: Define minimum leadership required for training militia. Set to 0 for "no limit".
|
||||
gGameExternalOptions.ubMinimumLeadershipToTrainMilitia = iniReader.ReadInteger("JA2 HAM Settings","MINIMUM_LEADERSHIP_TO_TRAIN_MILITIA", 0, 0, 99);
|
||||
|
||||
// HEADROCK HAM 3: Define effect of "TEACHER" trait in increasing effective leadership, for purposes of eligibility for training militia. This is a percentage value. HAM Default would be 200 = double effective leadership for each TEACHING level.
|
||||
gGameExternalOptions.usTeacherTraitEffectOnLeadership = iniReader.ReadInteger("JA2 HAM Settings","TEACHER_TRAIT_EFFECT_ON_LEADERSHIP", 100, 1, 10000);
|
||||
|
||||
// HEADROCK HAM 3: If enabled, the trainer's "effective" leadership skill determines HOW MANY militia he/she creates per session.
|
||||
gGameExternalOptions.fLeadershipAffectsMilitiaQuantity = iniReader.ReadBoolean("JA2 HAM Settings","LEADERSHIP_AFFECTS_MILITIA_QUANTITY", FALSE);
|
||||
|
||||
// HEADROCK HAM 3: If "LEADERSHIP_AFFECTS_MILITIA_QUANTITY" is true, this value determines the lowest leadership required to train a full (default size 10) squad of town militia in one training session.
|
||||
gGameExternalOptions.ubReqLeadershipForFullTraining = iniReader.ReadInteger("JA2 HAM Settings","REQ_LEADERSHIP_FOR_MAX_MILITIA", 100, 1, 100);
|
||||
|
||||
// HEADROCK HAM 3: Four INI settings to control the number of kills you must accumulate to win one progress point, one setting per difficulty level
|
||||
gGameExternalOptions.usNumKillsPerProgressPointNovice = iniReader.ReadInteger("JA2 HAM Settings","NUM_KILLS_PER_PROGRESS_POINT_NOVICE", 7, 1, 1000);
|
||||
gGameExternalOptions.usNumKillsPerProgressPointExperienced = iniReader.ReadInteger("JA2 HAM Settings","NUM_KILLS_PER_PROGRESS_POINT_EXPERIENCED", 10, 1, 1000);
|
||||
gGameExternalOptions.usNumKillsPerProgressPointExpert = iniReader.ReadInteger("JA2 HAM Settings","NUM_KILLS_PER_PROGRESS_POINT_EXPERT", 15, 1, 1000);
|
||||
gGameExternalOptions.usNumKillsPerProgressPointInsane = iniReader.ReadInteger("JA2 HAM Settings","NUM_KILLS_PER_PROGRESS_POINT_INSANE", 60, 1, 1000);
|
||||
|
||||
// HEADROCK HAM 3: If enabled, changes the way the game calculates progress. It will look at each progress control separately (Kills/Income/Control/Visited) and set the progress to the HIGHEST scoring control.
|
||||
gGameExternalOptions.fAlternateProgressCalculation = iniReader.ReadBoolean("JA2 HAM Settings","ALTERNATE_PROGRESS_CALCULATION", FALSE);
|
||||
|
||||
// HEADROCK HAM 3: If enabled, tooltipping over Bobby Ray's weapons will show a list of possible attachments to those weapons.
|
||||
gGameExternalOptions.fBobbyRayTooltipsShowAttachments = iniReader.ReadBoolean("JA2 HAM Settings","BOBBY_RAY_TOOLTIPS_SHOW_POSSIBLE_ATTACHMENTS", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.1: Divisor for the AP-to-Ready cost charge on first aiming click, when extra aiming costs are enabled. 0 = No ready-time-based charge.
|
||||
gGameExternalOptions.ubFirstAimReadyCostDivisor = iniReader.ReadInteger("JA2 HAM Settings","FIRST_AIM_READY_COST_DIVISOR", 0, 0, 255);
|
||||
|
||||
// HEADROCK HAM 3.1: This is a suppression tool that not everyone will like. It gives an on-screen message when any character has been suppressed so much he's lost his next turn completely!
|
||||
gGameExternalOptions.fShowSuppressionShutdown = iniReader.ReadBoolean("JA2 HAM Settings","SHOW_MSG_FULLY_SUPPRESSED", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.1: Set whether you'd like to determine yourself which mine (if any) will shut down during the campaign.
|
||||
gGameExternalOptions.fManuallySelectMineShutdown = iniReader.ReadBoolean("JA2 HAM Settings","MANUALLY_SELECT_MINE_TO_RUN_OUT", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.1: Select which mine will run out. 0 = no mine. 1 = San Mona (unused), 2 = Drassen, 3 = Alma, 4 = Cambria, 5 = Chitzena, 6 = Grumm.
|
||||
gGameExternalOptions.ubWhichMineRunsOut = iniReader.ReadInteger("JA2 HAM Settings","WHICH_MINE_RUNS_OUT", 0, 0, 6);
|
||||
|
||||
// HEADROCK HAM 3.1: Can the Humvee go off-road?
|
||||
gGameExternalOptions.fHumveeOffroad = iniReader.ReadBoolean("JA2 HAM Settings","HUMVEE_OFFROAD", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.2: If activated, reinforcements (militia/enemy) arrive in the battle with 0 APs. This makes them less of a diablo-ex-machina. 0 = Diabled. 2 = Enemies. 3 = Militia. 1 = both
|
||||
gGameExternalOptions.ubReinforcementsFirstTurnFreeze = iniReader.ReadInteger("JA2 HAM Settings","REINFORCEMENTS_ARRIVE_WITH_NO_AP", 0, 0, 3);
|
||||
|
||||
// HEADROCK HAM 3.2: This feature allows the status, leadership and experience of nearby friendlies help/hinder a character's tolerance, based on their distance from him.
|
||||
gGameExternalOptions.fFriendliesAffectTolerance = iniReader.ReadBoolean("JA2 HAM Settings","FRIENDLIES_AFFECT_TOLERANCE", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.2: Set a divisor for the CtH of Mortar weapons.
|
||||
gGameExternalOptions.ubMortarCTHDivisor = iniReader.ReadInteger("JA2 HAM Settings","MORTAR_CTH_DIVISOR", 1, 1, 255);
|
||||
|
||||
// HEADROCK HAM 3.2: This enabled reduced sight for cowering characters. 0 = disabled. 2 = Reduced Sightrange. 3 = Tunnel-vision. 1 = Both.
|
||||
gGameExternalOptions.ubCoweringReducesSightRange = iniReader.ReadInteger("JA2 HAM Settings","COWERING_REDUCES_SIGHTRANGE", 0, 0, 3);
|
||||
|
||||
// HEADROCK HAM 3.2: Critical Headshots may cause blindness. Rolls 1 to X change of being blinded. 0 = disabled.
|
||||
gGameExternalOptions.ubChanceBlindedByHeadshot = iniReader.ReadInteger("JA2 HAM Settings","CHANCE_BLINDED_BY_HEADSHOT", 0, 0, 10);
|
||||
|
||||
// HEADROCK HAM 3.2: Critical Legshots cause additional AP loss
|
||||
gGameExternalOptions.fCriticalLegshotCausesAPLoss = iniReader.ReadBoolean("JA2 HAM Settings","CRITICAL_LEGSHOT_CAUSES_AP_LOSS", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.2: When enabled, this setting removes the player's omniscience inside his own sectors. The player will no longer see the movement of enemy groups unless someone is nearby to scout them.
|
||||
gGameExternalOptions.fNoEnemyDetectionWithoutRecon = iniReader.ReadBoolean("JA2 HAM Settings","NO_ENEMY_DETECTION_WITHOUT_RECON", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.2: Determines the training bonus for the Medical skill, when training in "hospital" sectors
|
||||
gGameExternalOptions.ubHospitalTrainingBonus = iniReader.ReadInteger("JA2 HAM Settings","HOSPITAL_TRAINING_BONUS", 0, 0, 100);
|
||||
|
||||
// HEADROCK HAM 3.2: Determines the repaid bonus when training in factory ("industrial") sectors - in percentage of the character's original repair points!
|
||||
gGameExternalOptions.ubFactoryRepairBonus = iniReader.ReadInteger("JA2 HAM Settings","FACTORY_REPAIR_BONUS", 0, 0, 100);
|
||||
|
||||
// HEADROCK HAM 3.2: How much MECHANICAL skill do we need to gain a repair bonus from a factory?
|
||||
gGameExternalOptions.ubMinMechanicalForFactoryRepairBonus = iniReader.ReadInteger("JA2 HAM Settings","MIN_MECHANICAL_FOR_FACTORY_REPAIR_BONUS", 0, 0, 100);
|
||||
|
||||
// HEADROCK HAM 3.3: Externalized maximum possible penalty for hitting a moving target. JA2 Default = 30.
|
||||
gGameExternalOptions.usMaxCTHPenaltyForMovingTarget = iniReader.ReadInteger("JA2 HAM Settings","MAX_CTH_PENALTY_FOR_MOVING_TARGET", 30, 0, 300);
|
||||
|
||||
// HEADROCK HAM 3.3: Increases tolerance while moving.
|
||||
gGameExternalOptions.ubTilesMovedPerBonusTolerancePoint = iniReader.ReadInteger("JA2 HAM Settings","TILES_MOVED_PER_BONUS_TOLERANCE_POINT", 5, 0, 20);
|
||||
|
||||
// HEADROCK HAM 3.3: New militia feature, Minimum Leadership required to train Roaming Militia
|
||||
gGameExternalOptions.ubMinimumLeadershipToTrainMobileMilitia = iniReader.ReadInteger("JA2 HAM Settings","MIN_LEADERSHIP_TO_TRAIN_MOBILE_MILITIA", 0, 0, 100);
|
||||
|
||||
// HEADROCK HAM 3.3: If enabled, the trainer's "effective" leadership skill determines HOW MANY Mobile Militia he/she creates per session.
|
||||
gGameExternalOptions.fLeadershipAffectsMobileMilitiaQuantity = iniReader.ReadBoolean("JA2 HAM Settings","LEADERSHIP_AFFECTS_MOBILE_MILITIA_QUANTITY", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.3: If "LEADERSHIP_AFFECTS_MILITIA_QUANTITY" is true, this value determines the lowest leadership required to train a full (default size 5) squad of Mobile Militia in one training session.
|
||||
gGameExternalOptions.ubReqLeadershipForFullMobileTraining = iniReader.ReadInteger("JA2 HAM Settings","REQ_LEADERSHIP_FOR_MAX_MOBILE_MILITIA", 1, 1, 100);
|
||||
|
||||
// HEADROCK HAM 3.3: Minimum distance (in METERS) at which character suffer from friendly suppression.
|
||||
gGameExternalOptions.usMinDistanceFriendlySuppression = iniReader.ReadInteger("JA2 HAM Settings","MIN_DISTANCE_FRIENDLY_SUPPRESSION", 30, 0, 65000);
|
||||
|
||||
// HEADROCK HAM 3.3: If enabled, Roaming Militia can automatically reinforce city garrisons.
|
||||
gGameExternalOptions.fAllowMobileReinforceCities = iniReader.ReadBoolean("JA2 HAM Settings","ALLOW_MOBILE_MILITIA_REINFORCE_TOWN_GARRISONS", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.3: If enabled, Roaming Militia can automatically reinforce city garrisons.
|
||||
gGameExternalOptions.fAllowMobileReinforceSAM = iniReader.ReadBoolean("JA2 HAM Settings","ALLOW_MOBILE_MILITIA_REINFORCE_SAM_GARRISONS", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.4: This controls the intensity of Hiding the Bullet Count during combat. The higher it is, the more intense the effect. Negative values reduce the effect.
|
||||
gGameExternalOptions.usBulletHideIntensity = iniReader.ReadInteger("JA2 HAM Settings","BULLET_HIDE_INTENSITY", 100, 0, 1000);
|
||||
|
||||
// HEADROCK HAM 3.4: What percentage of a new Mobile Militia group will be made of Elites? If >0, then at least one of every new group will be an Elite. 100 = All Elites.
|
||||
gGameExternalOptions.ubPercentRoamingMilitiaElites = iniReader.ReadInteger("JA2 HAM Settings","PERCENT_ROAMING_MILITIA_ELITES", 100, 0, 100);
|
||||
|
||||
// HEADROCK HAM 3.4: What percentage of a new Mobile Militia group will be made of Regulars? If >0, then at least one of every new group will be a Regular. 100 = All Regulars.
|
||||
gGameExternalOptions.ubPercentRoamingMilitiaRegulars = iniReader.ReadInteger("JA2 HAM Settings","PERCENT_ROAMING_MILITIA_REGULARS", 0, 0, 100);
|
||||
|
||||
// HEADROCK HAM 3.5: Does leadership affect the Quality of new Mobile Militia groups?
|
||||
gGameExternalOptions.fLeadershipAffectsMobileMilitiaQuality = iniReader.ReadBoolean("JA2 HAM Settings","LEADERSHIP_AFFECTS_MOBILE_MILITIA_QUALITY", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.5: Explosive Suppression Effectiveness alters the amount of Suppression Points you get from nearby blasts.
|
||||
gGameExternalOptions.usExplosionSuppressionEffect = iniReader.ReadInteger("JA2 HAM Settings","EXPLOSIVE_SUPPRESSION_EFFECTIVENESS", 100, 0, 1000);
|
||||
|
||||
// HEADROCK HAM 3.5: When enabled, goggle-switching affects every merc in the sector, not just those belonging to the current squad.
|
||||
gGameExternalOptions.fGoggleSwapAffectsAllMercsInSector = iniReader.ReadBoolean("JA2 HAM Settings","GOGGLE_SWAP_AFFECTS_ALL_MERCS_IN_SECTOR", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.5: Helicopter - Base cost per tile in "GREEN" airspace
|
||||
gGameExternalOptions.usHelicopterBaseCostPerGreenTile = iniReader.ReadInteger("JA2 HAM Settings","HELICOPTER_BASE_COST_PER_GREEN_TILE", 100, 0, 60000);
|
||||
|
||||
// HEADROCK HAM 3.5: Helicopter - Base cost per tile in "RED" airspace
|
||||
gGameExternalOptions.usHelicopterBaseCostPerRedTile = iniReader.ReadInteger("JA2 HAM Settings","HELICOPTER_BASE_COST_PER_RED_TILE", 1000, 0, 60000);
|
||||
|
||||
// HEADROCK HAM 3.5: Experimental, arrival sectorX/Y.
|
||||
gGameExternalOptions.ubDefaultArrivalSectorX = iniReader.ReadInteger("JA2 HAM Settings","DEFAULT_ARRIVAL_SECTOR_X", 9, 1, 16);
|
||||
gGameExternalOptions.ubDefaultArrivalSectorY = iniReader.ReadInteger("JA2 HAM Settings","DEFAULT_ARRIVAL_SECTOR_Y", 1, 1, 16);
|
||||
|
||||
// HEADROCK HAM 3.5: Limit bonus from tracers based on range to target. This is a multiplier factor - higher means harder to aim with tracers.
|
||||
gGameExternalOptions.ubRangeDifficultyAimingWithTracers = iniReader.ReadInteger("JA2 HAM Settings","RANGE_EFFECT_ON_MAX_TRACER_CTH_BONUS", 3, 1, 10);
|
||||
|
||||
// HEADROCK HAM 3.6: Militia can now place blue flags when they spot a landmine.
|
||||
gGameExternalOptions.fMilitiaPlaceBlueFlags = iniReader.ReadBoolean("JA2 HAM Settings","MILITIA_PLACE_FLAGS_ON_MINES", FALSE);
|
||||
|
||||
// HEADROCK PROFEX/3.6: Activate this to read Profile data from MercProfiles.XML and MercOpinions.XML
|
||||
gGameExternalOptions.fReadProfileDataFromXML = iniReader.ReadBoolean("JA2 HAM Settings","READ_PROFILE_DATA_FROM_XML", FALSE);
|
||||
|
||||
// HEADROCK PROFEX/3.6: Activate this to write Profile data to MercProfiles Out.XML and MercOpinions Out.XML. This can be used to convert PROF.DAT to XML format.
|
||||
gGameExternalOptions.fWriteProfileDataToXML = iniReader.ReadBoolean("JA2 HAM Settings","WRITE_PROFILE_DATA_TO_XML", FALSE);
|
||||
|
||||
// HEADROCK HAM 3.6: Progress bars for each stat, displayed behind the stat value on the merc panel. INI settings give RGB color, Menu setting toggles on/off.
|
||||
gGameExternalOptions.ubStatProgressBarsRed = iniReader.ReadInteger("JA2 HAM Settings","STAT_PROGRESS_BARS_RED", 200, 0, 255);
|
||||
gGameExternalOptions.ubStatProgressBarsGreen = iniReader.ReadInteger("JA2 HAM Settings","STAT_PROGRESS_BARS_GREEN", 0, 0, 255);
|
||||
gGameExternalOptions.ubStatProgressBarsBlue = iniReader.ReadInteger("JA2 HAM Settings","STAT_PROGRESS_BARS_BLUE", 0, 0, 255);
|
||||
|
||||
// HEADROCK HAM 3.6: Determines how likely a character is, every hour, to trigger a facility event. The actual chance is X in every Y attempts, where X is facility-specific, and Y is the value adjusted here.
|
||||
gGameExternalOptions.usFacilityEventRarity = iniReader.ReadInteger("JA2 HAM Settings","FACILITY_EVENT_RARITY", 1000, 0, 50000);
|
||||
// HEADROCK HAM 3.6: Controls how important the character's stats are, in insuring he/she gets better results (or smaller damage) from using facilities. The higher this is, the more dangerous all facilities are.
|
||||
gGameExternalOptions.ubFacilityDangerRate = iniReader.ReadInteger("JA2 HAM Settings","FACILITY_DANGER_RATE", 50, 0, 100);
|
||||
|
||||
// HEADROCK HAM 3.6: Determines whether the extrapolated daily costs of mercs are figured into the "Daily Expenses" display. 0 = No, just facility costs. 1 = Only mercs with a fixed daily rate. 2 = All mercs, including AIM contracts.
|
||||
gGameExternalOptions.ubIncludeContractsInExpenses = iniReader.ReadInteger("JA2 HAM Settings","INCLUDE_CONTRACTS_IN_EXPENSES_DISPLAY", 1, 0, 2);
|
||||
|
||||
// HEADROCK HAM 3.6: Maximum number of messages displayed in Tactical view
|
||||
gGameExternalOptions.ubMaxMessagesTactical = iniReader.ReadInteger("JA2 HAM Settings","MAXIMUM_MESSAGES_IN_TACTICAL", 6, 1, 36);
|
||||
switch (iResolution)
|
||||
{
|
||||
case 0:
|
||||
gGameExternalOptions.ubMaxMessagesTactical = __max(20, gGameExternalOptions.ubMaxMessagesTactical);
|
||||
break;
|
||||
case 1:
|
||||
gGameExternalOptions.ubMaxMessagesTactical = __max(26, gGameExternalOptions.ubMaxMessagesTactical);
|
||||
break;
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: Daily upkeep costs for militia
|
||||
gGameExternalOptions.usDailyCostTownGreen = iniReader.ReadInteger("JA2 HAM Settings","DAILY_MILITIA_UPKEEP_TOWN_GREEN", 0, 0, 10000);
|
||||
gGameExternalOptions.usDailyCostTownRegular = iniReader.ReadInteger("JA2 HAM Settings","DAILY_MILITIA_UPKEEP_TOWN_REGULAR", 0, 0, 10000);
|
||||
gGameExternalOptions.usDailyCostTownElite = iniReader.ReadInteger("JA2 HAM Settings","DAILY_MILITIA_UPKEEP_TOWN_ELITE", 0, 0, 10000);
|
||||
gGameExternalOptions.usDailyCostMobileGreen = iniReader.ReadInteger("JA2 HAM Settings","DAILY_MILITIA_UPKEEP_MOBILE_GREEN", 0, 0, 10000);
|
||||
gGameExternalOptions.usDailyCostMobileRegular = iniReader.ReadInteger("JA2 HAM Settings","DAILY_MILITIA_UPKEEP_MOBILE_REGULAR", 0, 0, 10000);
|
||||
gGameExternalOptions.usDailyCostMobileElite = iniReader.ReadInteger("JA2 HAM Settings","DAILY_MILITIA_UPKEEP_MOBILE_ELITE", 0, 0, 10000);
|
||||
|
||||
// HEADROCK HAM 3.6: Non-Combat Bodytypes shouldn't become hostile
|
||||
gGameExternalOptions.fCanTrueCiviliansBecomeHostile = iniReader.ReadBoolean("JA2 HAM Settings","CAN_TRUE_CIVILIANS_BECOME_HOSTILE", TRUE);
|
||||
|
||||
// HEADROCK HAM 3.6: Militia become hostile when attacked. 0 = No. 1 = If killed. 2 = If attacked (JA2 Default)
|
||||
gGameExternalOptions.ubCanMilitiaBecomeHostile = iniReader.ReadInteger("JA2 HAM Settings","CAN_MILITIA_BECOME_HOSTILE", 2, 0, 2);
|
||||
|
||||
// HEADROCK HAM 3.6: If activated, the game does not switch focus to a merc who spots an enemy in real-time mode. This fixes issues with Real-Time Sneak.
|
||||
gGameExternalOptions.fNoAutoFocusChangeInRealtimeSneak = iniReader.ReadBoolean("JA2 HAM Settings","NO_AUTO_FOCUS_CHANGE_IN_REALTIME_SNEAK", FALSE);
|
||||
}
|
||||
|
||||
INT16 DynamicAdjustAPConstants(INT16 iniReadValue, INT16 iniDefaultValue, BOOLEAN reverse)
|
||||
@@ -1259,6 +1429,15 @@ void LoadGameAPBPConstants()
|
||||
APBPConstants[AP_OPEN_ZIPPER] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_OPEN_ZIPPER",24),24);
|
||||
APBPConstants[AP_CLOSE_ZIPPER] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_CLOSE_ZIPPER",28),28);
|
||||
APBPConstants[AP_CLICK_AIM] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_CLICK_AIM",4),4);
|
||||
// HEADROCK HAM 3.1: Separate costs for each aiming click (when using a scope):
|
||||
APBPConstants[AP_FIRST_CLICK_AIM_SCOPE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_FIRST_CLICK_AIM_SCOPE",4),4);
|
||||
APBPConstants[AP_SECOND_CLICK_AIM_SCOPE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_SECOND_CLICK_AIM_SCOPE",4),4);
|
||||
APBPConstants[AP_THIRD_CLICK_AIM_SCOPE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_THIRD_CLICK_AIM_SCOPE",4),4);
|
||||
APBPConstants[AP_FOURTH_CLICK_AIM_SCOPE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_FOURTH_CLICK_AIM_SCOPE",4),4);
|
||||
APBPConstants[AP_FIFTH_CLICK_AIM_SCOPE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_FIFTH_CLICK_AIM_SCOPE",4),4);
|
||||
APBPConstants[AP_SIXTH_CLICK_AIM_SCOPE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_SIXTH_CLICK_AIM_SCOPE",4),4);
|
||||
APBPConstants[AP_SEVENTH_CLICK_AIM_SCOPE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_SEVENTH_CLICK_AIM_SCOPE",4),4);
|
||||
APBPConstants[AP_EIGHTTH_CLICK_AIM_SCOPE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_EIGHTTH_CLICK_AIM_SCOPE",4),4);
|
||||
APBPConstants[AUTOFIRE_SHOTS_AP_VALUE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AUTOFIRE_SHOTS_AP_VALUE",20),20);
|
||||
APBPConstants[BAD_AP_COST] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","BAD_AP_COST",36),36);
|
||||
APBPConstants[AP_RELOAD_LOOSE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_RELOAD_LOOSE",8),8);
|
||||
@@ -1268,6 +1447,10 @@ void LoadGameAPBPConstants()
|
||||
APBPConstants[AP_MIN_LIMIT] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_MIN_LIMIT",-100),-100);
|
||||
APBPConstants[AP_LOST_PER_MORALE_DROP] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_LOST_PER_MORALE_DROP",12),12);
|
||||
APBPConstants[AP_SUPPRESSION_MOD] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_SUPPRESSION_MOD",24),24);
|
||||
// HEADROCK HAM 3.5: Determines divisor for AP/Shock ratio. 100AP will have this set at 4, 25AP will have this set at 1.
|
||||
APBPConstants[AP_SUPPRESSION_SHOCK_DIVISOR] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_SUPPRESSION_SHOCK_DIVISOR",4),4);
|
||||
// HEADROCK HAM 3.2: Modifier for legshot AP loss based on damage
|
||||
APBPConstants[AP_LOSS_PER_LEGSHOT_DAMAGE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_LOSS_PER_LEGSHOT_DAMAGE",4),4);
|
||||
APBPConstants[DEFAULT_APS] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","DEFAULT_APS",80),80);
|
||||
APBPConstants[DEFAULT_AIMSKILL] = iniReader.ReadInteger("APConstants","DEFAULT_AIMSKILL",80);
|
||||
|
||||
|
||||
+212
-60
@@ -54,9 +54,14 @@ enum
|
||||
TOPTION_SILENT_SKYRIDER,
|
||||
TOPTION_LOW_CPU_USAGE,
|
||||
TOPTION_ENHANCED_DESC_BOX,
|
||||
|
||||
|
||||
// arynn
|
||||
TOPTION_TOGGLE_TURN_MODE,
|
||||
TOPTION_TOGGLE_TURN_MODE,
|
||||
|
||||
// HEADROCK HAM 3.6:
|
||||
TOPTION_STAT_PROGRESS_BARS,
|
||||
|
||||
// arynn: Debug/Cheat
|
||||
TOPTION_CHEAT_MODE_OPTIONS_HEADER,
|
||||
TOPTION_FORCE_BOBBY_RAY_SHIPMENTS, // force all pending Bobby Ray shipments
|
||||
TOPTION_CHEAT_MODE_OPTIONS_END,
|
||||
@@ -80,7 +85,6 @@ enum
|
||||
TOPTION_HIDE_BULLETS,
|
||||
TOPTION_TRACKING_MODE,
|
||||
|
||||
|
||||
NUM_ALL_GAME_OPTIONS,
|
||||
};
|
||||
|
||||
@@ -276,9 +280,10 @@ typedef struct
|
||||
UINT32 guiTrainVeteranMilitiaDelay;
|
||||
UINT32 guiCreateEachNHours;
|
||||
UINT32 guiDivOfOriginalMilitia;
|
||||
UINT32 guiMinMilitiaSquadSize;
|
||||
UINT32 guiMaxMilitiaSquadSize;
|
||||
UINT32 guiMaxMilitiaSquadSizeBattle;
|
||||
// HEADROCK HAM 3.6: These settings are REDUNDANT.
|
||||
//UINT32 guiMinMilitiaSquadSize;
|
||||
//UINT32 guiMaxMilitiaSquadSize;
|
||||
//UINT32 guiMaxMilitiaSquadSizeBattle;
|
||||
|
||||
//BOOLEAN gfAllowSoldierToolTips; // moved to prefereces - SANDRO
|
||||
|
||||
@@ -419,9 +424,11 @@ typedef struct
|
||||
INT32 ubTrainingSkillMax;
|
||||
INT32 ubSelfTrainingDivisor;
|
||||
INT32 ubInstructedTrainingDivisor;
|
||||
INT32 ubGunRangeTrainingBonus;
|
||||
// HEADROCK HAM 3.5: No longer necessary.
|
||||
//INT32 ubGunRangeTrainingBonus;
|
||||
INT32 ubTownMilitiaTrainingRate;
|
||||
INT32 ubMaxMilitiaTrainersPerSector;
|
||||
// HEADROCK HAM 3.5: No longer necessary.
|
||||
//INT32 ubMaxMilitiaTrainersPerSector;
|
||||
INT32 ubTeachBonusToTrain;
|
||||
INT32 ubRpcBonusToTrainMilitia;
|
||||
INT32 ubMinSkillToTeach;
|
||||
@@ -502,7 +509,7 @@ BOOLEAN gbBulletTracer;
|
||||
|
||||
// HEADROCK: Enhanced Item Description Box ON/OFF
|
||||
// WANNE: Changed from BOOLEAN to INT32!
|
||||
INT32 fEnhancedDescriptionBox;
|
||||
INT32 iEnhancedDescriptionBox;
|
||||
|
||||
// WANNE: Always use "prof.dat".
|
||||
BOOLEAN fAlwaysUseProfDat;
|
||||
@@ -518,58 +525,46 @@ BOOLEAN gbBulletTracer;
|
||||
UINT8 ubCoverDisplayUpdateWait;
|
||||
|
||||
// HEADROCK HAM B1: Global modifier for mine income (0 is automatically turned to 1 to avoid divide-by-zero.)
|
||||
INT16 iMineIncomePercentage;
|
||||
INT16 usMineIncomePercentage;
|
||||
|
||||
// HEADROCK HAM B1: Allows changing the maximum CTH possible, for any attack 0-100
|
||||
UINT8 iMaximumCTH;
|
||||
UINT8 ubMaximumCTH;
|
||||
|
||||
// HEADROCK HAM B1: Allows changing the minimum CTH possible, for any attack 0-100
|
||||
UINT8 iMinimumCTH;
|
||||
UINT8 ubMinimumCTH;
|
||||
|
||||
// HEADROCK HAM B1: Allows reducing the chance of scoring a hit fractionally, if CTH = Minimum CTH
|
||||
UINT8 iMinimumCTHDivisor;
|
||||
UINT16 usMinimumCTHDivisor;
|
||||
|
||||
// HEADROCK HAM B1: Allows Restricted Roaming Militia to move through previously visited sectors, even if restricted.
|
||||
BOOLEAN bUnrestrictVisited;
|
||||
BOOLEAN fUnrestrictVisited;
|
||||
|
||||
// HEADROCK HAM B1: Allows the capture of towns to dynamically alter roaming restrictions
|
||||
BOOLEAN bDynamicRestrictRoaming;
|
||||
|
||||
// HEADROCK HAM B2: Reset suppression counter. 0 = never (oldskool), 1 = Every turn, 2 = Every attack.
|
||||
UINT8 iClearSuppression;
|
||||
BOOLEAN fDynamicRestrictRoaming;
|
||||
|
||||
// HEADROCK HAM B2.1: This controls how effective suppression is, by increasing the number of ubSuppressionPoints accumulated by combatants (percentage);
|
||||
INT16 iSuppressionEffectiveness;
|
||||
INT16 sSuppressionEffectiveness;
|
||||
|
||||
// HEADROCK HAM B2: MAXIMUM number of APs that can be lost to suppression in a given turn (0=unlimited)
|
||||
BOOLEAN fSuppressionAPLossPerTurn;
|
||||
|
||||
// HEADROCK HAM B2: MAXIMUM number of APs that can be lost to suppression in a given attack (0=unlimited)
|
||||
BOOLEAN fSuppressionAPLossPerAttack;
|
||||
|
||||
UINT8 iSuppressionToleranceMax;
|
||||
UINT8 iSuppressionToleranceMin;
|
||||
|
||||
// HEADROCK HAM B2: Suppression Shock ON/OFF
|
||||
BOOLEAN fSuppressionShock;
|
||||
UINT8 ubSuppressionToleranceMax;
|
||||
UINT8 ubSuppressionToleranceMin;
|
||||
|
||||
// HEADROCK HAM B2: Suppression Shock effectiveness (percentage, 100 = "normal", 0 = deactivated. Range 0-65535)
|
||||
UINT16 iSuppressionShockEffectiveness;
|
||||
UINT16 usSuppressionShockEffect;
|
||||
|
||||
// HEADROCK HAM B2.1: CTH penalty given by a "Cowering" target to any enemy shooter.
|
||||
INT8 iAimPenaltyPerTargetShock;
|
||||
UINT8 ubAimPenaltyPerTargetShock;
|
||||
|
||||
// HEADROCK HAM B2.3: It is now possible for "cowering" to increase a target's suppression.
|
||||
UINT16 iCowerEffectOnSuppression;
|
||||
UINT16 usCowerEffectOnSuppression;
|
||||
|
||||
// HEADROCK HAM B2.5: Turn on Realistic Tracers. 0 = off (regular tracers). 1 = Fully realistic tracers. 2 = Tracer Bump + 1.13 Autofire Penalty Reduction
|
||||
UINT8 iRealisticTracers;
|
||||
UINT8 ubRealisticTracers;
|
||||
|
||||
// HEADROCK HAM B2.5: Realistic tracers - one of every X bullets in a tracer magazines will be a tracer bullet. 0 = off (JA2 normal)
|
||||
UINT8 iNumBulletsPerTracer;
|
||||
UINT8 ubNumBulletsPerTracer;
|
||||
|
||||
// HEADROCK HAM B2.5: Realistic tracers - CTH increased by this amount whenever a tracer is fired. 0 = off.
|
||||
INT16 iCTHBumpPerTracer;
|
||||
UINT8 ubCTHBumpPerTracer;
|
||||
|
||||
// HEADROCK HAM B2.6: Increased aiming costs?
|
||||
BOOLEAN fIncreasedAimingCost;
|
||||
@@ -581,32 +576,32 @@ BOOLEAN gbBulletTracer;
|
||||
FLOAT iMovementEffectOnAiming;
|
||||
|
||||
// HEADROCK HAM B2.6: Autofire Bullets/5AP modifier
|
||||
INT16 iAutofireBulletsPer5APModifier;
|
||||
INT8 bAutofireBulletsPer5APModifier;
|
||||
|
||||
// HEADROCK HAM B2.6/B1: Adjustable "luck" factor in Auto-Resolve
|
||||
FLOAT iAutoResolveLuckFactor;
|
||||
|
||||
// HEADROCK HAM B2.6: Adjustable maximum for Suppression Shock effect. This has the added effect of reducing overall susceptibility to shock and may render some enemies unshockable.
|
||||
UINT8 iMaxSuppressionShock;
|
||||
UINT8 ubMaxSuppressionShock;
|
||||
|
||||
// HEADROCK HAM B2.6/2/1: Toggle new Burst/Auto CTH bars: 0=neither, 1=both, 2=Burst, 3=Auto
|
||||
UINT8 iNewCTHBars;
|
||||
UINT8 ubNewCTHBars;
|
||||
|
||||
// HEADROCK HAM B2.6: Toggle whether AI checks for larger magazine when wanting to suppress at a distance
|
||||
BOOLEAN fIncreaseAISuppressionFire;
|
||||
|
||||
// HEADROCK HAM B2.7: Change the speed of skill progression. (defaults set to JA2 normal)
|
||||
UINT16 ubHealthSubpointsToImprove;
|
||||
UINT16 ubStrengthSubpointsToImprove;
|
||||
UINT16 ubDexteritySubpointsToImprove;
|
||||
UINT16 ubAgilitySubpointsToImprove;
|
||||
UINT16 ubWisdomSubpointsToImprove;
|
||||
UINT16 ubMarksmanshipSubpointsToImprove;
|
||||
UINT16 ubMedicalSubpointsToImprove;
|
||||
UINT16 ubMechanicalSubpointsToImprove;
|
||||
UINT16 ubExplosivesSubpointsToImprove;
|
||||
UINT16 ubLeadershipSubpointsToImprove;
|
||||
UINT16 ubLevelSubpointsToImprove;
|
||||
UINT16 usHealthSubpointsToImprove;
|
||||
UINT16 usStrengthSubpointsToImprove;
|
||||
UINT16 usDexteritySubpointsToImprove;
|
||||
UINT16 usAgilitySubpointsToImprove;
|
||||
UINT16 usWisdomSubpointsToImprove;
|
||||
UINT16 usMarksmanshipSubpointsToImprove;
|
||||
UINT16 usMedicalSubpointsToImprove;
|
||||
UINT16 usMechanicalSubpointsToImprove;
|
||||
UINT16 usExplosivesSubpointsToImprove;
|
||||
UINT16 usLeadershipSubpointsToImprove;
|
||||
UINT16 usLevelSubpointsToImprove;
|
||||
|
||||
// HEADROCK HAM B2.7: When turned on, this will give a CTH approximation instead of an exact value, on CTH Bars and "F" key feedback.
|
||||
BOOLEAN fApproximateCTH;
|
||||
@@ -614,15 +609,6 @@ BOOLEAN gbBulletTracer;
|
||||
// HEADROCK HAM B2.7: Augmented Roaming Militia code - turn this to TRUE to allow militia free travel through San Mona, Tixa, Orta, Omerta, and Estoni.
|
||||
BOOLEAN fAllowMilitiaMoveThroughMinorCities;
|
||||
|
||||
// HEADROCK HAM B2.7: Smarter Roaming Militia Generator will generate Roamers in any available city perimeter square, allowing us to avoid "wasting" training sessions more easily.
|
||||
BOOLEAN fSmartRoamingMilitiaGenerator;
|
||||
|
||||
// HEADROCK HAM B2.7: When "TRUE", Roaming Militia will be created on a 25% Veteran, 25% Regular, 50% green basis. If new militia is placed into a full group, it will upgrade greens/regulars in that group.
|
||||
BOOLEAN fDiverseRoamingMilitiaGroups;
|
||||
|
||||
// HEADROCK HAM B2.8: This setting controls whether militia will try to join up into the largest groups they can, or average out the size of the groups to cover more territory.
|
||||
UINT8 ubRoamingMilitiaSpreadsOutChance;
|
||||
|
||||
// HEADROCK HAM B2.8: These are new cowering penalty divisors that help us determine how effective cowering is in different stances and when the shooter is targetting different bodyparts
|
||||
UINT8 ubCoweringPenaltyDivisorProne;
|
||||
UINT8 ubCoweringPenaltyDivisorCrouchedHead;
|
||||
@@ -648,9 +634,175 @@ BOOLEAN gbBulletTracer;
|
||||
// HEADROCK HAM B2.8: New Trainer Relations: 2 = Trainers will rest if no trainees available. 3 = Trainees will rest if no trainers available (not recommended). 1 = Both. 0 = Neither.
|
||||
UINT8 ubSmartTrainingRest;
|
||||
|
||||
// HEADROCK HAM 3: Show Tooltips from Attachments in Bobby Rays shop=
|
||||
// HEADROCK HAM 3: Externalized ratio between Weight and Strength. This value determines how many strength points we need to lift 0.5kg with no encumberance.
|
||||
FLOAT iStrengthToLiftHalfKilo;
|
||||
|
||||
// HEADROCK HAM 3: Define minimum leadership required for training militia. Set to 0 for "no limit".
|
||||
UINT8 ubMinimumLeadershipToTrainMilitia;
|
||||
|
||||
// HEADROCK HAM 3: Define effect of "TEACHER" trait in increasing effective leadership, for purposes of eligibility for training militia
|
||||
UINT16 usTeacherTraitEffectOnLeadership;
|
||||
|
||||
// HEADROCK HAM 3: If enabled, the trainer's "effective" leadership skill determines HOW MANY militia he/she creates per session (only works in town militia training).
|
||||
BOOLEAN fLeadershipAffectsMilitiaQuantity;
|
||||
|
||||
// HEADROCK HAM 3: If "LEADERSHIP_AFFECTS_MILITIA_QUANTITY" is true, this value determines the lowest leadership required to train a full (default size 10) squad of town militia in one training session.
|
||||
UINT8 ubReqLeadershipForFullTraining;
|
||||
|
||||
// HEADROCK HAM 3: Four INI settings to control the number of kills you must accumulate to win one progress point, one setting per difficulty level
|
||||
UINT16 usNumKillsPerProgressPointNovice;
|
||||
UINT16 usNumKillsPerProgressPointExperienced;
|
||||
UINT16 usNumKillsPerProgressPointExpert;
|
||||
UINT16 usNumKillsPerProgressPointInsane;
|
||||
|
||||
// HEADROCK HAM 3: If enabled, changes the way the game calculates progress. It will look at each progress control separately (Kills/Income/Control/Visited) and set the progress to the HIGHEST scoring control.
|
||||
BOOLEAN fAlternateProgressCalculation;
|
||||
|
||||
// HEADROCK HAM 3: If enabled, tooltipping over Bobby Ray's weapons will show a list of possible attachments to those weapons.
|
||||
BOOLEAN fBobbyRayTooltipsShowAttachments;
|
||||
|
||||
// HEADROCK HAM 3.1: Divisor for the AP-to-Ready cost charge on first aiming click, when extra aiming costs are enabled. 0 = No ready-time-based charge.
|
||||
UINT8 ubFirstAimReadyCostDivisor;
|
||||
|
||||
// HEADROCK HAM 3.1: This is a suppression tool that not everyone will like. It gives an on-screen message when any character has been suppressed so much he's lost his next turn completely!
|
||||
BOOLEAN fShowSuppressionShutdown;
|
||||
|
||||
// HEADROCK HAM 3.1: Set whether you'd like to determine yourself which mine (if any) will shut down during the campaign.
|
||||
BOOLEAN fManuallySelectMineShutdown;
|
||||
|
||||
// HEADROCK HAM 3.1: Select which mine will run out. 0 = no mine. 1 = San Mona (unused), 2 = Drassen, 3 = Alma, 4 = Cambria, 5 = Chitzena, 6 = Grumm.
|
||||
UINT8 ubWhichMineRunsOut;
|
||||
|
||||
// HEADROCK HAM 3.1: Can the Humvee go off-road?
|
||||
BOOLEAN fHumveeOffroad;
|
||||
|
||||
// HEADROCK HAM 3.2: If activated, reinforcements (militia/enemy) arrive in the battle with 0 APs. This makes them less of a diablo-ex-machina.
|
||||
UINT8 ubReinforcementsFirstTurnFreeze;
|
||||
|
||||
// HEADROCK HAM 3.2: This feature allows the status, leadership and experience of nearby friendlies help/hinder a character's tolerance, based on their distance from him.
|
||||
BOOLEAN fFriendliesAffectTolerance;
|
||||
|
||||
// HEADROCK HAM 3.2: Set a divisor for the CtH of Mortar weapons.
|
||||
UINT8 ubMortarCTHDivisor;
|
||||
|
||||
// HEADROCK HAM 3.2: This enabled reduced sight for cowering characters. 0 = disabled. 2 = Reduced Sightrange. 3 = Tunnel-vision. 1 = Both.
|
||||
UINT8 ubCoweringReducesSightRange;
|
||||
|
||||
// HEADROCK HAM 3.2: Critical Headshots may cause blindness. Rolls 1 to X change of being blinded. 0 = disabled.
|
||||
UINT8 ubChanceBlindedByHeadshot;
|
||||
|
||||
// HEADROCK HAM 3.2: Critical Legshots cause additional AP loss
|
||||
BOOLEAN fCriticalLegshotCausesAPLoss;
|
||||
|
||||
// HEADROCK HAM 3.2: When enabled, this setting removes the player's omniscience inside his own sectors. The player will no longer see the movement of enemy groups unless someone is nearby to scout them.
|
||||
BOOLEAN fNoEnemyDetectionWithoutRecon;
|
||||
|
||||
// HEADROCK HAM 3.2: Determines the training bonus for the Medical skill, when training in "hospital" sectors
|
||||
UINT8 ubHospitalTrainingBonus;
|
||||
|
||||
// HEADROCK HAM 3.2: Determines the repaid bonus when training in factory ("industrial") sectors
|
||||
UINT8 ubFactoryRepairBonus;
|
||||
|
||||
// HEADROCK HAM 3.2: How much MECHANICAL skill do we need to gain a repair bonus from a factory?
|
||||
UINT8 ubMinMechanicalForFactoryRepairBonus;
|
||||
|
||||
// HEADROCK HAM 3.3: Externalized maximum possible penalty for hitting a moving target. JA2 Default = 30.
|
||||
UINT16 usMaxCTHPenaltyForMovingTarget;
|
||||
|
||||
// HEADROCK HAM 3.3: Increases tolerance while moving.
|
||||
UINT8 ubTilesMovedPerBonusTolerancePoint;
|
||||
|
||||
// HEADROCK HAM 3.3: New militia feature, Minimum Leadership required to train Roaming Militia
|
||||
UINT8 ubMinimumLeadershipToTrainMobileMilitia;
|
||||
|
||||
// HEADROCK HAM 3.3: If enabled, the trainer's "effective" leadership skill determines HOW MANY militia he/she creates per session.
|
||||
BOOLEAN fLeadershipAffectsMobileMilitiaQuantity;
|
||||
|
||||
// HEADROCK HAM 3.3: If "LEADERSHIP_AFFECTS_MILITIA_QUANTITY" is true, this value determines the lowest leadership required to train a full (default size 10) squad of town militia in one training session.
|
||||
UINT8 ubReqLeadershipForFullMobileTraining;
|
||||
|
||||
// HEADROCK HAM 3.3: Minimum distance (in METERS) at which character suffer from friendly suppression.
|
||||
UINT16 usMinDistanceFriendlySuppression;
|
||||
|
||||
// HEADROCK HAM 3.3: If enabled, Roaming Militia can automatically reinforce city garrisons.
|
||||
BOOLEAN fAllowMobileReinforceCities;
|
||||
|
||||
// HEADROCK HAM 3.3: If enabled, Roaming Militia can automatically reinforce city garrisons.
|
||||
BOOLEAN fAllowMobileReinforceSAM;
|
||||
|
||||
// HEADROCK HAM 3.4: This controls the intensity of Hiding the Bullet Count during combat. The higher it is, the more intense the effect. Negative values reduce the effect.
|
||||
UINT16 usBulletHideIntensity;
|
||||
|
||||
// HEADROCK HAM 3.4: What percentage of a new Mobile Militia group will be made of Elites? If >0, then at least one of every group will be an Elite. 100 = All Elites.
|
||||
UINT8 ubPercentRoamingMilitiaElites;
|
||||
|
||||
// HEADROCK HAM 3.4: What percentage of a new Mobile Militia group will be made of Elites? If >0, then at least one of every group will be an Elite. 100 = All Elites.
|
||||
UINT8 ubPercentRoamingMilitiaRegulars;
|
||||
|
||||
// HEADROCK HAM 3.5: Does leadership affect the Quality of new Mobile Militia groups?
|
||||
BOOLEAN fLeadershipAffectsMobileMilitiaQuality;
|
||||
|
||||
// HEADROCK HAM 3.5: Explosive Suppression Effectiveness alters the amount of Suppression Points you get from nearby blasts.
|
||||
UINT16 usExplosionSuppressionEffect;
|
||||
|
||||
// HEADROCK HAM 3.5: When enabled, goggle-switching affects every merc in the sector, not just those belonging to the current squad.
|
||||
BOOLEAN fGoggleSwapAffectsAllMercsInSector;
|
||||
|
||||
// HEADROCK HAM 3.5: Helicopter - Base cost per tile in "GREEN" airspace
|
||||
UINT16 usHelicopterBaseCostPerGreenTile;
|
||||
|
||||
// HEADROCK HAM 3.5: Helicopter - Base cost per tile in "RED" airspace
|
||||
UINT16 usHelicopterBaseCostPerRedTile;
|
||||
|
||||
// HEADROCK HAM 3.5: Experimental, arrival sectorX/Y.
|
||||
UINT8 ubDefaultArrivalSectorX;
|
||||
UINT8 ubDefaultArrivalSectorY;
|
||||
|
||||
// HEADROCK HAM 3.5: Limit bonus from tracers based on range to target. This is a divisor for the effect.
|
||||
UINT8 ubRangeDifficultyAimingWithTracers;
|
||||
|
||||
// HEADROCK HAM 3.6: Militia can now place flags on discovered mines.
|
||||
BOOLEAN fMilitiaPlaceBlueFlags;
|
||||
|
||||
// HEADROCK PROFEX: Activate this to read Profile data from Profiles.XML and Opinions.XML
|
||||
BOOLEAN fReadProfileDataFromXML;
|
||||
|
||||
// HEADROCK PROFEX: Activate this to read Profile data from Profiles.XML and Opinions.XML
|
||||
BOOLEAN fWriteProfileDataToXML;
|
||||
|
||||
// HEADROCK HAM 3.6: Progress bars for each stat, displayed behind the stat value on the merc panel.
|
||||
UINT8 ubStatProgressBarsRed;
|
||||
UINT8 ubStatProgressBarsGreen;
|
||||
UINT8 ubStatProgressBarsBlue;
|
||||
|
||||
// HEADROCK HAM 3.6: Determines how likely a character is, every hour, to trigger a facility event. The actual chance is X in every Y attempts, where X is facility-specific, and Y is the value adjusted here.
|
||||
UINT16 usFacilityEventRarity;
|
||||
// HEADROCK HAM 3.6: Controls how important the character's stats are, in insuring he/she gets better results (or smaller damage) from using facilities. The higher this is, the more dangerous all facilities are.
|
||||
UINT8 ubFacilityDangerRate;
|
||||
|
||||
// HEADROCK HAM 3.6: Determines whether the extrapolated daily costs of mercs are figured into the "Daily Expenses" display. 0 = No, just facility costs. 1 = Only mercs with a fixed daily rate. 2 = All mercs, including AIM contracts.
|
||||
UINT8 ubIncludeContractsInExpenses;
|
||||
|
||||
// HEADROCK HAM 3.6: Maximum number of messages displayed in Tactical view
|
||||
UINT8 ubMaxMessagesTactical;
|
||||
|
||||
// HEADROCK HAM 3.6: Daily upkeep costs for militia
|
||||
UINT16 usDailyCostTownGreen;
|
||||
UINT16 usDailyCostTownRegular;
|
||||
UINT16 usDailyCostTownElite;
|
||||
UINT16 usDailyCostMobileGreen;
|
||||
UINT16 usDailyCostMobileRegular;
|
||||
UINT16 usDailyCostMobileElite;
|
||||
|
||||
// HEADROCK HAM 3.6: Non-Combat Bodytypes can't become hostile
|
||||
BOOLEAN fCanTrueCiviliansBecomeHostile;
|
||||
|
||||
// HEADROCK HAM 3.6: Militia become hostile when attacked. 0 = No. 1 = If killed. 2 = If attacked (JA2 Default)
|
||||
UINT8 ubCanMilitiaBecomeHostile;
|
||||
|
||||
// HEADROCK HAM 3.6: If activated, the game does not switch focus to a merc who spots an enemy in real-time mode. This fixes issues with Real-Time Sneak.
|
||||
BOOLEAN fNoAutoFocusChangeInRealtimeSneak;
|
||||
|
||||
// The_Bob - real time sneaking code 01/06/09
|
||||
// Suport disabling/silencing real time sneaking via external .ini file
|
||||
BOOLEAN fAllowRealTimeSneak;
|
||||
|
||||
+4
-4
@@ -13,12 +13,12 @@
|
||||
#ifdef JA2EDITOR
|
||||
|
||||
//MAP EDITOR BUILD VERSION
|
||||
CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.3023" };
|
||||
CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.3322" };
|
||||
|
||||
#elif defined JA2BETAVERSION
|
||||
|
||||
//BETA/TEST BUILD VERSION
|
||||
CHAR16 zVersionLabel[256] = { L"Debug v1.13.3287" };
|
||||
CHAR16 zVersionLabel[256] = { L"Debug v1.13.3322" };
|
||||
|
||||
#elif defined CRIPPLED_VERSION
|
||||
|
||||
@@ -28,11 +28,11 @@ CHAR16 zVersionLabel[256] = { L"Beta v. 0.98" };
|
||||
#else
|
||||
|
||||
//RELEASE BUILD VERSION
|
||||
CHAR16 zVersionLabel[256] = { L"Release v1.13.3287" };
|
||||
CHAR16 zVersionLabel[256] = { L"Release v1.13.3322" };
|
||||
|
||||
#endif
|
||||
|
||||
CHAR8 czVersionNumber[16] = { "Build 09.10.23" }; //YY.MM.DD
|
||||
CHAR8 czVersionNumber[16] = { "Build 10.02.20" }; //YY.MM.DD
|
||||
CHAR16 zTrackingNumber[16] = { L"Z" };
|
||||
|
||||
|
||||
|
||||
@@ -524,6 +524,57 @@ BOOLEAN LoadExternalGameplayData(STR directoryName)
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName));
|
||||
THROWIFFALSE(ReadInDeliveryMethods(fileName),DELIVERYMETHODSFILENAME);
|
||||
|
||||
// HEADROCK HAM 3.5: Read in facility types
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, FACILITYTYPESFILENAME);
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName));
|
||||
THROWIFFALSE(ReadInFacilityTypes(fileName), FACILITYTYPESFILENAME);
|
||||
|
||||
// HEADROCK HAM 3.4: Read in facility locations
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, SECTORFACILITIESFILENAME);
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName));
|
||||
THROWIFFALSE(ReadInSectorFacilities(fileName), SECTORFACILITIESFILENAME);
|
||||
|
||||
// HEADROCK HAM 3.4: Read in dynamic roaming restrictions
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, DYNAMICROAMINGFILENAME);
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName));
|
||||
THROWIFFALSE(ReadInDynamicRoamingRestrictions(fileName), DYNAMICROAMINGFILENAME);
|
||||
|
||||
// HEADROCK HAM 3.6: Read in customized sector names
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, SECTORNAMESFILENAME);
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName));
|
||||
THROWIFFALSE(ReadInSectorNames(fileName), SECTORNAMESFILENAME);
|
||||
|
||||
if (gGameExternalOptions.fReadProfileDataFromXML)
|
||||
{
|
||||
// HEADROCK PROFEX: Read in Merc Profile data to replace PROF.DAT data
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, MERCPROFILESFILENAME);
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName));
|
||||
THROWIFFALSE(ReadInMercProfiles(fileName), MERCPROFILESFILENAME);
|
||||
|
||||
// HEADROCK PROFEX: Read in Merc Opinion data to replace PROF.DAT data
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, MERCOPINIONSFILENAME);
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName));
|
||||
THROWIFFALSE(ReadInMercOpinions(fileName), MERCOPINIONSFILENAME);
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: Read in customized Bloodcat Placements
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, BLOODCATPLACEMENTSFILENAME);
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName));
|
||||
THROWIFFALSE(ReadInBloodcatPlacements(fileName), BLOODCATPLACEMENTSFILENAME);
|
||||
|
||||
// HEADROCK HAM 3.6: Read in customized Uniform Colors
|
||||
strcpy(fileName, directoryName);
|
||||
strcat(fileName, UNIFORMCOLORSFILENAME);
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("LoadExternalGameplayData, fileName = %s", fileName));
|
||||
THROWIFFALSE(ReadInUniforms(fileName), UNIFORMCOLORSFILENAME);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,15 @@ AP_BACK_PACK,
|
||||
AP_OPEN_ZIPPER,
|
||||
AP_CLOSE_ZIPPER,
|
||||
AP_CLICK_AIM,
|
||||
// HEADROCK HAM 3.1: Eight different settings for each aiming click with a scope.
|
||||
AP_FIRST_CLICK_AIM_SCOPE,
|
||||
AP_SECOND_CLICK_AIM_SCOPE,
|
||||
AP_THIRD_CLICK_AIM_SCOPE,
|
||||
AP_FOURTH_CLICK_AIM_SCOPE,
|
||||
AP_FIFTH_CLICK_AIM_SCOPE,
|
||||
AP_SIXTH_CLICK_AIM_SCOPE,
|
||||
AP_SEVENTH_CLICK_AIM_SCOPE,
|
||||
AP_EIGHTTH_CLICK_AIM_SCOPE,
|
||||
AP_RELOAD_LOOSE,
|
||||
AP_UNJAM,
|
||||
AP_WRONG_MAG,
|
||||
@@ -94,6 +103,10 @@ AP_MAX_TURN_SUPPRESSED,
|
||||
AP_MIN_LIMIT,
|
||||
AP_LOST_PER_MORALE_DROP,
|
||||
AP_SUPPRESSION_MOD,
|
||||
// HEADROCK HAM 3.5: Ratio of AP loss to Suppression Shock gain.
|
||||
AP_SUPPRESSION_SHOCK_DIVISOR,
|
||||
// HEADROCK HAM 3.3: AP loss per point of damage, inflicted when a character is knocked down by a hit to the legs.
|
||||
AP_LOSS_PER_LEGSHOT_DAMAGE,
|
||||
AUTOFIRE_SHOTS_AP_VALUE,
|
||||
BAD_AP_COST,
|
||||
DEFAULT_APS,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "Text.h"
|
||||
#include "aimsort.h"
|
||||
#include "Assignments.h"
|
||||
#include "GameSettings.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -98,7 +99,15 @@ BOOLEAN EnterAimFacialIndex()
|
||||
MSYS_AddRegion( &gMercFaceMouseRegions[ i ] );
|
||||
MSYS_SetRegionUserData( &gMercFaceMouseRegions[ i ], 0, i);
|
||||
|
||||
sprintf(sTemp, "%s%02d.sti", sFaceLoc, AimMercArray[i]);
|
||||
if (gGameExternalOptions.fReadProfileDataFromXML)
|
||||
{
|
||||
// HEADROCK PROFEX: Do not read direct profile number, instead, look inside the profile for a ubFaceIndex value.
|
||||
sprintf(sTemp, "%s%02d.sti", sFaceLoc, gMercProfiles[AimMercArray[i]].ubFaceIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sTemp, "%s%02d.sti", sFaceLoc, AimMercArray[i]);
|
||||
}
|
||||
VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE;
|
||||
FilenameForBPP(sTemp, VObjectDesc.ImageFile);
|
||||
if( !AddVideoObject(&VObjectDesc, &guiAimFiFace[i]) )
|
||||
|
||||
@@ -1432,7 +1432,15 @@ BOOLEAN DisplayMercsFace()
|
||||
BltVideoObject(FRAME_BUFFER, hPortraitHandle, 0,PORTRAIT_X, PORTRAIT_Y, VO_BLT_SRCTRANSPARENCY,NULL);
|
||||
|
||||
// load the Face graphic and add it
|
||||
sprintf(sTemp, "%s%02d.sti", sFaceLoc, gbCurrentSoldier);
|
||||
if (gGameExternalOptions.fReadProfileDataFromXML)
|
||||
{
|
||||
// HEADROCK PROFEX: Do not read direct profile number, instead, look inside the profile for a ubFaceIndex value.
|
||||
sprintf(sTemp, "%s%02d.sti", sFaceLoc, gMercProfiles[gbCurrentSoldier].ubFaceIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sTemp, "%s%02d.sti", sFaceLoc, gbCurrentSoldier);
|
||||
}
|
||||
VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE;
|
||||
FilenameForBPP(sTemp, VObjectDesc.ImageFile);
|
||||
CHECKF(AddVideoObject(&VObjectDesc, &guiFace));
|
||||
|
||||
@@ -604,7 +604,9 @@ void HandleBeginScreenTextEvent( UINT32 uiKey )
|
||||
uiKey >= 'a' && uiKey <= 'z' ||
|
||||
uiKey >= '0' && uiKey <= '9' ||
|
||||
uiKey == '_' || uiKey == '.' ||
|
||||
uiKey == ' ' )
|
||||
uiKey == ' ' || uiKey == '"' ||
|
||||
uiKey == 39 // This is ' which cannot be written explicitly here of course
|
||||
)
|
||||
#else
|
||||
if( charSet::IsFromSet( uiKey, charSet::CS_SPACE|charSet::CS_ALPHA_NUM|charSet::CS_SPECIAL_ALPHA ) )
|
||||
#endif
|
||||
|
||||
@@ -222,7 +222,7 @@ public:
|
||||
UINT16 RemoveDestination(UINT16 usDestinationID);
|
||||
RefToDestinationStruct GetDestination(UINT16 usDestinationID) const;
|
||||
RefToDestinationList LookupDestinationList(void) const;
|
||||
|
||||
|
||||
// WANNE:
|
||||
BOOLEAN IsSectorAShipmentSector(UINT8 ubMapX, UINT8 ubMapY, UINT8 ubMapZ);
|
||||
|
||||
|
||||
+21
-4
@@ -15,6 +15,9 @@
|
||||
#include "cursors.h"
|
||||
#include "email.h"
|
||||
#include "text.h"
|
||||
// HEADROCK PROFEX: This is required to display the proper facial image.
|
||||
#include "Soldier Profile.h"
|
||||
#include "GameSettings.h"
|
||||
#endif
|
||||
|
||||
#define TOP_X LAPTOP_SCREEN_UL_X
|
||||
@@ -1759,16 +1762,30 @@ BOOLEAN HandleSpecialTerroristFile( INT32 iFileNumber, STR sPictureName )
|
||||
// show picture
|
||||
if( ( giFilesPage == 0 ) && ( iCounter == 5 ) )
|
||||
{
|
||||
if( usProfileIdsForTerroristFiles[ iFileNumber + 1 ] < 100 )
|
||||
if (gGameExternalOptions.fReadProfileDataFromXML)
|
||||
{
|
||||
sprintf(sTemp, "%s%02d.sti", "FACES\\BIGFACES\\", usProfileIdsForTerroristFiles[ iFileNumber + 1 ]);
|
||||
// HEADROCK PROFEX: Do not read direct profile number, instead, look inside the profile for a ubFaceIndex value.
|
||||
if( usProfileIdsForTerroristFiles[ iFileNumber + 1 ] < 100 )
|
||||
{
|
||||
sprintf(sTemp, "%s%02d.sti", "FACES\\BIGFACES\\", gMercProfiles[ usProfileIdsForTerroristFiles[ iFileNumber + 1 ] ].ubFaceIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sTemp, "%s%03d.sti", "FACES\\BIGFACES\\", gMercProfiles[ usProfileIdsForTerroristFiles[ iFileNumber + 1 ] ].ubFaceIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sTemp, "%s%03d.sti", "FACES\\BIGFACES\\", usProfileIdsForTerroristFiles[ iFileNumber + 1 ]);
|
||||
if( usProfileIdsForTerroristFiles[ iFileNumber + 1 ] < 100 )
|
||||
{
|
||||
sprintf(sTemp, "%s%02d.sti", "FACES\\BIGFACES\\", usProfileIdsForTerroristFiles[ iFileNumber + 1 ]);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sTemp, "%s%03d.sti", "FACES\\BIGFACES\\", usProfileIdsForTerroristFiles[ iFileNumber + 1 ]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE;
|
||||
FilenameForBPP(sTemp, VObjectDesc.ImageFile);
|
||||
CHECKF(AddVideoObject(&VObjectDesc, &uiPicture));
|
||||
|
||||
+37
-2
@@ -17,6 +17,10 @@
|
||||
#include "LaptopSave.h"
|
||||
#include "Campaign Types.h"
|
||||
#include "strategicmap.h"
|
||||
// HEADROCK HAM 3.6: Added facilities for calculating hourly expenses
|
||||
#include "Facilities.h"
|
||||
// HEADROCK HAM 3.6: Militia upkeep
|
||||
#include "Town Militia.h"
|
||||
#endif
|
||||
|
||||
// the global defines
|
||||
@@ -402,7 +406,27 @@ INT32 GetProjectedTotalDailyIncome( void )
|
||||
// then there is how many deposits have been made, now look at how many mines we have, thier rate, amount of ore left and predict if we still
|
||||
// had these mines how much more would we get?
|
||||
|
||||
return( PredictIncomeFromPlayerMines() );
|
||||
// HEADROCK HAM 3.6: Facilities can make you money, and this is figured into your daily income.
|
||||
|
||||
INT32 iRate = 0;
|
||||
iRate = PredictIncomeFromPlayerMines() + (15 * GetTotalFacilityHourlyCosts( TRUE )); // 15 hours is the average time a merc can work per day
|
||||
|
||||
return( iRate );
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: Predict expenses today. Takes into account facilities, and in the future merc contracts.
|
||||
INT32 GetProjectedExpenses( void )
|
||||
{
|
||||
INT32 iTotalExpenses = 0;
|
||||
|
||||
INT32 iFacilityExpenses = GetTotalFacilityHourlyCosts( FALSE );
|
||||
INT32 iContractExpenses = GetTotalContractExpenses();
|
||||
|
||||
iTotalExpenses += (iFacilityExpenses*15); // 15 hours is the average time a merc can work every day.
|
||||
iTotalExpenses += iContractExpenses;
|
||||
iTotalExpenses += guiTotalUpkeepForMilitia;
|
||||
|
||||
return (iTotalExpenses);
|
||||
}
|
||||
|
||||
INT32 GetProjectedBalance( void )
|
||||
@@ -1224,7 +1248,8 @@ UINT32 ProcessAndEnterAFinacialRecord( UINT8 ubCode, UINT32 uiDate, INT32 iAmoun
|
||||
else
|
||||
{
|
||||
// alloc space
|
||||
uiId = ReadInLastElementOfFinanceListAndReturnIdNumber( );
|
||||
// HEADROCK HAM 3.6: Fix by Warmsteel to prevent repetitive entries on finance list. Next line commented out.
|
||||
// uiId = ReadInLastElementOfFinanceListAndReturnIdNumber( );
|
||||
pFinance = (FinanceUnitPtr) MemAlloc(sizeof(FinanceUnit));
|
||||
|
||||
// setup info passed
|
||||
@@ -1534,6 +1559,16 @@ void ProcessTransactionString(STR16 pString, FinanceUnitPtr pFinance)
|
||||
swprintf(pString, pTransactionText[ MERC_DEPOSITED_MONEY_TO_PLAYER_ACCOUNT ], gMercProfiles[ pFinance->ubSecondCode ].zNickname );
|
||||
break;
|
||||
|
||||
// HEADROCK HAM 3.6: Paid for Facility Use
|
||||
case( FACILITY_OPERATIONS ):
|
||||
swprintf(pString, L"%s", pTransactionText[ FACILITY_OPERATIONS ]);
|
||||
break;
|
||||
|
||||
// HEADROCK HAM 3.6: Paid for militia upkeep
|
||||
case( MILITIA_UPKEEP ):
|
||||
swprintf(pString, L"%s", pTransactionText[ MILITIA_UPKEEP ]);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-1
@@ -50,7 +50,9 @@ enum
|
||||
TRAIN_TOWN_MILITIA,
|
||||
PURCHASED_ITEM_FROM_DEALER,
|
||||
MERC_DEPOSITED_MONEY_TO_PLAYER_ACCOUNT,
|
||||
SOLD_ITEMS
|
||||
SOLD_ITEMS,
|
||||
FACILITY_OPERATIONS, // HEADROCK HAM 3.6: Facility costs (daily payment)
|
||||
MILITIA_UPKEEP, // HEADROCK HAM 3.6: Militia Upkeep Costs (daily payment)
|
||||
};
|
||||
|
||||
|
||||
@@ -64,6 +66,7 @@ void InsertDollarSignInToString( STR16 pString );
|
||||
void InsertCommasForDollarFigure( STR16 pString );
|
||||
INT32 GetTodaysDaysIncome( void );
|
||||
INT32 GetProjectedTotalDailyIncome( void );
|
||||
INT32 GetProjectedExpenses( void ); // HEADROCK HAM 3.6: Projected daily expenses.
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Binary file not shown.
+74
-14
@@ -824,10 +824,21 @@ void RenderPersonnelFace(INT32 iId, INT32 iSlot, BOOLEAN fDead, BOOLEAN fFired,
|
||||
|
||||
// special case?..player generated merc
|
||||
if (fCurrentTeamMode) {
|
||||
if( ( 50 < MercPtrs[iId]->ubProfile )&&( 57 > MercPtrs[iId]->ubProfile ) ) {
|
||||
if( ( 50 < MercPtrs[iId]->ubProfile )&&( 57 > MercPtrs[iId]->ubProfile ) )
|
||||
{
|
||||
sprintf( sTemp, "%s%03d.sti", FACES_DIR, gMercProfiles[ MercPtrs[iId]->ubProfile ].ubFaceIndex );
|
||||
} else {
|
||||
sprintf(sTemp, "%s%02d.sti", FACES_DIR, Menptr[ iId ].ubProfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gGameExternalOptions.fReadProfileDataFromXML)
|
||||
{
|
||||
// HEADROCK PROFEX: Do not read direct profile number, instead, look inside the profile for a ubFaceIndex value.
|
||||
sprintf(sTemp, "%s%02d.sti", FACES_DIR, gMercProfiles[Menptr[ iId ].ubProfile].ubFaceIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sTemp, "%s%02d.sti", FACES_DIR, Menptr[ iId ].ubProfile);
|
||||
}
|
||||
}
|
||||
|
||||
if( MercPtrs[iId]->flags.uiStatusFlags & SOLDIER_VEHICLE ) {
|
||||
@@ -839,10 +850,21 @@ void RenderPersonnelFace(INT32 iId, INT32 iSlot, BOOLEAN fDead, BOOLEAN fFired,
|
||||
return;
|
||||
}
|
||||
|
||||
if( ( 50 < iId )&&( 57 > iId ) ) {
|
||||
if( ( 50 < iId )&&( 57 > iId ) )
|
||||
{
|
||||
sprintf( sTemp, "%s%03d.sti", FACES_DIR, gMercProfiles[ iId ].ubFaceIndex );
|
||||
} else {
|
||||
sprintf(sTemp, "%s%02d.sti", FACES_DIR, iId );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gGameExternalOptions.fReadProfileDataFromXML)
|
||||
{
|
||||
// HEADROCK PROFEX: Do not read direct profile number, instead, look inside the profile for a ubFaceIndex value.
|
||||
sprintf(sTemp, "%s%02d.sti", FACES_DIR, gMercProfiles[Menptr[ iId ].ubProfile].ubFaceIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sTemp, "%s%02d.sti", FACES_DIR, iId );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1943,10 +1965,29 @@ void DisplayPicturesOfCurrentTeam( void )
|
||||
if ((50 < pSoldier->ubProfile) && (57 > pSoldier->ubProfile)) {
|
||||
sprintf( sTemp, "%s%03d.sti", SMALL_FACES_DIR, gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex );
|
||||
} else {
|
||||
if ( pSoldier->ubProfile < 100 ) {
|
||||
sprintf(sTemp, "%s%02d.sti", SMALL_FACES_DIR, pSoldier->ubProfile);
|
||||
} else {
|
||||
sprintf(sTemp, "%s%03d.sti", SMALL_FACES_DIR, pSoldier->ubProfile);
|
||||
if ( pSoldier->ubProfile < 100 )
|
||||
{
|
||||
if (gGameExternalOptions.fReadProfileDataFromXML)
|
||||
{
|
||||
// HEADROCK PROFEX: Do not read direct profile number, instead, look inside the profile for a ubFaceIndex value.
|
||||
sprintf(sTemp, "%s%02d.sti", SMALL_FACES_DIR, gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sTemp, "%s%02d.sti", SMALL_FACES_DIR, pSoldier->ubProfile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gGameExternalOptions.fReadProfileDataFromXML)
|
||||
{
|
||||
// HEADROCK PROFEX: Do not read direct profile number, instead, look inside the profile for a ubFaceIndex value.
|
||||
sprintf(sTemp, "%s%03d.sti", SMALL_FACES_DIR, gMercProfiles[ pSoldier->ubProfile ].ubFaceIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sTemp, "%s%03d.sti", SMALL_FACES_DIR, pSoldier->ubProfile);
|
||||
}
|
||||
} // else
|
||||
} // else
|
||||
|
||||
@@ -4462,10 +4503,29 @@ void DisplayPortraitOfPastMerc( INT32 iId , INT32 iCounter, BOOLEAN fDead, BOOLE
|
||||
if( ( 50 < iId )&&( 57 > iId ) ) {
|
||||
sprintf( sTemp, "%s%03d.sti", SMALL_FACES_DIR, gMercProfiles[ iId ].ubFaceIndex );
|
||||
} else {
|
||||
if( iId < 100 ) {
|
||||
sprintf(sTemp, "%s%02d.sti", SMALL_FACES_DIR, iId );
|
||||
} else {
|
||||
sprintf(sTemp, "%s%03d.sti", SMALL_FACES_DIR, iId );
|
||||
if( iId < 100 )
|
||||
{
|
||||
if (gGameExternalOptions.fReadProfileDataFromXML)
|
||||
{
|
||||
// HEADROCK PROFEX: Do not read direct profile number, instead, look inside the profile for a ubFaceIndex value.
|
||||
sprintf(sTemp, "%s%02d.sti", SMALL_FACES_DIR, gMercProfiles[ iId ].ubFaceIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sTemp, "%s%02d.sti", SMALL_FACES_DIR, iId );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gGameExternalOptions.fReadProfileDataFromXML)
|
||||
{
|
||||
// HEADROCK PROFEX: Do not read direct profile number, instead, look inside the profile for a ubFaceIndex value.
|
||||
sprintf(sTemp, "%s%03d.sti", SMALL_FACES_DIR, gMercProfiles[ iId ].ubFaceIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(sTemp, "%s%03d.sti", SMALL_FACES_DIR, iId );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+51
-4
@@ -108,6 +108,10 @@
|
||||
#include "postalservice.h"
|
||||
// HEADROCK HAM B1: Additional Include for HAM
|
||||
#include "MilitiaSquads.h"
|
||||
// HEADROCK HAM 3.5: Another include for HAM
|
||||
#include "Facilities.h"
|
||||
// HEADROCK HAM 3.6: Yet another include, goddammit
|
||||
#include "Town Militia.h"
|
||||
#endif
|
||||
|
||||
#include "BobbyR.h"
|
||||
@@ -389,7 +393,20 @@ typedef struct
|
||||
INT8 fPlayerTeamSawJoey;
|
||||
INT8 fMikeShouldSayHi;
|
||||
|
||||
UINT8 ubFiller[550]; //This structure should be 1024 bytes
|
||||
// HEADROCK HAM 3.6: New global variable that tracks money owed for facility use.
|
||||
INT32 iTotalOwedForFacilityOperationsToday;
|
||||
|
||||
// HEADROCK HAM 3.6: Now saving Skyrider Cost Modifier variable;
|
||||
INT16 sSkyriderCostModifier;
|
||||
|
||||
// HEADROCK HAM 3.6: New global variable indicating whether we owe cash for facility work.
|
||||
BOOLEAN fOutstandingFacilityDebt;
|
||||
|
||||
// HEADROCK HAM 3.6: Global variable keeping track of Militia Upkeep Costs at last midnight.
|
||||
UINT32 uiTotalUpkeepForMilitia;
|
||||
|
||||
// HEADROCK HAM 3.6: Removed 16 fillers (16 bytes) to accomodate the above new variables.
|
||||
UINT8 ubFiller[534]; //This structure should be 1024 bytes
|
||||
|
||||
} GENERAL_SAVE_INFO;
|
||||
|
||||
@@ -4390,7 +4407,6 @@ BOOLEAN LoadSavedGame( int ubSavedGameID )
|
||||
UpdateMercMercContractInfo();
|
||||
}
|
||||
|
||||
|
||||
if ( guiCurrentSaveGameVersion <= 89 )
|
||||
{
|
||||
// ARM: A change was made in version 89 where refuel site availability now also depends on whether the player has
|
||||
@@ -4441,11 +4457,17 @@ BOOLEAN LoadSavedGame( int ubSavedGameID )
|
||||
// fix squads
|
||||
CheckSquadMovementGroups();
|
||||
// HEADROCK HAM B1: Re-Adjust Dynamic Roaming Militia restrictions
|
||||
if (gGameExternalOptions.bDynamicRestrictRoaming)
|
||||
if (gGameExternalOptions.fDynamicRestrictRoaming)
|
||||
{
|
||||
AdjustRoamingRestrictions();
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.5: Tells the rest of the program whether we've got mercs working on detecting enemy units.
|
||||
UpdateStrategicDetectionLevel( );
|
||||
|
||||
// HEADROCK HAM 3.5: recalculate a modifier to Skyrider's costs, based on mercs working in certain facilities.
|
||||
UpdateSkyriderCostModifier( );
|
||||
|
||||
//The above function LightSetBaseLevel adjusts ALL the level node light values including the merc node,
|
||||
//we must reset the values
|
||||
HandlePlayerTogglingLightEffects( FALSE );
|
||||
@@ -6133,6 +6155,18 @@ BOOLEAN SaveGeneralInfo( HWFILE hFile )
|
||||
sGeneralInfo.fPlayerTeamSawJoey = gfPlayerTeamSawJoey;
|
||||
sGeneralInfo.fMikeShouldSayHi = gfMikeShouldSayHi;
|
||||
|
||||
// HEADROCK HAM 3.6: Save new global variable for facility costs
|
||||
sGeneralInfo.iTotalOwedForFacilityOperationsToday = giTotalOwedForFacilityOperationsToday;
|
||||
|
||||
// HEADROCK HAM 3.6: Save Skyrider Costs Modifier
|
||||
sGeneralInfo.sSkyriderCostModifier = gsSkyriderCostModifier;
|
||||
|
||||
// HEADROCK HAM 3.6: Save new global variable for facility debt
|
||||
sGeneralInfo.fOutstandingFacilityDebt = gfOutstandingFacilityDebt;
|
||||
|
||||
// HEADROCK HAM 3.6: Save new global variable for militia upkeep
|
||||
sGeneralInfo.uiTotalUpkeepForMilitia = guiTotalUpkeepForMilitia;
|
||||
|
||||
//Setup the
|
||||
//Save the current music mode
|
||||
FileWrite( hFile, &sGeneralInfo, sizeof( GENERAL_SAVE_INFO ), &uiNumBytesWritten );
|
||||
@@ -6155,7 +6189,8 @@ BOOLEAN LoadGeneralInfo( HWFILE hFile )
|
||||
|
||||
GENERAL_SAVE_INFO sGeneralInfo;
|
||||
memset( &sGeneralInfo, 0, sizeof( GENERAL_SAVE_INFO ) );
|
||||
|
||||
// HEADROCK HAM 3.6: Hi. If you can see this comment, please delete the next line. Sorry! :)
|
||||
INT32 blah = sizeof( GENERAL_SAVE_INFO );
|
||||
|
||||
//Load the current music mode
|
||||
FileRead( hFile, &sGeneralInfo, sizeof( GENERAL_SAVE_INFO ), &uiNumBytesRead );
|
||||
@@ -6405,6 +6440,18 @@ BOOLEAN LoadGeneralInfo( HWFILE hFile )
|
||||
gfPlayerTeamSawJoey = sGeneralInfo.fPlayerTeamSawJoey;
|
||||
gfMikeShouldSayHi = sGeneralInfo.fMikeShouldSayHi;
|
||||
|
||||
// HEADROCK HAM 3.6: Load new global variable for facility costs
|
||||
giTotalOwedForFacilityOperationsToday = sGeneralInfo.iTotalOwedForFacilityOperationsToday;
|
||||
|
||||
// HEADROCK HAM 3.6: Load Skyrider Costs Modifier
|
||||
gsSkyriderCostModifier = sGeneralInfo.sSkyriderCostModifier;
|
||||
|
||||
// HEADROCK HAM 3.6: Load new global variable for facility debt
|
||||
gfOutstandingFacilityDebt = sGeneralInfo.fOutstandingFacilityDebt;
|
||||
|
||||
// HEADROCK HAM 3.6: Load new global variable for militia upkeep
|
||||
guiTotalUpkeepForMilitia = sGeneralInfo.uiTotalUpkeepForMilitia;
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
@@ -1296,6 +1296,8 @@ INT16 GetNumberOfLinesInHeight( const STR16 pStringA )
|
||||
{
|
||||
STR16 pToken;
|
||||
INT16 sCounter = 0;
|
||||
// HEADROCK HAM 3.6: This is a serious limitation... Increasing size
|
||||
//CHAR16 pString[ 512 ];
|
||||
CHAR16 pString[ 4096 ];
|
||||
|
||||
wcscpy( pString, pStringA );
|
||||
@@ -1305,16 +1307,14 @@ INT16 GetNumberOfLinesInHeight( const STR16 pStringA )
|
||||
|
||||
while( pToken != NULL )
|
||||
{
|
||||
// WANNE: Fix by Headrock
|
||||
// HEADROCK HAM 3.6: Make sure that all lines can appear on screen. If impossible, reduce number of lines
|
||||
// artificially.
|
||||
if ( (sCounter+1) * (GetFontHeight(FONT10ARIAL)+1) > (SCREEN_HEIGHT - 10) )
|
||||
{
|
||||
break;
|
||||
}
|
||||
pToken = wcstok( NULL, L"\n" );
|
||||
sCounter++;
|
||||
|
||||
/*pToken = wcstok( NULL, L"\n" );
|
||||
sCounter++;*/
|
||||
{
|
||||
break;
|
||||
}
|
||||
pToken = wcstok( NULL, L"\n" );
|
||||
sCounter++;
|
||||
}
|
||||
|
||||
return( sCounter );
|
||||
@@ -1347,7 +1347,10 @@ void DisplayFastHelp( MOUSE_REGION *region )
|
||||
if ( (iX + iW) >= SCREEN_WIDTH )
|
||||
iX = (SCREEN_WIDTH - iW - 4);
|
||||
|
||||
iY = (INT32)region->RegionTopLeftY - (iH * 3 / 4);
|
||||
// HEADROCK HAM 3.6: This formula causes the tooltip to appear UNDERNEATH the cursor if
|
||||
// the tooltip's parent region is small. That makes reading the tooltip very difficult. Not desirable.
|
||||
//iY = (INT32)region->RegionTopLeftY - (iH * 3 / 4);
|
||||
iY = (INT32)region->RegionTopLeftY - iH;
|
||||
if (iY < 0)
|
||||
iY = 0;
|
||||
|
||||
@@ -1384,6 +1387,8 @@ void DisplayFastHelp( MOUSE_REGION *region )
|
||||
|
||||
INT16 GetWidthOfString( const STR16 pStringA )
|
||||
{
|
||||
// HEADROCK HAM 3.6: This is a serious limitation... Increasing size.
|
||||
//CHAR16 pString[ 512 ];
|
||||
CHAR16 pString[ 4096 ];
|
||||
STR16 pToken;
|
||||
INT16 sWidth = 0;
|
||||
@@ -1411,6 +1416,8 @@ void DisplayHelpTokenizedString( const STR16 pStringA, INT16 sX, INT16 sY )
|
||||
STR16 pToken;
|
||||
INT32 iCounter = 0, i;
|
||||
UINT32 uiCursorXPos;
|
||||
// HEADROCK HAM 3.6: This is a serious limitation... Increasing size
|
||||
//CHAR16 pString[ 512 ];
|
||||
CHAR16 pString[ 4096 ];
|
||||
INT32 iLength;
|
||||
|
||||
@@ -1421,15 +1428,14 @@ void DisplayHelpTokenizedString( const STR16 pStringA, INT16 sX, INT16 sY )
|
||||
|
||||
while( pToken != NULL )
|
||||
{
|
||||
// WANNE: Fix by Headrock
|
||||
// HEADROCK HAM 3.6: If height of screen exceeds screen height, replace the last VISIBLE line with "..."
|
||||
// and break the cycle.
|
||||
if ( (iCounter+2) * (GetFontHeight(FONT10ARIAL)+1) > (SCREEN_HEIGHT - 10) )
|
||||
{
|
||||
mprintf( sX, sY + iCounter * (GetFontHeight(FONT10ARIAL)+1), L"..." );
|
||||
break;
|
||||
}
|
||||
iLength = (INT32)wcslen( pToken );
|
||||
|
||||
//iLength = (INT32)wcslen( pToken );
|
||||
{
|
||||
mprintf( sX, sY + iCounter * (GetFontHeight(FONT10ARIAL)+1), L"..." );
|
||||
break;
|
||||
}
|
||||
iLength = (INT32)wcslen( pToken );
|
||||
for( i = 0; i < iLength; i++ )
|
||||
{
|
||||
uiCursorXPos = StringPixLengthArgFastHelp( FONT10ARIAL, FONT10ARIALBOLD, i, pToken );
|
||||
|
||||
@@ -1256,7 +1256,8 @@ void TestIncoming4SidesCallback( GUI_BUTTON *btn, INT32 reason )
|
||||
UINT32 uiWorldMin;
|
||||
Compression0Callback( ButtonList[ iViewerButton[ COMPRESSION0 ] ], MSYS_CALLBACK_REASON_LBUTTON_UP );
|
||||
if( ( gsSelSectorX == 0 ) || ( gsSelSectorY == 0 ) )
|
||||
gsSelSectorX = 9, gsSelSectorY = 1;
|
||||
// HEADROCK HAM 3.5: Not sure what this function does at all... But this is externalized now anyway.
|
||||
gsSelSectorX = gGameExternalOptions.ubDefaultArrivalSectorX, gsSelSectorY = gGameExternalOptions.ubDefaultArrivalSectorY;
|
||||
|
||||
ubSector = SECTOR( gsSelSectorX, gsSelSectorY );
|
||||
uiWorldMin = GetWorldTotalMin();
|
||||
|
||||
+3553
-316
File diff suppressed because it is too large
Load Diff
+54
-5
@@ -26,7 +26,7 @@
|
||||
|
||||
#define VEHICLE_REPAIR_POINTS_DIVISOR 10
|
||||
|
||||
|
||||
// HEADROCK HAM 3.6: Added separate Mobile Militia training assignment.
|
||||
// Assignments Defines
|
||||
enum{
|
||||
SQUAD_1 =0,
|
||||
@@ -57,8 +57,11 @@ enum{
|
||||
REPAIR,
|
||||
TRAIN_SELF,
|
||||
TRAIN_TOWN,
|
||||
TRAIN_MOBILE, // HEADROCK HAM 3.6: Training mobile militia.
|
||||
TRAIN_TEAMMATE,
|
||||
TRAIN_BY_OTHER,
|
||||
FACILITY_STAFF, // HEADROCK HAM 3.6: Operating a facility for strategic gain.
|
||||
FACILITY_REST, // HEADROCK HAM 3.6: Facility equivalent of resting (no assignment)
|
||||
ASSIGNMENT_DEAD,
|
||||
ASSIGNMENT_UNCONCIOUS, // unused
|
||||
ASSIGNMENT_POW,
|
||||
@@ -83,6 +86,16 @@ enum{
|
||||
// NOTE: Wisdom isn't trainable!
|
||||
};
|
||||
|
||||
// HEADROCK HAM 3.2: Set bitwise flags for locating facilities in current sector (for training/otherwise)
|
||||
// facilities flags
|
||||
// HEADROCK HAM 3.4: Removed due to facility externalization.
|
||||
/*#define AT_HOSPITAL 0x00000001
|
||||
#define AT_INDUSTRY 0x00000002
|
||||
#define AT_PRISON 0x00000004
|
||||
#define AT_MILITARY 0x00000008
|
||||
#define AT_AIRPORT 0x00000010
|
||||
#define AT_GUN_RANGE 0x00000020*/
|
||||
|
||||
|
||||
typedef struct TOWN_TRAINER_TYPE
|
||||
{
|
||||
@@ -106,6 +119,7 @@ BOOLEAN CanCharacterPatient( SOLDIERTYPE *pCharacter );
|
||||
|
||||
// can character train militia?
|
||||
BOOLEAN CanCharacterTrainMilitia( SOLDIERTYPE *pCharacter );
|
||||
BOOLEAN CanCharacterTrainMobileMilitia( SOLDIERTYPE *pSoldier );
|
||||
|
||||
// can character train stat?..as train self or as trainer?
|
||||
BOOLEAN CanCharacterTrainStat( SOLDIERTYPE *pSoldier, INT8 bStat, BOOLEAN fTrainSelf, BOOLEAN fTrainTeammate );
|
||||
@@ -116,6 +130,9 @@ BOOLEAN CanCharacterPractise( SOLDIERTYPE *pCharacter );
|
||||
// can this character train others?
|
||||
BOOLEAN CanCharacterTrainTeammates( SOLDIERTYPE *pSoldier );
|
||||
|
||||
// HEADROCK HAM 3.6: Can character use a specific facility?
|
||||
BOOLEAN CanCharacterFacility( SOLDIERTYPE *pSoldier, UINT8 ubFacilityType, UINT8 ubAssignmentType );
|
||||
|
||||
// put character on duty?
|
||||
BOOLEAN CanCharacterOnDuty( SOLDIERTYPE *pCharacter );
|
||||
|
||||
@@ -183,16 +200,18 @@ UINT8 CalculateRepairPointsForRepairman(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts
|
||||
|
||||
|
||||
// get bonus tarining pts due to an instructor for this student
|
||||
INT16 GetBonusTrainingPtsDueToInstructor( SOLDIERTYPE *pInstructor, SOLDIERTYPE *pStudent, INT8 bTrainStat, BOOLEAN fAtGunRange, UINT16 *pusMaxPts );
|
||||
// HEADROCK HAM 3.5: Three functions below have lost an argument which is no longer required ("uiAtGunRange", which was "uiAtFacility" in HAM 3.4)
|
||||
INT16 GetBonusTrainingPtsDueToInstructor( SOLDIERTYPE *pInstructor, SOLDIERTYPE *pStudent, INT8 bTrainStat, UINT16 *pusMaxPts );
|
||||
|
||||
// get training pts for this soldier
|
||||
INT16 GetSoldierTrainingPts( SOLDIERTYPE *pSoldier, INT8 bTrainStat, BOOLEAN fAtGunRange, UINT16 *pusMaxPts );
|
||||
INT16 GetSoldierTrainingPts( SOLDIERTYPE *pSoldier, INT8 bTrainStat, UINT16 *pusMaxPts );
|
||||
|
||||
// pts for being a student for this soldier
|
||||
INT16 GetSoldierStudentPts( SOLDIERTYPE *pSoldier, INT8 bTrainStat, BOOLEAN fAtGunRange, UINT16 *pusMaxPts );
|
||||
INT16 GetSoldierStudentPts( SOLDIERTYPE *pSoldier, INT8 bTrainStat, UINT16 *pusMaxPts );
|
||||
|
||||
// HEADROCK HAM 3.6: Completely unused.
|
||||
// reset these soldiers
|
||||
void ResetAssignmentsForAllSoldiersInSectorWhoAreTrainingTown( SOLDIERTYPE *pSoldier );
|
||||
//void ResetAssignmentsForAllSoldiersInSectorWhoAreTrainingTown( SOLDIERTYPE *pSoldier );
|
||||
|
||||
// Handle assignment done
|
||||
void AssignmentDone( SOLDIERTYPE *pSoldier, BOOLEAN fSayQuote, BOOLEAN fMeToo );
|
||||
@@ -207,6 +226,9 @@ extern INT32 ghAttributeBox;
|
||||
extern INT32 ghRemoveMercAssignBox;
|
||||
extern INT32 ghContractBox;
|
||||
extern INT32 ghMoveBox;
|
||||
// HEADROCK HAM 3.6: Facility Menu, Submenu
|
||||
extern INT32 ghFacilityBox;
|
||||
extern INT32 ghFacilityAssignmentBox;
|
||||
//extern INT32 ghUpdateBox;
|
||||
|
||||
|
||||
@@ -219,6 +241,9 @@ extern MOUSE_REGION gSquadMenuRegion[ ];
|
||||
extern MOUSE_REGION gContractMenuRegion[ ];
|
||||
extern MOUSE_REGION gRemoveMercAssignRegion[ ];
|
||||
extern MOUSE_REGION gVehicleMenuRegion[];
|
||||
// HEADROCK HAM 3.6: Facility Menu.
|
||||
extern MOUSE_REGION gFacilityMenuRegion[];
|
||||
extern MOUSE_REGION gFacilityMenuRegion[];
|
||||
|
||||
extern BOOLEAN fShownContractMenu;
|
||||
extern BOOLEAN fShownAssignmentMenu;
|
||||
@@ -260,6 +285,16 @@ void CreateDestroyMouseRegionForRepairMenu( void );
|
||||
void RepairMenuMvtCallback(MOUSE_REGION * pRegion, INT32 iReason );
|
||||
void RepairMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason );
|
||||
|
||||
// HEADROCK HAM 3.6: Facility Menu
|
||||
void CreateDestroyMouseRegionForFacilityMenu( void );
|
||||
void FacilityMenuMvtCallback(MOUSE_REGION * pRegion, INT32 iReason );
|
||||
void FacilityMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason );
|
||||
|
||||
// HEADROCK HAM 3.6: Facility sub-menu
|
||||
void CreateDestroyMouseRegionsForFacilityAssignmentMenu( void );
|
||||
void FacilityAssignmentMenuMvtCallBack( MOUSE_REGION * pRegion, INT32 iReason );
|
||||
void FacilityAssignmentMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason );
|
||||
|
||||
// contract menu
|
||||
void CreateDestroyMouseRegionsForContractMenu( void );
|
||||
void ContractMenuBtnCallback( MOUSE_REGION * pRegion, INT32 iReason );
|
||||
@@ -334,6 +369,20 @@ void HandleTrainingWakeSynchronize( SOLDIERTYPE *pSoldier );
|
||||
BOOLEAN FindAnyAwakeTrainers( SOLDIERTYPE *pTrainee );
|
||||
BOOLEAN FindAnyAwakeTrainees( SOLDIERTYPE *pTrainer );
|
||||
|
||||
// HEADROCK HAM 3.6: Functions for testing and reporting reasons why character can't train here.
|
||||
BOOLEAN CanCharacterTrainMilitiaWithErrorReport( SOLDIERTYPE *pSoldier );
|
||||
BOOLEAN CanCharacterTrainMobileMilitiaWithErrorReport( SOLDIERTYPE *pSoldier );
|
||||
// HEADROCK HAM 3.6: Function for testing and reporting reasons why character can't staff a facility.
|
||||
BOOLEAN CanCharacterFacilityWithErrorReport( SOLDIERTYPE *pSoldier, UINT8 ubFacilityType, UINT8 ubAssignmentType );
|
||||
void HandleInterfaceMessageForCostOfOperatingFacility( SOLDIERTYPE *pSoldier, UINT8 ubAssignmentType );
|
||||
void PayFacilityCostsYesNoBoxCallback( UINT8 bExitValue );
|
||||
void FacilityStaffingRejected( void );
|
||||
void ResetAllExpensiveFacilityAssignments();
|
||||
BOOLEAN IsOutstandingFacilityDebtWithErrorReport();
|
||||
extern INT8 gubFacilityInSubmenu;
|
||||
extern UINT8 gubFacilityLineForSubmenu;
|
||||
extern SOLDIERTYPE *gpFacilityStaffer;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -339,7 +339,8 @@ void RenderSoldierCellHealth( SOLDIERCELL *pCell );
|
||||
void RenderSoldierCell( SOLDIERCELL *pCell );
|
||||
void RenderSoldierCellBars( SOLDIERCELL *pCell );
|
||||
|
||||
void GenerateDirectionInfos( INT16 sMapX, INT16 sMapY, UINT8* uiDirNumber, UINT16 pMoveDir[4][3], BOOLEAN fWithCities, BOOLEAN fForBattle, BOOLEAN fOnlyCitySectors );
|
||||
// HEADROCK HAM 3.4: New argument configuration to make use of revamped movement controls
|
||||
void GenerateDirectionInfos( INT16 sMapX, INT16 sMapY, UINT8* uiDirNumber, UINT16 pMoveDir[4][3], BOOLEAN fForTraining, BOOLEAN fForBattle );
|
||||
|
||||
|
||||
//Dynamic globals -- to conserve memory, all global variables are allocated upon entry
|
||||
@@ -2146,8 +2147,8 @@ void CreateAutoResolveInterface()
|
||||
ARCreateMilitiaSquad( &cnt, ubEliteMilitia, ubRegMilitia, ubGreenMilitia, gpAR->ubSectorX, gpAR->ubSectorY);
|
||||
|
||||
// Add the militia in the surrounding sectors
|
||||
GenerateDirectionInfos( gpAR->ubSectorX, gpAR->ubSectorY, &uiDirNumber, pMoveDir,
|
||||
( GetTownIdForSector( gpAR->ubSectorX, gpAR->ubSectorY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, FALSE );
|
||||
// HEADROCK HAM 3.4: Changed argument configuration.
|
||||
GenerateDirectionInfos( gpAR->ubSectorX, gpAR->ubSectorY, &uiDirNumber, pMoveDir, FALSE, TRUE );
|
||||
for( i=0; i<uiDirNumber; i++)
|
||||
{
|
||||
INT16 sX = SECTORX( pMoveDir[ i ][0] );
|
||||
|
||||
@@ -273,8 +273,28 @@ UNDERGROUND_SECTORINFO* NewUndergroundNode( UINT8 ubSectorX, UINT8 ubSectorY, UI
|
||||
// setup which know facilities are in which cities
|
||||
void InitKnowFacilitiesFlags( )
|
||||
{
|
||||
SECTORINFO *pSector;
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// HEADROCK HAM 3.5: No longer required. Function disconnected.
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
//SECTORINFO *pSector;
|
||||
|
||||
// HEADROCK HAM 3.4: Externalized. All "known" facilities are read from gFacilityLocations. The
|
||||
// ones that have (fHidden=0) will be added to the sector info now, and thus visible immediately.
|
||||
// The others are added only once the player visits those sectors.
|
||||
|
||||
/*for(UINT32 cnt=0; (gFacilityLocations[cnt].uiSectorID >= 0 && gFacilityLocations[cnt].uiSectorID <= 256); cnt++ )
|
||||
{
|
||||
// Is the current sector valid? Is the facility set to be revealed on game-start?
|
||||
if (gFacilityLocations[cnt].uiSectorID > 0 && gFacilityLocations[cnt].uiSectorID < 257 &&
|
||||
gFacilityLocations[cnt].fHidden == 0)
|
||||
{
|
||||
// Reveal the facility.
|
||||
pSector = &SectorInfo[gFacilityLocations[cnt].uiSectorID];
|
||||
pSector->uiFacilitiesFlags |= (1 << (gFacilityLocations[cnt].uiFacilityType-1));
|
||||
}
|
||||
}*/
|
||||
|
||||
/* HEADROCK HAM 3.4: Externalized.
|
||||
// Cambria hospital
|
||||
pSector = &SectorInfo[SEC_G8];
|
||||
pSector->uiFacilitiesFlags |= SFCF_HOSPITAL;
|
||||
@@ -304,6 +324,7 @@ void InitKnowFacilitiesFlags( )
|
||||
pSector->uiFacilitiesFlags |= SFCF_AIRPORT;
|
||||
pSector = &SectorInfo[SEC_O4];
|
||||
pSector->uiFacilitiesFlags |= SFCF_AIRPORT;
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -603,13 +624,16 @@ void InitNewCampaign()
|
||||
|
||||
InitWorld(); // Lesh: generate different world each time using alternative maps
|
||||
InitMiningLocations();
|
||||
InitKnowFacilitiesFlags( );
|
||||
|
||||
// HEADROCK HAM 3.5: This is no longer required.
|
||||
//InitKnowFacilitiesFlags( );
|
||||
|
||||
BuildUndergroundSectorInfoList();
|
||||
|
||||
if (!is_networked)
|
||||
// allow overhead view of omerta A9 on game onset
|
||||
SetSectorFlag( startingX, startingY, startingZ, SF_ALREADY_VISITED ); //hayden
|
||||
// HEADROCK HAM 3.5: Externalized.
|
||||
SetSectorFlag( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ, SF_ALREADY_VISITED ); //hayden
|
||||
|
||||
//Generates the initial forces in a new campaign. The idea is to randomize numbers and sectors
|
||||
//so that no two games are the same.
|
||||
|
||||
+210
-8
@@ -112,19 +112,214 @@ enum
|
||||
MAX_MILITIA_LEVELS
|
||||
};
|
||||
|
||||
// facilities flags
|
||||
// HEADROCK HAM 3.5: No longer needed. Facility types externalized.
|
||||
/*// facilities flags
|
||||
#define SFCF_HOSPITAL 0x00000001
|
||||
#define SFCF_INDUSTRY 0x00000002
|
||||
#define SFCF_PRISON 0x00000004
|
||||
#define SFCF_MILITARY 0x00000008
|
||||
#define SFCF_AIRPORT 0x00000010
|
||||
#define SFCF_GUN_RANGE 0x00000020
|
||||
#define SFCF_GUN_RANGE 0x00000020*/
|
||||
|
||||
// coordinates of shooting range sector
|
||||
// HEADROCK HAM 3.4: These are no longer needed anywhere in the code.
|
||||
/*// coordinates of shooting range sector
|
||||
#define GUN_RANGE_X 13
|
||||
#define GUN_RANGE_Y MAP_ROW_H
|
||||
#define GUN_RANGE_Z 0
|
||||
|
||||
// HEADROCK HAM 3.2: New values for the location of an Industrial sector in Grumm H2. This sector boosts repair rates.
|
||||
#define INDUSTRIAL_X 2
|
||||
#define INDUSTRIAL_Y MAP_ROW_H
|
||||
#define INDUSTRIAL_Z 0*/
|
||||
|
||||
// HEADROCK HAM 3.4: Facility Locations
|
||||
typedef struct FACILITYLOCATIONS
|
||||
{
|
||||
BOOLEAN fFacilityHere;
|
||||
UINT8 ubHidden;
|
||||
}FACILITYLOCATIONS;
|
||||
|
||||
enum
|
||||
{
|
||||
// Enumerate the different assignments that a facility can emulate.
|
||||
FAC_AMBIENT = 0,
|
||||
FAC_STAFF,
|
||||
FAC_REST,
|
||||
FAC_REPAIR_ITEMS,
|
||||
FAC_REPAIR_VEHICLE,
|
||||
FAC_REPAIR_ROBOT,
|
||||
FAC_DOCTOR,
|
||||
FAC_PATIENT,
|
||||
FAC_PRACTICE_STRENGTH,
|
||||
FAC_PRACTICE_DEXTERITY,
|
||||
FAC_PRACTICE_AGILITY,
|
||||
FAC_PRACTICE_HEALTH,
|
||||
FAC_PRACTICE_MARKSMANSHIP,
|
||||
FAC_PRACTICE_MEDICAL,
|
||||
FAC_PRACTICE_MECHANICAL,
|
||||
FAC_PRACTICE_LEADERSHIP,
|
||||
FAC_PRACTICE_EXPLOSIVES,
|
||||
FAC_STUDENT_STRENGTH,
|
||||
FAC_STUDENT_DEXTERITY,
|
||||
FAC_STUDENT_AGILITY,
|
||||
FAC_STUDENT_HEALTH,
|
||||
FAC_STUDENT_MARKSMANSHIP,
|
||||
FAC_STUDENT_MEDICAL,
|
||||
FAC_STUDENT_MECHANICAL,
|
||||
FAC_STUDENT_LEADERSHIP,
|
||||
FAC_STUDENT_EXPLOSIVES,
|
||||
FAC_TRAINER_STRENGTH,
|
||||
FAC_TRAINER_DEXTERITY,
|
||||
FAC_TRAINER_AGILITY,
|
||||
FAC_TRAINER_HEALTH,
|
||||
FAC_TRAINER_MARKSMANSHIP,
|
||||
FAC_TRAINER_MEDICAL,
|
||||
FAC_TRAINER_MECHANICAL,
|
||||
FAC_TRAINER_LEADERSHIP,
|
||||
FAC_TRAINER_EXPLOSIVES,
|
||||
NUM_FACILITY_ASSIGNMENTS,
|
||||
};
|
||||
|
||||
|
||||
// Enumerated list of risk types
|
||||
enum
|
||||
{
|
||||
RISK_STRENGTH = 0,
|
||||
RISK_HEALTH,
|
||||
RISK_AGILITY,
|
||||
RISK_DEXTERITY,
|
||||
RISK_WISDOM,
|
||||
RISK_MARKSMANSHIP,
|
||||
RISK_LEADERSHIP,
|
||||
RISK_EXPLOSIVES,
|
||||
RISK_MECHANICAL,
|
||||
RISK_MEDICAL,
|
||||
|
||||
RISK_INJURY,
|
||||
RISK_MORALE,
|
||||
RISK_FATIGUE,
|
||||
RISK_DRUNK,
|
||||
|
||||
RISK_LOYALTY_LOCAL,
|
||||
RISK_LOYALTY_GLOBAL,
|
||||
|
||||
NUM_RISKS,
|
||||
};
|
||||
|
||||
typedef struct FACILITYRISKTYPE
|
||||
{
|
||||
// The risks involved with perfoming an assignment at a specific facility.
|
||||
|
||||
UINT8 ubChance; // Chance out of X that this risk will trigger every hour. X is INI-defined and is normally 1000.
|
||||
INT8 bBaseEffect; // Base result. If negative, result will always be negative. If positive, result will always be positive.
|
||||
// If 0, result can be either negative or positive.
|
||||
UINT8 ubRange; // Range of deviation for the base effect.
|
||||
|
||||
} FACILITYRISKTYPE;
|
||||
|
||||
typedef struct FACILITYASSIGNMENTTYPE
|
||||
{
|
||||
// This contains data about performing a specific assignment at a specific facility.
|
||||
|
||||
UINT8 ubStaffLimit; // Maximum number of people who can perform this assignment simultaneously
|
||||
CHAR16 szTooltipText[300]; // Tooltip explaining the assignment in general terms.
|
||||
INT16 sCostPerHour; // Cost per hour. Can be negative to indicate FLAT PROFIT per hour.
|
||||
|
||||
UINT16 usPerformance; // Percentage effectiveness of this assignment compared to non-emulated assignment (100 = normal)
|
||||
UINT16 usFatigue; // Percentage speed of losing Max Breath (100 = normal)
|
||||
UINT16 usSleep; // Percentage effectiveness of sleeping on the job (100 = normal)
|
||||
UINT16 usKitDegrade; // Percentage speed of kit degrade (100 = normal)
|
||||
|
||||
UINT8 ubMaximumMorale; // Maximum morale achievable while performing this assignment
|
||||
UINT8 ubMaximumBreath; // Maximum breath achievable while performing this assignment
|
||||
|
||||
UINT8 ubDetectEnemiesImmediate; // Detection of enemies in adjacent sectors, value = range of detection.
|
||||
BOOLEAN fDetectEnemiesLongrange; // Detection of enemies in explored territory
|
||||
BOOLEAN fDetectEnemiesDynamic; // Detection of enemies in Mobile Militia areas
|
||||
BOOLEAN fDetectEnemiesAnywhere; // Detection of enemies all over the map
|
||||
BOOLEAN fCountEnemiesInWild; // Count number of enemies in wilderness sectors
|
||||
BOOLEAN fCountEnemiesInCities; // Count number of enemies in city sectors
|
||||
|
||||
INT16 sSkyriderCostModifier; // Flat modifier for Skyrider's Cost Per Tile
|
||||
UINT16 usMineIncomeModifier; // Percentage income adjustment
|
||||
BOOLEAN fOnlyLocalMineAffected; // Determines whether income modifier applies to local mine only, or all mines.
|
||||
|
||||
UINT8 ubMinimumStrength; // Minimum STR Requirement to begin this assignment
|
||||
UINT8 ubMinimumHealth; // Minimum HLT Requirement to begin this assignment
|
||||
UINT8 ubMinimumWisdom; // Minimum WIS Requirement to begin this assignment
|
||||
UINT8 ubMinimumAgility; // Minimum AGI Requirement to begin this assignment
|
||||
UINT8 ubMinimumDexterity; // Minimum DEX Requirement to begin this assignment
|
||||
UINT8 ubMinimumMarksmanship; // Minimum MRK Requirement to begin this assignment
|
||||
UINT8 ubMinimumLeadership; // Minimum LDR Requirement to begin this assignment
|
||||
UINT8 ubMinimumExplosives; // Minimum EXP Requirement to begin this assignment
|
||||
UINT8 ubMinimumMechanical; // Minimum MEC Requirement to begin this assignment
|
||||
UINT8 ubMinimumMedical; // Minimum MED Requirement to begin this assignment
|
||||
UINT8 ubMinimumLevel; // Minimum LVL Requirement to begin this assignment
|
||||
|
||||
UINT8 ubMinimumLoyaltyHere; // Minimum loyalty required in the town where the facility is placed (if any)
|
||||
UINT8 ubMinimumBreath; // Minimum Breath Requirement to begin this assignment
|
||||
UINT8 ubMinimumMorale; // Minimum Morale Requirement to begin this assignment
|
||||
|
||||
FACILITYRISKTYPE Risk[ NUM_RISKS ]; // Data about risks/chances possible when doing this assignment
|
||||
|
||||
} FACILITYASSIGNMENTTYPE;
|
||||
|
||||
// HEADROCK HAM 3.5: Facility Type
|
||||
typedef struct FACILITYTYPE
|
||||
{
|
||||
// Basic data about the facility
|
||||
|
||||
CHAR16 szFacilityName[30]; // Long facility name
|
||||
CHAR16 szFacilityShortName[15]; // Short facility name
|
||||
UINT8 ubTotalStaffLimit; // Total number of people who can work here simultaneously
|
||||
|
||||
UINT8 ubMilitiaTrainersAllowed; // Number of Militia trainers allowed simultaneously
|
||||
UINT8 ubMobileMilitiaTrainersAllowed; // Number of Mobile Militia trainers allowed simultaneously
|
||||
UINT16 usMilitiaTraining; // Percentage effectiveness of Militia training (100 = normal)
|
||||
UINT16 usMobileMilitiaTraining; // Percentage effectiveness of Mobile Militia training (100 = normal)
|
||||
|
||||
FACILITYASSIGNMENTTYPE AssignmentData[ NUM_FACILITY_ASSIGNMENTS ]; // Data about possible assignments that can be done here
|
||||
|
||||
} FACILITYTYPE;
|
||||
|
||||
|
||||
// HEADROCK HAM 3.5: Maximum number of different facility types
|
||||
#define MAX_NUM_FACILITY_TYPES 255
|
||||
// HEADROCK HAM 3.5: Number of facilities placed on the map
|
||||
extern UINT16 NUM_FACILITIES;
|
||||
// HEADROCK HAM 3.5: Number of facility types read from XML
|
||||
extern UINT16 NUM_FACILITY_TYPES;
|
||||
// HEADROCK HAM 3.4: Array to hold facilities in each sector
|
||||
extern FACILITYLOCATIONS gFacilityLocations[256][MAX_NUM_FACILITY_TYPES];
|
||||
// HEADROCK HAM 3.5: Array to hold all different facility types
|
||||
extern FACILITYTYPE gFacilityTypes[MAX_NUM_FACILITY_TYPES];
|
||||
|
||||
// HEADROCK HAM 3.6: Bloodcat Placement and Encounter data.
|
||||
typedef struct BLOODCATPLACEMENT
|
||||
{
|
||||
UINT8 PlacementType;
|
||||
UINT8 ubMinBloodcats;
|
||||
UINT8 ubMaxBloodcats;
|
||||
UINT8 ubAmbushChance;
|
||||
BOOLEAN ubFactionAffiliation;
|
||||
BOOLEAN fRespawn;
|
||||
}BLOODCATPLACEMENT;
|
||||
|
||||
// HEADROCK HAM 3.6: Array to hold bloodcat placements and user-set bloodcat encounter data. There are 256 of these
|
||||
// (one for each sector), with 4 sublevels (one for each difficulty)
|
||||
extern BLOODCATPLACEMENT gBloodcatPlacements[256][4];
|
||||
// Location of the Bloodcat Lair. There can be only one, as there's a quest that relies on its location. This is a
|
||||
// sectorID, 0-255.
|
||||
extern UINT8 gubBloodcatLairSectorId;
|
||||
|
||||
// HEADROCK HAM 3.6: Enumerated Bloodcat Placement types
|
||||
enum
|
||||
{
|
||||
BLOODCAT_PLACEMENT_AMBUSH = 0,
|
||||
BLOODCAT_PLACEMENT_STATIC,
|
||||
BLOODCAT_PLACEMENT_LAIR,
|
||||
NUM_BLOODCAT_PLACEMENT_TYPES
|
||||
};
|
||||
|
||||
//Vehicle types
|
||||
#define FOOT 0x01 //anywhere
|
||||
@@ -227,8 +422,8 @@ typedef struct SECTORINFO
|
||||
//throught the sector without entering it.
|
||||
INT8 bNameId;
|
||||
INT8 bUSUSED;
|
||||
INT8 bBloodCats;
|
||||
INT8 bBloodCatPlacements;
|
||||
INT8 bBloodCats; // Actual number of bloodcats existing on this map.
|
||||
INT8 bBloodCatPlacements; // "Maximum" potential bloodcats that can appear on this map.
|
||||
INT8 UNUSEDbSAMCondition;
|
||||
|
||||
UINT8 ubTravelRating; //Represents how travelled a sector is. Typically, the higher the travel rating,
|
||||
@@ -236,15 +431,22 @@ typedef struct SECTORINFO
|
||||
//around. This value is used for determining how often items would "vanish" from
|
||||
//a sector (nice theory, except it isn't being used that way. Stealing is only in towns. ARM)
|
||||
UINT8 ubNumberOfCivsAtLevel[ MAX_MILITIA_LEVELS ]; // town militia per experience class, 0/1/2 is GREEN/REGULAR/ELITE
|
||||
UINT16 usUNUSEDMilitiaLevels; // unused (ARM)
|
||||
UINT8 ubUNUSEDNumberOfJoeBlowCivilians; // unused (ARM)
|
||||
// HEADROCK HAM 3.6: Adding separate training percentage for MOBILES.
|
||||
UINT8 ubMobileMilitiaTrainingPercentDone;
|
||||
UINT8 ubMobileMilitiaTrainingHundredths;
|
||||
BOOLEAN fMobileMilitiaTrainingPaid;
|
||||
// Replacing these variables with the ones above. They really are unused.
|
||||
//UINT16 usUNUSEDMilitiaLevels; // unused (ARM)
|
||||
//UINT8 ubUNUSEDNumberOfJoeBlowCivilians; // unused (ARM)
|
||||
UINT32 uiTimeCurrentSectorWasLastLoaded; //Specifies the last time the player was in the sector
|
||||
UINT8 ubUNUSEDNumberOfEnemiesThoughtToBeHere; // using bLastKnownEnemies instead
|
||||
UINT32 uiTimeLastPlayerLiberated; //in game seconds (used to prevent the queen from attacking for awhile)
|
||||
|
||||
BOOLEAN fSurfaceWasEverPlayerControlled;
|
||||
|
||||
UINT8 bFiller1;
|
||||
// HEADROCK HAM 3.6: Flag to determine whether enemy units in this sector can be seen, and whether their numbers
|
||||
// should be displayed. One filler was replaced to make room.
|
||||
UINT8 ubDetectionLevel;
|
||||
UINT8 bFiller2;
|
||||
UINT8 bFiller3;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,78 @@
|
||||
#ifndef _FACILITIES_H
|
||||
#define _FACILITIES_H
|
||||
|
||||
#include "campaign types.h"
|
||||
#include "Soldier Control.h"
|
||||
|
||||
// Get a specific modifier for a specific assignment at a specific facility. Includes Ambient (non-assignment based)
|
||||
// effects, if any.
|
||||
INT16 GetFacilityModifier( UINT8 ubModifierType, UINT8 ubFacilityType, UINT8 ubAssignmentType );
|
||||
// Get a specific modifier from all facilities in the soldier's sector. This utilizes the above function.
|
||||
INT16 GetSectorModifier( SOLDIERTYPE *pSoldier, UINT8 ubModifierType );
|
||||
|
||||
// Level of awareness to enemy movements, bestowed by facilities
|
||||
extern void UpdateStrategicDetectionLevel( );
|
||||
|
||||
// Adjustment to Skyrider's cost-per-tile, bestowed by facilities
|
||||
extern void UpdateSkyriderCostModifier( );
|
||||
extern INT16 gsSkyriderCostModifier; // This variable is SAVED/LOADED
|
||||
|
||||
// HEADROCK HAM 3.6: Strategic info variable, total of costs accumulated for the use of facilities today. Deducted
|
||||
// from account and reset at midnight, unless player can't pay (in which case, carries over to the next day).
|
||||
extern INT32 giTotalOwedForFacilityOperationsToday; // This variable is SAVED and LOADED.
|
||||
// Do we have outstanding debts for facility operation?
|
||||
extern BOOLEAN gfOutstandingFacilityDebt; // This variable is SAVED and LOADED.
|
||||
|
||||
// Place this here for facility staffing checks.
|
||||
extern UINT32 GetWorldTotalMin( );
|
||||
|
||||
// These are all the different modifiers we could be checking for.
|
||||
enum
|
||||
{
|
||||
FACILITY_PERFORMANCE_MOD = 0,
|
||||
FACILITY_SLEEP_MOD,
|
||||
FACILITY_FATIGUE_MOD,
|
||||
FACILITY_KIT_DEGRADE_MOD,
|
||||
|
||||
FACILITY_MAX_MORALE,
|
||||
FACILITY_MAX_BREATH,
|
||||
|
||||
FACILITY_DETECT_IMMEDIATE,
|
||||
FACILITY_DETECT_DYNAMIC,
|
||||
FACILITY_DETECT_LONGRANGE,
|
||||
FACILITY_DETECT_ANYWHERE,
|
||||
FACILITY_COUNT_INWILD,
|
||||
FACILITY_COUNT_INCITIES,
|
||||
|
||||
FACILITY_MINE_INCOME_MOD,
|
||||
FACILITY_SKYRIDER_COST_MOD,
|
||||
};
|
||||
|
||||
// HEADROCK HAM 3.6: Different enemy detection and counting levels
|
||||
enum
|
||||
{
|
||||
DETECT_ENEMIES_DYNAMIC = 0,
|
||||
DETECT_ENEMIES_LONGRANGE,
|
||||
DETECT_ENEMIES_ANYWHERE,
|
||||
|
||||
COUNT_ENEMIES_IN_WILD,
|
||||
COUNT_ENEMIES_IN_CITIES,
|
||||
};
|
||||
|
||||
void UpdateGlobalVariablesFromFacilities( void );
|
||||
void UpdateFacilityUsageCosts( void );
|
||||
|
||||
void HandleDailyPaymentFacilityDebt( void );
|
||||
void HandleManualPaymentFacilityDebt( void );
|
||||
void HandleHourlyRisks( void );
|
||||
|
||||
INT32 MineIncomeModifierFromFacility( UINT8 ubMine );
|
||||
INT8 GetSoldierFacilityAssignmentIndex( SOLDIERTYPE *pSoldier );
|
||||
void HandleRisksForSoldier( SOLDIERTYPE *pSoldier );
|
||||
void HandleRisksForSoldierFacilityAssignment( SOLDIERTYPE *pSoldier, UINT8 ubFacilityType, UINT8 ubAssignmentType );
|
||||
INT16 FacilityRiskResult( SOLDIERTYPE *pSoldier, UINT8 ubRiskType, UINT8 ubFacilityType, UINT8 ubAssignmentType );
|
||||
INT32 GetTotalFacilityHourlyCosts( BOOLEAN fPositive );
|
||||
|
||||
void InitFacilities();
|
||||
|
||||
#endif
|
||||
+78
-2
@@ -61,6 +61,8 @@
|
||||
#include "Interface.h"
|
||||
#include "cheats.h"
|
||||
#include "Interface Panels.h"
|
||||
// HEADROCK HAM 3.6: Include for adding facility debt reset
|
||||
#include "Facilities.h"
|
||||
#endif
|
||||
|
||||
#include "Vehicles.h"
|
||||
@@ -233,6 +235,64 @@ void InitNPCs( void )
|
||||
|
||||
void InitBloodCatSectors()
|
||||
{
|
||||
///////////////////////////////////////////////////
|
||||
// HEADROCK HAM 3.6: Bloodcat Placement Externalization
|
||||
//
|
||||
// It is now possible for the user/modder to set the maximum number of bloodcats that may appear in the sector.
|
||||
// We can now place bloodcats anywhere we'd like (aboveground), stretching the limits of maps without disturbing
|
||||
// the game. The placements defined here are still the absolute MAXIMUM, so if the map has more placements available
|
||||
// they will be ignored.
|
||||
// Please note that if the mapfile has LESS placements than indicated here, then the game will reduce the number of
|
||||
// placements automatically to fit the MAP, not the XML.
|
||||
|
||||
UINT16 x = 0;
|
||||
UINT8 PlacementType = 0;
|
||||
UINT8 ubMaxBloodcats = 0;
|
||||
UINT8 ubDifficulty = gGameOptions.ubDifficultyLevel-1; // This way, novice=0.
|
||||
INT16 ubLairSectorId = -1; // Location of ONE lair sector (the first one found)
|
||||
|
||||
// Clean all bloodcat data.
|
||||
for( x = 0; x < 256; x++ )
|
||||
{
|
||||
SectorInfo[ x ].bBloodCats = 0;
|
||||
SectorInfo[ x ].bBloodCatPlacements = 0;
|
||||
}
|
||||
|
||||
// Begin loop for every sector.
|
||||
for (x = 0; x < 256; x++)
|
||||
{
|
||||
// Set "maximum placements" value to whatever is defined in the XML file for this difficulty level.
|
||||
SectorInfo[ x ].bBloodCatPlacements = gBloodcatPlacements[x][ubDifficulty].ubMaxBloodcats;
|
||||
|
||||
PlacementType = gBloodcatPlacements[x][0].PlacementType;
|
||||
|
||||
// Record the first sector you can find which is defined as a LAIR sector. Only one sector can serve
|
||||
// this purpose, because the quests rely on it.
|
||||
if (PlacementType == BLOODCAT_PLACEMENT_LAIR && ubLairSectorId == -1)
|
||||
{
|
||||
ubLairSectorId = x;
|
||||
}
|
||||
|
||||
if (PlacementType != 0)
|
||||
{
|
||||
// Sector is a lair or static bloodcat sector. Fill it up with actual bloodcats please.
|
||||
SectorInfo[ x ].bBloodCats = gBloodcatPlacements[x][ubDifficulty].ubMaxBloodcats;
|
||||
// "Ambush" sectors (PlacementType 0) do not have bloodcats in them until triggered.
|
||||
}
|
||||
}
|
||||
|
||||
if (ubLairSectorId >= 0)
|
||||
{
|
||||
gubBloodcatLairSectorId = (UINT8)ubLairSectorId;
|
||||
}
|
||||
else
|
||||
{
|
||||
THROWEXCEPTION(L"At least one Bloodcat Lair must be defined in BloodcatPlacements.XML!");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
|
||||
INT32 i;
|
||||
//Hard coded table of bloodcat populations. We don't have
|
||||
//access to the real population (if different) until we physically
|
||||
@@ -296,7 +356,7 @@ void InitBloodCatSectors()
|
||||
SectorInfo[ SEC_N5 ].bBloodCatPlacements = 18;
|
||||
SectorInfo[ SEC_N5 ].bBloodCats = 18;
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
@@ -334,6 +394,8 @@ void InitStrategicLayer( void )
|
||||
// make Orta, Tixa, SAM sites not found
|
||||
InitMapSecrets();
|
||||
|
||||
// HEADROCK HAM 3.6: Initialize facilities.
|
||||
InitFacilities();
|
||||
|
||||
// free up any leave list arrays that were left allocated
|
||||
ShutDownLeaveList( );
|
||||
@@ -344,7 +406,8 @@ void InitStrategicLayer( void )
|
||||
SetGameTimeCompressionLevel( TIME_COMPRESS_X0 );
|
||||
|
||||
// select A9 Omerta as the initial selected sector
|
||||
ChangeSelectedMapSector( startingX, startingY, startingZ );
|
||||
// HEADROCK HAM 3.5: Actually, this is where we set the starting sector based on external variables.
|
||||
ChangeSelectedMapSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ );
|
||||
|
||||
// Reset these flags or mapscreen could be disabled and cause major headache.
|
||||
fDisableDueToBattleRoster = FALSE;
|
||||
@@ -498,6 +561,10 @@ BOOLEAN InitNewGame( BOOLEAN fReset )
|
||||
AddFutureDayStrategicEvent( EVENT_DAY3_ADD_EMAIL_FROM_SPECK, 60*7, 0, uiDaysTimeMercSiteAvailable );
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.5: Reset LZ to default arrival
|
||||
gsMercArriveSectorX = gGameExternalOptions.ubDefaultArrivalSectorX;
|
||||
gsMercArriveSectorY = gGameExternalOptions.ubDefaultArrivalSectorY;
|
||||
|
||||
#ifdef CRIPPLED_VERSION
|
||||
{
|
||||
UINT32 cnt;
|
||||
@@ -864,6 +931,15 @@ void ReStartingGame()
|
||||
//Reload the Merc profiles
|
||||
LoadMercProfiles( );
|
||||
|
||||
if (gGameExternalOptions.fWriteProfileDataToXML)
|
||||
{
|
||||
// HEADROCK PROFEX: Create mercprofiles xml output
|
||||
WriteMercProfiles();
|
||||
|
||||
// HEADROCK PROFEX: Create mercopinions xml output
|
||||
WriteMercOpinions();
|
||||
}
|
||||
|
||||
// Reload quote files
|
||||
ReloadAllQuoteFiles();
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "SaveLoadGame.h"
|
||||
#include "GameSettings.h"
|
||||
#include "connect.h"
|
||||
// HEADROCK HAM 3.5: Add facility code for hourly update of detection levels
|
||||
#include "Facilities.h"
|
||||
|
||||
void HourlyQuestUpdate( void );
|
||||
void HourlyLarryUpdate( void );
|
||||
@@ -56,9 +58,17 @@ void HandleHourlyUpdate()
|
||||
// hourly update of team assignments
|
||||
UpdateAssignments();
|
||||
|
||||
// HEADROCK HAM 3.5: Tells the rest of the program whether we've got mercs working on detecting enemy units.
|
||||
UpdateStrategicDetectionLevel();
|
||||
|
||||
// HEADROCK HAM 3.5: Re-calculates a modifier to Skyrider's flight costs based on mercs working in specific facilities.
|
||||
UpdateSkyriderCostModifier();
|
||||
|
||||
// hourly update of hated/liked mercs
|
||||
UpdateBuddyAndHatedCounters();
|
||||
|
||||
HandleHourlyRisks();
|
||||
|
||||
// update morale!
|
||||
HourlyMoraleUpdate();
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "soundman.h"
|
||||
#include "Isometric Utils.h"
|
||||
#include "Scheduling.h"
|
||||
// HEADROCK HAM 3.5: Added facility-based skyrider costs modifier
|
||||
#include "Facilities.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -527,16 +529,23 @@ INT32 GetCostOfPassageForHelicopter( INT16 sX, INT16 sY )
|
||||
// check if sector is air controlled or not, if so, then normal cost, otherwise increase the cost
|
||||
INT32 iCost = 0;
|
||||
|
||||
// HEADROCK HAM 3.5: Costs externalized
|
||||
INT32 iBaseCostPerGreenTile = gGameExternalOptions.usHelicopterBaseCostPerGreenTile;
|
||||
INT32 iBaseCostPerRedTile = gGameExternalOptions.usHelicopterBaseCostPerRedTile;
|
||||
|
||||
// if they don't control it
|
||||
if( StrategicMap[ CALCULATE_STRATEGIC_INDEX( sX, sY ) ].fEnemyAirControlled == FALSE )
|
||||
{
|
||||
iCost = COST_AIRSPACE_SAFE;
|
||||
iCost = iBaseCostPerGreenTile;
|
||||
}
|
||||
else
|
||||
{
|
||||
iCost = COST_AIRSPACE_UNSAFE;
|
||||
iCost = iBaseCostPerRedTile;
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.5: Apply facility-based modifiers from global integer recalculated hourly
|
||||
iCost = __max(0, iCost + gsSkyriderCostModifier);
|
||||
|
||||
return( iCost );
|
||||
}
|
||||
|
||||
|
||||
@@ -773,7 +773,9 @@ void ToggleShowMilitiaMode( void )
|
||||
// no - so put up a message explaining how it works
|
||||
|
||||
// if he's already training some
|
||||
if( IsAnyOneOnPlayersTeamOnThisAssignment( TRAIN_TOWN ) )
|
||||
// HEADROCK HAM 3.6: Also for Mobile trainers.
|
||||
if( IsAnyOneOnPlayersTeamOnThisAssignment( TRAIN_TOWN ) ||
|
||||
IsAnyOneOnPlayersTeamOnThisAssignment( TRAIN_MOBILE ) )
|
||||
{
|
||||
// say they'll show up when training is completed
|
||||
pwString = pMapErrorString[ 28 ];
|
||||
|
||||
@@ -68,8 +68,12 @@ want to have the new inventory panel not overlap the message text area. */
|
||||
#define MESSAGE_SCROLL_AREA_HEIGHT ( MESSAGE_SCROLL_AREA_END_Y - MESSAGE_SCROLL_AREA_START_Y + 1 )
|
||||
|
||||
// CHRISL: Use these if we want scroll bar based on left edge of screen
|
||||
#define MESSAGE_SCROLL_AREA_START_X 330
|
||||
#define MESSAGE_SCROLL_AREA_END_X 344
|
||||
// HEADROCK HAM 3.6: Now global variables to be changed when initializing map mode.
|
||||
// See InitMapScreenInterfaceBottomCoords()
|
||||
//#define MESSAGE_SCROLL_AREA_START_X 330
|
||||
//#define MESSAGE_SCROLL_AREA_END_X 344
|
||||
UINT16 MESSAGE_SCROLL_AREA_START_X;
|
||||
UINT16 MESSAGE_SCROLL_AREA_END_X;
|
||||
|
||||
#define SLIDER_HEIGHT 11
|
||||
#define SLIDER_WIDTH 11
|
||||
@@ -184,6 +188,7 @@ void DeleteMapScreenBottomMessageScrollRegion( void );
|
||||
void DisplayCurrentBalanceForMapBottom( void );
|
||||
void DisplayCurrentBalanceTitleForMapBottom( void );
|
||||
void DisplayProjectedDailyMineIncome( void );
|
||||
void DisplayProjectedDailyExpenses( void ); // HEADROCK HAM 3.6: New expenses window shows running costs today.
|
||||
void DrawNameOfLoadedSector( void );
|
||||
|
||||
void EnableDisableBottomButtonsAndRegions( void );
|
||||
@@ -296,7 +301,8 @@ void RenderMapScreenInterfaceBottom( BOOLEAN fForceMapscreenFullRender )
|
||||
// render whole panel
|
||||
// HEADROCK Changed this line to accept outside influence through the new boolean:
|
||||
//if ( fForceMapscreenFullRender == TRUE || fMapScreenBottomDirty == TRUE)
|
||||
if ( fMapScreenBottomDirty )
|
||||
// HEADROCK HAM 3.6: OK, let's always render this panel, as long as the team inventory screen isn't open.
|
||||
if ( fMapScreenBottomDirty || !fShowInventoryFlag )
|
||||
{
|
||||
// get and blt panel
|
||||
GetVideoObject(&hHandle, guiMAPBOTTOMPANEL );
|
||||
@@ -334,12 +340,20 @@ void RenderMapScreenInterfaceBottom( BOOLEAN fForceMapscreenFullRender )
|
||||
|
||||
// Headrock: Moved this next line from the above marker ^
|
||||
fMapScreenBottomDirty = FALSE;
|
||||
|
||||
// CHRISL: Don't display messagelist if inventory panel is open
|
||||
// CHRISL: Only run this condition if we're drawing the message list on the left
|
||||
// display messages that can be scrolled through
|
||||
// HEADROCK HAM 3.6: Hmmmm, why not draw them? LEt's just move this whole segment here, shall we?
|
||||
//if(!fShowInventoryFlag)
|
||||
DisplayStringsInMapScreenMessageList( );
|
||||
}
|
||||
|
||||
DisplayCompressMode( );
|
||||
|
||||
DisplayCurrentBalanceForMapBottom( );
|
||||
DisplayProjectedDailyMineIncome( );
|
||||
DisplayProjectedDailyExpenses( );
|
||||
|
||||
// draw the name of the loaded sector
|
||||
DrawNameOfLoadedSector( );
|
||||
@@ -347,12 +361,7 @@ void RenderMapScreenInterfaceBottom( BOOLEAN fForceMapscreenFullRender )
|
||||
// display slider on the scroll bar
|
||||
DisplayScrollBarSlider( );
|
||||
|
||||
// CHRISL: Don't display messagelist if inventory panel is open
|
||||
// CHRISL: Only run this condition if we're drawing the message list on the left
|
||||
// display messages that can be scrolled through
|
||||
if(!fShowInventoryFlag)
|
||||
DisplayStringsInMapScreenMessageList( );
|
||||
|
||||
|
||||
// handle auto scroll
|
||||
//CheckForAndHandleAutoMessageScroll( );
|
||||
|
||||
@@ -427,10 +436,12 @@ BOOLEAN CreateButtonsForMapScreenInterfaceBottom( void )
|
||||
// BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
||||
// (GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnMessageDownMapScreenCallback);
|
||||
// CHRISL: Use these if we want buttons based on left edge of screen
|
||||
guiMapMessageScrollButtons[ MAP_SCROLL_MESSAGE_UP ] = QuickCreateButton( guiMapMessageScrollButtonsImage[ MAP_SCROLL_MESSAGE_UP ], 331, (SCREEN_HEIGHT - 109),
|
||||
// HEADROCK HAM 3.6: Message window is now as wide as possible.
|
||||
|
||||
guiMapMessageScrollButtons[ MAP_SCROLL_MESSAGE_UP ] = QuickCreateButton( guiMapMessageScrollButtonsImage[ MAP_SCROLL_MESSAGE_UP ], (SCREEN_WIDTH - 306), (SCREEN_HEIGHT - 109),
|
||||
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
||||
(GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnMessageUpMapScreenCallback);
|
||||
guiMapMessageScrollButtons[ MAP_SCROLL_MESSAGE_DOWN ] = QuickCreateButton( guiMapMessageScrollButtonsImage[ MAP_SCROLL_MESSAGE_DOWN ], 331, (SCREEN_HEIGHT - 28),
|
||||
guiMapMessageScrollButtons[ MAP_SCROLL_MESSAGE_DOWN ] = QuickCreateButton( guiMapMessageScrollButtonsImage[ MAP_SCROLL_MESSAGE_DOWN ], (SCREEN_WIDTH - 306), (SCREEN_HEIGHT - 28),
|
||||
BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1,
|
||||
(GUI_CALLBACK)BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)BtnMessageDownMapScreenCallback);
|
||||
|
||||
@@ -1334,7 +1345,8 @@ BOOLEAN AllowedToTimeCompress( void )
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if( fShowAssignmentMenu || fShowTrainingMenu || fShowAttributeMenu || fShowSquadMenu || fShowContractMenu || fShowRemoveMenu )
|
||||
// HEADROCK HAM 3.6: Added Facility Menus
|
||||
if( fShowAssignmentMenu || fShowTrainingMenu || fShowAttributeMenu || fShowSquadMenu || fShowContractMenu || fShowRemoveMenu || fShowFacilityAssignmentMenu || fShowFacilityMenu )
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
@@ -1428,7 +1440,9 @@ void DisplayCurrentBalanceTitleForMapBottom( void )
|
||||
// CHRISL: Replaced X coordinate with dynamic coordinate set from right edge of screen
|
||||
//VarFindFontCenterCoordinates( (SCREEN_WIDTH - 637), (SCREEN_HEIGHT - 107), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
// CHRISL: Use this if we want to display from the left edge
|
||||
VarFindFontCenterCoordinates( 359, (SCREEN_HEIGHT - 107), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
//VarFindFontCenterCoordinates( 359, (SCREEN_HEIGHT - 107), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
// HEADROCK HAM 3.6: The balance/income box has been moved to the right side, near the laptop button.
|
||||
VarFindFontCenterCoordinates( (SCREEN_WIDTH - 278), (SCREEN_HEIGHT - 111), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
|
||||
// print it
|
||||
mprintf( sFontX, sFontY, L"%s", sString );
|
||||
@@ -1439,7 +1453,18 @@ void DisplayCurrentBalanceTitleForMapBottom( void )
|
||||
// CHRISL: Replaced X coordinate with dynamic coordinate set from right edge of screen
|
||||
//VarFindFontCenterCoordinates( (SCREEN_WIDTH - 637), (SCREEN_HEIGHT - 61), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
// CHRISL: Use this if we want to display from the left edge
|
||||
VarFindFontCenterCoordinates( 359, (SCREEN_HEIGHT - 61), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
//VarFindFontCenterCoordinates( 359, (SCREEN_HEIGHT - 61), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
// HEADROCK HAM 3.6: The balance/income box has been moved to the right side, near the laptop button.
|
||||
VarFindFontCenterCoordinates( (SCREEN_WIDTH - 278), (SCREEN_HEIGHT - 74), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
|
||||
// print it
|
||||
mprintf( sFontX, sFontY, L"%s", sString );
|
||||
|
||||
swprintf( sString, L"%s", New113HAMMessage[ 20 ] );
|
||||
|
||||
// HEADROCK HAM 3.6: Projected expenses for today, with facilities (and in the future, merc contracts) taken into
|
||||
// account.
|
||||
VarFindFontCenterCoordinates( (SCREEN_WIDTH - 278), (SCREEN_HEIGHT - 37), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
|
||||
// print it
|
||||
mprintf( sFontX, sFontY, L"%s", sString );
|
||||
@@ -1474,7 +1499,9 @@ void DisplayCurrentBalanceForMapBottom( void )
|
||||
// CHRISL: Replaced X coordinate with dynamic coordinate set from right edge of screen
|
||||
//VarFindFontCenterCoordinates( (SCREEN_WIDTH - 637), (SCREEN_HEIGHT - 91), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
// CHRISL: Use this if we want to display from the left edge
|
||||
VarFindFontCenterCoordinates( 359, (SCREEN_HEIGHT - 91), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
//VarFindFontCenterCoordinates( 359, (SCREEN_HEIGHT - 91), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
// HEADROCK HAM 3.6: The balance/income box has been moved to the right side, near the laptop button.
|
||||
VarFindFontCenterCoordinates( (SCREEN_WIDTH - 278), (SCREEN_HEIGHT - 95), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
|
||||
// print it
|
||||
mprintf( sFontX, sFontY, L"%s", sString );
|
||||
@@ -1588,7 +1615,9 @@ void DisplayProjectedDailyMineIncome( void )
|
||||
// CHRISL: Replaced X coordinate with dynamic coordinate set from right edge of screen
|
||||
//VarFindFontCenterCoordinates( (SCREEN_WIDTH - 637), (SCREEN_HEIGHT - 45), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
// CHRISL: Use this if we want to display from the left edge
|
||||
VarFindFontCenterCoordinates( 359, (SCREEN_HEIGHT - 45), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
//VarFindFontCenterCoordinates( 359, (SCREEN_HEIGHT - 45), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
// HEADROCK HAM 3.6: The balance/income box has been moved to the right side, near the laptop button.
|
||||
VarFindFontCenterCoordinates( (SCREEN_WIDTH - 278), (SCREEN_HEIGHT - 58), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
|
||||
// print it
|
||||
mprintf( sFontX, sFontY, L"%s", sString );
|
||||
@@ -1596,6 +1625,58 @@ void DisplayProjectedDailyMineIncome( void )
|
||||
return;
|
||||
}
|
||||
|
||||
void DisplayProjectedDailyExpenses( void )
|
||||
{
|
||||
INT32 iRate = 0;
|
||||
static INT32 iOldExpensesRate = -1;
|
||||
CHAR16 sString[ 128 ];
|
||||
INT16 sFontX, sFontY;
|
||||
|
||||
// grab the rate from the financial system
|
||||
iRate = GetProjectedExpenses( );
|
||||
|
||||
if( iRate != iOldExpensesRate )
|
||||
{
|
||||
iOldExpensesRate = iRate;
|
||||
fMapScreenBottomDirty = TRUE;
|
||||
|
||||
// if screen was not dirtied, leave
|
||||
if( fMapBottomDirtied == FALSE )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// set the font buffer
|
||||
SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
|
||||
|
||||
// set up the font
|
||||
SetFont( COMPFONT );
|
||||
if (iRate == 0)
|
||||
{
|
||||
SetFontForeground( 183 );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFontForeground( FONT_MCOLOR_LTRED );
|
||||
}
|
||||
SetFontBackground( FONT_BLACK );
|
||||
|
||||
swprintf( sString, L"%d", iRate );
|
||||
|
||||
// insert extra characters
|
||||
InsertCommasForDollarFigure( sString );
|
||||
InsertDollarSignInToString( sString );
|
||||
|
||||
// center it
|
||||
VarFindFontCenterCoordinates( (SCREEN_WIDTH - 278), (SCREEN_HEIGHT - 21), 78, 10, COMPFONT, &sFontX, &sFontY, sString );
|
||||
|
||||
// print it
|
||||
mprintf( sFontX, sFontY, L"%s", sString );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN CommonTimeCompressionChecks( void )
|
||||
{
|
||||
@@ -1950,3 +2031,11 @@ void ChangeCurrentMapscreenMessageIndex( UINT8 ubNewMessageIndex )
|
||||
// refresh screen
|
||||
fMapScreenBottomDirty = TRUE;
|
||||
}
|
||||
|
||||
void InitMapScreenInterfaceBottomCoords( void )
|
||||
{
|
||||
// HEADROCK HAM 3.6: Message window is now as wide as possible.
|
||||
MESSAGE_SCROLL_AREA_START_X = SCREEN_WIDTH - 307;
|
||||
MESSAGE_SCROLL_AREA_END_X = SCREEN_WIDTH - 293;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,4 +65,7 @@ void MapScreenMsgScrollUp( UINT8 ubLinesUp );
|
||||
void ChangeCurrentMapscreenMessageIndex( UINT8 ubNewMessageIndex );
|
||||
void MoveToEndOfMapScreenMessageList( void );
|
||||
|
||||
// HEADROCK HAM 3.6: Reset coordinates for slider bar and message window
|
||||
void InitMapScreenInterfaceBottomCoords( void );
|
||||
|
||||
#endif
|
||||
@@ -582,6 +582,8 @@ void CreateDestroyMapInventoryPoolButtons( BOOLEAN fExitFromMapScreen )
|
||||
fMapPanelDirty = TRUE;
|
||||
fTeamPanelDirty = TRUE;
|
||||
fCharacterInfoPanelDirty = TRUE;
|
||||
// HEADROCK HAM 3.6: Yet again, make sure to refresh the bottom panel on closing.
|
||||
fMapScreenBottomDirty = TRUE;
|
||||
|
||||
//CHRISL: close stack popup and item description windows
|
||||
DeleteItemStackPopup();
|
||||
@@ -1471,8 +1473,6 @@ void BeginInventoryPoolPtr( OBJECTTYPE *pInventorySlot )
|
||||
{
|
||||
for( UINT32 iNumber = 0 ; iNumber < pInventoryPoolList.size() ; ++iNumber)
|
||||
{
|
||||
// WANNE: Fix by Headrock
|
||||
//if ( pInventoryPoolList[ iNumber ].object.usItem == gItemPointer.usItem )
|
||||
if ( pInventoryPoolList[ iNumber ].object.usItem == gItemPointer.usItem && pInventoryPoolList[ iNumber ].usFlags & WORLD_ITEM_REACHABLE)
|
||||
{
|
||||
iPrice += SellItem( pInventoryPoolList[ iNumber ].object );
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
|
||||
#include "Quests.h"
|
||||
#include "connect.h"
|
||||
// HEADROCK HAM 3.5: included for detectionlevels
|
||||
#include "Facilities.h"
|
||||
#include "MilitiaSquads.h"
|
||||
|
||||
// zoom x and y coords for map scrolling
|
||||
INT32 iZoomX = 0;
|
||||
@@ -355,8 +358,9 @@ extern BOOLEAN fMapScreenBottomDirty;
|
||||
BOOLEAN fFoundTixa = FALSE;
|
||||
|
||||
// selected sector
|
||||
UINT16 sSelMapX = 9;
|
||||
UINT16 sSelMapY = 1;
|
||||
// HEADROCK HAM 3.5: Default selected sector doesn't have to be Omerta does it? :)
|
||||
UINT16 sSelMapX = gGameExternalOptions.ubDefaultArrivalSectorX;
|
||||
UINT16 sSelMapY = gGameExternalOptions.ubDefaultArrivalSectorY;
|
||||
|
||||
// highlighted sector
|
||||
INT16 gsHighlightSectorX=-1;
|
||||
@@ -522,6 +526,7 @@ void CreateMilitiaPanelBottomButton( void );
|
||||
void DeleteMilitiaPanelBottomButton( void );
|
||||
void MilitiaDoneButtonCallback(GUI_BUTTON *btn,INT32 reason);
|
||||
void MilitiaAutoButtonCallback(GUI_BUTTON *btn,INT32 reason);
|
||||
void MilitiaDisbandYesNoBoxCallback( UINT8 bExitValue ); // HEADROCK HAM 3.6: Disband militia callback
|
||||
void RenderShadingForUnControlledSectors( void );
|
||||
void DrawTownMilitiaForcesOnMap( void );
|
||||
void CheckAndUpdateStatesOfSelectedMilitiaSectorButtons( void );
|
||||
@@ -4381,7 +4386,10 @@ void DisplayDistancesForHelicopter( void )
|
||||
|
||||
|
||||
// calculate the cost of the trip based on the number of safe and unsafe sectors it will pass through
|
||||
uiTripCost = ( sNumSafeSectors * COST_AIRSPACE_SAFE ) + ( sNumUnSafeSectors * COST_AIRSPACE_UNSAFE );
|
||||
// HEADROCK HAM 3.5: Externalized Base Cost. Also includes hourly-calculated facility modifier.
|
||||
UINT32 uiCostGreen = __max(0,gGameExternalOptions.usHelicopterBaseCostPerGreenTile + gsSkyriderCostModifier);
|
||||
UINT32 uiCostRed = __max(0,gGameExternalOptions.usHelicopterBaseCostPerRedTile + gsSkyriderCostModifier);
|
||||
uiTripCost = ( sNumSafeSectors * uiCostGreen ) + ( sNumUnSafeSectors * uiCostRed );
|
||||
|
||||
swprintf( sString, L"%d", uiTripCost );
|
||||
InsertCommasForDollarFigure( sString );
|
||||
@@ -6092,13 +6100,22 @@ void MilitiaDoneButtonCallback(GUI_BUTTON *btn,INT32 reason)
|
||||
{
|
||||
btn->uiFlags &= ~( BUTTON_CLICKED_ON );
|
||||
|
||||
// reset fact we are in the box
|
||||
sSelectedMilitiaTown = 0;
|
||||
fMapPanelDirty = TRUE;
|
||||
// Go ahead and reset the militia in the selected sector (even if we didn't change it here)
|
||||
if (gfStrategicMilitiaChangesMade)
|
||||
// HEADROCK HAM 3.6: Clicking the done button while militia are on the cursor causes a pop-up
|
||||
// for authorizing DISBANDING those militia.
|
||||
if (sGreensOnCursor || sRegularsOnCursor || sElitesOnCursor)
|
||||
{
|
||||
ResetMilitia();
|
||||
DoMapMessageBox( MSG_BOX_BASIC_STYLE, pMilitiaString[ 3 ], MAP_SCREEN, MSG_BOX_FLAG_YESNO, MilitiaDisbandYesNoBoxCallback );
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset fact we are in the box
|
||||
sSelectedMilitiaTown = 0;
|
||||
fMapPanelDirty = TRUE;
|
||||
// Go ahead and reset the militia in the selected sector (even if we didn't change it here)
|
||||
if (gfStrategicMilitiaChangesMade)
|
||||
{
|
||||
ResetMilitia();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6279,13 +6296,17 @@ void CheckAndUpdateStatesOfSelectedMilitiaSectorButtons( void )
|
||||
iNumberOfRegulars = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + sRegularsOnCursor;
|
||||
iNumberOfElites = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] + sElitesOnCursor;
|
||||
|
||||
// HEADROCK HAM 3.6: This button is no longer disabled when there are unassigned militia. In fact,
|
||||
// clicking the button when militia are unassigned will prompt the player to authorize disbanding them.
|
||||
if( ( sGreensOnCursor > 0 ) || ( sRegularsOnCursor > 0 ) || ( sElitesOnCursor > 0 ) )
|
||||
{
|
||||
DisableButton( giMapMilitiaButton[ 4 ] ); // DONE
|
||||
// DisableButton( giMapMilitiaButton[ 4 ] ); // DONE
|
||||
SpecifyButtonText( giMapMilitiaButton[ 4 ], pMilitiaButtonString[ 2 ] );
|
||||
}
|
||||
else
|
||||
{
|
||||
EnableButton( giMapMilitiaButton[ 4 ] ); // DONE
|
||||
// EnableButton( giMapMilitiaButton[ 4 ] ); // DONE
|
||||
SpecifyButtonText( giMapMilitiaButton[ 4 ], pMilitiaButtonString[ 1 ] );
|
||||
}
|
||||
|
||||
// greens button
|
||||
@@ -6445,34 +6466,59 @@ void ClearAnySectorsFlashingNumberOfEnemies()
|
||||
UINT32 WhatPlayerKnowsAboutEnemiesInSector( INT16 sSectorX, INT16 sSectorY )
|
||||
{
|
||||
UINT32 uiSectorFlags = SectorInfo[ SECTOR( sSectorX, sSectorY ) ].uiFlags;
|
||||
BOOLEAN fDetection = FALSE;
|
||||
BOOLEAN fCount = FALSE;
|
||||
|
||||
Assert(sSectorX > 0 && sSectorY > 0 && sSectorX < 17 && sSectorY < 17);
|
||||
|
||||
// if player has militia close enough to scout this sector out, if there are mercs who can scout here, OR
|
||||
//Special case flag used when players encounter enemies in a sector, then retreat. The number of enemies
|
||||
//will display on mapscreen until time is compressed. When time is compressed, the flag is cleared, and
|
||||
//a question mark is displayed to reflect that the player no longer knows.
|
||||
// HEADROCK HAM 3.5: There are now several ways to control the detection of enemy units. This function has been revamped
|
||||
// to consider all options. Depending on externalized settings, different conditions yield different results.
|
||||
//
|
||||
// Option #1: Vanilla Default.
|
||||
// It is possible to detect all enemies in explored territory, including cities.
|
||||
// Militia in an adjacent sector can count how many enemies are there, except standing garrisons.
|
||||
// Option #2: HAM 3.2. No Detection without Recon.
|
||||
// Mobile enemy groups are only detected if there are militia in any adjacent sector. Otherwise, they can
|
||||
// travel through explored sectors without being seen.
|
||||
//
|
||||
// Option #3: This is a new feature for HAM 3.5, which ties together with Facility Externalization.
|
||||
// In simple words, facilities can enhance detection abilities. Facilities that do so may be placed around the
|
||||
// map in any sector. When a merc with sufficient wisdom is resting here, he increases the detection "level",
|
||||
// making it easier to detect or even count enemies in distant sectors.
|
||||
// This option can be combined with either of the two above.
|
||||
|
||||
|
||||
// Detection through active recon.
|
||||
// Mercs provide recon in the same sector they're in.
|
||||
// Militia provide recon in any adjacent sector (diagonals included)
|
||||
// There's also a special case flag used when players encounter enemies in a sector, then retreat. You can only
|
||||
// see the size of their force while the clock is paused. When unpaused, the flag is reset.
|
||||
if ( CanMercsScoutThisSector( sSectorX, sSectorY, 0 ) ||
|
||||
CanNearbyMilitiaScoutThisSector( sSectorX, sSectorY ) ||
|
||||
( uiSectorFlags & SF_PLAYER_KNOWS_ENEMIES_ARE_HERE ) )
|
||||
{
|
||||
// if the enemies are stationary (i.e. mercs attacking a garrison)
|
||||
if ( NumStationaryEnemiesInSector( sSectorX, sSectorY ) > 0 )
|
||||
fDetection = TRUE;
|
||||
|
||||
// if all enemies are mobile (I.E. not garrison troops)
|
||||
if ( NumStationaryEnemiesInSector( sSectorX, sSectorY ) == 0 )
|
||||
{
|
||||
// inside a garrison - hide their # (show question mark) to match what the PBI is showing
|
||||
return KNOWS_THEYRE_THERE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// other situations - show exactly how many there are
|
||||
return KNOWS_HOW_MANY;
|
||||
// They're also counted by default.
|
||||
fCount = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// if the player has visited the sector during this game
|
||||
// Explored Sector Detection
|
||||
// Enemy can be detected in any previously-visited sector.
|
||||
// This is also enabled by some facilities, provided a merc is present and available to do it.
|
||||
if( GetSectorFlagStatus( sSectorX, sSectorY, 0, SF_ALREADY_VISITED ) == TRUE )
|
||||
{
|
||||
// then he always knows about any enemy presence for the remainder of the game, but not exact numbers
|
||||
return KNOWS_THEYRE_THERE;
|
||||
// HEADROCK HAM 3.2: When enabled, this INI setting disallows detection of enemy roamers beyond merc/militia
|
||||
// recon range.
|
||||
if (!gGameExternalOptions.fNoEnemyDetectionWithoutRecon)
|
||||
{
|
||||
// then he always knows about any enemy presence for the remainder of the game, but not exact numbers
|
||||
fDetection = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// if Skyrider noticed the enemis in the sector recently
|
||||
@@ -6482,7 +6528,7 @@ UINT32 WhatPlayerKnowsAboutEnemiesInSector( INT16 sSectorX, INT16 sSectorY )
|
||||
if( IsSkyriderIsFlyingInSector( sSectorX, sSectorY ) )
|
||||
{
|
||||
// player remains aware of them as long as Skyrider remains in the sector
|
||||
return KNOWS_THEYRE_THERE;
|
||||
fDetection = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -6491,9 +6537,32 @@ UINT32 WhatPlayerKnowsAboutEnemiesInSector( INT16 sSectorX, INT16 sSectorY )
|
||||
}
|
||||
}
|
||||
|
||||
// Facilities can set a flag that allows detection in some sectors. We can read flags directly from the sector
|
||||
// data to know whether we should show the enemies there. This overrides ANYTHING else.
|
||||
if (SectorInfo[ SECTOR( sSectorX, sSectorY ) ].ubDetectionLevel & 1)
|
||||
{
|
||||
fDetection = TRUE;
|
||||
}
|
||||
if (SectorInfo[ SECTOR( sSectorX, sSectorY ) ].ubDetectionLevel & (1<<2) )
|
||||
{
|
||||
fCount = TRUE;
|
||||
}
|
||||
|
||||
// no information available
|
||||
return KNOWS_NOTHING;
|
||||
if (!fDetection)
|
||||
{
|
||||
// no information available
|
||||
return KNOWS_NOTHING;
|
||||
}
|
||||
else if (!fCount)
|
||||
{
|
||||
// No accurate information
|
||||
return KNOWS_THEYRE_THERE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Accurate information
|
||||
return KNOWS_HOW_MANY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7126,3 +7195,38 @@ BOOLEAN CanRedistributeMilitiaInSector( INT16 sClickedSectorX, INT16 sClickedSec
|
||||
// the fight is elsewhere - ok to redistribute
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
// Callback for disbanding militia in the Militia Box
|
||||
void MilitiaDisbandYesNoBoxCallback( UINT8 bExitValue )
|
||||
{
|
||||
// yes
|
||||
if( bExitValue == MSG_BOX_RETURN_YES )
|
||||
{
|
||||
if( sSelectedMilitiaTown != BLANK_SECTOR )
|
||||
{
|
||||
// HEADROCK HAM 3.6: Adjust loyalty based on how many militia were disbanded, compared to
|
||||
// how many can be trained in a single session (max).
|
||||
UINT32 uiMilitiaToDisband = sGreensOnCursor + (2*sRegularsOnCursor) + (3*sElitesOnCursor);
|
||||
UINT32 uiTownLoyaltyBonus = (LOYALTY_BONUS_FOR_TOWN_TRAINING * uiMilitiaToDisband) / gGameExternalOptions.iTrainingSquadSize;
|
||||
// loyalty in this town increases a bit because we obviously care about them...
|
||||
DecrementTownLoyalty( (UINT8)sSelectedMilitiaTown, uiTownLoyaltyBonus );
|
||||
}
|
||||
|
||||
// zero out numbers on the cursor
|
||||
sGreensOnCursor = 0;
|
||||
sRegularsOnCursor = 0;
|
||||
sElitesOnCursor = 0;
|
||||
|
||||
// reset fact we are in the box
|
||||
sSelectedMilitiaTown = 0;
|
||||
fMapPanelDirty = TRUE;
|
||||
// Go ahead and reset the militia in the selected sector
|
||||
ResetMilitia();
|
||||
}
|
||||
else if( bExitValue == MSG_BOX_RETURN_NO )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -340,11 +340,8 @@ void AddTextToTownBox( void )
|
||||
AddSecondColumnMonoString( &hStringHandle, wString );
|
||||
|
||||
// main facilities
|
||||
swprintf( wString, L"%s:", pwTownInfoStrings[ 8 ] );
|
||||
AddMonoString( &hStringHandle, wString );
|
||||
wcscpy(wString, L"");
|
||||
GetSectorFacilitiesFlags( bCurrentTownMineSectorX, bCurrentTownMineSectorY, wString );
|
||||
AddSecondColumnMonoString( &hStringHandle, wString );
|
||||
// HEADROCK HAM 3.6: This function now does all the work of assembling a facility entry.
|
||||
AddFacilitiesToBox( bCurrentTownMineSectorX, bCurrentTownMineSectorY, &hStringHandle, TRUE );
|
||||
|
||||
// the concept of control is only meaningful in sectors where militia can be trained
|
||||
if ( MilitiaTrainingAllowedInSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY, 0 ) )
|
||||
@@ -551,6 +548,9 @@ void AddTextToBlankSectorBox( void )
|
||||
|
||||
// sector
|
||||
AddSectorToBox();
|
||||
|
||||
// HEADROCK HAM 3.6: Facilities
|
||||
AddFacilitiesToBox( bCurrentTownMineSectorX, bCurrentTownMineSectorY, &hStringHandle, FALSE );
|
||||
}
|
||||
|
||||
|
||||
@@ -639,12 +639,64 @@ void AddCommonInfoToBox(void)
|
||||
AddSecondColumnMonoString( &hStringHandle, wString );
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: Only show these for sectors that have a training facility
|
||||
BOOLEAN fMilitiaTrainingAllowed = FALSE;
|
||||
BOOLEAN fMobileTrainingAllowed = FALSE;
|
||||
|
||||
// percentage of current militia squad training completed
|
||||
swprintf( wString, L"%s:", pwTownInfoStrings[ 10 ] );
|
||||
AddMonoString( &hStringHandle, wString );
|
||||
swprintf( wString, L"%d%%%%", SectorInfo[ SECTOR( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) ].ubMilitiaTrainingPercentDone );
|
||||
AddSecondColumnMonoString( &hStringHandle, wString );
|
||||
|
||||
// Sector contains Militia training facility?
|
||||
for (UINT8 ubCounter = 0; ubCounter < MAX_NUM_FACILITY_TYPES; ubCounter++)
|
||||
{
|
||||
if (gFacilityLocations[SECTOR(bCurrentTownMineSectorX, bCurrentTownMineSectorY)][ubCounter].fFacilityHere)
|
||||
{
|
||||
if (gFacilityTypes[ubCounter].ubMilitiaTrainersAllowed)
|
||||
{
|
||||
fMilitiaTrainingAllowed = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fMilitiaTrainingAllowed)
|
||||
{
|
||||
// Show percent completed
|
||||
swprintf( wString, L"%d%%%%", SectorInfo[ SECTOR( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) ].ubMilitiaTrainingPercentDone );
|
||||
AddSecondColumnMonoString( &hStringHandle, wString );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show N/A
|
||||
AddSecondColumnMonoString( &hStringHandle, New113HAMMessage[19] );
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: percentage of current Mobile Militia squad training completed
|
||||
swprintf( wString, L"%s:", pwTownInfoStrings[ 12 ] );
|
||||
AddMonoString( &hStringHandle, wString );
|
||||
|
||||
// Sector contains Mobile training facility?
|
||||
for (UINT8 ubCounter = 0; ubCounter < MAX_NUM_FACILITY_TYPES; ubCounter++)
|
||||
{
|
||||
if (gFacilityLocations[SECTOR(bCurrentTownMineSectorX, bCurrentTownMineSectorY)][ubCounter].fFacilityHere)
|
||||
{
|
||||
if (gFacilityTypes[ubCounter].ubMobileMilitiaTrainersAllowed)
|
||||
{
|
||||
fMobileTrainingAllowed = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fMobileTrainingAllowed)
|
||||
{
|
||||
// Show percentage completed
|
||||
swprintf( wString, L"%d%%%%", SectorInfo[ SECTOR( bCurrentTownMineSectorX, bCurrentTownMineSectorY ) ].ubMobileMilitiaTrainingPercentDone );
|
||||
AddSecondColumnMonoString( &hStringHandle, wString );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show N/A
|
||||
AddSecondColumnMonoString( &hStringHandle, New113HAMMessage[19] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -313,6 +313,8 @@ BOOLEAN fShowContractMenu = FALSE;
|
||||
BOOLEAN fShowRemoveMenu = FALSE;
|
||||
BOOLEAN fShowMilitiaControlMenu = FALSE; //lal
|
||||
//BOOLEAN fShowTalkToAllMenu = FALSE;//lal
|
||||
BOOLEAN fShowFacilityMenu = FALSE; // HEADROCK HAM 3.6: Facility Menu
|
||||
BOOLEAN fShowFacilityAssignmentMenu = FALSE; // HEADROCK HAM 3.6: Facility Sub-menu
|
||||
|
||||
BOOLEAN fRebuildMoveBox = FALSE;
|
||||
|
||||
@@ -325,6 +327,12 @@ SGPRect TrainDimensions={0,0,100,95};
|
||||
SGPPoint TrainPosition={160,150};
|
||||
SGPRect VehicleDimensions={0,0,80,60};
|
||||
SGPPoint VehiclePosition={160,150};
|
||||
// HEADROCK HAM 3.6: Facility Menu Position/Size:
|
||||
SGPRect FacilityDimensions={0,0,80,60};
|
||||
SGPPoint FacilityPosition={160,150};
|
||||
// HEADROCK HAM 3.6: Facility Sub-menu Position/Size:
|
||||
SGPRect FacilityAssignmentDimensions={0,0,80,60};
|
||||
SGPPoint FacilityAssignmentPosition={220,150};
|
||||
|
||||
SGPPoint RepairPosition={160,150};
|
||||
SGPRect RepairDimensions={0,0,80,80};
|
||||
@@ -350,6 +358,8 @@ SGPPoint OrigAssignmentPosition = { 120, 150 };
|
||||
SGPPoint OrigTrainPosition={160,150};
|
||||
SGPPoint OrigVehiclePosition={160,150};
|
||||
SGPPoint OrigMilitiaControlPosition = { 120, 150 }; //lal
|
||||
SGPPoint OrigFacilityPosition = { 160, 150 }; // HEADROCK HAM 3.6
|
||||
SGPPoint OrigFacilityAssignmentPosition = { 220,150 }; // HEADROCK HAM 3.6
|
||||
//SGPPoint OrigTalkToAllPosition = { 160, 150 };
|
||||
|
||||
//extern BOOLEAN fMapExitDueToMessageBox;
|
||||
@@ -542,7 +552,7 @@ BOOLEAN MultipleCharacterListEntriesSelected( void )
|
||||
|
||||
|
||||
|
||||
void ResetAssignmentsForMercsTrainingUnpaidSectorsInSelectedList( INT8 bAssignment )
|
||||
void ResetAssignmentsForMercsTrainingUnpaidSectorsInSelectedList( UINT8 ubMilitiaType )
|
||||
{
|
||||
INT32 iCounter = 0;
|
||||
SOLDIERTYPE *pSoldier = NULL;
|
||||
@@ -563,18 +573,31 @@ void ResetAssignmentsForMercsTrainingUnpaidSectorsInSelectedList( INT8 bAssignme
|
||||
continue;
|
||||
}
|
||||
|
||||
if( pSoldier->bAssignment == TRAIN_TOWN )
|
||||
if (ubMilitiaType == TOWN_MILITIA)
|
||||
{
|
||||
if ( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ].fMilitiaTrainingPaid == FALSE )
|
||||
if( pSoldier->bAssignment == TRAIN_TOWN )
|
||||
{
|
||||
ResumeOldAssignment( pSoldier );
|
||||
if ( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ].fMilitiaTrainingPaid == FALSE )
|
||||
{
|
||||
ResumeOldAssignment( pSoldier );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ubMilitiaType == MOBILE_MILITIA)
|
||||
{
|
||||
if( pSoldier->bAssignment == TRAIN_MOBILE )
|
||||
{
|
||||
if ( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ].fMobileMilitiaTrainingPaid == FALSE )
|
||||
{
|
||||
ResumeOldAssignment( pSoldier );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ResetAssignmentOfMercsThatWereTrainingMilitiaInThisSector( INT16 sSectorX, INT16 sSectorY )
|
||||
// HEADROCK HAM 3.6: Added argument for Militia Type
|
||||
void ResetAssignmentOfMercsThatWereTrainingMilitiaInThisSector( INT16 sSectorX, INT16 sSectorY, UINT8 ubMilitiaType )
|
||||
{
|
||||
INT32 iCounter = 0;
|
||||
SOLDIERTYPE *pSoldier = NULL;
|
||||
@@ -595,11 +618,24 @@ void ResetAssignmentOfMercsThatWereTrainingMilitiaInThisSector( INT16 sSectorX,
|
||||
continue;
|
||||
}
|
||||
|
||||
if( pSoldier->bAssignment == TRAIN_TOWN )
|
||||
if( ubMilitiaType == TOWN_MILITIA )
|
||||
{
|
||||
if( ( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == 0 ) )
|
||||
if( pSoldier->bAssignment == TRAIN_TOWN )
|
||||
{
|
||||
ResumeOldAssignment( pSoldier );
|
||||
if( ( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == 0 ) )
|
||||
{
|
||||
ResumeOldAssignment( pSoldier );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ubMilitiaType == MOBILE_MILITIA )
|
||||
{
|
||||
if( pSoldier->bAssignment == TRAIN_MOBILE )
|
||||
{
|
||||
if( ( pSoldier->sSectorX == sSectorX ) && ( pSoldier->sSectorY == sSectorY ) && ( pSoldier->bSectorZ == 0 ) )
|
||||
{
|
||||
ResumeOldAssignment( pSoldier );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -890,6 +926,7 @@ void RestoreBackgroundForAssignmentGlowRegionList( void )
|
||||
// restore background
|
||||
RestoreExternBackgroundRect( 66, Y_START - 1, 118 + 1 - 67, yHeight );
|
||||
|
||||
|
||||
// ARM: not good enough! must reblit the whole panel to erase glow chunk restored by help text disappearing!!!
|
||||
fTeamPanelDirty = TRUE;
|
||||
|
||||
@@ -2285,7 +2322,24 @@ void UpdateMapScreenAssignmentPositions( void )
|
||||
SetBoxPosition( ghRepairBox, pPoint );
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: Facility Menu
|
||||
if( fShowFacilityMenu )
|
||||
{
|
||||
GetBoxPosition( ghFacilityBox, &pPoint);
|
||||
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_FACILITY;
|
||||
|
||||
SetBoxPosition( ghFacilityBox, pPoint );
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: Facility Sub-menu
|
||||
if( fShowFacilityAssignmentMenu )
|
||||
{
|
||||
GetBoxPosition( ghFacilityAssignmentBox, &pPoint);
|
||||
|
||||
pPoint.iY = giBoxY + ( GetFontHeight( MAP_SCREEN_FONT ) + 2 ) * ASSIGN_MENU_FACILITY;
|
||||
|
||||
SetBoxPosition( ghFacilityAssignmentBox, pPoint );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -5655,7 +5709,8 @@ BOOLEAN HandleTimeCompressWithTeamJackedInAndGearedToGo( void )
|
||||
|
||||
if (!is_networked)
|
||||
// select starting sector (A9 - Omerta)
|
||||
ChangeSelectedMapSector( startingX, startingY, startingZ );
|
||||
// HEADROCK HAM 3.5: Externalized.
|
||||
ChangeSelectedMapSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ );
|
||||
|
||||
if (is_networked)
|
||||
{
|
||||
@@ -5671,22 +5726,30 @@ BOOLEAN HandleTimeCompressWithTeamJackedInAndGearedToGo( void )
|
||||
else
|
||||
{
|
||||
// load starting sector
|
||||
if ( !SetCurrentWorldSector( startingX, startingY, startingZ ) )
|
||||
// Externalized
|
||||
if ( !SetCurrentWorldSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ ) )
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
gubPBSectorX = startingX;
|
||||
gubPBSectorY = startingY;
|
||||
gubPBSectorX = gGameExternalOptions.ubDefaultArrivalSectorX;
|
||||
gubPBSectorY = gGameExternalOptions.ubDefaultArrivalSectorY;
|
||||
}
|
||||
|
||||
gubPBSectorZ = 0;
|
||||
|
||||
//Setup variables in the PBI for this first battle. We need to support the
|
||||
//non-persistant PBI in case the user goes to mapscreen.
|
||||
gfBlitBattleSectorLocator = TRUE;
|
||||
|
||||
gubPBSectorZ = 0;
|
||||
gubEnemyEncounterCode = ENTERING_ENEMY_SECTOR_CODE;
|
||||
// HEADROCK HAM 3.5: Arrival sector externalized. Fix for entering non-hostile sector/
|
||||
if ( NumEnemiesInAnySector( gubPBSectorX, gubPBSectorY, 0 ) > 0 )
|
||||
{
|
||||
gfBlitBattleSectorLocator = TRUE;
|
||||
gubEnemyEncounterCode = ENTERING_ENEMY_SECTOR_CODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
gfBlitBattleSectorLocator = FALSE;
|
||||
gubEnemyEncounterCode = NO_ENCOUNTER_CODE;
|
||||
}
|
||||
|
||||
InitHelicopterEntranceByMercs( );
|
||||
|
||||
|
||||
@@ -113,15 +113,17 @@ enum {
|
||||
ASSIGN_MENU_VEHICLE,
|
||||
ASSIGN_MENU_REPAIR,
|
||||
ASSIGN_MENU_TRAIN,
|
||||
ASSIGN_MENU_FACILITY, // HEAROCK HAM 3.6: Facility List menu
|
||||
ASSIGN_MENU_CANCEL,
|
||||
MAX_ASSIGN_STRING_COUNT,
|
||||
};
|
||||
|
||||
|
||||
// HEADROCK HAM 3.6: Added new option to train Mobile Militia separately.
|
||||
// training assignment menu defines
|
||||
enum {
|
||||
TRAIN_MENU_SELF,
|
||||
TRAIN_MENU_TOWN,
|
||||
TRAIN_MENU_MOBILE,
|
||||
TRAIN_MENU_TEAMMATES,
|
||||
TRAIN_MENU_TRAIN_BY_OTHER,
|
||||
TRAIN_MENU_CANCEL,
|
||||
@@ -202,6 +204,12 @@ enum{
|
||||
STOP_YELLOW_SECTOR_LOCATOR,
|
||||
};
|
||||
|
||||
// HEADROCK HAM 3.6: Enums for Militia Training Types
|
||||
enum{
|
||||
TOWN_MILITIA = 0,
|
||||
MOBILE_MILITIA,
|
||||
NUM_MILITIA_TRAINING_TYPES
|
||||
};
|
||||
|
||||
// dimensions and offset for merc update box
|
||||
#define UPDATE_MERC_FACE_X_WIDTH 50
|
||||
@@ -254,6 +262,8 @@ extern BOOLEAN fShowContractMenu ;
|
||||
extern BOOLEAN fShowRemoveMenu ;
|
||||
extern BOOLEAN fShowMilitiaControlMenu ; //lal
|
||||
//extern BOOLEAN fShowTalkToAllMenu ;
|
||||
extern BOOLEAN fShowFacilityMenu; // HEADROCK HAM 3.6
|
||||
extern BOOLEAN fShowFacilityAssignmentMenu; // HEADROCK HAM 3.6
|
||||
|
||||
extern BOOLEAN fFirstTimeInMapScreen;
|
||||
extern BOOLEAN fLockOutMapScreenInterface;
|
||||
@@ -299,6 +309,11 @@ extern SGPRect AssignmentDimensions ;
|
||||
extern SGPPoint AssignmentPosition ;
|
||||
extern SGPPoint SquadPosition ;
|
||||
extern SGPRect SquadDimensions ;
|
||||
// HEADROCK HAM 3.6: Facility Menu variables
|
||||
extern SGPPoint FacilityPosition;
|
||||
extern SGPRect FacilityDimensions;
|
||||
extern SGPPoint FacilityAssignmentPosition;
|
||||
extern SGPRect FacilityAssignmentDimensions;
|
||||
|
||||
extern SGPPoint RepairPosition;
|
||||
extern SGPRect RepairDimensions;
|
||||
@@ -316,6 +331,8 @@ extern SGPPoint OrigAssignmentPosition ;
|
||||
extern SGPPoint OrigTrainPosition;
|
||||
extern SGPPoint OrigVehiclePosition;
|
||||
extern SGPPoint OrigMilitiaControlPosition ; //lal
|
||||
extern SGPPoint OrigFacilityPosition; // HEADROCK HAM 3.6: Facility Menu
|
||||
extern SGPPoint OrigFacilityAssignmentPosition; // HEADROCK HAM 3.6
|
||||
//extern SGPPoint OrigTalkToAllPosition ;
|
||||
|
||||
// disble team info panel due to showing of battle roster
|
||||
@@ -374,7 +391,8 @@ BOOLEAN MultipleCharacterListEntriesSelected( void );
|
||||
void ToggleEntryInSelectedList( INT8 bEntry );
|
||||
|
||||
// reset assignments for mercs on selected list who have this assignment
|
||||
void ResetAssignmentsForMercsTrainingUnpaidSectorsInSelectedList( INT8 bAssignment );
|
||||
// HEADROCK HAM 3.6: Argument was unused... adding my own.
|
||||
void ResetAssignmentsForMercsTrainingUnpaidSectorsInSelectedList( UINT8 ubMilitiaType );
|
||||
|
||||
/*
|
||||
// plot path for selected character list
|
||||
@@ -553,7 +571,7 @@ BOOLEAN SetUpFastHelpListRegions( INT32 iXPosition[], INT32 iYPosition[], INT32
|
||||
void InitializeMovingLists( void );
|
||||
|
||||
// reset assignment for mercs trainign militia in this sector
|
||||
void ResetAssignmentOfMercsThatWereTrainingMilitiaInThisSector( INT16 sSectorX, INT16 sSectorY );
|
||||
void ResetAssignmentOfMercsThatWereTrainingMilitiaInThisSector( INT16 sSectorX, INT16 sSectorY, UINT8 ubMilitiaType );
|
||||
|
||||
|
||||
// the sector move box
|
||||
|
||||
+1250
-430
File diff suppressed because it is too large
Load Diff
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "Types.h"
|
||||
#include "Soldier Control.h"
|
||||
#include "campaign types.h"
|
||||
|
||||
//#define MAXIMUM_MILITIA_SQUAD_SIZE 30
|
||||
|
||||
@@ -18,7 +19,8 @@ void UpdateMilitiaSquads(INT16 sMapX, INT16 sMapY );
|
||||
void CreateMilitiaSquads(INT16 sMapX, INT16 sMapY );
|
||||
void MilitiaHelpFromAdjacentSectors( INT16 sMapX, INT16 sMapY );
|
||||
|
||||
void GenerateDirectionInfos( INT16 sMapX, INT16 sMapY, UINT8* uiDirNumber, UINT16 pMoveDir[4][3], BOOLEAN fWithCities, BOOLEAN fForBattle, BOOLEAN fOnlyCitySectors );
|
||||
// HEADROCK HAM 3.4: Now using different arguments for this function. All relevent instances have also been altered.
|
||||
void GenerateDirectionInfos( INT16 sMapX, INT16 sMapY, UINT8* uiDirNumber, UINT16 pMoveDir[4][3], BOOLEAN fForTraining, BOOLEAN fForBattle );
|
||||
BOOLEAN MoveOneBestMilitiaMan(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY);
|
||||
void MilitiaFollowPlayer( INT16 sMapX, INT16 sMapY, INT16 sDMapX, INT16 sDMapY );
|
||||
|
||||
@@ -29,9 +31,29 @@ extern BOOLEAN gDynamicRestrictMilitia[ 256 ];
|
||||
// HEADROCK HAM B2.7: Wonder why this function wasn't declared here. It is now, to allow Town Militia.cpp to
|
||||
// access it.
|
||||
|
||||
BOOLEAN CheckStandardConditionsForDirection( INT16 sSMapX, INT16 sSMapY, INT16 sMapX, INT16 sMapY, BOOLEAN fWithCities, BOOLEAN fForBattle, BOOLEAN fOnlyCitySectors );
|
||||
BOOLEAN CheckStandardConditionsForDirection( INT16 sSMapX, INT16 sSMapY, INT16 sMapX, INT16 sMapY, BOOLEAN fForTraining, BOOLEAN fForBattle );
|
||||
|
||||
// HEADROCK HAM B2.7: Generates possible movement directions - this is used only in CreateMilitiaGroup(), and
|
||||
// makes sure that the target sector has room for more militia.
|
||||
void GenerateDirectionInfosWithCapacityCheck( INT16 sMapX, INT16 sMapY, UINT8* uiDirNumber, UINT16 pMoveDir[4][3], BOOLEAN fWithCities, BOOLEAN fForBattle, BOOLEAN fOnlyCitySectors );
|
||||
void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNumber, UINT16 pMoveDir[4][3] );
|
||||
|
||||
// HEADROCK HAM 3.4: Stores restriction data from XML, including required cities for each sector to be allowed.
|
||||
typedef struct DYNAMICRESTRICTIONS
|
||||
{
|
||||
INT8 bSectorID;
|
||||
UINT32 uiReqTownFlags;
|
||||
} DYNAMICRESTRICTIONS;
|
||||
|
||||
// HEADROCK HAM 3.4: New function for simple Roaming Restriction testing.
|
||||
BOOLEAN IsSectorRoamingAllowed( UINT32 uiSector );
|
||||
|
||||
// HEADROCK HAM 3.6: New upgrade check returns the amount of militia that can be upgraded at target sector, in
|
||||
// "upgrade points"
|
||||
UINT16 MilitiaUpgradeSlotsCheck( SECTORINFO * pSectorInfo );
|
||||
|
||||
// HEADROCK HAM 3.6: This needs to be accessible.
|
||||
void AddToBlockMoveList(INT16 sMapX, INT16 sMapY);
|
||||
// And this:
|
||||
UINT8 CountMilitia(SECTORINFO *pSectorInfo);
|
||||
|
||||
#endif
|
||||
@@ -25,6 +25,8 @@
|
||||
#include "Tactical Save.h"
|
||||
#include "interface Dialogue.h"
|
||||
#include "Random.h"
|
||||
// HEADROCK HAM 3.6: Added for facility string printing...
|
||||
#include "PopUpBox.h"
|
||||
#endif
|
||||
|
||||
#include "postalservice.h"
|
||||
@@ -32,26 +34,70 @@
|
||||
extern BOOLEAN fMapScreenBottomDirty;
|
||||
extern CPostalService gPostalService;
|
||||
|
||||
void GetSectorFacilitiesFlags( INT16 sMapX, INT16 sMapY, STR16 sFacilitiesString )
|
||||
|
||||
void AddFacilitiesToBox( INT16 sMapX, INT16 sMapY, UINT32 *uiHandle, BOOLEAN fCityInfoBox )
|
||||
{
|
||||
// will build a string stating current facilities present in sector
|
||||
|
||||
if( SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFacilitiesFlags == 0 )
|
||||
// HEADROCK HAM 3.5: Facilities are now read from XMLs, including their names.
|
||||
|
||||
UINT32 cnt = 0;
|
||||
UINT32 uiNumFacilities = 0;
|
||||
BOOLEAN fHeaderAdded = FALSE;
|
||||
|
||||
CHAR16 szFacilityString[30];
|
||||
|
||||
Assert(sMapX > 0 && sMapY > 0 && sMapX < 17 && sMapY < 17);
|
||||
|
||||
for ( cnt = 0; cnt < NUM_FACILITY_TYPES; cnt++ )
|
||||
{
|
||||
// none
|
||||
swprintf( sFacilitiesString, L"%s", sFacilitiesStrings[ 0 ] );
|
||||
if (fCityInfoBox && uiNumFacilities == 0 && !fHeaderAdded )
|
||||
{
|
||||
// For a city info box, always show this line on the left side.
|
||||
swprintf( szFacilityString, L"%s:", pwTownInfoStrings[ 8 ] );
|
||||
AddMonoString( uiHandle, szFacilityString );
|
||||
fHeaderAdded = TRUE;
|
||||
}
|
||||
// Facility type exists at this location?
|
||||
if (gFacilityLocations[SECTOR(sMapX,sMapY)][cnt].fFacilityHere)
|
||||
{
|
||||
if (gFacilityLocations[SECTOR(sMapX,sMapY)][cnt].ubHidden == 0 ||
|
||||
(gFacilityLocations[SECTOR(sMapX,sMapY)][cnt].ubHidden == 1 && SectorInfo[SECTOR(sMapX,sMapY)].fSurfaceWasEverPlayerControlled) )
|
||||
{
|
||||
if (!fCityInfoBox && uiNumFacilities == 0 && !fHeaderAdded )
|
||||
{
|
||||
// For a non-city info box, show this line on the left side only if there's at least one facility.
|
||||
swprintf( szFacilityString, L"%s:", pwTownInfoStrings[ 8 ] );
|
||||
AddMonoString( uiHandle, szFacilityString );
|
||||
}
|
||||
else if (uiNumFacilities > 0)
|
||||
{
|
||||
// Add empty line on the left size to make room for text on the right.
|
||||
AddMonoString( uiHandle, L"" );
|
||||
}
|
||||
|
||||
AddSecondColumnMonoString( uiHandle, gFacilityTypes[cnt].szFacilityName );
|
||||
uiNumFacilities++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( uiNumFacilities == 0 && fCityInfoBox )
|
||||
{
|
||||
// Add "NONE" on the right side. Only happens when the sector is a city.
|
||||
AddSecondColumnMonoString( uiHandle, sFacilitiesStrings[0] );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* HEADROCK HAM 3.4: Hardcodes removed.
|
||||
// hospital
|
||||
if( SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFacilitiesFlags & SFCF_HOSPITAL )
|
||||
if( SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFacilitiesFlags & (1 << FACILITY_HOSPITAL) )
|
||||
{
|
||||
swprintf( sFacilitiesString, L"%s", sFacilitiesStrings[ 1 ] );
|
||||
swprintf( sFacilitiesString, L"%s", sFacilitiesStrings[ FACILITY_HOSPITAL ] );
|
||||
}
|
||||
|
||||
// industry
|
||||
if( SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFacilitiesFlags & SFCF_INDUSTRY )
|
||||
if( SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFacilitiesFlags & (1 << FACILITY_INDUSTRY) )
|
||||
{
|
||||
if( wcslen( sFacilitiesString ) == 0 )
|
||||
{
|
||||
@@ -59,13 +105,13 @@ void GetSectorFacilitiesFlags( INT16 sMapX, INT16 sMapY, STR16 sFacilitiesString
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscat( sFacilitiesString, L",");
|
||||
wcscat( sFacilitiesString, L", ");
|
||||
wcscat( sFacilitiesString, sFacilitiesStrings[ 2 ]);
|
||||
}
|
||||
}
|
||||
|
||||
// prison
|
||||
if( SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFacilitiesFlags & SFCF_PRISON )
|
||||
if( SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFacilitiesFlags & (1 << FACILITY_PRISON) )
|
||||
{
|
||||
if( wcslen( sFacilitiesString ) == 0 )
|
||||
{
|
||||
@@ -73,13 +119,27 @@ void GetSectorFacilitiesFlags( INT16 sMapX, INT16 sMapY, STR16 sFacilitiesString
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscat( sFacilitiesString, L",");
|
||||
wcscat( sFacilitiesString, L", ");
|
||||
wcscat( sFacilitiesString, sFacilitiesStrings[ 3 ]);
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.4: What about the military base!
|
||||
if( SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFacilitiesFlags & (1 << FACILITY_MILITARY) )
|
||||
{
|
||||
if( wcslen( sFacilitiesString ) == 0 )
|
||||
{
|
||||
swprintf( sFacilitiesString, L"%s", sFacilitiesStrings[ 4 ] );
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscat( sFacilitiesString, L", ");
|
||||
wcscat( sFacilitiesString, sFacilitiesStrings[ 4 ]);
|
||||
}
|
||||
}
|
||||
|
||||
// airport
|
||||
if( SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFacilitiesFlags & SFCF_AIRPORT )
|
||||
if( SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFacilitiesFlags & (1 << FACILITY_AIRPORT) )
|
||||
{
|
||||
if( wcslen( sFacilitiesString ) == 0 )
|
||||
{
|
||||
@@ -87,13 +147,13 @@ void GetSectorFacilitiesFlags( INT16 sMapX, INT16 sMapY, STR16 sFacilitiesString
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscat( sFacilitiesString, L",");
|
||||
wcscat( sFacilitiesString, L", ");
|
||||
wcscat( sFacilitiesString, sFacilitiesStrings[ 5 ]);
|
||||
}
|
||||
}
|
||||
|
||||
// gun range
|
||||
if( SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFacilitiesFlags & SFCF_GUN_RANGE )
|
||||
if( SectorInfo[ SECTOR( sMapX, sMapY ) ].uiFacilitiesFlags & (1 << FACILITY_GUNRANGE) )
|
||||
{
|
||||
if( wcslen( sFacilitiesString ) == 0 )
|
||||
{
|
||||
@@ -101,12 +161,11 @@ void GetSectorFacilitiesFlags( INT16 sMapX, INT16 sMapY, STR16 sFacilitiesString
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscat( sFacilitiesString, L",");
|
||||
wcscat( sFacilitiesString, L", ");
|
||||
wcscat( sFacilitiesString, sFacilitiesStrings[ 6 ]);
|
||||
}
|
||||
}
|
||||
|
||||
sFacilitiesString[ wcslen( sFacilitiesString ) ] = 0;
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
|
||||
// build main facilities strings for sector
|
||||
void GetSectorFacilitiesFlags( INT16 sMapX, INT16 sMapY, STR16 sFacilitiesString );
|
||||
void AddFacilitiesToBox( INT16 sMapX, INT16 sMapY, UINT32 *uiHandle, BOOLEAN fCityInfoBox );
|
||||
|
||||
// set sector as enemy controlled
|
||||
BOOLEAN SetThisSectorAsEnemyControlled( INT16 sMapX, INT16 sMapY, INT8 bMapZ, BOOLEAN fContested );
|
||||
|
||||
+16
-12
@@ -210,15 +210,15 @@ UINT8 NumEnemiesInSector( INT16 sSectorX, INT16 sSectorY )
|
||||
GROUP *pGroup;
|
||||
UINT8 ubNumTroops;
|
||||
|
||||
// HEADROCK: This is a TEMPORARY fix to avoid the assertion error. Not sure this is the best solution,
|
||||
// probably isn't. But I need this bit to work.
|
||||
if (sSectorX < MINIMUM_VALID_X_COORDINATE ||
|
||||
sSectorX > MAXIMUM_VALID_X_COORDINATE ||
|
||||
sSectorY < MINIMUM_VALID_Y_COORDINATE ||
|
||||
sSectorY > MAXIMUM_VALID_Y_COORDINATE)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
// HEADROCK HAM 3.5: This is a TEMPORARY fix to avoid the assertion error. Not sure this is the best solution,
|
||||
// probably isn't. But I need this bit to work.
|
||||
if (sSectorX < MINIMUM_VALID_X_COORDINATE ||
|
||||
sSectorX > MAXIMUM_VALID_X_COORDINATE ||
|
||||
sSectorY < MINIMUM_VALID_Y_COORDINATE ||
|
||||
sSectorY > MAXIMUM_VALID_Y_COORDINATE)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE);
|
||||
AssertLE( sSectorX, MAXIMUM_VALID_X_COORDINATE );
|
||||
@@ -503,8 +503,7 @@ BOOLEAN PrepareEnemyForSectorBattle()
|
||||
// They arrived in multiple groups, so here they come
|
||||
pThisSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ];
|
||||
|
||||
GenerateDirectionInfos( gWorldSectorX, gWorldSectorY, &ubDirNumber, pusMoveDir,
|
||||
( GetTownIdForSector( gWorldSectorX, gWorldSectorY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
|
||||
GenerateDirectionInfos( gWorldSectorX, gWorldSectorY, &ubDirNumber, pusMoveDir, FALSE, TRUE );
|
||||
|
||||
for( unsigned ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
|
||||
{
|
||||
@@ -788,7 +787,6 @@ BOOLEAN PrepareEnemyForSectorBattle()
|
||||
continue;
|
||||
}
|
||||
|
||||
// At this point we should not have added more soldiers than are in slots
|
||||
AssertGT( sNumSlots, 0 );
|
||||
|
||||
switch( pSoldier->ubSoldierClass )
|
||||
@@ -1394,6 +1392,7 @@ void AddPossiblePendingEnemiesToBattle()
|
||||
|
||||
if( ubStrategicInsertionCode == 255 )
|
||||
{
|
||||
// HEADROCK HAM 3.5: This runs into assertion errors along the map's edge! Should be fixed!
|
||||
if( NumEnemiesInSector( gWorldSectorX + 1, gWorldSectorY ) )
|
||||
ubStrategicInsertionCode = INSERTION_CODE_EAST;
|
||||
else if( NumEnemiesInSector( gWorldSectorX - 1, gWorldSectorY ) )
|
||||
@@ -1704,6 +1703,11 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub
|
||||
}
|
||||
UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, 0 );
|
||||
}
|
||||
// HEADROCK HAM 3.2: enemy reinforcements arrive with 0 APs.
|
||||
if (gGameExternalOptions.ubReinforcementsFirstTurnFreeze == 1 || gGameExternalOptions.ubReinforcementsFirstTurnFreeze == 2)
|
||||
{
|
||||
pSoldier->bActionPoints = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1126,8 +1126,9 @@ BOOLEAN CheckFact( UINT16 usFact, UINT8 ubProfileID )
|
||||
gubFact[usFact] = gMercProfiles[ ARNIE ].bMercStatus != MERC_IS_DEAD;
|
||||
break;
|
||||
|
||||
case FACT_I16_BLOODCATS_KILLED:
|
||||
gubFact[usFact] = (SectorInfo[ SEC_I16 ].bBloodCats == 0);
|
||||
// HEADROCK HAM 3.6: No longer necessarily I16.
|
||||
case FACT_BLOODCAT_LAIR_CLEANED:
|
||||
gubFact[usFact] = (SectorInfo[ gubBloodcatLairSectorId ].bBloodCats == 0);
|
||||
break;
|
||||
|
||||
case FACT_NPC_BANDAGED_TODAY:
|
||||
|
||||
+2
-1
@@ -430,7 +430,8 @@ enum Facts
|
||||
FACT_KINGPIN_NOT_IN_OFFICE,// 256
|
||||
FACT_DONT_OWE_KINGPIN_MONEY,// 257
|
||||
FACT_PC_MARRYING_DARYL_IS_FLO,// 258
|
||||
FACT_I16_BLOODCATS_KILLED,// 259
|
||||
// HEADROCK HAM 3.6: Renamed this. It is no longer necessarily at I16.
|
||||
FACT_BLOODCAT_LAIR_CLEANED,// 259
|
||||
|
||||
FACT_NPC_COWERING = 261,
|
||||
|
||||
|
||||
+11
-20
@@ -52,8 +52,7 @@ void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pub
|
||||
if ( ( GetTownIdForSector( sSectorX, sSectorY ) == OMERTA )&&( gGameOptions.ubDifficultyLevel != DIF_LEVEL_INSANE ) ) //Madd: skip Omerta //Lal: but not on insane ;-)
|
||||
return;
|
||||
|
||||
GenerateDirectionInfos( sSectorX, sSectorY, &ubDirNumber, pusMoveDir,
|
||||
( GetTownIdForSector( sSectorX, sSectorY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
|
||||
GenerateDirectionInfos( sSectorX, sSectorY, &ubDirNumber, pusMoveDir, FALSE, TRUE );
|
||||
|
||||
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
|
||||
{
|
||||
@@ -104,8 +103,7 @@ BOOLEAN IsGroupInARightSectorToReinforce( GROUP *pGroup, INT16 sSectorX, INT16 s
|
||||
if( !gGameExternalOptions.gfAllowReinforcements )
|
||||
return FALSE;
|
||||
|
||||
GenerateDirectionInfos( sSectorX, sSectorY, &ubDirNumber, pusMoveDir,
|
||||
( GetTownIdForSector( sSectorX, sSectorY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
|
||||
GenerateDirectionInfos( sSectorX, sSectorY, &ubDirNumber, pusMoveDir, FALSE, TRUE );
|
||||
|
||||
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
|
||||
if( pGroup->ubSectorX == SECTORX( pusMoveDir[ ubIndex ][ 0 ] ) && pGroup->ubSectorY == SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) )
|
||||
@@ -120,8 +118,7 @@ UINT8 GetAdjacentSectors( UINT8 pSectors[4], INT16 sSectorX, INT16 sSectorY )
|
||||
UINT8 ubDirNumber = 0, ubIndex;
|
||||
UINT8 ubCounter = 0;
|
||||
|
||||
GenerateDirectionInfos( sSectorX, sSectorY, &ubDirNumber, pusMoveDir,
|
||||
( GetTownIdForSector( sSectorX, sSectorY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
|
||||
GenerateDirectionInfos( sSectorX, sSectorY, &ubDirNumber, pusMoveDir, FALSE, TRUE );
|
||||
|
||||
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
|
||||
pSectors[ ubCounter++ ] = (UINT8)pusMoveDir[ ubIndex ][ 0 ];
|
||||
@@ -140,8 +137,7 @@ UINT8 CountAllMilitiaInFiveSectors(INT16 sMapX, INT16 sMapY)
|
||||
if( !gGameExternalOptions.gfAllowReinforcements )
|
||||
return ubResult;
|
||||
|
||||
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir,
|
||||
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
|
||||
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir, FALSE, TRUE );
|
||||
|
||||
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
|
||||
ubResult += CountAllMilitiaInSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) );
|
||||
@@ -161,8 +157,7 @@ UINT8 MilitiaInFiveSectorsOfRank( INT16 sMapX, INT16 sMapY, UINT8 ubRank )
|
||||
if( !gGameExternalOptions.gfAllowReinforcements )
|
||||
return ubResult;
|
||||
|
||||
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir,
|
||||
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
|
||||
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir, FALSE, TRUE );
|
||||
|
||||
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
|
||||
ubResult += MilitiaInSectorOfRank( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ), ubRank );
|
||||
@@ -179,12 +174,11 @@ BOOLEAN ARMoveBestMilitiaManFromAdjacentSector(INT16 sMapX, INT16 sMapY)
|
||||
if( !gGameExternalOptions.gfAllowReinforcements )
|
||||
return FALSE;
|
||||
|
||||
if( CountAllMilitiaInSector( sMapX, sMapY ) >= gGameExternalOptions.guiMaxMilitiaSquadSize ||
|
||||
if( CountAllMilitiaInSector( sMapX, sMapY ) >= gGameExternalOptions.iMaxMilitiaPerSector ||
|
||||
CountAllMilitiaInFiveSectors( sMapX, sMapY ) - CountAllMilitiaInSector( sMapX, sMapY ) == 0 )
|
||||
return FALSE;
|
||||
|
||||
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir,
|
||||
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
|
||||
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir, FALSE, TRUE );
|
||||
|
||||
ubRandom = Random( ubDirNumber );
|
||||
|
||||
@@ -209,8 +203,7 @@ BOOLEAN ARRemoveMilitiaMan( INT16 sMapX, INT16 sMapY, UINT8 ubRank )
|
||||
if( !gGameExternalOptions.gfAllowReinforcements )
|
||||
return FALSE;
|
||||
|
||||
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir,
|
||||
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
|
||||
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir, FALSE, TRUE );
|
||||
|
||||
for( ; ; )
|
||||
{
|
||||
@@ -256,8 +249,7 @@ UINT8 DoReinforcementAsPendingEnemy( INT16 sMapX, INT16 sMapY )
|
||||
|
||||
pThisSector = &SectorInfo[ SECTOR( sMapX, sMapY ) ];
|
||||
|
||||
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir,
|
||||
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
|
||||
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir, FALSE, TRUE );
|
||||
|
||||
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
|
||||
{
|
||||
@@ -328,7 +320,7 @@ UINT8 NumFreeMilitiaSlots()
|
||||
if( !pSoldier->bActive )
|
||||
ubNumFreeSlots++;
|
||||
}
|
||||
return max( 0 , ubNumFreeSlots - ( gGameExternalOptions.ubGameMaximumNumberOfRebels - gGameExternalOptions.guiMaxMilitiaSquadSize ) );
|
||||
return max( 0 , ubNumFreeSlots - ( gGameExternalOptions.ubGameMaximumNumberOfRebels - gGameExternalOptions.iMaxMilitiaPerSector ) );
|
||||
}
|
||||
|
||||
UINT8 DoReinforcementAsPendingMilitia( INT16 sMapX, INT16 sMapY, UINT8 *pubRank )
|
||||
@@ -342,8 +334,7 @@ UINT8 DoReinforcementAsPendingMilitia( INT16 sMapX, INT16 sMapY, UINT8 *pubRank
|
||||
|
||||
// pThisSector = &SectorInfo[ SECTOR( sMapX, sMapY ) ];
|
||||
|
||||
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir,
|
||||
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
|
||||
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir, FALSE, TRUE );
|
||||
|
||||
if( CountAllMilitiaInFiveSectors( sMapX, sMapY ) - CountAllMilitiaInSector( sMapX, sMapY ) == 0 )
|
||||
{
|
||||
|
||||
@@ -3704,6 +3704,9 @@ BOOLEAN LoadStrategicAI( HWFILE hFile )
|
||||
}
|
||||
if( ubSAIVersion < 18 )
|
||||
{ //adjust down the number of bloodcats based on difficulty in the two special bloodcat levels
|
||||
// HEADROCK HAM 3.6: Run the Init function instead.
|
||||
InitBloodCatSectors();
|
||||
/*
|
||||
switch( gGameOptions.ubDifficultyLevel )
|
||||
{
|
||||
case DIF_LEVEL_EASY: //50%
|
||||
@@ -3729,7 +3732,7 @@ BOOLEAN LoadStrategicAI( HWFILE hFile )
|
||||
SectorInfo[ SEC_I16 ].bBloodCats = 39;
|
||||
SectorInfo[ SEC_N5 ].bBloodCats = 37;
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
if( ubSAIVersion < 19 )
|
||||
{
|
||||
@@ -3753,6 +3756,8 @@ BOOLEAN LoadStrategicAI( HWFILE hFile )
|
||||
}
|
||||
if( ubSAIVersion < 22 )
|
||||
{ //adjust down the number of bloodcats based on difficulty in the two special bloodcat levels
|
||||
// HEADROCK HAM 3.6: Run the Init function instead.
|
||||
InitBloodCatSectors();
|
||||
switch( gGameOptions.ubDifficultyLevel )
|
||||
{
|
||||
case DIF_LEVEL_EASY: //50%
|
||||
|
||||
@@ -42,6 +42,10 @@
|
||||
#include "Quests.h"
|
||||
// HEADROCK HAM B1: Additional Include for Dynamic Roaming Restrictions
|
||||
#include "MilitiaSquads.h"
|
||||
// HEADROCK HAM 3.6: Additional include for Facility Operating Deby
|
||||
#include "Facilities.h"
|
||||
// HEADROCK HAM 3.6: And another include, for militia upkeep costs.
|
||||
#include "Town Militia.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -513,10 +517,19 @@ void MercDailyUpdate()
|
||||
// rebuild list for mapscreen
|
||||
ReBuildCharactersList( );
|
||||
// HEADROCK HAM B1: Run a function to redefine Roaming Militia Restrictions.
|
||||
if (gGameExternalOptions.bDynamicRestrictRoaming)
|
||||
if (gGameExternalOptions.fDynamicRestrictRoaming)
|
||||
{
|
||||
AdjustRoamingRestrictions();
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: Pay debt for operating Facilities today. If can't be paid, apply loyalty hit.
|
||||
if (giTotalOwedForFacilityOperationsToday)
|
||||
{
|
||||
HandleDailyPaymentFacilityDebt();
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: Pay for militia upkeep
|
||||
HandleMilitiaUpkeepPayment();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "Strategic AI.h"
|
||||
#include "Campaign Types.h"
|
||||
#include "history.h"
|
||||
#include "Facilities.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -202,12 +203,27 @@ void InitializeMines( void )
|
||||
// Alma mine can't run out for quest-related reasons (see Ian)
|
||||
} while (gMineStatus[ubDepletedMineIndex].fEmpty || (ubDepletedMineIndex == MINE_ALMA));
|
||||
|
||||
// HEADROCK HAM 3.1: We can now select which mine runs out, or disable mine shutdown.
|
||||
if (gGameExternalOptions.fManuallySelectMineShutdown)
|
||||
{
|
||||
// Make sure selection isn't 0 (no mine runs out) or invalid (San Mona, Alma)
|
||||
if (gGameExternalOptions.ubWhichMineRunsOut > 0 &&
|
||||
gGameExternalOptions.ubWhichMineRunsOut < MAX_NUMBER_OF_MINES &&
|
||||
gGameExternalOptions.ubWhichMineRunsOut-1 != MINE_SAN_MONA &&
|
||||
gGameExternalOptions.ubWhichMineRunsOut-1 != MINE_ALMA )
|
||||
{
|
||||
// Set depleted mine index.
|
||||
ubDepletedMineIndex = (gGameExternalOptions.ubWhichMineRunsOut-1);
|
||||
}
|
||||
}
|
||||
|
||||
for( ubMineIndex = 0; ubMineIndex < MAX_NUMBER_OF_MINES; ubMineIndex++ )
|
||||
{
|
||||
pMineStatus = &(gMineStatus[ ubMineIndex ]);
|
||||
|
||||
if (ubMineIndex == ubDepletedMineIndex)
|
||||
// HEADROCK HAM 3.1: We can disable mine shutdown, so make sure the settings aren't telling us to do so.
|
||||
if (!(gGameExternalOptions.fManuallySelectMineShutdown && gGameExternalOptions.ubWhichMineRunsOut == 0) &&
|
||||
(ubMineIndex == ubDepletedMineIndex))
|
||||
{
|
||||
if ( ubDepletedMineIndex == MINE_DRASSEN )
|
||||
{
|
||||
@@ -343,7 +359,7 @@ UINT32 GetMaxPeriodicRemovalFromMine( INT8 bMineIndex )
|
||||
}
|
||||
|
||||
// HEADROCK HAM B1: Affected by external INI option.
|
||||
return(( gMineStatus[ bMineIndex ].uiMaxRemovalRate * gGameExternalOptions.iMineIncomePercentage ) / 100);
|
||||
return(( gMineStatus[ bMineIndex ].uiMaxRemovalRate * gGameExternalOptions.usMineIncomePercentage ) / 100);
|
||||
}
|
||||
|
||||
|
||||
@@ -370,7 +386,7 @@ UINT32 GetMaxDailyRemovalFromMine( INT8 bMineIndex )
|
||||
uiAmtExtracted = gMineStatus[ bMineIndex ].uiRemainingOreSupply;
|
||||
}
|
||||
// HEADROCK HAM B1: Affected by external INI option.
|
||||
uiAmtExtracted = (uiAmtExtracted * gGameExternalOptions.iMineIncomePercentage) / 100;
|
||||
uiAmtExtracted = (uiAmtExtracted * gGameExternalOptions.usMineIncomePercentage) / 100;
|
||||
|
||||
return(uiAmtExtracted);
|
||||
}
|
||||
@@ -660,15 +676,22 @@ void HandleIncomeFromMines( void )
|
||||
{
|
||||
INT32 iIncome = 0;
|
||||
INT8 bCounter = 0;
|
||||
// HEADROCK HAM 3.6: Modifier from Facilities
|
||||
INT32 iFacilityModifier = 0;
|
||||
|
||||
// mine each mine, check if we own it and such
|
||||
for( bCounter = 0; bCounter < MAX_NUMBER_OF_MINES; bCounter++ )
|
||||
{
|
||||
if (bCounter)
|
||||
{
|
||||
// HEADROCK HAM 3.6: Add facility modifier as a percentage
|
||||
iFacilityModifier = 100 + MineIncomeModifierFromFacility( bCounter );
|
||||
}
|
||||
// mine this mine
|
||||
iIncome += MineAMine( bCounter );
|
||||
iIncome += (MineAMine( bCounter ) * iFacilityModifier) / 100;
|
||||
}
|
||||
// HEADROCK HAM B1: Affected by external INI Option.
|
||||
iIncome = (iIncome * gGameExternalOptions.iMineIncomePercentage) / 100;
|
||||
iIncome = (iIncome * gGameExternalOptions.usMineIncomePercentage) / 100;
|
||||
if( iIncome )
|
||||
{
|
||||
AddTransactionToPlayersBook( DEPOSIT_FROM_SILVER_MINE, 0, GetWorldTotalMin( ), iIncome );
|
||||
@@ -681,6 +704,8 @@ UINT32 PredictDailyIncomeFromAMine( INT8 bMineIndex )
|
||||
// predict income from this mine, estimate assumes mining situation will not change during next 4 income periods
|
||||
// (miner loyalty, % town controlled, monster infestation level, and current max removal rate may all in fact change)
|
||||
UINT32 uiAmtExtracted = 0;
|
||||
// HEADROCK HAM 3.6: Facilities can now modify income
|
||||
INT32 iFacilityModifier = 0;
|
||||
|
||||
if(PlayerControlsMine(bMineIndex))
|
||||
{
|
||||
@@ -693,10 +718,16 @@ UINT32 PredictDailyIncomeFromAMine( INT8 bMineIndex )
|
||||
// yes reduce to value of mine
|
||||
uiAmtExtracted = gMineStatus[ bMineIndex ].uiRemainingOreSupply;
|
||||
}
|
||||
if (bMineIndex)
|
||||
{
|
||||
// HEADROCK HAM 3.6: Facility modifier applied as a percentage
|
||||
iFacilityModifier = 100 + MineIncomeModifierFromFacility( bMineIndex );
|
||||
uiAmtExtracted = (uiAmtExtracted * iFacilityModifier) / 100;
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM B1: Affected by external INI Option.
|
||||
return( ( uiAmtExtracted * gGameExternalOptions.iMineIncomePercentage ) / 100 ) ;
|
||||
return( ( uiAmtExtracted * gGameExternalOptions.usMineIncomePercentage ) / 100 ) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -727,7 +758,7 @@ INT32 CalcMaxPlayerIncomeFromMines( void )
|
||||
iTotal += (MINE_PRODUCTION_NUMBER_OF_PERIODS * gMineStatus[bCounter].uiMaxRemovalRate);
|
||||
}
|
||||
// HEADROCK HAM B1: Affected by external INI Option.
|
||||
iTotal = (iTotal * gGameExternalOptions.iMineIncomePercentage) / 100;
|
||||
iTotal = (iTotal * gGameExternalOptions.usMineIncomePercentage) / 100;
|
||||
|
||||
return( iTotal );
|
||||
}
|
||||
|
||||
@@ -1554,6 +1554,10 @@ void AwardExperienceForTravelling( GROUP * pGroup )
|
||||
|
||||
void AddCorpsesToBloodcatLair( INT16 sSectorX, INT16 sSectorY )
|
||||
{
|
||||
// HEADROCK HAM 3.6: Note, lair location externalized, but may cause issues because the GridNos here are
|
||||
// hardcoded... Maybe there will be a better way to solve this in the future, with externalized GridNos.
|
||||
// At the moment, no changes.
|
||||
|
||||
ROTTING_CORPSE_DEFINITION Corpse;
|
||||
INT16 sXPos, sYPos;
|
||||
|
||||
@@ -1884,12 +1888,14 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe
|
||||
if( pGroup->pPlayerList->pSoldier->bAssignment < ON_DUTY )
|
||||
{
|
||||
// squad
|
||||
ScreenMsg( FONT_MCOLOR_DKRED, MSG_INTERFACE, pMessageStrings[ MSG_ARRIVE ], pAssignmentStrings[ pGroup->pPlayerList->pSoldier->bAssignment ], pMapVertIndex[ pGroup->pPlayerList->pSoldier->sSectorY ], pMapHortIndex[ pGroup->pPlayerList->pSoldier->sSectorX ]);
|
||||
// HEADROCK HAM 3.6: Messages are no longer yellow by default.
|
||||
ScreenMsg( FONT_MCOLOR_LTGREEN, MSG_INTERFACE, pMessageStrings[ MSG_ARRIVE ], pAssignmentStrings[ pGroup->pPlayerList->pSoldier->bAssignment ], pMapVertIndex[ pGroup->pPlayerList->pSoldier->sSectorY ], pMapHortIndex[ pGroup->pPlayerList->pSoldier->sSectorX ]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// a loner
|
||||
ScreenMsg( FONT_MCOLOR_DKRED, MSG_INTERFACE, pMessageStrings[ MSG_ARRIVE ], pGroup->pPlayerList->pSoldier->name, pMapVertIndex[ pGroup->pPlayerList->pSoldier->sSectorY ], pMapHortIndex[ pGroup->pPlayerList->pSoldier->sSectorX ] );
|
||||
// HEADROCK HAM 3.6: Messages are no longer yellow by default.
|
||||
ScreenMsg( FONT_MCOLOR_LTGREEN, MSG_INTERFACE, pMessageStrings[ MSG_ARRIVE ], pGroup->pPlayerList->pSoldier->name, pMapVertIndex[ pGroup->pPlayerList->pSoldier->sSectorY ], pMapHortIndex[ pGroup->pPlayerList->pSoldier->sSectorX ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1978,7 +1984,8 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe
|
||||
// don't print any messages when arriving underground, there's no delay involved
|
||||
if ( GroupAtFinalDestination( pGroup ) && ( pGroup->ubSectorZ == 0 ) && !fNeverLeft )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_DKRED, MSG_INTERFACE, pMessageStrings[ MSG_ARRIVE ], pVehicleStrings[ pVehicleList[ iVehId ].ubVehicleType ], pMapVertIndex[ pGroup->ubSectorY ], pMapHortIndex[ pGroup->ubSectorX ] );
|
||||
// HEADROCK HAM 3.6: Messages are no longer yellow by default.
|
||||
ScreenMsg( FONT_MCOLOR_LTGREEN, MSG_INTERFACE, pMessageStrings[ MSG_ARRIVE ], pVehicleStrings[ pVehicleList[ iVehId ].ubVehicleType ], pMapVertIndex[ pGroup->ubSectorY ], pMapHortIndex[ pGroup->ubSectorX ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1997,7 +2004,8 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe
|
||||
if ( !pGroup->fVehicle || !IsGroupTheHelicopterGroup( pGroup ) )
|
||||
{
|
||||
// ATE: Add a few corpse to the bloodcat lair...
|
||||
if ( SECTOR( pGroup->ubSectorX, pGroup->ubSectorY ) == SEC_I16 && fFirstTimeInSector )
|
||||
// HEADROCK: No longer hardcoded to I16
|
||||
if ( SECTOR( pGroup->ubSectorX, pGroup->ubSectorY ) == gubBloodcatLairSectorId && fFirstTimeInSector )
|
||||
{
|
||||
AddCorpsesToBloodcatLair( pGroup->ubSectorX, pGroup->ubSectorY );
|
||||
}
|
||||
@@ -4708,13 +4716,20 @@ void RandomizePatrolGroupLocation( GROUP *pGroup )
|
||||
//roll the dice to see if this will become an ambush random encounter.
|
||||
BOOLEAN TestForBloodcatAmbush( GROUP *pGroup )
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HEADROCK HAM 3.6: Ambush locations, min/max strength and chance of ambush have all been externalized to XML.
|
||||
|
||||
SECTORINFO *pSector;
|
||||
INT32 iHoursElapsed;
|
||||
UINT8 ubSectorID;
|
||||
UINT8 ubChance;
|
||||
INT8 bDifficultyMaxCats;
|
||||
INT8 bProgressMaxCats;
|
||||
UINT8 ubDifficulty = gGameOptions.ubDifficultyLevel-1; // For use by Placements Array. Novice = 0 instead of 1.
|
||||
UINT8 ubRange;
|
||||
UINT8 ubRandomCats;
|
||||
INT8 bNumMercMaxCats;
|
||||
UINT8 PlacementType; // 0 = Ambush site. 1 = Static placement. 2 = Lair.
|
||||
UINT8 ubMinBloodcats; // XML minimum.
|
||||
UINT8 ubMaxBloodcats; // XML maximum.
|
||||
BOOLEAN fAlreadyAmbushed = FALSE;
|
||||
|
||||
if( pGroup->ubSectorZ )
|
||||
@@ -4725,17 +4740,24 @@ BOOLEAN TestForBloodcatAmbush( GROUP *pGroup )
|
||||
ubSectorID = (UINT8)SECTOR( pGroup->ubSectorX, pGroup->ubSectorY );
|
||||
pSector = &SectorInfo[ ubSectorID ];
|
||||
|
||||
ubChance = 5 * gGameOptions.ubDifficultyLevel;
|
||||
// Read chance from XML data, based on difficulty.
|
||||
ubChance = gBloodcatPlacements[ ubSectorID ][ ubDifficulty ].ubAmbushChance;
|
||||
iHoursElapsed = __max(0,(GetWorldTotalMin() - pSector->uiTimeCurrentSectorWasLastLoaded) / 60);
|
||||
// Decrease chance to 0% if sector has been visited this hour. Every hour after that, increase the chance by 1%
|
||||
// until it reaches the default value again.
|
||||
ubChance = (UINT8)__min((INT32)ubChance, iHoursElapsed);
|
||||
ubChance = __max(0,ubChance);
|
||||
|
||||
iHoursElapsed = (GetWorldTotalMin() - pSector->uiTimeCurrentSectorWasLastLoaded) / 60;
|
||||
if( ubSectorID == SEC_N5 || ubSectorID == SEC_I16 )
|
||||
{ //These are special maps -- we use all placements.
|
||||
if( pSector->bBloodCats == -1 )
|
||||
{
|
||||
pSector->bBloodCats = pSector->bBloodCatPlacements;
|
||||
}
|
||||
else if( pSector->bBloodCats > 0 && pSector->bBloodCats < pSector->bBloodCatPlacements )
|
||||
{ //Slowly have them recuperate if we haven't been here for a long time. The population will
|
||||
// Determine what type of placement this is.
|
||||
PlacementType = gBloodcatPlacements[ ubSectorID ][0].PlacementType;
|
||||
|
||||
// At lair?
|
||||
if( PlacementType == BLOODCAT_PLACEMENT_LAIR )
|
||||
{
|
||||
// Bloodcats still exist here, but aren't at the optimal number?
|
||||
if( pSector->bBloodCats > 0 && pSector->bBloodCats < pSector->bBloodCatPlacements )
|
||||
{
|
||||
//Slowly have them recuperate if we haven't been here for a long time. The population will
|
||||
//come back up to the maximum if left long enough.
|
||||
INT32 iBloodCatDiff;
|
||||
iBloodCatDiff = pSector->bBloodCatPlacements - pSector->bBloodCats;
|
||||
@@ -4743,55 +4765,80 @@ BOOLEAN TestForBloodcatAmbush( GROUP *pGroup )
|
||||
}
|
||||
//Once 0, the bloodcats will never recupe.
|
||||
}
|
||||
else if( pSector->bBloodCats == -1 )
|
||||
{ //If we haven't been ambushed by bloodcats yet...
|
||||
if( gfAutoAmbush || PreChance( ubChance ) )
|
||||
|
||||
// At ambush sector?
|
||||
else if( PlacementType == BLOODCAT_PLACEMENT_AMBUSH )
|
||||
{
|
||||
//If there's any chance of ambush in this sector, and we beat that chance...
|
||||
if( ubChance && (gfAutoAmbush || PreChance( ubChance )) )
|
||||
{
|
||||
//randomly choose from 5-8, 7-10, 9-12 bloodcats based on easy, normal, and hard, respectively
|
||||
bDifficultyMaxCats = (INT8)( Random( 4 ) + gGameOptions.ubDifficultyLevel*2 + 3 );
|
||||
|
||||
//bDifficultyMaxCats = (INT8)( Random( 4 ) + gGameOptions.ubDifficultyLevel*2 + 3 );
|
||||
//maximum of 3 bloodcats or 1 for every 6%, 5%, 4% progress based on easy, normal, and hard, respectively
|
||||
bProgressMaxCats = (INT8)max( CurrentPlayerProgressPercentage() / (7 - gGameOptions.ubDifficultyLevel), 3 );
|
||||
|
||||
//make sure bloodcats don't outnumber mercs by a factor greater than 2
|
||||
bNumMercMaxCats = (INT8)(PlayerMercsInSector( pGroup->ubSectorX, pGroup->ubSectorY, pGroup->ubSectorZ ) * 2);
|
||||
|
||||
//bProgressMaxCats = (INT8)max( CurrentPlayerProgressPercentage() / (7 - gGameOptions.ubDifficultyLevel), 3 );
|
||||
//choose the lowest number of cats calculated by difficulty and progress.
|
||||
pSector->bBloodCats = (INT8)min( bDifficultyMaxCats, bProgressMaxCats );
|
||||
//pSector->bBloodCats = (INT8)min( bDifficultyMaxCats, bProgressMaxCats );
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HEADROCK HAM 3.6: Minimum and Maximum are now modder-defined, so pick a random number between them.
|
||||
|
||||
// Read Min/Max from XML
|
||||
ubMaxBloodcats = gBloodcatPlacements[ ubSectorID ][ ubDifficulty ].ubMaxBloodcats;
|
||||
ubMinBloodcats = gBloodcatPlacements[ ubSectorID ][ ubDifficulty ].ubMinBloodcats;
|
||||
// Find range between Min and Max
|
||||
ubRange = ubMaxBloodcats-ubMinBloodcats;
|
||||
// Adjust range based on current progress.
|
||||
ubRange = __max(0,( ubRange * CurrentPlayerProgressPercentage() ) / 100);
|
||||
// Randomize "extra" bloodcats
|
||||
ubRandomCats = PreRandom(ubRange+1);
|
||||
// Add "extra" bloodcats to minimum value
|
||||
ubRandomCats += ubMinBloodcats;
|
||||
|
||||
// SET NUMBER OF CATS THAT WILL APPEAR
|
||||
pSector->bBloodCats = ubRandomCats;
|
||||
|
||||
if( gGameOptions.ubDifficultyLevel < DIF_LEVEL_HARD )
|
||||
{ //if not hard difficulty, ensure cats never outnumber mercs by a factor of 2 (min 3 bloodcats)
|
||||
{
|
||||
//At NOVICE/EXPERIENCED difficulty, ensure cats never outnumber mercs by a factor of more than 2.
|
||||
bNumMercMaxCats = (INT8)(PlayerMercsInSector( pGroup->ubSectorX, pGroup->ubSectorY, pGroup->ubSectorZ ) * 2);
|
||||
pSector->bBloodCats = (INT8)min( pSector->bBloodCats, bNumMercMaxCats );
|
||||
pSector->bBloodCats = (INT8)max( pSector->bBloodCats, 3 );
|
||||
//pSector->bBloodCats = (INT8)max( pSector->bBloodCats, 3 );
|
||||
}
|
||||
|
||||
//ensure that there aren't more bloodcats than placements
|
||||
pSector->bBloodCats = (INT8)min( pSector->bBloodCats, pSector->bBloodCatPlacements );
|
||||
|
||||
// Once again, make absolutely sure we're still within XML-set limits
|
||||
pSector->bBloodCats = (INT8)min( pSector->bBloodCats, ubMaxBloodcats);
|
||||
pSector->bBloodCats = (INT8)max( pSector->bBloodCats, ubMinBloodcats);
|
||||
}
|
||||
}
|
||||
else if( ubSectorID != SEC_I16 )
|
||||
{
|
||||
if( !gfAutoAmbush && PreChance( 95 ) )
|
||||
{ //already ambushed here. But 5% chance of getting ambushed again!
|
||||
else
|
||||
{
|
||||
// Chance was 0.
|
||||
fAlreadyAmbushed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if( !fAlreadyAmbushed && ubSectorID != SEC_N5 && pSector->bBloodCats > 0 &&
|
||||
// An ambush is occuring?
|
||||
if( !fAlreadyAmbushed && PlacementType != BLOODCAT_PLACEMENT_STATIC && pSector->bBloodCats > 0 &&
|
||||
!pGroup->fVehicle && !NumEnemiesInSector( pGroup->ubSectorX, pGroup->ubSectorY ) )
|
||||
{
|
||||
if( ubSectorID != SEC_I16 || !gubFact[ FACT_PLAYER_KNOWS_ABOUT_BLOODCAT_LAIR ] )
|
||||
// Wilderness ambush, or the player has unwittingly entered the lair?
|
||||
if( PlacementType == BLOODCAT_PLACEMENT_AMBUSH || !gubFact[ FACT_PLAYER_KNOWS_ABOUT_BLOODCAT_LAIR ] )
|
||||
{
|
||||
// Ambush occurs.
|
||||
gubEnemyEncounterCode = BLOODCAT_AMBUSH_CODE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Player knowingly enters lair.
|
||||
gubEnemyEncounterCode = ENTERING_BLOODCAT_LAIR_CODE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No special bloodcat encounter. This ALWAYS happens in STATIC PLACEMENT sectors.
|
||||
gubEnemyEncounterCode = NO_ENCOUNTER_CODE;
|
||||
return FALSE;
|
||||
}
|
||||
@@ -4808,7 +4855,8 @@ void NotifyPlayerOfBloodcatBattle( UINT8 ubSectorX, UINT8 ubSectorY )
|
||||
}
|
||||
else if( gubEnemyEncounterCode == ENTERING_BLOODCAT_LAIR_CODE )
|
||||
{
|
||||
wcscpy( str, pMapErrorString[ 13 ] );
|
||||
GetSectorIDString( ubSectorX, ubSectorY, 0, zTempString, FALSE );
|
||||
swprintf( str, pMapErrorString[ 13 ], zTempString );
|
||||
}
|
||||
|
||||
if( guiCurrentScreen == MAP_SCREEN )
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include "Strategic Status.h"
|
||||
// HEADROCK HAM B1: Added include for Dynamic Roaming Militia
|
||||
#include "MilitiaSquads.h"
|
||||
// HEADROCK HAM 3.6: Include for Facility Debt
|
||||
#include "Facilities.h"
|
||||
#endif
|
||||
|
||||
// the max loyalty rating for any given town
|
||||
@@ -1817,7 +1819,7 @@ void CheckIfEntireTownHasBeenLiberated( INT8 bTownId, INT16 sSectorX, INT16 sSec
|
||||
UpdateLastDayOfPlayerActivity( ( UINT16 ) ( GetWorldDay() + 2 ) );
|
||||
}
|
||||
// HEADROCK HAM B1: Run a function to redefine Roaming Militia Restrictions on city capture.
|
||||
if (gGameExternalOptions.bDynamicRestrictRoaming)
|
||||
if (gGameExternalOptions.fDynamicRestrictRoaming)
|
||||
{
|
||||
AdjustRoamingRestrictions();
|
||||
}
|
||||
@@ -1994,3 +1996,24 @@ void MaximizeLoyaltyForDeidrannaKilled(void)
|
||||
SetTownLoyalty(bTownId, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: A loyalty hit based on outstanding debt for facility use.
|
||||
void HandleFacilityDebtLoyaltyHit( void )
|
||||
{
|
||||
// Loyalty hit is 1% per $1000 dollars owed.
|
||||
INT32 iLoyaltyHit = giTotalOwedForFacilityOperationsToday;
|
||||
|
||||
if (giTotalOwedForFacilityOperationsToday > 500)
|
||||
{
|
||||
// But no less than 1%, if $500 are owed.
|
||||
iLoyaltyHit = __max(500,iLoyaltyHit);
|
||||
}
|
||||
|
||||
if (iLoyaltyHit > 1)
|
||||
{
|
||||
DecrementTownLoyaltyEverywhere( iLoyaltyHit );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -204,4 +204,7 @@ void HandleLoyaltyImplicationsOfMercRetreat( INT8 bRetreatCode, INT16 sSectorX,
|
||||
|
||||
void MaximizeLoyaltyForDeidrannaKilled( void );
|
||||
|
||||
// HEADROCK HAM 3.6: Loyalty hit for owing too much money on facility work
|
||||
void HandleFacilityDebtLoyaltyHit( void );
|
||||
|
||||
#endif
|
||||
@@ -296,6 +296,10 @@
|
||||
RelativePath=".\Creature Spreading.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Facilities.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Game Clock.h"
|
||||
>
|
||||
@@ -470,6 +474,10 @@
|
||||
RelativePath=".\Creature Spreading.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Facilities.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Game Clock.cpp"
|
||||
>
|
||||
@@ -626,14 +634,38 @@
|
||||
RelativePath=".\XML_Army.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Bloodcats.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_DynamicRestrictions.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_ExtraItems.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Facilities.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_FacilityTypes.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Roaming.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_SectorNames.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_UniformColors.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
|
||||
@@ -295,6 +295,10 @@
|
||||
RelativePath="Creature Spreading.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Facilities.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Game Clock.h"
|
||||
>
|
||||
@@ -467,6 +471,10 @@
|
||||
RelativePath="Creature Spreading.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Facilities.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="Game Clock.cpp"
|
||||
>
|
||||
@@ -623,15 +631,39 @@
|
||||
RelativePath="XML_Army.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Bloodcats.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_DynamicRestrictions.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_ExtraItems.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_Facilities.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_FacilityTypes.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="XML_Roaming.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_SectorNames.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\XML_UniformColors.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\XML_ExtraItems.cpp"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
||||
+854
-144
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,11 @@ UINT8 CheckOneMilitiaForPromotion(INT16 sMapX, INT16 sMapY, UINT8 ubCurrentRank,
|
||||
|
||||
void BuildMilitiaPromotionsString( STR16 str );
|
||||
|
||||
// HEADROCK HAM 3.3: Function to determine best leadership for militia training in a given sector.
|
||||
// Is used for both town and mobile militia.
|
||||
// HEADROCK HAM 3.6: Argument for Mobile/Town Militia training
|
||||
UINT8 FindBestMilitiaTrainingLeadershipInSector ( INT16 sMapX, INT16 sMapY, INT8 usMapZ, UINT8 ubMilitiaType );
|
||||
|
||||
// call this if the player attacks his own militia
|
||||
void HandleMilitiaDefections(INT16 sMapX, INT16 sMapY);
|
||||
|
||||
@@ -70,7 +75,8 @@ BOOLEAN IsSAMSiteFullOfMilitia( INT16 sSectorX, INT16 sSectorY, INT8 iMilitiaTyp
|
||||
void HandleContinueOfTownTraining( void );
|
||||
|
||||
// handle completion of assignment byt his soldier too and inform the player
|
||||
void HandleCompletionOfTownTrainingByGroupWithTrainer( SOLDIERTYPE *pTrainer );
|
||||
// HEADROCK HAM 3.6: Added argument for Mobile Militia training.
|
||||
void HandleCompletionOfTownTrainingByGroupWithTrainer( SOLDIERTYPE *pTrainer, UINT8 ubMilitiaType );
|
||||
|
||||
// clear the list of training completed sectors
|
||||
void ClearSectorListForCompletedTrainingOfMilitia( void );
|
||||
@@ -78,4 +84,29 @@ void ClearSectorListForCompletedTrainingOfMilitia( void );
|
||||
BOOLEAN MilitiaTrainingAllowedInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ );
|
||||
BOOLEAN MilitiaTrainingAllowedInTown( INT8 bTownId );
|
||||
|
||||
// HEADROCK HAM 3.6: Function to calculate Militia and Mobile Militia training squad size.
|
||||
UINT8 CalcNumMilitiaTrained(UINT8 ubBestLeadership, BOOLEAN fMobile);
|
||||
|
||||
// HEADROCK HAM 3.6: Total upkeep costs for YESTERDAY at midnight. Saved to savegames.
|
||||
extern UINT32 guiTotalUpkeepForMilitia;
|
||||
|
||||
// HEADROCK HAM 3.6: Daily check for upkeep of all militia
|
||||
void HandleMilitiaUpkeepPayment( void );
|
||||
|
||||
// Type to hold number of militia in each sector.
|
||||
typedef struct MILITIA_LIST_TYPE
|
||||
{
|
||||
UINT8 ubSectorId;
|
||||
UINT8 ubNumTownGreens;
|
||||
UINT8 ubNumTownRegulars;
|
||||
UINT8 ubNumTownElites;
|
||||
UINT8 ubNumMobileGreens;
|
||||
UINT8 ubNumMobileRegulars;
|
||||
UINT8 ubNumMobileElites;
|
||||
|
||||
} MILITIA_LIST_TYPE;
|
||||
|
||||
// HEADROCK HAM 3.6: Calculate upkeep costs for militia
|
||||
UINT32 CalcMilitiaUpkeep( void );
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,343 @@
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Strategic All.h"
|
||||
#include "XML.h"
|
||||
#else
|
||||
#include "builddefines.h"
|
||||
#include <stdio.h>
|
||||
#include "XML.h"
|
||||
#include "expat.h"
|
||||
#include "string.h"
|
||||
#include "Campaign Types.h"
|
||||
#include "FileMan.h"
|
||||
#include "MemMan.h"
|
||||
#include "Debug Control.h"
|
||||
#include "mapscreen.h"
|
||||
#endif
|
||||
|
||||
#define MAX_CHAR_DATA_LENGTH 500
|
||||
|
||||
// This array stores all XML-read placement data. There are four arrays for each sector, one array for each difficulty
|
||||
// level. Please note that the Placement Type is only stored in array 0 (gBloodcatPlacements[x][0].PlacementType). It
|
||||
// is not possible to have different placement types at different difficulty levels. Yet.
|
||||
BLOODCATPLACEMENT gBloodcatPlacements[256][4];
|
||||
// Location of the Bloodcat Lair. There can be only one, as there's a quest that relies on its location. This is a
|
||||
// sectorID, 0-255.
|
||||
UINT8 gubBloodcatLairSectorId;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BLOODCAT_ELEMENT_NONE = 0,
|
||||
BLOODCAT_ELEMENT_PLACEMENTS,
|
||||
BLOODCAT_ELEMENT_SECTOR,
|
||||
BLOODCAT_ELEMENT,
|
||||
BLOODCAT_ELEMENT_DIFFICULTY,
|
||||
BLOODCAT_ELEMENT_DIFFICULTY_DATA,
|
||||
} BLOODCAT_PARSE_STAGE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BLOODCAT_PARSE_STAGE curElement;
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
UINT8 sCurSectorX;
|
||||
UINT8 sCurSectorY;
|
||||
BLOODCATPLACEMENT CurPlacement[4];
|
||||
UINT8 ubCurDifficulty;
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
} BloodcatsParseData;
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
BloodcatsStartElementHandle(void *userData, const XML_Char *name, const char **atts)
|
||||
{
|
||||
BloodcatsParseData * pData = (BloodcatsParseData *) userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
|
||||
if(strcmp(name, "BLOODCAT_PLACEMENTS") == 0 && pData->curElement == BLOODCAT_ELEMENT_NONE)
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_PLACEMENTS;
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
// Initiate Array by setting first character to 0.
|
||||
for (UINT16 x = 0; x < 256; x++)
|
||||
{
|
||||
for (UINT16 y = 0; y < 4; y++)
|
||||
{
|
||||
gBloodcatPlacements[x][y].ubFactionAffiliation = 0;
|
||||
gBloodcatPlacements[x][y].fRespawn = 0;
|
||||
gBloodcatPlacements[x][y].PlacementType = 0;
|
||||
gBloodcatPlacements[x][y].ubAmbushChance = 0;
|
||||
gBloodcatPlacements[x][y].ubMaxBloodcats = 0;
|
||||
gBloodcatPlacements[x][y].ubMinBloodcats = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if(strcmp(name, "SECTOR") == 0 && pData->curElement == BLOODCAT_ELEMENT_PLACEMENTS)
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
else if(pData->curElement == BLOODCAT_ELEMENT_SECTOR &&
|
||||
(strcmp(name, "SectorGrid") == 0 ||
|
||||
strcmp(name, "ubPlacementType") == 0) )
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
else if(pData->curElement == BLOODCAT_ELEMENT_SECTOR &&
|
||||
strcmp(name, "NOVICE") == 0)
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
||||
pData->ubCurDifficulty = 0;
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
else if(pData->curElement == BLOODCAT_ELEMENT_SECTOR &&
|
||||
strcmp(name, "EXPERIENCED") == 0)
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
||||
pData->ubCurDifficulty = 1;
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == BLOODCAT_ELEMENT_SECTOR &&
|
||||
strcmp(name, "EXPERT") == 0)
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
||||
pData->ubCurDifficulty = 2;
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(pData->curElement == BLOODCAT_ELEMENT_SECTOR &&
|
||||
strcmp(name, "INSANE") == 0)
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
||||
pData->ubCurDifficulty = 3;
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
else if(pData->curElement == BLOODCAT_ELEMENT_DIFFICULTY &&
|
||||
(strcmp(name, "ubMinBloodcats") == 0 ||
|
||||
strcmp(name, "ubMaxBloodcats") == 0 ||
|
||||
strcmp(name, "ubAmbushChance") == 0 ||
|
||||
strcmp(name, "ubFactionAffiliation") == 0 ||
|
||||
strcmp(name, "fRespawn") == 0 ))
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY_DATA;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
BloodcatsCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
BloodcatsParseData * pData = (BloodcatsParseData *) 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
|
||||
BloodcatsEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
BloodcatsParseData * pData = (BloodcatsParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
||||
{
|
||||
if(strcmp(name, "BLOODCAT_PLACEMENTS") == 0)
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_NONE;
|
||||
}
|
||||
else if(strcmp(name, "SECTOR") == 0)
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_PLACEMENTS;
|
||||
|
||||
UINT8 ubSectorId = SECTOR(pData->sCurSectorX, pData->sCurSectorY);
|
||||
if (ubSectorId >= 0 && ubSectorId < 256)
|
||||
{
|
||||
// Set placement type for this sector. Only first array has this set, as it is not difficulty-dependent.
|
||||
gBloodcatPlacements[ ubSectorId ][0].PlacementType = pData->CurPlacement[0].PlacementType;
|
||||
for (UINT8 x = 0; x < 4; x++)
|
||||
{
|
||||
if (pData->CurPlacement[0].PlacementType == 0)
|
||||
{
|
||||
// Ambush placement. Bloodcats will appear in this sector randomly.
|
||||
gBloodcatPlacements[ ubSectorId ][x].ubMinBloodcats = pData->CurPlacement[x].ubMinBloodcats;
|
||||
gBloodcatPlacements[ ubSectorId ][x].ubMaxBloodcats = pData->CurPlacement[x].ubMaxBloodcats;
|
||||
gBloodcatPlacements[ ubSectorId ][x].ubAmbushChance = pData->CurPlacement[x].ubAmbushChance;
|
||||
gBloodcatPlacements[ ubSectorId ][x].ubFactionAffiliation = 0;
|
||||
gBloodcatPlacements[ ubSectorId ][x].fRespawn = 0;
|
||||
}
|
||||
|
||||
else if (pData->CurPlacement[0].PlacementType == 1)
|
||||
{
|
||||
// Static placement. Bloodcats always appear here, but never respawn, and may be unaggressive
|
||||
// to enemies.
|
||||
gBloodcatPlacements[ ubSectorId ][x].ubMinBloodcats = 0;
|
||||
gBloodcatPlacements[ ubSectorId ][x].ubMaxBloodcats = pData->CurPlacement[x].ubMaxBloodcats;
|
||||
gBloodcatPlacements[ ubSectorId ][x].ubAmbushChance = 0;
|
||||
gBloodcatPlacements[ ubSectorId ][x].ubFactionAffiliation = pData->CurPlacement[x].ubFactionAffiliation;
|
||||
gBloodcatPlacements[ ubSectorId ][x].fRespawn = 0;
|
||||
}
|
||||
|
||||
else if (pData->CurPlacement[0].PlacementType == 2)
|
||||
{
|
||||
// Lair sector. There can be only one, and it is affected by the Quest. Bloodcats can regenerate
|
||||
// their numbers here over time.
|
||||
gBloodcatPlacements[ ubSectorId ][x].ubMinBloodcats = 0;
|
||||
gBloodcatPlacements[ ubSectorId ][x].ubMaxBloodcats = pData->CurPlacement[x].ubMaxBloodcats;
|
||||
gBloodcatPlacements[ ubSectorId ][x].ubAmbushChance = 0;
|
||||
gBloodcatPlacements[ ubSectorId ][x].ubFactionAffiliation = 0;
|
||||
gBloodcatPlacements[ ubSectorId ][x].fRespawn = pData->CurPlacement[x].fRespawn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if(strcmp(name, "SectorGrid") == 0 )
|
||||
{
|
||||
UINT8 x, y;
|
||||
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
||||
|
||||
y = (UINT8)pData->szCharData[0] & 0x1F;
|
||||
x = (UINT8)atol(&pData->szCharData[1]);
|
||||
if ( x > 0 && x <= 16 && y > 0 && y <= 16 )
|
||||
{
|
||||
pData->sCurSectorX = x;
|
||||
pData->sCurSectorY = y;
|
||||
}
|
||||
THROWIFFALSE( (SECTOR(x,y) >= 0 && SECTOR(x,y) < 256) , L"Illegal sector number in BloodcatPlacements.XML" );
|
||||
}
|
||||
else if(strcmp(name, "ubPlacementType") == 0 )
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
||||
// Only set for first array (Difficulty Irrelevant)
|
||||
pData->CurPlacement[0].PlacementType = (UINT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "NOVICE") == 0 )
|
||||
{
|
||||
// Just return to sector data.
|
||||
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
||||
}
|
||||
|
||||
else if(strcmp(name, "EXPERIENCED") == 0 )
|
||||
{
|
||||
// Just return to sector data.
|
||||
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
||||
}
|
||||
|
||||
else if(strcmp(name, "EXPERT") == 0 )
|
||||
{
|
||||
// Just return to sector data.
|
||||
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
||||
}
|
||||
|
||||
else if(strcmp(name, "INSANE") == 0 )
|
||||
{
|
||||
// Just return to sector data.
|
||||
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
||||
}
|
||||
|
||||
else if(strcmp(name, "ubMinBloodcats") == 0 )
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
||||
pData->CurPlacement[pData->ubCurDifficulty].ubMinBloodcats = (UINT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "ubMaxBloodcats") == 0 )
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
||||
pData->CurPlacement[pData->ubCurDifficulty].ubMaxBloodcats = (UINT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "ubAmbushChance") == 0 )
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
||||
pData->CurPlacement[pData->ubCurDifficulty].ubAmbushChance = (UINT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "ubFactionAffiliation") == 0 )
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
||||
pData->CurPlacement[pData->ubCurDifficulty].ubFactionAffiliation = (UINT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "fRespawn") == 0 )
|
||||
{
|
||||
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
||||
pData->CurPlacement[pData->ubCurDifficulty].fRespawn = (UINT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN ReadInBloodcatPlacements(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
BloodcatsParseData pData;
|
||||
|
||||
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
|
||||
if ( !hFile )
|
||||
return( FALSE );
|
||||
|
||||
uiFSize = FileGetSize(hFile);
|
||||
lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1);
|
||||
|
||||
//Read in block
|
||||
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
|
||||
{
|
||||
MemFree(lpcBuffer);
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
lpcBuffer[uiFSize] = 0; //add a null terminator
|
||||
|
||||
FileClose( hFile );
|
||||
|
||||
|
||||
XML_SetElementHandler(parser, BloodcatsStartElementHandle, BloodcatsEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, BloodcatsCharacterDataHandle);
|
||||
|
||||
|
||||
memset(&pData,0,sizeof(pData));
|
||||
XML_SetUserData(parser, &pData);
|
||||
|
||||
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
|
||||
{
|
||||
CHAR8 errorBuf[511];
|
||||
sprintf(errorBuf, "XML Parser Error in BloodcatPlacements.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
|
||||
LiveMessage(errorBuf);
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
|
||||
XML_ParserFree(parser);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// HEADROCK HAM 3.4: Dynamic Roaming Restrictions XMLization
|
||||
//
|
||||
// This is a new part of the Dynamic Roaming Restrictions system. It reads in
|
||||
// data about sectors to "un-restrict", and the towns that must be liberated
|
||||
// for them to be unrestricted. There can be several unrestriction conditions
|
||||
// for each sector, and only one of the conditions must be true for the sector
|
||||
// to become allowed.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Tactical All.h"
|
||||
#else
|
||||
#include "sgp.h"
|
||||
#include "Debug Control.h"
|
||||
#include "expat.h"
|
||||
#include "gamesettings.h"
|
||||
#include "XML.h"
|
||||
#include "FileMan.h"
|
||||
#include "campaign types.h"
|
||||
#include "militiasquads.h"
|
||||
#include "mapscreen.h"
|
||||
#endif
|
||||
|
||||
// HEADROCK HAM 3.4: Stores restriction data from XML, including required cities for each sector to be allowed.
|
||||
extern DYNAMICRESTRICTIONS gDynamicRestrictions[5001];
|
||||
|
||||
struct
|
||||
{
|
||||
PARSE_STAGE curElement;
|
||||
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
|
||||
INT16 sCurSectorX;
|
||||
INT16 sCurSectorY;
|
||||
UINT32 uiReqTownFlags;
|
||||
UINT32 maxArraySize;
|
||||
UINT32 curIndex;
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
}
|
||||
typedef dynamicroamingParseData;
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
dynamicroamingStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
dynamicroamingParseData * pData = (dynamicroamingParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
if(strcmp(name, "DYNAMICROAMING") == 0 && pData->curElement == ELEMENT_NONE)
|
||||
{
|
||||
// Set all sector IDs to -1 ("unused")
|
||||
for (UINT16 cnt=0; cnt<5001; cnt++)
|
||||
{
|
||||
gDynamicRestrictions[cnt].bSectorID = -1;
|
||||
}
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(strcmp(name, "RESTRICTION") == 0 && pData->curElement == ELEMENT_LIST)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->uiReqTownFlags = 0;
|
||||
|
||||
//DebugMsg(TOPIC_JA2, DBG_LEVEL_3,"MergeStartElementHandle: setting memory for curMerge");
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
|
||||
//pData->curIndex++;
|
||||
}
|
||||
else if(pData->curElement == ELEMENT &&
|
||||
(strcmp(name, "SectorGrid") == 0 ||
|
||||
strcmp(name, "ReqTown") == 0 ))
|
||||
{
|
||||
pData->curElement = ELEMENT_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
dynamicroamingCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
dynamicroamingParseData * pData = (dynamicroamingParseData *)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
|
||||
dynamicroamingEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
dynamicroamingParseData * pData = (dynamicroamingParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
||||
{
|
||||
if(strcmp(name, "DYNAMICROAMING") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_NONE;
|
||||
}
|
||||
else if(strcmp(name, "RESTRICTION") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
if (SECTOR(pData->sCurSectorX, pData->sCurSectorY) >= 0 && SECTOR(pData->sCurSectorX, pData->sCurSectorY) < 256)
|
||||
{
|
||||
pData->curIndex++;
|
||||
gDynamicRestrictions[pData->curIndex].bSectorID = SECTOR(pData->sCurSectorX,pData->sCurSectorY);
|
||||
gDynamicRestrictions[pData->curIndex].uiReqTownFlags |= pData->uiReqTownFlags;
|
||||
}
|
||||
}
|
||||
|
||||
else if(strcmp(name, "SectorGrid") == 0 )
|
||||
{
|
||||
UINT8 x, y;
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
y = (UINT8)pData->szCharData[0] & 0x1F;
|
||||
x = (UINT8)atol(&pData->szCharData[1]);
|
||||
if ( x > 0 && x <= 16 && y > 0 && y <= 16 )
|
||||
{
|
||||
pData->sCurSectorX = x;
|
||||
pData->sCurSectorY = y;
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, "ReqTown") == 0 )
|
||||
{
|
||||
if ((UINT8) atol(pData->szCharData) > 0 && (UINT8) atol(pData->szCharData) < NUM_TOWNS )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->uiReqTownFlags |= (1 << ((UINT8) atol(pData->szCharData) - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
pData->uiReqTownFlags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
BOOLEAN ReadInDynamicRoamingRestrictions(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
dynamicroamingParseData pData;
|
||||
|
||||
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading DynamicRestrictions.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, dynamicroamingStartElementHandle, dynamicroamingEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, dynamicroamingCharacterDataHandle);
|
||||
|
||||
|
||||
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 DynamicRestrictions.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
|
||||
LiveMessage(errorBuf);
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
|
||||
|
||||
XML_ParserFree(parser);
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// HEADROCK HAM 3.5: Facility Location Externalization
|
||||
//
|
||||
// This file reads from an XML called "Facilities.XML". That file contains
|
||||
// the locations of all facilities such as the "Gun Range", "Industrial",
|
||||
// "Prison", etcetera. The data is written DIRECTLY into the global SectorInfo
|
||||
// array, replacing a hardcoded system.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Tactical All.h"
|
||||
#else
|
||||
#include "sgp.h"
|
||||
#include "Debug Control.h"
|
||||
#include "expat.h"
|
||||
#include "gamesettings.h"
|
||||
#include "XML.h"
|
||||
#include "FileMan.h"
|
||||
#include "Campaign Types.h"
|
||||
#endif
|
||||
|
||||
FACILITYLOCATIONS gFacilityLocations[256][MAX_NUM_FACILITY_TYPES];
|
||||
UINT16 NUM_FACILITIES;
|
||||
|
||||
struct
|
||||
{
|
||||
PARSE_STAGE curElement;
|
||||
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
|
||||
INT16 sCurSectorX;
|
||||
INT16 sCurSectorY;
|
||||
UINT8 ubCurFacilityType;
|
||||
UINT8 ubHidden;
|
||||
UINT32 maxArraySize;
|
||||
UINT32 curIndex;
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
}
|
||||
typedef facilityParseData;
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
facilityStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
|
||||
{
|
||||
facilityParseData * pData = (facilityParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
if(strcmp(name, "SECTORFACILITIES") == 0 && pData->curElement == ELEMENT_NONE)
|
||||
{
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
else if(strcmp(name, "FACILITY") == 0 && pData->curElement == ELEMENT_LIST)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
//DebugMsg(TOPIC_JA2, DBG_LEVEL_3,"MergeStartElementHandle: setting memory for curMerge");
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
|
||||
//pData->curIndex++;
|
||||
}
|
||||
else if(pData->curElement == ELEMENT &&
|
||||
(strcmp(name, "SectorGrid") == 0 ||
|
||||
strcmp(name, "FacilityType") == 0 ||
|
||||
strcmp(name, "ubHidden") == 0
|
||||
))
|
||||
{
|
||||
pData->curElement = ELEMENT_PROPERTY;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
static void XMLCALL
|
||||
facilityCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
facilityParseData * pData = (facilityParseData *)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
|
||||
facilityEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
facilityParseData * pData = (facilityParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
||||
{
|
||||
if(strcmp(name, "SECTORFACILITIES") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT_NONE;
|
||||
NUM_FACILITIES = pData->curIndex;
|
||||
}
|
||||
else if(strcmp(name, "FACILITY") == 0)
|
||||
{
|
||||
pData->curIndex++;
|
||||
pData->curElement = ELEMENT_LIST;
|
||||
|
||||
if (pData->ubCurFacilityType != 0)
|
||||
{
|
||||
gFacilityLocations[SECTOR(pData->sCurSectorX,pData->sCurSectorY)][pData->ubCurFacilityType].fFacilityHere = TRUE;
|
||||
gFacilityLocations[SECTOR(pData->sCurSectorX,pData->sCurSectorY)][pData->ubCurFacilityType].ubHidden = pData->ubHidden;
|
||||
}
|
||||
}
|
||||
|
||||
else if(strcmp(name, "SectorGrid") == 0 )
|
||||
{
|
||||
UINT8 x, y;
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
y = (UINT8)pData->szCharData[0] & 0x1F;
|
||||
x = (UINT8)atol(&pData->szCharData[1]);
|
||||
if ( x > 0 && x <= 16 && y > 0 && y <= 16 )
|
||||
{
|
||||
pData->sCurSectorX = x;
|
||||
pData->sCurSectorY = y;
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, "FacilityType") == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->ubCurFacilityType = (UINT8) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "ubHidden") == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->ubHidden = (BOOLEAN) atol(pData->szCharData);
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
BOOLEAN ReadInSectorFacilities(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
facilityParseData pData;
|
||||
|
||||
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Loading Facilities.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, facilityStartElementHandle, facilityEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, facilityCharacterDataHandle);
|
||||
|
||||
|
||||
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 Facilities.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 );
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,6 @@
|
||||
extern INT32 iRestrictedSectorArraySize;
|
||||
extern UINT32 gRestrictMilitia[256];
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ROAMING_ELEMENT_NONE = 0,
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Strategic All.h"
|
||||
#include "XML.h"
|
||||
#else
|
||||
#include "builddefines.h"
|
||||
#include <stdio.h>
|
||||
#include "XML.h"
|
||||
#include "expat.h"
|
||||
#include "string.h"
|
||||
#include "Campaign Types.h"
|
||||
#include "FileMan.h"
|
||||
#include "MemMan.h"
|
||||
#include "Debug Control.h"
|
||||
#include "mapscreen.h"
|
||||
#endif
|
||||
|
||||
#define MAX_CHAR_DATA_LENGTH 500
|
||||
|
||||
// Four different sector names, used at different times.
|
||||
extern CHAR16 gzSectorNames[256][4][MAX_SECTOR_NAME_LENGTH];
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SECTORNAME_ELEMENT_NONE = 0,
|
||||
SECTORNAME_ELEMENT_SECTOR_NAMES,
|
||||
SECTORNAME_ELEMENT_SECTOR,
|
||||
SECTORNAME_ELEMENT,
|
||||
} SECTORNAME_PARSE_STAGE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SECTORNAME_PARSE_STAGE curElement;
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
UINT8 sCurSectorX;
|
||||
UINT8 sCurSectorY;
|
||||
CHAR16 szCurUnexploredName[MAX_SECTOR_NAME_LENGTH];
|
||||
CHAR16 szCurDetailedUnexploredName[MAX_SECTOR_NAME_LENGTH];
|
||||
CHAR16 szCurExploredName[MAX_SECTOR_NAME_LENGTH];
|
||||
CHAR16 szCurDetailedExploredName[MAX_SECTOR_NAME_LENGTH];
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
} SectorNameParseData;
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
SectorNameStartElementHandle(void *userData, const XML_Char *name, const char **atts)
|
||||
{
|
||||
SectorNameParseData * pData = (SectorNameParseData *) userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
|
||||
if(strcmp(name, "SECTOR_NAMES") == 0 && pData->curElement == SECTORNAME_ELEMENT_NONE)
|
||||
{
|
||||
pData->curElement = SECTORNAME_ELEMENT_SECTOR_NAMES;
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
// Initiate Array by setting first character to 0.
|
||||
for (UINT16 x = 0; x < 256; x++)
|
||||
{
|
||||
gzSectorNames[x][0][0]=0;
|
||||
gzSectorNames[x][1][0]=0;
|
||||
gzSectorNames[x][2][0]=0;
|
||||
gzSectorNames[x][3][0]=0;
|
||||
}
|
||||
}
|
||||
|
||||
else if(strcmp(name, "SECTOR") == 0 && pData->curElement == SECTORNAME_ELEMENT_SECTOR_NAMES)
|
||||
{
|
||||
pData->curElement = SECTORNAME_ELEMENT_SECTOR;
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
else if(pData->curElement == SECTORNAME_ELEMENT_SECTOR &&
|
||||
(strcmp(name, "SectorGrid") == 0 ||
|
||||
strcmp(name, "szUnexploredName") == 0 ||
|
||||
strcmp(name, "szDetailedUnexploredName") == 0 ||
|
||||
strcmp(name, "szExploredName") == 0 ||
|
||||
strcmp(name, "szDetailedExploredName") == 0 ))
|
||||
{
|
||||
pData->curElement = SECTORNAME_ELEMENT;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
SectorNameCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
SectorNameParseData * pData = (SectorNameParseData *) 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
|
||||
SectorNameEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
SectorNameParseData * pData = (SectorNameParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
||||
{
|
||||
if(strcmp(name, "SECTOR_NAMES") == 0)
|
||||
{
|
||||
pData->curElement = SECTORNAME_ELEMENT_NONE;
|
||||
}
|
||||
else if(strcmp(name, "SECTOR") == 0)
|
||||
{
|
||||
pData->curElement = SECTORNAME_ELEMENT_SECTOR_NAMES;
|
||||
|
||||
UINT8 ubSectorId = SECTOR(pData->sCurSectorX, pData->sCurSectorY);
|
||||
if (ubSectorId >= 0 && ubSectorId < 256)
|
||||
{
|
||||
wcscpy(gzSectorNames[ubSectorId][0], pData->szCurUnexploredName);
|
||||
wcscpy(gzSectorNames[ubSectorId][1], pData->szCurDetailedUnexploredName);
|
||||
wcscpy(gzSectorNames[ubSectorId][2], pData->szCurExploredName);
|
||||
wcscpy(gzSectorNames[ubSectorId][3], pData->szCurDetailedExploredName);
|
||||
}
|
||||
}
|
||||
|
||||
else if(strcmp(name, "SectorGrid") == 0 )
|
||||
{
|
||||
UINT8 x, y;
|
||||
pData->curElement = SECTORNAME_ELEMENT_SECTOR;
|
||||
|
||||
y = (UINT8)pData->szCharData[0] & 0x1F;
|
||||
x = (UINT8)atol(&pData->szCharData[1]);
|
||||
if ( x > 0 && x <= 16 && y > 0 && y <= 16 )
|
||||
{
|
||||
pData->sCurSectorX = x;
|
||||
pData->sCurSectorY = y;
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, "szUnexploredName") == 0 )
|
||||
{
|
||||
pData->curElement = SECTORNAME_ELEMENT_SECTOR;
|
||||
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->szCurUnexploredName, sizeof(pData->szCurUnexploredName)/sizeof(pData->szCurUnexploredName[0]) );
|
||||
pData->szCurUnexploredName[sizeof(pData->szCurUnexploredName)/sizeof(pData->szCurUnexploredName[0]) - 1] = '\0';
|
||||
}
|
||||
|
||||
else if(strcmp(name, "szDetailedUnexploredName") == 0 )
|
||||
{
|
||||
pData->curElement = SECTORNAME_ELEMENT_SECTOR;
|
||||
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->szCurDetailedUnexploredName, sizeof(pData->szCurDetailedUnexploredName)/sizeof(pData->szCurDetailedUnexploredName[0]) );
|
||||
pData->szCurDetailedUnexploredName[sizeof(pData->szCurDetailedUnexploredName)/sizeof(pData->szCurDetailedUnexploredName[0]) - 1] = '\0';
|
||||
}
|
||||
|
||||
else if(strcmp(name, "szExploredName") == 0 )
|
||||
{
|
||||
pData->curElement = SECTORNAME_ELEMENT_SECTOR;
|
||||
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->szCurExploredName, sizeof(pData->szCurExploredName)/sizeof(pData->szCurExploredName[0]) );
|
||||
pData->szCurExploredName[sizeof(pData->szCurExploredName)/sizeof(pData->szCurExploredName[0]) - 1] = '\0';
|
||||
}
|
||||
|
||||
else if(strcmp(name, "szDetailedExploredName") == 0 )
|
||||
{
|
||||
pData->curElement = SECTORNAME_ELEMENT_SECTOR;
|
||||
|
||||
MultiByteToWideChar( CP_UTF8, 0, pData->szCharData, -1, pData->szCurDetailedExploredName, sizeof(pData->szCurDetailedExploredName)/sizeof(pData->szCurDetailedExploredName[0]) );
|
||||
pData->szCurDetailedExploredName[sizeof(pData->szCurDetailedExploredName)/sizeof(pData->szCurDetailedExploredName[0]) - 1] = '\0';
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN ReadInSectorNames(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
SectorNameParseData pData;
|
||||
|
||||
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
|
||||
if ( !hFile )
|
||||
return( FALSE );
|
||||
|
||||
uiFSize = FileGetSize(hFile);
|
||||
lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1);
|
||||
|
||||
//Read in block
|
||||
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
|
||||
{
|
||||
MemFree(lpcBuffer);
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
lpcBuffer[uiFSize] = 0; //add a null terminator
|
||||
|
||||
FileClose( hFile );
|
||||
|
||||
|
||||
XML_SetElementHandler(parser, SectorNameStartElementHandle, SectorNameEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, SectorNameCharacterDataHandle);
|
||||
|
||||
|
||||
memset(&pData,0,sizeof(pData));
|
||||
XML_SetUserData(parser, &pData);
|
||||
|
||||
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
|
||||
{
|
||||
CHAR8 errorBuf[511];
|
||||
sprintf(errorBuf, "XML Parser Error in SectorNames.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
|
||||
LiveMessage(errorBuf);
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MemFree(lpcBuffer);
|
||||
|
||||
XML_ParserFree(parser);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// HEADROCK HAM 3.6:
|
||||
//
|
||||
// This code reads an XML called "UniformColors.XML", which tells the program which colors to use for
|
||||
// "standard" uniforms, including randomly-generated enemies and militia (for now).
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#ifdef PRECOMPILEDHEADERS
|
||||
#include "Strategic All.h"
|
||||
#include "XML.h"
|
||||
#else
|
||||
#include "builddefines.h"
|
||||
#include <stdio.h>
|
||||
#include "XML.h"
|
||||
#include "expat.h"
|
||||
#include "string.h"
|
||||
#include "Campaign Types.h"
|
||||
#include "FileMan.h"
|
||||
#include "MemMan.h"
|
||||
#include "Debug Control.h"
|
||||
#include "mapscreen.h"
|
||||
#endif
|
||||
|
||||
#define MAX_CHAR_DATA_LENGTH 500
|
||||
|
||||
// Error strings for this XML reader
|
||||
STR16 szUniformErrorStrings[]=
|
||||
{
|
||||
L"ENEMY_ADMIN",
|
||||
L"ENEMY_TROOP",
|
||||
L"ENEMY_ELITE",
|
||||
L"MILITIA_ROOKIE",
|
||||
L"MILITIA_REGULAR",
|
||||
L"MILITIA_ELITE",
|
||||
};
|
||||
|
||||
// Array to hold uniform data
|
||||
UNIFORMCOLORS gUniformColors[NUM_UNIFORMS];
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UNIFORM_ELEMENT_NONE = 0,
|
||||
UNIFORM_ELEMENT_LIST,
|
||||
UNIFORM_ELEMENT,
|
||||
UNIFORM_ELEMENT_DATA,
|
||||
} UNIFORM_PARSE_STAGE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UNIFORM_PARSE_STAGE curElement;
|
||||
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
||||
UINT8 sCurUniform;
|
||||
PaletteRepID szCurVest;
|
||||
PaletteRepID szCurPants;
|
||||
UINT32 currentDepth;
|
||||
UINT32 maxReadDepth;
|
||||
} UniformParseData;
|
||||
|
||||
// Array for flags making sure that we have ALL uniform data defined.
|
||||
BOOLEAN UniformDataFound[NUM_UNIFORMS];
|
||||
|
||||
static void XMLCALL
|
||||
UniformStartElementHandle(void *userData, const XML_Char *name, const char **atts)
|
||||
{
|
||||
UniformParseData * pData = (UniformParseData *) userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
||||
{
|
||||
|
||||
if(strcmp(name, "UNIFORMS") == 0 && pData->curElement == UNIFORM_ELEMENT_NONE)
|
||||
{
|
||||
pData->curElement = UNIFORM_ELEMENT_LIST;
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
for (UINT8 cnt = 0; cnt < NUM_UNIFORMS; cnt++)
|
||||
{
|
||||
// reset array
|
||||
UniformDataFound[cnt] = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
else if(pData->curElement == UNIFORM_ELEMENT_LIST &&
|
||||
(strcmp(name, "ENEMY_ADMIN") == 0 ||
|
||||
strcmp(name, "ENEMY_TROOP") == 0 ||
|
||||
strcmp(name, "ENEMY_ELITE") == 0 ||
|
||||
strcmp(name, "MILITIA_ROOKIE") == 0 ||
|
||||
strcmp(name, "MILITIA_REGULAR") == 0 ||
|
||||
strcmp(name, "MILITIA_ELITE") == 0 ) )
|
||||
{
|
||||
if (strcmp(name, "ENEMY_ADMIN") == 0)
|
||||
{
|
||||
pData->sCurUniform = UNIFORM_ENEMY_ADMIN;
|
||||
}
|
||||
else if (strcmp(name, "ENEMY_TROOP") == 0)
|
||||
{
|
||||
pData->sCurUniform = UNIFORM_ENEMY_TROOP;
|
||||
}
|
||||
else if (strcmp(name, "ENEMY_ELITE") == 0)
|
||||
{
|
||||
pData->sCurUniform = UNIFORM_ENEMY_ELITE;
|
||||
}
|
||||
else if (strcmp(name, "MILITIA_ROOKIE") == 0)
|
||||
{
|
||||
pData->sCurUniform = UNIFORM_MILITIA_ROOKIE;
|
||||
}
|
||||
else if (strcmp(name, "MILITIA_REGULAR") == 0)
|
||||
{
|
||||
pData->sCurUniform = UNIFORM_MILITIA_REGULAR;
|
||||
}
|
||||
else if (strcmp(name, "MILITIA_ELITE") == 0)
|
||||
{
|
||||
pData->sCurUniform = UNIFORM_MILITIA_ELITE;
|
||||
}
|
||||
pData->curElement = UNIFORM_ELEMENT;
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
else if(pData->curElement == UNIFORM_ELEMENT &&
|
||||
(strcmp(name, "Vest") == 0 ||
|
||||
strcmp(name, "Pants") == 0 ))
|
||||
{
|
||||
pData->curElement = UNIFORM_ELEMENT_DATA;
|
||||
|
||||
pData->maxReadDepth++; //we are not skipping this element
|
||||
}
|
||||
|
||||
pData->szCharData[0] = '\0';
|
||||
}
|
||||
|
||||
pData->currentDepth++;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void XMLCALL
|
||||
UniformCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
||||
{
|
||||
UniformParseData * pData = (UniformParseData *) 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
|
||||
UniformEndElementHandle(void *userData, const XML_Char *name)
|
||||
{
|
||||
UniformParseData * pData = (UniformParseData *)userData;
|
||||
|
||||
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
||||
{
|
||||
if(strcmp(name, "UNIFORMS") == 0)
|
||||
{
|
||||
// All entries are mandatory. Exception thrown if an entry was not found
|
||||
for (UINT8 cnt = 0; cnt < NUM_UNIFORMS; cnt++)
|
||||
{
|
||||
if (!UniformDataFound[cnt])
|
||||
{
|
||||
CHAR16 sString[256];
|
||||
swprintf( sString, L"Error in UniformColors.XML: Uniform color for %s not found or not properly defined!", szUniformErrorStrings[ cnt ] );
|
||||
THROWEXCEPTION( sString );
|
||||
}
|
||||
}
|
||||
|
||||
pData->curElement = UNIFORM_ELEMENT_NONE;
|
||||
}
|
||||
|
||||
else if(strcmp(name, "ENEMY_ADMIN") == 0 ||
|
||||
strcmp(name, "ENEMY_TROOP") == 0 ||
|
||||
strcmp(name, "ENEMY_ELITE") == 0 ||
|
||||
strcmp(name, "MILITIA_ROOKIE") == 0 ||
|
||||
strcmp(name, "MILITIA_REGULAR") == 0 ||
|
||||
strcmp(name, "MILITIA_ELITE") == 0 )
|
||||
{
|
||||
pData->curElement = UNIFORM_ELEMENT_LIST;
|
||||
|
||||
if (pData->sCurUniform >= UNIFORM_ENEMY_ADMIN && pData->sCurUniform < NUM_UNIFORMS )
|
||||
{
|
||||
memcpy( &(gUniformColors[pData->sCurUniform].pants), &(pData->szCurPants), sizeof(PaletteRepID) );
|
||||
memcpy( &(gUniformColors[pData->sCurUniform].vest), &(pData->szCurVest), sizeof(PaletteRepID) );
|
||||
UniformDataFound[pData->sCurUniform] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Vest") == 0 )
|
||||
{
|
||||
pData->curElement = UNIFORM_ELEMENT;
|
||||
|
||||
strcpy(pData->szCurVest, pData->szCharData);
|
||||
}
|
||||
|
||||
else if(strcmp(name, "Pants") == 0 )
|
||||
{
|
||||
pData->curElement = UNIFORM_ELEMENT;
|
||||
|
||||
strcpy(pData->szCurPants, pData->szCharData);
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
|
||||
pData->currentDepth--;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN ReadInUniforms(STR fileName)
|
||||
{
|
||||
HWFILE hFile;
|
||||
UINT32 uiBytesRead;
|
||||
UINT32 uiFSize;
|
||||
CHAR8 * lpcBuffer;
|
||||
XML_Parser parser = XML_ParserCreate(NULL);
|
||||
|
||||
UniformParseData pData;
|
||||
|
||||
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
|
||||
if ( !hFile )
|
||||
return( FALSE );
|
||||
|
||||
uiFSize = FileGetSize(hFile);
|
||||
lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1);
|
||||
|
||||
//Read in block
|
||||
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
|
||||
{
|
||||
MemFree(lpcBuffer);
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
lpcBuffer[uiFSize] = 0; //add a null terminator
|
||||
|
||||
FileClose( hFile );
|
||||
|
||||
|
||||
XML_SetElementHandler(parser, UniformStartElementHandle, UniformEndElementHandle);
|
||||
XML_SetCharacterDataHandler(parser, UniformCharacterDataHandle);
|
||||
|
||||
|
||||
memset(&pData,0,sizeof(pData));
|
||||
XML_SetUserData(parser, &pData);
|
||||
|
||||
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
|
||||
{
|
||||
CHAR8 errorBuf[511];
|
||||
sprintf(errorBuf, "XML Parser Error in UniformColors.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;
|
||||
}
|
||||
+329
-11
@@ -111,6 +111,8 @@
|
||||
#include "Strategic Status.h"
|
||||
#include "Soldier Create.h"
|
||||
#include "Animation Control.h"
|
||||
// HEADROCK HAM 3.6: Include facilities for assignment display
|
||||
#include "Facilities.h"
|
||||
#endif
|
||||
|
||||
#include "connect.h" //hayden
|
||||
@@ -905,6 +907,9 @@ void CreateContractBox( SOLDIERTYPE *pCharacter );
|
||||
void CreateAssignmentsBox( void );
|
||||
void CreateTrainingBox( void );
|
||||
void CreateMercRemoveAssignBox( void );
|
||||
// HEADROCK HAM 3.6: Facility box, Sub-menu
|
||||
void CreateFacilityBox( void );
|
||||
void CreateFacilityAssignmentBox( void );
|
||||
|
||||
void DetermineWhichAssignmentMenusCanBeShown( void );
|
||||
void DetermineWhichMilitiaControlMenusCanBeShown( void ); //lal
|
||||
@@ -2837,16 +2842,29 @@ void DrawCharacterInfo(INT16 sCharNumber)
|
||||
|
||||
// second assignment line
|
||||
|
||||
// HEADROCK HAM 3.6: Operating a facility?
|
||||
if (pSoldier->sFacilityTypeOperated != -1)
|
||||
{
|
||||
UINT8 ubFacilityType = (UINT8)pSoldier->sFacilityTypeOperated;
|
||||
// Print sector ID string
|
||||
GetShortSectorString( pSoldier->sSectorX, pSoldier->sSectorY, sString );
|
||||
wcscat( sString, L": " );
|
||||
wcscat( sString, gFacilityTypes[ubFacilityType].szFacilityShortName );
|
||||
//wcscpy(sString, gFacilityTypes[ pSoldier->sFacilityTypeOperated ].szFacilityName);
|
||||
}
|
||||
|
||||
// train self / teammate / by other ?
|
||||
if( ( pSoldier->bAssignment == TRAIN_SELF ) || ( pSoldier->bAssignment == TRAIN_TEAMMATE ) || ( pSoldier->bAssignment == TRAIN_BY_OTHER ) )
|
||||
else if( ( pSoldier->bAssignment == TRAIN_SELF ) || ( pSoldier->bAssignment == TRAIN_TEAMMATE ) || ( pSoldier->bAssignment == TRAIN_BY_OTHER ) )
|
||||
{
|
||||
wcscpy(sString, pAttributeMenuStrings[pSoldier->bTrainStat]);
|
||||
}
|
||||
// train town?
|
||||
else if( pSoldier->bAssignment == TRAIN_TOWN )
|
||||
// HEADROCK HAM 3.6: Draw for Mobile Trainers as well.
|
||||
else if( pSoldier->bAssignment == TRAIN_TOWN || pSoldier->bAssignment == TRAIN_MOBILE )
|
||||
{
|
||||
wcscpy(sString,pTownNames[GetTownIdForSector( pSoldier->sSectorX, pSoldier->sSectorY ) ] );
|
||||
}
|
||||
|
||||
// repairing?
|
||||
else if( pSoldier->bAssignment == REPAIR )
|
||||
{
|
||||
@@ -3127,6 +3145,136 @@ void DisplayCharacterInfo( void )
|
||||
// set font buffer
|
||||
SetFontDestBuffer( guiSAVEBUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
|
||||
|
||||
// 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 STRATEGIC info pages. Another section is in Interface Panels.cpp and draws TACTICAL 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] )
|
||||
{
|
||||
SOLDIERTYPE *pSoldier = MercPtrs[ gCharactersList[bSelectedInfoChar].usSolID ];
|
||||
|
||||
UINT8 *pDestBuf;
|
||||
UINT32 uiDestPitchBYTES = 0;
|
||||
SGPRect ClipRect;
|
||||
UINT8 ubBarWidth = 0;
|
||||
UINT16 usColor = Get16BPPColor( FROMRGB( gGameExternalOptions.ubStatProgressBarsRed, gGameExternalOptions.ubStatProgressBarsGreen, gGameExternalOptions.ubStatProgressBarsBlue ) );
|
||||
//pDestBuf = LockVideoSurface( FRAME_BUFFER, &uiDestPitchBYTES );
|
||||
pDestBuf = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES );
|
||||
|
||||
// AGI
|
||||
if (gMercProfiles[ pSoldier->ubProfile ].sAgilityGain)
|
||||
{
|
||||
ubBarWidth = (STAT_WID * (gMercProfiles[ pSoldier->ubProfile ].sAgilityGain+1)) / SubpointsPerPoint(AGILAMT,0);
|
||||
ClipRect.iTop = (AGL_Y-1);
|
||||
ClipRect.iBottom = (AGL_Y-1) + STAT_HEI;
|
||||
ClipRect.iLeft = AGL_X;
|
||||
ClipRect.iRight = AGL_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// DEX
|
||||
if (gMercProfiles[ pSoldier->ubProfile ].sDexterityGain)
|
||||
{
|
||||
ubBarWidth = (STAT_WID * (gMercProfiles[ pSoldier->ubProfile ].sDexterityGain+1)) / SubpointsPerPoint(DEXTAMT,0);
|
||||
ClipRect.iTop = (DEX_Y-1);
|
||||
ClipRect.iBottom = (DEX_Y-1) + STAT_HEI;
|
||||
ClipRect.iLeft = DEX_X;
|
||||
ClipRect.iRight = DEX_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// STR
|
||||
if (gMercProfiles[ pSoldier->ubProfile ].sStrengthGain)
|
||||
{
|
||||
ubBarWidth = (STAT_WID * (gMercProfiles[ pSoldier->ubProfile ].sStrengthGain+1)) / SubpointsPerPoint(STRAMT,0);
|
||||
ClipRect.iTop = (STR_Y-1);
|
||||
ClipRect.iBottom = (STR_Y-1) + STAT_HEI;
|
||||
ClipRect.iLeft = STR_X;
|
||||
ClipRect.iRight = STR_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// WIS
|
||||
if (gMercProfiles[ pSoldier->ubProfile ].sWisdomGain)
|
||||
{
|
||||
ubBarWidth = (STAT_WID * (gMercProfiles[ pSoldier->ubProfile ].sWisdomGain+1)) / SubpointsPerPoint(WISDOMAMT,0);
|
||||
ClipRect.iTop = (WIS_Y-1);
|
||||
ClipRect.iBottom = (WIS_Y-1) + STAT_HEI;
|
||||
ClipRect.iLeft = WIS_X;
|
||||
ClipRect.iRight = WIS_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// MRK
|
||||
if (gMercProfiles[ pSoldier->ubProfile ].sMarksmanshipGain)
|
||||
{
|
||||
ubBarWidth = (STAT_WID * (gMercProfiles[ pSoldier->ubProfile ].sMarksmanshipGain+1)) / SubpointsPerPoint(MARKAMT,0);
|
||||
ClipRect.iTop = (MRK_Y-1);
|
||||
ClipRect.iBottom = (MRK_Y-1) + STAT_HEI;
|
||||
ClipRect.iLeft = MRK_X;
|
||||
ClipRect.iRight = MRK_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// LDR
|
||||
if (gMercProfiles[ pSoldier->ubProfile ].sLeadershipGain)
|
||||
{
|
||||
ubBarWidth = (STAT_WID * (gMercProfiles[ pSoldier->ubProfile ].sLeadershipGain+1)) / SubpointsPerPoint(LDRAMT,0);
|
||||
ClipRect.iTop = (LDR_Y-1);
|
||||
ClipRect.iBottom = (LDR_Y-1) + STAT_HEI;
|
||||
ClipRect.iLeft = LDR_X;
|
||||
ClipRect.iRight = LDR_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// MECH
|
||||
if (gMercProfiles[ pSoldier->ubProfile ].sMechanicGain)
|
||||
{
|
||||
ubBarWidth = (STAT_WID * (gMercProfiles[ pSoldier->ubProfile ].sMechanicGain+1)) / SubpointsPerPoint(MECHANAMT,0);
|
||||
ClipRect.iTop = (MEC_Y-1);
|
||||
ClipRect.iBottom = (MEC_Y-1) + STAT_HEI;
|
||||
ClipRect.iLeft = MEC_X;
|
||||
ClipRect.iRight = MEC_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// EXPLO
|
||||
if (gMercProfiles[ pSoldier->ubProfile ].sExplosivesGain)
|
||||
{
|
||||
ubBarWidth = (STAT_WID * (gMercProfiles[ pSoldier->ubProfile ].sExplosivesGain+1)) / SubpointsPerPoint(EXPLODEAMT,0);
|
||||
ClipRect.iTop = (EXP_Y-1);
|
||||
ClipRect.iBottom = (EXP_Y-1) + STAT_HEI;
|
||||
ClipRect.iLeft = EXP_X;
|
||||
ClipRect.iRight = EXP_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// MED
|
||||
if (gMercProfiles[ pSoldier->ubProfile ].sMedicalGain)
|
||||
{
|
||||
ubBarWidth = (STAT_WID * (gMercProfiles[ pSoldier->ubProfile ].sMedicalGain+1)) / SubpointsPerPoint(MEDICALAMT,0);
|
||||
ClipRect.iTop = (MED_Y-1);
|
||||
ClipRect.iBottom = (MED_Y-1) + STAT_HEI;
|
||||
ClipRect.iLeft = MED_X;
|
||||
ClipRect.iRight = MED_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
// EXPLEVEL
|
||||
if (gMercProfiles[ pSoldier->ubProfile ].sExpLevelGain)
|
||||
{
|
||||
ubBarWidth = (STAT_WID * (gMercProfiles[ pSoldier->ubProfile ].sExpLevelGain+1)) / SubpointsPerPoint(EXPERAMT, pSoldier->stats.bExpLevel);
|
||||
ClipRect.iTop = (LVL_Y-1);
|
||||
ClipRect.iBottom = (LVL_Y-1) + STAT_HEI;
|
||||
ClipRect.iLeft = LVL_X;
|
||||
ClipRect.iRight = LVL_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
}
|
||||
|
||||
UnLockVideoSurface( guiSAVEBUFFER );
|
||||
}
|
||||
|
||||
|
||||
// draw character info and face
|
||||
DrawCharacterInfo( bSelectedInfoChar );
|
||||
|
||||
@@ -4428,12 +4576,16 @@ UINT32 MapScreenHandle(void)
|
||||
|
||||
InitPreviousPaths();
|
||||
|
||||
// HEADROCK HAM 3.6: Init coordinates for new variable-sized message window
|
||||
InitMapScreenInterfaceBottomCoords();
|
||||
|
||||
// if arrival sector is invalid, reset to A9
|
||||
if ( ( gsMercArriveSectorX < 1 ) || ( gsMercArriveSectorY < 1 ) ||
|
||||
( gsMercArriveSectorX > 16 ) || ( gsMercArriveSectorY > 16 ) )
|
||||
{
|
||||
gsMercArriveSectorX = 9;
|
||||
gsMercArriveSectorY = 1;
|
||||
// HEADROCK HAM 3.5: Externalized coordinates
|
||||
gsMercArriveSectorX = gGameExternalOptions.ubDefaultArrivalSectorX;
|
||||
gsMercArriveSectorY = gGameExternalOptions.ubDefaultArrivalSectorY;
|
||||
}
|
||||
|
||||
gfInConfirmMapMoveMode = FALSE;
|
||||
@@ -4702,7 +4854,8 @@ UINT32 MapScreenHandle(void)
|
||||
if( AnyMercsHired( ) == FALSE )
|
||||
{
|
||||
// select starting sector (A9 - Omerta)
|
||||
ChangeSelectedMapSector( startingX, startingY, startingZ );
|
||||
// HEADROCK HAM 3.5: Externalized!
|
||||
ChangeSelectedMapSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ );
|
||||
}
|
||||
else if( ( gWorldSectorX > 0 ) && ( gWorldSectorY > 0 ) && ( gbWorldSectorZ != -1 ) )
|
||||
{
|
||||
@@ -4714,7 +4867,8 @@ UINT32 MapScreenHandle(void)
|
||||
// only select A9 - Omerta IF there is no current selection, otherwise leave it as is
|
||||
if ( ( sSelMapX == 0 ) || ( sSelMapY == 0 ) || ( iCurrentMapSectorZ == -1 ) )
|
||||
{
|
||||
ChangeSelectedMapSector( startingX, startingY, startingZ );
|
||||
// HEADROCK HAM 3.5: Externalized!
|
||||
ChangeSelectedMapSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5261,7 +5415,8 @@ UINT32 MapScreenHandle(void)
|
||||
|
||||
|
||||
// handle display of inventory pop up
|
||||
HandleDisplayOfItemPopUpForSector( startingX, startingY, startingZ );
|
||||
// HEADROCK HAM 3.5: Externalize!
|
||||
HandleDisplayOfItemPopUpForSector( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY, startingZ );
|
||||
|
||||
// Display Framerate
|
||||
DisplayFrameRate( );
|
||||
@@ -5311,7 +5466,9 @@ UINT32 MapScreenHandle(void)
|
||||
|
||||
|
||||
|
||||
|
||||
fCharacterInfoPanelDirty=TRUE;
|
||||
fMapPanelDirty = TRUE;
|
||||
fMapScreenBottomDirty = TRUE;
|
||||
fTeamPanelDirty = TRUE;
|
||||
fEndShowInventoryFlag = FALSE;
|
||||
}
|
||||
@@ -5702,6 +5859,8 @@ void DrawAssignment(INT16 sCharNumber, INT16 sRowIndex, INT32 iFont)
|
||||
FindFontCenterCoordinates((short)ASSIGN_X + 1, (short)(usVehicleY+(sRowIndex*Y_SIZE)), (short)ASSIGN_WIDTH, (short)Y_SIZE, sString, (long)iFont, &usX, &usY);
|
||||
}
|
||||
|
||||
SOLDIERTYPE *pSoldier = MercPtrs[ gCharactersList[ sCharNumber ].usSolID ];
|
||||
|
||||
if( fFlashAssignDone == TRUE )
|
||||
{
|
||||
if( Menptr[gCharactersList[sCharNumber].usSolID].flags.fDoneAssignmentAndNothingToDoFlag )
|
||||
@@ -5710,6 +5869,97 @@ void DrawAssignment(INT16 sCharNumber, INT16 sRowIndex, INT32 iFont)
|
||||
}
|
||||
}
|
||||
|
||||
if ( gGameSettings.fOptions[TOPTION_STAT_PROGRESS_BARS] &&
|
||||
(pSoldier->bAssignment >= TRAIN_SELF ||
|
||||
pSoldier->bAssignment <= TRAIN_BY_OTHER ) &&
|
||||
pSoldier->bAssignment != TRAIN_TEAMMATE )
|
||||
{
|
||||
// HEADROCK HAM 3.6: Draw militia training progress bar
|
||||
UINT32 uiDestBuffer;
|
||||
UINT8 *pDestBuf;
|
||||
UINT32 uiDestPitchBYTES = 0;
|
||||
SGPRect ClipRect;
|
||||
UINT8 ubBarWidth;
|
||||
UINT16 usColor = Get16BPPColor( FROMRGB( gGameExternalOptions.ubStatProgressBarsRed, gGameExternalOptions.ubStatProgressBarsGreen, gGameExternalOptions.ubStatProgressBarsBlue ) );
|
||||
|
||||
if( ( fShowAssignmentMenu == TRUE ) && ( fTeamPanelDirty == FALSE ) )
|
||||
{
|
||||
uiDestBuffer = FRAME_BUFFER;
|
||||
}
|
||||
else
|
||||
{
|
||||
uiDestBuffer = guiSAVEBUFFER;
|
||||
}
|
||||
pDestBuf = LockVideoSurface( uiDestBuffer, &uiDestPitchBYTES );
|
||||
|
||||
UINT8 ubProgress;
|
||||
UINT16 usMaxProgress;
|
||||
UINT8 sMapX = (UINT8)pSoldier->sSectorX;
|
||||
UINT8 sMapY = (UINT8)pSoldier->sSectorY;
|
||||
if ( pSoldier->bAssignment == TRAIN_TOWN )
|
||||
{
|
||||
ubProgress = SectorInfo[SECTOR(sMapX, sMapY)].ubMilitiaTrainingPercentDone;
|
||||
usMaxProgress = 100;
|
||||
}
|
||||
else if ( pSoldier->bAssignment == TRAIN_MOBILE )
|
||||
{
|
||||
ubProgress = SectorInfo[SECTOR(sMapX, sMapY)].ubMobileMilitiaTrainingPercentDone;
|
||||
usMaxProgress = 100;
|
||||
}
|
||||
else if ( pSoldier->bAssignment == TRAIN_SELF ||
|
||||
pSoldier->bAssignment == TRAIN_BY_OTHER )
|
||||
{
|
||||
switch (pSoldier->bTrainStat)
|
||||
{
|
||||
case STRENGTH:
|
||||
ubProgress = gMercProfiles[ pSoldier->ubProfile ].sStrengthGain+1;
|
||||
usMaxProgress = gGameExternalOptions.usStrengthSubpointsToImprove;
|
||||
break;
|
||||
case AGILITY:
|
||||
ubProgress = gMercProfiles[ pSoldier->ubProfile ].sAgilityGain+1;
|
||||
usMaxProgress = gGameExternalOptions.usAgilitySubpointsToImprove;
|
||||
break;
|
||||
case DEXTERITY:
|
||||
ubProgress = gMercProfiles[ pSoldier->ubProfile ].sDexterityGain+1;
|
||||
usMaxProgress = gGameExternalOptions.usDexteritySubpointsToImprove;
|
||||
break;
|
||||
case HEALTH:
|
||||
ubProgress = gMercProfiles[ pSoldier->ubProfile ].sLifeGain+1;
|
||||
usMaxProgress = gGameExternalOptions.usHealthSubpointsToImprove;
|
||||
break;
|
||||
case MARKSMANSHIP:
|
||||
ubProgress = gMercProfiles[ pSoldier->ubProfile ].sMarksmanshipGain+1;
|
||||
usMaxProgress = gGameExternalOptions.usMarksmanshipSubpointsToImprove;
|
||||
break;
|
||||
case LEADERSHIP:
|
||||
ubProgress = gMercProfiles[ pSoldier->ubProfile ].sLeadershipGain+1;
|
||||
usMaxProgress = gGameExternalOptions.usLeadershipSubpointsToImprove;
|
||||
break;
|
||||
case MECHANICAL:
|
||||
ubProgress = gMercProfiles[ pSoldier->ubProfile ].sMechanicGain+1;
|
||||
usMaxProgress = gGameExternalOptions.usMechanicalSubpointsToImprove;
|
||||
break;
|
||||
case MEDICAL:
|
||||
ubProgress = gMercProfiles[ pSoldier->ubProfile ].sMedicalGain+1;
|
||||
usMaxProgress = gGameExternalOptions.usMedicalSubpointsToImprove;
|
||||
break;
|
||||
case EXPLOSIVE_ASSIGN:
|
||||
ubProgress = gMercProfiles[ pSoldier->ubProfile ].sExplosivesGain+1;
|
||||
usMaxProgress = gGameExternalOptions.usExplosivesSubpointsToImprove;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ubBarWidth = (ASSIGN_WIDTH * ubProgress) / usMaxProgress;
|
||||
ClipRect.iTop = (usY+(Y_OFFSET*sRowIndex+1))-1;
|
||||
ClipRect.iBottom = ClipRect.iTop + Y_SIZE;
|
||||
ClipRect.iLeft = ASSIGN_X+2;
|
||||
ClipRect.iRight = ASSIGN_X + ubBarWidth;
|
||||
Blt16BPPBufferHatchRectWithColor( (UINT16*)pDestBuf, uiDestPitchBYTES, &ClipRect, usColor );
|
||||
|
||||
UnLockVideoSurface( uiDestBuffer );
|
||||
}
|
||||
|
||||
//RestoreExternBackgroundRect(ASSIGN_X-2, ((UINT16)(usY+(Y_OFFSET*sRowIndex+1))), ASSIGN_WIDTH+2, Y_SIZE);
|
||||
DrawString(sString, (UINT16)usX, ((UINT16)(usY+(Y_OFFSET*sRowIndex+1))), iFont);
|
||||
}
|
||||
@@ -6438,6 +6688,12 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent )
|
||||
fShowAttributeMenu = FALSE;
|
||||
fMapPanelDirty = TRUE;
|
||||
}
|
||||
// stop showing current assignment box
|
||||
if( fShowFacilityAssignmentMenu == TRUE )
|
||||
{
|
||||
fShowFacilityAssignmentMenu = FALSE;
|
||||
fMapPanelDirty = TRUE;
|
||||
}
|
||||
else if( fShowTrainingMenu == TRUE )
|
||||
{
|
||||
fShowTrainingMenu = FALSE;
|
||||
@@ -6450,6 +6706,11 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent )
|
||||
{
|
||||
fShowRepairMenu = FALSE;
|
||||
}
|
||||
// HEADROCK HAM 3.6: Facility Menu
|
||||
else if( fShowFacilityMenu == TRUE )
|
||||
{
|
||||
fShowFacilityMenu = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fShowAssignmentMenu = FALSE;
|
||||
@@ -10695,6 +10956,12 @@ void RenderMapRegionBackground( void )
|
||||
ForceUpDateOfBox( ghAttributeBox );
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: Force re-render due to Facility box
|
||||
if ( ghFacilityAssignmentBox != 1 )
|
||||
{
|
||||
ForceUpDateOfBox( ghFacilityAssignmentBox );
|
||||
}
|
||||
|
||||
if ( ghTownMineBox != - 1 )
|
||||
{
|
||||
// force update of town mine info boxes
|
||||
@@ -14970,13 +15237,18 @@ void HandlePostAutoresolveMessages()
|
||||
|
||||
void GetMapscreenMercAssignmentString( SOLDIERTYPE *pSoldier, CHAR16 sString[] )
|
||||
{
|
||||
if( pSoldier->bAssignment != VEHICLE )
|
||||
if ( pSoldier->bAssignment == VEHICLE )
|
||||
{
|
||||
wcscpy(sString, pAssignmentStrings[ pSoldier->bAssignment ] );
|
||||
wcscpy( sString, pShortVehicleStrings[ pVehicleList[ pSoldier->iVehicleId ].ubVehicleType ] );
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscpy( sString, pShortVehicleStrings[ pVehicleList[ pSoldier->iVehicleId ].ubVehicleType ] );
|
||||
wcscpy(sString, pAssignmentStrings[ pSoldier->bAssignment ] );
|
||||
}
|
||||
// If soldier is working at a facility, add an asterisk.
|
||||
if (pSoldier->sFacilityTypeOperated != -1)
|
||||
{
|
||||
wcscat(sString, L"*");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15433,6 +15705,7 @@ void RequestToggleMercInventoryPanel( void )
|
||||
else
|
||||
{
|
||||
// Headrock. New line forces InvBottom rerender when the inventory is opened and closed.
|
||||
fEndShowInventoryFlag = TRUE;
|
||||
RenderMapScreenInterfaceBottom ( TRUE );
|
||||
SetRegionFastHelpText( &gCharInfoHandRegion, pMiscMapScreenMouseRegionHelpText[ 0 ] );
|
||||
}
|
||||
@@ -15549,3 +15822,48 @@ void MapscreenMarkButtonsDirty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM 3.6: Get a total of all merc salaries. Used for the new Daily Expenses display.
|
||||
INT32 GetTotalContractExpenses ( void )
|
||||
{
|
||||
if (gGameExternalOptions.ubIncludeContractsInExpenses == 0)
|
||||
{
|
||||
// Contract costs are excluded.
|
||||
return (0);
|
||||
}
|
||||
|
||||
UINT8 ubCounter = 0;
|
||||
SOLDIERTYPE *pSoldier;
|
||||
INT32 iTotalCost = 0;
|
||||
|
||||
while(gCharactersList[ubCounter].fValid)
|
||||
{
|
||||
pSoldier = MercPtrs[ gCharactersList[ ubCounter ].usSolID ];
|
||||
// salary
|
||||
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
|
||||
{
|
||||
if (gGameExternalOptions.ubIncludeContractsInExpenses == 2)
|
||||
{
|
||||
// daily rate
|
||||
if( pSoldier->bTypeOfLastContract == CONTRACT_EXTEND_2_WEEK )
|
||||
{
|
||||
iTotalCost += ( gMercProfiles[ pSoldier->ubProfile ].uiBiWeeklySalary / 14 );
|
||||
}
|
||||
if( pSoldier->bTypeOfLastContract == CONTRACT_EXTEND_1_WEEK )
|
||||
{
|
||||
iTotalCost += ( gMercProfiles[ pSoldier->ubProfile ].uiWeeklySalary / 7 );
|
||||
}
|
||||
else
|
||||
{
|
||||
iTotalCost += gMercProfiles[ pSoldier->ubProfile ].sSalary;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iTotalCost += gMercProfiles[ pSoldier->ubProfile ].sSalary;
|
||||
}
|
||||
ubCounter++;
|
||||
}
|
||||
return (iTotalCost);
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
#define MAP_WORLD_Y 18
|
||||
|
||||
#define MAX_TOWN_NAME_LENGHT 32
|
||||
#define MAX_SECTOR_NAME_LENGTH 128
|
||||
|
||||
#define MAX_TOWNS 50 //13 //50
|
||||
#define MAX_TOWN_SECTORS 260 //40 //260
|
||||
@@ -93,4 +94,7 @@ BOOLEAN InitializeInvPanelCoordsOld( );
|
||||
BOOLEAN InitializeInvPanelCoordsNew( );
|
||||
BOOLEAN InitializeInvPanelCoordsVehicle( );
|
||||
|
||||
// HEADROCK HAM 3.6: Calculate daily cost for all mercs who have one.
|
||||
INT32 GetTotalContractExpenses ( void );
|
||||
|
||||
#endif
|
||||
+194
-91
@@ -296,6 +296,9 @@ STR8 pHortStrings[]={
|
||||
"17",
|
||||
};
|
||||
|
||||
// HEADROCK HAM 3.6: Array to hold user-defined sector names
|
||||
CHAR16 gzSectorNames[256][4][MAX_SECTOR_NAME_LENGTH];
|
||||
|
||||
BOOLEAN ReadInStrategicMapSectorTownNames(STR fileName, BOOLEAN localizedVersion);
|
||||
|
||||
void DoneFadeOutAdjacentSector( void );
|
||||
@@ -1616,8 +1619,9 @@ void InitializeSAMSites( void )
|
||||
{
|
||||
UINT32 cnt;
|
||||
// move the landing zone over to Omerta
|
||||
gsMercArriveSectorX = 9;
|
||||
gsMercArriveSectorY = 1;
|
||||
// HEADROCK HAM 3.5: Externalized coordinates
|
||||
gsMercArriveSectorX = gGameExternalOptions.ubDefaultArrivalSectorX;
|
||||
gsMercArriveSectorY = gGameExternalOptions.ubDefaultArrivalSectorY;
|
||||
|
||||
// all SAM sites start game in perfect working condition
|
||||
for ( cnt = 0; cnt < NUMBER_OF_SAMS; cnt++ )
|
||||
@@ -3009,109 +3013,179 @@ void GetSectorIDString( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ , STR16 zS
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
bTownNameID = StrategicMap[ CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].bNameId;
|
||||
ubSectorID = (UINT8)SECTOR( sSectorX, sSectorY );
|
||||
AssertGE(ubSectorID, 0);
|
||||
AssertLT(ubSectorID,256);
|
||||
pSector = &SectorInfo[ ubSectorID ];
|
||||
ubLandType = pSector->ubTraversability[ 4 ];
|
||||
swprintf( zString, L"%c%d: ", 'A' + sSectorY - 1, sSectorX );
|
||||
|
||||
if ( bTownNameID == BLANK_SECTOR )
|
||||
////////////////////////////////////
|
||||
// Read and verify XML sector names
|
||||
BOOLEAN fSectorHasXMLNames = TRUE;
|
||||
CHAR16 zUnexplored[MAX_SECTOR_NAME_LENGTH];
|
||||
CHAR16 zDetailedUnexplored[MAX_SECTOR_NAME_LENGTH];
|
||||
CHAR16 zExplored[MAX_SECTOR_NAME_LENGTH];
|
||||
CHAR16 zDetailedExplored[MAX_SECTOR_NAME_LENGTH];
|
||||
|
||||
wcscpy( zUnexplored, gzSectorNames[ ubSectorID ][0] );
|
||||
wcscpy( zDetailedUnexplored, gzSectorNames[ ubSectorID ][1] );
|
||||
wcscpy( zExplored, gzSectorNames[ ubSectorID ][2] );
|
||||
wcscpy( zDetailedExplored, gzSectorNames[ ubSectorID ][3] );
|
||||
|
||||
if (zUnexplored[0] == 0 || zDetailedUnexplored[0] == 0 || zExplored[0] == 0 || zDetailedExplored[0] == 0)
|
||||
{
|
||||
// OK, build string id like J11
|
||||
// are we dealing with the unfound towns?
|
||||
switch( ubSectorID )
|
||||
fSectorHasXMLNames = FALSE;
|
||||
}
|
||||
|
||||
if (fSectorHasXMLNames)
|
||||
{
|
||||
// HEADROCK HAM 3.6: The program can now read custom names from XML for all above-ground sectors.
|
||||
// In the event that a specific name or set of names is missing, the program generates a default
|
||||
// name as it always has.
|
||||
// I've also updated the SAM Site sectors to rely on SamSite.XML data.
|
||||
|
||||
BOOLEAN fVisited = (SectorInfo[ ubSectorID ].uiFlags & SF_ALREADY_VISITED);
|
||||
BOOLEAN fSAMSiteKnown = FALSE;
|
||||
|
||||
// Test for known SAM Site at this location
|
||||
for (UINT16 x=0; x < MAX_NUMBER_OF_SAMS; x++)
|
||||
{
|
||||
case SEC_D2: //Chitzena SAM
|
||||
if( !fSamSiteFound[ SAM_SITE_ONE ] )
|
||||
wcscat( zString, pLandTypeStrings[ TROPICS ] );
|
||||
else if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ TROPICS_SAM_SITE ] );
|
||||
else
|
||||
wcscat( zString, pLandTypeStrings[ SAM_SITE ] );
|
||||
break;
|
||||
case SEC_D15: //Drassen SAM
|
||||
if( !fSamSiteFound[ SAM_SITE_TWO ] )
|
||||
wcscat( zString, pLandTypeStrings[ SPARSE ] );
|
||||
else if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ SPARSE_SAM_SITE ] );
|
||||
else
|
||||
wcscat( zString, pLandTypeStrings[ SAM_SITE ] );
|
||||
break;
|
||||
case SEC_I8: //Cambria SAM
|
||||
if( !fSamSiteFound[ SAM_SITE_THREE ] )
|
||||
wcscat( zString, pLandTypeStrings[ SAND ] );
|
||||
else if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ SAND_SAM_SITE ] );
|
||||
else
|
||||
wcscat( zString, pLandTypeStrings[ SAM_SITE ] );
|
||||
break;
|
||||
default:
|
||||
wcscat( zString, pLandTypeStrings[ ubLandType ] );
|
||||
break;
|
||||
if ( pSamList[x] == ubSectorID )
|
||||
{
|
||||
if ( fSamSiteFound[ x ] )
|
||||
{
|
||||
fSAMSiteKnown = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fVisited || fSAMSiteKnown)
|
||||
{
|
||||
if (fDetailed)
|
||||
{
|
||||
wcscat( zString, zDetailedExplored );
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscat( zString, zExplored);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fDetailed)
|
||||
{
|
||||
wcscat( zString, zDetailedUnexplored);
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscat( zString, zUnexplored );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( ubSectorID )
|
||||
// Default JA2 Name selection
|
||||
if ( bTownNameID == BLANK_SECTOR )
|
||||
{
|
||||
case SEC_B13:
|
||||
if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ DRASSEN_AIRPORT_SITE ] );
|
||||
else
|
||||
wcscat( zString, pTownNames[ DRASSEN ] );
|
||||
break;
|
||||
case SEC_F8:
|
||||
if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ CAMBRIA_HOSPITAL_SITE ] );
|
||||
else
|
||||
wcscat( zString, pTownNames[ CAMBRIA ] );
|
||||
break;
|
||||
case SEC_J9: //Tixa
|
||||
if( !fFoundTixa )
|
||||
wcscat( zString, pLandTypeStrings[ SAND ] );
|
||||
else
|
||||
wcscat( zString, pTownNames[ TIXA ] );
|
||||
break;
|
||||
case SEC_K4: //Orta
|
||||
if( !fFoundOrta )
|
||||
wcscat( zString, pLandTypeStrings[ SWAMP ] );
|
||||
else
|
||||
wcscat( zString, pTownNames[ ORTA ] );
|
||||
break;
|
||||
case SEC_N3:
|
||||
if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ MEDUNA_AIRPORT_SITE ] );
|
||||
else
|
||||
wcscat( zString, pTownNames[ MEDUNA ] );
|
||||
break;
|
||||
default:
|
||||
if( ubSectorID == SEC_N4 && fSamSiteFound[ SAM_SITE_FOUR ] )
|
||||
{ //Meduna's SAM site
|
||||
if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ MEDUNA_SAM_SITE ] );
|
||||
// OK, build string id like J11
|
||||
// are we dealing with the unfound towns?
|
||||
switch( ubSectorID )
|
||||
{
|
||||
case SEC_D2: //Chitzena SAM
|
||||
if( !fSamSiteFound[ SAM_SITE_ONE ] )
|
||||
wcscat( zString, pLandTypeStrings[ TROPICS ] );
|
||||
else if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ TROPICS_SAM_SITE ] );
|
||||
else
|
||||
wcscat( zString, pLandTypeStrings[ SAM_SITE ] );
|
||||
}
|
||||
else
|
||||
{ //All other towns that are known since beginning of the game.
|
||||
wcscat( zString, pTownNames[ bTownNameID ] );
|
||||
break;
|
||||
case SEC_D15: //Drassen SAM
|
||||
if( !fSamSiteFound[ SAM_SITE_TWO ] )
|
||||
wcscat( zString, pLandTypeStrings[ SPARSE ] );
|
||||
else if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ SPARSE_SAM_SITE ] );
|
||||
else
|
||||
wcscat( zString, pLandTypeStrings[ SAM_SITE ] );
|
||||
break;
|
||||
case SEC_I8: //Cambria SAM
|
||||
if( !fSamSiteFound[ SAM_SITE_THREE ] )
|
||||
wcscat( zString, pLandTypeStrings[ SAND ] );
|
||||
else if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ SAND_SAM_SITE ] );
|
||||
else
|
||||
wcscat( zString, pLandTypeStrings[ SAM_SITE ] );
|
||||
break;
|
||||
default:
|
||||
wcscat( zString, pLandTypeStrings[ ubLandType ] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( ubSectorID )
|
||||
{
|
||||
case SEC_B13:
|
||||
if( fDetailed )
|
||||
{
|
||||
switch( ubSectorID )
|
||||
{ //Append the word, "mine" for town sectors containing a mine.
|
||||
case SEC_B2:
|
||||
case SEC_D4:
|
||||
case SEC_D13:
|
||||
case SEC_H3:
|
||||
case SEC_H8:
|
||||
case SEC_I14:
|
||||
wcscat( zString, L" " ); //space
|
||||
wcscat( zString, pwMineStrings[ 0 ] ); //then "Mine"
|
||||
break;
|
||||
wcscat( zString, pLandTypeStrings[ DRASSEN_AIRPORT_SITE ] );
|
||||
else
|
||||
wcscat( zString, pTownNames[ DRASSEN ] );
|
||||
break;
|
||||
case SEC_F8:
|
||||
if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ CAMBRIA_HOSPITAL_SITE ] );
|
||||
else
|
||||
wcscat( zString, pTownNames[ CAMBRIA ] );
|
||||
break;
|
||||
case SEC_J9: //Tixa
|
||||
if( !fFoundTixa )
|
||||
wcscat( zString, pLandTypeStrings[ SAND ] );
|
||||
else
|
||||
wcscat( zString, pTownNames[ TIXA ] );
|
||||
break;
|
||||
case SEC_K4: //Orta
|
||||
if( !fFoundOrta )
|
||||
wcscat( zString, pLandTypeStrings[ SWAMP ] );
|
||||
else
|
||||
wcscat( zString, pTownNames[ ORTA ] );
|
||||
break;
|
||||
case SEC_N3:
|
||||
if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ MEDUNA_AIRPORT_SITE ] );
|
||||
else
|
||||
wcscat( zString, pTownNames[ MEDUNA ] );
|
||||
break;
|
||||
default:
|
||||
if( ubSectorID == SEC_N4 && fSamSiteFound[ SAM_SITE_FOUR ] )
|
||||
{ //Meduna's SAM site
|
||||
if( fDetailed )
|
||||
wcscat( zString, pLandTypeStrings[ MEDUNA_SAM_SITE ] );
|
||||
else
|
||||
wcscat( zString, pLandTypeStrings[ SAM_SITE ] );
|
||||
}
|
||||
else
|
||||
{ //All other towns that are known since beginning of the game.
|
||||
wcscat( zString, pTownNames[ bTownNameID ] );
|
||||
if( fDetailed )
|
||||
{
|
||||
switch( ubSectorID )
|
||||
{ //Append the word, "mine" for town sectors containing a mine.
|
||||
case SEC_B2:
|
||||
case SEC_D4:
|
||||
case SEC_D13:
|
||||
case SEC_H3:
|
||||
case SEC_H8:
|
||||
case SEC_I14:
|
||||
wcscat( zString, L" " ); //space
|
||||
wcscat( zString, pwMineStrings[ 0 ] ); //then "Mine"
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4605,8 +4679,26 @@ void UpdateAirspaceControl( void )
|
||||
GetSectorIDString( gsMercArriveSectorX, gsMercArriveSectorY, 0, sMsgSubString1, FALSE );
|
||||
|
||||
// move the landing zone over to Omerta
|
||||
gsMercArriveSectorX = 9;
|
||||
gsMercArriveSectorY = 1;
|
||||
// HEADROCK HAM 3.5: Externalized coordinates
|
||||
if ( StrategicMap[ CALCULATE_STRATEGIC_INDEX( gGameExternalOptions.ubDefaultArrivalSectorX, gGameExternalOptions.ubDefaultArrivalSectorY ) ].fEnemyAirControlled == FALSE )
|
||||
{
|
||||
gsMercArriveSectorX = gGameExternalOptions.ubDefaultArrivalSectorX;
|
||||
gsMercArriveSectorY = gGameExternalOptions.ubDefaultArrivalSectorY;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (UINT8 ubSectorX = 1; ubSectorX <= 16; ubSectorX++)
|
||||
{
|
||||
for (UINT8 ubSectorY = 1; ubSectorY <=16; ubSectorY++)
|
||||
{
|
||||
if ( StrategicMap[ CALCULATE_STRATEGIC_INDEX( ubSectorX, ubSectorY ) ].fEnemyAirControlled == FALSE )
|
||||
{
|
||||
gsMercArriveSectorX = ubSectorX;
|
||||
gsMercArriveSectorY = ubSectorY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get the name of the new sector
|
||||
GetSectorIDString( gsMercArriveSectorX, gsMercArriveSectorY, 0, sMsgSubString2, FALSE );
|
||||
@@ -4615,7 +4707,11 @@ void UpdateAirspaceControl( void )
|
||||
swprintf( sMsgString, pBullseyeStrings[ 4 ], sMsgSubString1, sMsgSubString2 );
|
||||
|
||||
// confirm the change with overlay message
|
||||
DoScreenIndependantMessageBox( sMsgString, MSG_BOX_FLAG_OK, NULL );
|
||||
// HEADROCK HAM 3.5: If we do this during SaveLoad, the message box prevents loading the game at all!
|
||||
if (guiCurrentScreen != SAVE_LOAD_SCREEN)
|
||||
{
|
||||
DoScreenIndependantMessageBox( sMsgString, MSG_BOX_FLAG_OK, NULL );
|
||||
}
|
||||
|
||||
// update position of bullseye
|
||||
fMapPanelDirty = TRUE;
|
||||
@@ -4627,6 +4723,7 @@ void UpdateAirspaceControl( void )
|
||||
|
||||
// ARM: airspace control now affects refueling site availability, so update that too with every change!
|
||||
UpdateRefuelSiteAvailability( );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -5524,6 +5621,12 @@ void HandleSlayDailyEvent( void )
|
||||
|
||||
BOOLEAN IsSectorDesert( INT16 sSectorX, INT16 sSectorY )
|
||||
{
|
||||
// HEADROCK HAM 3.5: Fix for assertion errors associated with rain checks.
|
||||
if (sSectorX <= 0 || sSectorY <=0 || sSectorX > 16 || sSectorY > 16)
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if ( SectorInfo[ SECTOR(sSectorX, sSectorY) ].ubTraversability[ THROUGH_STRATEGIC_MOVE ] == SAND )
|
||||
{
|
||||
// desert
|
||||
@@ -5669,7 +5772,7 @@ BOOLEAN CheckAndHandleUnloadingOfCurrentWorld()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( gTacticalStatus.fDidGameJustStart && gWorldSectorX == 9 && gWorldSectorY == 1 && !gbWorldSectorZ )
|
||||
if( gTacticalStatus.fDidGameJustStart && gWorldSectorX == gGameExternalOptions.ubDefaultArrivalSectorX && gWorldSectorY == gGameExternalOptions.ubDefaultArrivalSectorY && !gbWorldSectorZ )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
+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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user