MCPcopy Create free account
hub / github.com/OpenXcom/OpenXcom / applyAccuracy

Method applyAccuracy

src/Battlescape/Projectile.cpp:245–326  ·  view source on GitHub ↗

* Calculates the new target in voxel space, based on the given accuracy modifier. * @param origin Startposition of the trajectory in voxels. * @param target Endpoint of the trajectory in voxels. * @param accuracy Accuracy modifier. * @param keepRange Whether range affects accuracy. * @param targetTile Tile of target. Default = 0. * @param extendLine should this line get extended to maximum d

Source from the content-addressed store, hash-verified

243 * @param extendLine should this line get extended to maximum distance?
244 */
245void Projectile::applyAccuracy(const Position& origin, Position *target, double accuracy, bool keepRange, Tile *targetTile, bool extendLine)
246{
247 int xdiff = origin.x - target->x;
248 int ydiff = origin.y - target->y;
249 double realDistance = sqrt((double)(xdiff*xdiff)+(double)(ydiff*ydiff));
250 // maxRange is the maximum range a projectile shall ever travel in voxel space
251 double maxRange = keepRange?realDistance:16*1000; // 1000 tiles
252 maxRange = _action.type == BA_HIT?46:maxRange; // up to 2 tiles diagonally (as in the case of reaper v reaper)
253 RuleItem *weapon = _action.weapon->getRules();
254
255 if (_action.type != BA_THROW && _action.type != BA_HIT)
256 {
257 double modifier = 0.0;
258 int upperLimit = weapon->getAimRange();
259 int lowerLimit = weapon->getMinRange();
260 if (Options::battleUFOExtenderAccuracy)
261 {
262 if (_action.type == BA_AUTOSHOT)
263 {
264 upperLimit = weapon->getAutoRange();
265 }
266 else if (_action.type == BA_SNAPSHOT)
267 {
268 upperLimit = weapon->getSnapRange();
269 }
270 }
271 if (realDistance / 16 < lowerLimit)
272 {
273 modifier = (weapon->getDropoff() * (lowerLimit - realDistance / 16)) / 100;
274 }
275 else if (upperLimit < realDistance / 16)
276 {
277 modifier = (weapon->getDropoff() * (realDistance / 16 - upperLimit)) / 100;
278 }
279 accuracy = std::max(0.0, accuracy - modifier);
280 }
281
282 int xDist = abs(origin.x - target->x);
283 int yDist = abs(origin.y - target->y);
284 int zDist = abs(origin.z - target->z);
285 int xyShift, zShift;
286
287 if (xDist / 2 <= yDist) //yes, we need to add some x/y non-uniformity
288 xyShift = xDist / 4 + yDist; //and don't ask why, please. it's The Commandment
289 else
290 xyShift = (xDist + yDist) / 2; //that's uniform part of spreading
291
292 if (xyShift <= zDist) //slight z deviation
293 zShift = xyShift / 2 + zDist;
294 else
295 zShift = xyShift + zDist / 2;
296
297 int deviation = RNG::generate(0, 100) - (accuracy * 100);
298
299 if (deviation >= 0)
300 deviation += 50; // add extra spread to "miss" cloud
301 else
302 deviation += 10; //accuracy of 109 or greater will become 1 (tightest spread)

Callers

nothing calls this directly

Calls 7

generateFunction · 0.85
getAimRangeMethod · 0.80
getMinRangeMethod · 0.80
getAutoRangeMethod · 0.80
getSnapRangeMethod · 0.80
getDropoffMethod · 0.80
getRulesMethod · 0.45

Tested by

no test coverage detected