Jump to content

Squadsight Aim Penalties


Amineri

Recommended Posts

I've been working on a method to apply aim penalties to units (presumably snipers ...) that are currently using Squadsight to target/shoot at an enemy.

 

Here are the results of my efforts so far:

http://wiki.tesnexus.com/images/e/ef/Squadsight_aim_penalty_example.jpg

 

The picture link is updated to one in which the mod is fully working. Everything about the mod is on the wiki here: http://wiki.tesnexus.com/index.php/XCOM_Squadsight_Aim_Penalty_Mod

 

-----------------------------------------------------------------------------------

 

Unfortunately the actual to-hit calculations are hidden in the native code, so I've had to come up with some workarounds (read: HACKS).

 

Essentially I'll be applying an extra penalty in the function XGAbility_Targeted.RollForHit, which only triggers if the target unit is greater than 27.5 "tile units" away from the shooter.

 

The HUD Shot Summary above is modified via XGAbility_Targeted.GetShotSummary. Unfortunately, the total chance to hit is not reflecting the additional modifier that I snuck into the ShotSummary data structure -- it must be retrieving the hit value directly (fixable, but yet another HACK).

 

--------------------------------------------------------------------------

 

The question then arises: what form should the aim penalty take? So far I have come up with two options:

 

option #1)

if(range > 27.5)

{

penalty = Max(int(10.0 + (range - 27.5)*1.1) ,0); // measured in %
}
This provides a constant aim penalty as soon as squadsight is activated, plus an additional aim penalty for each tile further away the target is. The 19% penalty in the screenshot above reflects this formula.
I see this as requiring the player to keep the sniper somewhat close to the action in order to keep her effective. Shooting from across the map just won't work anymore. Positioning the sniper well is now more difficult. Because the sniper is closer, she is at more risk of damage/death.
((if you are interested, range = VSize(m_kUnit.GetLocation() -GetPrimaryTarget().GetLocation()) / float(64); ))
option #2)
if(range > 27.5)
{
penalty = -25 + 5*Max(ktarget.m_arrEnemiesSeenBy.Length, 5); // measured in %
}
This is a penalty that is not dependent upon range to target, but is based upon the number of XCOM soldiers that can see the target unit. It's a flat -25 aim, with an additional +5 aim recovered for each XCOM unit that can see the enemy. I capped it at 5 units so that it can never become an actual bonus (I think battlescanners count, so it could be possible to get more than 5 XCOM units seeing a target).
This limits the effectiveness of a single scout sighting for multiple squadsight snipers. It encourages more limited numbers of snipers, but also requires the player to put other units at more risk in order to effectively use the sniper. The sniper can stay at extremely long range and stay very safe, however (excepting those launching Floater, of course!).
I actually cribbed this idea from someone on the 2K forums.
-----------------------------------------------------------------
In both cases the numbers could be tweaked. (or tuned/balanced for a particular mod). Unfortunately the values had to be hard-coded into the hex.
My question to all you happy people out there is this : are both of the options above of interest to people? Is there another formulation that anyone would care to suggest?
If one of the options is clearly preferable, I'd be happy to save time by implementing only one of them. That said, most of the work is involved in clearing space and correcting jump offsets, so it's not a ton of extra work to make both available. (or a good 3rd option, if one presents itself)
Is some combination of the two a good idea? My worry is that the penalties could easily stack up so high as to render Squadsight completely unusable.
Edited by Amineri
Link to comment
Share on other sites

My gut likes #2 a little better, because it has more of a teamwork component to it.

 

The presence of a civilian in a council mission or a mind-controlled alien might also affect the calculation, so the max check is definitely necessary.

Edited by johnnylump
Link to comment
Share on other sites

I've realized that I can roll both options into a single formula, which can be configured (via the constants) to be either one, or a combination of the two:

 

penalty = Min(-25 + 5*Max(GetPrimaryTarget().m_arrEnemiesSeenBy.Length, 5) - int(1.1*(range - 27.5)), 0);

 

  • To make it only based on number of XCOM units that see that target, change the 1.1 to 0.0
  • To make it only based on range, change the 5 (before Max) to 0
  • To make it a constant penalty, change both the 5 to 0 and the 1.1 to 0.0

It's possible to combine both. In fact, it can be set so that having more XCOM units spotting the target can offset the range penalty.

 

If the -25 were changed to -15, having 5 XCOM units spotting the target would grant a +10 aim bonus that could offset up to -10 of range penalty (-10 would be achieved at around 9 tiles beyond the 27 visual range).

 

-----------------------------------------------

 

The biggest advantage for me, naturally, is that I would only have to maintain one version :)

Link to comment
Share on other sites

