1
0
Fork 0
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:
fgenesis 2023-06-23 15:05:05 +02:00
parent 5e75bc486c
commit aaed341569
9 changed files with 71 additions and 50 deletions

View file

@ -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)

View file

@ -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);

View file

@ -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)
{

View file

@ -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();}

View file

@ -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

View file

@ -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()

View file

@ -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();

View file

@ -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),

View file

@ -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));
}