Author Topic: a different shotgun behavior  (Read 12922 times)

Offline HelmetHair

  • Colonel
  • ****
  • Posts: 360
  • He who laughs last thinks fastest.
    • View Profile
Re: a different shotgun behavior
« Reply #15 on: August 04, 2016, 08:58:34 pm »
Yes and no.

Choke, Barrel type, barrel length, shot size, shell length, and gauge are all factors.

-HH

Offline ohartenstein23

  • Commander
  • *****
  • Posts: 1933
  • Flamethrowers fry cyberdisk circuits
    • View Profile
Re: a different shotgun behavior
« Reply #16 on: August 05, 2016, 03:27:32 pm »
I was thinking about this again - what if the spread pattern was determined by both ammunition and the shotgun?  Say, have a pelletSpread parameter defined for both, and the actual spread is the average of them, and in case it's only defined for one, then no averaging is performed.

Maybe I need to learn some C++ to try this out.

Offline Star_Treasure

  • Captain
  • ***
  • Posts: 96
    • View Profile
Re: a different shotgun behavior
« Reply #17 on: August 05, 2016, 11:46:58 pm »
If it's just the average though, you'd still see slugs being effected by the choke. There would have to be a way for the ammunition to override it completely.

Offline ohartenstein23

  • Commander
  • *****
  • Posts: 1933
  • Flamethrowers fry cyberdisk circuits
    • View Profile
Re: a different shotgun behavior
« Reply #18 on: August 05, 2016, 11:53:55 pm »
Slugs are already not effected by the same spread as the pellets, the whole pellet spread idea/calculation would only be invoked for an ammunition type that has multiple pellets in the ruleset definition.

Offline ohartenstein23

  • Commander
  • *****
  • Posts: 1933
  • Flamethrowers fry cyberdisk circuits
    • View Profile
Re: a different shotgun behavior
« Reply #19 on: August 11, 2016, 08:29:06 pm »
Looking at the code for determining shotgun-like behavior (lines 556-581 in ProjectileFlyBState.cpp on the latest nightly in particular), each additional pellet after the first has it's own unique trajectory, but with accuracy decreasing by 5.0 * (number of pellet after the first).

Actually, can someone who has worked on the code comment on this?
Code: [Select]
_projectileImpact = proj->calculateTrajectory(std::max(0.0, (_unit->getFiringAccuracy(_action.type, _action.weapon) / 100.0) - i * 5.0));In this line, the impact from each additional pellet is traced from a new trajectory based on the firing accuracy / 100.0 minus the number of the pellet * 5.0; looking at the function getFiringAccuracy, the value returned should be the same as the percentage displayed on the crosshairs, so approximately between 0 and 150 (more for ridiculously accurate weapons).  This is then divided by 100.0, leading to a value between 0.0 and ~1.50, which means taking the maximum between 0.0 and this number minus the number of the pellet * 5.0 should always be 0.0, making any pellet after the first a shot with zero accuracy.  Am I interpreting this code correctly?

Edit:
I have two ideas for modifying the shotgun behavior here:
1.  Have that 'magic number' 5.0 be exposed to the ruleset as a 'pellet spread' number, which can be defined in the weapon or ammunition part of the ruleset, or both with either one superseding the other or combine them by an average.  This would be the easier of the two methods, and is more or less just being able to tweak the current behavior more.

2.  Add a second type of shotgun behavior, that rather than getting a completely new trajectory off of each particle, calculates a modified trajectory for each additional pellet beyond the first, that is based on the first.  The implementation in my head is saving the targetVoxel from the first fired projectile (first pellet), and using applyAccuracy to get a new target for each additional pellet, using a 'pellet spread' parameter instead of firing accuracy to pick a randomized target in the area of the impact from the first projectile.
« Last Edit: August 11, 2016, 09:13:59 pm by ohartenstein23 »

Offline ohartenstein23

  • Commander
  • *****
  • Posts: 1933
  • Flamethrowers fry cyberdisk circuits
    • View Profile
Re: a different shotgun behavior
« Reply #20 on: August 12, 2016, 06:54:47 pm »
Okay, I've tried an implementation of the first idea:

In src/Mod/RuleItem.cpp, I added a function getShotgunSpread that looks for the line shotgunSpread in an ammo item
Code: [Select]
/**
 * Gets the number of projectiles this ammo shoots at once.
 * @return The number of projectiles.
 */
int RuleItem::getShotgunPellets() const
{
return _shotgunPellets;
}
In RuleItem::load(...), I added the line
Code: [Select]
_shotgunSpread = node["shotgunSpread"].as<int>(_shotgunSpread);

Then, in src/Battlescape/ProjectileFlyBState.cpp, I changed the section governing the additional shotgun pellets to
Code: [Select]
https:// special shotgun behaviour: trace extra projectile paths, and add bullet hits at their termination points.
if (shotgun)
{
_spread = _ammo->getRules()->getShotgunSpread();

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 * _spread / 100.0));
if (_projectileImpact != V_EMPTY)
{
https:// as above: skip the shot to the end of it's path
proj->skipTrajectory();
https:// insert an explosion and hit
if (_projectileImpact != V_OUTOFBOUNDS)
{
Explosion *explosion = new Explosion(proj->getPosition(1), _ammo->getRules()->getHitAnimation());
int power = _ammo->getRules()->getPowerBonus(_unit) - _ammo->getRules()->getPowerRangeReduction(proj->getDistance());
_parent->getMap()->getExplosions()->push_back(explosion);
_parent->getSave()->getTileEngine()->hit(proj->getPosition(1), power, _ammo->getRules()->getDamageType(), 0, _action.weapon);
}
}
++i;
delete proj;
}
}