I've always found the squadsight ability a bit lame, and in fact the very first hex edit I made to xcom was removing it and some other cheaty perks, so I welcome any attempt to limit it. Honestly what I find more interesting of all this is the possibility of creating a custom weapon range penalty, either via specific formula, or just in two steps, using regular aim range penalty plus squadsight range penalty, so any soldier could shoot using squadsight but at greater aim penalty than regular weapon range penalty... the issue is still sight range, anything above 29 will eventualy cause a ctd. For this purpouse it would be great if the check that triggers the process were to check if (distance > weapon range) instead of constant 27.5, to allow it being implemented as an extra aim penalty for very long distances. In this direction, if the number in the combined formula were to represent weapon range instead of 27.5 again that would be great, making so weapons with largest range takes less range penalty, while short-ranged weapons take huge aim penalty once using squadsight (out of weap range). Imo this would better simulate a shotgun behaviour than current linear aim decrease (which could still be present but moderated).

Link to comment
Share on other sites

I also considered that this could be used to create aim penalties based on range in a more generic sense than just squadsight. This same methodology also would allow adjusting damage based on range (recall my concept of making plasma weapons do less damage at longer ranges?).

 

I freed up a LOT of hex filebytes in the XGAbility_Targetted.GetShotSummary. The issue is that the bytes freed were the "extra" calls to retrieve constants, which also dramatically reduced the virtual size. The function is very long (I only reworked the first half, and it's still a hex replacement of over 2,000 bytes). Going through and recalculating all those jump offsets ... @_@. There is room for more code, but code that actually uses variables is better than using constants, as it turns out in this case.

 

I had hard-coded 27.5 as 27 is the standard sight range. I went with 27.5 to give a little slop (in case of floating point round-off issues) so that it shouldn't be possible to get the "squadsight" range penalty when the target is actually still in sight range.

 

---------

 

Regarding the weapon range thing, I think there are other checks that prevent a unit from firing at a target unit if it is beyond weapon range, so this code wouldn't even be encountered in that case. Sniper rifles have their range set to 100 for just that purpose. I believe that if the test were compared to weapon range, then there would never be a penalty -- it certainly wouldn't work as a squadsight penalty.

 

The code that actually checks whether a unit is visible or "visible via squadsight" is hidden away in the native code as far as I can tell -- thus my triggering the extra penalty based on being beyond standard sight range. I could alter the test to explicitly compare to sight range, but I don't know that it would gain much. If there were some secondary weapon value that could be used, that would work. Then "weapon range" would really be "maximum weapon range" and the new value would be "optimal weapon range". The only value that seems "free" is the ReactionAngle. I've been avoiding touching any of the Reaction Fire stuff, since it apparently works if turned on, so I've not wanted to break existing functionality.

 

Another alternative would be to use a fixed percentage of the weapons current range (effectively maximum range). Thus the optimal range could be set to 60% or 70% of the maximum range. However, this would effectively be a nerf to all classes except for snipers, which is kind of the opposite of what I was going for. Unless the other classes all got access to squadsight, which creates all sorts of balance issues, since the aliens don't have access to squadsight. If the aliens were to get Squadsight, I don't know that it would really make the game all that much more enjoyable, tbh.

 

I also have not tested under what conditions it is possible to give non-sniper units Squadsight. It may be that they would require sniper weapons to utilize it, just as Bullet Swarm is hard-coded to be usable only by the Heavy class using a Heavy weapon.

 

-------------------------------------------

 

The funny thing about Squadsight being a "cheat" is that it was the standard in the X-COM OG. All units could shoot at any sighted unit -- effectively all units had "Squadsight" as it's conceived of now in the XCOM NG. I think that it still has a place in the game, but the flat hit percentages that work within the limit of sight radius become broken when extended out to range 100.

 

I'm certainly open to entertaining additional mutations to this, but for now I'm just trying to get the functionality working for squadsight snipers. It looks as though I have to significantly rebuild three major functions. RollForHit and GetShotSummary in XGAbility_Targeted, and UpdateDisplay in UIUnitGermanMode_ShotInfo. These functions are called quite frequently, so any bugs should become apparent quickly, at least.

 

((I still have no idea why those functions are called GermanMode, btw))

Link to comment
Share on other sites

XComGame >> XGAbilityTree >> BuildAbilities() define how each ability performs, in many sort of terms, one of them being range, as defined in

enum EAbilityRange
{
    eRange_None,
    eRange_Weapon,
    eRange_Sight,
    eRange_SquadSight,
    eRange_Loot,
    eRange_Unlimited,
    eRange_MAX
};

I've tweaked this function to make standard shot ability, head shot, disabling shot, rapid fire, supression, overwatch, etc, use the Weapon range, so that can be effectively limited. If those abilities were granted squadsight range instead, the weapon "custom" range (as set in the ini) would be still valid --- not as a maximum range (it'd always be squadsight), but for using it in that function as the distance from which the weapon really becomes inaccurate. So in theory this should work either for eWP_Rifle weapons (only aim bonus), eWP_Assault weapons (both close range bonus and long range penalty), eWP_Sniper weaps (using SNIPER_AIM_FALL, which can be given a positive value and thus using it as another close range bonus), and if the formula used to calculate that "squadsight aim penalty" would use the weapon range as a factor for aim drop then I think that'd work for most of weapons without feeling like cheating when shooting distant targets. This same weapon range value could be used to calculate output damage. "In range" shots could grant always 100% dmg, while out of range means a quick damage drop (depending on weapon type) or vice versa (long range 100% dmg, close range even more), or make it linear...

 

One thing that bothers me regarding weapons aim bonus is that they're tied to this properties that also set which class can equip them, the IsClassEquipable function is a mess, and Machineguns having to reload more often that rifles bothers me the most, but surprise, that is tied to weaps having the eWP_Heavy property, ... if it weren't such a mess I'd tried to stack the eWP_Rifle & eWP_Assault tags to get a greater close aim bonus than long range penalty (ie increasing +5% aim for each tile closer than CLOSE_RANGE, and decreasing aim 2~3% for each tile further), but balancing this all would mean reworking that IsClassEquipable function entirely, and maybe swapping or changing weapon properies (so for example the eWP_Support tag means it can be equipped by Heavy class) in order for each weapon to behave as desired and to make it available only to desired classes, so it would be less clear in the end... but anyway I haven't found the time for this yet, so any improvement in this field is welcome.

 

I was just thinking now of the possible implications of making abilities use squadsight... if aliens were to use it as well, we may expect being shot without actually seeing who shots at us... the sole idea it's quite scarying, although a bit exciting too :P

Link to comment
Share on other sites

I don't believe that there is a "squadsight range". There is just weapon range. The DGC.ini line for the Sniper Rifle:

 

 

 

Weapons=(iType=eItem_SniperRifle,ABILITIES[0]=eAbility_Overwatch,ABILITIES[1]=eAbility_NONE,ABILITIES[2]=eAbility_ShotStandard,ABILITIES[3]=eAbility_NONE,ABILITIES[4]=eAbility_NONE,ABILITIES[5]=eAbility_NONE,Properties[0]=eWP_Sniper,Properties[1]=eWP_MoveLimited,Properties[2]=eWP_None,Properties[3]=eWP_None,Properties[4]=eWP_None,Properties[5]=eWP_None,iDamage=4,iEnvironmentDamage=30,iRange=100,iReactionRange=-1,iReactionAngle=200,iRadius=0,iCritical=25,iOffenseBonus=0,iSuppression=0,iSize=eItemSize_Large,iHPBonus=0,iWillBonus=0)
has iRange = 100. This is how the squadsight range is defined for snipers. Normally you are limited to shoot at what you can see, but squadsight lets you shoot at things that you can't see, but others can (although you have to have LOS still, of course). This is why I can't use the sniper weapon range, but have to use the sight radius.
-------------------------
The functions that calculate aim drop and rise based on the DGC.ini constants are not accessible (they seem to be in native code). That means that those aim bonuses/penalties can't be easily turned off (I haven't figure out how to do so), except by changing the DGC.ini values. This means that I can't re-use those DGC.ini variables as a part of this mod :(
I'm effectively circumventing the code's normal mechanism for applying distance penalties. What I'm doing is more akin to the "cheating" aim bonus that the game applies in Easy and Normal modes. In fact, I'm applying the mod to hit at the same place. However, I'm duplicating the formula so that it will display in the ShotInfo HUD.
-----------------------
In X-COM OG, during night missions the X-COM soldiers sight radius was reduced, but the aliens' wasn't. Combined with the reaction fire mechanic, it made night missions especially terrifying and deadly. Night missions often meant several dead soldiers. This balanced okay because of larger squad size, though -- 14 soldiers or 10 soldiers + 1 tank. With 4 soldiers it would be a hot mess, I suspect.
Also, I'm not exactly sure how squadsight would interact with the alien AI. We already have problems with aliens skipping turns, without introducing too many new abilities.
----------------------
Those functions ARE a big mess. Hence I'm going to try and keep the scope of this initially limited -- providing a way to tone down the power of squadsight on snipers. I'll post up my notes if you are interested, but I warn you -- they are long! The text document with my hex changes and notes for this mod is already 106 kilobytes. I have implemented the HUD ShotInfo (testing now), but not the actual RollForHit mechanics.
Link to comment
Share on other sites

Update:

 

So, I've got the total to-hit chance being correctly displayed in the big ShotSummary Window. The m_arrEnemiesSeenBy includes only those enemies in Sight Radius range (direct sight), so the squadsight trooper doesn't count.

 

However, I've just realized that there are THREE additional places where the overall to-hit percentage is displayed:

1) In the zoom-in view, to the upper left of the targetted creature

2) In the small HUD when you first start the Fire Action

3) When hovering the mouse over the enemy icons on the right side of the screen

 

All three of these draw from the innate m_iHitChance (which is computed/updated in the native code).

 

If you look at the screenshot in the original post, you can see #1 and #2 behind and above the large Shot Summary window.

 

I can think of a couple of options:

1) Just let it go -- the player has to be aware that the displayed values for squadsight are optimistic, and the correct values are displayed in the Shot Summary window.

2) Try to suppress the display of those three values for squadsight shots

 

I don't think I'll be able to get the other three values updated. I had to pull a bunch of tricks to get the ShotSummary HUD values to display correctly, and the same tricks won't work for the other values.

 

The decompiled code that computes the aim penalty looks like so:

m_fDistanceToTarget = VSize(m_kUnit.GetLocation() - GetPrimaryTarget().GetLocation()) / float(64);
// End:0x6C7
if(m_fDistanceToTarget > float(m_kUnit.m_aCurrentStats[10]))
{
m_iPrimaryMultiShotTarget = Min(((5 * Min(GetPrimaryTarget().m_arrEnemiesInRange.Length, 5)) - 25) - int(0.0 * (m_fDistanceToTarget - float(m_kUnit.m_aCurrentStats[10]))), 0);
kInfo.arrHitPenaltyStrings.AddItem(m_strCheating);
kInfo.arrHitPenaltyValues.AddItem(m_iPrimaryMultiShotTarget);
}

 

I can't quite release the hex code yet. :D I've updated the HUD display (both line item and total hit chance), but still have to actually adjust the RollForHit function. I left it for the end because it's a lot harder to verify. Now that I know that the aim penalty is being calculated correctly, I can re-use the same code in RollForHit. ((I the the m_strCheating config variable to hold the new label for the "Squadsight Long Range" ))

 

I also gave in and am using the actual sight-range stat from the shooting unit, rather than the hard-coded 27.5 number.

 

Any thoughts, suggestions, or ideas about the other three to-hit displays would be much appreciated.

Link to comment
Share on other sites

I've tried that squadsight range out of curiosity and it isn't as cool as it could have been. I've tested giving standard shot the squadsight range, and then I gave assault rifle 100 range, but I couldn't shot out of sight range enemies (I mean in LOS but further than 27 distance units). Then I tried giving each soldier the squadsight perk, and now I could shot any enemy in LOS regardless of the weapon range set in the ini (I know cause pistols had short range but I was able to shoot squad-sighted enemies with the pistol as well), but I had to give'em the perk, so I guess if this were to be used for aliens I should give'em the perk as well.

Link to comment
Share on other sites

<p>I've been experimenting a bit more with this abilities' range and I think I finally get it:<br />

- If ability range is Squadsight and unit has the squadsight perk then there's no range limit, regardless what the weapon range was in the ini.<br />

- If ability range is Weapon and unit has the squadsight perk, maximum range is still limited to weapon range (as set in the ini), although now that range can exceed unit's view distance.<br />

- If unit doesn't have squadsight perk, then if ability range is sight or squadsight, max range becomes unit's view distance, but if ability range is Weapon, the max range is the weapon own max range as set in the ini, but not above view distance.<br />

 <br />

I think that forcing this second case (all the abilities' range set to Weapon range, and also all units having free squadsight perk) could drastically expand the battlefield, allowing fights from longer distances (hopefuly in both directions). The idea is to increase the "close range treeshold" up to 15~19, so it gets closer to view distance (29), and then limit each weapon range above that 29, or below for short range weapons, or much above for snipers, although it may not need to reach 100, just x1.5 or x2 times a rifle range is ok. So when you'd spot an enemy it wouldn't be faaar far away, but rather pretty close! It may get somehow weird though if aliens disappear from a unit's sight because you've moved *another* unit... conceptually this squad sight thing still doesn't convince me, I realize I'm just looking for workarounds for the limited view distance, but that's what we've got.<br />

 <br />

Another interesting combination is granting each unit the squadsight perk as well and make abillities use the sight or squadsight range, so weapon range (ini setting) is ignored for this purpouse and thus can be safely used to set a custom long range aim penalty. In this case it is to assume that this custom long range penalty would be enough in itself to discourage or disable the use of short range weapons against far enemies.<br />

 <br />

I know it's much of what I said before, and that is quite off-topic, but now I've tested what I'm stating and it's still pretty related to your proto-mod, so if some of this thoughts may help improving your tactical game use them as you please.</p>

Edited by anUser
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...