Home » MODDING HQ 1.13 » v1.13 Modding, Customising, Editing » v1.13 Time Capsule (Howto Library) » "How does it work?" Part 4: ChancetoHit
"How does it work?" Part 4: ChancetoHit[message #196106] 
Tue, 09 September 2008 11:45  
Headrock


Messages:1772
Registered:March 2006 Location: Jerusalem 


I remember downloading a little tool, a long time ago, that allowed me to calculate the ChancetoHit of shots in Jagged Alliance 2. That was a long time ago, way before the 1.13 project started. The calculation was relatively simple, and you could even do it by hand. It was affected by about a dozen factors, but wasn't difficult to calculate them all together, although the tool really helped.
When I started playing 1.13, I was amazed by the CTH bar that appears over my shooting icon. It actually showed how likely my shots were to hit, which helped immensely. It's really hard to play the old JA2 now, without it, and I wonder how I've managed to play the vanilla JA2 at all! Then came the "F" hotkey, which even shows a numeric value of CTH. Life couldn't get much simpler than that.
But the simple calculation is gone now. No longer do we rely on a dozen factors, but several dozen. Nowadays, CTH is affected by everything but the kitched sink. The formula to calculate CTH in 1.13 is extremely complex, and since we only see the result, it can be very confusing. Why is one merc's CTH so much higher? Why is my CTH so low when it looks like I should have a better shot? What the hell is going on with the extra aiming?
Now, there are tons of questions, and it would take a long time to answer all of them one by one. So instead, in the best tradition of "How does it work?", I'm going to make a very ambitious and very foolish attempt to translate the entire CTH calculation into something resembling plain english and 5th grade maths.
The CTH formula is huge. It draws on a lot of factors, and frequently jumps aside, using other functions to make complex calculations. Translating it from C++ to the English Language was very tricky, and in some cases I wasn't even sure I understood what the hell was going on.
The explanation below is written partially in PseudoCode. That's the "English Translation" of the real game code, that is to say I've tried to use simple sentences instead of lines of code, to describe what's going on. In many cases, it remains cryptic as hell despite my best efforts. But at the very least, some things should be BLATANTLY clear.
I hope that this will, at least partially, help us understand what we are doing wrong, and help us reduce an enemy's CTH while increasing our own. I know my tactical understanding of the game has already benefitted from reading the formula, and I hope the same will happen to others who read this.
DISCLAIMER: Yes, this formula is EXTREMELY COMPLEX and you may not understand some/half/all of it. It's the best I could do though.
So, without further ado, the CHANCE TO HIT formula is unveiled!!

The formula is called in several cases, the most important of which is when we actually fire a weapon. But it is also called when we simply put our cursor on an enemy, and when we press the "F" key to see our CTH. In any case, the program will always put these values into the formula:
Shooter: The guy who's firing the gun!
TargetLocation: The point we were aiming at. Doesn't have to be an enemy, we'll see how that works later.
Targetted_Bodypart: The enemy's bodypart we are trying to hit, if there's an enemy at all. Also, when shooting at PRONE enemies or tanks, the targetted bodypart is "none".
AimTime: The number of extra APs we spent aiming at the target.
Armed with these, we can start calculating.

To begin, the program makes sure that the Shooter has some marksmanship:
If Shooter's_Marksmanship = 0 then
ChanceToHit = a big fat 0. stop the calculation and go find something to eat.

Next, the program checks to see whether the weapon we're using has a highpower scope:
For each Attachment on the Weapon, do
If Attachment gives more than +14 Aiming_Bonus, then
HighPowered Scope!
Else
Not a highpowered scope.
Nice to know  scopes that give +15 or more Aiming Bonus are treated differently from others. The program needs to know that it needs to handle a highpowered scope  you'll see the effect this has in later parts of the program.

The program now calculates a modifier based on the gun's condition.
If Weapon_Status is greater than or equal to 85, then
Status_Modifier = 100
else
Status_Modifier = Weapon_Status * 100 / 85
If the condition of the weapon is 85100%, the result (status_modifier) is 100. If the weapon's condition is 84%, the result will be 98. It drops steadily downwards after that. At 0% status, the weapon is broken and can't fire at all, so the result is 0.
We'll keep this value (called "Status_Modifier") for later.

Now we come to the most important part of the CTH formula  we're going to determine the base chancetohit. This is done primarily with our Marksmanship skill. It's done differently for RocketLaunchers, and I'll explain that in a moment. But here's the formula for bulletshooting guns:
Effective_Marksmanship = Shooter's_Actual_Marksmanship
If Shooter is Drunk, then
Effective_Marksmanship = Shooter's_Actual_Marksmanship * Drunkness_Value / 100
If Shooter is a Robot, then
Effective_Marksmanship = Whichever is higher: the Robot's Marksmanship, or the Controller's Marksmanship
Drunkness takes effect here, and the drunkness_value depends on how severely drunk the shooter is.
If you're sober, the value is 100.
At drunkness level 1, the value is 75.
At drunkness level 2, it's 65.
At drunkness level 3, it's 50.
There's also a drunkness level 4 (hung over!) but it doesn't affect shooting (the value is 100, like when you're sober).
So in effect, if you're tipsy, you lose 25% of your effective_marksmanship. If you're drunk, you lose 50%.
Ok, let's get back to business, and see how Rocket Launchers are handled. This is a bit more complex, as it takes into account such things as dexterity and level. I'll do this bit by bit.
If Weapon is a Rocket Launcher, then
Effective_Marksmanship = Average of:
1) Shooter's_Actual_Marksmanship
2) Shooter's_Actual_Dexterity
3) Shooter's_Actual_Wisdom
4) Shooter's_Actual_Level * 10
Each of these are then tempered by drunkness, in the same way explained above. Except level  if you're tipsy (first level of drunkness) there's no effect on level. At the next drunkness stage, you lose 1 level, and when completely drunk you lose 2 levels, for the purposes of this calculation. Again, being hung over doesn't matter here.
Also, level is further adjusted for Claustrophobic mercs. If you've read my previous articles, you'll know that when a Claustrophobic character is underground, their effective level is dropped by one point. Note that the effective level can't ever drop below 1.
Furthermore, the HEAVY_WEAPONS skill now takes effect:
If Weapon is a Rocket Launcher, then
Effective Marksmanship is increased by 15 points per level of the HEAVY_WEAPONS skill.
Pretty straightforward there.

Right, so now we have our basic value, called "Effective_Marksmanship". From now, on, I'm just going to call it "Base_Chance". Later on, we're going to have another value called "Actual_Chance", but that's later.

First up, we're going to modify the Base_Chance a bit, and we'll start with Morale.
Morale works differently for Player Characters and AI characters. PCs have a morale value that goes from 0 to 100. 50, the middle value, is the "normal" state that our mercs are usually in (called "Stable" in the game). At 100, our morale is highest, and at very low values we get deserters. The AI however simply has four different morale "stages", going from "hopeless" to "worried" to "confident" to "fearless.
With PCs, this is the formula:
If Soldier's_Morale > 50, then
Morale_Modifier = (Soldier's_Morale  45) / 100
Else
Morale_Modifier = (Soldier's_Morale  50) * 2 / 5
Effectively it means that at 55 morale, you get +1 Morale Modifier, and an extra +1 for each 10 points above 55. At 95100 morale, we get the maximum bonus, which is +5.
When our morale is around 47, we get 1 penalty, and an extra 1 for each 23 points below 47. At 1 morale we get a whopping 20 modifier!
With NPCs, each "stage" of morale gives a different bonus:
"Hopeless" morale gives 15
"Worried" morale gives 7
"Confident" morale gives +2
"Fearless" morale gives +5
Right, regardless of whether it's a PC or NPC, we now add this up to the Base_Chance:
Base_Chance = Base_Chance + Morale Modifier
Next, we're going to calculate how stamina affects the shooter's aim. Here's another complicated formula for you:
Fatigue_Modifier = Base_Chance * Breath_Penalty / 100 / 2
Breath_Penalty here depends on the character's current stamina, and it works in stages as we've seen some things do before:
At 85 or above, Breath_Penalty is 0
At 7084, Breath_Penalty is 10
At 5069, Breath_Penalty is 25
At 3049, Breath_Penalty is 50
At 1529, Breath_Penalty is 75
At 14 or less, Breath_Penatly is 90
When we figure this into the formula above, we see that the Fatigue_Modifier can't be more than 45% of our Base_Chance, and that's only if we're about to pass out. Normally, we'd only lose about 5% of our Base_Chance due to fatigue.
So once we have that penalty, let's just subtract it from our Base_Chance:
Base_Chance = Base_Chance  Fatigue_Modifier

This is where the Base_Chance value branches off. The program makes a "working copy" of this value, and saves the Base_Chance for later calculations. The copy will now be called "Actual_Chance", and we're going to be modifying it exclusively. It'll later be compared to Base_Chance, as you'll see soon, but the end result will be the Actual_Chance after it has gone through a TON of modifications.
Actual_Chance = Base_Chance
Straight away, however, the program does something very important  it'll check to see whether our gun is in good enough shape to compensate for the shooter's inaccuracy. We'll use the Status_Modifier we calculated a few steps ago.
If Status_Modifier < Base_Chance then
Actual_Chance = average of:
1) Base_Chance
2) Status_Modifier
This can have a very serious impact on our chancetohit. It means that if the gun is in bad shape, it can drop our chance to hit by a good amount, before we've even had the chance to calculate other stuff! This is very strange though, because if you remember then we've already taken gun condition into account earlier in the calculations... I'm not sure I agree with this part of the code, but that's what we've got for now.

Right, so from now on we're going to be working with "Actual_Chance", and keep "Base_Chance" for later comparisons.
We're going to add a couple of straight bonuses now, and most of you probably know the first one well  a bonus for firing at the same target again:
If TargetLocation is the same as the TargetLocation of the previous shot, then
Actual_Chance increased by 10
A flat +10 to CTH right there. Note of course that we haven't checked if the TargetLocation has an enemy in it yet  so you actually get a bonus for firing at empty squares repeatedly, too! Please note that it's always just +10, it's not an incremental bonus. You won't get +20 in the next shot at the same target.
After this, we'll add a wicked bonus to PSYCHO characters. Yes, indeed, all psychos get a bonus to their CTH, with any gun, at any mode of fire:
If Shooter is a PSYCHO, then
Actual_Chance is increased by 15

Now we add another piece of data to the cauldron  "Range". The program computes this by itself, and the result we get is the range in METERS, not tiles. So from this point on, whenever range is discussed, I'm talking about meters (unless stated otherwise!). In the current game system, 10 METERS = 1 TILE.
Let's see how range figures into this, as we move on to our next section. This section calculates the modifier based on the shooter's stance. Different stances give different bonuses, of course.
We'll do them one by one, starting with the STANDING stance:
If Shooter is Standing, then
If using a High_Power_Scope, and Range is greater than the Minimum_Range_For_Aim_Bonus of the scope, then
Scope_Penalty = Scope_Aim_Bonus * (Range  Minimum_Range_For_Aim_Bonus) / 1000
If Scope_Penalty > 20, then
Scope_Penalty = 20
Hmmm, a tad complicated there. It's going to get even more complicated later on, but I'll do my best to explain.
Basically, in the Standing stance, we get no penalty to our accuracy, UNLESS we're firing a sniper rifle with a very powerful scope (remember? +15 aiming bonus or above is a highpower scope).
If such a scope is involved, things get complicated. The Minimum_Range_For_Aim_Bonus is drawn directly from the XML data of the scope we're using  it determines at which distance our character uses the scope. If the target is closer than this distance, the character doesn't use the scope at all. Beyond the distance, he can get aiming bonuses from the scope, but as you see here he'll also have some trouble using it while standing up.
See that complex line with the mathematical equation? We can write it a bit differently to have it make more sense:
Scope_Penalty = Scope_Aim_Bonus * The difference between the minimum range to use the scope and the actual range to target, in TILES / 100.
So for each tile beyond the minimum range to use the scope, we get a penalty equal to 1/100 of the scope's aiming bonus. This doesn't sound like much, of course, but let's show some examples of how this works:
A Scope 10x (a regular Sniper Scope) has a minimum range of 70 (that's 7 tiles), and an aiming bonus of 20. Let's see how this scope behaves when we shoot at someone who is standing 8 tiles from us:
Scope_Penalty = 20 * (87) / 100 = 0.2
Not a serious penalty, of course. 0.2 gets immediately translated to 0, anyway. Now, what happens if the target is standing further away, say 30 tiles away, just beyond viewing range?
Scope_Penalty = 20 * (307) / 100 = 4.6
That's a bit more impact there. I'm not happy with this bit, myself, because the penalty is really very small. But it's important that we understand how this works, because we're going to see this recurring later.
Also note in the code block above, that the program makes sure that the Stance_Penalty doesn't go above 20.
Next, let's look at the CROUCHING stance:
If Shooter is Crouched, then
Stance_Bonus = Range IN TILES
If Stance_Bonus > 10, then
Stance_Bonus = 10
Wow, so actually, while we're crouched, we get a bonus equal to the distance to the target! The farther the enemy is from us, the more bonus we get! Of course, we don't get any bonus beyond the 10 tile range. This tells us something important though  at very short range, we only get a very small bonus when crouched, compared to standing up... That little bit of info could save us some APs in closequarterscombat, eh?
Crouch stance also gives a penalty for using HighPowered Scopes, in fact it is exactly HALF the penalty we get while STANDING. Read about this above.
Prone stance is the best of all three, as far as shooting is concerned:
If Shooter is PRONE, then
Stance_Bonus = Range IN TILES
If Stance_Bonus > 20, then
Stance_Bonus = 20
This is the same as crouched mode, except it works for up to 20 tiles of range (giving us a maximum bonus of 20). Again, the farther the target is, the more bonus you get.
But the best feature of Prone mode is, of course, that you do NOT get a penalty for using a highpowered scope! Snipers should lie down whenever they can for this very reason. Of course, as you saw above, the penalty isn't too big, so it doesn't REALLY matter much, but it does help. Also, of course, prone stance allows us to get bonuses from bipods, but that's later.
Let's add it all up:
Actual_Chance = Actual_Chance + Stance_Bonus  Scope_Penalty

Actual_Chance is increased by the weapon's Accuracy value
This should be obvious. The weapon's Accuracy is read directly from Weapons.XML, and never ever changes.

Next up, we take a look at handguns, and particularly, dualfiring (firing two weapons at the same time).
If Weapon is OneHanded, then
If Other hand is free, then
If Weapon is a Handgun, then
Actual_Chance is increased by 5
Else (if other hand is holding something)
If Weapon is an SMG, then
Actual_Chance is reduced by 5
If character doesn't have the Ambidextrous skill, then
If we meet the requirements to dualfire, then
Actual_chance is reduced by 20!
Let's break this up into components, and go step by step.
First we check to see if the weapon we're firing is onehanded, like a handgun or SMG. If it isn't, we move on, otherwise let's see what happens.
If the other hand is free, meaning we're not holding anything there (ANYTHING!!), and the gun we're firing is a handgun, then we can use both hands to hold it and we get +5 to our chancetohit.
If the other hand is occupied, and we're trying to fire an SMG, then our weapon is less stable. We lose 5 points of CTH for not holding the weapon with both hands.
Finally, if we're trying to shoot two weapons at the same time, and we don't have the ambidextrous trait, then we lose 20 points of CTH. That's why ambidextrous mercs are so much better at shooting two weapons at the same time!
Note that in the code above I used the words "meet the requirements to dualfire". This is actually a pretty complex check. To be valid, the weapons you are holding have to answer these criteria:
1) Both weapons need to be guns. (not GLs, rockets, etc.)
2) Both weapons have to be onehanded.
3) Both weapons must not be set to burst fire.
4) Both weapons must have ammo.
5) Both weapons must be useable (condition better than 10)

