mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-01-24 17:26:41 +00:00
Cleanup underwater checks, fix rectangular water bubbles
Long/thin rectangular nodes were not handled correctly, because it would only check the nearest waterbubble node for overlap, not all on the map. + Lua func: isUnderWater(x, y, radius)
This commit is contained in:
parent
5e75bc486c
commit
aaed341569
9 changed files with 71 additions and 50 deletions
|
@ -277,13 +277,14 @@ bool Entity::checkSplash(const Vector &o)
|
|||
if (!o.isZero())
|
||||
check = o;
|
||||
bool changed = false;
|
||||
if (wasUnderWater && !isUnderWater(o))
|
||||
bool uw = isUnderWater(o);
|
||||
if (wasUnderWater && !uw)
|
||||
{
|
||||
sound("splash-outof");
|
||||
changed = true;
|
||||
wasUnderWater = false;
|
||||
}
|
||||
else if (!wasUnderWater && isUnderWater(o))
|
||||
else if (!wasUnderWater && uw)
|
||||
{
|
||||
sound("splash-into");
|
||||
changed = true;
|
||||
|
@ -1774,34 +1775,21 @@ int Entity::getRandomTargetPoint()
|
|||
return rand()%targetPoints.size();
|
||||
}
|
||||
|
||||
bool Entity::isUnderWater(const Vector &override)
|
||||
bool Entity::isUnderWater()
|
||||
{
|
||||
Vector check = position;
|
||||
if (!override.isZero())
|
||||
check = override;
|
||||
|
||||
if (game->useWaterLevel && game->waterLevel.x > 0 && check.y-collideRadius > game->waterLevel.x)
|
||||
return true;
|
||||
|
||||
|
||||
Path *p = game->getNearestPath(position, PATH_WATERBUBBLE);
|
||||
if (p && p->active && p->isCoordinateInside(position, collideRadius))
|
||||
{
|
||||
waterBubble = p;
|
||||
return true;
|
||||
}
|
||||
return _isUnderWaterPos(position);
|
||||
}
|
||||
|
||||
if (!game->useWaterLevel || game->waterLevel.x == 0) return true;
|
||||
else
|
||||
{
|
||||
if (check.y-collideRadius > game->waterLevel.x)
|
||||
{
|
||||
waterBubble = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
bool Entity::isUnderWater(const Vector& overridePos)
|
||||
{
|
||||
return _isUnderWaterPos(overridePos.isZero() ? position : overridePos);
|
||||
}
|
||||
|
||||
return false;
|
||||
bool Entity::_isUnderWaterPos(const Vector& pos)
|
||||
{
|
||||
UnderWaterResult res = game->isUnderWater(pos, collideRadius);
|
||||
waterBubble = res.waterbubble;
|
||||
return res.uw;
|
||||
}
|
||||
|
||||
void Entity::push(const Vector &vec, float time, float maxSpeed, float dmg)
|
||||
|
|
|
@ -103,7 +103,9 @@ public:
|
|||
virtual int messageVariadic(lua_State *L, int nparams) { return 0; }
|
||||
virtual int activateVariadic(lua_State *L, int nparams) { return 0; }
|
||||
|
||||
bool isUnderWater(const Vector &o=Vector());
|
||||
bool isUnderWater();
|
||||
bool isUnderWater(const Vector& overridePos);
|
||||
bool _isUnderWaterPos(const Vector& pos);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1262,6 +1262,30 @@ Path *Game::getPathByName(std::string name)
|
|||
return 0;
|
||||
}
|
||||
|
||||
Path *Game::getWaterbubbleAt(const Vector& pos, float rad) const
|
||||
{
|
||||
for (Path *p = getFirstPathOfType(PATH_WATERBUBBLE); p; p = p->nextOfType)
|
||||
if(p->active && p->isCoordinateInside(pos, rad))
|
||||
return p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UnderWaterResult Game::isUnderWater(const Vector& pos, float rad) const
|
||||
{
|
||||
UnderWaterResult ret { false, NULL };
|
||||
if (!game->useWaterLevel || game->waterLevel.x == 0
|
||||
|| (useWaterLevel && waterLevel.x > 0 && pos.y-rad > waterLevel.x))
|
||||
{
|
||||
ret.uw = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Path *p = game->getWaterbubbleAt(pos, rad);
|
||||
ret.waterbubble = p;
|
||||
ret.uw = !!p;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Game::toggleOverrideZoom(bool on)
|
||||
{
|
||||
if (avatar)
|
||||
|
@ -2536,14 +2560,7 @@ int game_collideParticle(Vector pos)
|
|||
bool inWaterBubble = false;
|
||||
if (!aboveWaterLine)
|
||||
{
|
||||
Path *p = game->getNearestPath(pos, PATH_WATERBUBBLE);
|
||||
if (p && p->active)
|
||||
{
|
||||
if (p->isCoordinateInside(pos))
|
||||
{
|
||||
inWaterBubble = true;
|
||||
}
|
||||
}
|
||||
inWaterBubble = !!game->getWaterbubbleAt(pos);
|
||||
}
|
||||
if (!inWaterBubble && aboveWaterLine)
|
||||
{
|
||||
|
|
|
@ -283,6 +283,9 @@ public:
|
|||
Path *getNearestPath(const Vector &pos, PathType pathType=PATH_NONE);
|
||||
Path *getNearestPath(Path *p, std::string name);
|
||||
|
||||
Path *getWaterbubbleAt(const Vector& pos, float rad = 0) const;
|
||||
UnderWaterResult isUnderWater(const Vector& pos, float rad = 0) const;
|
||||
|
||||
SceneEditor sceneEditor;
|
||||
bool isSceneEditorActive() {return sceneEditor.isOn();}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include "Vector.h"
|
||||
#include "GameEnums.h"
|
||||
|
||||
class Path;
|
||||
|
||||
struct ElementEffect
|
||||
{
|
||||
public:
|
||||
|
@ -191,5 +193,11 @@ private:
|
|||
typedef std::vector<IngredientData*> IngredientDatas;
|
||||
|
||||
|
||||
struct UnderWaterResult
|
||||
{
|
||||
bool uw;
|
||||
Path *waterbubble;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -105,20 +105,13 @@ void Path::setActive(bool v)
|
|||
active = v;
|
||||
}
|
||||
|
||||
bool Path::isCoordinateInside(const Vector &pos, int radius)
|
||||
bool Path::isCoordinateInside(const Vector &pos, float radius) const
|
||||
{
|
||||
if (nodes.empty()) return false;
|
||||
if (pathShape == PATHSHAPE_CIRCLE)
|
||||
{
|
||||
Vector diff = pos - nodes[0].position;
|
||||
return diff.isLength2DIn(this->rect.getWidth()*0.5f - radius);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector rel = pos - nodes[0].position;
|
||||
return rect.isCoordinateInside(rel);
|
||||
}
|
||||
return false;
|
||||
return pathShape == PATHSHAPE_CIRCLE
|
||||
? diff.isLength2DIn(rect.getWidth()*0.5f - radius)
|
||||
: rect.isCoordinateInside(diff, radius);
|
||||
}
|
||||
|
||||
Vector Path::getEnterNormal()
|
||||
|
|
|
@ -96,7 +96,7 @@ public:
|
|||
void setEmitter(const std::string& name);
|
||||
|
||||
PathNode *getPathNode(size_t idx);
|
||||
bool isCoordinateInside(const Vector &pos, int rad=0);
|
||||
bool isCoordinateInside(const Vector &pos, float rad=0) const;
|
||||
|
||||
void reverseNodes();
|
||||
|
||||
|
|
|
@ -7930,6 +7930,15 @@ luaFunc(findWall)
|
|||
luaReturnNum(wall);
|
||||
}
|
||||
|
||||
luaFunc(isUnderWater)
|
||||
{
|
||||
float x = lua_tonumber(L, 1);
|
||||
float y = lua_tonumber(L, 2);
|
||||
float rad = lua_tonumber(L, 3);
|
||||
luaReturnBool(game->isUnderWater(Vector(x, y), rad).uw);
|
||||
}
|
||||
|
||||
|
||||
luaFunc(setCutscene)
|
||||
{
|
||||
dsq->setCutscene(getBool(L, 1), getBool(L, 2));
|
||||
|
@ -10796,6 +10805,7 @@ static const struct {
|
|||
luaRegister(entity_alpha),
|
||||
|
||||
luaRegister(findWall),
|
||||
luaRegister(isUnderWater),
|
||||
|
||||
|
||||
luaRegister(overrideZoom),
|
||||
|
|
|
@ -59,7 +59,7 @@ public:
|
|||
*x = x1 + ((*w) / 2);
|
||||
*y = y1 + ((*h) / 2);
|
||||
}
|
||||
bool isCoordinateInside(const Vector &vec, int radius=0) const
|
||||
bool isCoordinateInside(const Vector &vec, float radius=0) const
|
||||
{
|
||||
return ((vec.x >= x1-radius && vec.x <= x2+radius) && (vec.y >= y1-radius && vec.y <= y2+radius));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue