Skip to content

Commit 2b6c8ae

Browse files
YankesSupSuper
authored andcommitted
Final fix to 25y bug with throw
1 parent 02bac59 commit 2b6c8ae

4 files changed

Lines changed: 36 additions & 21 deletions

File tree

‎src/Battlescape/Projectile.cpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,10 @@ int Projectile::calculateThrow(double accuracy)
305305
applyAccuracy(originVoxel, &targetVoxel, accuracy, true, false); //arcing shot deviation
306306
deltas = Position(0,0,0);
307307
}
308-
_trajectory.push_back(originVoxel);
308+
309309
test = _save->getTileEngine()->calculateParabola(originVoxel, targetVoxel, true, &_trajectory, _action.actor, curvature, deltas);
310310
if (forced) return O_OBJECT; //fake hit
311-
Position endPoint = _trajectory.back() / Position (16, 16, 24);
311+
Position endPoint = _trajectory.at(_trajectory.size() + ItemDropVoxelOffset - 1) / Position (16, 16, 24);
312312
Tile *endTile = _save->getTile(endPoint);
313313
// check if the item would land on a tile with a blocking object
314314
if (_action.type == BA_THROW

‎src/Battlescape/Projectile.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ class Mod;
3636
*/
3737
class Projectile
3838
{
39+
public:
40+
/// Offset of voxel path where item should be drop
41+
static const int ItemDropVoxelOffset = -2;
42+
3943
private:
4044
Mod *_mod;
4145
SavedBattleGame *_save;

‎src/Battlescape/ProjectileFlyBState.cpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ void ProjectileFlyBState::think()
507507
if (_action.type == BA_THROW)
508508
{
509509
_parent->getMap()->resetCameraSmoothing();
510-
Position pos = _parent->getMap()->getProjectile()->getPosition(-1);
510+
Position pos = _parent->getMap()->getProjectile()->getPosition(Projectile::ItemDropVoxelOffset);
511511
pos.x /= 16;
512512
pos.y /= 16;
513513
pos.z /= 24;
@@ -525,7 +525,7 @@ void ProjectileFlyBState::think()
525525
if (Options::battleInstantGrenade && item->getRules()->getBattleType() == BT_GRENADE && item->getFuseTimer() == 0)
526526
{
527527
// it's a hot grenade to explode immediately
528-
_parent->statePushFront(new ExplosionBState(_parent, _parent->getMap()->getProjectile()->getPosition(-1), item, _action.actor));
528+
_parent->statePushFront(new ExplosionBState(_parent, _parent->getMap()->getProjectile()->getPosition(Projectile::ItemDropVoxelOffset), item, _action.actor));
529529
}
530530
else
531531
{

‎src/Battlescape/TileEngine.cpp‎

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "AIModule.h"
2525
#include "Map.h"
2626
#include "Camera.h"
27+
#include "Projectile.h"
2728
#include "../Savegame/SavedGame.h"
2829
#include "../Savegame/SavedBattleGame.h"
2930
#include "ExplosionBState.h"
@@ -2411,35 +2412,39 @@ int TileEngine::calculateParabola(Position origin, Position target, bool storeTr
24112412
int z = origin.z;
24122413
int i = 8;
24132414
int result = V_EMPTY;
2414-
std::vector<Position> _trajectory;
24152415
Position lastPosition = Position(x,y,z);
24162416
Position nextPosition = lastPosition;
2417+
2418+
if (storeTrajectory && trajectory)
2419+
{
2420+
//initla value for small hack to glue `calculateLine` into one continuous arc
2421+
trajectory->push_back(lastPosition);
2422+
}
24172423
while (z > 0)
24182424
{
24192425
x = (int)((double)origin.x + (double)i * cos(te) * sin(fi));
24202426
y = (int)((double)origin.y + (double)i * sin(te) * sin(fi));
24212427
z = (int)((double)origin.z + (double)i * cos(fi) - zK * ((double)i - ro / 2.0) * ((double)i - ro / 2.0) + zA);
24222428
//passes through this point?
24232429
nextPosition = Position(x,y,z);
2424-
_trajectory.clear();
2425-
result = calculateLine(lastPosition, nextPosition, false, 0, excludeUnit);
2426-
if (result != V_EMPTY)
2430+
2431+
if (storeTrajectory && trajectory)
24272432
{
2428-
result = calculateLine(lastPosition, nextPosition, true, &_trajectory, excludeUnit);
2429-
nextPosition = _trajectory.back(); //pick the INSIDE position of impact
2430-
break;
2433+
//remove end point of previus trajectory part, becasue next one will add this point again
2434+
trajectory->pop_back();
24312435
}
2432-
if (storeTrajectory && trajectory)
2436+
result = calculateLine(lastPosition, nextPosition, storeTrajectory, storeTrajectory ? trajectory : 0, excludeUnit);
2437+
if (result != V_EMPTY)
24332438
{
2434-
trajectory->push_back(nextPosition);
2439+
if (!storeTrajectory && trajectory)
2440+
{
2441+
result = calculateLine(lastPosition, nextPosition, false, trajectory, excludeUnit); //pick the INSIDE position of impact
2442+
}
2443+
break;
24352444
}
24362445
lastPosition = nextPosition;
24372446
++i;
24382447
}
2439-
if (trajectory != 0)
2440-
{ // store the position of impact
2441-
trajectory->push_back(nextPosition);
2442-
}
24432448
return result;
24442449
}
24452450

@@ -2930,13 +2935,19 @@ bool TileEngine::validateThrow(BattleAction &action, Position originVoxel, Posit
29302935
return false;
29312936
}
29322937

2938+
std::vector<Position> trajectory;
2939+
// thows should be around 10 tiles far, make one allocation that fit 99% cases with some margin
2940+
trajectory.resize(16*20);
29332941
// we try 8 different curvatures to try and reach our goal.
29342942
int test = V_OUTOFBOUNDS;
29352943
while (!foundCurve && curvature < 5.0)
29362944
{
2937-
std::vector<Position> trajectory;
2938-
test = calculateParabola(originVoxel, targetVoxel, false, &trajectory, action.actor, curvature, Position(0,0,0));
2939-
Position tilePos = ((trajectory.at(0) + Position(0,0,1)) / Position(16, 16, 24));
2945+
trajectory.clear();
2946+
test = calculateParabola(originVoxel, targetVoxel, true, &trajectory, action.actor, curvature, Position(0,0,0));
2947+
//position that item hit
2948+
Position hitPos = (trajectory.back() + Position(0,0,1)) / Position(16, 16, 24);
2949+
//position where item will land
2950+
Position tilePos = ((trajectory.at(trajectory.size() + Projectile::ItemDropVoxelOffset - 1)) / Position(16, 16, 24));
29402951
if (forced || (test != V_OUTOFBOUNDS && tilePos == targetPos))
29412952
{
29422953
if (voxelType)
@@ -2950,7 +2961,7 @@ bool TileEngine::validateThrow(BattleAction &action, Position originVoxel, Posit
29502961
curvature += 0.5;
29512962
if (test != V_OUTOFBOUNDS && action.actor->getFaction() == FACTION_PLAYER) //obstacle indicator is only for player
29522963
{
2953-
Tile* hitTile = _save->getTile(tilePos);
2964+
Tile* hitTile = _save->getTile(hitPos);
29542965
if (hitTile)
29552966
{
29562967
hitTile->setObstacle(test);

0 commit comments

Comments
 (0)