1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-11-15 05:59:16 +00:00

Corrected shot bouncing logic

There was a problem calculating how shots with the BOUNCE_REAL attribute
would bounce off walls. The calculation was triggered when the shot
was already obstructed, which possibly got the shot stuck,
and later killed by a wrong obstruction check, which almost always killed
fast shots in narrow tunnels.

Also added some const.
This commit is contained in:
fgenesis 2012-01-10 22:27:52 +01:00
parent 1ab32b585f
commit 9dbdac547e
3 changed files with 35 additions and 31 deletions

View file

@ -640,7 +640,7 @@ public:
int getGridRaw(unsigned int x, unsigned int y) const;
const signed char *getGridColumn(int tileX);
void setGrid(const TileVector &tile, int v);
bool isObstructed(const TileVector &tile, int t = -1);
bool isObstructed(const TileVector &tile, int t = -1) const;
void clearPointers();
@ -1246,7 +1246,7 @@ void Game::setGrid(const TileVector &tile, int v)
}
inline
bool Game::isObstructed(const TileVector &tile, int t)
bool Game::isObstructed(const TileVector &tile, int t) const
{
if (t == -1)
return (getGrid(tile) != 0);

View file

@ -586,7 +586,7 @@ void Shot::targetDied(Entity *target)
*/
}
bool Shot::isHitEnts()
bool Shot::isHitEnts() const
{
if (!shotData || shotData->hitEnts)
{
@ -684,14 +684,14 @@ void Shot::noSegs()
}
}
int Shot::getCollideRadius()
int Shot::getCollideRadius() const
{
if (shotData)
return shotData->collideRadius;
return 0;
}
float Shot::getDamage()
float Shot::getDamage() const
{
if (shotData)
{
@ -700,7 +700,7 @@ float Shot::getDamage()
return 0;
}
DamageType Shot::getDamageType()
DamageType Shot::getDamageType() const
{
if (shotData)
{
@ -733,11 +733,11 @@ void Shot::setTargetPoint(int pt)
targetPt = pt;
}
bool Shot::isObstructed()
bool Shot::isObstructed(float dt) const
{
if (shotData->wallHitRadius == 0)
{
TileVector t(position);
TileVector t(position + velocity * dt);
if (dsq->game->isObstructed(t)
|| dsq->game->isObstructed(TileVector(t.x+1, t.y))
|| dsq->game->isObstructed(TileVector(t.x-1, t.y))
@ -858,33 +858,37 @@ void Shot::onUpdate(float dt)
diff.z = 0;
if (shotData->hitWalls)
{
if (isObstructed())
if (isObstructed(dt))
{
switch(shotData->bounceType)
{
case BOUNCE_REAL:
{
if (!shotData->bounceSfx.empty())
// Should have been checked in last onUpdate()
// If it is stuck now, it must have been fired from a bad position,
// the obstruction map changed, or it was a bouncing beast form shot,
// fired from avatar head - which may be inside a wall.
// In any of these cases, there is nowhere to bounce, so we let the shot die. -- FG
if (!isObstructed(0))
{
dsq->playPositionalSfx(shotData->bounceSfx, position);
}
float len = velocity.getLength2D();
Vector I = velocity/len;
Vector N = dsq->game->getWallNormal(position);
if (!shotData->bounceSfx.empty())
{
dsq->playPositionalSfx(shotData->bounceSfx, position);
}
float len = velocity.getLength2D();
Vector I = velocity/len;
Vector N = dsq->game->getWallNormal(position);
if (!N.isZero())
{
//2*(-I dot N)*N + I
velocity = 2*(-I.dot(N))*N + I;
velocity *= len;
}
Vector test = position+velocity;
if (dsq->game->isObstructed(test))
{
suicide();
if (!N.isZero())
{
//2*(-I dot N)*N + I
velocity = 2*(-I.dot(N))*N + I;
velocity *= len;
}
break;
}
// fall through
}
break;
default:
{
suicide();

View file

@ -109,13 +109,13 @@ public:
void setAimVector(const Vector &aim);
void setTarget(Entity *target);
void setTargetPoint(int pt);
float getDamage();
int getCollideRadius();
DamageType getDamageType();
float getDamage() const;
int getCollideRadius() const;
DamageType getDamageType() const;
ShotData *shotData;
void updatePosition();
bool isHitEnts();
bool isObstructed();
bool isHitEnts() const;
bool isObstructed(float dt) const;
float extraDamage;
protected: