OpenXcom Forum

Modding => OpenXcom Extended => Topic started by: ohartenstein23 on August 13, 2016, 06:46:51 pm

Title: [DONE] [Suggestion] 'Realistic' Shotgun Behavior
Post by: ohartenstein23 on August 13, 2016, 06:46:51 pm
'Realistic' Shotgun Behavior Executable
Link for Google Drive Archive with Test Mod (https://drive.google.com/open?id=0BzdM3YhNg14pandia1c1aTN0aFE)
Link for Test Mod Only (https://drive.google.com/open?id=0BzdM3YhNg14pam96enJzc0RubU0)
Link for OXCE+ Executables (https://drive.google.com/open?id=0BzdM3YhNg14pLWY4Ml9aTGZ2aTA)
Link for GitHub OXCE+ Repository (https://github.com/ohartenstein23/OpenXcom/tree/oxce3.0-plus-proto)

Based on the discussion in https://openxcom.org/forum/index.php/topic,4744.0.html (https://openxcom.org/forum/index.php/topic,4744.0.html), I've created an edited version of Yankes' OpenXcom Extended executable to better model realistic shotgun behavior, or at least make the spread pattern of shotgun pellets configurable enough to look realistic.  I've attached a link to a zip archive of the edited source code (in the subfolder OXCE/src) and a mod that demonstrates this new behavior on a few different shotguns.  There's a compiled executable for Ubuntu 14.04 and Windows.  Here's the rundown of what this modification does:

The base behavior of shotgun pellets starts by calculating a normal trajectory like any other weapon for the 'first' pellet projectile.  The following pellets, up to the number defined by shotgunPellets on the ammunition in the ruleset, take the previous trajectory and modify it by the accuracy of the shot minus 5% for each pellet after the first, leading to a wide cone around wherever you clicked.

The new behavior starts the same way by calculating the first trajectory by the normal weapon/firing accuracy, but then each subsequent pellet is spread around the point of impact, with the spread defined by a few new definitions in the ruleset, affected by the range dropoff of the weapon:

All the ruleset defaults are set such that these changes will not affect weapon/ammunition definitions in current mods, ensuring compatibility and no unexpected changes.

The attached mod borrows a few shotguns from Dioxine's XPiratez mod (https://openxcom.org/forum/index.php/topic,3626.0.html (https://openxcom.org/forum/index.php/topic,3626.0.html)), and adds possible values of the parameters above to give a feeling of what's possible using these changes.

Edit 170130 This has been included in OXCE+ long ago, so the above links to my repositories and .exe's are deprecated in favor of the current OXCE+ version.
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: ohartenstein23 on August 13, 2016, 06:50:00 pm
Here are the changes that I made to the source code: (now out of date, will modify later)

In src/Battlescape/ProjectileFlyBState.cpp, changed these lines under ProjectileFlyBState::think() from
Code: [Select]
https:// special shotgun behaviour: trace extra projectile paths, and add bullet hits at their termination points.
if (shotgun)
{
int i = 1;
while (i != _ammo->getRules()->getShotgunPellets())
{
https:// create a projectile
Projectile *proj = new Projectile(_parent->getMod(), _parent->getSave(), _action, _origin, _targetVoxel, _ammo);
https:// let it trace to the point where it hits
_projectileImpact = proj->calculateTrajectory(std::max(0.0, (_unit->getFiringAccuracy(_action.type, _action.weapon, _parent->getMod()) / 100.0) - i * 5.0));
to
Code: [Select]
https:// special shotgun behaviour: trace extra projectile paths, and add bullet hits at their termination points.
if (shotgun)
{
int spread = _ammo->getRules()->getShotgunSpread();
int choke = _action.weapon->getRules()->getShotgunChoke();
Position firstPelletImpact = _targetVoxel;

int i = 1;
while (i != _ammo->getRules()->getShotgunPellets())
{
https:// create a projectile
Projectile *proj = new Projectile(_parent->getMod(), _parent->getSave(), _action, _origin, _targetVoxel, _ammo);

https:// which type of shotgun behavior to use?
bool groupingBehavior = _ammo->getRules()->getShotgunBehavior();
if (!groupingBehavior)
{
https:// let it trace to the point where it hits
_projectileImpact = proj->calculateTrajectory(std::max(0.0, (_unit->getFiringAccuracy(_action.type, _action.weapon, _parent->getMod()) / 100.0) - i * 5.0 * spread / 100.0));
}
https:// pellet spread based on where first pellet hit
else
{
_targetVoxel = firstPelletImpact;
_projectileImpact = proj->calculateTrajectory(std::max(0.0, (1.0 - spread / 100.0) * choke / 100.0));
}

To expose the calculates to the ruleset, in src/Mod/RuleItem.cpp, the line
Code: [Select]
_maxRange(200), _aimRange(200), _snapRange(15), _autoRange(7), _minRange(0), _dropoff(2), _bulletSpeed(0), _explosionSpeed(0), _autoShots(3), _shotgunPellets(0),
was changed to
Code: [Select]
_maxRange(200), _aimRange(200), _snapRange(15), _autoRange(7), _minRange(0), _dropoff(2), _bulletSpeed(0), _explosionSpeed(0), _autoShots(3), _shotgunPellets(0), _shotgunSpread(100), _shotgunBehavior(false), _shotgunChoke(100),
and the following lines were added to RuleItem::load()
Code: [Select]
_shotgunSpread = node["shotgunSpread"].as<int>(_shotgunSpread);
_shotgunBehavior = node["shotgunBehavior"].as<bool>(_shotgunBehavior);
_shotgunChoke = node["shotgunChoke"].as<int>(_shotgunChoke);
with the functions
Code: [Select]
/**
 * Gets the spread of projectiles from this ammo for use in shotgun behavior.
 * @return The spread.
 */
int RuleItem::getShotgunSpread() const
{
return _shotgunSpread;
}

/**
 * Do the shotgun pellets follow a grouping, or just fired in a cone-like behavior?
 * @return false => cone-like spread, true => grouping
 */
bool RuleItem::getShotgunBehavior() const
{
return _shotgunBehavior;
}

/**
 * Gets the shotgun choke value for modifying pellet spread
 * @return weapon shotgun choke value
 */
int RuleItem::getShotgunChoke() const
{
return _shotgunChoke;
}

Finally, the variables were added to RuleItem.h
Code: [Select]
int _listOrder, _maxRange, _aimRange, _snapRange, _autoRange, _minRange, _dropoff, _bulletSpeed, _explosionSpeed, _autoShots, _shotgunPellets, _shotgunSpread;
bool _shotgunBehavior;
int  _shotgunChoke;

and

https:/// Get the spread of projectiles with shotgun behavior.
int getShotgunSpread() const;
https:/// Get which shotgun spread behavior to use.
bool getShotgunBehavior() const;
https:/// Get the shotgun choke value of this weapon.
int getShotgunChoke() const;

Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: Meridian on August 13, 2016, 07:40:54 pm
Source code?
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: ohartenstein23 on August 15, 2016, 06:40:06 am
It's in the OXCE folder of the zip archive, and I'm planning on posting the changes here in the thread later today.

Once I figure out how to use it, I can put it on GitHub too.

--- posts merged - Solarius Scorch ---

I'm having trouble with my windows partition - could somebody compile the source and send me a copy of the .exe?
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: Meridian on August 15, 2016, 08:30:40 pm
Took me an hour to make a diff... really should use git :)
Anyway, git patch is attached, if anyone wants to have a look.

A quick question:
1. what is the purpose of this code:

Code: [Select]
https:// pellet spread based on where first pellet hit
_targetVoxel = firstPelletImpact;


I tried it without this code and the _targetVoxel value is not changing anyway... am I missing something?

Use for example this to log the values:

Code: [Select]
Log(LOG_INFO) << "_targetVoxel [x,y,z]: [" << _targetVoxel.x << "," << _targetVoxel.y << "," << _targetVoxel.z << "]";

My output on blunderbuss was:

Code: [Select]
[15-08-2016 19:27:14] [INFO] _targetVoxel [x,y,z]: [344,264,24]
[15-08-2016 19:27:14] [INFO] _targetVoxel [x,y,z]: [344,264,24]
[15-08-2016 19:27:14] [INFO] _targetVoxel [x,y,z]: [344,264,24]
[15-08-2016 19:27:14] [INFO] _targetVoxel [x,y,z]: [344,264,24]
[15-08-2016 19:27:14] [INFO] _targetVoxel [x,y,z]: [344,264,24]

And one more question:
2. why did you change also the vanilla behaviour (by adding spread to it)?
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: Yankes on August 15, 2016, 09:15:02 pm
Took me an hour to make a diff... really should use git :)
Anyway, git patch is attached, if anyone wants to have a look.

A quick question:
1. what is the purpose of this code:

Code: [Select]
https:// pellet spread based on where first pellet hit
_targetVoxel = firstPelletImpact;

I tried it without this code and the _targetVoxel value is not changing anyway... am I missing something?
I miss this it too. `_targetVoxel` looks that is change only on initing this state, after that it stay constant.



And one more question:
2. why did you change also the vanilla behaviour (by adding spread to it)?
Default is 100 and this probably should give result similar to original.
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: ohartenstein23 on August 15, 2016, 09:48:29 pm
@Meridian:  I started a fork of your code on github and made a pull request to your branch there, here's the link to my repository: https://github.com/ohartenstein23/OpenXcom/tree/oxce3.0-plus-proto

I must have misread calculateTrajectory in Projectile.cpp - I thought the call to applyAccuracy changed _targetVoxel, and so each call to it would would replace the original value.  The point was that I wanted to make sure the final pellet spread was centered around where the first one hit, rather than always where you clicked.  If it doesn't change at all between calls to calculateTrajectory, then this was unnecessary.  I also didn't know quite how to write to the log; I don't have a whole lot of C++ experience.

And Yankes was right about the change to the vanilla behavior, I wanted to make the vanilla behavior configurable as well, while the default value of shotgunSpread: 100 is to return to the original behavior.
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: Meridian on August 15, 2016, 10:07:30 pm
OK, thanks a lot.
I will check it on Wednesday... format a bit, remove unnecessary code, probably change the behaviourType from bool to int... and do some testing.

After that I will merge it to OXCE+ and let Dioxine do the proper testing  8)
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: ohartenstein23 on August 15, 2016, 10:14:45 pm
Sweet, thanks for taking a look at it.  I originally had shotgunBehavior as an int, I had changed it to bool for readability - I can change it back.  The _targetVoxel thing makes me want to take a second look at this, I'm not sure it's working the way I intended.  I'll commit the changes to the GitHub repository.
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: Meridian on August 15, 2016, 10:21:02 pm
The _targetVoxel thing makes me want to take a second look at this, I'm not sure it's working the way I intended.

Yes, please have a look.
The more eyes, the better!
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: ohartenstein23 on August 15, 2016, 10:26:34 pm
After some testing with output to the log, it looks like the spread isn't actually going around the first pellet impact point, so it always spreads around the tile that was clicked.  Do you know offhand how to get the (x, y, z) position of the impact point, rather than just the target voxel?
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: Yankes on August 15, 2016, 10:53:57 pm
After some testing with output to the log, it looks like the spread isn't actually going around the first pellet impact point, so it always spreads around the tile that was clicked.  Do you know offhand how to get the (x, y, z) position of the impact point, rather than just the target voxel?
Code: [Select]
_parent->getMap()->getProjectile()->getPosition(offset)
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: ohartenstein23 on August 15, 2016, 11:16:07 pm
Thanks Yankes, I just found that in the code for where the hit explosion is drawn.
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: ohartenstein23 on August 16, 2016, 12:25:49 am
Is there a way to cause a calculateTrajectory() call to do the calculation as if CTRL was being held for force fire?  I'm getting a problem where in some instances the extra pellets fail to fire with _projectileImpact = -1 (no line of fire).

Edit: Never mind, I think I found the problem - instead of using getPosition(offset), I used getPosition(-2) to make sure that the position calculated for the impact was not inside an object and therefore the line of fire to the new target isn't obstructed.

Edit:  Repository and archive updated with new code that should be working as intended.  Anyone out there want to compile a Windows executable?
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: Yankes on August 16, 2016, 06:48:05 pm
Is there a way to cause a calculateTrajectory() call to do the calculation as if CTRL was being held for force fire?  I'm getting a problem where in some instances the extra pellets fail to fire with _projectileImpact = -1 (no line of fire).

Edit: Never mind, I think I found the problem - instead of using getPosition(offset), I used getPosition(-2) to make sure that the position calculated for the impact was not inside an object and therefore the line of fire to the new target isn't obstructed.

Edit:  Repository and archive updated with new code that should be working as intended.  Anyone out there want to compile a Windows executable?
As you use Linux you can easy compile it yourself using mxe build chain (https://"https://mxe.cc/") with this makefile: https://github.com/Yankes/OpenXcom/blob/OpenXcomExtended/src/Makefile.mxe
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: ohartenstein23 on August 16, 2016, 06:56:26 pm
Huh, I didn't know that.  Thanks for the tip, I'll try it and add the windows executable to my archive!

Also, thanks for helping me figure out how to do this - I don't think I'd know what to do just figuring out the C++ code myself.

Edit: Got it to compile!  Had to mess around with Makefile.mxe though, specifically adding -lyaml-cpp to the libs in LDFLAGS.  I'll update the first post and the archive with the new executables.
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: HelmetHair on August 18, 2016, 02:47:29 am
Does this mean if I had a near miss with a shotgun that I could still hit them with the spread?

So if my soldier actually "missed" by not hitting with the first pellet then one from the spread might hit?

I'd love to shoot and miss and still "wing" a target from a near miss beyond point blank range.

Anyways...

best regards

-HH
Title: Re: 'Realistic' Shotgun Behavior Executable
Post by: ohartenstein23 on August 18, 2016, 04:14:52 am
Yes, depending on the spread parameters, a near miss could still hit the target.  The larger (wider) the shotgunSpread value and the lower the shotgunChoke value, the more likely it is you'll still hit the target on a miss.  At low spreads, all the pellets will probably hit in the same tile and a miss means a complete miss.
Title: Re: [DONE] [Suggestion] 'Realistic' Shotgun Behavior
Post by: Eddie on February 15, 2019, 02:03:41 am
Sorry to resurrect this topic, but I think there is an important error in the description.

It says that a shotgun spread of 50 should result in roughly 50% of the pellets hitting the target. I did some testing to see if that is true, and it seems the scaling is not linear but quadratic. So it's not "pellets*0,5" but rather "pellets*(0,5^2)"

What I did: shoot a double barrel shotgun from piretez mod with buckshot at a target 15 tiles away. That thing has a spread of 48,75% and 10 pellets.
According to the description for his mod, this should result in roughly 5 pellets hitting your target on average. What I actually saw was an average of 2.1, which is significantly less than 5 but quite close to 2.37 that you would expect if the quadratic scaling was true.
I did some further testing with the military shotgun and buckshot. That thing has a spread of 75 and 7 pellets. Linear scaling will give you 5.25 pellets on average, quadratic scaling 3.9. What I saw was exactly 3.9 pellets hitting on average. This weapon I also tested at 20 tiles and got roughly the same number.
The quadratic scaling makes sense since you fire in a cone and the spread is in 2D and not 1D.

Now what really bugs me: Is this quadratic scaling also true for non shotgun weapons, or is that just ohartenstein23's code? Like, a 50% shot will actually only hit 25% of the time.
That seems congruent with my gut feeling. When playing I try to avoid 50% shots if I can because those always miss anyway. 75% and up is an accuracy where I feel comfortable that it is worth taking the shot...
Title: Re: [DONE] [Suggestion] 'Realistic' Shotgun Behavior
Post by: ohartenstein23 on February 15, 2019, 03:47:56 am
The accuracies reported in X-Com aren't actually percentages, they're measurements of maximum possible/likely deviation from the direct line of fire to the target. 0% accuracy means maximum possible deviation, 110% means minimum possible. I think it works out to approximate chance to hit at either 10 or 20 tiles from when I did the math on it, but the point is lower spread is better, higher spread is worse.