The result is that setting shotgunSpread: 100 in the ruleset for an ammo type returns the current behavior (I made this the default value for backwards compatibility on mods), shotgunSpread: 0 makes the spread of pellets equal to the accuracy of the weapon, removing the decreasing accuracy per pellet beyond the first.  I've attached .zip files containing the changed files for OXCE and OXCE+, to be able to use it you'll have to compile either Yankes' or Meridian's version of the source code after replacing the files included here (sorry, I don't know how to use GitHub well enough to post any changes there).  I can create a nightly version if someone wants that too.

Offline ohartenstein23

  • Commander
  • *****
  • Posts: 1933
  • Flamethrowers fry cyberdisk circuits
    • View Profile
Re: a different shotgun behavior
« Reply #21 on: August 12, 2016, 10:06:22 pm »
I think I've got a nice working version of the second idea too now - the gist of it is that I save the position of where the 'first' pellet hits (I think of it being where your soldier ended up aiming when they pulled the trigger), then the remaining pellets spread around that with accuracy (100 - shotgunSpread)%, affected by the range/accuracy of the gun.  Thus, shotgunSpread: 0 means all pellets should hit the target at ranges up to the accurate range of the gun, and 100 means they'll spread around the first impact like taking 0% accuracy shots.  Maybe the best way to think about is that on average, shotgunSpread percent of the extra pellets will hit the same target as the first.

I'll upload the edited source files once I clean things up a bit and make it less hacky-looking.

Edit: Based on the discussion in this thread, I'm thinking of adding a shotgunChoke parameter to the weapon item in the ruleset that would be a multiplicative modifier to shotgunSpread, so that both weapon and ammo would affect the final pellet spread.  Something like choke > 1.0 decreases spread, choke < 1.0 increases spread, and choke = 0.0 is maximum spread.
« Last Edit: August 12, 2016, 10:29:57 pm by ohartenstein23 »

Offline robin

  • Commander
  • *****
  • Posts: 1224
  • ULTIMATE ROOKIE
    • View Profile
Re: a different shotgun behavior
« Reply #22 on: April 01, 2017, 03:34:32 pm »
necromancy!

I know no projectile is shown because it's impossible to draw multiple projectiles.
But I wonder: what about drawing the projectile for the first/main pellet up to half (or two thirds) the distance to the impact point?

Like:

Code: [Select]
                              x
                       x   
@=================            X    x
                            x
                      x            x
Where "@" is the attacker, "=" is the projectile drawn, "X" the main (first pellet) impact point, "x" the secondary impact points.

It could look less ugly than "nothing at all", especially when coupled with this new shotgun behavior that groups better together the pellets.
Maybe a "fragmented-looking" projectile sprite is helpful (see attachments), instead of a regular one.
Of course it could look like total shit, it's impossible to know before we see it.


After all I think it's not worth it.
« Last Edit: April 01, 2017, 04:40:29 pm by robin »

Offline RSSwizard

  • Commander
  • *****
  • Posts: 793
    • View Profile
Re: a different shotgun behavior
« Reply #23 on: April 18, 2017, 03:34:57 am »
Since this thing got necrobumped I figured I would chime in on it with some insights I had regarding a roleplaying game system ive been working on (pen+paper) and also a general overview design for a what-if computerized version (and tactical, which means it could host something like xcom).

This isnt code but it could be implemented as such.

For a multi-projectile attack, including Bursts the way my rpg system handles it is assuming that the full attack represents 1 Hurtful Maneuver against the target. Its not getting hit a bunch of times, its one big hit that hurts alot. This way players dont have to resolve rolling damage against something 3, 5, or 8+ times depending on how central this dynamic (tricked out) it is to their character.

To give an example of how it works in my rpg system currently, it uses a logarithmic system to keep multipliers easily applied as simple bumps to a single die roll:

There is only one damage roll, its either 1d20+Damage Modifier or 1d6x3 + Damage Modifier.

For Burst attacks (but not shotguns, unless they're firing more than once) you make 2 Attack Rolls. The first one gets a bonus toHit for volume of fire. If you hit then that means you hit at least once. The second attack roll confirms extra shots hitting the target, to score extra hits you've got to score extra degrees of success on that one (if the gun has heavy recoil, you get a penalty for this roll, if it has light recoil or no recoil like a gatling laser you get a bonus, but the default assumption is "some recoil" thus no modifier to hassle the players with). Any shots which miss count as "missed shots" which can potentially hit bystanders near the line of fire, as determined by the evil dungeon master.


Shotguns cause about +14 damage modifier, but they also get +4 Dots of Antipersonnel modifier. Every range increment beyond the first reduces the damage by 4 but it also reduces the antipersonnel modifier by 1 dot. For shotguns, twelve gauge in any case, the power/range reduction occurs up to 3 times (up to -12damage and -3Dots antipersonnel)

Bursts add +3 damage for every shot that hits including the first one (so get shot twice and its +6 damage, but get shot three times and its +9 damage). It also adds +1Dot Antipersonnel if you score multiple hits... but only one. Every 5 Shots that hits gets consolidated into a separate damage roll if it goes that high.

(and Miniguns already have their stats set to assume for their base damage that 5 shots were inflicted, unless its suppressive fire, which only hits for a single bullet.)


Antipersonnel doubles all armor values but only up to +5 armor points per dot. So 4 Dots of antipersonnel doubles armor up to 20 Armor points. However only a single dot would provide only +5 Armor unless their armor was lower than that.

However the behavior of an autofiring Shotgun compounds with Bursts such that getting hit with a 12 gauge combat shotgun twice is going to cause 20 damage modifier and 5 Dots antipersonnel (notice that armor is only doubled, but will yield up to +25 armor if you've got that much)

This is in contrast to Dots of Armor Piercing which pretty much just bypass 3 Armor for every dot it has (armor works like damage reduction), which is like free damage but only if the target had the armor to start with. Which can make armor piercing attacks rather weak against tough characters unless they have alot of natural armor chitin plates (since AP dots work against natural armor too).

Because of how antipersonnel works, given this is a simple boardgame, the difference is if you have okay armor but not alot of it - having a high volume of hits will still slaughter you even if your armor could stop probably 50% of the damage of a single one.

Getting hit with a volley of arrows can still hurt you pretty good even if your chainmail would normally get rid of at least half of the damage. Likewise getting shot by an unreal tournament Flak Cannon is going to splatter you even if you've got combat armor that could generally stop most of the damage its flak chunks cause.

The reason I made that judgement call, aside for simplicity to keep multiplication out of the game, is because multiple hits means its more likely its going to find weaknesses in the armor or the sum of those projectiles will dig into it and make it easier to penetrate in that one area of the armor. Blunt Force Trauma is a thing too... Tactical armor will NOT stop a shotgun blast at point blank range from crushing your ribs, its still causing damage even though the projectiles dont get through.

The only instance where this doesnt follow reality is when you're working with Forcefields which do not have weak spots, or if the reason the projectiles are causing damage has nothing to do with blunt force trauma (still even something that only splashes you like acid is going to find alot of spots to seep into the cracks of the armor, so it still makes sense for acid and chems).

And AP/Antipersonnel dots cancel each other out. So if you combine armor piercing things like flechettes or beam weapons with multi-hit damage its just going to obliterate someone, its alot of free damage.

Whats more, energy attacks like Lightning or Magic Projectiles do not bestow antipersonnel dots when they score extra hits. The force combines to increase both damage and penetrative capability, more literally is better, which provides a tactical layer to the rpg to "not get hit with alot of crap at the same time"

(given that its a logarithmic damage system it means characters have a Toughness value to overcome - a soak value, and any damage that they get above that causes them wounds. But the amount it exceeds toughness starts really amplifying the number of wounds because it represents "how bad you got hit" - so this does not dilute the power of the attack in any way just because it only got a damage bonus. It literally has almost the same effect as if multiple damage rolls had taken place, and in fact its even more potent than that because targets with a really high Toughness value, such as the Baron Of Hell from doom as an example... can be hurt by getting hit a bunch of times even if the attack normally had no capability to overcome their toughness)


Under the exponential system to be used for a computerized version...

Shotguns/multi projectile spigot would have damage listed for a single projectile. When the attack is called it counts how many times the target got hit. This multiplies the Damage caused by the projectile by a certain amount (a formula) before damage is rolled, based on how many hit.

For example if the exponential system is based on a Cube Root model then that means to multiply the damage of a shot by 2 you must multiply its firepower by 8. GURPS and Fallout use a Square Root model but Xcom uses a Cube Root model so thats why I use this example.

So you would take the total number of hits that struck the character, take the Cube Root of that number, and multiply the Damage (and Armor!) by that amount.

Some guy gets hit with 6 Pellets that do 20 damage... thats 1.82x or 36 Damage they're getting rolled at them. If they had 5 Armor it is raised to 9 against that.

(Though... ive found that by fine tuning... there should be a bonus incentive for multiple projectiles due to how much more it hurts, but thats besides the point for this exercise.)

I think you get the idea here.

Only the location that was hit by the Ideal Trajectory of the shot cone is considered for the locational armor (ie, the shooter makes the shot, the trajectory is remembered, shotgun pellets are randomly fired with the equivalent of choke/spread deviation from that trajectory - hits may ensue even if the shooter technically missed with the ideal trajectory). If the ideal trajectory missed, then it just sticks to whichever one hit first.



Displaying multiple projectiles, among other things...


The key to avoiding trying to Extend a commonly used current algorithm is to not use it at all, and instead divert to creating an Overlay graphic of some kind that follows the intended scripted rules.

For a Shotgun thats damn easy, and it could be extended to burst attacks too (if an option was included for an item to make it behave that way).

Just spray a bunch of Projectile graphic from the weapon in a random trajectory that corresponds to the weapon. They dont have to hit the exact place where the actual attacks went. You can do hit collision for each path if you want (pretty much replicating a Sight check) just to make sure nothing looks funky like projectiles moving through walls.

Emit a spray of these not all at once but over a course of time depending on the kind of attack. For a shotgun blast it emits as many projectiles over the course of 0.2 Seconds and a burst would time the projectiles over the course of 1.2 Seconds (it would also force the character to play the weapon-extended-in-firing-position graphic for at least that long). These could be global variables?

So what you'd see for a shotgun is a volley of projectiles released with only a single sound effect and impact sound played, they'd all come out really quick but they wouldnt be in one solid horizontal line either. Thats important and the reason they'd be timed, even though in real life it would be a swarm. If there were 5 shotgunpellets then they'd emit at a rate of one every 0.04 seconds for example.

And with Bursts this also opens the door for giving the weapon/item a special Burst Sound Effect for firing a burst of attacks. To correspond to a minigun chewing away at the scenery over the course of 1.2 Seconds as a dazzling hail of projectiles gets emitted.

In either case you would have shot-following turned OFF for these options so it would only display this action relevant to wherever the camera was (the current shot following of the shotgun attacks is so jumpy its potentially spasm inducing anyway). Thats where the player would notice a discrepency between the projectiles being emitted and the fact all the projectile hits were tallied instantly when the attack was made.

But oh well, this is a graphical presentation overlay.



Making Big Units better... and more bigger...

HWPs, 2X2, 3X3 and other large units for example are a pain to design because they are built around a dirty hack of relying on them being composed of 1x1 tiles, this was always the case even back in vanilla (its 1994, you're making xcom, you have a limited amount of time to figure this out in programming terms, and a limited amount of processing resources. Oh wait, we'll just treat it like its in 4 different tiles).

However thinking outside the box, while they take up a certain amount of real estate, they are NOT 1x1 size objects at all and should not be handled as such or an extension of them.

Instead of drawing them using that routine, just figure out where their "Center" is and OVERLAY a graphic, indexed to the proper rotation (and uhh... shaded properly based on darkness).

The object itself is invisible, it does not have a tile graphic. This is something else being applied to it.

That what-if game design of mine wouldnt even consider large objects to be bound to Tile Sizes, it would have a collision box attached to it based on tile-decimal dimensions (how about a Delivery Truck thats 3x6 Tiles in size?) and then as it moved it would take up Tiles based on its current position on its movement path.

Much like Font Rendering does to check whether a pixel should be shaded based on how much of the vector wireframe is present in enough quantity within a given pixel. The actual "Tiles" which are "Affected by the position" of this thing are interpolated.

Though mine would have some extra rules for clipping objects, whenever one of those interpolated movements involved an occupied tile it would even be able to throw a "Collision? but not blocked" event, making a car-sideswipe crunch and generating sparks (and possibly a damage roll of some kind to both objects) but not stopping movement.

I would even keep the motion realistic based on how many rotations the object had, if it only had 16 or 24 or 32 rotations - it could only move in those direction arcs but whenever it intercepted a compatible arc to reach the target location - it would rotate 1 increment over to match that and move.

This prevents unwanted zig-zagging motion and ALSO prevent using "the nearest equivalent rotation" which could make the motion look kinda not-straight. Having a car moving and make a slight turn midway to reach a given location looks realistic enough, it looks like the driver made a little course correction inbetween.


In terms of Xcom you can even do other creative things with this like give it multiple frames for varying levels of damage (in place of walking animations, if it does not have those). And additional rotations such as 16, 24, or 32 directions, but these are just examples of adventurous extensions.

It would be nice to have a tank that looks like its on its last legs (25% or less Health remaining) after it got shot with a plasma weapon, holes in the armor, pieces dangling off.

This is a big post but I didnt want to double post.

« Last Edit: April 18, 2017, 03:48:08 am by RSSwizard »