mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
Added Headrock's HAM 2.8
git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@2650 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -812,6 +812,144 @@ void LoadGameExternalOptions()
|
||||
|
||||
// WANNE: Always use prof.dat??
|
||||
gGameExternalOptions.fAlwaysUseProfDat = iniReader.ReadBoolean("JA2 Gameplay Settings", "ALWAYS_USE_PROF_DAT", FALSE);
|
||||
|
||||
|
||||
// HEADROCK HAM B1: Set % of mine income, where 100% = normal
|
||||
gGameExternalOptions.iMineIncomePercentage = iniReader.ReadInteger("JA2 HAM Settings","MINE_INCOME_PERCENTAGE",0);
|
||||
// HEADROCK HAM B2.4: Set a threshold at 1% - otherwise game crashes on asserting mine income.
|
||||
// Can anyone have a look at circumventing the income check? I don't want to cause any damage...
|
||||
gGameExternalOptions.iMineIncomePercentage = __max(gGameExternalOptions.iMineIncomePercentage, 1);
|
||||
|
||||
// HEADROCK HAM B1: Set minimum and maximum CTH
|
||||
gGameExternalOptions.iMaximumCTH = iniReader.ReadInteger("JA2 HAM Settings","MAXIMUM_POSSIBLE_CTH",0);
|
||||
|
||||
gGameExternalOptions.iMinimumCTH = iniReader.ReadInteger("JA2 HAM Settings","MINIMUM_POSSIBLE_CTH",0);
|
||||
|
||||
// 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",0);
|
||||
|
||||
// HEADROCK HAM B1: Allow restricted militia to move through visited sectors?
|
||||
gGameExternalOptions.bUnrestrictVisited = iniReader.ReadBoolean("JA2 HAM Settings","ALLOW_RESTRICTED_MILITIA_THROUGH_VISITED_SECTORS",0);
|
||||
|
||||
gGameExternalOptions.bDynamicRestrictRoaming = iniReader.ReadBoolean("JA2 HAM Settings","ALLOW_DYNAMIC_RESTRICTED_ROAMING",0);
|
||||
|
||||
// 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",0);
|
||||
|
||||
// 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",100);
|
||||
|
||||
// HEADROCK HAM B2: MAXIMUM number of APs that can be lost to suppression in a given turn (0=unlimited)
|
||||
gGameExternalOptions.iMaxSuppressionAPLossPerTurn = iniReader.ReadInteger("JA2 HAM Settings","MAX_SUPPRESSION_AP_LOSS_PER_TURN",8);
|
||||
|
||||
// HEADROCK HAM B2: MAXIMUM number of APs that can be lost to suppression in a given attack (0=unlimited)
|
||||
gGameExternalOptions.iMaxSuppressionAPLossPerAttack = iniReader.ReadInteger("JA2 HAM Settings","MAX_SUPPRESSION_AP_LOSS_PER_ATTACK",8);
|
||||
|
||||
// HEADROCK HAM B2: Rigid limit to which a soldier's APs can drop due to suppression fire. (0=unlimited)
|
||||
gGameExternalOptions.iMinAPLimitFromSuppression = iniReader.ReadInteger("JA2 HAM Settings","MIN_LIMIT_SUPPRESSION_AP_LOSS",0);
|
||||
|
||||
// HEADROCK HAM B2: Suppression Shock ON/OFF
|
||||
gGameExternalOptions.fSuppressionShock = iniReader.ReadBoolean("JA2 HAM Settings","SUPPRESSION_SHOCK",FALSE);
|
||||
|
||||
// HEADROCK HAM B2: Suppression Shock effectiveness (percentage, 100 = "normal", 0 = deactivated. Range 0-65535)
|
||||
gGameExternalOptions.iSuppressionShockEffectiveness = iniReader.ReadInteger("JA2 HAM Settings","SUPPRESSION_SHOCK_EFFECTIVENESS",100);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// HEADROCK HAM B2.4: How many APs must be lost due to suppression for every 1 point of morale lost?
|
||||
gGameExternalOptions.iAPLostPerMoraleDrop = iniReader.ReadInteger("JA2 HAM Settings","AP_LOST_PER_MORALE_DROP",2);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// HEADROCK HAM B2.6: Increased aiming costs?
|
||||
gGameExternalOptions.fIncreasedAimingCost = iniReader.ReadBoolean("JA2 HAM Settings","INCREASED_AIM_COST", FALSE);
|
||||
|
||||
// HEADROCK HAM B2.6: Dynamically determine Max-Aiming based also on weapon, bipod, etc?
|
||||
gGameExternalOptions.fDynamicAimingTime = iniReader.ReadBoolean("JA2 HAM Settings","DYNAMIC_AIM_LIMITS", FALSE);
|
||||
|
||||
// HEADROCK HAM B2.6: Controls how much effect target movement has on aiming
|
||||
//gGameExternalOptions.iMovementEffectOnAiming = iniReader.ReadFloat("JA2 HAM Settings","MOVEMENT_EFFECT_ON_AIMING", 1.5);
|
||||
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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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));
|
||||
|
||||
// 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);
|
||||
|
||||
// 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));
|
||||
|
||||
// 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", 100));
|
||||
|
||||
// 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", 100));
|
||||
gGameExternalOptions.usMaxTargetCoweringPenalty = __max(1,iniReader.ReadInteger("JA2 HAM Settings","MAX_TARGET_COWERING_PENALTY", 100));
|
||||
|
||||
// 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: 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
INT16 DynamicAdjustAPConstants(INT16 iniReadValue, INT16 iniDefaultValue, BOOLEAN reverse)
|
||||
|
||||
+135
-1
@@ -486,7 +486,141 @@ BOOLEAN gbBulletTracer;
|
||||
INT32 fEnhancedDescriptionBox;
|
||||
|
||||
// WANNE: Always use "prof.dat".
|
||||
BOOLEAN fAlwaysUseProfDat;
|
||||
BOOLEAN fAlwaysUseProfDat;
|
||||
|
||||
// HEADROCK HAM B1: Global modifier for mine income (0 is automatically turned to 1 to avoid divide-by-zero.)
|
||||
INT16 iMineIncomePercentage;
|
||||
|
||||
// HEADROCK HAM B1: Allows changing the maximum CTH possible, for any attack 0-100
|
||||
UINT8 iMaximumCTH;
|
||||
|
||||
// HEADROCK HAM B1: Allows changing the minimum CTH possible, for any attack 0-100
|
||||
UINT8 iMinimumCTH;
|
||||
|
||||
// HEADROCK HAM B1: Allows reducing the chance of scoring a hit fractionally, if CTH = Minimum CTH
|
||||
UINT8 iMinimumCTHDivisor;
|
||||
|
||||
// HEADROCK HAM B1: Allows Restricted Roaming Militia to move through previously visited sectors, even if restricted.
|
||||
BOOLEAN bUnrestrictVisited;
|
||||
|
||||
// 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;
|
||||
|
||||
// HEADROCK HAM B2.1: This controls how effective suppression is, by increasing the number of ubSuppressionPoints accumulated by combatants (percentage);
|
||||
INT16 iSuppressionEffectiveness;
|
||||
|
||||
// HEADROCK HAM B2: MAXIMUM number of APs that can be lost to suppression in a given turn (0=unlimited)
|
||||
UINT8 iMaxSuppressionAPLossPerTurn;
|
||||
|
||||
// HEADROCK HAM B2: MAXIMUM number of APs that can be lost to suppression in a given attack (0=unlimited)
|
||||
UINT8 iMaxSuppressionAPLossPerAttack;
|
||||
|
||||
// HEADROCK HAM B2: Rigid limit to which a soldier's APs can drop due to suppression fire. (0=unlimited)
|
||||
INT8 iMinAPLimitFromSuppression;
|
||||
|
||||
// HEADROCK HAM B2: Suppression Shock ON/OFF
|
||||
BOOLEAN fSuppressionShock;
|
||||
|
||||
// HEADROCK HAM B2: Suppression Shock effectiveness (percentage, 100 = "normal", 0 = deactivated. Range 0-65535)
|
||||
UINT16 iSuppressionShockEffectiveness;
|
||||
|
||||
// HEADROCK HAM B2.1: CTH penalty given by a "Cowering" target to any enemy shooter.
|
||||
INT8 iAimPenaltyPerTargetShock;
|
||||
|
||||
// HEADROCK HAM B2.3: It is now possible for "cowering" to increase a target's suppression.
|
||||
UINT16 iCowerEffectOnSuppression;
|
||||
|
||||
// HEADROCK HAM B2.4: How many APs must be lost due to suppression for every 1 point of morale lost?
|
||||
UINT8 iAPLostPerMoraleDrop;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// HEADROCK HAM B2.5: Realistic tracers - CTH increased by this amount whenever a tracer is fired. 0 = off.
|
||||
INT16 iCTHBumpPerTracer;
|
||||
|
||||
// HEADROCK HAM B2.6: Increased aiming costs?
|
||||
BOOLEAN fIncreasedAimingCost;
|
||||
|
||||
// HEADROCK HAM B2.6: Dynamically determine Max-Aiming based also on weapon, bipod, etc?
|
||||
BOOLEAN fDynamicAimingTime;
|
||||
|
||||
// HEADROCK HAM B2.6: Controls how much effect target movement has on aiming
|
||||
FLOAT iMovementEffectOnAiming;
|
||||
|
||||
// HEADROCK HAM B2.6: Autofire Bullets/5AP modifier
|
||||
INT16 iAutofireBulletsPer5APModifier;
|
||||
|
||||
// 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;
|
||||
|
||||
// HEADROCK HAM B2.6/2/1: Toggle new Burst/Auto CTH bars: 0=neither, 1=both, 2=Burst, 3=Auto
|
||||
UINT8 iNewCTHBars;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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;
|
||||
UINT8 ubCoweringPenaltyDivisorCrouchedTorso;
|
||||
UINT8 ubCoweringPenaltyDivisorCrouchedLegs;
|
||||
|
||||
// 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.
|
||||
UINT16 usMinRangeForFullCoweringPenalty;
|
||||
|
||||
// HEADROCK HAM B2.8: Absolute maximum CTH penalty from target/shooter cowering
|
||||
UINT16 usMaxShooterCoweringPenalty;
|
||||
UINT16 usMaxTargetCoweringPenalty;
|
||||
|
||||
// HEADROCK HAM B2.8: If this is turned on, Militia will drop their equipment similar to enemies, IF killed by non-player character.
|
||||
UINT8 ubMilitiaDropEquipment;
|
||||
|
||||
// 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.
|
||||
UINT8 ubSmartTrainingSleep;
|
||||
|
||||
// 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.
|
||||
UINT8 ubSmartTrainingWake;
|
||||
|
||||
// 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;
|
||||
|
||||
} GAME_EXTERNAL_OPTIONS;
|
||||
|
||||
|
||||
@@ -105,6 +105,8 @@
|
||||
#include "Assignments.h"
|
||||
#include "Interface Items.h"
|
||||
#include "Shopkeeper Interface.h"
|
||||
// HEADROCK HAM B1: Additional Include for HAM
|
||||
#include "MilitiaSquads.h"
|
||||
#endif
|
||||
|
||||
#include "BobbyR.h"
|
||||
@@ -4401,6 +4403,11 @@ BOOLEAN LoadSavedGame( int ubSavedGameID )
|
||||
|
||||
// fix squads
|
||||
CheckSquadMovementGroups();
|
||||
// HEADROCK HAM B1: Re-Adjust Dynamic Roaming Militia restrictions
|
||||
if (gGameExternalOptions.bDynamicRestrictRoaming)
|
||||
{
|
||||
AdjustRoamingRestrictions();
|
||||
}
|
||||
|
||||
//The above function LightSetBaseLevel adjusts ALL the level node light values including the merc node,
|
||||
//we must reset the values
|
||||
|
||||
+419
-24
@@ -105,10 +105,12 @@ enum {
|
||||
REPAIR_BIG_POCKETS,
|
||||
REPAIR_MED_POCKETS,
|
||||
REPAIR_SML_POCKETS,
|
||||
REPAIR_LBE_GEAR, // HEADROCK HAM B2.8: New pass type for fixing LBEs only
|
||||
NUM_REPAIR_PASS_TYPES,
|
||||
};
|
||||
|
||||
#define FINAL_REPAIR_PASS REPAIR_SML_POCKETS
|
||||
// HEADROCK HAM B2.8: Changed LBEs to be the final pass
|
||||
#define FINAL_REPAIR_PASS REPAIR_LBE_GEAR
|
||||
|
||||
|
||||
/* CHRISL: bSlot[xx] array declaration needs to reflect largest number of inventory locations. New inventory
|
||||
@@ -128,6 +130,7 @@ REPAIR_PASS_SLOTS_TYPE gRepairPassSlotList[ NUM_REPAIR_PASS_TYPES ] =
|
||||
{ /* big pockets */ 4, 7, BIGPOCK1POS, BIGPOCK2POS, BIGPOCK3POS, BIGPOCK4POS, BIGPOCK5POS, BIGPOCK6POS, BIGPOCK7POS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
{ /* med pockets */ 0, 4, MEDPOCK1POS, MEDPOCK2POS, MEDPOCK3POS, MEDPOCK4POS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
{ /* sml pockets */ 8, 30, SMALLPOCK1POS, SMALLPOCK2POS, SMALLPOCK3POS, SMALLPOCK4POS, SMALLPOCK5POS, SMALLPOCK6POS, SMALLPOCK7POS, SMALLPOCK8POS, SMALLPOCK9POS, SMALLPOCK10POS, SMALLPOCK11POS, SMALLPOCK12POS, SMALLPOCK13POS, SMALLPOCK14POS, SMALLPOCK15POS, SMALLPOCK16POS, SMALLPOCK17POS, SMALLPOCK18POS, SMALLPOCK19POS, SMALLPOCK20POS, SMALLPOCK21POS, SMALLPOCK22POS, SMALLPOCK23POS, SMALLPOCK24POS, SMALLPOCK25POS, SMALLPOCK26POS, SMALLPOCK27POS, SMALLPOCK28POS, SMALLPOCK29POS, SMALLPOCK30POS },
|
||||
{ /* HEADROCK HAM B2.8: LBE Slot pass */ 0, 5, VESTPOCKPOS, LTHIGHPOCKPOS, RTHIGHPOCKPOS, CPACKPOCKPOS, BPACKPOCKPOS, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
||||
};
|
||||
|
||||
extern STR16 sRepairsDoneString[];
|
||||
@@ -3298,18 +3301,42 @@ void HandleRepairBySoldier( SOLDIERTYPE *pSoldier )
|
||||
fAnyOfSoldiersOwnItemsWereFixed = UnjamGunsOnSoldier( pSoldier, pSoldier, &ubRepairPtsLeft );
|
||||
|
||||
// repair items on self
|
||||
for( bLoop = 0; bLoop < 2; bLoop++ )
|
||||
// HEADROCK HAM B2.8: Experimental feature: Fixes LBEs last, as they don't actually require repairs.
|
||||
for( bLoop = 0; bLoop < 4; bLoop++ )
|
||||
{
|
||||
if ( bLoop == 0 )
|
||||
{
|
||||
bLoopStart = SECONDHANDPOS;
|
||||
// HEADROCK: New loop stage only checks second hand, to avoid LBEs.
|
||||
bLoopEnd = SECONDHANDPOS;
|
||||
}
|
||||
else if ( bLoop == 1 )
|
||||
{
|
||||
// HEADROCK: Second check is for armor and headgear only.
|
||||
bLoopStart = HELMETPOS;
|
||||
bLoopEnd = HEAD2POS;
|
||||
}
|
||||
else if ( bLoop == 2 )
|
||||
{
|
||||
// HEADROCK: Loop stage altered to run through inventory only
|
||||
bLoopStart = UsingNewInventorySystem() == false ? BIGPOCKSTART : GUNSLINGPOCKPOS;
|
||||
// CHRISL: Changed to dynamically determine max inventory locations.
|
||||
bLoopEnd = (NUM_INV_SLOTS - 1);
|
||||
}
|
||||
else
|
||||
else if ( bLoop == 3 )
|
||||
{
|
||||
bLoopStart = HELMETPOS;
|
||||
bLoopEnd = UsingNewInventorySystem() == false ? HEAD2POS : BPACKPOCKPOS;
|
||||
if (UsingNewInventorySystem() == true)
|
||||
{
|
||||
// HEADROCK: Last loop fixes LBEs
|
||||
bLoopStart = VESTPOCKPOS;
|
||||
bLoopEnd = BPACKPOCKPOS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// HEADROCK: In OIV, simply check everything again.
|
||||
bLoopStart = SECONDHANDPOS;
|
||||
bLoopEnd = (NUM_INV_SLOTS - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// now repair objects running from left hand to small pocket
|
||||
@@ -3317,10 +3344,12 @@ void HandleRepairBySoldier( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
//CHRISL: These two conditions allow us to repair LBE pocket items at the same time as worn armor, while
|
||||
// still letting us repair the item in our offhand first.
|
||||
if(UsingNewInventorySystem() == true && bLoop == 0 && bPocket>SECONDHANDPOS && bPocket<GUNSLINGPOCKPOS)
|
||||
continue;
|
||||
if(UsingNewInventorySystem() == true && bLoop == 1 && bPocket==SECONDHANDPOS)
|
||||
continue;
|
||||
// HEADROCK HAM B2.8: No longer necessary, as I've artificially added new stages for this. LBE
|
||||
// pockets are now repaired LAST.
|
||||
//if(UsingNewInventorySystem() == true && bLoop == 0 && bPocket>SECONDHANDPOS && bPocket<GUNSLINGPOCKPOS)
|
||||
// continue;
|
||||
//if(UsingNewInventorySystem() == true && bLoop == 1 && bPocket==SECONDHANDPOS)
|
||||
// continue;
|
||||
pObj = &(pSoldier->inv[ bPocket ]);
|
||||
|
||||
if ( RepairObject( pSoldier, pSoldier, pObj, &ubRepairPtsLeft ) )
|
||||
@@ -3693,7 +3722,17 @@ void HandleTrainingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ )
|
||||
}
|
||||
|
||||
// now finally train the grunt
|
||||
TrainSoldierWithPts( pStudent, sTotalTrainingPts );
|
||||
// HEADROCK HAM B2.8: A new trainer/student synch system allows students to rest while
|
||||
// their trainer is asleep. If this happens, the student should not train on their own!
|
||||
if (gGameExternalOptions.ubSmartTrainingRest == 0 || gGameExternalOptions.ubSmartTrainingRest == 2)
|
||||
{
|
||||
TrainSoldierWithPts( pStudent, sTotalTrainingPts );
|
||||
}
|
||||
else if ( pTrainer != NULL )
|
||||
{
|
||||
// This only occurs if at least one trainer is awake.
|
||||
TrainSoldierWithPts( pStudent, sTotalTrainingPts );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5587,13 +5626,17 @@ void MakeSureToolKitIsInHand( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
if( Item[pSoldier->inv[ bPocket ].usItem].toolkit )
|
||||
{
|
||||
// If the second hand is empty, swap item in first hand there
|
||||
if (pSoldier->inv[HANDPOS].exists() &&
|
||||
!pSoldier->inv[SECONDHANDPOS].exists() &&
|
||||
CanItemFitInPosition(pSoldier, &pSoldier->inv[SECONDHANDPOS], HANDPOS, FALSE)) {
|
||||
SwapObjs( pSoldier, HANDPOS, SECONDHANDPOS, TRUE );
|
||||
}
|
||||
if(!CanItemFitInPosition(pSoldier, &pSoldier->inv[HANDPOS], bPocket, FALSE))
|
||||
// HEADROCK HAM B2.8: These new conditions will create a bias for swapping an item out of
|
||||
// our hand.
|
||||
|
||||
//If the second hand is free, the item will go to the SECONDHANDPOS while the toolkit
|
||||
// goes into the HANDPOS
|
||||
if( Item[pSoldier->inv[HANDPOS].usItem].usItemClass & (IC_WEAPON | IC_PUNCH) && !pSoldier->inv[SECONDHANDPOS].exists())
|
||||
SwapObjs(pSoldier, HANDPOS, SECONDHANDPOS, TRUE);
|
||||
// Else, if the gun sling slot is free, and the item can go there, it will.
|
||||
else if(UsingNewInventorySystem() && !pSoldier->inv[GUNSLINGPOCKPOS].exists() && CanItemFitInPosition(pSoldier, &pSoldier->inv[HANDPOS], GUNSLINGPOCKPOS, FALSE))
|
||||
SwapObjs(pSoldier, HANDPOS, GUNSLINGPOCKPOS, TRUE);
|
||||
else if(!CanItemFitInPosition(pSoldier, &pSoldier->inv[HANDPOS], bPocket, FALSE))
|
||||
SwapObjs(pSoldier, HANDPOS, SECONDHANDPOS, TRUE);
|
||||
SwapObjs( pSoldier, HANDPOS, bPocket, TRUE );
|
||||
break;
|
||||
@@ -5623,13 +5666,17 @@ BOOLEAN MakeSureMedKitIsInHand( SOLDIERTYPE *pSoldier )
|
||||
if ( Item[pSoldier->inv[ bPocket ].usItem].medicalkit )
|
||||
{
|
||||
fCharacterInfoPanelDirty = TRUE;
|
||||
// If the second hand is empty, swap item in first hand there
|
||||
if (pSoldier->inv[HANDPOS].exists() &&
|
||||
!pSoldier->inv[SECONDHANDPOS].exists() &&
|
||||
CanItemFitInPosition(pSoldier, &pSoldier->inv[SECONDHANDPOS], HANDPOS, FALSE)) {
|
||||
SwapObjs( pSoldier, HANDPOS, SECONDHANDPOS, TRUE );
|
||||
}
|
||||
if(!CanItemFitInPosition(pSoldier, &pSoldier->inv[HANDPOS], bPocket, FALSE))
|
||||
// HEADROCK HAM B2.8: These new conditions will create a bias for swapping an item out of
|
||||
// our hand.
|
||||
|
||||
//If the second hand is free, the item will go to the SECONDHANDPOS while the medikit
|
||||
// goes into the HANDPOS
|
||||
if( Item[pSoldier->inv[HANDPOS].usItem].usItemClass & (IC_WEAPON | IC_PUNCH) && !pSoldier->inv[SECONDHANDPOS].exists())
|
||||
SwapObjs(pSoldier, HANDPOS, SECONDHANDPOS, TRUE);
|
||||
// Else, if the gun sling slot is free, and the item can go there, it will.
|
||||
else if(UsingNewInventorySystem() && !pSoldier->inv[GUNSLINGPOCKPOS].exists() && CanItemFitInPosition(pSoldier, &pSoldier->inv[HANDPOS], GUNSLINGPOCKPOS, FALSE))
|
||||
SwapObjs(pSoldier, HANDPOS, GUNSLINGPOCKPOS, TRUE);
|
||||
else if(!CanItemFitInPosition(pSoldier, &pSoldier->inv[HANDPOS], bPocket, FALSE))
|
||||
SwapObjs(pSoldier, HANDPOS, SECONDHANDPOS, TRUE);
|
||||
SwapObjs( pSoldier, HANDPOS, bPocket, TRUE );
|
||||
return(TRUE);
|
||||
@@ -11719,9 +11766,357 @@ BOOLEAN UnjamGunsOnSoldier( SOLDIERTYPE *pOwnerSoldier, SOLDIERTYPE *pRepairSold
|
||||
return ( fAnyGunsWereUnjammed );
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2.8: A set of functions to synchronize sleeping periods of trainers and trainees
|
||||
BOOLEAN SetTrainerSleepWhenTraineesSleep( SOLDIERTYPE *pThisTrainee)
|
||||
{
|
||||
UINT16 sMapX = pThisTrainee->sSectorX;
|
||||
UINT16 sMapY = pThisTrainee->sSectorY;
|
||||
UINT16 sMapZ = pThisTrainee->sZLevel;
|
||||
UINT8 bStat = pThisTrainee->bTrainStat;
|
||||
INT32 iCounter, iNumberOnTeam;
|
||||
|
||||
SOLDIERTYPE * pOtherTrainee;
|
||||
SOLDIERTYPE * pTrainer;
|
||||
BOOLEAN fAllTraineesAsleep = TRUE;
|
||||
BOOLEAN fTrainersSentToSleep = FALSE;
|
||||
|
||||
if (pThisTrainee->bAssignment != TRAIN_BY_OTHER)
|
||||
{
|
||||
// Shouldn't happen...
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
iNumberOnTeam =gTacticalStatus.Team[ OUR_TEAM ].bLastID;
|
||||
|
||||
// Check to see if all other trainees of the same stat are also asleep
|
||||
for( iCounter = 0; iCounter < iNumberOnTeam; iCounter++ )
|
||||
{
|
||||
pOtherTrainee = &Menptr[ iCounter ];
|
||||
if (pOtherTrainee->bAssignment == TRAIN_BY_OTHER && pOtherTrainee->bTrainStat == pThisTrainee->bTrainStat &&
|
||||
pOtherTrainee->sSectorX == sMapX && pOtherTrainee->sSectorY == sMapY && pOtherTrainee->sZLevel == sMapZ &&
|
||||
pOtherTrainee->bActive && !pOtherTrainee->flags.fMercAsleep )
|
||||
{
|
||||
// Trainee is present and awake. Flag is reset to false.
|
||||
fAllTraineesAsleep = FALSE;
|
||||
}
|
||||
}
|
||||
// If they are all asleep
|
||||
if (fAllTraineesAsleep)
|
||||
{
|
||||
// Look for trainers of that stat, in the same sector
|
||||
for( iCounter = 0; iCounter < iNumberOnTeam; iCounter++ )
|
||||
{
|
||||
pTrainer = &Menptr[ iCounter ];
|
||||
if (pTrainer->bAssignment == TRAIN_TEAMMATE && pTrainer->bTrainStat == pThisTrainee->bTrainStat &&
|
||||
pTrainer->sSectorX == sMapX && pTrainer->sSectorY == sMapY && pTrainer->sZLevel == sMapZ &&
|
||||
pTrainer->bActive && !pTrainer->flags.fMercAsleep )
|
||||
{
|
||||
// Trainer will go to sleep
|
||||
if( SetMercAsleep( pTrainer, FALSE ) )
|
||||
{
|
||||
if( gGameSettings.fOptions[ TOPTION_SLEEPWAKE_NOTIFICATION ] )
|
||||
{
|
||||
// tell player about it
|
||||
AddSoldierToWaitingListQueue( pTrainer );
|
||||
}
|
||||
|
||||
// seems unnecessary now? ARM
|
||||
pTrainer->bOldAssignment = pTrainer->bAssignment;
|
||||
|
||||
fTrainersSentToSleep = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fTrainersSentToSleep)
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN SetTraineesSleepWhenTrainerSleeps( SOLDIERTYPE *pTrainer)
|
||||
{
|
||||
UINT16 sMapX = pTrainer->sSectorX;
|
||||
UINT16 sMapY = pTrainer->sSectorY;
|
||||
UINT16 sMapZ = pTrainer->sZLevel;
|
||||
UINT8 bStat = pTrainer->bTrainStat;
|
||||
INT32 iCounter, iNumberOnTeam;
|
||||
BOOLEAN fTraineesSentToSleep = FALSE;
|
||||
|
||||
SOLDIERTYPE * pTrainee;
|
||||
|
||||
if (pTrainer->bAssignment != TRAIN_TEAMMATE)
|
||||
{
|
||||
// Shouldn't happen...
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
iNumberOnTeam =gTacticalStatus.Team[ OUR_TEAM ].bLastID;
|
||||
|
||||
for( iCounter = 0; iCounter < iNumberOnTeam; iCounter++ )
|
||||
{
|
||||
pTrainee = &Menptr[ iCounter ];
|
||||
if (pTrainee->bAssignment == TRAIN_BY_OTHER && pTrainee->bTrainStat == pTrainer->bTrainStat &&
|
||||
pTrainee->sSectorX == sMapX && pTrainee->sSectorY == sMapY && pTrainee->sZLevel == sMapZ &&
|
||||
pTrainee->bActive && !pTrainee->flags.fMercAsleep )
|
||||
{
|
||||
// Trainee will go to sleep
|
||||
if( SetMercAsleep( pTrainee, FALSE ) )
|
||||
{
|
||||
if( gGameSettings.fOptions[ TOPTION_SLEEPWAKE_NOTIFICATION ] )
|
||||
{
|
||||
// tell player about it
|
||||
AddSoldierToWaitingListQueue( pTrainee );
|
||||
}
|
||||
|
||||
// seems unnecessary now? ARM
|
||||
pTrainee->bOldAssignment = pTrainee->bAssignment;
|
||||
|
||||
fTraineesSentToSleep = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fTraineesSentToSleep)
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN SetTrainerWakeWhenTraineesWake( SOLDIERTYPE *pThisTrainee)
|
||||
{
|
||||
UINT16 sMapX = pThisTrainee->sSectorX;
|
||||
UINT16 sMapY = pThisTrainee->sSectorY;
|
||||
UINT16 sMapZ = pThisTrainee->sZLevel;
|
||||
UINT8 bStat = pThisTrainee->bTrainStat;
|
||||
INT32 iCounter, iNumberOnTeam;
|
||||
|
||||
SOLDIERTYPE * pOtherTrainee;
|
||||
SOLDIERTYPE * pTrainer;
|
||||
BOOLEAN fAllTraineesAwake = TRUE;
|
||||
BOOLEAN fTrainersWokenUp = FALSE;
|
||||
|
||||
if (pThisTrainee->bAssignment != TRAIN_BY_OTHER)
|
||||
{
|
||||
// Shouldn't happen...
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
iNumberOnTeam =gTacticalStatus.Team[ OUR_TEAM ].bLastID;
|
||||
|
||||
// Check to see if all other trainees of the same stat are also asleep
|
||||
for( iCounter = 0; iCounter < iNumberOnTeam; iCounter++ )
|
||||
{
|
||||
pOtherTrainee = &Menptr[ iCounter ];
|
||||
if (pOtherTrainee->bAssignment == TRAIN_BY_OTHER && pOtherTrainee->bTrainStat == pThisTrainee->bTrainStat &&
|
||||
pOtherTrainee->sSectorX == sMapX && pOtherTrainee->sSectorY == sMapY && pOtherTrainee->sZLevel == sMapZ &&
|
||||
pOtherTrainee->bActive && pOtherTrainee->flags.fMercAsleep )
|
||||
{
|
||||
// Trainee is present and asleep. Flag is reset to FALSE.
|
||||
fAllTraineesAwake = FALSE;
|
||||
}
|
||||
}
|
||||
// If they are all awake
|
||||
if (fAllTraineesAwake)
|
||||
{
|
||||
// Look for trainers of that stat, in the same sector
|
||||
for( iCounter = 0; iCounter < iNumberOnTeam; iCounter++ )
|
||||
{
|
||||
pTrainer = &Menptr[ iCounter ];
|
||||
if (pTrainer->bAssignment == TRAIN_TEAMMATE && pTrainer->bTrainStat == pThisTrainee->bTrainStat &&
|
||||
pTrainer->sSectorX == sMapX && pTrainer->sSectorY == sMapY && pTrainer->sZLevel == sMapZ &&
|
||||
pTrainer->bActive && pTrainer->flags.fMercAsleep )
|
||||
{
|
||||
// Trainer will wake up
|
||||
if( SetMercAwake( pTrainer, FALSE, FALSE ) )
|
||||
{
|
||||
if( gGameSettings.fOptions[ TOPTION_SLEEPWAKE_NOTIFICATION ] )
|
||||
{
|
||||
// tell player about it
|
||||
AddSoldierToWaitingListQueue( pTrainer );
|
||||
}
|
||||
|
||||
// seems unnecessary now? ARM
|
||||
pTrainer->bOldAssignment = pTrainer->bAssignment;
|
||||
|
||||
fTrainersWokenUp = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fTrainersWokenUp)
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN SetTraineesWakeWhenTrainerWakes( SOLDIERTYPE *pTrainer)
|
||||
{
|
||||
UINT16 sMapX = pTrainer->sSectorX;
|
||||
UINT16 sMapY = pTrainer->sSectorY;
|
||||
UINT16 sMapZ = pTrainer->sZLevel;
|
||||
UINT8 bStat = pTrainer->bTrainStat;
|
||||
INT32 iCounter, iNumberOnTeam;
|
||||
BOOLEAN fTraineesWokenUp = FALSE;
|
||||
|
||||
SOLDIERTYPE * pTrainee;
|
||||
|
||||
if (pTrainer->bAssignment != TRAIN_TEAMMATE)
|
||||
{
|
||||
// Shouldn't happen...
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
iNumberOnTeam =gTacticalStatus.Team[ OUR_TEAM ].bLastID;
|
||||
|
||||
for( iCounter = 0; iCounter < iNumberOnTeam; iCounter++ )
|
||||
{
|
||||
pTrainee = &Menptr[ iCounter ];
|
||||
if (pTrainee->bAssignment == TRAIN_BY_OTHER && pTrainee->bTrainStat == pTrainer->bTrainStat &&
|
||||
pTrainee->sSectorX == sMapX && pTrainee->sSectorY == sMapY && pTrainee->sZLevel == sMapZ &&
|
||||
pTrainee->bActive && pTrainee->flags.fMercAsleep )
|
||||
{
|
||||
// Trainee will wake up
|
||||
if( SetMercAwake( pTrainee, FALSE, FALSE ) )
|
||||
{
|
||||
if( gGameSettings.fOptions[ TOPTION_SLEEPWAKE_NOTIFICATION ] )
|
||||
{
|
||||
// tell player about it
|
||||
AddSoldierToWaitingListQueue( pTrainee );
|
||||
}
|
||||
|
||||
// seems unnecessary now? ARM
|
||||
pTrainee->bOldAssignment = pTrainee->bAssignment;
|
||||
|
||||
fTraineesWokenUp = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fTraineesWokenUp)
|
||||
{
|
||||
return(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void HandleTrainingSleepSynchronize( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
// HEADROCK HAM B2.8: Trainees will now go to sleep if the trainer goes to sleep.
|
||||
if ((gGameExternalOptions.ubSmartTrainingSleep == 1 || gGameExternalOptions.ubSmartTrainingSleep == 2) && pSoldier->bAssignment == TRAIN_TEAMMATE)
|
||||
{
|
||||
SetTraineesSleepWhenTrainerSleeps( pSoldier );
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2.8: If this is a trainee, and all other trainees are already asleep, put all trainers to sleep as well.
|
||||
if ( (gGameExternalOptions.ubSmartTrainingSleep == 1 || gGameExternalOptions.ubSmartTrainingSleep == 3 ) && pSoldier->bAssignment == TRAIN_BY_OTHER)
|
||||
{
|
||||
SetTrainerSleepWhenTraineesSleep( pSoldier );
|
||||
}
|
||||
}
|
||||
|
||||
void HandleTrainingWakeSynchronize( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
// HEADROCK HAM B2.8: Trainees will now go to sleep if the trainer goes to sleep.
|
||||
if ((gGameExternalOptions.ubSmartTrainingWake == 1 || gGameExternalOptions.ubSmartTrainingWake == 2) && pSoldier->bAssignment == TRAIN_TEAMMATE)
|
||||
{
|
||||
SetTraineesWakeWhenTrainerWakes( pSoldier );
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2.8: If this is a trainee, and all other trainees are already asleep, put all trainers to sleep as well.
|
||||
if ( (gGameExternalOptions.ubSmartTrainingWake == 1 || gGameExternalOptions.ubSmartTrainingWake == 3 ) && pSoldier->bAssignment == TRAIN_BY_OTHER)
|
||||
{
|
||||
SetTrainerWakeWhenTraineesWake( pSoldier );
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN FindAnyAwakeTrainers( SOLDIERTYPE *pTrainee )
|
||||
{
|
||||
UINT16 sMapX = pTrainee->sSectorX;
|
||||
UINT16 sMapY = pTrainee->sSectorY;
|
||||
UINT16 sMapZ = pTrainee->sZLevel;
|
||||
UINT8 bStat = pTrainee->bTrainStat;
|
||||
INT32 iCounter, iNumberOnTeam;
|
||||
BOOLEAN fAllTrainersAsleep = TRUE;
|
||||
|
||||
SOLDIERTYPE * pTrainer;
|
||||
|
||||
if (pTrainee->bAssignment != TRAIN_BY_OTHER)
|
||||
{
|
||||
// Shouldn't happen...
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
iNumberOnTeam =gTacticalStatus.Team[ OUR_TEAM ].bLastID;
|
||||
|
||||
for( iCounter = 0; iCounter < iNumberOnTeam; iCounter++ )
|
||||
{
|
||||
pTrainer = &Menptr[ iCounter ];
|
||||
if (pTrainer->bAssignment == TRAIN_TEAMMATE && pTrainer->bTrainStat == pTrainee->bTrainStat &&
|
||||
pTrainer->sSectorX == sMapX && pTrainer->sSectorY == sMapY && pTrainer->sZLevel == sMapZ &&
|
||||
pTrainer->bActive && !pTrainer->flags.fMercAsleep )
|
||||
{
|
||||
fAllTrainersAsleep = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return(fAllTrainersAsleep);
|
||||
}
|
||||
|
||||
BOOLEAN FindAnyAwakeTrainees( SOLDIERTYPE *pTrainer )
|
||||
{
|
||||
UINT16 sMapX = pTrainer->sSectorX;
|
||||
UINT16 sMapY = pTrainer->sSectorY;
|
||||
UINT16 sMapZ = pTrainer->sZLevel;
|
||||
UINT8 bStat = pTrainer->bTrainStat;
|
||||
INT32 iCounter, iNumberOnTeam;
|
||||
BOOLEAN fAllTraineesAsleep = TRUE;
|
||||
|
||||
SOLDIERTYPE * pTrainee;
|
||||
|
||||
if (pTrainer->bAssignment != TRAIN_TEAMMATE)
|
||||
{
|
||||
// Shouldn't happen...
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
iNumberOnTeam =gTacticalStatus.Team[ OUR_TEAM ].bLastID;
|
||||
|
||||
for( iCounter = 0; iCounter < iNumberOnTeam; iCounter++ )
|
||||
{
|
||||
pTrainee = &Menptr[ iCounter ];
|
||||
if (pTrainee->bAssignment == TRAIN_BY_OTHER && pTrainee->bTrainStat == pTrainer->bTrainStat &&
|
||||
pTrainee->sSectorX == sMapX && pTrainee->sSectorY == sMapY && pTrainee->sZLevel == sMapZ &&
|
||||
pTrainee->bActive && !pTrainee->flags.fMercAsleep )
|
||||
{
|
||||
fAllTraineesAsleep = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return(fAllTraineesAsleep);
|
||||
}
|
||||
|
||||
@@ -324,6 +324,15 @@ void UnEscortEPC( SOLDIERTYPE *pSoldier );
|
||||
|
||||
SOLDIERTYPE *AnyDoctorWhoCanHealThisPatient( SOLDIERTYPE *pPatient, BOOLEAN fThisHour );
|
||||
|
||||
// HEADROCK HAM B2.8: A set of functions to synchronize sleeping periods of trainers and trainees
|
||||
BOOLEAN SetTrainerSleepWhenTraineesSleep( SOLDIERTYPE *pTrainee);
|
||||
BOOLEAN SetTraineesSleepWhenTrainerSleeps( SOLDIERTYPE *pTrainer );
|
||||
BOOLEAN SetTrainerWakeWhenTraineesWake( SOLDIERTYPE *pTrainee );
|
||||
BOOLEAN SetTraineesWakeWhenTrainerWakes( SOLDIERTYPE *pTrainer );
|
||||
void HandleTrainingSleepSynchronize( SOLDIERTYPE *pSoldier );
|
||||
void HandleTrainingWakeSynchronize( SOLDIERTYPE *pSoldier );
|
||||
BOOLEAN FindAnyAwakeTrainers( SOLDIERTYPE *pTrainee );
|
||||
BOOLEAN FindAnyAwakeTrainees( SOLDIERTYPE *pTrainer );
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4007,7 +4007,7 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget )
|
||||
|
||||
pAttacker->uiFlags |= CELL_FIREDATTARGET | CELL_DIRTY;
|
||||
if( pAttacker->usAttack < 950 )
|
||||
usAttack = (UINT16)(pAttacker->usAttack + PreRandom(2000 - pAttacker->usAttack ));
|
||||
usAttack = (UINT16)(pAttacker->usAttack + PreRandom((INT16)(gGameExternalOptions.iAutoResolveLuckFactor*1000.0) - pAttacker->usAttack ));
|
||||
else
|
||||
usAttack = (UINT16)(950 + PreRandom( 50 ));
|
||||
if( pTarget->uiFlags & CELL_RETREATING && !(pAttacker->uiFlags & CELL_FEMALECREATURE) )
|
||||
@@ -4016,7 +4016,7 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget )
|
||||
usAttack = usAttack * 7 / 10;
|
||||
}
|
||||
if( pTarget->usDefence < 950 )
|
||||
usDefence = (UINT16)(pTarget->usDefence + PreRandom(2000 - pTarget->usDefence ));
|
||||
usDefence = (UINT16)(pTarget->usDefence + PreRandom((INT16)(gGameExternalOptions.iAutoResolveLuckFactor*1000.0) - pTarget->usDefence ));
|
||||
else
|
||||
usDefence = (UINT16)(950 + PreRandom( 50 ));
|
||||
if( pAttacker->uiFlags & CELL_FEMALECREATURE )
|
||||
|
||||
+760
-65
@@ -66,6 +66,10 @@
|
||||
|
||||
INT32 iRestrictedSectorArraySize;
|
||||
UINT32 gRestrictMilitia[256];
|
||||
// HEADROCK HAM B1: Alternate array keeps track of dynamically unrestricted sectors
|
||||
BOOLEAN gDynamicRestrictMilitia[ 256 ];
|
||||
// HEADROCK HAM B1: Function that dynamically unrestricts sectors as we take over towns.
|
||||
extern void AdjustRoamingRestrictions();
|
||||
|
||||
UINT8 gpAttackDirs[5][4]; // 0. Green Militia 1. Regular Militia 2. Elite Militia 3. Insertion code
|
||||
UINT8 guiDirNumber = 0;
|
||||
@@ -143,9 +147,41 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY )
|
||||
{
|
||||
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
|
||||
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] / gGameExternalOptions.guiDivOfOriginalMilitia);
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] / gGameExternalOptions.guiDivOfOriginalMilitia);
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] / gGameExternalOptions.guiDivOfOriginalMilitia);
|
||||
//HEADROCK HAM B2.7: Track the number of militia at the source.
|
||||
UINT16 bTotalMilitiaAtSource = pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ];
|
||||
UINT8 bTargetGreen, bTargetRegular, bTargetElite;
|
||||
UINT8 bUpgradePoints;
|
||||
|
||||
if (gGameExternalOptions.fDiverseRoamingMilitiaGroups)
|
||||
{
|
||||
bTargetRegular = __max(1,bTotalMilitiaAtSource / (gGameExternalOptions.guiDivOfOriginalMilitia * 4));
|
||||
bTargetElite = __max(1,bTotalMilitiaAtSource / (gGameExternalOptions.guiDivOfOriginalMilitia * 4));
|
||||
bTargetGreen = (bTotalMilitiaAtSource / gGameExternalOptions.guiDivOfOriginalMilitia) - (bTargetRegular + bTargetElite);
|
||||
|
||||
pSectorInfo = &( SectorInfo[ SECTOR( sTMapX, sTMapY ) ] );
|
||||
|
||||
// Continue if we're dealing with a full group that isn't full of veterans
|
||||
if ( CountMilitia(pSectorInfo) >= gGameExternalOptions.guiMaxMilitiaSquadSize && pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA] < CountMilitia(pSectorInfo) )
|
||||
{
|
||||
bUpgradePoints = bTargetGreen + (bTargetRegular * 2);
|
||||
bTargetElite += __min(bTargetRegular, pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA]);
|
||||
bUpgradePoints -= (__min(bTargetRegular, pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA]))*2;
|
||||
bTargetRegular = bUpgradePoints;
|
||||
bTargetGreen = 0;
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2.7: Create 1/2 green, 1/4 regular, 1/4 elite.
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, bTargetGreen);
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, bTargetRegular);
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, bTargetElite);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] / gGameExternalOptions.guiDivOfOriginalMilitia);
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] / gGameExternalOptions.guiDivOfOriginalMilitia);
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] / gGameExternalOptions.guiDivOfOriginalMilitia);
|
||||
}
|
||||
|
||||
pSectorInfo = &( SectorInfo[ SECTOR( sTMapX, sTMapY ) ] );
|
||||
|
||||
@@ -178,13 +214,145 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL
|
||||
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
|
||||
SECTORINFO *pTSectorInfo = &( SectorInfo[ SECTOR( sTMapX, sTMapY ) ] );
|
||||
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
|
||||
UINT8 bGreensSourceTeam = 0, bGreensDestTeam = 0;
|
||||
UINT8 bRegularsSourceTeam = 0, bRegularsDestTeam = 0;
|
||||
UINT8 bElitesSourceTeam = 0, bElitesDestTeam = 0;
|
||||
UINT8 bTotalGreens = 0, bTotalRegulars = 0, bTotalElites = 0;
|
||||
UINT8 bTotalGreensPercent = 0, bTotalRegularsPercent = 0, bTotalElitesPercent = 0;
|
||||
INT8 bNewSourceGroupSize = 0, bNewDestGroupSize = 0, bGroupSizeRatio = 0;
|
||||
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
|
||||
// HEADROCK HAM B2.8
|
||||
// There are now several methods of militia join-up.
|
||||
if (PreRandom(100) < gGameExternalOptions.ubRoamingMilitiaSpreadsOutChance)
|
||||
{
|
||||
// Militia will attempt to spread out, averaging the size and composition of both groups.
|
||||
if ( CountMilitia(pSectorInfo) && CountMilitia(pTSectorInfo) )
|
||||
{
|
||||
bGreensSourceTeam = pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ];
|
||||
bGreensDestTeam = pTSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ];
|
||||
bRegularsSourceTeam = pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ];
|
||||
bRegularsDestTeam = pTSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ];
|
||||
bElitesSourceTeam = pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ];
|
||||
bElitesDestTeam = pTSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ];
|
||||
|
||||
bTotalGreens = bGreensSourceTeam + bGreensDestTeam;
|
||||
bTotalRegulars = bRegularsSourceTeam + bRegularsDestTeam;
|
||||
bTotalElites = bElitesSourceTeam + bElitesDestTeam;
|
||||
|
||||
// Source team gets half of each group, rounded down
|
||||
bGreensSourceTeam = bTotalGreens / 2;
|
||||
bRegularsSourceTeam = bTotalRegulars / 2;
|
||||
bElitesSourceTeam = bTotalElites / 2;
|
||||
|
||||
// Destination team gets half of each group, rounded up
|
||||
bGreensDestTeam = bTotalGreens - bGreensSourceTeam;
|
||||
bRegularsDestTeam = bTotalRegulars - bRegularsSourceTeam;
|
||||
bElitesDestTeam = bTotalElites - bElitesSourceTeam;
|
||||
|
||||
// Erase ALL militia from both locations.
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sTMapX, sTMapY, GREEN_MILITIA, pTSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sTMapX, sTMapY, REGULAR_MILITIA, pTSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sTMapX, sTMapY, ELITE_MILITIA, pTSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
|
||||
|
||||
// Add new militia.
|
||||
StrategicAddMilitiaToSector( sMapX, sMapY, GREEN_MILITIA, bGreensSourceTeam );
|
||||
StrategicAddMilitiaToSector( sMapX, sMapY, REGULAR_MILITIA, bRegularsSourceTeam );
|
||||
StrategicAddMilitiaToSector( sMapX, sMapY, ELITE_MILITIA, bElitesSourceTeam );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, bGreensDestTeam );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, bRegularsDestTeam );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, bElitesDestTeam );
|
||||
}
|
||||
else
|
||||
{
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
|
||||
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( gGameExternalOptions.fDiverseRoamingMilitiaGroups )
|
||||
{
|
||||
// Diverse Militia Join-up: Destination team gets as many troops as possible, but both teams
|
||||
// keep an averaged green-regular-elite ratio.
|
||||
bNewDestGroupSize = __min((CountMilitia(pTSectorInfo) + CountMilitia(pSectorInfo)), (UINT8)gGameExternalOptions.guiMaxMilitiaSquadSize);
|
||||
bNewSourceGroupSize = __max(0,(CountMilitia(pTSectorInfo) + CountMilitia(pSectorInfo)) - gGameExternalOptions.guiMaxMilitiaSquadSize);
|
||||
|
||||
// If there are still going to be two teams after the transfer
|
||||
if ( bNewSourceGroupSize > 0 )
|
||||
{
|
||||
|
||||
bGreensSourceTeam = pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ];
|
||||
bGreensDestTeam = pTSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ];
|
||||
bRegularsSourceTeam = pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ];
|
||||
bRegularsDestTeam = pTSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ];
|
||||
bElitesSourceTeam = pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ];
|
||||
bElitesDestTeam = pTSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ];
|
||||
|
||||
bTotalGreens = bGreensSourceTeam + bGreensDestTeam;
|
||||
bTotalRegulars = bRegularsSourceTeam + bRegularsDestTeam;
|
||||
bTotalElites = bElitesSourceTeam + bElitesDestTeam;
|
||||
|
||||
bGroupSizeRatio = __max(1,(bNewDestGroupSize / bNewSourceGroupSize));
|
||||
|
||||
// Destination team gets the majority of troops (based on the ratios),
|
||||
// but will always leave at least 1 troop of each type (if available) for the source team
|
||||
bGreensDestTeam = __min(__min(bTotalGreens, ((bTotalGreens * bGroupSizeRatio) / (bGroupSizeRatio + 1) +1) ), __max(0,bTotalGreens-1));
|
||||
bRegularsDestTeam = __min(__min(bTotalRegulars, ((bTotalRegulars * bGroupSizeRatio) / (bGroupSizeRatio + 1) +1) ), __max(0,bTotalRegulars-1));
|
||||
bElitesDestTeam = __min(__min(bTotalElites, ((bTotalElites * bGroupSizeRatio) / (bGroupSizeRatio + 1) +1) ), __max(0,bTotalElites-1));
|
||||
|
||||
// Source team gets the remainder (no less than one troop of each type, if available)
|
||||
bGreensSourceTeam = bTotalGreens - bGreensDestTeam;
|
||||
bRegularsSourceTeam = bTotalRegulars - bRegularsDestTeam;
|
||||
bElitesSourceTeam = bTotalElites - bElitesDestTeam;
|
||||
|
||||
// Erase ALL militia from both locations.
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sTMapX, sTMapY, GREEN_MILITIA, pTSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sTMapX, sTMapY, REGULAR_MILITIA, pTSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sTMapX, sTMapY, ELITE_MILITIA, pTSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
|
||||
|
||||
// Add new militia.
|
||||
StrategicAddMilitiaToSector( sMapX, sMapY, GREEN_MILITIA, bGreensSourceTeam );
|
||||
StrategicAddMilitiaToSector( sMapX, sMapY, REGULAR_MILITIA, bRegularsSourceTeam );
|
||||
StrategicAddMilitiaToSector( sMapX, sMapY, ELITE_MILITIA, bElitesSourceTeam );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, bGreensDestTeam );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, bRegularsDestTeam );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, bElitesDestTeam );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move all militia from source to destination.
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
|
||||
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal join-up. Destination group gets all the best militia. Source team gets the leftovers.
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
|
||||
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
|
||||
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
|
||||
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
|
||||
}
|
||||
}
|
||||
|
||||
while( !fAlternativeMax && CountMilitia(pTSectorInfo) > gGameExternalOptions.guiMaxMilitiaSquadSize ||
|
||||
fAlternativeMax && CountMilitia(pTSectorInfo) > gGameExternalOptions.guiMaxMilitiaSquadSizeBattle )
|
||||
@@ -362,12 +530,40 @@ UINT16 CountDirectionRating( INT16 sMapX, INT16 sMapY, UINT8 uiDir )
|
||||
BOOLEAN CheckStandardConditionsForDirection( INT16 sSMapX, INT16 sSMapY, INT16 sMapX, INT16 sMapY, BOOLEAN fWithCities, BOOLEAN fForBattle, BOOLEAN fOnlyCitySectors )
|
||||
{
|
||||
UINT8 uiTravab = GetTraversability( SECTOR( sSMapX , sSMapY ) , SECTOR( sMapX, sMapY ) );
|
||||
BOOLEAN fTargetCityAllowsRoaming;
|
||||
|
||||
if( uiTravab == GROUNDBARRIER || uiTravab == EDGEOFWORLD ) return FALSE;
|
||||
|
||||
if( !fForBattle && gfMSBattle && NumEnemiesInSector( sMapX, sMapY ) ) return FALSE;
|
||||
|
||||
return (GetTownIdForSector( sMapX, sMapY ) == BLANK_SECTOR || fWithCities) && !IsThisSectorASAMSector( sMapX, sMapY , 0 ) &&
|
||||
// HEADROCK HAM B2.7 : This allows roaming militia to move into Minor City sectors, if liberated at least
|
||||
// once before
|
||||
if (GetTownIdForSector( sMapX, sMapY ) == BLANK_SECTOR)
|
||||
{
|
||||
fTargetCityAllowsRoaming = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gGameExternalOptions.fAllowMilitiaMoveThroughMinorCities)
|
||||
{
|
||||
if ( SectorInfo[SECTOR( sMapX, sMapY )].fSurfaceWasEverPlayerControlled )
|
||||
{
|
||||
fTargetCityAllowsRoaming = ( !gfMilitiaAllowedInTown[GetTownIdForSector( sMapX, sMapY )] );
|
||||
}
|
||||
else
|
||||
{
|
||||
fTargetCityAllowsRoaming = FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fTargetCityAllowsRoaming = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//return (GetTownIdForSector( sMapX, sMapY ) == BLANK_SECTOR || fWithCities) && !IsThisSectorASAMSector( sMapX, sMapY , 0 ) &&
|
||||
// (GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR || !fOnlyCitySectors);// &&
|
||||
return (fTargetCityAllowsRoaming || fWithCities) && !IsThisSectorASAMSector( sMapX, sMapY , 0 ) &&
|
||||
(GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR || !fOnlyCitySectors);// &&
|
||||
// ( !NumEnemiesInSector( sMapX, sMapY ) || GetEnemyGroupIdInSector(sMapX, sMapY ) || fForBattle ) &&
|
||||
// ( fForBattle || CountAllMilitiaInSector( sMapX, sMapY ) < gGameExternalOptions.guiMaxMilitiaSquadSize || PlayerMercsInSector( sMapX, sMapY, 0 ) )
|
||||
@@ -482,6 +678,7 @@ void UpdateMilitiaSquads(INT16 sMapX, INT16 sMapY )
|
||||
UINT8 x;//,y;
|
||||
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
|
||||
UINT8 uiMilitiaCount;
|
||||
BOOLEAN fSourceCityAllowsRoaming;
|
||||
|
||||
|
||||
// If we don't want roaming militia
|
||||
@@ -521,9 +718,14 @@ void UpdateMilitiaSquads(INT16 sMapX, INT16 sMapY )
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2.7: If INI flag is set, allow militia to move out of Minor City sectors (Orta, Tixa, San Mona, etc).
|
||||
if (gGameExternalOptions.fAllowMilitiaMoveThroughMinorCities)
|
||||
fSourceCityAllowsRoaming = ( !gfMilitiaAllowedInTown[GetTownIdForSector( sMapX, sMapY )] );
|
||||
else
|
||||
fSourceCityAllowsRoaming = ( GetTownIdForSector( sMapX, sMapY ) == BLANK_SECTOR );
|
||||
|
||||
// moving squad, if it is not a SAM site
|
||||
if( ( GetTownIdForSector( sMapX, sMapY ) == BLANK_SECTOR ) && (!IsThisSectorASAMSector( sMapX, sMapY, 0 )) )
|
||||
if( ( fSourceCityAllowsRoaming ) && (!IsThisSectorASAMSector( sMapX, sMapY, 0 )) )
|
||||
{
|
||||
if( !PlayerMercsInSector_MSE( (UINT8)sMapX, (UINT8)sMapY, FALSE ) ) // and there's no player's mercs in the sector
|
||||
{
|
||||
@@ -559,13 +761,74 @@ void UpdateMilitiaSquads(INT16 sMapX, INT16 sMapY )
|
||||
//Kaiden: if Restricted Sectors List option is turned on,
|
||||
// militia can't move to any sectors in the list.
|
||||
// Unless they are following a group of mercs.
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// HEADROCK HAM B1: Restrict roamers by XML as normal, but also
|
||||
// allow them to move through visited sectors.
|
||||
// Also, there's an option now to use dynamic restriction. The
|
||||
// AdjustRoamingRestrictions() function is used to dynamically
|
||||
// define which sectors are restricted, based on city conquest.
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
if (gGameExternalOptions.gflimitedRoaming)
|
||||
for (INT32 i=0;i<iRestrictedSectorArraySize; ++i)
|
||||
{
|
||||
// Is militia allowed to move through visited sectors?
|
||||
if (gGameExternalOptions.bUnrestrictVisited)
|
||||
{
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("RestrictedSectors, %d", gRestrictMilitia[i]));
|
||||
if(pMoveDir[iRandomRes][0] == gRestrictMilitia[i])
|
||||
return;
|
||||
// Scan each sector restricted in the XML.
|
||||
for (INT32 i=0;i<iRestrictedSectorArraySize; ++i)
|
||||
{
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("RestrictedSectors, %d", gRestrictMilitia[i]));
|
||||
// If sector isn't explored yet
|
||||
if ( SectorInfo[ pMoveDir[iRandomRes][0] ].fSurfaceWasEverPlayerControlled == 0 )
|
||||
{
|
||||
// Is militia allowed to move through dynamically defined sectors?
|
||||
if (gGameExternalOptions.bDynamicRestrictRoaming)
|
||||
{
|
||||
// Is destination allowed by Dynamic Array?
|
||||
if( !gDynamicRestrictMilitia[pMoveDir[iRandomRes][0]] )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Militia limited to XMLized sectors
|
||||
else
|
||||
{
|
||||
// Is destination allowed by XML?
|
||||
if(pMoveDir[iRandomRes][0] == gRestrictMilitia[i] )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Militia must adhere to restrictions, regardless of visited sectors
|
||||
else
|
||||
{
|
||||
for (INT32 i=0;i<iRestrictedSectorArraySize; ++i)
|
||||
{
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("RestrictedSectors, %d", gRestrictMilitia[i]));
|
||||
// Is militia allowed to move through dynamically defined sectors?
|
||||
if (gGameExternalOptions.bDynamicRestrictRoaming)
|
||||
{
|
||||
// Is destination allowed by Dynamic Array?
|
||||
if( !gDynamicRestrictMilitia[pMoveDir[iRandomRes][0]] )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Militia limited to XMLized sectors
|
||||
else
|
||||
{
|
||||
// Is destination allowed by XML?
|
||||
if(pMoveDir[iRandomRes][0] == gRestrictMilitia[i] )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WDS bug fix for moving militia
|
||||
int targetX = SECTORX( pMoveDir[ iRandomRes ][0] );
|
||||
@@ -622,6 +885,11 @@ void CreateMilitiaSquads(INT16 sMapX, INT16 sMapY )
|
||||
UINT8 x;//,y;
|
||||
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
|
||||
UINT8 uiMilitiaCount;
|
||||
// HEADROCK HAM B2.7: New values:
|
||||
UINT16 iCounter;
|
||||
BOOLEAN fFoundValidSector;
|
||||
UINT16 bTownId;
|
||||
INT16 sCurrentX, sCurrentY;
|
||||
|
||||
|
||||
// If we're not allowing roaming groups,
|
||||
@@ -649,68 +917,139 @@ void CreateMilitiaSquads(INT16 sMapX, INT16 sMapY )
|
||||
|
||||
// Create new Militia Squad
|
||||
|
||||
if( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR )
|
||||
bTownId = GetTownIdForSector( sMapX, sMapY );
|
||||
|
||||
if( bTownId != BLANK_SECTOR )
|
||||
{
|
||||
fFoundValidSector = FALSE;
|
||||
|
||||
// Check all sectors adjacent to the training sector itself.
|
||||
GenerateDirectionInfosWithCapacityCheck( sMapX, sMapY, &uiDirNumber, pMoveDir, FALSE, FALSE, FALSE );
|
||||
|
||||
if(uiDirNumber)// && Random(100) < CHANCE_TO_GENERATE_A_SQUAD)
|
||||
{
|
||||
GenerateDirectionInfos( sMapX, sMapY, &uiDirNumber, pMoveDir, FALSE, FALSE, FALSE );
|
||||
for( x = 1; x < uiDirNumber ; ++x )pMoveDir[x][1] += pMoveDir[x-1][1];
|
||||
|
||||
if(uiDirNumber)// && Random(100) < CHANCE_TO_GENERATE_A_SQUAD)
|
||||
{
|
||||
for( x = 1; x < uiDirNumber ; ++x )pMoveDir[x][1] += pMoveDir[x-1][1];
|
||||
iRandomRes = Random( pMoveDir[ uiDirNumber - 1 ][1] );
|
||||
|
||||
iRandomRes = Random( pMoveDir[ uiDirNumber - 1 ][1] );
|
||||
|
||||
for( x = 0; x < uiDirNumber; ++x)
|
||||
if( iRandomRes < pMoveDir[x][1] )
|
||||
{
|
||||
iRandomRes = x;
|
||||
break;
|
||||
}
|
||||
|
||||
// shouldn't be!
|
||||
if(iRandomRes >= uiDirNumber)iRandomRes = 0;
|
||||
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%ld,%ld:Dir count %ld, Rand %ld. Go to %ld,%ld", sMapX, sMapY, uiDirNumber, iRandomRes, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ));
|
||||
|
||||
GenerateMilitiaSquad( sMapX, sMapY, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
|
||||
AddToBlockMoveList( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
|
||||
|
||||
if( NumEnemiesInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) && CountAllMilitiaInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) )
|
||||
for( x = 0; x < uiDirNumber; ++x)
|
||||
if( iRandomRes < pMoveDir[x][1] )
|
||||
{
|
||||
/* GROUP* pEnemyGroup = GetGroup( GetEnemyGroupIdInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) );
|
||||
|
||||
if(pEnemyGroup && pEnemyGroup->ubGroupID)
|
||||
{
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Attacking from %ld,%ld to %ld,%ld - enemy's group id %ld", sMapX, sMapY, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0], pEnemyGroup->ubGroupID ));
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Arrival 1, Arrival 2");
|
||||
|
||||
pEnemyGroup->ubPrevX = sMapX;
|
||||
pEnemyGroup->ubPrevY = sMapY;
|
||||
|
||||
pEnemyGroup->ubNextX = SECTORX( pMoveDir[ iRandomRes ][0] );
|
||||
pEnemyGroup->ubNextY = SECTORY( pMoveDir[ iRandomRes ][0] );
|
||||
*/
|
||||
gfMSBattle = TRUE;
|
||||
// GroupArrivedAtSector( pEnemyGroup->ubGroupID , TRUE, FALSE );
|
||||
|
||||
EnterAutoResolveMode( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
|
||||
// }
|
||||
iRandomRes = x;
|
||||
break;
|
||||
}
|
||||
|
||||
// shouldn't be!
|
||||
if(iRandomRes >= uiDirNumber)iRandomRes = 0;
|
||||
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%ld,%ld:Dir count %ld, Rand %ld. Go to %ld,%ld", sMapX, sMapY, uiDirNumber, iRandomRes, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ));
|
||||
|
||||
GenerateMilitiaSquad( sMapX, sMapY, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
|
||||
fFoundValidSector = TRUE;
|
||||
AddToBlockMoveList( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
|
||||
|
||||
if( NumEnemiesInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) && CountAllMilitiaInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) )
|
||||
{
|
||||
/* GROUP* pEnemyGroup = GetGroup( GetEnemyGroupIdInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) );
|
||||
|
||||
if(pEnemyGroup && pEnemyGroup->ubGroupID)
|
||||
{
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Attacking from %ld,%ld to %ld,%ld - enemy's group id %ld", sMapX, sMapY, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0], pEnemyGroup->ubGroupID ));
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Arrival 1, Arrival 2");
|
||||
|
||||
pEnemyGroup->ubPrevX = sMapX;
|
||||
pEnemyGroup->ubPrevY = sMapY;
|
||||
|
||||
pEnemyGroup->ubNextX = SECTORX( pMoveDir[ iRandomRes ][0] );
|
||||
pEnemyGroup->ubNextY = SECTORY( pMoveDir[ iRandomRes ][0] );
|
||||
*/
|
||||
gfMSBattle = TRUE;
|
||||
// GroupArrivedAtSector( pEnemyGroup->ubGroupID , TRUE, FALSE );
|
||||
|
||||
EnterAutoResolveMode( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
|
||||
// }
|
||||
}
|
||||
else return;
|
||||
|
||||
}
|
||||
// HEADROCK HAM B2.7: Smarter check - looks at each city sector, and checks if there's room around that
|
||||
// sector to place militia. Also relies on whether the sector has full militia before generating more.
|
||||
// This section only runs if the program has failed to find suitable sectors around the "home" sector
|
||||
// (where militia is being trained).
|
||||
|
||||
iCounter = 0;
|
||||
if (gGameExternalOptions.fSmartRoamingMilitiaGenerator)
|
||||
{
|
||||
while( pTownNamesList[ iCounter ] != 0 && fFoundValidSector == FALSE )
|
||||
{
|
||||
if( pTownNamesList[ iCounter] == bTownId )
|
||||
{
|
||||
sCurrentX = GET_X_FROM_STRATEGIC_INDEX( pTownLocationsList[ iCounter ] );
|
||||
sCurrentY = GET_Y_FROM_STRATEGIC_INDEX( pTownLocationsList[ iCounter ] );
|
||||
|
||||
// if sector has enemies or hasn't already been taken at least once, then
|
||||
if ( !SectorInfo[ SECTOR(sCurrentX, sCurrentY) ].fSurfaceWasEverPlayerControlled || NumEnemiesInSector( sCurrentX, sCurrentY ) > 0 )
|
||||
{
|
||||
// skip the rest. Generate no militia from this sector.
|
||||
iCounter++;
|
||||
continue;
|
||||
}
|
||||
|
||||
GenerateDirectionInfosWithCapacityCheck( sCurrentX, sCurrentY, &uiDirNumber, pMoveDir, FALSE, TRUE, FALSE );
|
||||
|
||||
if(uiDirNumber)// && Random(100) < CHANCE_TO_GENERATE_A_SQUAD)
|
||||
{
|
||||
for( x = 1; x < uiDirNumber ; ++x )pMoveDir[x][1] += pMoveDir[x-1][1];
|
||||
|
||||
iRandomRes = Random( pMoveDir[ uiDirNumber - 1 ][1] );
|
||||
|
||||
for( x = 0; x < uiDirNumber; ++x)
|
||||
if( iRandomRes < pMoveDir[x][1] )
|
||||
{
|
||||
iRandomRes = x;
|
||||
break;
|
||||
}
|
||||
|
||||
// shouldn't be!
|
||||
if(iRandomRes >= uiDirNumber)iRandomRes = 0;
|
||||
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%ld,%ld:Dir count %ld, Rand %ld. Go to %ld,%ld", sMapX, sMapY, uiDirNumber, iRandomRes, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ));
|
||||
|
||||
GenerateMilitiaSquad( sCurrentX, sCurrentY, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
|
||||
fFoundValidSector = TRUE;
|
||||
AddToBlockMoveList( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
|
||||
|
||||
if( NumEnemiesInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) && CountAllMilitiaInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) )
|
||||
{
|
||||
/* GROUP* pEnemyGroup = GetGroup( GetEnemyGroupIdInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) );
|
||||
|
||||
if(pEnemyGroup && pEnemyGroup->ubGroupID)
|
||||
{
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Attacking from %ld,%ld to %ld,%ld - enemy's group id %ld", sMapX, sMapY, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0], pEnemyGroup->ubGroupID ));
|
||||
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Arrival 1, Arrival 2");
|
||||
|
||||
pEnemyGroup->ubPrevX = sMapX;
|
||||
pEnemyGroup->ubPrevY = sMapY;
|
||||
|
||||
pEnemyGroup->ubNextX = SECTORX( pMoveDir[ iRandomRes ][0] );
|
||||
pEnemyGroup->ubNextY = SECTORY( pMoveDir[ iRandomRes ][0] );
|
||||
*/
|
||||
gfMSBattle = TRUE;
|
||||
// GroupArrivedAtSector( pEnemyGroup->ubGroupID , TRUE, FALSE );
|
||||
|
||||
EnterAutoResolveMode( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
iCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern BOOLEAN gfMSResetMilitia;
|
||||
|
||||
void DoMilitiaHelpFromAdjacentSectors( INT16 sMapX, INT16 sMapY )
|
||||
@@ -837,3 +1176,359 @@ void MilitiaFollowPlayer( INT16 sMapX, INT16 sMapY, INT16 sDMapX, INT16 sDMapY )
|
||||
|
||||
MoveMilitiaSquad( sMapX, sMapY, sDMapX, sDMapY, FALSE );
|
||||
}
|
||||
// HEADROCK (HAM): New function to alter Restricted Roaming based on the recent capture of new towns. The area
|
||||
// around the town will be unrestricted, as well as some road sectors leading away from the town.
|
||||
// This function runs during sector conquest checks, and only if an entire town has been conquered. It also
|
||||
// runs at day end, as well as on load/save.
|
||||
void AdjustRoamingRestrictions()
|
||||
{
|
||||
if (!gGameExternalOptions.bDynamicRestrictRoaming)
|
||||
return;
|
||||
|
||||
// to do: Add something to clean up the entire array before setting the flags...
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(DRASSEN) )
|
||||
{
|
||||
// DRASSEN OUTSKIRTS
|
||||
gDynamicRestrictMilitia[SECTOR(12,1)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(13,1)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(14,1)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(12,2)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(14,2)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(12,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(14,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(12,4)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(14,4)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(12,5)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(13,5)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(14,5)] = true;
|
||||
|
||||
// SAM SITE DEFENSE
|
||||
gDynamicRestrictMilitia[SECTOR(15,5)] = true;
|
||||
|
||||
// ROAD WEST TO OMERTA
|
||||
gDynamicRestrictMilitia[SECTOR(9,2)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(10,2)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(11,2)] = true;
|
||||
|
||||
// ROAD SOUTH TO ALMA
|
||||
gDynamicRestrictMilitia[SECTOR(12,6)] = true;
|
||||
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(ALMA) )
|
||||
{
|
||||
// ALMA OUTSKIRTS
|
||||
gDynamicRestrictMilitia[SECTOR(12,7)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(13,7)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(14,7)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(15,7)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(12,8)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(15,8)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(12,9)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(15,9)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(12,10)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(13,10)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(14,10)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(15,10)] = true;
|
||||
|
||||
// ROAD SOUTH
|
||||
gDynamicRestrictMilitia[SECTOR(14,11)] = true;
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(CHITZENA) )
|
||||
{
|
||||
// CHITZENA OUTSKIRTS
|
||||
gDynamicRestrictMilitia[SECTOR(1,1)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(3,1)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(1,2)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(3,2)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(1,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(2,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(3,3)] = true;
|
||||
|
||||
// SAM SITE DEFENSE / ROAD SOUTH
|
||||
gDynamicRestrictMilitia[SECTOR(3,4)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(3,5)] = true;
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(CAMBRIA) )
|
||||
{
|
||||
// CAMBRIA OUTSKIRTS
|
||||
gDynamicRestrictMilitia[SECTOR(7,5)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(8,5)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(9,5)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(10,5)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(7,6)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(10,6)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(7,7)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(10,7)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(7,8)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(9,8)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(10,8)] = true;
|
||||
|
||||
// SAM SITE DEFENSE
|
||||
gDynamicRestrictMilitia[SECTOR(7,9)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(9,9)] = true;
|
||||
|
||||
// ROAD TO OMERTA
|
||||
gDynamicRestrictMilitia[SECTOR(9,2)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(9,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(9,4)] = true;
|
||||
|
||||
// CROSSROADS WEST
|
||||
gDynamicRestrictMilitia[SECTOR(6,7)] = true;
|
||||
|
||||
// ROAD TO ALMA
|
||||
gDynamicRestrictMilitia[SECTOR(11,7)] = true;
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(BALIME) )
|
||||
{
|
||||
// BALIME OUTSKIRTS
|
||||
gDynamicRestrictMilitia[SECTOR(10,11)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(11,11)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(12,11)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(13,11)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(10,12)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(13,12)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(10,13)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(13,13)] = true;
|
||||
|
||||
// WEST ROAD
|
||||
gDynamicRestrictMilitia[SECTOR(6,11)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(7,11)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(8,11)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(9,11)] = true;
|
||||
|
||||
// SOUTH ROAD
|
||||
gDynamicRestrictMilitia[SECTOR(8,14)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(9,14)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(10,14)] = true;
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(GRUMM) )
|
||||
{
|
||||
// GRUMM OUTSKIRTS
|
||||
gDynamicRestrictMilitia[SECTOR(1,6)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(2,6)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(3,6)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(3,7)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(4,7)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(4,8)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(3,9)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(4,9)] = true;
|
||||
|
||||
// ROAD NORTH
|
||||
gDynamicRestrictMilitia[SECTOR(3,5)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(3,4)] = true;
|
||||
|
||||
// ROAD EAST
|
||||
gDynamicRestrictMilitia[SECTOR(5,7)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(6,7)] = true;
|
||||
|
||||
// ROAD SOUTH
|
||||
gDynamicRestrictMilitia[SECTOR(2,10)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(3,10)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(2,11)] = true;
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(DRASSEN) && IsTownUnderCompleteControlByPlayer(CHITZENA) )
|
||||
{
|
||||
// ROAD EAST OF SAN-MONA
|
||||
gDynamicRestrictMilitia[SECTOR(7,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(8,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(9,3)] = true;
|
||||
|
||||
// SAN MONA
|
||||
gDynamicRestrictMilitia[SECTOR(5,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(6,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(4,4)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(5,4)] = true;
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(CAMBRIA) && ( IsTownUnderCompleteControlByPlayer(CHITZENA) || IsTownUnderCompleteControlByPlayer(DRASSEN) ) )
|
||||
{
|
||||
// ROAD TO SAN MONA
|
||||
gDynamicRestrictMilitia[SECTOR(7,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(8,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(9,3)] = true;
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(CAMBRIA) && ( IsTownUnderCompleteControlByPlayer(DRASSEN) || IsTownUnderCompleteControlByPlayer(CHITZENA) || IsTownUnderCompleteControlByPlayer(GRUMM) ) )
|
||||
{
|
||||
// ROAD SOUTH-EAST OF SAN MONA
|
||||
gDynamicRestrictMilitia[SECTOR(6,4)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(7,4)] = true;
|
||||
|
||||
// SAN MONA
|
||||
gDynamicRestrictMilitia[SECTOR(5,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(6,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(4,4)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(5,4)] = true;
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(ALMA) && ( IsTownUnderCompleteControlByPlayer(DRASSEN) || IsTownUnderCompleteControlByPlayer(CAMBRIA) ) )
|
||||
{
|
||||
// ROAD WEST OF ALMA
|
||||
gDynamicRestrictMilitia[SECTOR(11,7)] = true;
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(CHITZENA) && ( IsTownUnderCompleteControlByPlayer(DRASSEN) || IsTownUnderCompleteControlByPlayer(CAMBRIA) || IsTownUnderCompleteControlByPlayer(GRUMM) ) )
|
||||
{
|
||||
// SAN MONA
|
||||
gDynamicRestrictMilitia[SECTOR(5,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(6,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(4,4)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(5,4)] = true;
|
||||
|
||||
// ROAD TO SAN MONA
|
||||
gDynamicRestrictMilitia[SECTOR(7,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(8,3)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(9,3)] = true;
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(CAMBRIA) && IsTownUnderCompleteControlByPlayer(ALMA) )
|
||||
{
|
||||
// ROAD EAST OF CAMBRIA
|
||||
gDynamicRestrictMilitia[SECTOR(11,7)] = true;
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(CAMBRIA) && ( IsTownUnderCompleteControlByPlayer(BALIME) || IsTownUnderCompleteControlByPlayer(GRUMM) || IsTownUnderCompleteControlByPlayer(ALMA) ) )
|
||||
{
|
||||
// UPGRADED SAM-SITE DEFENSE FOR CAMBRIA
|
||||
gDynamicRestrictMilitia[SECTOR(7,10)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(8,10)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(9,10)] = true; // Tixa. Won't be accessible unless Minor Cities are allowed.
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(CAMBRIA) && IsTownUnderCompleteControlByPlayer(GRUMM) )
|
||||
{
|
||||
// ESTONI
|
||||
gDynamicRestrictMilitia[SECTOR(6,8)] = true;
|
||||
|
||||
// ESTONI MOUNTAIN GATE
|
||||
gDynamicRestrictMilitia[SECTOR(6,9)] = true;
|
||||
|
||||
// SOUTHEAST ROAD TO SAN MONA
|
||||
gDynamicRestrictMilitia[SECTOR(6,4)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(7,4)] = true;
|
||||
}
|
||||
|
||||
if ( IsTownUnderCompleteControlByPlayer(BALIME) && IsTownUnderCompleteControlByPlayer(GRUMM) && IsTownUnderCompleteControlByPlayer(CAMBRIA) )
|
||||
{
|
||||
// GRUMM-CAMBRIA-BALIME ROAD
|
||||
gDynamicRestrictMilitia[SECTOR(6,10)] = true;
|
||||
}
|
||||
|
||||
// CONTROL ALL TOWNS?
|
||||
if ( IsTownUnderCompleteControlByPlayer(BALIME) && IsTownUnderCompleteControlByPlayer(CAMBRIA) && IsTownUnderCompleteControlByPlayer(CHITZENA) && IsTownUnderCompleteControlByPlayer(DRASSEN) && IsTownUnderCompleteControlByPlayer(ALMA) && IsTownUnderCompleteControlByPlayer(GRUMM) )
|
||||
{
|
||||
// ROADS TO MEDUNA
|
||||
gDynamicRestrictMilitia[SECTOR(6,12)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(7,14)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(2,12)] = true;
|
||||
|
||||
// MEDUNA OUTSKIRTS
|
||||
gDynamicRestrictMilitia[SECTOR(2,13)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(3,13)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(4,13)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(5,13)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(6,13)] = true;
|
||||
gDynamicRestrictMilitia[SECTOR(6,14)] = true;
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2.7: This is a copy of an existing function that generates possible movement directions for militia.
|
||||
// Due to the widespread use of that function, I've decided to make a new one that calculates directions
|
||||
// when generating militia. This function checks for available space at the target location. It won't count green
|
||||
// or regular militia in this total, as they will be replaced by higher grade militia when added.
|
||||
|
||||
void GenerateDirectionInfosWithCapacityCheck( INT16 sMapX, INT16 sMapY, UINT8* uiDirNumber, UINT16 pMoveDir[4][3], BOOLEAN fWithCities, BOOLEAN fForBattle, BOOLEAN fOnlyCitySectors )
|
||||
{
|
||||
SECTORINFO *pSectorInfo;
|
||||
|
||||
*uiDirNumber = 0;
|
||||
|
||||
#ifdef DEBUG_SHOW_RATINGS
|
||||
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%ld,%ld-------------------", sMapX, sMapY );
|
||||
#endif
|
||||
|
||||
pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY - 1 ) ] );
|
||||
if(CheckStandardConditionsForDirection( sMapX, sMapY, sMapX, sMapY - 1, fWithCities, fForBattle, fOnlyCitySectors ) &&
|
||||
pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] < gGameExternalOptions.iMaxMilitiaPerSector )
|
||||
{
|
||||
pMoveDir[ *uiDirNumber ][0] = SECTOR( sMapX, sMapY - 1 );
|
||||
|
||||
if( fForBattle )
|
||||
pMoveDir[ *uiDirNumber ][1] = 0;
|
||||
else
|
||||
pMoveDir[ *uiDirNumber ][1] = CountDirectionRating( sMapX, sMapY, DIR_NORTH );
|
||||
|
||||
pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_NORTH;
|
||||
|
||||
#ifdef DEBUG_SHOW_RATINGS
|
||||
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]);
|
||||
#endif
|
||||
|
||||
++(*uiDirNumber);
|
||||
}
|
||||
pSectorInfo = &( SectorInfo[ SECTOR( sMapX - 1, sMapY ) ] );
|
||||
if(CheckStandardConditionsForDirection( sMapX, sMapY, sMapX - 1, sMapY, fWithCities, fForBattle, fOnlyCitySectors ) &&
|
||||
pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] < gGameExternalOptions.iMaxMilitiaPerSector)
|
||||
{
|
||||
pMoveDir[ *uiDirNumber ][0] = SECTOR( sMapX - 1, sMapY );
|
||||
|
||||
if( fForBattle )
|
||||
pMoveDir[ *uiDirNumber ][1] = 0;
|
||||
else
|
||||
pMoveDir[ *uiDirNumber ][1] = CountDirectionRating( sMapX, sMapY, DIR_WEST );
|
||||
|
||||
pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_WEST;
|
||||
|
||||
#ifdef DEBUG_SHOW_RATINGS
|
||||
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of west direction - %ld", pMoveDir[ *uiDirNumber ][1]);
|
||||
#endif
|
||||
|
||||
++(*uiDirNumber);
|
||||
}
|
||||
pSectorInfo = &( SectorInfo[ SECTOR( sMapX , sMapY + 1 ) ] );
|
||||
if(CheckStandardConditionsForDirection( sMapX, sMapY, sMapX, sMapY + 1, fWithCities, fForBattle, fOnlyCitySectors ) &&
|
||||
pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] < gGameExternalOptions.iMaxMilitiaPerSector )
|
||||
{
|
||||
pMoveDir[ *uiDirNumber ][0] = SECTOR( sMapX, sMapY + 1 );
|
||||
|
||||
if( fForBattle )
|
||||
pMoveDir[ *uiDirNumber ][1] = 0;
|
||||
else
|
||||
pMoveDir[ *uiDirNumber ][1] = CountDirectionRating( sMapX, sMapY, DIR_SOUTH );
|
||||
|
||||
pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_SOUTH;
|
||||
|
||||
#ifdef DEBUG_SHOW_RATINGS
|
||||
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of south direction - %ld", pMoveDir[ *uiDirNumber ][1]);
|
||||
#endif
|
||||
|
||||
++(*uiDirNumber);
|
||||
}
|
||||
pSectorInfo = &( SectorInfo[ SECTOR( sMapX + 1 , sMapY ) ] );
|
||||
if(CheckStandardConditionsForDirection( sMapX, sMapY, sMapX + 1, sMapY, fWithCities, fForBattle, fOnlyCitySectors ) &&
|
||||
pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] < gGameExternalOptions.iMaxMilitiaPerSector )
|
||||
{
|
||||
pMoveDir[ *uiDirNumber ][0] = SECTOR( sMapX + 1, sMapY );
|
||||
|
||||
if( fForBattle )
|
||||
pMoveDir[ *uiDirNumber ][1] = 0;
|
||||
else
|
||||
pMoveDir[ *uiDirNumber ][1] = CountDirectionRating( sMapX, sMapY, DIR_EAST );
|
||||
|
||||
pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_EAST;
|
||||
|
||||
#ifdef DEBUG_SHOW_RATINGS
|
||||
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of east direction - %ld", pMoveDir[ *uiDirNumber ][1]);
|
||||
#endif
|
||||
|
||||
++(*uiDirNumber);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,4 +22,16 @@ void GenerateDirectionInfos( INT16 sMapX, INT16 sMapY, UINT8* uiDirNumber, UINT1
|
||||
BOOLEAN MoveOneBestMilitiaMan(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY);
|
||||
void MilitiaFollowPlayer( INT16 sMapX, INT16 sMapY, INT16 sDMapX, INT16 sDMapY );
|
||||
|
||||
// HEADROCK HAM B1: Changes the allowed militia sectors
|
||||
extern void AdjustRoamingRestrictions();
|
||||
// HEADROCK HAM B1: Alternate array keeps track of dynamically unrestricted sectors
|
||||
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 );
|
||||
|
||||
// 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 );
|
||||
#endif
|
||||
@@ -40,6 +40,8 @@
|
||||
#include "finances.h"
|
||||
#include "GameSettings.h"
|
||||
#include "Quests.h"
|
||||
// HEADROCK HAM B1: Additional Include for Dynamic Roaming Restrictions
|
||||
#include "MilitiaSquads.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -510,6 +512,11 @@ void MercDailyUpdate()
|
||||
|
||||
// rebuild list for mapscreen
|
||||
ReBuildCharactersList( );
|
||||
// HEADROCK HAM B1: Run a function to redefine Roaming Militia Restrictions.
|
||||
if (gGameExternalOptions.bDynamicRestrictRoaming)
|
||||
{
|
||||
AdjustRoamingRestrictions();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -342,7 +342,8 @@ UINT32 GetMaxPeriodicRemovalFromMine( INT8 bMineIndex )
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
return( gMineStatus[ bMineIndex ].uiMaxRemovalRate );
|
||||
// HEADROCK HAM B1: Affected by external INI option.
|
||||
return(( gMineStatus[ bMineIndex ].uiMaxRemovalRate * gGameExternalOptions.iMineIncomePercentage ) / 100);
|
||||
}
|
||||
|
||||
|
||||
@@ -368,6 +369,8 @@ UINT32 GetMaxDailyRemovalFromMine( INT8 bMineIndex )
|
||||
// yes, reduce to value of mine
|
||||
uiAmtExtracted = gMineStatus[ bMineIndex ].uiRemainingOreSupply;
|
||||
}
|
||||
// HEADROCK HAM B1: Affected by external INI option.
|
||||
uiAmtExtracted = (uiAmtExtracted * gGameExternalOptions.iMineIncomePercentage) / 100;
|
||||
|
||||
return(uiAmtExtracted);
|
||||
}
|
||||
@@ -664,6 +667,8 @@ void HandleIncomeFromMines( void )
|
||||
// mine this mine
|
||||
iIncome += MineAMine( bCounter );
|
||||
}
|
||||
// HEADROCK HAM B1: Affected by external INI Option.
|
||||
iIncome = (iIncome * gGameExternalOptions.iMineIncomePercentage) / 100;
|
||||
if( iIncome )
|
||||
{
|
||||
AddTransactionToPlayersBook( DEPOSIT_FROM_SILVER_MINE, 0, GetWorldTotalMin( ), iIncome );
|
||||
@@ -690,7 +695,8 @@ UINT32 PredictDailyIncomeFromAMine( INT8 bMineIndex )
|
||||
}
|
||||
}
|
||||
|
||||
return( uiAmtExtracted );
|
||||
// HEADROCK HAM B1: Affected by external INI Option.
|
||||
return( ( uiAmtExtracted * gGameExternalOptions.iMineIncomePercentage ) / 100 ) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -720,6 +726,8 @@ INT32 CalcMaxPlayerIncomeFromMines( void )
|
||||
// add up the total
|
||||
iTotal += (MINE_PRODUCTION_NUMBER_OF_PERIODS * gMineStatus[bCounter].uiMaxRemovalRate);
|
||||
}
|
||||
// HEADROCK HAM B1: Affected by external INI Option.
|
||||
iTotal = (iTotal * gGameExternalOptions.iMineIncomePercentage) / 100;
|
||||
|
||||
return( iTotal );
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#include "history.h"
|
||||
#include "meanwhile.h"
|
||||
#include "Strategic Status.h"
|
||||
// HEADROCK HAM B1: Added include for Dynamic Roaming Militia
|
||||
#include "MilitiaSquads.h"
|
||||
#endif
|
||||
|
||||
// the max loyalty rating for any given town
|
||||
@@ -1814,6 +1816,11 @@ 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)
|
||||
{
|
||||
AdjustRoamingRestrictions();
|
||||
}
|
||||
|
||||
// set flag even for towns where you can't train militia, useful for knowing Orta/Tixa were previously controlled
|
||||
gTownLoyalty[ bTownId ].fLiberatedAlready = TRUE;
|
||||
|
||||
+239
-23
@@ -653,6 +653,8 @@ extern BOOLEAN gfDeductPoints;
|
||||
|
||||
extern void CleanUpStack( OBJECTTYPE * pObj, OBJECTTYPE * pCursorObj );
|
||||
extern void SwapGoggles(SOLDIERTYPE *pTeamSoldier);
|
||||
// HEADROCK HAM B2.8: Function to switch team's goggles uniformly
|
||||
extern void SwapGogglesUniformly(SOLDIERTYPE *pTeamSoldier, BOOLEAN fToNightVision);
|
||||
|
||||
UINT32 guiCHARLIST;
|
||||
UINT32 guiCHARINFO;
|
||||
@@ -1038,7 +1040,8 @@ void CheckForInventoryModeCancellation();
|
||||
void ChangeMapScreenMaskCursor( UINT16 usCursor );
|
||||
void CancelOrShortenPlottedPath( void );
|
||||
|
||||
BOOLEAN HandleCtrlOrShiftInTeamPanel( INT8 bCharNumber );
|
||||
// HEADROCK HAM B2.8: Added argument to enable multi-selecting entire squads
|
||||
BOOLEAN HandleCtrlOrShiftInTeamPanel( INT8 bCharNumber, BOOLEAN fFromRightClickAssignments );
|
||||
|
||||
INT32 GetContractExpiryTime( SOLDIERTYPE *pSoldier );
|
||||
|
||||
@@ -9674,7 +9677,8 @@ void TeamListInfoRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason )
|
||||
|
||||
if( gCharactersList[ iValue ].fValid == TRUE )
|
||||
{
|
||||
if ( HandleCtrlOrShiftInTeamPanel( ( INT8 ) iValue ) )
|
||||
// HEADROCK HAM B2.8: Added argument for multi-select entire squads
|
||||
if ( HandleCtrlOrShiftInTeamPanel( ( INT8 ) iValue , FALSE ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -9824,7 +9828,8 @@ void TeamListAssignmentRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason )
|
||||
|
||||
if( gCharactersList[ iValue ].fValid == TRUE )
|
||||
{
|
||||
if ( HandleCtrlOrShiftInTeamPanel( ( INT8 ) iValue ) )
|
||||
// HEADROCK HAM B2.8: Added argument for multi-select entire squads
|
||||
if ( HandleCtrlOrShiftInTeamPanel( ( INT8 ) iValue , FALSE ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -9892,8 +9897,87 @@ void TeamListAssignmentRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason )
|
||||
|
||||
if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP)
|
||||
{
|
||||
// HEADROCK HAM B2.8: Added argument for multi-select entire squads
|
||||
if ( HandleCtrlOrShiftInTeamPanel( ( INT8 ) iValue, TRUE ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// reset selected characters
|
||||
ResetAllSelectedCharacterModes( );
|
||||
// HEADROCK HAM B2.8: Right mouse button selects entire squad, if clicked on a squad-assigned character.
|
||||
// set to new info character...make sure is valid
|
||||
if( IsMapScreenHelpTextUp() )
|
||||
{
|
||||
// stop mapscreen text
|
||||
StopMapScreenHelpText( );
|
||||
return;
|
||||
}
|
||||
|
||||
if( gCharactersList[ iValue ].fValid == TRUE )
|
||||
{
|
||||
|
||||
ChangeSelectedInfoChar( ( INT8 ) iValue, TRUE );
|
||||
|
||||
pSoldier = &Menptr[ gCharactersList[ iValue ].usSolID ];
|
||||
|
||||
// highlight
|
||||
giDestHighLine = -1;
|
||||
|
||||
// reset character
|
||||
bSelectedAssignChar = -1;
|
||||
bSelectedDestChar = -1;
|
||||
bSelectedContractChar = -1;
|
||||
fPlotForHelicopter = FALSE;
|
||||
|
||||
// if not dead or POW, select his sector
|
||||
if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) )
|
||||
{
|
||||
ChangeSelectedMapSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
|
||||
}
|
||||
|
||||
// Select all characters in squad
|
||||
INT16 iCounter;
|
||||
|
||||
for( iCounter = 0; iCounter < CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
||||
{
|
||||
if( gCharactersList[ iCounter ].fValid == TRUE )
|
||||
{
|
||||
// if not already selected
|
||||
if( fSelectedListOfMercsForMapScreen[ iCounter ] == FALSE )
|
||||
{
|
||||
pSoldier = &( Menptr[ gCharactersList[ iCounter ].usSolID ] );
|
||||
|
||||
// if on a squad or in a vehicle
|
||||
if ( ( pSoldier->bAssignment < ON_DUTY ) || ( pSoldier->bAssignment == VEHICLE ) )
|
||||
{
|
||||
// and a member of that squad or vehicle is selected
|
||||
if ( AnyMercInSameSquadOrVehicleIsSelected( pSoldier ) )
|
||||
{
|
||||
// then also select this guy
|
||||
SetEntryInSelectedCharacterList( ( INT8 ) iCounter );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unhilight contract line
|
||||
giContractHighLine = -1;
|
||||
|
||||
// can't assign highlight line
|
||||
giAssignHighLine = -1;
|
||||
|
||||
// dirty team and map regions
|
||||
fTeamPanelDirty = TRUE;
|
||||
fMapPanelDirty = TRUE;
|
||||
//fMapScreenBottomDirty = TRUE;
|
||||
gfRenderPBInterface = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset selected characters
|
||||
ResetAllSelectedCharacterModes( );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9980,7 +10064,8 @@ void TeamListDestinationRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason )
|
||||
|
||||
if( gCharactersList[ iValue ].fValid == TRUE )
|
||||
{
|
||||
if ( HandleCtrlOrShiftInTeamPanel( ( INT8 ) iValue ) )
|
||||
// HEADROCK HAM B2.8: Added argument for multi-select entire squads
|
||||
if ( HandleCtrlOrShiftInTeamPanel( ( INT8 ) iValue , FALSE ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -10153,7 +10238,8 @@ void TeamListSleepRegionBtnCallBack( MOUSE_REGION *pRegion, INT32 iReason )
|
||||
|
||||
if( ( gCharactersList[ iValue ].fValid == TRUE ) )
|
||||
{
|
||||
if ( HandleCtrlOrShiftInTeamPanel( ( INT8 ) iValue ) )
|
||||
// HEADROCK HAM B2.8: Added argument for multi-select entire squads
|
||||
if ( HandleCtrlOrShiftInTeamPanel( ( INT8 ) iValue , FALSE ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -10171,6 +10257,8 @@ void TeamListSleepRegionBtnCallBack( MOUSE_REGION *pRegion, INT32 iReason )
|
||||
// try to wake him up
|
||||
if( SetMercAwake( pSoldier, TRUE, FALSE ) )
|
||||
{
|
||||
// HEADROCK HAM B2.8: New feature wakes all trainees/trainers automatically
|
||||
HandleTrainingWakeSynchronize( pSoldier );
|
||||
// propagate
|
||||
HandleSelectedMercsBeingPutAsleep( TRUE, TRUE );
|
||||
return;
|
||||
@@ -10185,6 +10273,8 @@ void TeamListSleepRegionBtnCallBack( MOUSE_REGION *pRegion, INT32 iReason )
|
||||
// try to put him to sleep
|
||||
if( SetMercAsleep( pSoldier, TRUE ) )
|
||||
{
|
||||
// HEADROCK HAM B2.8: New feature sends all trainees/trainers to sleep automatically
|
||||
HandleTrainingSleepSynchronize( pSoldier );
|
||||
// propagate
|
||||
HandleSelectedMercsBeingPutAsleep( FALSE, TRUE );
|
||||
return;
|
||||
@@ -13853,34 +13943,160 @@ void CancelOrShortenPlottedPath( void )
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN HandleCtrlOrShiftInTeamPanel( INT8 bCharNumber )
|
||||
BOOLEAN HandleCtrlOrShiftInTeamPanel( INT8 bCharNumber, BOOLEAN fFromRightClickAssignments )
|
||||
{
|
||||
// check if shift or ctrl held down, if so, set values in list
|
||||
if (_KeyDown(CTRL))
|
||||
// HEADROCK HAM B2.8: New condition based on new argument.
|
||||
if (fFromRightClickAssignments)
|
||||
{
|
||||
ToggleEntryInSelectedList( bCharNumber );
|
||||
if ( _KeyDown(CTRL) || _KeyDown(SHIFT) )
|
||||
{
|
||||
if ( fSelectedListOfMercsForMapScreen[ bCharNumber ] == FALSE )
|
||||
{
|
||||
SetEntryInSelectedCharacterList( bCharNumber );
|
||||
|
||||
fTeamPanelDirty = TRUE;
|
||||
fCharacterInfoPanelDirty = TRUE;
|
||||
INT16 iCounter;
|
||||
|
||||
return( TRUE);
|
||||
for( iCounter = 0; iCounter < CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
||||
{
|
||||
if( gCharactersList[ iCounter ].fValid == TRUE )
|
||||
{
|
||||
// if not already selected
|
||||
if( fSelectedListOfMercsForMapScreen[ iCounter ] == FALSE )
|
||||
{
|
||||
SOLDIERTYPE * pSelected = &( Menptr[ gCharactersList[ bCharNumber ].usSolID ] );
|
||||
SOLDIERTYPE * pSoldier = &( Menptr[ gCharactersList[ iCounter ].usSolID ] );
|
||||
|
||||
// if on a squad, or in a vehicle, or IS a vehicle
|
||||
if ( pSoldier->bAssignment == VEHICLE )
|
||||
{
|
||||
// and a member of that squad or vehicle is selected, or we are a vehicle
|
||||
if ( pSoldier->iVehicleId == pSelected->iVehicleId ||
|
||||
(pSelected->flags.uiStatusFlags & SOLDIER_VEHICLE && pSoldier->iVehicleId == pSelected->bVehicleID ) ||
|
||||
(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && pSelected->iVehicleId == pSoldier->bVehicleID ) )
|
||||
{
|
||||
// then also select this guy
|
||||
SetEntryInSelectedCharacterList( ( INT8 ) iCounter );
|
||||
}
|
||||
}
|
||||
|
||||
else if ( pSoldier->bAssignment == pSelected->bAssignment &&
|
||||
(pSoldier->bAssignment == TRAIN_TEAMMATE || pSoldier->bAssignment == TRAIN_BY_OTHER) &&
|
||||
pSoldier->sSectorX == pSelected->sSectorX &&
|
||||
pSoldier->sSectorY == pSelected->sSectorY &&
|
||||
pSoldier->sZLevel == pSelected->sZLevel )
|
||||
{
|
||||
// make sure only trainers/trainees of the same stat are selected together.
|
||||
if (pSoldier->bTrainStat == pSelected->bTrainStat)
|
||||
{
|
||||
SetEntryInSelectedCharacterList( ( INT8 ) iCounter );
|
||||
}
|
||||
}
|
||||
|
||||
else if ( pSoldier->bAssignment == pSelected->bAssignment &&
|
||||
pSoldier->sSectorX == pSelected->sSectorX &&
|
||||
pSoldier->sSectorY == pSelected->sSectorY &&
|
||||
pSoldier->sZLevel == pSelected->sZLevel )
|
||||
{
|
||||
SetEntryInSelectedCharacterList( ( INT8 ) iCounter );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Deselect entire group
|
||||
ResetEntryForSelectedList( bCharNumber );
|
||||
|
||||
INT16 iCounter;
|
||||
|
||||
for( iCounter = 0; iCounter < CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ )
|
||||
{
|
||||
if( gCharactersList[ iCounter ].fValid == TRUE )
|
||||
{
|
||||
// if not already selected
|
||||
if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE )
|
||||
{
|
||||
SOLDIERTYPE * pSelected = &( Menptr[ gCharactersList[ bCharNumber ].usSolID ] );
|
||||
SOLDIERTYPE * pSoldier = &( Menptr[ gCharactersList[ iCounter ].usSolID ] );
|
||||
|
||||
// if on a squad, or in a vehicle, or IS a vehicle
|
||||
if ( pSoldier->bAssignment == VEHICLE )
|
||||
{
|
||||
// and a member of that squad or vehicle is selected, or we are a vehicle
|
||||
if ( pSoldier->iVehicleId == pSelected->iVehicleId ||
|
||||
(pSelected->flags.uiStatusFlags & SOLDIER_VEHICLE && pSoldier->iVehicleId == pSelected->bVehicleID ) ||
|
||||
(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && pSelected->iVehicleId == pSoldier->bVehicleID ) )
|
||||
{
|
||||
// then also select this guy
|
||||
ResetEntryForSelectedList( ( INT8 ) iCounter );
|
||||
}
|
||||
}
|
||||
|
||||
else if ( pSoldier->bAssignment == pSelected->bAssignment &&
|
||||
(pSoldier->bAssignment == TRAIN_TEAMMATE || pSoldier->bAssignment == TRAIN_BY_OTHER) &&
|
||||
pSoldier->sSectorX == pSelected->sSectorX &&
|
||||
pSoldier->sSectorY == pSelected->sSectorY &&
|
||||
pSoldier->sZLevel == pSelected->sZLevel )
|
||||
{
|
||||
// make sure only trainers/trainees of the same stat are selected together.
|
||||
if (pSoldier->bTrainStat == pSelected->bTrainStat)
|
||||
{
|
||||
ResetEntryForSelectedList( ( INT8 ) iCounter );
|
||||
}
|
||||
}
|
||||
|
||||
else if ( pSoldier->bAssignment == pSelected->bAssignment &&
|
||||
pSoldier->sSectorX == pSelected->sSectorX &&
|
||||
pSoldier->sSectorY == pSelected->sSectorY &&
|
||||
pSoldier->sZLevel == pSelected->sZLevel )
|
||||
{
|
||||
ResetEntryForSelectedList( ( INT8 ) iCounter );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fTeamPanelDirty = TRUE;
|
||||
fCharacterInfoPanelDirty = TRUE;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
else if( _KeyDown(SHIFT) )
|
||||
else
|
||||
{
|
||||
// build a list from the bSelectedInfoChar To here, reset everyone
|
||||
|
||||
//empty the list
|
||||
ResetSelectedListForMapScreen( );
|
||||
// rebuild the list
|
||||
BuildSelectedListFromAToB( bSelectedInfoChar, bCharNumber );
|
||||
// check if shift or ctrl held down, if so, set values in list
|
||||
if (_KeyDown(CTRL))
|
||||
{
|
||||
ToggleEntryInSelectedList( bCharNumber );
|
||||
|
||||
fTeamPanelDirty = TRUE;
|
||||
fCharacterInfoPanelDirty = TRUE;
|
||||
fTeamPanelDirty = TRUE;
|
||||
fCharacterInfoPanelDirty = TRUE;
|
||||
|
||||
return( TRUE );
|
||||
return( TRUE);
|
||||
}
|
||||
else if( _KeyDown(SHIFT) )
|
||||
{
|
||||
// build a list from the bSelectedInfoChar To here, reset everyone
|
||||
|
||||
//empty the list
|
||||
ResetSelectedListForMapScreen( );
|
||||
// rebuild the list
|
||||
BuildSelectedListFromAToB( bSelectedInfoChar, bCharNumber );
|
||||
|
||||
fTeamPanelDirty = TRUE;
|
||||
fCharacterInfoPanelDirty = TRUE;
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#define MAX_TOWNS 50 //13 //50
|
||||
#define MAX_TOWN_SECTORS 260 //40 //260
|
||||
|
||||
// HEADROCK HAM B2.7: Moved here from Strategicmap.cpp to allow use by MilitiaSquads.cpp
|
||||
|
||||
extern BOOLEAN gfMilitiaAllowedInTown [ MAX_TOWNS ];
|
||||
// Sector name identifiers
|
||||
enum Towns
|
||||
{
|
||||
|
||||
@@ -69,6 +69,10 @@ typedef struct
|
||||
UINT16 ubItemStatus;
|
||||
UINT16 fromItem;
|
||||
INT32 flash;
|
||||
// HEADROCK HAM B2.5: Experimental bullet tracer info. If the new tracer system is activated, this flag tells
|
||||
// the bullet animation functions to create a lightpath for this bullet. This means now all bullets in a tracer
|
||||
// magazine will cause a lightshow (that's the intended result).
|
||||
BOOLEAN fTracer;
|
||||
} BULLET;
|
||||
|
||||
extern UINT32 guiNumBullets;
|
||||
|
||||
+103
-25
@@ -73,7 +73,11 @@ STR16 wDebugStatStrings[]={
|
||||
|
||||
// local prototypes
|
||||
UINT8 CalcImportantSectorControl( void );
|
||||
// HEADROCK HAM B1: New function to calculate how many important sectors there are in the game at all.
|
||||
UINT8 CalcTotalImportantSectors( void );
|
||||
UINT16 CountSurfaceSectorsVisited( void );
|
||||
// HAEDROCK HAM B1: New function to calculate how many sectors CAN be visited, on the surface.
|
||||
UINT16 TotalVisitableSurfaceSectors( void );
|
||||
|
||||
|
||||
|
||||
@@ -1076,30 +1080,58 @@ 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;
|
||||
// figure out how many subpoints this type of stat needs to change
|
||||
switch (ubStat)
|
||||
{
|
||||
// Attributes
|
||||
case HEALTHAMT:
|
||||
usSubpointsPerPoint = HEALTH_SUBPOINTS_TO_IMPROVE;
|
||||
break;
|
||||
case AGILAMT:
|
||||
usSubpointsPerPoint = AGILITY_SUBPOINTS_TO_IMPROVE;
|
||||
break;
|
||||
case DEXTAMT:
|
||||
usSubpointsPerPoint = DEXTERITY_SUBPOINTS_TO_IMPROVE;
|
||||
break;
|
||||
case WISDOMAMT:
|
||||
case STRAMT:
|
||||
// attributes
|
||||
usSubpointsPerPoint = ATTRIBS_SUBPOINTS_TO_IMPROVE;
|
||||
break;
|
||||
|
||||
usSubpointsPerPoint = WISDOM_SUBPOINTS_TO_IMPROVE;
|
||||
break;
|
||||
case STRAMT:
|
||||
usSubpointsPerPoint = STRENGTH_SUBPOINTS_TO_IMPROVE;
|
||||
break;
|
||||
|
||||
// Skills
|
||||
case MEDICALAMT:
|
||||
usSubpointsPerPoint = MEDICAL_SUBPOINTS_TO_IMPROVE;
|
||||
break;
|
||||
case EXPLODEAMT:
|
||||
usSubpointsPerPoint = EXPLOSIVES_SUBPOINTS_TO_IMPROVE;
|
||||
break;
|
||||
case MECHANAMT:
|
||||
usSubpointsPerPoint = MECHANICAL_SUBPOINTS_TO_IMPROVE;
|
||||
break;
|
||||
case MARKAMT:
|
||||
case LDRAMT:
|
||||
// skills
|
||||
usSubpointsPerPoint = SKILLS_SUBPOINTS_TO_IMPROVE;
|
||||
break;
|
||||
usSubpointsPerPoint = MARKSMANSHIP_SUBPOINTS_TO_IMPROVE;
|
||||
break;
|
||||
case LDRAMT:
|
||||
usSubpointsPerPoint = LEADERSHIP_SUBPOINTS_TO_IMPROVE;
|
||||
break;
|
||||
|
||||
// Experience
|
||||
case EXPERAMT:
|
||||
usSubpointsPerPoint = LEVEL_SUBPOINTS_TO_IMPROVE * bExpLevel;
|
||||
break;
|
||||
usSubpointsPerPoint = LEVEL_SUBPOINTS_TO_IMPROVE * bExpLevel;
|
||||
break;
|
||||
|
||||
default:
|
||||
// BETA message
|
||||
@@ -1267,7 +1299,7 @@ UINT8 CurrentPlayerProgressPercentage(void)
|
||||
{
|
||||
UINT32 uiCurrentIncome;
|
||||
UINT32 uiPossibleIncome;
|
||||
UINT8 ubCurrentProgress = gGameExternalOptions.ubGameProgressIncrement;
|
||||
UINT8 ubCurrentProgress;
|
||||
UINT8 ubKillsPerPoint;
|
||||
UINT16 usKillsProgress;
|
||||
UINT16 usControlProgress;
|
||||
@@ -1332,7 +1364,12 @@ UINT8 CurrentPlayerProgressPercentage(void)
|
||||
|
||||
|
||||
// 19 sectors in mining towns + 3 wilderness SAMs each count double. Balime & Meduna are extra and not required
|
||||
usControlProgress = CalcImportantSectorControl();
|
||||
// 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 = gGameExternalOptions.ubGameProgressPortionControl;
|
||||
@@ -1343,21 +1380,14 @@ UINT8 CurrentPlayerProgressPercentage(void)
|
||||
|
||||
// WDS: Adding more ways to progress in the game
|
||||
// Get a ratio of sectors visited to the total number of sectors
|
||||
usVisitProgress = CountSurfaceSectorsVisited() * gGameExternalOptions.ubGameProgressPortionVisited / ((MAP_WORLD_X - 2) * (MAP_WORLD_Y - 2) - 56 /* note: should be calculated */);
|
||||
// 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();
|
||||
|
||||
// add visit progress
|
||||
// add control progress
|
||||
ubCurrentProgress += usVisitProgress;
|
||||
|
||||
// Add increment to progress
|
||||
ubCurrentProgress += gGameExternalOptions.ubGameProgressIncrement;
|
||||
|
||||
if (ubCurrentProgress < gGameExternalOptions.ubGameProgressMinimum)
|
||||
return gGameExternalOptions.ubGameProgressMinimum;
|
||||
|
||||
if (ubCurrentProgress < 100)
|
||||
return ubCurrentProgress;
|
||||
else
|
||||
return 100;
|
||||
return(ubCurrentProgress);
|
||||
}
|
||||
|
||||
|
||||
@@ -1607,6 +1637,36 @@ UINT8 CalcImportantSectorControl( void )
|
||||
return( ubSectorControlPts );
|
||||
}
|
||||
|
||||
// HEADROCK HAM B1: function to calculate how many "important sectors" there actually are in the game. This is
|
||||
// used to fix the weight of strategic control importance on game progress, which was until now not really
|
||||
// moddable.
|
||||
|
||||
UINT8 CalcTotalImportantSectors( void )
|
||||
{
|
||||
UINT8 ubMapX, ubMapY;
|
||||
UINT8 ubSectorControlPts = 0;
|
||||
|
||||
|
||||
for ( ubMapX = 1; ubMapX < MAP_WORLD_X - 1; ubMapX++ )
|
||||
{
|
||||
for ( ubMapY = 1; ubMapY < MAP_WORLD_Y - 1; ubMapY++ )
|
||||
{
|
||||
// towns where militia can be trained and SAM sites are important sectors
|
||||
if ( MilitiaTrainingAllowedInSector( ubMapX, ubMapY, 0 ) )
|
||||
{
|
||||
ubSectorControlPts++;
|
||||
|
||||
// SAM sites count double - they have no income, but have significant air control value
|
||||
if ( IsThisSectorASAMSector( ubMapX, ubMapY, 0 ) )
|
||||
{
|
||||
ubSectorControlPts++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return( ubSectorControlPts );
|
||||
}
|
||||
|
||||
// WDS: Adding more ways to progress in the game
|
||||
// Count how many surface sectors the player has visited
|
||||
@@ -1627,6 +1687,24 @@ UINT16 CountSurfaceSectorsVisited( void )
|
||||
|
||||
return( ubSectorsVisited );
|
||||
}
|
||||
// HEADROCK: Count number of VISITABLE sectors
|
||||
UINT16 TotalVisitableSurfaceSectors( void )
|
||||
{
|
||||
UINT8 ubMapX, ubMapY;
|
||||
UINT16 ubVisitableSectors = 0;
|
||||
|
||||
|
||||
for ( ubMapX = 1; ubMapX < MAP_WORLD_X - 1; ubMapX++ )
|
||||
{
|
||||
for ( ubMapY = 1; ubMapY < MAP_WORLD_Y - 1; ubMapY++ )
|
||||
{
|
||||
if( SectorInfo[ SECTOR(ubMapX,ubMapY) ].ubTraversability[ THROUGH_STRATEGIC_MOVE ] != GROUNDBARRIER && SectorInfo[ SECTOR(ubMapX,ubMapY) ].ubTraversability[ THROUGH_STRATEGIC_MOVE ] != EDGEOFWORLD )
|
||||
++ubVisitableSectors;
|
||||
}
|
||||
}
|
||||
|
||||
return( ubVisitableSectors );
|
||||
}
|
||||
|
||||
void MERCMercWentUpALevelSendEmail( UINT8 ubMercMercIdValue )
|
||||
{
|
||||
|
||||
+7
-3
@@ -25,9 +25,13 @@
|
||||
#define MAX_STAT_VALUE 100 // for stats and skills
|
||||
#define MAXEXPLEVEL 10 // maximum merc experience level
|
||||
|
||||
#define SKILLS_SUBPOINTS_TO_IMPROVE 25
|
||||
#define ATTRIBS_SUBPOINTS_TO_IMPROVE 50
|
||||
#define LEVEL_SUBPOINTS_TO_IMPROVE 350 // per current level! (Can't go over 6500, 10x must fit in USHORT!)
|
||||
// HEADROCK HAM B2.7 : Externalizing these (changed from #define)
|
||||
//#define SKILLS_SUBPOINTS_TO_IMPROVE 25
|
||||
//#define ATTRIBS_SUBPOINTS_TO_IMPROVE 50
|
||||
//#define LEVEL_SUBPOINTS_TO_IMPROVE 350 // per current level! (Can't go over 6500, 10x must fit in USHORT!)
|
||||
extern UINT16 SKILLS_SUBPOINTS_TO_IMPROVE;
|
||||
extern UINT16 ATTRIBS_SUBPOINTS_TO_IMPROVE;
|
||||
extern UINT16 LEVEL_SUBPOINTS_TO_IMPROVE;
|
||||
|
||||
#define WORKIMPROVERATE 2 // increase to make working mercs improve more
|
||||
#define TRAINIMPROVERATE 2 // increase to make training mercs improve more
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "Text.h"
|
||||
#include "strategicmap.h"
|
||||
#include "Render Fun.h"
|
||||
// HEADROCK HAM B2.7: Allow calling a CTH approximation function for the CTH display ("F" key)
|
||||
#include "UI Cursors.h"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -635,7 +637,12 @@ void DisplayRangeToTarget( SOLDIERTYPE *pSoldier, INT16 sTargetGridNo )
|
||||
//AXP 30.03.2007: Fix CtH calculation for first shot after changing aim level (roof/ground)
|
||||
INT8 bTempTargetLevel = pSoldier->bTargetLevel;
|
||||
pSoldier->bTargetLevel = (INT8)gsInterfaceLevel;
|
||||
uiHitChance = CalcChanceToHitGun( pSoldier, sTargetGridNo, (pSoldier->aiData.bShownAimTime ), pSoldier->bAimShotLocation );
|
||||
uiHitChance = CalcChanceToHitGun( pSoldier, sTargetGridNo, (INT8)(pSoldier->aiData.bShownAimTime ), pSoldier->bAimShotLocation );
|
||||
// HEADROCK HAM B2.7: CTH approximation?
|
||||
if (gGameExternalOptions.fApproximateCTH)
|
||||
{
|
||||
uiHitChance = ChanceToHitApproximation( pSoldier, uiHitChance );
|
||||
}
|
||||
pSoldier->bTargetLevel = bTempTargetLevel;
|
||||
|
||||
swprintf( zOutputString, zNewTacticalMessages[ TCTL_MSG__GUN_RANGE_AND_CTH ], Weapon[ pSoldier->inv[HANDPOS].usItem ].usRange / 10, uiHitChance );
|
||||
|
||||
@@ -230,7 +230,11 @@ INT16 gsTreeRevealYPos;
|
||||
|
||||
// taken out of header to remove multiple symbol definitions (jonathanl)
|
||||
BOOLEAN gfUICtHBar;
|
||||
UINT8 gbCtH;
|
||||
// HEADROCK HAM B1/2: Created an array to hold CTH of different bullets for Burst/Auto CTH Bar.
|
||||
UINT8 gbCtH[ 10 ];
|
||||
UINT8 gbCtHBurstCount;
|
||||
// HEADROCK HAM B2: This value tracks whether Autofire mode is selected. This value may be redundant... not sure.
|
||||
BOOLEAN gbCtHAutoFire;
|
||||
UINT16 gsTotalBulletCount;
|
||||
UINT16 gsBulletCount;
|
||||
BOOLEAN gTintBulletCounts;
|
||||
@@ -514,6 +518,8 @@ UINT32 HandleTacticalUI( void )
|
||||
gTintBulletCounts = FALSE;
|
||||
gfUIAutofireBulletCount = FALSE;
|
||||
gfUICtHBar = FALSE;
|
||||
// HEADROCK HAM B2: tells the cursor-drawing function to draw two CTH bars (for autofire).
|
||||
gbCtHAutoFire = FALSE;
|
||||
|
||||
// Set old event value
|
||||
guiOldEvent = uiNewEvent = guiCurrentEvent;
|
||||
|
||||
@@ -220,7 +220,11 @@ extern BOOLEAN gTintBulletCounts;
|
||||
extern BOOLEAN gfUIAutofireBulletCount;
|
||||
|
||||
extern BOOLEAN gfUICtHBar;
|
||||
extern UINT8 gbCtH;
|
||||
// HEADROCK HAM B1/2: Multiple-bullet CTH bar array (replaces old single integer)
|
||||
extern UINT8 gbCtH[ 10 ];
|
||||
extern UINT8 gbCtHBurstCount;
|
||||
// HEADROCK HAM B2: Track autofire on/off
|
||||
extern BOOLEAN gbCtHAutoFire;
|
||||
|
||||
extern CHAR16 gzIntTileLocation[ 20 ];
|
||||
extern BOOLEAN gfUIIntTileLocation;
|
||||
|
||||
@@ -2241,7 +2241,8 @@ else
|
||||
|
||||
// only enemy soldiers use auto-drop system!
|
||||
// don't use the auto-drop system in auto-resolve: player won't see what's being used & enemies will often win & keep'em
|
||||
if ( SOLDIER_CLASS_ENEMY( bSoldierClass ) && !IsAutoResolveActive() )
|
||||
// HEADROCK HAM B2.8: Militia now drop all their equipment... IF not killed by player (see TurnSoldierIntoCorpse() )
|
||||
if ( (SOLDIER_CLASS_ENEMY( bSoldierClass ) || ( gGameExternalOptions.ubMilitiaDropEquipment > 0 && SOLDIER_CLASS_MILITIA( bSoldierClass ) )) && !IsAutoResolveActive() )
|
||||
{
|
||||
// SPECIAL handling for weapons: we'll always drop a weapon type that has never been dropped before
|
||||
for( i = 0; i < pp->Inv.size(); i++ )
|
||||
|
||||
@@ -7102,6 +7102,9 @@ INT16 GetBurstToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance )
|
||||
bonus += Item[pObj->usItem].bipod;
|
||||
|
||||
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 )
|
||||
bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].bursttohitbonus ;
|
||||
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
|
||||
@@ -7228,6 +7231,10 @@ INT16 GetAutoToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance )
|
||||
|
||||
bonus += BonusReduceMore( Item[pObj->usItem].autofiretohitbonus, (*pObj)[0]->data.objectStatus );
|
||||
|
||||
// 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 )
|
||||
bonus += Item[(*pObj)[0]->data.gun.usGunAmmoItem].autofiretohitbonus ;
|
||||
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) {
|
||||
@@ -8491,6 +8498,88 @@ UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier)
|
||||
float iScopeBonus = 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)
|
||||
{
|
||||
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;
|
||||
maxAimWithoutBipod = 4;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
@@ -8506,6 +8595,7 @@ UINT8 AllowedAimingLevels(SOLDIERTYPE * pSoldier)
|
||||
if ( iScopeBonus >= ( (float)gGameExternalOptions.ubStraightSightRange * 0.6) ) // >= 60% of sight range (~9 tiles by default)
|
||||
{
|
||||
aimLevels += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+46
-2
@@ -3669,6 +3669,24 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
|
||||
usBulletFlags |= BULLET_FLAG_FLAME;
|
||||
ubSpreadIndex = 2;
|
||||
}
|
||||
// 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)
|
||||
&& AmmoTypes[ pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType ].tracerEffect )
|
||||
{
|
||||
UINT16 iBulletsLeft, iBulletsPerTracer;
|
||||
iBulletsPerTracer = gGameExternalOptions.iNumBulletsPerTracer;
|
||||
iBulletsLeft = pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunShotsLeft + pFirer->bDoBurst;
|
||||
|
||||
if ((((iBulletsLeft - (pFirer->bDoBurst - 1)) / iBulletsPerTracer) - ((iBulletsLeft - pFirer->bDoBurst) / iBulletsPerTracer)) == 1)
|
||||
{
|
||||
fTracer = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fTracer = FALSE;
|
||||
}
|
||||
}
|
||||
else if ( AmmoTypes[ pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType ].tracerEffect && (pFirer->bDoBurst || gGameSettings.fOptions[ TOPTION_TRACERS_FOR_SINGLE_FIRE ]) )
|
||||
{
|
||||
//usBulletFlags |= BULLET_FLAG_TRACER;
|
||||
@@ -3817,6 +3835,26 @@ INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOA
|
||||
// this distance limit only applies in a "hard" sense to fake bullets for chance-to-get-through,
|
||||
// but is used for determining structure hits by the regular code
|
||||
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)
|
||||
&& AmmoTypes[ pFirer->inv[pFirer->ubAttackingHand][0]->data.gun.ubGunAmmoType ].tracerEffect )
|
||||
{
|
||||
UINT16 iBulletsLeft, iBulletsPerTracer;
|
||||
iBulletsPerTracer = gGameExternalOptions.iNumBulletsPerTracer;
|
||||
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
|
||||
// a tracer magazine (INI-settable).
|
||||
if ((((iBulletsLeft - (pFirer->bDoBurst - 1)) / iBulletsPerTracer) - ((iBulletsLeft - pFirer->bDoBurst) / iBulletsPerTracer)) == 1)
|
||||
{
|
||||
pBullet->fTracer = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBullet->fTracer = FALSE;
|
||||
}
|
||||
}
|
||||
if (fFake)
|
||||
{
|
||||
bCTGT = FireBullet( pFirer, pBullet, TRUE );
|
||||
@@ -4366,7 +4404,10 @@ void MoveBullet( INT32 iBullet )
|
||||
}
|
||||
}
|
||||
|
||||
if (( pBullet->usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT /*| BULLET_FLAG_TRACER*/ ) ) || fTracer == TRUE)
|
||||
// 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)))
|
||||
{
|
||||
INT8 bStepsPerMove = STEPS_FOR_BULLET_MOVE_TRAILS;
|
||||
|
||||
@@ -4653,7 +4694,10 @@ void MoveBullet( INT32 iBullet )
|
||||
pBullet->iCurrCubesZ = CONVERT_HEIGHTUNITS_TO_INDEX( FIXEDPT_TO_INT32( pBullet->qCurrZ ) );
|
||||
pBullet->iLoop++;
|
||||
|
||||
if (( pBullet->usFlags & ( BULLET_FLAG_MISSILE | BULLET_FLAG_SMALL_MISSILE | BULLET_FLAG_TANK_CANNON | BULLET_FLAG_FLAME | BULLET_FLAG_CREATURE_SPIT /*| BULLET_FLAG_TRACER */) ) || fTracer == TRUE)
|
||||
// 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)))
|
||||
{
|
||||
INT8 bStepsPerMove = STEPS_FOR_BULLET_MOVE_TRAILS;
|
||||
|
||||
|
||||
+158
-15
@@ -7206,12 +7206,24 @@ INT8 CalcSuppressionTolerance( SOLDIERTYPE * pSoldier )
|
||||
|
||||
void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// HEADROCK HAM B2: This entire function has been completely revamped.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// External options.
|
||||
UINT8 MAX_APS_SUPPRESSED = gGameExternalOptions.iMaxSuppressionAPLossPerAttack;
|
||||
UINT8 MAX_APS_SUPPRESSED_TOTAL = gGameExternalOptions.iMaxSuppressionAPLossPerTurn;
|
||||
INT8 SUPPRESSION_AP_LIMIT = gGameExternalOptions.iMinAPLimitFromSuppression;
|
||||
INT8 MAXIMUM_SUPPRESSION_SHOCK = gGameExternalOptions.iMaxSuppressionShock;
|
||||
INT8 bTolerance;
|
||||
INT16 sClosestOpponent, sClosestOppLoc;
|
||||
UINT8 ubPointsLost, ubTotalPointsLost, ubNewStance;
|
||||
UINT32 uiLoop;
|
||||
UINT8 ubLoop2;
|
||||
UINT16 uiLoop3;
|
||||
// Flag to determine if the target is cowering (if allowed)
|
||||
BOOLEAN fCower;
|
||||
SOLDIERTYPE * pSoldier;
|
||||
|
||||
for (uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++)
|
||||
@@ -7226,7 +7238,14 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
|
||||
|
||||
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
|
||||
ubPointsLost = (UINT8)( (FLOAT)((pSoldier->ubSuppressionPoints * APBPConstants[AP_SUPPRESSION_MOD]) / (bTolerance + 6)) * 2 + 1 ) / 2;
|
||||
// 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).
|
||||
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;
|
||||
|
||||
// reduce loss of APs based on stance
|
||||
// ATE: Taken out because we can possibly supress ourselves...
|
||||
@@ -7243,37 +7262,125 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
|
||||
//}
|
||||
|
||||
// cap the # of APs we can lose
|
||||
if (ubPointsLost > APBPConstants[AP_MAX_SUPPRESSED])
|
||||
// HEADROCK HAM B2: This now reads an external value. 0 means no limit.
|
||||
if (MAX_APS_SUPPRESSED > 0)
|
||||
{
|
||||
ubPointsLost = (UINT8)APBPConstants[AP_MAX_SUPPRESSED];
|
||||
if (ubPointsLost > APBPConstants[AP_MAX_SUPPRESSED])
|
||||
{
|
||||
ubPointsLost = APBPConstants[AP_MAX_SUPPRESSED];
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2: This makes sure that we never lose more APs than we're allowed per turn,
|
||||
if (MAX_APS_SUPPRESSED_TOTAL > 0)
|
||||
{
|
||||
if (pSoldier->ubAPsLostToSuppression + ubPointsLost > MAX_APS_SUPPRESSED_TOTAL)
|
||||
{
|
||||
ubPointsLost = MAX_APS_SUPPRESSED_TOTAL - pSoldier->ubAPsLostToSuppression;
|
||||
}
|
||||
}
|
||||
// Keeps a number for later reference
|
||||
ubTotalPointsLost = ubPointsLost;
|
||||
|
||||
// Subtract off the APs lost before this point to find out how many points are lost now
|
||||
// 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"));
|
||||
// morale modifier
|
||||
if (ubTotalPointsLost / 2 > pSoldier->ubAPsLostToSuppression / 2)
|
||||
|
||||
// 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)
|
||||
{
|
||||
//CHRISL: This should dynamically adjust the number of times we run the morale loop based on AP_MAXIMUM
|
||||
uiLoop3 = (((ubTotalPointsLost / 2) - (pSoldier->ubAPsLostToSuppression / 2)) * APBPConstants[AP_MAXIMUM]) / 100;
|
||||
for ( ubLoop2 = 0; ubLoop2 < uiLoop3; ubLoop2++ )
|
||||
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;
|
||||
|
||||
if (bShockValue < 0)
|
||||
bShockValue = 0;
|
||||
if (bShockLimit < 0)
|
||||
bShockLimit = 0;
|
||||
|
||||
// use external value to determine how effective SHOCK really is.
|
||||
bShockValue = (bShockValue * gGameExternalOptions.iSuppressionShockEffectiveness) / 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.
|
||||
|
||||
if ( pSoldier->aiData.bShock + bShockValue <= bShockLimit )
|
||||
{
|
||||
// Shock limit not yet breached. Add shock to character.
|
||||
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;
|
||||
}
|
||||
// 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.
|
||||
|
||||
fCower = false;
|
||||
if ( gGameExternalOptions.fSuppressionShock && gGameExternalOptions.iAimPenaltyPerTargetShock > 0 )
|
||||
{
|
||||
if (pSoldier->aiData.bShock >= bTolerance)
|
||||
{ fCower = true; }
|
||||
}
|
||||
|
||||
// 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.
|
||||
if (gGameExternalOptions.iAPLostPerMoraleDrop > 0 && ubPointsLost > 0)
|
||||
{
|
||||
for ( ubLoop2 = 0; ubLoop2 < (ubPointsLost / gGameExternalOptions.iAPLostPerMoraleDrop); ubLoop2++ )
|
||||
{
|
||||
HandleMoraleEvent( pSoldier, MORALE_SUPPRESSED, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ubPointsLost -= pSoldier->ubAPsLostToSuppression;
|
||||
ubNewStance = 0;
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: check for reaction"));
|
||||
// merc may get to react
|
||||
if ( pSoldier->ubSuppressionPoints >= ( 130 / (6 + bTolerance) ) )
|
||||
// Headrock: apply suppression effectiveness percentage to this value.
|
||||
if ( (pSoldier->ubSuppressionPoints * gGameExternalOptions.iSuppressionEffectiveness) / 100 >= ( 130 / (6 + bTolerance) ) || fCower )
|
||||
{
|
||||
// merc gets to use APs to react!
|
||||
switch (gAnimControl[ pSoldier->usAnimState ].ubEndHeight)
|
||||
@@ -7285,7 +7392,8 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
|
||||
if (ubTotalPointsLost >= APBPConstants[AP_PRONE] && IsValidStance( pSoldier, ANIM_PRONE ) )
|
||||
{
|
||||
sClosestOpponent = ClosestKnownOpponent( pSoldier, &sClosestOppLoc, NULL );
|
||||
if (sClosestOpponent == NOWHERE || SpacesAway( pSoldier->sGridNo, sClosestOppLoc ) > 8)
|
||||
// HEADROCK: Added cowering.
|
||||
if (sClosestOpponent == NOWHERE || SpacesAway( pSoldier->sGridNo, sClosestOppLoc ) > 8 || fCower)
|
||||
{
|
||||
if (ubPointsLost < APBPConstants[AP_PRONE])
|
||||
{
|
||||
@@ -7311,7 +7419,8 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
|
||||
else if (ubTotalPointsLost >= (APBPConstants[AP_CROUCH] + APBPConstants[AP_PRONE]) && ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight != ANIM_PRONE ) && IsValidStance( pSoldier, ANIM_PRONE ) )
|
||||
{
|
||||
sClosestOpponent = ClosestKnownOpponent( pSoldier, &sClosestOppLoc, NULL );
|
||||
if ( sClosestOpponent == NOWHERE || SpacesAway( pSoldier->sGridNo, sClosestOppLoc ) > 8 )
|
||||
// HEADROCK: Added cowering.
|
||||
if ( sClosestOpponent == NOWHERE || SpacesAway( pSoldier->sGridNo, sClosestOppLoc ) > 8 ||fCower )
|
||||
{
|
||||
if ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_STAND )
|
||||
{
|
||||
@@ -7341,7 +7450,18 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: reduce action points"));
|
||||
// Reduce action points!
|
||||
pSoldier->bActionPoints -= ubPointsLost;
|
||||
// HEADROCK HAM Beta 2.2: Enforce a minimum limit via INI.
|
||||
if (pSoldier->bActionPoints - ubPointsLost < gGameExternalOptions.iMinAPLimitFromSuppression )
|
||||
{
|
||||
pSoldier->bActionPoints = gGameExternalOptions.iMinAPLimitFromSuppression;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSoldier->bActionPoints -= ubPointsLost;
|
||||
}
|
||||
// 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;
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleSuppressionFire: check for quote"));
|
||||
@@ -7404,6 +7524,18 @@ 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;
|
||||
}
|
||||
|
||||
} // end of examining one soldier
|
||||
} // end of loop
|
||||
|
||||
@@ -7988,6 +8120,17 @@ 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)
|
||||
|
||||
@@ -316,6 +316,8 @@ void ResetAllMercSpeeds( );
|
||||
BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLEAN fInitialMove, UINT16 usAnimState );
|
||||
|
||||
SOLDIERTYPE * ReduceAttackBusyCount( );
|
||||
// HEADROCK HAM B2.6: Made this public so it can be used elsewhere.
|
||||
INT8 CalcSuppressionTolerance( SOLDIERTYPE * pSoldier );
|
||||
|
||||
void CommonEnterCombatModeCode( );
|
||||
|
||||
|
||||
+37
-1
@@ -1122,7 +1122,43 @@ INT16 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAddTur
|
||||
}
|
||||
else
|
||||
{
|
||||
sAPCost += (bAimTime*APBPConstants[AP_CLICK_AIM]);
|
||||
if (gGameExternalOptions.fIncreasedAimingCost )
|
||||
{
|
||||
// HEADROCK HAM B2.6: Changed the number of APs to attack when aiming.
|
||||
if (bAimTime > 0)
|
||||
{
|
||||
// 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;
|
||||
|
||||
// Add regular aim time for the first 4 aiming actions.
|
||||
sAPCost += __min(bAimTime,4);
|
||||
|
||||
// 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)
|
||||
{
|
||||
sAPCost += 1;
|
||||
}
|
||||
// Add 2 APs for each aiming point between 5 and 6
|
||||
if (bAimTime > 4)
|
||||
{
|
||||
sAPCost += __min(((bAimTime - 4) * 2), 4);
|
||||
}
|
||||
// Add 3 APs for each aiming point beyond 6.
|
||||
if (bAimTime > 6)
|
||||
{
|
||||
sAPCost += (bAimTime - 6) * 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sAPCost += bAimTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -932,9 +932,12 @@ BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLE
|
||||
if ( !(Item[ pObj->usItem ].defaultundroppable ) )
|
||||
{
|
||||
ReduceAmmoDroppedByNonPlayerSoldiers( pSoldier, cnt );
|
||||
//if this soldier was an enemy
|
||||
// Kaiden: Added from UB's reveal all items after combat feature!
|
||||
if( pSoldier->bTeam == ENEMY_TEAM )
|
||||
//if this soldier was an enemy
|
||||
// Kaiden: Added from UB's reveal all items after combat feature!
|
||||
// HEADROCK HAM B2.8: Now also reveals equipment dropped by militia, if requirement is met.
|
||||
if( pSoldier->bTeam == ENEMY_TEAM ||
|
||||
( gGameExternalOptions.ubMilitiaDropEquipment == 2 && pSoldier->bTeam == MILITIA_TEAM ) ||
|
||||
( gGameExternalOptions.ubMilitiaDropEquipment == 1 && pSoldier->bTeam == MILITIA_TEAM && Menptr[ pSoldier->ubAttackerID ].bTeam != OUR_TEAM ))
|
||||
{
|
||||
//add a flag to the item so when all enemies are killed, we can run through and reveal all the enemies items
|
||||
usItemFlags |= WORLD_ITEM_DROPPED_FROM_ENEMY;
|
||||
@@ -946,7 +949,12 @@ BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLE
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2.8: Militia will drop items only if allowed.
|
||||
if (!(gGameExternalOptions.ubMilitiaDropEquipment == 0 && pSoldier->bTeam == MILITIA_TEAM ) &&
|
||||
!(gGameExternalOptions.ubMilitiaDropEquipment == 1 && pSoldier->bTeam == MILITIA_TEAM && Menptr[ pSoldier->ubAttackerID ].bTeam == OUR_TEAM ))
|
||||
{
|
||||
AddItemToPool( pSoldier->sGridNo, pObj, bVisible , pSoldier->pathing.bLevel, usItemFlags, -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1849,8 +1849,9 @@ INT16 SOLDIERTYPE::CalcActionPoints( void )
|
||||
ubPoints = DynamicAdjustAPConstants(ubPoints, ubPoints);
|
||||
|
||||
// If resulting APs are below our permitted minimum, raise them to it!
|
||||
if (ubPoints < APBPConstants[AP_MINIMUM])
|
||||
ubPoints = APBPConstants[AP_MINIMUM];
|
||||
// HEADROCK: Enforce new minimums due to suppression. I should've done this neater though.
|
||||
if (ubPoints < gGameExternalOptions.iMinAPLimitFromSuppression)
|
||||
ubPoints = gGameExternalOptions.iMinAPLimitFromSuppression;
|
||||
|
||||
// make sure action points doesn't exceed the permitted maximum
|
||||
ubMaxAPs = gubMaxActionPoints[ this->ubBodyType ];
|
||||
@@ -6688,6 +6689,15 @@ 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;
|
||||
}
|
||||
this->flags.fCloseCall = FALSE;
|
||||
|
||||
this->ubMovementNoiseHeard = 0;
|
||||
|
||||
+274
-121
@@ -192,6 +192,8 @@ extern INT16 ITEMDESC_START_Y;
|
||||
|
||||
//Little functions called by keyboard input
|
||||
void SwapGoggles(SOLDIERTYPE *pTeamSoldier);
|
||||
// HEADROCK HAM B2.8: Function to switch team's goggles uniformly
|
||||
void SwapGogglesUniformly(SOLDIERTYPE *pTeamSoldier, BOOLEAN fToNightVision);
|
||||
void SeperateItems();
|
||||
void StackAndSort( BOOLEAN fRestrictToAmmo );
|
||||
void CreateRandomItem();
|
||||
@@ -3315,10 +3317,43 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
|
||||
case 'N':
|
||||
SOLDIERTYPE *pTeamSoldier;
|
||||
INT8 bLoop;
|
||||
for (bLoop=gTacticalStatus.Team[gbPlayerNum].bFirstID, pTeamSoldier=MercPtrs[bLoop]; bLoop <= gTacticalStatus.Team[gbPlayerNum].bLastID; bLoop++, pTeamSoldier++)
|
||||
BOOLEAN fToNightVision;
|
||||
|
||||
// HEADROCK HAM B2.8: Added call for CTRL-SHIFT-N to switch all soldiers to day/night.
|
||||
if ( fCtrl )
|
||||
{
|
||||
if ( OK_CONTROLLABLE_MERC( pTeamSoldier ) && pTeamSoldier->bAssignment == CurrentSquad( ) && !AM_A_ROBOT( pTeamSoldier ) ) {
|
||||
SwapGoggles(pTeamSoldier);
|
||||
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 ) )
|
||||
{
|
||||
if ( pTeamSoldier->inv[HEAD1POS].exists() || pTeamSoldier->inv[HEAD2POS].exists() )
|
||||
{
|
||||
fToNightVision = ( Item[pTeamSoldier->inv[HEAD1POS].usItem].brightlightvisionrangebonus > 0 || Item[pTeamSoldier->inv[HEAD2POS].usItem].brightlightvisionrangebonus > 0 );
|
||||
break;
|
||||
}
|
||||
if ( bLoop == gTacticalStatus.Team[gbPlayerNum].bLastID )
|
||||
{
|
||||
// Default to night or day based on game hour
|
||||
fToNightVision = NightTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
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 ) )
|
||||
{
|
||||
SwapGogglesUniformly(pTeamSoldier, fToNightVision);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Shift-N
|
||||
{
|
||||
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 ) )
|
||||
{
|
||||
SwapGoggles(pTeamSoldier);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -5638,81 +5673,186 @@ void SwapGoggles(SOLDIERTYPE *pTeamSoldier)
|
||||
/* CHRISL - Adjusted this option to allow the game to search through Helmet attachments
|
||||
as well as inventory positions.
|
||||
*/
|
||||
|
||||
// WDS - Smart goggle switching
|
||||
// NOTE: Investigate using GetItemVisionRangeBonus from Items.cpp???
|
||||
if (gGameExternalOptions.smartGoggleSwitch) {
|
||||
// Look through the head slots and find any sort of goggle or an empty spot
|
||||
int slotToUse = -1;
|
||||
for (int headSlot = HEAD1POS; headSlot <= HEAD2POS; ++headSlot) {
|
||||
if ( (Item[pTeamSoldier->inv[headSlot].usItem].brightlightvisionrangebonus > 0) ) {
|
||||
slotToUse = headSlot;
|
||||
break;
|
||||
} else if ( (Item[pTeamSoldier->inv[headSlot].usItem].nightvisionrangebonus > 0) ) {
|
||||
slotToUse = headSlot;
|
||||
break;
|
||||
} else if (pTeamSoldier->inv[headSlot].exists() == false) {
|
||||
slotToUse = headSlot;
|
||||
OBJECTTYPE * pObj;
|
||||
OBJECTTYPE * pGoggles = NULL;
|
||||
INT8 bSlot1;
|
||||
int bestBonus;
|
||||
bool itemFound = false;
|
||||
//CHRISL: Before doing anything, we should look at both head slots to see if either slot has some sort of goggles
|
||||
for(bSlot1 = HEAD1POS; bSlot1 <= HEAD2POS; bSlot1++)
|
||||
{
|
||||
if(Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus > 0)
|
||||
itemFound = true;
|
||||
if(Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus > 0)
|
||||
itemFound = true;
|
||||
}
|
||||
//2 head slots
|
||||
for (bSlot1 = HEAD1POS; bSlot1 <= HEAD2POS; bSlot1++)
|
||||
{
|
||||
// if wearing sungoggles
|
||||
if ( Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus > 0 )
|
||||
{
|
||||
itemFound = true;
|
||||
bestBonus = 0;
|
||||
pGoggles = FindNightGogglesInInv( pTeamSoldier );
|
||||
//search for better goggles on the helmet
|
||||
if (pGoggles)
|
||||
{
|
||||
bestBonus = Item[pGoggles->usItem].nightvisionrangebonus;
|
||||
}
|
||||
}
|
||||
if (slotToUse == -1) {
|
||||
// No place to swap in a new goggle, give up
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the best goggles for the current time of day anywhere in inventory
|
||||
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()) {
|
||||
SwapObjs( pTeamSoldier, slotToUse, pGoggles, TRUE );
|
||||
} else {
|
||||
pGoggles->MoveThisObjectTo(pTeamSoldier->inv[slotToUse], 1, pTeamSoldier, slotToUse);
|
||||
}
|
||||
} else {
|
||||
// No goggles to equip, should the current ones be unequiped?
|
||||
if (pTeamSoldier->inv[slotToUse].exists()) {
|
||||
if ((DayTime() && (Item[pTeamSoldier->inv[slotToUse].usItem].nightvisionrangebonus > 0)) ||
|
||||
(!DayTime() && (Item[pTeamSoldier->inv[slotToUse].usItem].brightlightvisionrangebonus > 0))) {
|
||||
// It's day and we're wearing night goggles (or vice-versa), find a place to stash them
|
||||
if (pTeamSoldier->inv[ HELMETPOS ].exists()) {
|
||||
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
|
||||
}
|
||||
} else {
|
||||
// Try dumping it anywhere in inventory given there's no helemt
|
||||
//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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Normal goggle switching
|
||||
OBJECTTYPE * pObj;
|
||||
OBJECTTYPE * pGoggles = NULL;
|
||||
INT8 bSlot1;
|
||||
int bestBonus;
|
||||
bool itemFound = false;
|
||||
|
||||
//CHRISL: Before doing anything, we should look at both head slots to see if either slot has some sort of goggles
|
||||
for (bSlot1 = HEAD1POS; bSlot1 <= HEAD2POS; bSlot1++) {
|
||||
if ((Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus > 0) ||
|
||||
(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) )
|
||||
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 sungoggles.
|
||||
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// else if wearing NVGs
|
||||
else if(Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus > 0)
|
||||
{
|
||||
itemFound = true;
|
||||
bestBonus = 0;
|
||||
pGoggles = FindSunGogglesInInv( pTeamSoldier );
|
||||
//search for better goggles on the helmet
|
||||
if (pGoggles)
|
||||
{
|
||||
bestBonus = Item[pGoggles->usItem].brightlightvisionrangebonus;
|
||||
}
|
||||
//search helmet and vest
|
||||
for(UINT8 gear = HELMETPOS; gear <= VESTPOS; gear++)
|
||||
{
|
||||
pObj = &(pTeamSoldier->inv[gear]);
|
||||
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter)
|
||||
{
|
||||
if ( Item[ iter->usItem ].brightlightvisionrangebonus > bestBonus && Item[ iter->usItem ].usItemClass == IC_FACE )
|
||||
{
|
||||
pGoggles = &(*iter);
|
||||
bestBonus = Item[ iter->usItem ].brightlightvisionrangebonus;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( pGoggles )
|
||||
{
|
||||
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
|
||||
break;
|
||||
}
|
||||
// HEADROCK HAM B2.8: If no goggles were found to switch to, the character will remove what they're
|
||||
// wearing, to avoid situations where a character refuses to remove the wrong set of goggles and
|
||||
// thus suffers a penalty.
|
||||
else
|
||||
{
|
||||
// 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;
|
||||
pTeamSoldier->DeleteSoldierLight( );
|
||||
pTeamSoldier->PositionSoldierLight( );
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2.8: This function does the same as SwapGoggles, with a twist. It changes all worn goggles in the
|
||||
// team uniformly, so that everyone is wearing either nightvision or dayvision, regardless of what they were wearing
|
||||
// before. The check is based on the headgear of the first character in the group (he'll switch, and everyone else
|
||||
// will switch to match him.
|
||||
|
||||
void SwapGogglesUniformly(SOLDIERTYPE *pTeamSoldier, BOOLEAN fToNightVision)
|
||||
{
|
||||
/* CHRISL - Adjusted this option to allow the game to search through Helmet attachments
|
||||
as well as inventory positions.
|
||||
*/
|
||||
OBJECTTYPE * pObj;
|
||||
OBJECTTYPE * pGoggles = NULL;
|
||||
INT8 bSlot1;
|
||||
int bestBonus;
|
||||
bool itemFound = false;
|
||||
|
||||
//CHRISL: Before doing anything, we should look at both head slots to see if either slot has some sort of goggles
|
||||
for(bSlot1 = HEAD1POS; bSlot1 <= HEAD2POS; bSlot1++)
|
||||
{
|
||||
if(Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus > 0)
|
||||
itemFound = true;
|
||||
if(Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus > 0)
|
||||
itemFound = true;
|
||||
}
|
||||
//2 head slots
|
||||
for (bSlot1 = HEAD1POS; bSlot1 <= HEAD2POS; bSlot1++)
|
||||
{
|
||||
// if wearing sungoggles
|
||||
if ( Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus > 0 )
|
||||
{
|
||||
if (fToNightVision == TRUE) // Only if we want to switch to nightvision!
|
||||
{
|
||||
itemFound = true;
|
||||
bestBonus = 0;
|
||||
pGoggles = FindNightGogglesInInv( pTeamSoldier );
|
||||
//search for better goggles on the helmet
|
||||
@@ -5738,10 +5878,20 @@ void SwapGoggles(SOLDIERTYPE *pTeamSoldier)
|
||||
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
|
||||
break;
|
||||
}
|
||||
else if (Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus <= 0)
|
||||
{
|
||||
// Remove sungoggles.
|
||||
PlaceInAnyPocket(pTeamSoldier, &pTeamSoldier->inv[bSlot1], FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// else if wearing NVGs
|
||||
else if(Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus > 0 )
|
||||
}
|
||||
// else if wearing NVGs
|
||||
else if(Item[pTeamSoldier->inv[bSlot1].usItem].nightvisionrangebonus > 0)
|
||||
{
|
||||
if (fToNightVision == FALSE) // Only if we want to switch to dayvision!
|
||||
{
|
||||
itemFound = true;
|
||||
bestBonus = 0;
|
||||
pGoggles = FindSunGogglesInInv( pTeamSoldier );
|
||||
//search for better goggles on the helmet
|
||||
@@ -5767,57 +5917,60 @@ void SwapGoggles(SOLDIERTYPE *pTeamSoldier)
|
||||
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
|
||||
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
|
||||
else if (Item[pTeamSoldier->inv[bSlot1].usItem].brightlightvisionrangebonus <= 0)
|
||||
{
|
||||
// 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(fToNightVision == FALSE && Item[iter->usItem].brightlightvisionrangebonus > bestBonus && Item[iter->usItem].usItemClass == IC_FACE)
|
||||
{
|
||||
pGoggles = &(*iter);
|
||||
bestBonus = Item[iter->usItem].brightlightvisionrangebonus;
|
||||
}
|
||||
else if(fToNightVision == 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(fToNightVision == FALSE)
|
||||
pGoggles = FindSunGogglesInInv( pTeamSoldier );
|
||||
else
|
||||
pGoggles = FindNightGogglesInInv( pTeamSoldier );
|
||||
if(pGoggles)
|
||||
{
|
||||
SwapObjs( pTeamSoldier, bSlot1, pGoggles, TRUE );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fCharacterInfoPanelDirty = TRUE;
|
||||
fTeamPanelDirty = TRUE;
|
||||
fInterfacePanelDirty = DIRTYLEVEL2;
|
||||
@@ -5963,4 +6116,4 @@ void StackAndSort( BOOLEAN fRestrictToAmmo )
|
||||
//HandleAllReachAbleItemsInTheSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pImpButtonText[11] );
|
||||
}
|
||||
}
|
||||
}
|
||||
+231
-14
@@ -575,19 +575,123 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT16 sMapPos, BOOLEAN
|
||||
{
|
||||
usCursor = ACTION_TARGETCONFIRMBURST_UICURSOR;
|
||||
|
||||
// HEADROCK HAM B1: Burst cursor now shows multiple CTH bars (one for each bullet)
|
||||
// and also a Targetted Bodypart indicator.
|
||||
if(pSoldier->bDoAutofire == 0 && gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
|
||||
{
|
||||
//AXP 29.03.2007: Rooftop CtH fix. See below.
|
||||
INT8 bTempTargetLevel = pSoldier->bTargetLevel;
|
||||
pSoldier->bTargetLevel = (INT8) gsInterfaceLevel;
|
||||
if (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 2)
|
||||
{
|
||||
// Burst mode only
|
||||
OBJECTTYPE * pInHand;
|
||||
pInHand = &(pSoldier->inv[pSoldier->ubAttackingHand]);
|
||||
// Burst size
|
||||
gbCtHBurstCount = GetShotsPerBurst(pInHand);
|
||||
UINT8 i, saveDoBurst;
|
||||
// Save original burst value (should be 1 always, before the burst has been fired, but
|
||||
// this is just a failsafe
|
||||
saveDoBurst = pSoldier->bDoBurst;
|
||||
|
||||
UINT32 uiHitChance;
|
||||
uiHitChance = CalcChanceToHitGun( pSoldier, sMapPos, 0, pSoldier->bAimShotLocation );
|
||||
// For each bullet in the burst
|
||||
for (i=0;i<gbCtHBurstCount;i++)
|
||||
{
|
||||
//AXP 29.03.2007: Rooftop CtH fix. See below.
|
||||
INT8 bTempTargetLevel = pSoldier->bTargetLevel;
|
||||
pSoldier->bTargetLevel = (INT8) gsInterfaceLevel;
|
||||
|
||||
pSoldier->bTargetLevel = bTempTargetLevel;
|
||||
// Calculate hit chance (using the current bDoBurst for burst-penalty calculations)
|
||||
UINT32 uiHitChance;
|
||||
uiHitChance = CalcChanceToHitGun( pSoldier, sMapPos, 0, pSoldier->bAimShotLocation );
|
||||
// HEADROCK HAM B2.7: CTH approximation?
|
||||
if (gGameExternalOptions.fApproximateCTH)
|
||||
{
|
||||
uiHitChance = ChanceToHitApproximation( pSoldier, uiHitChance );
|
||||
}
|
||||
|
||||
gfUICtHBar = TRUE;
|
||||
gbCtH = (gbCtH+uiHitChance)/2;
|
||||
pSoldier->bTargetLevel = bTempTargetLevel;
|
||||
|
||||
// Put result (burst CTH) into the array
|
||||
gbCtH[i] = (gbCtH[i]+uiHitChance)/2;
|
||||
|
||||
// Increase burst size, so that the next time we run CalcChanceToHitGun we'll get a lower
|
||||
// result, based on our Burst Penalty
|
||||
pSoldier->bDoBurst++;
|
||||
}
|
||||
// Reset original burst status
|
||||
pSoldier->bDoBurst = saveDoBurst;
|
||||
// Activate CTH bar display
|
||||
gfUICtHBar = TRUE;
|
||||
}
|
||||
else // One "BASE CTH" bar, JA2 1.13 vanilla
|
||||
{
|
||||
//AXP 29.03.2007: Rooftop CtH fix. See below.
|
||||
INT8 bTempTargetLevel = pSoldier->bTargetLevel;
|
||||
pSoldier->bTargetLevel = (INT8) gsInterfaceLevel;
|
||||
|
||||
UINT32 uiHitChance;
|
||||
uiHitChance = CalcChanceToHitGun( pSoldier, sMapPos, 0, pSoldier->bAimShotLocation );
|
||||
// HEADROCK HAM B2.7: CTH approximation?
|
||||
if (gGameExternalOptions.fApproximateCTH)
|
||||
{
|
||||
uiHitChance = ChanceToHitApproximation( pSoldier, uiHitChance );
|
||||
}
|
||||
|
||||
pSoldier->bTargetLevel = bTempTargetLevel;
|
||||
|
||||
gfUICtHBar = TRUE;
|
||||
gbCtH[0] = (gbCtH[0]+uiHitChance)/2;
|
||||
gbCtHBurstCount = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// HEADROCK HAM B2: Now autofire will show both its starting CTH and the CTH of the last
|
||||
// bullet in the volley.
|
||||
|
||||
else if(pSoldier->bDoAutofire > 0 && gGameSettings.fOptions[ TOPTION_CTH_CURSOR ])
|
||||
{
|
||||
if (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3)
|
||||
{
|
||||
gbCtHBurstCount = 1;
|
||||
|
||||
//AXP 29.03.2007: Rooftop CtH fix. See below.
|
||||
INT8 bTempTargetLevel = pSoldier->bTargetLevel;
|
||||
pSoldier->bTargetLevel = (INT8) gsInterfaceLevel;
|
||||
|
||||
UINT32 uiHitChance;
|
||||
// Calculate CTH for the first bullet
|
||||
uiHitChance = CalcChanceToHitGun( pSoldier, sMapPos, 0, pSoldier->bAimShotLocation );
|
||||
// HEADROCK HAM B2.7: CTH approximation?
|
||||
if (gGameExternalOptions.fApproximateCTH)
|
||||
{
|
||||
uiHitChance = ChanceToHitApproximation( pSoldier, uiHitChance );
|
||||
}
|
||||
|
||||
// CTH for the first bullet is entered into this array, and later displayed
|
||||
gbCtH[0] = (gbCtH[0]+uiHitChance)/2;
|
||||
|
||||
// Fool the CTH formula into thinking we're already firing the last bullet in the volley,
|
||||
// by artificially altering bDoBurst (which tracks actual burst progression). The CTH formula
|
||||
// calculates Auto Penalty based on bDoBurst - (Autopen * (bDoBurst-1), basically).
|
||||
UINT8 saveDoBurst = pSoldier->bDoBurst;
|
||||
pSoldier->bDoBurst = pSoldier->bDoAutofire;
|
||||
|
||||
uiHitChance = CalcChanceToHitGun( pSoldier, sMapPos, 0, pSoldier->bAimShotLocation );
|
||||
// HEADROCK HAM B2.7: CTH approximation?
|
||||
if (gGameExternalOptions.fApproximateCTH)
|
||||
{
|
||||
uiHitChance = ChanceToHitApproximation( pSoldier, uiHitChance );
|
||||
}
|
||||
|
||||
pSoldier->bTargetLevel = bTempTargetLevel;
|
||||
// Return Burst State to original value
|
||||
pSoldier->bDoBurst = saveDoBurst;
|
||||
|
||||
// CTH for the last bullet is entered into this array and later displayed.
|
||||
gbCtH[1] = (gbCtH[1]+uiHitChance)/2;
|
||||
|
||||
// Flag to tell the program to draw two CTH bars.
|
||||
gbCtHAutoFire = TRUE;
|
||||
gfUICtHBar = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -603,11 +707,17 @@ UINT8 HandleActivatedTargetCursor( SOLDIERTYPE *pSoldier, INT16 sMapPos, BOOLEAN
|
||||
|
||||
UINT32 uiHitChance;
|
||||
uiHitChance = CalcChanceToHitGun( pSoldier, sMapPos, (INT8)(pSoldier->aiData.bShownAimTime ), pSoldier->bAimShotLocation );
|
||||
// HEADROCK HAM B2.7: CTH approximation?
|
||||
if (gGameExternalOptions.fApproximateCTH)
|
||||
{
|
||||
uiHitChance = ChanceToHitApproximation( pSoldier, uiHitChance );
|
||||
}
|
||||
|
||||
pSoldier->bTargetLevel = bTempTargetLevel;
|
||||
|
||||
gfUICtHBar = TRUE;
|
||||
gbCtH = (gbCtH+uiHitChance)/2;
|
||||
gbCtHBurstCount = 1;
|
||||
gbCtH[0] = (gbCtH[0]+uiHitChance)/2;
|
||||
}
|
||||
|
||||
switchVal = pSoldier->aiData.bShownAimTime;
|
||||
@@ -1283,8 +1393,10 @@ void DetermineCursorBodyLocation( UINT8 ubSoldierID, BOOLEAN fDisplay, BOOLEAN f
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( fDisplay && !pSoldier->bDoBurst)
|
||||
// HEADROCK HAM B2: Now shows targetted bodypart for ALL firing modes. Note that the external toggle is not
|
||||
// taken into account yet.
|
||||
// if ( fDisplay && !pSoldier->bDoAutofire )
|
||||
if ( fDisplay )
|
||||
{
|
||||
if ( gfUIFullTargetFound )
|
||||
{
|
||||
@@ -1296,7 +1408,14 @@ void DetermineCursorBodyLocation( UINT8 ubSoldierID, BOOLEAN fDisplay, BOOLEAN f
|
||||
|
||||
wcscpy( gzLocation, TacticalStr[ CROW_HIT_LOCATION_STR ] );
|
||||
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
if ( !pSoldier->bDoBurst )
|
||||
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) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
else if ( pSoldier->bDoBurst && pSoldier->bDoAutofire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1318,16 +1437,37 @@ void DetermineCursorBodyLocation( UINT8 ubSoldierID, BOOLEAN fDisplay, BOOLEAN f
|
||||
{
|
||||
wcscpy( gzLocation, TacticalStr[ HEAD_HIT_LOCATION_STR ] );
|
||||
}
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
if ( !pSoldier->bDoBurst )
|
||||
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) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
else if ( pSoldier->bDoBurst && pSoldier->bDoAutofire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
break;
|
||||
|
||||
case AIM_SHOT_TORSO:
|
||||
wcscpy( gzLocation, TacticalStr[ TORSO_HIT_LOCATION_STR ] );
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
if ( !pSoldier->bDoBurst )
|
||||
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) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
else if ( pSoldier->bDoBurst && pSoldier->bDoAutofire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
break;
|
||||
|
||||
case AIM_SHOT_LEGS:
|
||||
wcscpy( gzLocation, TacticalStr[ LEGS_HIT_LOCATION_STR ] );
|
||||
if ( !pSoldier->bDoBurst )
|
||||
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) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
else if ( pSoldier->bDoBurst && pSoldier->bDoAutofire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3) )
|
||||
gfUIBodyHitLocation = TRUE;
|
||||
break;
|
||||
}
|
||||
@@ -2384,3 +2524,80 @@ void HandleUICursorRTFeedback( SOLDIERTYPE *pSoldier )
|
||||
}
|
||||
|
||||
}
|
||||
// HEADROCK HAM B2.7: This function gives us an "approximate" CTH bar, that doesn't show the exact value of
|
||||
// CTH unless the character is well-trained. The worse trained a character is, the wilder the speculation.
|
||||
|
||||
UINT32 ChanceToHitApproximation( SOLDIERTYPE * pSoldier, UINT32 uiChance )
|
||||
{
|
||||
UINT16 bExpLevel = pSoldier->stats.bExpLevel;
|
||||
UINT16 bMarksmanship = pSoldier->stats.bMarksmanship;
|
||||
UINT16 bWisdom = pSoldier->stats.bWisdom;
|
||||
UINT16 iNumStages, iNumStagesBase, StageSize, SubStageSize;
|
||||
UINT8 iSniper;
|
||||
UINT16 uiNewChance;
|
||||
UINT16 i;
|
||||
|
||||
if ( pSoldier->ubProfile != NO_PROFILE )
|
||||
{
|
||||
iSniper = NUM_SKILL_TRAITS( pSoldier, PROF_SNIPER );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dunno, but I get the strong feeling that we don't want CTH bars for non-mercs.
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (uiChance == 100)
|
||||
{
|
||||
// Sure hit. The player needs to set Maximum_CTH to 100 for this to happen. Normally, the
|
||||
// max chance is only 99.
|
||||
return(100);
|
||||
}
|
||||
if (uiChance == 0)
|
||||
{
|
||||
// Sure Miss. The player needs to set Minimum_CTH to 0 for this to happen. Normally, the
|
||||
// min chance is 1.
|
||||
return(0);
|
||||
}
|
||||
|
||||
uiNewChance = uiChance;
|
||||
iNumStagesBase = __min(165,__max(0, ((bExpLevel * 10) - 30) + (bMarksmanship - 25) + (bWisdom - 50)));
|
||||
//iNumStagesBase = __max(255, iNumStagesBase);
|
||||
|
||||
iNumStagesBase = __min(165, iNumStagesBase + (10 * iSniper));
|
||||
|
||||
iNumStagesBase = (UINT16)((float)iNumStagesBase * (float)((float)iNumStagesBase / 195.0));
|
||||
|
||||
// Gives a number between 2 and 51.
|
||||
iNumStages = __max(2,(100 * iNumStagesBase) / 300);
|
||||
|
||||
// Find out how large the slices are
|
||||
StageSize = 100/iNumStages;
|
||||
// Correct iNumStages to match StageSize, +1 compensates for the rounding down of StageSize.
|
||||
iNumStages = (100/StageSize) + 1;
|
||||
// These sub-stages are used to determine which way to round the results.
|
||||
SubStageSize = __max(1, StageSize / 2);
|
||||
|
||||
if (StageSize == 1)
|
||||
// CTH assessment is perfect. No need for the rest of this function
|
||||
return (uiChance);
|
||||
|
||||
// Jump each "stage" and see whether the CTH is within this slice of the scale
|
||||
for (i=0; i<iNumStages; i++)
|
||||
{
|
||||
UINT16 CurrentStage = i * StageSize;
|
||||
UINT16 NextStage = (i+1) * StageSize;
|
||||
// Check whether the CTH should be rounded down or up.
|
||||
if ( (CurrentStage <= (UINT16) uiChance) && (CurrentStage + SubStageSize > (UINT16) uiChance) )
|
||||
{
|
||||
return (CurrentStage);
|
||||
}
|
||||
else if ( (CurrentStage + SubStageSize <= (UINT16) uiChance) && (NextStage > (UINT16) uiChance))
|
||||
{
|
||||
return (NextStage);
|
||||
}
|
||||
}
|
||||
|
||||
// Something went wrong. Return 50, as in "God Knows"
|
||||
return (50);
|
||||
}
|
||||
|
||||
@@ -24,5 +24,8 @@ void HandleEndConfirmCursor( SOLDIERTYPE *pSoldier );
|
||||
|
||||
BOOLEAN GetMouseRecalcAndShowAPFlags( UINT32 *puiCursorFlags, BOOLEAN *pfShowAPs );
|
||||
|
||||
// HEADROCK HAM B2.7: This function calculates the nearest value (display purposes only)
|
||||
// based on how trained the shooter is.
|
||||
UINT32 ChanceToHitApproximation( SOLDIERTYPE * pSoldier, UINT32 uiChance );
|
||||
|
||||
#endif
|
||||
+224
-27
@@ -59,8 +59,9 @@ extern INT8 gbCurrentRainIntensity;
|
||||
//end rain
|
||||
|
||||
|
||||
#define MINCHANCETOHIT 1
|
||||
#define MAXCHANCETOHIT 99
|
||||
// HEADROCK HAM B1: Externalized both values to INI
|
||||
//#define MINCHANCETOHIT 1
|
||||
//#define MAXCHANCETOHIT 99
|
||||
|
||||
// NB this is arbitrary, chances in DG ranged from 1 in 6 to 1 in 20
|
||||
#define BASIC_DEPRECIATE_CHANCE 15
|
||||
@@ -105,6 +106,10 @@ INT32 HTHImpact( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTarget, INT32 iHitBy, BO
|
||||
BOOLEAN gfNextShotKills = FALSE;
|
||||
BOOLEAN gfReportHitChances = FALSE;
|
||||
|
||||
// HEADROCK HAM B2.5:Using this boolean to tell the CTH formula that it is being called by UseGun(), rather than
|
||||
// by other functions. This is mostly to assist the new Tracer Fire system...
|
||||
BOOLEAN fCalculateCTHDuringGunfire = FALSE;
|
||||
|
||||
//GLOBALS
|
||||
|
||||
// TODO: Move strings to extern file
|
||||
@@ -1683,8 +1688,10 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT16 sTargetGridNo )
|
||||
}
|
||||
else
|
||||
{
|
||||
uiHitChance = CalcChanceToHitGun( pSoldier, sTargetGridNo, pSoldier->aiData.bAimTime, pSoldier->bAimShotLocation );
|
||||
fCalculateCTHDuringGunfire = TRUE;
|
||||
uiHitChance = CalcChanceToHitGun( pSoldier, sTargetGridNo, pSoldier->aiData.bAimTime, pSoldier->bAimShotLocation );
|
||||
}
|
||||
fCalculateCTHDuringGunfire = FALSE;
|
||||
|
||||
//DIGICRAB: Barrel extender wear code
|
||||
// Relocated from CalcChanceToHitGun
|
||||
@@ -1728,10 +1735,19 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT16 sTargetGridNo )
|
||||
// big penalty to hit
|
||||
// WDS 07/06/2008 fix randoms
|
||||
//if(uiHitChance < 30)
|
||||
if(uiHitChance <= 30)
|
||||
uiHitChance = MINCHANCETOHIT;
|
||||
// HEADROCK: Altered formula to accept variable MINIMUM CTH.
|
||||
//if(uiHitChance <= 30)
|
||||
// uiHitChance = MINCHANCETOHIT;
|
||||
//else
|
||||
// uiHitChance -= 30;
|
||||
if(uiHitChance <= (UINT16)(__max(30, gGameExternalOptions.iMinimumCTH + 30)))
|
||||
{
|
||||
uiHitChance = gGameExternalOptions.iMinimumCTH ;
|
||||
}
|
||||
else
|
||||
{
|
||||
uiHitChance -= 30;
|
||||
}
|
||||
|
||||
// curse!
|
||||
if ( pSoldier->bTeam == OUR_TEAM )
|
||||
@@ -3552,8 +3568,9 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
|
||||
if ( pSoldier->stats.bMarksmanship == 0 )
|
||||
{
|
||||
// always min chance
|
||||
return( MINCHANCETOHIT );
|
||||
// HEADROCK: (HAM) Altered to accept external arguments
|
||||
// return( MINCHANCETOHIT );
|
||||
return( gGameExternalOptions.iMinimumCTH );
|
||||
}
|
||||
|
||||
// make sure the guy's actually got a weapon in his hand!
|
||||
@@ -3724,7 +3741,7 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
}
|
||||
|
||||
// If in burst mode, deduct points for change to hit for each shot after the first
|
||||
if ( pSoldier->bDoBurst > 0 && pSoldier->bDoAutofire == 0 )
|
||||
if ( pSoldier->bDoBurst && pSoldier->bDoAutofire == 0 )
|
||||
{
|
||||
// Snap: bipod may reduce burst penalty
|
||||
iPenalty = GetBurstPenalty(pInHand, gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE)
|
||||
@@ -3749,6 +3766,54 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ADB we need to calculate the distance visible and SoldierTo...LOSTests that we want to
|
||||
@@ -3866,7 +3931,22 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
|
||||
// if shooter is still in shock
|
||||
if (pSoldier->aiData.bShock)
|
||||
iChance -= (pSoldier->aiData.bShock * AIM_PENALTY_PER_SHOCK);
|
||||
{
|
||||
// HEADROCK HAM B2.8: Placed a maximum here, as shock is now also used in suppression.
|
||||
UINT16 usShockPenalty;
|
||||
|
||||
usShockPenalty = pSoldier->aiData.bShock * AIM_PENALTY_PER_SHOCK;
|
||||
|
||||
if (gGameExternalOptions.usMaxShooterCoweringPenalty > 0)
|
||||
{
|
||||
if ( usShockPenalty > gGameExternalOptions.usMaxShooterCoweringPenalty )
|
||||
usShockPenalty = gGameExternalOptions.usMaxShooterCoweringPenalty;
|
||||
}
|
||||
if ( usShockPenalty < 1 )
|
||||
usShockPenalty = 1;
|
||||
|
||||
iChance -= usShockPenalty;
|
||||
}
|
||||
|
||||
// WANNE: Changed this, because RPGs are not in the calculation, only guns
|
||||
//if ( Item[ usInHand ].usItemClass == IC_GUN )
|
||||
@@ -3962,6 +4042,92 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
{
|
||||
iSightRange = 1;
|
||||
}
|
||||
// HEADROCK HAM B2.1 : The TARGET's shock now also affects aiming. If the target is prone
|
||||
// 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 )
|
||||
{
|
||||
// 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.
|
||||
// As of HAM B2.8: Target's stance and the targetted bodypart will affect the end result.
|
||||
|
||||
INT8 AIM_PENALTY_PER_TARGET_SHOCK;
|
||||
INT16 sCoweringPenalty = 0;
|
||||
UINT8 ubCoweringDivisor;
|
||||
UINT16 MIN_RANGE_FOR_FULL_COWER;
|
||||
UINT16 MAX_TARGET_COWERING_PENALTY;
|
||||
|
||||
AIM_PENALTY_PER_TARGET_SHOCK = gGameExternalOptions.iAimPenaltyPerTargetShock;
|
||||
MIN_RANGE_FOR_FULL_COWER = gGameExternalOptions.usMinRangeForFullCoweringPenalty;
|
||||
MAX_TARGET_COWERING_PENALTY = gGameExternalOptions.usMaxTargetCoweringPenalty;
|
||||
|
||||
pTarget = SimpleFindSoldier( sGridNo, pSoldier->bTargetLevel );
|
||||
if (pTarget != NULL)
|
||||
{
|
||||
if (pTarget->aiData.bShock )
|
||||
{
|
||||
if (gAnimControl[ pTarget->usAnimState ].ubHeight == ANIM_PRONE)
|
||||
{
|
||||
ubCoweringDivisor = gGameExternalOptions.ubCoweringPenaltyDivisorProne;
|
||||
|
||||
sCoweringPenalty = (pTarget->aiData.bShock * AIM_PENALTY_PER_TARGET_SHOCK);
|
||||
sCoweringPenalty = sCoweringPenalty / ubCoweringDivisor;
|
||||
sCoweringPenalty = (sCoweringPenalty * __min(iSightRange,MIN_RANGE_FOR_FULL_COWER)) / MIN_RANGE_FOR_FULL_COWER;
|
||||
|
||||
if (gGameExternalOptions.usMaxTargetCoweringPenalty > 0)
|
||||
{
|
||||
if ( sCoweringPenalty > gGameExternalOptions.usMaxTargetCoweringPenalty )
|
||||
sCoweringPenalty = gGameExternalOptions.usMaxTargetCoweringPenalty;
|
||||
}
|
||||
if ( sCoweringPenalty < 1 )
|
||||
sCoweringPenalty = 1;
|
||||
|
||||
iChance -= sCoweringPenalty;
|
||||
}
|
||||
else if (gAnimControl[ pTarget->usAnimState ].ubHeight == ANIM_CROUCH)
|
||||
{
|
||||
switch ( ubAimPos )
|
||||
{
|
||||
case AIM_SHOT_HEAD:
|
||||
ubCoweringDivisor = gGameExternalOptions.ubCoweringPenaltyDivisorCrouchedHead;
|
||||
break;
|
||||
case AIM_SHOT_TORSO:
|
||||
case AIM_SHOT_RANDOM:
|
||||
case AIM_SHOT_GLAND:
|
||||
ubCoweringDivisor = gGameExternalOptions.ubCoweringPenaltyDivisorCrouchedTorso;
|
||||
break;
|
||||
case AIM_SHOT_LEGS:
|
||||
ubCoweringDivisor = gGameExternalOptions.ubCoweringPenaltyDivisorCrouchedLegs;
|
||||
break;
|
||||
}
|
||||
|
||||
sCoweringPenalty = (pTarget->aiData.bShock * AIM_PENALTY_PER_TARGET_SHOCK);
|
||||
sCoweringPenalty = sCoweringPenalty / ubCoweringDivisor;
|
||||
sCoweringPenalty = (sCoweringPenalty * __min(iSightRange,MIN_RANGE_FOR_FULL_COWER)) / MIN_RANGE_FOR_FULL_COWER;
|
||||
|
||||
if (gGameExternalOptions.usMaxTargetCoweringPenalty > 0)
|
||||
{
|
||||
if ( sCoweringPenalty > gGameExternalOptions.usMaxTargetCoweringPenalty )
|
||||
sCoweringPenalty = gGameExternalOptions.usMaxTargetCoweringPenalty;
|
||||
}
|
||||
if ( sCoweringPenalty < 1 )
|
||||
sCoweringPenalty = 1;
|
||||
|
||||
// HEADROCK HAM B2.8.1: Added formula to make sure that cowering target penalties
|
||||
// are not given when on the roof.
|
||||
|
||||
if (pSoldier->pathing.bLevel == pTarget->pathing.bLevel && pSoldier->pathing.bLevel > 0)
|
||||
sCoweringPenalty = 0; // No cowering penalties when both are on the roof!
|
||||
else if (pSoldier->pathing.bLevel < pSoldier->pathing.bLevel && gAnimControl[ pTarget->usAnimState ].ubHeight == ANIM_PRONE)
|
||||
sCoweringPenalty *= 2; // Much harder to shoot at anyone cowering above you.
|
||||
else if (pSoldier->pathing.bLevel > pSoldier->pathing.bLevel)
|
||||
sCoweringPenalty /= 2; // Much easier to shoot at cowerers below you.
|
||||
iChance -= sCoweringPenalty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcChanceToHitGun: after scope bonus - ubAimTime = %d, iSightRange = %d, iChance = %d ", ubAimTime, iSightRange, iChance));
|
||||
|
||||
UINT8 bLightLevel = LightTrueLevel(sGridNo, pSoldier->bTargetLevel);
|
||||
@@ -4123,7 +4289,8 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
}
|
||||
|
||||
// penalty for amount that enemy has moved
|
||||
iPenalty = __min( ((pTarget->bTilesMoved * 3) / 2), 30 );
|
||||
// HEADROCK HAM B2.6: Externalized the value
|
||||
iPenalty = __min( (UINT16)((float)pTarget->bTilesMoved * (float)gGameExternalOptions.iMovementEffectOnAiming), 30 );
|
||||
iChance -= iPenalty;
|
||||
|
||||
// if target sees us, he may have a chance to dodge before the gun goes off
|
||||
@@ -4235,7 +4402,12 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
}
|
||||
|
||||
// MAKE SURE CHANCE TO HIT IS WITHIN DEFINED LIMITS
|
||||
if (iChance < MINCHANCETOHIT)
|
||||
// HEADROCK: (HAM) Altered so called "Defined Limits" to accept external arguments.
|
||||
// The divisor argument only works when the minimum is set to 0. It has a chance of 1 in X to
|
||||
// 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 ( TANK( pSoldier ) )
|
||||
{
|
||||
@@ -4244,14 +4416,24 @@ UINT32 CalcChanceToHitGun(SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 ubAimTime,
|
||||
}
|
||||
else
|
||||
{
|
||||
iChance = MINCHANCETOHIT;
|
||||
iChance = gGameExternalOptions.iMinimumCTH;
|
||||
if ( gGameExternalOptions.iMinimumCTH == 0 )
|
||||
{
|
||||
if ( PreRandom( gGameExternalOptions.iMinimumCTHDivisor ) == (gGameExternalOptions.iMinimumCTHDivisor - 1) )
|
||||
{
|
||||
iChance = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iChance > MAXCHANCETOHIT)
|
||||
iChance = MAXCHANCETOHIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// HEADROCK (HAM): Externalized maximum to JA2_OPTIONS.INI
|
||||
// if (iChance > MAXCHANCETOHIT)
|
||||
// iChance = MAXCHANCETOHIT;
|
||||
if (iChance > gGameExternalOptions.iMaximumCTH)
|
||||
iChance = gGameExternalOptions.iMaximumCTH;
|
||||
}
|
||||
|
||||
// NumMessage("ChanceToHit = ",chance);
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CalcChanceToHitGun: ichance = %d",iChance));
|
||||
@@ -5305,14 +5487,19 @@ UINT32 CalcChanceHTH( SOLDIERTYPE * pAttacker,SOLDIERTYPE *pDefender, INT16 ubAi
|
||||
|
||||
|
||||
// MAKE SURE CHANCE TO HIT IS WITHIN DEFINED LIMITS
|
||||
if (iChance < MINCHANCETOHIT)
|
||||
// HEADROCK: I urinate on your Defined Limits! Power Rangers, Externalize!
|
||||
// Disclaimer: No offense meant, all in good fun ;)
|
||||
if (iChance < gGameExternalOptions.iMinimumCTH)
|
||||
{
|
||||
iChance = MINCHANCETOHIT;
|
||||
iChance = gGameExternalOptions.iMinimumCTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iChance > MAXCHANCETOHIT)
|
||||
iChance = MAXCHANCETOHIT;
|
||||
// HEADROCK (HAM): Externalized maximum to JA2_OPTIONS.INI
|
||||
//if (iChance > MAXCHANCETOHIT)
|
||||
// iChance = MAXCHANCETOHIT;
|
||||
if (iChance > gGameExternalOptions.iMaximumCTH)
|
||||
iChance = gGameExternalOptions.iMaximumCTH;
|
||||
}
|
||||
|
||||
//NumMessage("ChanceToStab = ",chance);
|
||||
@@ -5768,13 +5955,17 @@ 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;
|
||||
|
||||
// MAKE SURE CHANCE TO HIT IS WITHIN DEFINED LIMITS
|
||||
if (iChance < MINCHANCETOHIT)
|
||||
iChance = MINCHANCETOHIT;
|
||||
// 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;
|
||||
else
|
||||
{
|
||||
if (iChance > MAXCHANCETOHIT)
|
||||
iChance = MAXCHANCETOHIT;
|
||||
// HEADROCK (HAM): Externalized maximum to JA2_OPTIONS.INI
|
||||
//if (iChance > MAXCHANCETOHIT)
|
||||
// iChance = MAXCHANCETOHIT;
|
||||
if (iChance > gGameExternalOptions.iMaximumCTH)
|
||||
iChance = gGameExternalOptions.iMaximumCTH;
|
||||
}
|
||||
|
||||
|
||||
@@ -5969,7 +6160,13 @@ UINT8 GetAutofireShotsPerFiveAPs( OBJECTTYPE *pObj )
|
||||
{
|
||||
// DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("GetAutofireShotsPerFiveAPs"));
|
||||
|
||||
return Weapon[ pObj->usItem ].bAutofireShotsPerFiveAP;
|
||||
// HEADROCK HAM B2.6: Added overall modifier
|
||||
if (Weapon[ pObj->usItem ].bAutofireShotsPerFiveAP > 0)
|
||||
{
|
||||
return __max((Weapon[ pObj->usItem ].bAutofireShotsPerFiveAP + gGameExternalOptions.iAutofireBulletsPer5APModifier), 0);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
}
|
||||
UINT16 GetMagSize( OBJECTTYPE *pObj )
|
||||
|
||||
+2
-1
@@ -19,7 +19,8 @@ enum WeaponMode
|
||||
void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInvPos, UINT16 usOldItem, UINT16 usNewItem );
|
||||
|
||||
|
||||
#define MAXCHANCETOHIT 99
|
||||
// HEADROCK: Removed this and externalized to JA2_OPTIONS.INI as part of HAM project.
|
||||
//#define MAXCHANCETOHIT 99
|
||||
#define BAD_DODGE_POSITION_PENALTY 20
|
||||
|
||||
#define GUN_BARREL_RANGE_BONUS 100
|
||||
|
||||
+10
-2
@@ -470,7 +470,11 @@ void AddMissileTrail( BULLET *pBullet, FIXEDPT qCurrX, FIXEDPT qCurrY, FIXEDPT q
|
||||
}
|
||||
}
|
||||
|
||||
if (fTracer == TRUE)
|
||||
// HEADROCK HAM B2.5: Created new bullet flag that tells us whether this specific bullet is a tracer.
|
||||
// The condition now reads that flag and creates a lightshow only for tracer bullets. This flag is only
|
||||
// used if the new Tracer System is on.
|
||||
//if (fTracer == TRUE)
|
||||
if ((gGameExternalOptions.iRealisticTracers > 0 && gGameExternalOptions.iNumBulletsPerTracer > 0 && pBullet->fTracer == TRUE) || (gGameExternalOptions.iRealisticTracers == 0 && fTracer == TRUE))
|
||||
{
|
||||
if ( pBullet->iLoop < 5 )
|
||||
{
|
||||
@@ -517,7 +521,11 @@ void AddMissileTrail( BULLET *pBullet, FIXEDPT qCurrX, FIXEDPT qCurrY, FIXEDPT q
|
||||
AniParams.sDelay = (INT16)( 100 );
|
||||
}
|
||||
//else if ( pBullet->usFlags & ( BULLET_FLAG_TRACER ) )
|
||||
else if (fTracer == TRUE)
|
||||
// HEADROCK HAM B2.5: Created new bullet flag that tells us whether this specific bullet is a tracer.
|
||||
// The condition now reads that flag and creates a lightshow only for tracer bullets. This flag is only
|
||||
// used if the new Tracer System is on.
|
||||
// else if (fTracer == TRUE)
|
||||
else if ((gGameExternalOptions.iRealisticTracers > 0 && gGameExternalOptions.iNumBulletsPerTracer > 0 && pBullet->fTracer == TRUE) || (gGameExternalOptions.iRealisticTracers == 0 && fTracer == TRUE))
|
||||
{
|
||||
INT16 sXPos, sYPos;
|
||||
|
||||
|
||||
@@ -231,4 +231,8 @@ INT16 FindBestCoverNearTheGridNo(SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubS
|
||||
|
||||
INT8 FindDirectionForClimbing( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel);
|
||||
|
||||
// HEADROCK HAM B2.7: Functions to assist group AI
|
||||
|
||||
INT16 AssessTacticalSituation( INT8 bSide );
|
||||
BOOLEAN TeamSeesOpponent( INT8 bSide, SOLDIERTYPE * pOpponent );
|
||||
INT32 CalcStraightThreatValue( SOLDIERTYPE *pEnemy );
|
||||
|
||||
@@ -2565,3 +2565,236 @@ void AINameMessage(SOLDIERTYPE * pSoldier,const STR8 str,INT32 num)
|
||||
DebugAI( tempstr );
|
||||
}
|
||||
#endif
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HEADROCK:
|
||||
//
|
||||
// The following function(s) are part of my half-assed attempt to have the AI analyze the tactical
|
||||
// situation, by comparing (known) squad sizes, the state of all combatants, and the orders of all
|
||||
// friendlies. The idea is to return a value called "TacticalSituation" which can tell a combatant
|
||||
// whether he should try to undertake a smarter course of action.
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
INT16 AssessTacticalSituation( INT8 bTeam )
|
||||
{
|
||||
UINT16 ubFriendlyTeamTacticalValue = 0;
|
||||
UINT16 ubEnemyTeamTacticalValue = 0;
|
||||
UINT8 ubSoldierTacticalThreat;
|
||||
INT16 ubTacticalSituation;
|
||||
UINT16 cnt;
|
||||
SOLDIERTYPE * pSoldier;
|
||||
|
||||
// begin loop through all MERCs.
|
||||
for ( cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++ )
|
||||
{
|
||||
pSoldier = MercPtrs[ cnt ];
|
||||
ubSoldierTacticalThreat = CalcStraightThreatValue( pSoldier );
|
||||
// Player-controlled Mercs are 1.5 times more threatening than AIs
|
||||
if (pSoldier->flags.uiStatusFlags & SOLDIER_PC)
|
||||
ubSoldierTacticalThreat = (UINT8)((float)ubSoldierTacticalThreat * 1.5);
|
||||
|
||||
// Assess Threat
|
||||
if (bTeam == OUR_TEAM || bTeam == MILITIA_TEAM)
|
||||
{
|
||||
// Friendly!
|
||||
ubFriendlyTeamTacticalValue += ubSoldierTacticalThreat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enemy!
|
||||
if ( TeamSeesOpponent( ENEMY_TEAM, pSoldier ) )
|
||||
ubEnemyTeamTacticalValue += ubSoldierTacticalThreat;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// begin loop through all Militia.
|
||||
for ( cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; cnt++ )
|
||||
{
|
||||
pSoldier = MercPtrs[ cnt ];
|
||||
ubSoldierTacticalThreat = CalcStraightThreatValue( pSoldier );
|
||||
|
||||
// Assess Threat
|
||||
if (bTeam == OUR_TEAM || bTeam == MILITIA_TEAM)
|
||||
{
|
||||
// Friendly!
|
||||
ubFriendlyTeamTacticalValue += ubSoldierTacticalThreat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enemy!
|
||||
if ( TeamSeesOpponent( ENEMY_TEAM, pSoldier ) )
|
||||
ubEnemyTeamTacticalValue += ubSoldierTacticalThreat;
|
||||
}
|
||||
}
|
||||
|
||||
// begin loop through all Enemies.
|
||||
for ( cnt = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; cnt++ )
|
||||
{
|
||||
pSoldier = MercPtrs[ cnt ];
|
||||
ubSoldierTacticalThreat = CalcStraightThreatValue( pSoldier );
|
||||
|
||||
// Assess Threat
|
||||
|
||||
if (bTeam == ENEMY_TEAM)
|
||||
{
|
||||
// Friendly!
|
||||
ubFriendlyTeamTacticalValue += ubSoldierTacticalThreat;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Enemy!
|
||||
if ( TeamSeesOpponent( OUR_TEAM, pSoldier ) || TeamSeesOpponent ( MILITIA_TEAM, pSoldier) )
|
||||
ubEnemyTeamTacticalValue += ubSoldierTacticalThreat;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ubTacticalSituation = ubEnemyTeamTacticalValue - ubFriendlyTeamTacticalValue;
|
||||
|
||||
return (ubTacticalSituation);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// HEADROCK: Function to check whether a team can see the specified soldier.
|
||||
BOOLEAN TeamSeesOpponent( INT8 bTeam, SOLDIERTYPE * pOpponent )
|
||||
{
|
||||
SOLDIERTYPE * pSoldier;
|
||||
UINT16 cnt;
|
||||
|
||||
// This assertion can be safely removed, assuming the program does what it should. It simply checks
|
||||
// whether the "opponent" is on the same team being checked. That should be avoided when calling this
|
||||
// function.
|
||||
Assert( pOpponent->bTeam != bTeam );
|
||||
|
||||
// We're checking Merc/Militia visibility
|
||||
if (bTeam == OUR_TEAM || bTeam == MILITIA_TEAM )
|
||||
{
|
||||
for ( cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; cnt++ )
|
||||
{
|
||||
pSoldier = MercPtrs[ cnt ];
|
||||
|
||||
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE)
|
||||
{
|
||||
|
||||
|
||||
if (pSoldier->aiData.bOppList[ pOpponent->ubID ] == SEEN_CURRENTLY)
|
||||
return ( TRUE );
|
||||
}
|
||||
}
|
||||
for ( cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; cnt++ )
|
||||
{
|
||||
pSoldier = MercPtrs[ cnt ];
|
||||
|
||||
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE)
|
||||
{
|
||||
// This assertion can be safely removed, assuming the program does what it should. It simply checks
|
||||
// whether the "opponent" is on the same team being checked. That should be avoided when calling this
|
||||
// function.
|
||||
//Assert( pOpponent->bSide != bSide );
|
||||
|
||||
if (pSoldier->aiData.bOppList[ pOpponent->ubID ] == SEEN_CURRENTLY)
|
||||
return ( TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
return ( FALSE );
|
||||
}
|
||||
// Check enemy visibility
|
||||
else if (bTeam == ENEMY_TEAM)
|
||||
{
|
||||
for ( cnt = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; cnt <= gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; cnt++ )
|
||||
{
|
||||
pSoldier = MercPtrs[ cnt ];
|
||||
|
||||
if (pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife >= OKLIFE)
|
||||
{
|
||||
// This assertion can be safely removed, assuming the program does what it should. It simply checks
|
||||
// whether the "opponent" is on the same team being checked. That should be avoided when calling this
|
||||
// function.
|
||||
//Assert( pOpponent->bSide != bSide );
|
||||
|
||||
if (pSoldier->aiData.bOppList[ pOpponent->ubID ] == SEEN_CURRENTLY)
|
||||
return ( TRUE );
|
||||
}
|
||||
}
|
||||
return ( FALSE );
|
||||
}
|
||||
|
||||
else
|
||||
return (FALSE);
|
||||
|
||||
}
|
||||
|
||||
// HEADROCK: Function to assess an enemy's threat value without "me" argument.
|
||||
INT32 CalcStraightThreatValue( SOLDIERTYPE *pEnemy )
|
||||
{
|
||||
INT32 iThreatValue = 0;
|
||||
|
||||
// If man is inactive, at base, on assignment, dead, unconscious
|
||||
if (!pEnemy->bActive || !pEnemy->bInSector || !pEnemy->stats.bLife )
|
||||
{
|
||||
// he's no threat at all, return a negative number
|
||||
iThreatValue = 0;
|
||||
return(iThreatValue);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// ADD twice the man's level (2-20)
|
||||
iThreatValue += pEnemy->stats.bExpLevel;
|
||||
|
||||
// ADD man's total action points (10-35)
|
||||
iThreatValue += pEnemy->CalcActionPoints();
|
||||
|
||||
// ADD 1/2 of man's current action points (4-17)
|
||||
iThreatValue += (pEnemy->bActionPoints / 2);
|
||||
|
||||
// ADD 1/10 of man's current health (0-10)
|
||||
iThreatValue += (pEnemy->stats.bLife / 10);
|
||||
|
||||
if (pEnemy->bAssignment < ON_DUTY )
|
||||
{
|
||||
// ADD 1/4 of man's protection percentage (0-25)
|
||||
iThreatValue += ArmourPercent( pEnemy ) / 4;
|
||||
|
||||
// ADD 1/5 of man's marksmanship skill (0-20)
|
||||
iThreatValue += (pEnemy->stats.bMarksmanship / 5);
|
||||
|
||||
if ( Item[ pEnemy->inv[HANDPOS].usItem ].usItemClass & IC_WEAPON )
|
||||
{
|
||||
// ADD the deadliness of the item(weapon) he's holding (0-50)
|
||||
iThreatValue += Weapon[pEnemy->inv[HANDPOS].usItem].ubDeadliness;
|
||||
}
|
||||
}
|
||||
|
||||
// SUBTRACT 1/5 of man's bleeding (0-20)
|
||||
iThreatValue -= (pEnemy->bBleeding / 5);
|
||||
|
||||
// SUBTRACT 1/10 of man's breath deficiency (0-10)
|
||||
iThreatValue -= ((100 - pEnemy->bBreath) / 10);
|
||||
|
||||
// SUBTRACT man's current shock value
|
||||
iThreatValue -= pEnemy->aiData.bShock;
|
||||
}
|
||||
|
||||
// if this man is conscious
|
||||
if (pEnemy->stats.bLife < OKLIFE)
|
||||
{
|
||||
// if he's still something of a threat
|
||||
if (iThreatValue > 0)
|
||||
{
|
||||
// drastically reduce his threat value (divide by 5 to 18)
|
||||
iThreatValue /= (4 + (OKLIFE - pEnemy->stats.bLife));
|
||||
}
|
||||
}
|
||||
|
||||
// threat value of any opponent can never drop below 1
|
||||
if (iThreatValue < 0)
|
||||
{
|
||||
iThreatValue = 0;
|
||||
}
|
||||
|
||||
return(iThreatValue);
|
||||
}
|
||||
|
||||
+20
-4
@@ -1296,7 +1296,9 @@ void CalcBestStab(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestStab, BOOLEAN fBladeAt
|
||||
}
|
||||
}
|
||||
else
|
||||
ubChanceToHit = MAXCHANCETOHIT;
|
||||
// HEADROCK (HAM): Externalized maximum to JA2_OPTIONS.INI
|
||||
// ubChanceToHit = MAXCHANCETOHIT;
|
||||
ubChanceToHit = gGameExternalOptions.iMaximumCTH;
|
||||
//NumMessage("chance to Hit = ",ubChanceToHit);
|
||||
|
||||
//sprintf(tempstr,"Vs. %s, at AimTime %d, ubChanceToHit = %d",ExtMen[pOpponent->ubID].name,ubAimTime,ubChanceToHit);
|
||||
@@ -1473,7 +1475,9 @@ void CalcTentacleAttack(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestStab )
|
||||
ubChanceToHit = (INT16) CalcChanceToStab(pSoldier,pOpponent,ubAimTime);
|
||||
}
|
||||
else
|
||||
ubChanceToHit = MAXCHANCETOHIT;
|
||||
// HEADROCK (HAM): Externalized maximum to JA2_OPTIONS.INI
|
||||
// ubChanceToHit = MAXCHANCETOHIT;
|
||||
ubChanceToHit = gGameExternalOptions.iMaximumCTH;
|
||||
//NumMessage("chance to Hit = ",ubChanceToHit);
|
||||
|
||||
//sprintf(tempstr,"Vs. %s, at AimTime %d, ubChanceToHit = %d",ExtMen[pOpponent->ubID].name,ubAimTime,ubChanceToHit);
|
||||
@@ -2472,8 +2476,20 @@ void CheckIfShotPossible(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN s
|
||||
}
|
||||
|
||||
//if ( (!suppressionFire && ( (IsScoped(pObj) && GunRange(pObj) > pSoldier->MaxDistanceVisible(pBestShot->sTarget, pBestShot->bTargetLevel) ) || pSoldier->bOrders == SNIPER ) ) ||
|
||||
if ( (!suppressionFire && ( (IsScoped(pObj) && GunRange(pObj) > MaxNormalDistanceVisible() ) || pSoldier->aiData.bOrders == SNIPER ) ) ||
|
||||
(suppressionFire && IsGunAutofireCapable(&pSoldier->inv[pBestShot->bWeaponIn] ) && GetMagSize(pObj) > 30 && (*pObj)[0]->data.gun.ubGunShotsLeft > 20 ))
|
||||
// HEADROCK HAM B2.4: Changed this again - weapons are no longer checked for larger magazine to allow suppressive fire, due to
|
||||
// suppressive fire revamp.
|
||||
// if ( (!suppressionFire && ( (IsScoped(pObj) && GunRange(pObj) > MaxNormalDistanceVisible() ) || pSoldier->aiData.bOrders == SNIPER ) ) ||
|
||||
// (suppressionFire && IsGunAutofireCapable(&pSoldier->inv[pBestShot->bWeaponIn] ) && GetMagSize(pObj) > 30 && (*pObj)[0]->data.gun.ubGunShotsLeft > 20 ))
|
||||
BOOLEAN fEnableAISuppression = FALSE;
|
||||
|
||||
if ( gGameExternalOptions.fIncreaseAISuppressionFire && ((!suppressionFire && ( (IsScoped(pObj) && GunRange(pObj) > MaxNormalDistanceVisible() ) || pSoldier->aiData.bOrders == SNIPER ) ) ||
|
||||
(suppressionFire && IsGunAutofireCapable(&pSoldier->inv[pBestShot->bWeaponIn]))) )
|
||||
fEnableAISuppression = TRUE;
|
||||
else if ( !gGameExternalOptions.fIncreaseAISuppressionFire && ( (!suppressionFire && ( (IsScoped(pObj) && GunRange(pObj) > MaxNormalDistanceVisible() ) || pSoldier->aiData.bOrders == SNIPER ) ) ||
|
||||
(suppressionFire && IsGunAutofireCapable(&pSoldier->inv[pBestShot->bWeaponIn] ) && GetMagSize(pObj) > 30 && (*pObj)[0]->data.gun.ubGunShotsLeft > 20 )))
|
||||
fEnableAISuppression = TRUE;
|
||||
|
||||
if (fEnableAISuppression)
|
||||
{
|
||||
// get the minimum cost to attack with this item
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"CheckIfShotPossible: getting min aps");
|
||||
|
||||
@@ -1950,6 +1950,8 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
BOOLEAN fCivilian = (PTR_CIVILIAN && (pSoldier->ubCivilianGroup == NON_CIV_GROUP ||
|
||||
(pSoldier->aiData.bNeutral && gTacticalStatus.fCivGroupHostile[pSoldier->ubCivilianGroup] == CIV_GROUP_NEUTRAL) ||
|
||||
(pSoldier->ubBodyType >= FATCIV && pSoldier->ubBodyType <= CRIPPLECIV) ) );
|
||||
// HEADROCK HAM B2.7: Calculate the overall tactical situation
|
||||
INT16 ubOverallTacticalSituation = AssessTacticalSituation(pSoldier->bSide);
|
||||
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,String("DecideActionRed: soldier orders = %d",pSoldier->aiData.bOrders));
|
||||
|
||||
@@ -2313,7 +2315,17 @@ if(!is_networked)//hayden
|
||||
CheckIfShotPossible(pSoldier,&BestShot,TRUE);
|
||||
|
||||
//must have a small chance to hit and the opponent must be on the ground (can't suppress guys on the roof)
|
||||
if ( BestShot.ubPossible && BestShot.ubChanceToReallyHit < 50 && Menptr[BestShot.ubOpponent].pathing.bLevel == 0 && pSoldier->aiData.bOrders != SNIPER )
|
||||
// HEADROCK HAM BETA2.4: Adjusted this for a random chance to suppress regardless of chance. This augments
|
||||
// current revamp of suppression fire.
|
||||
BOOLEAN fEnableAIAutofire = FALSE;
|
||||
|
||||
if ( gGameExternalOptions.fIncreaseAISuppressionFire && ( ( BestShot.ubPossible && BestShot.ubChanceToReallyHit < 50 ) || (BestShot.ubPossible && BestShot.ubChanceToReallyHit < PreRandom(100)) && Menptr[BestShot.ubOpponent].pathing.bLevel == 0 && pSoldier->aiData.bOrders != SNIPER ))
|
||||
fEnableAIAutofire = TRUE;
|
||||
|
||||
else if ( !gGameExternalOptions.fIncreaseAISuppressionFire && ( BestShot.ubPossible && BestShot.ubChanceToReallyHit < 50 && Menptr[BestShot.ubOpponent].pathing.bLevel == 0 && pSoldier->aiData.bOrders != SNIPER ))
|
||||
fEnableAIAutofire = TRUE;
|
||||
|
||||
if (fEnableAIAutofire)
|
||||
{
|
||||
// then do it!
|
||||
|
||||
@@ -3141,7 +3153,23 @@ if(!is_networked)//hayden
|
||||
{
|
||||
// only try to run if we've actually been hit recently & noticably so
|
||||
// otherwise, presumably our current cover is pretty good & sufficient
|
||||
if (pSoldier->aiData.bShock > 0 || fCivilian)
|
||||
// HEADROCK HAM B2.6: New value here helps us change the ratio of running away due to shock. This
|
||||
// is terribly important if Suppression Shock is enabled.
|
||||
UINT16 bShock = 0;
|
||||
|
||||
if (gGameExternalOptions.fSuppressionShock)
|
||||
{
|
||||
// If bShock value is greater than (2*ExpLevel + MoraleModifier)*1.5, the target will flee.
|
||||
bShock = pSoldier->aiData.bShock;
|
||||
if (bShock <= ((float)CalcSuppressionTolerance(pSoldier)*(float)1.5))
|
||||
bShock = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bShock = pSoldier->aiData.bShock;
|
||||
}
|
||||
|
||||
if (bShock > 0 || fCivilian)
|
||||
{
|
||||
// look for best place to RUN AWAY to (farthest from the closest threat)
|
||||
pSoldier->aiData.usActionData = FindSpotMaxDistFromOpponents(pSoldier);
|
||||
@@ -4424,7 +4452,10 @@ INT8 DecideActionBlack(SOLDIERTYPE *pSoldier)
|
||||
case ATTACKSLAYONLY:iChance += 30; break;
|
||||
}
|
||||
|
||||
if ( pSoldier->inv[BestAttack.bWeaponIn][0]->data.gun.ubGunShotsLeft > 50 )
|
||||
// HEADROCK HAM B2.6: Allows control over increased enemy burstfire.
|
||||
if ( gGameExternalOptions.fIncreaseAISuppressionFire && pSoldier->inv[BestAttack.bWeaponIn][0]->data.gun.ubGunShotsLeft > 10 )
|
||||
iChance += 20;
|
||||
else if ( !gGameExternalOptions.fIncreaseAISuppressionFire && pSoldier->inv[BestAttack.bWeaponIn][0]->data.gun.ubGunShotsLeft > 50 )
|
||||
iChance += 20;
|
||||
|
||||
// increase chance based on proximity and difficulty of enemy
|
||||
@@ -4502,7 +4533,10 @@ INT8 DecideActionBlack(SOLDIERTYPE *pSoldier)
|
||||
}
|
||||
|
||||
|
||||
if ( pSoldier->inv[BestAttack.bWeaponIn][0]->data.gun.ubGunShotsLeft > 50 )
|
||||
// HEADROCK HAM B2.6: Allows control over increased enemy autofire.
|
||||
if ( gGameExternalOptions.fIncreaseAISuppressionFire && pSoldier->inv[BestAttack.bWeaponIn][0]->data.gun.ubGunShotsLeft > 20 )
|
||||
iChance += 30;
|
||||
else if ( !gGameExternalOptions.fIncreaseAISuppressionFire && pSoldier->inv[BestAttack.bWeaponIn][0]->data.gun.ubGunShotsLeft > 50 )
|
||||
iChance += 30;
|
||||
|
||||
if ( bInGas )
|
||||
|
||||
+76
-34
@@ -16,6 +16,8 @@
|
||||
#include "overhead.h"
|
||||
#include "Cursor Control.h"
|
||||
#include "Sound Control.h"
|
||||
// HEADROCK HAM B2.6: included this here to allow toggling the CTH bars.
|
||||
#include "GameSettings.h"
|
||||
#endif
|
||||
|
||||
//aim
|
||||
@@ -1244,10 +1246,11 @@ extern UINT16 gsCurMouseWidth;*/
|
||||
|
||||
void DrawMouseGraphics( )
|
||||
{
|
||||
// HEADROCK (HAM): Made several changes here to allow multi-shot CtH display for bursts.
|
||||
UINT16 * ptrBuf;
|
||||
UINT32 uiPitch;
|
||||
UINT32 cnt;
|
||||
UINT32 actualPct = __min(gbCtH,99);
|
||||
UINT32 cnt, i;
|
||||
UINT32 actualPct = __min(gbCtH[0],99);
|
||||
UINT16 usCBorderTop = Get16BPPColor( FROMRGB( 155, 155, 155 ) );
|
||||
UINT16 usCBorderBottom = Get16BPPColor( FROMRGB( 120, 120, 120 ) );
|
||||
UINT16 usCBar = Get16BPPColor( FROMRGB( 255, 255-255*actualPct/99, 0 ) );
|
||||
@@ -1255,40 +1258,67 @@ void DrawMouseGraphics( )
|
||||
UINT16 usCBar2 = Get16BPPColor( FROMRGB( 180, 140-140*actualPct/99, 0 ) );
|
||||
UINT16 usCBack2 = Get16BPPColor( FROMRGB( 110, 100-100*actualPct/99, 0 ) );
|
||||
UINT32 barLength = __min(35,gsCurMouseWidth);
|
||||
UINT32 barY = gsCurMouseOffsetY-__min(35,gsCurMouseHeight)/2;
|
||||
//UINT32 barY = gsCurMouseOffsetY-__min(35,gsCurMouseHeight)/2;
|
||||
UINT32 barY;
|
||||
|
||||
if(gfUICtHBar)
|
||||
{
|
||||
ptrBuf = (UINT16 *) LockMouseBuffer( &uiPitch );
|
||||
uiPitch >>= 1;
|
||||
// HEADROCK HAM B1/2/2.6:
|
||||
// This causes the function to display two CTH bars for autofire - the CTH of the first bullet,
|
||||
// and the CTH of the last bullet in the volley, stored in gbCtH[0] and [1] respectively.
|
||||
if ( gbCtHAutoFire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3) )
|
||||
gbCtHBurstCount = 2;
|
||||
else if ( gbCtHAutoFire )
|
||||
gbCtHBurstCount = 0;
|
||||
|
||||
|
||||
for(cnt = gsCurMouseOffsetX+barLength/2;cnt > gsCurMouseOffsetX-barLength/2+1;cnt--)
|
||||
// Sets the initial offsets of the bars. Burst and Autofire will display them higher above the
|
||||
// cursor, to avoid obscuring the target or other data.
|
||||
if (gbCtHBurstCount > 1 && !gbCtHAutoFire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 2) )
|
||||
barY = gsCurMouseOffsetY-__min(55,gsCurMouseHeight)/2;
|
||||
else if (gbCtHBurstCount && gbCtHAutoFire && (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3) )
|
||||
barY = gsCurMouseOffsetY-__min(55,gsCurMouseHeight)/2;
|
||||
else
|
||||
barY = gsCurMouseOffsetY-__min(35,gsCurMouseHeight)/2;
|
||||
|
||||
for (i=0; i<gbCtHBurstCount; i++)
|
||||
{
|
||||
ptrBuf[cnt-1 + uiPitch*(3+barY)] = usCBorderBottom;
|
||||
ptrBuf[cnt-1 + uiPitch*barY] = usCBorderTop;
|
||||
actualPct = __min(gbCtH[ i ],99);
|
||||
|
||||
ptrBuf = (UINT16 *) LockMouseBuffer( &uiPitch );
|
||||
uiPitch >>= 1;
|
||||
|
||||
for(cnt = gsCurMouseOffsetX+barLength/2;cnt > gsCurMouseOffsetX-barLength/2+1;cnt--)
|
||||
{
|
||||
ptrBuf[cnt-1 + uiPitch*(3+barY)] = usCBorderBottom;
|
||||
ptrBuf[cnt-1 + uiPitch*barY] = usCBorderTop;
|
||||
}
|
||||
|
||||
ptrBuf[gsCurMouseOffsetX+barLength/2 + uiPitch*(1+barY)] = usCBorderBottom;
|
||||
ptrBuf[gsCurMouseOffsetX-barLength/2 + uiPitch*(1+barY)] = usCBorderTop;
|
||||
|
||||
ptrBuf[gsCurMouseOffsetX+barLength/2 + uiPitch*(2+barY)] = usCBorderBottom;
|
||||
ptrBuf[gsCurMouseOffsetX-barLength/2 + uiPitch*(2+barY)] = usCBorderTop;
|
||||
|
||||
|
||||
for(cnt = 0;cnt < (barLength-2)*actualPct/99;cnt++)
|
||||
{
|
||||
ptrBuf[cnt + gsCurMouseOffsetX-barLength/2+1 + uiPitch*(barY+2)] = usCBar2;
|
||||
ptrBuf[cnt + gsCurMouseOffsetX-barLength/2+1 + uiPitch*(barY+1)] = usCBar;
|
||||
}
|
||||
|
||||
for(cnt = (barLength-2)*actualPct/99;cnt < (barLength-2);cnt++)
|
||||
{
|
||||
ptrBuf[cnt + gsCurMouseOffsetX-barLength/2+1 + uiPitch*(barY+2)] = usCBack2;
|
||||
ptrBuf[cnt + gsCurMouseOffsetX-barLength/2+1 + uiPitch*(barY+1)] = usCBack;
|
||||
}
|
||||
|
||||
|
||||
UnlockMouseBuffer();
|
||||
if (gbCtHBurstCount>1)
|
||||
barY = barY+5;
|
||||
}
|
||||
|
||||
ptrBuf[gsCurMouseOffsetX+barLength/2 + uiPitch*(1+barY)] = usCBorderBottom;
|
||||
ptrBuf[gsCurMouseOffsetX-barLength/2 + uiPitch*(1+barY)] = usCBorderTop;
|
||||
|
||||
ptrBuf[gsCurMouseOffsetX+barLength/2 + uiPitch*(2+barY)] = usCBorderBottom;
|
||||
ptrBuf[gsCurMouseOffsetX-barLength/2 + uiPitch*(2+barY)] = usCBorderTop;
|
||||
|
||||
|
||||
for(cnt = 0;cnt < (barLength-2)*actualPct/99;cnt++)
|
||||
{
|
||||
ptrBuf[cnt + gsCurMouseOffsetX-barLength/2+1 + uiPitch*(barY+2)] = usCBar2;
|
||||
ptrBuf[cnt + gsCurMouseOffsetX-barLength/2+1 + uiPitch*(barY+1)] = usCBar;
|
||||
}
|
||||
|
||||
for(cnt = (barLength-2)*actualPct/99;cnt < (barLength-2);cnt++)
|
||||
{
|
||||
ptrBuf[cnt + gsCurMouseOffsetX-barLength/2+1 + uiPitch*(barY+2)] = usCBack2;
|
||||
ptrBuf[cnt + gsCurMouseOffsetX-barLength/2+1 + uiPitch*(barY+1)] = usCBack;
|
||||
}
|
||||
|
||||
|
||||
UnlockMouseBuffer();
|
||||
barY = gsCurMouseOffsetY-__min(35,gsCurMouseHeight)/2;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1346,11 +1376,23 @@ void DrawMouseText( )
|
||||
|
||||
swprintf( pStr, L"%d", gsBulletCount );
|
||||
FindFontCenterCoordinates( 0, 0, gsCurMouseWidth, gsCurMouseHeight, pStr, TINYFONT1, &sX, &sY );
|
||||
mprintf( sX, sY - 10 - GetFontHeight(TINYFONT1), pStr );
|
||||
// HEADROCK HAM B2: Moved bullet counter to right side (and a bit upwards) to accomodate two CTH bars.
|
||||
//mprintf( sX, sY - 10 - GetFontHeight(TINYFONT1), pStr );
|
||||
if (gGameExternalOptions.iNewCTHBars == 1 || gGameExternalOptions.iNewCTHBars == 3)
|
||||
// New CTH Bar moves bullet count to new location.
|
||||
mprintf( 46, sY - 15 - GetFontHeight(TINYFONT1), pStr );
|
||||
else
|
||||
// Vanilla 1.13
|
||||
mprintf( sX, sY - 10 - GetFontHeight(TINYFONT1), pStr );
|
||||
|
||||
swprintf( pStr, L"%d", gsTotalBulletCount );
|
||||
FindFontCenterCoordinates( 0, 0, gsCurMouseWidth, gsCurMouseHeight, pStr, TINYFONT1, &sX, &sY );
|
||||
mprintf( sX, sY + 7 + GetFontHeight(TINYFONT1), pStr );
|
||||
// HEADROCK HAM B2: Removed this. The bottom line will now display bodypart targetting, like Burst and
|
||||
// Single.
|
||||
if ( gGameExternalOptions.iNewCTHBars != 1 && gGameExternalOptions.iNewCTHBars != 3 )
|
||||
{
|
||||
swprintf( pStr, L"%d", gsTotalBulletCount );
|
||||
FindFontCenterCoordinates( 0, 0, gsCurMouseWidth, gsCurMouseHeight, pStr, TINYFONT1, &sX, &sY );
|
||||
mprintf( sX, sY + 7 + GetFontHeight(TINYFONT1), pStr );
|
||||
}
|
||||
|
||||
// reset
|
||||
SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
|
||||
|
||||
@@ -1653,6 +1653,8 @@ extern STR16 New113Message[];
|
||||
extern STR16 New113MERCMercMailTexts[];
|
||||
extern STR16 MissingIMPSkillsDescriptions[];
|
||||
|
||||
// HEADROCK: HAM Messages
|
||||
extern STR16 New113HAMMessage[];
|
||||
enum
|
||||
{
|
||||
MSG113_STORM_STARTED,
|
||||
|
||||
@@ -5091,9 +5091,10 @@ STR16 sRepairsDoneString[] =
|
||||
L"%s修复了自己的物品。",
|
||||
L"%s修复了所有人的枪和护甲。",
|
||||
L"%s修复了所有人的装备。",
|
||||
L"%s修复了所有人的携带物品。",
|
||||
L"%s修复了所有人的携带物品。",
|
||||
L"%s修复了所有人的携带物品。",
|
||||
L"%s finished repairing everyone's large carried items",
|
||||
L"%s finished repairing everyone's medium carried items",
|
||||
L"%s finished repairing everyone's small carried items",
|
||||
L"%s finished repairing everyone's LBE gear",
|
||||
};
|
||||
|
||||
STR16 zGioDifConfirmText[]=
|
||||
@@ -5406,6 +5407,11 @@ STR16 New113Message[] =
|
||||
L"你得检查一下你的眼部装备",
|
||||
};
|
||||
|
||||
STR16 New113HAMMessage[] =
|
||||
{
|
||||
L"%s cowers in fear!",
|
||||
};
|
||||
|
||||
// WANNE: This are the email texts, when one of the 4 new 1.13 MERC mercs have levelled up, that Speck sends
|
||||
// INFO: Do not replace the ?characters. They indicate the <B2> (-> Newline) from the edt files
|
||||
STR16 New113MERCMercMailTexts[] =
|
||||
|
||||
@@ -4243,9 +4243,10 @@ STR16 sRepairsDoneString[] =
|
||||
L"%s is klaar met reparatie van eigen items",
|
||||
L"%s is klaar met reparatie van ieders wapens en bepantering",
|
||||
L"%s is klaar met reparatie van ieders uitrusting",
|
||||
L"%s is klaar met reparatie van ieders vervoerde items",
|
||||
L"%s is klaar met reparatie van ieders vervoerde items",
|
||||
L"%s is klaar met reparatie van ieders vervoerde items",
|
||||
L"%s finished repairing everyone's large carried items",
|
||||
L"%s finished repairing everyone's medium carried items",
|
||||
L"%s finished repairing everyone's small carried items",
|
||||
L"%s finished repairing everyone's LBE gear",
|
||||
};
|
||||
|
||||
STR16 zGioDifConfirmText[]=
|
||||
@@ -4474,6 +4475,11 @@ STR16 New113Message[] =
|
||||
L"You should check your goggles",
|
||||
};
|
||||
|
||||
STR16 New113HAMMessage[] =
|
||||
{
|
||||
L"%s cowers in fear!",
|
||||
};
|
||||
|
||||
// WANNE: This are the email texts, when one of the 4 new 1.13 MERC mercs have levelled up, that Speck sends
|
||||
// INFO: Do not replace the ± characters. They indicate the <B2> (-> Newline) from the edt files
|
||||
STR16 New113MERCMercMailTexts[] =
|
||||
|
||||
+10
-3
@@ -4250,14 +4250,16 @@ STR16 gzCreditNameFunny[]=
|
||||
L"(did items and loading screens too!)", // Joey \"Joeker\" Whelan",
|
||||
};
|
||||
|
||||
// HEADROCK: Adjusted strings for better feedback, and added new string for LBE repair.
|
||||
STR16 sRepairsDoneString[] =
|
||||
{
|
||||
L"%s finished repairing own items",
|
||||
L"%s finished repairing everyone's guns & armor",
|
||||
L"%s finished repairing everyone's equipped items",
|
||||
L"%s finished repairing everyone's carried items",
|
||||
L"%s finished repairing everyone's carried items",
|
||||
L"%s finished repairing everyone's carried items",
|
||||
L"%s finished repairing everyone's large carried items",
|
||||
L"%s finished repairing everyone's medium carried items",
|
||||
L"%s finished repairing everyone's small carried items",
|
||||
L"%s finished repairing everyone's LBE gear",
|
||||
};
|
||||
|
||||
STR16 zGioDifConfirmText[]=
|
||||
@@ -4486,6 +4488,11 @@ STR16 New113Message[] =
|
||||
L"You should check your goggles",
|
||||
};
|
||||
|
||||
STR16 New113HAMMessage[] =
|
||||
{
|
||||
L"%s cowers in fear!",
|
||||
};
|
||||
|
||||
// WANNE: This are the email texts, when one of the 4 new 1.13 MERC mercs have levelled up, that Speck sends
|
||||
// INFO: Do not replace the ± characters. They indicate the <B2> (-> Newline) from the edt files
|
||||
STR16 New113MERCMercMailTexts[] =
|
||||
|
||||
@@ -4256,9 +4256,10 @@ STR16 sRepairsDoneString[] =
|
||||
L"%s a terminé la réparation de ses objets",
|
||||
L"%s a terminé la réparation des armes & protections",
|
||||
L"%s a terminé la réparation des objets portés",
|
||||
L"%s a terminé la réparation des objets transportés",
|
||||
L"%s a terminé la réparation des objets transportés",
|
||||
L"%s a terminé la réparation des objets transportés",
|
||||
L"%s finished repairing everyone's large carried items",
|
||||
L"%s finished repairing everyone's medium carried items",
|
||||
L"%s finished repairing everyone's small carried items",
|
||||
L"%s finished repairing everyone's LBE gear",
|
||||
};
|
||||
|
||||
STR16 zGioDifConfirmText[]=
|
||||
@@ -4487,6 +4488,11 @@ STR16 New113Message[] =
|
||||
L"Vous devriez vérifier votre accessoire de vision",
|
||||
};
|
||||
|
||||
STR16 New113HAMMessage[] =
|
||||
{
|
||||
L"%s cowers in fear!",
|
||||
};
|
||||
|
||||
// WANNE: This are the email texts, when one of the 4 new 1.13 MERC mercs have levelled up, that Speck sends
|
||||
// INFO: Do not replace the ± characters. They indicate the <B2> (-> Newline) from the edt files
|
||||
STR16 New113MERCMercMailTexts[] =
|
||||
|
||||
@@ -4058,9 +4058,10 @@ STR16 sRepairsDoneString[] =
|
||||
L"%s hat seine eigenen Gegenstände repariert",
|
||||
L"%s hat die Waffen und Rüstungen aller Teammitglieder repariert",
|
||||
L"%s hat die aktivierten Gegenstände aller Teammitglieder repariert",
|
||||
L"%s hat die mitgeführten Gegenstände aller Teammitglieder repariert",
|
||||
L"%s hat die mitgeführten Gegenstände aller Teammitglieder repariert",
|
||||
L"%s hat die mitgeführten Gegenstände aller Teammitglieder repariert",
|
||||
L"%s hat die großen mitgeführten Gegenstände aller Teammitglieder repariert",
|
||||
L"%s hat die mittelgroßen mitgeführten Gegenstände aller Teammitglieder repariert",
|
||||
L"%s hat die kleinen mitgeführten Gegenstände aller Teammitglieder repariert",
|
||||
L"%s hat die LBE-Gegenstände aller Teammitglieder repariert",
|
||||
};
|
||||
|
||||
STR16 zGioDifConfirmText[]=
|
||||
@@ -4282,6 +4283,11 @@ STR16 New113Message[] =
|
||||
L"Sie sollten Ihre Brillen prüfen",
|
||||
};
|
||||
|
||||
STR16 New113HAMMessage[] =
|
||||
{
|
||||
L"%s cowers in fear!",
|
||||
};
|
||||
|
||||
// WANNE: This are the email texts, when one of the 4 new 1.13 MERC mercs have levelled up, that Speck sends
|
||||
// INFO: Do not replace the ± characters. They indicate the <B2> (-> Newline) from the edt files
|
||||
STR16 New113MERCMercMailTexts[] =
|
||||
|
||||
@@ -4235,9 +4235,10 @@ STR16 sRepairsDoneString[] =
|
||||
L"%s ha finito di riparare gli oggetti",
|
||||
L"%s ha finito di riparare le armi e i giubbotti antiproiettile di tutti",
|
||||
L"%s ha finito di riparare gli oggetti dell'equipaggiamento di tutti",
|
||||
L"%s ha finito di riparare gli oggetti trasportati di tutti",
|
||||
L"%s ha finito di riparare gli oggetti trasportati di tutti",
|
||||
L"%s ha finito di riparare gli oggetti trasportati di tutti",
|
||||
L"%s finished repairing everyone's large carried items",
|
||||
L"%s finished repairing everyone's medium carried items",
|
||||
L"%s finished repairing everyone's small carried items",
|
||||
L"%s finished repairing everyone's LBE gear",
|
||||
};
|
||||
|
||||
STR16 zGioDifConfirmText[]=
|
||||
@@ -4472,6 +4473,11 @@ STR16 New113Message[] =
|
||||
L"You should check your goggles",
|
||||
};
|
||||
|
||||
STR16 New113HAMMessage[] =
|
||||
{
|
||||
L"%s cowers in fear!",
|
||||
};
|
||||
|
||||
// WANNE: This are the email texts, when one of the 4 new 1.13 MERC mercs have levelled up, that Speck sends
|
||||
// INFO: Do not replace the ± characters. They indicate the <B2> (-> Newline) from the edt files
|
||||
STR16 New113MERCMercMailTexts[] =
|
||||
|
||||
@@ -4248,9 +4248,10 @@ STR16 sRepairsDoneString[] =
|
||||
L"%s skoñczy³(a) naprawiaæ w³asne wyposa¿enie",
|
||||
L"%s skoñczy³(a) naprawiaæ broñ i ochraniacze wszystkich cz³onków oddzia³u",
|
||||
L"%s skoñczy³(a) naprawiaæ wyposa¿enie wszystkich cz³onków oddzia³u",
|
||||
L"%s skończył(a) naprawiać ekwipunek wszystkich członków oddziału",
|
||||
L"%s zakończył(a) naprawę ekwipunku oddziału",
|
||||
L"%s zakończył(a) naprawę ekwipunku oddziału",
|
||||
L"%s finished repairing everyone's large carried items",
|
||||
L"%s finished repairing everyone's medium carried items",
|
||||
L"%s finished repairing everyone's small carried items",
|
||||
L"%s finished repairing everyone's LBE gear",
|
||||
};
|
||||
|
||||
STR16 zGioDifConfirmText[]=
|
||||
@@ -4479,6 +4480,11 @@ STR16 New113Message[] =
|
||||
L"SprawdŸ swoje gogle",
|
||||
};
|
||||
|
||||
STR16 New113HAMMessage[] =
|
||||
{
|
||||
L"%s cowers in fear!",
|
||||
};
|
||||
|
||||
// WANNE: This are the email texts, when one of the 4 new 1.13 MERC mercs have levelled up, that Speck sends
|
||||
// INFO: Do not replace the ± characters. They indicate the <B2> (-> Newline) from the edt files
|
||||
STR16 New113MERCMercMailTexts[] =
|
||||
|
||||
@@ -4250,9 +4250,10 @@ STR16 sRepairsDoneString[] =
|
||||
L"%s: çàâåðøåí ðåìîíò ëè÷íûõ âåùåé.",
|
||||
L"%s: çàâåðøåí ðåìîíò âñåãî îðóæèÿ è áðîíè.",
|
||||
L"%s: çàâåðøåí ðåìîíò âñåé ýêèïèðîâêè îòðÿäà.",
|
||||
L"%s: ηΰβεπψεν πεμξνς βρευ βεωει, θμεώωθυρ� σ ξςπ�δΰ.",
|
||||
L"%s: ηΰβεπψεν πεμξνς βρευ βεωει, θμεώωθυρ� σ ξςπ�δΰ.",
|
||||
L"%s: ηΰβεπψεν πεμξνς βρευ βεωει, θμεώωθυρ� σ ξςπ�δΰ.",
|
||||
L"%s finished repairing everyone's large carried items",
|
||||
L"%s finished repairing everyone's medium carried items",
|
||||
L"%s finished repairing everyone's small carried items",
|
||||
L"%s finished repairing everyone's LBE gear",
|
||||
};
|
||||
|
||||
STR16 zGioDifConfirmText[]=
|
||||
@@ -4482,6 +4483,11 @@ STR16 New113Message[] =
|
||||
L"Ïðîâåðü ÷òî ñîëäàòó ìåøàåò ëó÷øå âèäåòü.", //You should check your goggles
|
||||
};
|
||||
|
||||
STR16 New113HAMMessage[] =
|
||||
{
|
||||
L"%s cowers in fear!",
|
||||
};
|
||||
|
||||
// WANNE: This are the email texts, when one of the 4 new 1.13 MERC mercs have levelled up, that Speck sends
|
||||
// INFO: Do not replace the ± characters. They indicate the <B2> (-> Newline) from the edt files
|
||||
STR16 New113MERCMercMailTexts[] =
|
||||
|
||||
@@ -4255,9 +4255,10 @@ STR16 sRepairsDoneString[] =
|
||||
L"%s finished repairing own items",
|
||||
L"%s finished repairing everyone's guns & armor",
|
||||
L"%s finished repairing everyone's equipped items",
|
||||
L"%s finished repairing everyone's carried items",
|
||||
L"%s finished repairing everyone's carried items",
|
||||
L"%s finished repairing everyone's carried items",
|
||||
L"%s finished repairing everyone's large carried items",
|
||||
L"%s finished repairing everyone's medium carried items",
|
||||
L"%s finished repairing everyone's small carried items",
|
||||
L"%s finished repairing everyone's LBE gear",
|
||||
};
|
||||
|
||||
STR16 zGioDifConfirmText[]=
|
||||
@@ -4486,6 +4487,11 @@ STR16 New113Message[] =
|
||||
L"You should check your goggles",
|
||||
};
|
||||
|
||||
STR16 New113HAMMessage[] =
|
||||
{
|
||||
L"%s cowers in fear!",
|
||||
};
|
||||
|
||||
// WANNE: This are the email texts, when one of the 4 new 1.13 MERC mercs have levelled up, that Speck sends
|
||||
// INFO: Do not replace the ± characters. They indicate the <B2> (-> Newline) from the edt files
|
||||
STR16 New113MERCMercMailTexts[] =
|
||||
|
||||
Reference in New Issue
Block a user