From this point on, there's a pair of subcalculation that need to be mentioned. These calculations are called "BonusReduce" and "BonusReduceMore". They are used to determine how much actual bonus is given by an item or attachment, based on their actual status.
When BonusReduce is used, items with 85 status or upwards give their full bonus. Under 85 status, the bonus begins to drop, until at 0 condition you get, well, 0 bonus. The formula is:
If Item's_Status is between 1 and 85 then
Final_Bonus = ( ( (Item's_Status * 100) / 85 ) * Original_Bonus ) / 100
else
Final_Bonus = Original_Bonus
In effect, if the item's status is 42%, then the bonus you receive from the item is roughly 50% of what it SHOULD give. If the item's status is 0, or over 85, the calculation is skipped and the result is simply the Original_Bonus.
The second formula, "BonusReduceMore", is much more severe. The bonus drops with item status, but at 50% status the item gives no bonus, and below 50% it gives a PENALTY instead:
If Item's_Status is between 1 and 99 then
Final_Bonus = ( ( ( (Item's_Status * 100) / 100 )  50 ) * Original_Bonus ) / 50
else
Final_Bonus = Original_Bonus
Yeah it's kind of complex, but the end result is that as the item's condition falls towards 50%, it gives a smaller bonus. But if the item's condition gets below 50%, it starts giving a penalty, which at 1% condition is opposite in strength to the bonus that would've been given at 99%.
Many items use one kind of bonus formula, and many use the other kind of bonus formula. I'm not sure, but it's possible that one type of item might be checked differently in different parts of the game.
For simplicity's sake, I'll give them new names:
a "MILD" bonus check is the steady decrease of the bonus from 100% to 0%, based on condition.
a "HARSH" bonus check is for bonuses that decrease as the item falls towards 50% condition, then turn into penalties if the item is further damaged beyond 50%.

We'll need to use those bonus formula now, as we calculate burst and autofire penalties. Both of these penalties are calculated the same way, but the penalty value itself is different, because they're based on different values (Burst Penalty and Auto Penalty, respectively).
If the bullet we're shooting is part of a Burst, then
Burst_Penalty = Weapon's_Total_Burst_Penalty * (number of bullets already fired in this burst  1)
If Shooter has the AUTO_WEAPONS trait, then
Burst_Penalty is cut in half for each level of the trait
Actual_Chance is reduced by Burst_Penalty
Pretty simple  the burst penalty only applies for each bullet after the first one, and gets more and more severe as we fire more bullets. The Auto_Weapons trait then cuts the penalty by half, and Expert_Auto_Weapons cuts it again by half (the resulting penalty would be only 25% as severe).
To calculate the Weapon's_Total_Burst_Penalty, the program does this:
Burst_Penalty = Weapon's_Inherent_Burst_Penalty
Burst_Bonus = Weapon's_Burst_ToHit_Bonus (MILD)
Burst_Bonus is increased by Ammo's_Burst_ToHit_Bonus
Burst_Bonus is increased by each attachment's Burst_ToHit_Bonus (HARSH)
If Shooter is PRONE, then
Burst_Bonus is increased by Weapon's_Bipod_Bonus
Burst_Bonus is increased by each attachment's Bipod_Bonus
Burst_Penalty is reduced by Burst_Bonus
So we have two values here  Burst_Penalty, and Burst_Bonus. At the very end they are added up together.
The weapon's inherent burst penalty comes from the weapon itself, it's written in the Weapons.XML file.
The burst ToHit Bonus works to offset that penalty. You can see that the weapon itself, as well as its ammo and attachments, can each increase the Burst ToHit Bonus. Today, only Foregrips (or builtin foregrips) can do this. Note of course that attachments in bad condition can actually increase the penalty, as this is a HARSH bonus calculation type (see above, if you don't know what this means).
Finally, if the shooter is lying down, he gets the benefits of the weapon's builtin bipod (if any) and attached bipod (if any).
Burst_Penalty and Burst_Bonus are then added together. But the end result is always either 0 or negative, as the program makes sure it doesn't go above 0. You can't have a POSITIVE Burst_penalty, that's why it's called a penalty. Unless you've got a very stable weapon, with good bipod and all that stuff, each bullet in the burst will be less accurate than the previous bullet.
AUTOFIRE penalty works in almost exactly the same way. The first difference is that it looks at different values, namely "Auto_Penalty" and "Auto_ToHit_bonus". Most guns and attachments have different values for burst and auto modifiers. Autofire is almost always less accurate, if not always.
Also, with autofire, it seems that the gun's condition is more important. The bonus you get from the gun's Autofire_ToHit_Bonus" is HARSH, so a damaged weapon (below 50% status) with inherent bonus may actually give a penalty instead! It's quite bizarre, but that's what the code says.
Actual_Chance is reduced by Burst_Penalty, or
Actual_Chance is reduced by Auto_Penalty...
Depending on the mode of fire, of course!

Now this is where things start getting really complex. At this point, we're actually going to split yet another value, this time it's Range.
We're going to remember the "pure" rangetotarget, which is the exact calculation of the distance between the shooter and the target location.
We're also going to add a second value which will be called "Effective_Range". This value is differently calculated, because the program runs a VERY complex calculation to figure it out. Basically, a lot of stuff figures into effective range, but most importantly it's camo and cover. But other stuff figure in as well, or at least it seems so. The end result is the "effective" range to the target, which will be used more often than the actual range.
If "Effective_Range" is 0, that's when we get that "can't shoot" indicator, and our mercs complain a little if we still try to take the shot. Please note that ridiculously, you would still have a certain chance of hitting the target, but I'm not going to discuss that now.
Also from this point on, I'm going to assume that there is an enemy soldier in the target square. If not, the program behaves a bit differently.

If we can see the target, and have spent extra APs to aim, the program now begins a bit of calculating our aiming bonus. Please be patient with this one, it's a very important part of the process, but can be pretty difficult to understand. Once again, I'll do my best to explain it step by step, and there's a detailed example of it below. So don't worry, you'll get it. I hope.
In the original JA2, each AP we spent on aiming our weapon gave us a flat +10 tohit bonus. In today's 1.13, things couldn't be more different. Not only is there a variable ToHit bonus per AP that's based on many factors, but we also have a maximum bonus that can be achieved from extra aiming, which also depends on many factors.
So without further ado, here is the formula, which is comprised of two steps.
Step 1: Calculate the maximum possible bonus from extra aiming.

Maximum_Aiming_Bonus = 20 + ( (Base_Chance / 20) * Shooter's_Experience_Level ) + (Weapon's_Accuracy * 2) + 10 points for each level of the SNIPER trait
Here we're using the Base_Chance, a value we "saved for later" somewhere earlier in the formula. If you remember, it was based mainly on our Marksmanship, Fatigue, Morale, and the status of our weapon. Shooter's_Experience_Level is the level of the character, without any modifiers. Weapon's_Accuracy is the weapon's XML value. This is pretty simple to understand, I think. It's just basic arithmetics.
The Maximum_Aiming_Bonus is the highest possible bonus we can get from extra aiming. Even with a 10x Sniper Scope, if you've hit the maximum then any extra APs spent on aiming would simply be wasted. You'll soon see how the formula achieves this automatically.
Now we do some crazy math.
Step 2: Figure out aiming bonus per each extra AP spent.

For each extra AP spent on aiming, repeat the following:
Aiming_Bonus = (Maximum_Aiming_Bonus * Aiming_Progression / 1000), but not more than 10.
Maximum_Aiming_Bonus reduced by Aiming_Bonus
Increase Actual_Chance by (Aiming_Bonus + 0.5), rounded down.
Let's do this line by line.
Line 1: "Aiming_Bonus = Blah blah blah"
First, we calculate the aiming bonus we get for this bullet. This is based on the maximum_aiming_bonus, but also on a value called "Aiming_Progression" which I haven't explained yet. Basically, Aiming_Progression is a value that gets bigger with each AP spent. With the first AP spent on extra aiming, the value Aiming_Progression equals 500. With the next AP spent, it still equals 500. With the third AP spent, it becomes 600. Then 600, 750, 750, 750, and with the eightth AP it is 1000. So you can see, we should get better results from spending the 8th AP than we get for spending the third AP. But while Aiming_Progression goes up, Maximum_Aiming_Bonus goes down (read next).
Line 2: "Maximum_Aiming_Bonus blah blah blah"
Next, we reduce Maximum_Aiming_Bonus. Since we go through the loop several times, each time we run Line 1, we get smaller results because Maximum_Aiming_Bonus has just been decreased. Characters with low marksmanship will feel this very strongly, because it makes each extra AP less useful than the last one, counteracting what we just did with the Aiming_Progression. Characters with high skills will not notice this so much  unless the weapon has a sniper scope and can add 8 extra APs, then each extra aiming will produce 10 points. If they do use a scope though, they'll find that their CTH increases rapidly at first, but the last few APs don't help as much. Then again, sniper rifles can be fired at very long ranges, so the first few APs might not even bring CTH above 0 at all! Then, the last few APs are very helpful...
Line 3: "Increase Actual_Chance blah blah blah"
This is where we add the aiming bonus we gained from this extra AP to our current chancetohit. Note that we get an extra 0.5 for some reason. Also, the value is rounded down, because Aiming_Bonus is a fractional value. It's always rounded down, even if it's negative (yeah, apparently you can get negative aiming bonus...), so 1.2 becomes 2.0 .
When we're done with all three lines, the loop runs again for the next AP spent. Eventually, all APs are calculated and the aiming bonuses are added to our current ChancetoHit one by one.
Good time for an example, as this has gotten quite complicated...
Let's take a merc with some imaginary values:
Base_Chance = 55 (This is the chancetohit after taking into account marksmanship, fatigue, etc, but before stance and tohit bonuses etc. are applied)
Shooter's_Experience_Level = 3 (A somewhat experienced mercenary)
Weapon's Accuracy = 5 (A nice, accurate rifle)
We'll also give our merc one level of the SNIPER trait.
Here's the first part of the formula, concerning the maximum aiming bonus:
Maximum_Aiming_Bonus = 20 + ( ( 55 / 20 ) * 3 ) + (5 * 2) + 10 * 1 = 48.25
Now let's say out Actual_Chance (CTH after all the calculations so far, including stance, etc.) is 40. We'll aim the weapon with 8 extra APs. The second part of the formula will therefore run 8 times. Start with the first AP:
Aiming_Bonus = (48.25 * 500) / 1000 = 24.125, which is larger than 10, so the result is 10.
Maximum_Aiming_Bonus = 48.25  10 = 38.25
Actual_Chance = 40 + ( 10 + 0.5 rounded down ) = 50.
Great, we've increased by 10 points. Let's aim some more. AP number 2:
Aiming_Bonus = (38.25 * 500) / 1000 = 19.125, which is larger than 10, so the result is 10.
Maximum_Aiming_Bonus = 38.25  10 = 28.25
Actual_Chance = 50 + ( 10 + 0.5 rounded down ) = 60
Another 10 points for us! AP number 3 coming up:
Aiming_Bonus = (28.25 * 600) / 1000 = 16.95, which is larger than 10, so the result is 10.
Maximum_Aiming_Bonus = 28.25  10 = 18.25
Actual_Chance = 60 + ( 10 + 0.5 rounded down ) = 70
Another cool 10. You've probably noticed that the Aiming Progression has grown from 500 to 600, which is helping us to overcome the fastdropping Maximum_Aiming_Bonus. It really helps that the maximum was so high to begin with (48.25), so we keep getting high results here. Maximum_Aiming_Bonus is going to vanish soon though. AP number 4:
Aiming_Bonus = (18.25 * 600) / 1000 = 10.95, which is larger than 10, so the result is 10.
Maximum_Aiming_Bonus = 18.25  10 = 8.25
Actual_Chance = 70 + ( 10 + 0.5 rounded down ) = 80
Yet another cool 10. But by now, the maximum aiming bonus is seriously low. Most rifles will not allow any more APs to be spent, so we've gained 40 points to our ChancetoHit, at the cost of 4 APs. This is mainly thanks to our sniper skill, an accurate rifle, and a relatively reasonable Base_Chance to begin with. But we've got a sniper rifle, so we can keep spending APs to aim some more. Let's see AP #5, then:
Aiming_Bonus = (8.25 * 750) / 1000 = 6.18, which is smaller than 10, so the result is 6.18
Maximum_Aiming_Bonus = 8.25  6.18 = 2.07
Actual_Chance = 80 + ( 6.18 + 0.5 rounded down ) = 86
Ah, this time around, we only got 6 point more. Our Experience Level and Sniper Skill are the major factors here  had they been higher, we would still be getting nice returns at this stage (more 10s!). Unfortunately, Maximum_Aiming_Bonus is close to disappearing, and even that increase from 600 to 750 Progression are not enough to give us good results at this stage. Going on to AP #6:
Aiming_Bonus = (2.07 * 750) / 1000 = 1.552, which is smaller than 10, so the result is 1.552
Maximum_Aiming_Bonus = 2.07  1.552 = 0.51
Actual_Chance = 86 + ( 1.552 + 0.5 rounded down ) = 88
Augh! Only 2 points extra CTH! This AP was almost entirely wasted! What happens with AP #7 then??
Aiming_Bonus = (0.51 * 750) / 1000 = 0.38, which is smaller (hell, much smaller) than 10, so the result is 0.38
Maximum_Aiming_Bonus = 0.51  0.38 = 0.13
Actual_Chance = 88 + ( 0.51 + 0.5 rounded down ) = 89
One stinking point. And that's only because we got lucky with that 0.51 there (and mainly because I'm avoiding very long fractional numbers, so the formula isn't 100% accurate ). Can we even hope that the last AP, #8, with a progression of 1000, will give us that final boost we need? Let's see:
Aiming_Bonus = (0.13 * 1000) / 1000 = 0.13, which is smaller than 10. The result is 0.13
Maximum_Aiming_Bonus = 0.130.13 = 0
Actual_Chance = 89 + ( 0.13 + 0.5 rounded down ) = 89
Not a chance. Our last AP was utterly wasted, giving us no bonus to CTH. Even progression didn't help here, and again, if our Maximum_Aiming_Bonus had been higher to begin with, we might've actually still scored a few points here. Our merc still has a lot to learn, it seems.
Now how much CTH did we gain here, from all this extra aiming? We started out with an Actual_Chance value of 40, and ended up with 89. The difference is... Surprise, surprise! 49 points! Almost exactly the original value of our Maximum_Aiming_Bonus! So you could say we've maximized our potential here
I just wonder why Dexterity played no part in this at all... odd.

Right. Now that we've got all of those bonuses out of the way, it's time to play nasty. Pretty much everything from now on will concern PENALTIES to CTH, which may cause it to drop like a rock. We're going to have a look at our target as well, see what he's doing and how it affects us.
We begin with something relatively simple:
If Shooter is an NPC (computercontrolled character), then
If difficulty_level is EASY, then
Actual_Chance is reduced by 5.
On the Easy difficulty level, all AI soldiers are given a 5 point penalty. That means enemies, militia, and civilians too. Just makes the game a bit easier, eh?
On other difficulty levels though, it's the other way around:
If Shooter is an NPC, then
If difficulty_level is EXPERT, then
Actual_Chance is increased by 5.
If difficulty_level is INSANE, then
Actual_Chance is increased by 10.
Freaky. No wonder INSANE level is so difficult. Note that on "EXPERIENCED" difficulty, CTH is not modified.
Now we check for some basic penalties:
If Shooter is under the effect of gas, then
Actual_Chance is reduced by 50!
Soldiers are only considered "gassed" if they're inside an active gas cloud and aren't wearing their mask. If the soldier's taken damage or stun damage from a gas attack at the beginning of the turn, they'll be "gassed" for the rest of the turn.
If Shooter is being bandaged, then
Actual_Chance is reduced by 20!
Yeah, characters being treated for injuries have a lower chancetohit. Though if you're having them fire at the enemy, you usually have no other choice anyway, do you?
If Shooter is in shock, then
Actual_Chance is reduced by 5 for each level of shock.
Shock is caused whenever a character is injured. It equals roughly 1/10th of the damage sustained, plus a little extra from any stamina damage from the attack. Therefore, if you're hit for 50 damage, your shock value is around 5. Each turn, shock is cut in half and rounded down.

We're going to calculate the gun's maximum range now. It's a relatively short calculation, but it's done separately, so I'm going to cover it now. Please make sure you've read a previous section that talks about BonusReduction.
Weapon_Max_Range = Weapon's_Range, from the XMLs
Weapon_Max_Range is increased by its own inherent Range_Bonus, if any (MILD)
Weapon_Max_Range is increased by the ammo's Range_Bonus, if any.
For each attachment, do:
If the attachment is not a DUCKBILL, or if it is a DUCKBILL and we're firing BUCKSHOT ammo, then
Weapon_Max_Range is inreased by the attachment's Range_Bonus (MILD)
Pretty simple. The gun's range, meaning the value taken from the gun's entry in Weapons.XML, is modified by its inherent range bonus (from builtin attachments), by the ammo (like Match ammo that increases range, or lockbuster ammo that decreases range), and by attachments. Duckbills give a range penalty, but only if you're firing nonbuckshot ammo. You'll note that all of these bonuses are MILD, meaning that the status of the gun/attachment causes the bonus to drop steadily towards 0, but it can't go negative. Of course, if the bonus was originally negative, then a damaged item would not give as severe a penalty as a fixed item. This is kind of confusing, but attachments almost never (or never?) give range penalties anyway...
In any case, this is the gun's Maximum Range. We're going to use it later when determining whether the target is beyond our effective shooting range.
Note that the Max_Range can't ever fall below 1. That's important for the program, so it has failsafes to make sure it never happens.

We're going back to using the "Effective_Range" value which we've been working with before. Remember, this value represents not only the range to target, but also such effects as camouflage and obstacles (cover).
If the effective_Range is 0 (meaning, no clear lineofsight to the target), it's pretty obvious that you're not going to make the shot. The code does continue to work with a value of 0 though, for some unexplained reason. Coupled with the fact that CTH can never go below 1%, that means that potentially any shot can hit anybody. Very annoying, and I've also made a few changes to that myself, but with the current release of 1.13, the minimum is still 1%. Of course, if Effective_Range is 0, that means some obstacle will probably stop the bullet anyway. But just so you'd know.

In any case, we're now going to do some stuff to our Actual_Chance  we're going to apply ToHit bonuses from all our worn gear, weapon attachments (like lasers), and even the brightness of the enemy's tile.
Fair warning here  this stuff is going to get SERIOUSLY complex. It's as complex as the Aiming_Bonus we just calculated from scopes. Only worse. Prepare thyself!!!
First, we change our effective_range, based on the Aiming_Bonus (usually penalty!) we get from armor, face items, and any attachments on the armor and face items. Please note that we're going to have to know how many APs we spent on aiming our weapon.
Final_Aiming_Bonus = 0
If Range_to_Target is less than or equal to the Item's_Minimum_Range_For_Aiming_Bonus, then
Return 0! No aiming bonus or penalty.
else
If Armor's_Aiming_Bonus is a penalty (less than 0), then
Extra_Aiming_APs = 1
Range_to_Target = Effective_Range
For each Extra_Aiming_AP, do:
Range_Modifier = (Item's_Aiming_Bonus * Range_to_Target) / 100
Range_to_Target is decreased by Range_Modifier
Final_Aiming_Bonus is increased by Range_Modifier
If Range_to_Target is now less than Item's_Minimum_Range_For_Aiming_Bonus, then
Range_Modifier equals (Item's_Minimum_Range_For_Aiming_Bonus  Range_To_Target)
Final_Aiming_Bonus is reduced by Range_Modifier
Stop now and give a final result equal to Final_Aiming_Bonus.
Ok, yeah, it's a bitch. And we're actually going to do this for each and every piece of armor, face item, and their attachments, adding up all those "Final_Aiming_Bonuses" together.
I'm really not going to explain this. It's too complex, and I think an example would be much better here. So let's grab an item and start calculating:
The item we're going to use for this example is a Ghille Hood, which is worn over the head. Ghillie equipment gives an aiming PENALTY, but then again all worn items in 1.13 that modify Aiming will also give a penalty. I won't deal with bonuses, for that reason. A Ghillie hood gives 1 Aiming Bonus, and is worn on the head or attached to armor. Whether worn or attached doesn't matter to us  it would be treated the same way.
Let's also assume that the effective range to the target is 100 meters (10 tiles). The minimum_range_For_Aiming_Bonus is 0, as it is for all worn items. Let's rumble!
If 100 is less than or equal to 0, then
Return 0!
This, of course doesn't happen. 100 is greater than 0. Next.
If Armor's_Aiming_Bonus is a penalty, then Extra_Aiming_AP = 1
The aiming bonus of the ghillie hood is 1, so it's a penalty. That means the program considers us to be spending only one AP to aim, for the purposes of this formula. Next.
Range_to_Target = 100
For each Extra_Aiming_AP, do:
Range_Modifier = ( 1 * 100 ) / 100 = 1
Range_to_Target = 100  (1) = 101
Final_Aiming_Bonus is increased by (1) (so its value is now 1).
Great, the penalty we get from the ghillie suit is now 1 points. The next line is:
If 101 is now less than 0, then
Whoa whoa, it's not. And since we only spent one AP to aim (as far as the program is telling itself), the loop ends here.
Not very interesting. The Ghillie Hood simply gave us the aiming penalty that is listed in the XML. Basically, this is the same for ALL worn items  they'll all give a penalty equal to their XML "Aiming_Bonus" value, which is always negative.
But let's have some fun with hypothesis. Let's create an item, a scope that can be worn on the face. Like a fixed binoculars hanging from the helmet. Makes some sense, right? Right. Let's assume that the item gives an aiming bonus of 20, like a Sniper Scope, and its minimum range for aiming bonus is 50. We'll spend 6 APs aiming our weapon. The range to target will stay the same (100 meters, equalling 10 tiles). Let's see the bonus we get for the first AP we spend:
Final_Aiming_Bonus = 0
If 100 is less than or equal to 50, then
Return 0! No aiming bonus or penalty.
Fortunately, the target is beyond the minimum range required to get the scope's bonus. Let's continue.
else
If 20 is a penalty (less than 0), then
Extra_Aiming_APs = 1
20 is not a penalty, so Extra_Aiming_Aps will equal the number of APs we spent aiming the weapon, 6.
Range_To_Target = 100
For each Extra_Aiming_AP (6 times), do:
Range_Modifier = (20 * 100) / 100 = 20
Range_To_Target = 100  20 = 80
Final_Aiming_Bonus = 0 + 20 = 20
Great, that's a 20 point bonus.
If 80 is now less than 50, then
Nono, it's not less than 50 yet. The target is still beyond the minimum range. Go on to AP #2:
Range_Modifier = (20 * 80) / 100 = 16
Range_To_Target = 80  16 = 64
Final_Aiming_Bonus = 20 + 16 = 36
Our bonus is now 36. We got less bonus for this AP than we did for the first one. Notice the range to target getting shorter, decreasing the bonus we get for each subsequent AP. On to AP #3:
Range_Modifier = (20 * 64) / 100 = 12.8 (rounded, this is 12)
Range_To_Target = 64  12 = 52
Final_Aiming_Bonus = 36 + 12 = 48
Right on to #4:
Range_Modifier = (20 * 52) / 100 = 10.4 (rounded, this is 10)
Range_To_Target = 52  10 = 42
Final_Aiming_Bonus = 48 + 10 = 58
Ok, so we keep getting less and less bonus for each AP we spend. But wait! Our Range_to_Target has just dropped below the minimum range for bonuses. Let's look at the last part of the loop:
If Range_to_Target (42) is now less than Item's_Minimum_Range_For_Aiming_Bonus (50), then
Range_Modifier = (50  42) = 8
Final_Aiming_Bonus = 58  8 = 50
Stop now and give a final result equal to Final_Aiming_Bonus, which is now 50.
Ah, ok. The last AP only gave us 2 points bonus to CTH, and the aiming bonus we got from this item is 50. Not too shabby, anyway

We add up all the aiming bonuses/penalties we got from all worn armor, face items and attachments in the previous section.
Effective Range is reduced by the Total of all the Final_Aiming_Bonuses we got in the previous section.
Naturally, if the worn items, combined, gave a penalty, then the effective_range is INCREASED, which isn't a good thing. We want the target to be considered closer to us, and thus easier to hit. So we want Effective_Range to decrease as much as possible.

What we did with worn items before, we're now going to do with the weapon and its attachments as well. Again, Minimum_range will come into play in the same way, with all that Range_Modifier and Final_Aiming_Bonus mumbojumbo. If you want your head to explode, read that formula again. It's a big headache. There is one difference here though:
Effective Range is reduced by the Total of all the Final_Aiming_Bonuses we get from the weapon and its attachments. (HARSH)
Did you notice the word HARSH at the end? That's another one of those statusbased modifiers. In this case, as the weapon or the attachment get damaged, their Final_Aiming_Bonus slowly decreases towards 0. It reaches 0 at 50% status, and if the item gets damaged beyond 50%, you start getting a PENALTY instead of a bonus!!! This is very different from armors, but then again armors always give penalties anyway in 1.13. I'm thinking people may want to change this, in the future...

The next step is to figure out how much Flat ToHit bonuses we get from our worn items and weapons. Similar to what we just did with Aiming Bonuses, we're going to go through each item, including our armor, face items, weapon, and all attachments, to figure out the Final_ToHit_Bonus of each and every one of them, and pool all those final bonuses together.
There's a big difference between Aiming Bonuses and ToHit Bonuses. Aiming is affected mainly by how many times we rightclick a target to increase our aim, at the cost of APs. ToHit bonuses do not rely on aiming, but some of them do rely on an important factor  range to target, and "Best Laser Range". Yes, many of the items that give a ToHit bonus are laser attachments, and they have a certain effective range. Now we're going to find out exactly how this range gets calculated. We're also going to see how brightness affects our aim!
For worn items (including armor, face items, and their attachments), the calculation is pretty simple. "Best Laser Range" doesn't play a factor here at all, so in effect we're getting a flat bonus (or penalty) to our CTH.
For each worn item, we do this:
Final_ToHit_Bonus = 0
Final_ToHit_Bonus increased by the item's_ToHit_Bonus value, taken from the XML
For each attachment of the item, do:
Final_ToHit_Bonus increased by the attachment's_ToHit_Bonus value, taken from the XML
Haha, finally something simple. We don't mess with ranges, we don't care about status, we just look at the XML values and add them all up. Unfortunately, most if not all worn items that modify our ToHit are penalties. Bummer.
Now, with weapons it gets tricky. We'll need to look up Best Laser Ranges, and we'll also need to know our effective_range. But by now we're getting pretty good at this. There's just one thing we need to do first:
If character has the SNIPER trait, then:
Effective_Range is decreased by 5% of the Real_Range_to_Target
If character is an EXPERT SNIPER, then:
Reduce effective_range by another 5% of the Real_Range_to_Target
Great, the SNIPER trait takes effect here too  it reduces the effective range to target, just before we measure whether the target is within laser range. This is really going to help us if we're using laser attachments. Note that we use the "REAL" range to target here, the actual distance in meters between you and the enemy, not taking into account camouflage and cover. It's not that important, but still important
Ok, with this new Effective_Range value, we're ready to tackle weapon and attachment ToHit bonuses.

... Continued in next post...
[Updated on: Mon, 27 April 2015 23:45] by Moderator




Re: "How does it work?" Part 4: ChancetoHit[message #196108] 
Tue, 09 September 2008 11:49  
Headrock


Messages:1772
Registered:March 2006 Location: Jerusalem 


To get the ToHit bonus from a weapon or attachment, we'll need to have some values ready for us:
Item's ToHit Bonus: Naturally, this is what we want to see added to our CTH at the end . We draw this straight from the XML.
Item's Best Laser Range: Most items that increase ToHit bonus have a best laser range. This too is drawn from the XML data of the item.
Item's Bipod Bonus: Yup, this is where Bipods come in. We draw this data from XML too.
Is Shooter Prone?: This is either TRUE or FALSE. We'll want to know if the shooter is prone so we can decide whether to give him the Bipod Bonus. But this doesn't rely only on the shooter's stance  he must also be at least 5 tiles away from his target if he wants to get that bipod bonus!! If the effective range to the target is less than 5 tiles, then "Is_Shooter_Prone?" is FALSE, as far as this part of the program is concerned.
Let's get cracking. Here's the basic outline of the whole shebang:
Final_ToHit_Bonus = 0
If Shooter is Prone, then
Final_ToHit_Bonus is increased by the Bipod_Bonus of the weapon's builtin bipod, if any.
Final_ToHit_Bonus is increased by the Laser_Bonus of the weapon's builtin laser, if any (HARSH)
Final_ToHit_Bonus is increased by the Ammo's ToHit Bonus.
For each attachment, do:
If Shooter is Prone, then
Final_ToHit_Bonus is increased by the Bipod_Bonus of the attachment
Final_ToHit_Bonus is increased by the Laser_Bonus of the attachment (HARSH)
It looks pretty simple, but then again we don't know how Laser_Bonus is calculated yet  it's not an XML value, we actually have to calculate it based on range, lighting, and a whole lot of other crap. We'll do that in a second. Please first pay attention  both laser bonuses are affected by the status of the gun or attachment giving those bonuses. It's a HARSH effect, meaning that if you go below 50% status, you start getting PENALTIES to your chancetohit, which is not good at all. Make sure you keep your lasers in good shape! Ammo and bipods do not rely on status.
Now, let's see how all that laser business is calculated. Remember we're going to calculate this for the weapon and all of its attachments, one by one. We'll later feed the results back into the formula, where it says "Laser_Bonus" above. This is going to be a bit rough, but certainly not as nasty as the aiming calculations from earlier.
If the item has no Best_Laser_Range, then
Laser_Bonus = Item's_ToHit_bonus (no changes!). Remember to check item status in the previous formula!
Great, some items and guns have a ToHit bonus (or penalty) but no Best_Laser_Range. We treat those as flat modifiers, except we have to check it against the item's status when we return to the previous formula (remember? HARSH...)
If the Effective_Range is less than or equal to the item's Best_Laser_Range, then
Laser_Bonus = Item's_ToHit_bonus (no changes!). Remember to check item status in the previous formula!
If we're within laser range, our laser works perfectly. The bonus stays untouched, until we return to the previous formula and check it against the item's status. (HARSH, again...)
Now things get messy.
If Effective_Range is greater than the item's Best_Laser_Range, then
Maximum_Laser_Range = Item's_Best_Laser_Range * ( (2 * Brightness_At_Target_Location) + 21 ) / 18
Ok, that's not even nearly as ugly as it looks in the code. Here's a rare occassion to look at something really scary. This is the same equation, but DIRECTLY out of the code:
INT32 iMaxLaserRange = ( pItem>bestlaserrange*( 2*bLightLevel + 3*NORMAL_LIGHTLEVEL_NIGHT  5*NORMAL_LIGHTLEVEL_DAY ) ) / ( 2 * ( NORMAL_LIGHTLEVEL_NIGHT  NORMAL_LIGHTLEVEL_DAY ) );
Ack. Well, in truth, the two are exactly the same. The reason mine's about half as long is that all those capitalletter names like NORMAL_LIGHTLEVEL_DAY are fixed values which the programmers can change if they ever need to. But in the end, assuming no changes are made to these values, my pseudocode is correct.
Now let's pretend I never showed you that thing.
Right. So now we have the maximum range at which the laser pointer can be seen, based on the light level at the target tile. If the target is within that "maximum" laser range, we can still get a few tohit bonus points from the laser, albeit less than the full amount. (we'll do that next)
Note that the light level is NOT what you see ingame when you press the F button. It's actually the opposite! In daylight, the light level of tiles is usually 3, and at night it is usually 12. So the higher, the darker! Weird, huh? It works like that throughout the whole game... EXCEPT when you press "F" to see the brightness level, in which case the program lies to you. Of course, the lie is intentional, because most of us would associate a LOWER level with LOWER light, and vice versa. We're just strange little humans. The program itself works the other way around  the higher the value, the darker it is! I guess they should've called it "DARKNESSLEVEL".
In any case, you can clearly see (now that I've explained this weirdness) that the darker the tile, the easier it is to see the red laser dot, and so the maximum range of the laser pointer will grow, for the purposes of shooting targets beyond the laser's original Best_Laser_Range. Of course, beyond the best_laser_range we're going to lose some of the laser's tohit bonus, but as long as the target's withing the Max_range, we'll still get a few points.
Now, let's see how far outside the laser's best range we are, and how much Laser_Bonus we get, if any.
Laser_Bonus = ( Item's_ToHit_Bonus * ( Maximum_Laser_Range  Effective_Range ) ) / ( Maximum_Laser_Range  Item's_Best_Laser_Range )
In effect, each tile of range beyond our Best_Laser_Range will decrease the bonus we were supposed to get from the laser. Dark conditions help, of course, because we're using Maximum_Laser_Range as well, which we've just calculated based on light levels. If the target is beyond the Maximum_Laser_Range, we'll get a result of 0 or less.
Finally, the program makes sure that we don't get a PENALTY:
If Laser_Bonus < 0, then
Laser_Bonus = 0.
This is interesting to know  Laser_Bonus is a HARSH bonus, which means that if the laser's status is below 50%, it could give a penalty instead of a bonus. However, if the Laser_Bonus we've just calculated is 0 (meaning, we can't see the laser dot because the target is too far out of range), then we won't get a penalty either (negative 0 is still 0). So if the target is out of laser range, you don't get a penalty for using a broken laser. Realistic!
Let's have a quick example here, just to make sure all this is understood:
Shooter is using a regular laser attachment, with 90 Best_Laser_Range, supposed to give a 20point ToHit Bonus. Target is 12 tiles away, in daylight (Brightness... errrr... darkness level 3).
If the item has no Best_Laser_Range, then
Laser_Bonus = Item's_ToHit_bonus (no changes!). Remember to check item status in the previous formula!
No, the item has a best_laser_range, so we skip this. Next.
If the Effective_Range is less than or equal to the item's Best_Laser_Range, then
Laser_Bonus = Item's_ToHit_bonus (no changes!). Remember to check item status in the previous formula!
No, the Effective_Range is 120 (12 tiles) and the laser range is 90, so we skip this.
If Effective_Range (120) is greater than the item's Best_Laser_Range (90), then
Maximum_Laser_Range = 90 * ( (2 * 3) + 21 ) / 18 = 135
The Great, so we're a bit out of range, the tile's not too dark, so we can still use the laser pointer effectively up to range 135. Let's move on:
Laser_Bonus = ( 20 * ( 135  120 ) ) / ( 135  90 ) = 6.666 (rounded down to 6).
So the final Laser_Bonus is 6. Much less than we should get from the laser, but of course we're a bit out of laser range.

All of the laser bonuses we've just calculated are added up to our Actual_Chance. Again, remember that the status of your laser will affect how much bonus you get from that laser, and you will get a penalty if the status is below 50%.

Next up are modifiers based on the bodypart we're trying to shoot.
If we're shooting at the head, then
Bodypart_Penalty = 3 * Effective_Range / 10
Actual_Chance is reduced by Bodypart_Penalty
When shooting at the head, we lose three CTH points per tile of effective distance. Remember that effective distance takes Camo and obstacles into account.
If we're shooting at the legs, then
Bodypart_Penalty = Effective_Range / 10
Actual_Chance is reduced by Bodypart_Penalty
When shooting at the legs, we lose 1 CTH point per tile of effective distance.

Now, the range to target really kicks in. We're going to rely on our weapon's Range value (which is drawn from XML). We'll compare it to the range to target. If the target is beyond range, we're going to start losing lots of CTH.
Range_Penalty = ( (Weapon's_Range  Range_to_Target) * 30 ) / 170
If Range_Penalty is a negative value, then
Actual_Chance is reduced by Range_Penalty
What we do is to check the difference between the weapon's inherent range (the value we see in the description box, drawn out of the XML files) and the range to the target (unmodified, not the "Effective_Range"). If the weapon's range is larger or equal to the range_to_target, then there's no problem  the penalty is positive (or 0), and is then ignored. However, if the target is beyond the weapon's natural range, the penalty gets bigger.
Please note that this isn't the only range modifier. If the target is out of range, we're going to get a HUGE hit to our CTH soon.
But first thing's first, let's have two examples on this:
First, we'll use a sniper rifle. The rifle has a range of 75 tiles (750 meters), and the range to target is 60 tiles (600 meters)
Range_Penalty = ( (750  600) * 30 ) / 170 = 26.4
Range_Penalty is a positive value  that's a good thing, because it means we've got no problems with range. Our target is within the weapon's range, and the program skips this bit altogether. No penalty.
Second example, we'll shoot a pistol with a range of 11 tiles (110 meters) at a target standing at 13 tiles (13 meters)
Range_Penalty = ( (110  130) * 30 ) / 170 = 3.5
Ok, this time we've actually got a penalty of 3.5 points. Since it's a negative value, it's subtracted from the ChancetoHit. We've lost 3.5 points of CTH, and we're going to lose a lot more than that later.

Here's a bit that restricts shooting for tanks, at close range. Tanks have a problem firing at enemies who are very close, and this is where it gets calculated:
If Shooter is a tank, and Range_to_Target in Tiles is less than (2 * normal sight range in tiles), then
Tank_Closerange_Penalty = 2 * ( (2 * Normal_Sight_Range in tiles)  Range_to_Target in Tiles )
Actual_Chance is reduced by Tank_Closerange_Penalty
The normal sightrange is not a fixed number  you can set it in your JA2_Options.INI file. The default is 13. Therefore, if the target is less than 26 tiles
away, the tank gets a penalty to his shooting.

If Effective_Range = 0, then
Actual_Chance is reduced by 80!!!
Heh, this is funny. The effective range only equals 0 if we don't have a clear lineofsight to the target, or if we're using a seriously damaged scope. It means that we're trying to shoot blindly, and so our chancetohit drops considerably. I think it's just making sure we don't actually hit the target, no matter how good we are

Now we're going to do something interesting.
Universal_Range_Modifier = 3 * (NORMAL_RANGE  Effective_Range) / 10
Actual_Chance is increased/reduced by Universal_Range_Penalty
This universal modifier is a curious little bugger. It gives a 3 point bonus or penalty to CTH, based on the how much closer, or farther, the target is from the NORMAL_RANGE. But what is "Normal_Range"? Well, this is a fixed value set up by the JA2 programmers. In 1.13, the NORMAL_RANGE is 90 meters (9 tiles). That means that any target beyond 9 tiles is harder to hit, and any target closer than 9 tiles is easier to hit. Each tile of difference gives 3 points in bonus or penalty as required. Theoretically, chancing the Normal_Range would make the game behave differently. If you set it to 200 (20 tiles), then it will be much easier to hit stuff at long range, and MUCH easier to hit people who are very close to you! On the other hand, if you set it to 10 (1 tile) then shooting becomes much more difficult, even at people standing close to you. There is no current option to change the NORMAL_RANGE, other than editing the code.

We're going to check and see whether the shooter and his target are on different levels of the map, and apply penalties/bonuses as appropriate.
If Shooter is on a roof, and Target is on the ground, then
Actual_Chance is increased by 15
If Shooter is on the ground, and Target is on the roof, then
Actual_Chance is decreased by 25
Shooting up to the roof is tricky. Shooting down from a roof is easy. 'Nuff said.

We're going to have a look at our target now, to see what they are doing. The stance of the target, compared to the stance of the shooter, is going to affect our aim. Let's do this one by one, covering all three stances, STANDING, CROUCHING, and PRONE.
If Target is STANDING, then
If Range_to_Target is 5 tiles or less, and Shooter is PRONE, then
If we're not shooting at any particular bodypart, then
Targetted_Bodypart = 2 (TORSO)
Bodypart_Penalty = (5  Targetted_Bodypart  Range_To_Target in Tiles) * 10
Actual_Chance is reduced by Bodypart_Penalty
Ok, the penalty for shooting at a standing target only happens if the shooter is prone, and the range is 5 tiles or less.
Targetted_Bodypart is a numeric value, where 1 = Head, 2 = Torso, and 3 = Legs. Range_To_Target is always 5 or less, because we only get to this calculation if we're within 5 tiles range.
Examples:
At range 2, shooting at the head (1):
Bodypart_Penalty = (5  1  2) * 10 = 20
At range 3, shooting at the Torso (2):
Bodypart_Penalty = (5  2  3) * 10 = 0
What's really weird is that you can actually get a bonus as well, especially if range is close to 5 tiles and shooting at the legs.
At range 4, shooting at the Legs (3):
Bodypart_Penalty = (5  3  4) * 10 = 20
It's negative, but because Actual_Chance is reduced by this, we get a bonus to CTH! So when prone, go for the legs!
Also note that in the code above, there's the bit that checks if we're not shooting at any particular bodypart. I think this happens when we're shooting at a prone target, but it also appears that it happens when shooting at a creature's glands (I.E., shooting them from behind?). In both cases, the game considers the shot to be aimed at the torso, for purposes of this calculation.

CROUCHING:
If Target is CROUCHED, then
If Shooter is a Tank, and Range_to_Target is less than 120 meters (12 tiles) then
Tank_Penalty = 13 * ( 120  Range_to_Target ) / 10
else
If Range_to_Target > 86 (???), then
Actual_Chance is reduced by 20
If Range_to_Target is between 16 and 86 (???), then
Closerange_Penalty = 3 * ( (Range_to_Target  16) / 10 )
Actual_Chance is reduced by Closerange_Penalty
Ok, that's a bit complex.
First, tanks get a penalty for shooting at crouched targets that are closer than 12 tiles.
If the shooter isn't a tank, then it's a bit weird there. Note that I'm not sure about 86, it's quite possible that the value here should be 182, as I may have read the calculation wrong. In any case, if the target is crouched and beyond this range (in METERS, not tiles), then we lose 20 points from our CTH.
However, if the target is closer than this range, but more than 1 tile away (16 meters... ok, 1.6 tiles away, geez), then we lose 3 points from CTH for each tile of distance.

PRONE:
If Target is PRONE, then
If Shooter is a Tank, and Range_to_Target is less than 120 meters (12 tiles) then
Tank_Penalty = 25 * ( 120  Range_to_Target ) / 10
else
If Range_to_Target is greater than 16 meters (1.6 tiles), then
Closerange_Penalty = 3 * ( (Range_to_Target  16) / 10 )
If Closerange_Penalty > 40, then
Closerange_Penalty = 40
Actual_Chance is reduced by Closerange_Penalty
It's almost the same as crouched, with a few differences.
Tanks suffer twice as much penalty for shooting at prone targets less than 12 tiles away. That's good to know  next time you charge at a tank, stay low and close!
As to other shooters, if you're prone and the target is prone and more than 1.6 tiles away, you will suffer a penalty of 3 points per tile. This penalty can't go over 40.

Next up, we take another drop of CTH based on how many tiles the target has moved during their turn:
Target_Movement_Penalty = Number of tiles moved * 1.5
If Target_Movement_Penalty > 30, then
Target_Movement_Penalty = 30
Actual_Chance is reduced by Target_Movement_Penalty
So we get 1.5 points penalty for each tile the target has moved during its turn, but no more than 30. Note that the "Tiles_moved" value is reset at the start of the target's next turn, so it includes any tiles moved during interrupts. I think that if the target stops to do something other than move, the value is NOT reset, so it's the total tiles moved during the turn, regardless of other actions performed.

Next up, bulletdodging!!! Yes, indeed, you can dodge bullets. An agile target causes a drop in the shooter's CTH. However, the shooter can compensate for this if his Dexterity is high. This is one of the reasons why dexterity is important for shooting.
If Target can see the Shooter, and Target is not a Tank, and Shooter is not the Bug Queen, then
Dodging_Penalty = (Target's_Effective_Agility / 5) + (Target's_Effective_Experience_Level * 2)
If Target is CROUCHED, then
Dodging_Penalty is reduced by 1/3
If Target is PRONE, then
Dodging_Penalty is reduced by 2/3
Dodging_Compensation = (Shooter's_Effective_Dexterity / 5) + (Shooter's_Effective_Experience_Level * 2)
If Target is a Tank (?????), or Shooter is not the Bug Queen (?????), then
Dodging_Compensation is cut in half!
If Dodging_Penalty is greater than Dodging_Compensation, then
Actual_Chance is reduced by (Dodging_Penalty  Dodging_Compensation)
There's an odd bit here but we'll get to it. If the target is aware of the shooter, they have a chance to try and dodge the bullet, by spotting the shooter preparing to fire, and trying to duck out of the way. Of course, tanks can't dodge out of the way, and the queen is apparently so good that her shots can't be dodged.
The dodging_penalty is based on the target's agility and experience level. To understand what the "EFFECTIVE" values are, please read the beginning of this topic, where this is explained.
Crouched targets are less likely to dodge, and prone targets will find it very hard to dodge.
The shooter's dexterity and level form the Dodging_Compensation. Again, these are EFFECTIVE levels, which are based on stuff like injury.
There's a strange bit here  the program tests to see whether the shooter is the Bug Queen, or the target is a Tank. However, the way the code is written, we won't even get to this point if either case is true! So this command (cut Dodging_Compensation in half) is never executed. Someone should take a look at this and fix it!!!
In any case, at the very end, the two values are compared. If the Dodging_Compensation is higher than the Penalty, that means the shooter is so good he can keep tracking the target even if it tries to dodge out of the way. If the penalty is higher, the target manages to reduce the shooter's CTH. The severity of the reduction depends on the difference between the Penalty and the Compensation, so the more skilled the target is, the more penalty it gives to the shooter!

There's a short bit here that gives range penalties to tanks that aren't firing directly at any target. Tanks sometimes do this if they know roughly where you are  they shoot close to you and hope to hit you in their areaofeffect.
If Target_Tile is empty, and Range_to_Target_tile is less than 120 meters (12 tiles), then
Tank_Penalty = 25 * ( 120  Range_to_Target_Tile ) / 10
This is similar to other tank penalties we've seen before. It's not a repeated penalty though, because earlier we were only talking about situations where the tank is firing at somebody, and this line is only executed if the tank isn't firing at anyone in particular.

We've already factored injury and fatigue into the calculation much earlier, but they're going to be calculated again, and may have a powerful impact on our CTH.
If Actual_Chance is still more than 0, and Shooter is Injured or Bandaged, then
Bandage_Value = Amount of Shooter's health that is currently bandaged (pink)
Injury_Penalty = Actual_Chance * 2 * ( Soldier's_Health_Below_Maximum + (Bandage_Value / 2) ) / (Soldier's_Maximum_Health * 3)
Final_Injury_Penalty = Injury_Penalty * ( 100  ( (Shooter's_Effective_Experience_Level  1) * 10 ) ) / 100
Actual_Chance is reduced by Final_Injury_Penalty
That's very confusing, of course. It's a lot of math, and I won't go too deeply into it. In practice, you get a drop to CTH based on your injury, meaning how much health you've got now compared to the maximum your merc can have. Bandaged damage is half as hurtful as unbandaged damage. Finally, your experience level helps compensate for the penalty, so experienced mercs will suffer less from injury.

Here's one of the most important penalties of them all. Ever notice how, when shooting at someone who is JUST outside your gun's range, your CTH is significantly lower? This is where it happens:
If Range_to_Target is greater than the Weapon's_Range, then
Actual_Chance is cut by half!
Even one tile more than the gun's range, and you lose half your remaining CTH. The programmers say this is due to "bullet drop", but seriously, it's ridiculous. We've already had penalties for being out of range, and this one isn't even scaled  once you're just one tile out of range, you lose 50% of what little CTH you had left?! Hmpf.

Here's another CTH hit:
If the Target is beyond the Shooter's range of vision, then
Actual_Chance is cut by half!
This happens when one soldier spots an enemy, and another soldier (who can't see the enemy) takes a shot. The calculation doesn't depend on whether the shooter can see the target right now, but whether he COULD see it if he turned in that direction and aimed his weapon. This bit of the code is the reason why Snipers need a good scope  otherwise their CTH will suck when firing at enemies they can't actually see.

Believe it or not, we've reached the very end of the formula. There's just one more thing left to do:
If Actual_Chance < 1, then
Actual_Chance = 1.
End.
OMG, this is the most annoying piece of code I have ever seen in my life. This is one of the reasons why I've been upset at JA2 for so long, especially once I started messing with XMLs to try and change the way that guns behave.
What this piece of code means is that CTH can NEVER EVER EVER EVER drop below 1%. You could be firing a pistol from the other end of the map, and it will have 1% chance of hitting the target. 1 in 100 shots is therefore guaranteed to hit the enemy, and with a good automatic weapon you can fire 100 shots within a couple of turns. Conversely, the enemy has a minimum of 1% too, and they tend to fire a whole lot of bullets, often without any realistic chance to hit you, but they still hit you anyway. Of course, if there are obstacles along the way they might stop the bullet, but on a clearer map with fewer obstacles you can actually hit from one side of the map to the other, 1 out of 100 times. This was made even worse by the fact that the program didn't use to really randomize numbers  it's complicated, but it was possible for the program to choose several numbers and only randomize between them, which meant that the minimum chancetohit was actually BETTER THAN 1/100 in some cases!!! Fortunately, SpaceViking has fixed the random number generator in the latest SVN builds.
I've actually managed to change the code and reduce the minimum CTH to 1/1000, and I can now change it to whatever I like, too. This isn't in the release version of 1.13, but I hope that some day this will be changed.

And that's it! The Actual_Chance value at this point is the ChancetoHit for the shot.
Please feel free to ask any questions about this.

CONCISE LIST OF THINGS THAT HELP/HURT CHANCETOHIT
As suggested by Moroes.
Things that help ChancetoHit
 Marksmanship, Dexterity, Wisdom, Experience Level
 Scope
Mostly helpful, especially if it's a highpower scope. Doesn't help if you're too close to the target (based on the scope's Minimum_Range_For_Aiming_Bonus).
 Weapon, worn gear, and attachment condition
Always helpful to keep items repaired, at least above 85%. At 50% or less, you risk getting penalties instead of bonuses.
 Morale
Always helpful to keep this at 50% or higher
 Shooting a second time at the same target
This is, assuming that the target hasn't moved since the last time you shot at it.
 PSYCHO trait
Always good for CTH (although not always good for the actual shooting process...)
 Crouched or Prone stances
Always good, although the closer the enemy, the less benefit you get from these stances.
Also, at very close range, Prone shooters should concentrate on the enemy's legs.
Also, when using a highpowered scope, lie prone.
When using a bipod, lie prone.
 Weapon accuracy
It helps both CTH and the maximum bonus from aiming. More important if the weapon has a scope, less if it doesn't.
 Range
Always good to keep the target at less than the weapon's effective range. If using a scope, try to keep the target at a range higher than the scope's Minimum_Range_For_Aiming_Bonus.
Also, when crouched or prone, without a scope, try to keep the enemy about 4 or 5 tiles away, but no more than 5. You get a good bonus that way.
Also, engagements at 9 tiles or less are always more accurate.
 Ambidextrity trait
For shooting two handguns/SMGs at the same time.
 Free second hand
When shooting a single handgun, gives a small bonus. This means don't put anything in the other hand.
 AutoWeapons trait
Great for bursts and autofire.
 HeavyWeapons trait
Good for rocketlaunchers.
 Sniper trait
Good for increasing the maximum aiming bonus possible.
Also decreases the "effective" range to target.
 Spend extra AP to aim
Helpful, up to a certain number of APs. Only very good marksmen will benefit from the last few APs spent, when using a highpowered scope.
 Good quality laser, in the darkness
Darkness increases the laser's effective range.
 EASY difficulty level
Enemies get lower CTH at easier difficulty, of course.
 Higher weapon range
 Close range to a tank
The closer you get to a tank (preferably under 12 tiles), the less chance it has to hit you.
 Shooting from the roof to targets on the ground
Things that reduce chancetohit
 Injury or bandages
Always bad for CTH. Bandages ("pink" health) have less effect than bleeding damage ("yellow" health).
 Item condition below 85%, or below 50%.
Item condition below 85% will reduce the effectiveness of the item (weapon, or a bonusgiving attachment).
With many weapons and attachments, condition below 50% may start giving penalties, so avoid it.
 Drunkeness
Always bad for you. Hangovers have no effect though.
 Low Morale
Anything below 50% morale is bad for you.
 Fatigue
Anything below 85% fatigue is bad for you.
 Standing or Crouching while using a highpowered scope
If the scope gives +15 aiming_bonus or more, you get a penalty when standing or crouching. Standing is obviously worse.
 When firing and SMG, holding an item in the second hand
Gives a penalty. Try to keep both hands free for SMGs.
 High burst penalty
When firing on burst/fullAuto modes. The more bullets are fired, the less likely they are to hit.
 EXPERT or INSANE difficulty levels
Enemies get a bonus to CTH in these difficulty settings.
 Being gassed
Always very bad for your CTH, unless you're wearing a mask.
 Being bandaged by another merc
A somewhat serious impact on CTH.
 Shock from being hit
Shock remains for a couple of turns after being hit. The worse you were hit, the lower your CTH will be.
 Shooting at the head or legs
Much harder to hit than shooting at the torso, but of course there are benefits to this.
 Target outside effective weapon range
Gives a huge penalty to CTH. You'll usually need a good scope to counteract this.
 Obstacles, enemy camouflage, and smoke
They will all increase the "Effective range to target", making it harder to hit.
 Shooting from the ground to the roof
A small but noticeable penalty.
 Shooting at a target's head or torso, while the shooter is prone and at close range (up to 5 tiles).
 CROUCHED or PRONE target
Will reduce your chance to hit considerably, especially at longrange
 Moving target
The more your target has moved during its turn, the harder it is to hit
 Agile/Experienced target
Decreases your CTH unless you're equally skilled.
 Not being able to see the target
Things you can do to avoid getting hit
 High agility and Experience Level
They help considerably to reduce the shooter's CTH.
 Crouched/Prone stance
They help, especially at long range. Not very helpful at short range.
 Stay outside enemy's effective range
Of course, you would need to know their weapon's range for that...
 Camouflage, cover, and smoke
All will increase the enemy's Effective_Range value
 Injure the enemy
Will increase their injury, fatigue, and shock penalties.
 Gas the enemy
Assuming he isn't wearing a gasmask.
 If enemy is a tank, stay close and low
If you have to get close to a tank, try to get as close as possible, as fast as possible. Below 12 tiles of range, the tank begins to take serious penalties, especially if you're crouched or prone.
 Get up on a roof
This decreases his chance to hit you, and increases your chance to hit him.
 Move around!
The more you move during your turn, the less chance the enemy has to hit you.
 High agility and experience level
Will help you dodge bullets... assuming the enemy isn't very skilled
[Updated on: Wed, 10 September 2008 01:52] by Moderator



   
Re: "How does it work?" Part 4: ChancetoHit[message #196144] 
Tue, 09 September 2008 20:37  
szultz


Messages:24
Registered:October 2004 Location: Estonia 


HeadrockDid you notice the word HARSH at the end? That's another one of those statusbased modifiers. In this case, as the weapon or the attachment get damaged, their Final_Aiming_Bonus slowly decreases towards 0. It reaches 0 at 50% status, and if the item gets damaged beyond 50%, you start getting a PENALTY instead of a bonus!!! This is very different from armors, but then again armors always give penalties anyway in 1.13. I'm thinking people may want to change this, in the future...
Actually I think the HARSH bonus system is more realistic, if you're laser sight is in a such a bad condition, it does not point to right target anymore, and if you aim where it points, you'll miss.



      
Re: "How does it work?" Part 4: ChancetoHit[message #196407] 
Mon, 15 September 2008 08:09  
Headrock


Messages:1772
Registered:March 2006 Location: Jerusalem 


In one word, yes. But not in the way you'd expect.
With today's code, the aiming bonus of a scope (and other equipment) helps reduce the effective range to the target. So in effect, the higher the scope's aiming bonus, the closer the target is considered to be, for purposes of determining whether the target is within laser range, and also in determining the universal range penalty (which is 3 points per tile). Even better, it reduces the penalty you get for shooting at the head or legs.
An aiming bonus of +20 (scope 10x) gives a 20meter shortening of range for the first AP spent (2 tiles). That number then slowly diminishes with each AP you spend. In one example I did in the article, I got the effective range shortened by 50 meters (5 tiles) using an imaginary scope. With a regular sniper scope you can get about 7 or 8 tiles shortening of range. It doesn't sound like much, but when the universal range penalty is taken into account, this translates to around +25 bonus to your CTH (not for each AP, but for ALL APs spent). Since the universal bonus is calculated near the end of the formula, the CTH bonus is almost entirely flat (meaning, an actual +25, unmitigated by anything else). Of course, with lowerend scopes, you'll get less of a bonus.
However, if the scope gives +15 aiming bonus or more, then you have to make sure you're prone (or at least crouched) to avoid getting penalties...
All in all, it's a very strange way to calculate it. Much of the confusion comes from the fact that a value with an outdated name ("Aiming Bonus") is now being used in a completely different way.



                
Re: "How does it work?" Part 4: ChancetoHit[message #215155] 
Mon, 04 May 2009 16:43  
Tobababy

Messages:1
Registered:March 2009 Location: sweden 


Splendid! Thanks a lot for lots of interesting info!



          
Goto Forum:
Current Time: Tue Sep 28 19:49:57 EEST 2021
Total time taken to generate the page: 0.09895 seconds
