1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-02-03 18:14:01 +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()) if (!o.isZero())
check = o; check = o;
bool changed = false; bool changed = false;
if (wasUnderWater && !isUnderWater(o)) bool uw = isUnderWater(o);
if (wasUnderWater && !uw)
{ {
sound("splash-outof"); sound("splash-outof");
changed = true; changed = true;
wasUnderWater = false; wasUnderWater = false;
} }
else if (!wasUnderWater && isUnderWater(o)) else if (!wasUnderWater && uw)
{ {
sound("splash-into"); sound("splash-into");
changed = true; changed = true;
@ -1774,34 +1775,21 @@ int Entity::getRandomTargetPoint()
return rand()%targetPoints.size(); return rand()%targetPoints.size();
} }
bool Entity::isUnderWater(const Vector &override) bool Entity::isUnderWater()
{ {
Vector check = position; return _isUnderWaterPos(position);
if (!override.isZero()) }
check = override;
if (game->useWaterLevel && game->waterLevel.x > 0 && check.y-collideRadius > game->waterLevel.x) bool Entity::isUnderWater(const Vector& overridePos)
return true; {
return _isUnderWaterPos(overridePos.isZero() ? position : overridePos);
}
bool Entity::_isUnderWaterPos(const Vector& pos)
Path *p = game->getNearestPath(position, PATH_WATERBUBBLE); {
if (p && p->active && p->isCoordinateInside(position, collideRadius)) UnderWaterResult res = game->isUnderWater(pos, collideRadius);
{ waterBubble = res.waterbubble;
waterBubble = p; return res.uw;
return true;
}
if (!game->useWaterLevel || game->waterLevel.x == 0) return true;
else
{
if (check.y-collideRadius > game->waterLevel.x)
{
waterBubble = 0;
return true;
}
}
return false;
} }
void Entity::push(const Vector &vec, float time, float maxSpeed, float dmg) 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 messageVariadic(lua_State *L, int nparams) { return 0; }
virtual int activateVariadic(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; 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) void Game::toggleOverrideZoom(bool on)
{ {
if (avatar) if (avatar)
@ -2536,14 +2560,7 @@ int game_collideParticle(Vector pos)
bool inWaterBubble = false; bool inWaterBubble = false;
if (!aboveWaterLine) if (!aboveWaterLine)
{ {
Path *p = game->getNearestPath(pos, PATH_WATERBUBBLE); inWaterBubble = !!game->getWaterbubbleAt(pos);
if (p && p->active)
{
if (p->isCoordinateInside(pos))
{
inWaterBubble = true;
}
}
} }
if (!inWaterBubble && aboveWaterLine) if (!inWaterBubble && aboveWaterLine)
{ {

View file

@ -283,6 +283,9 @@ public:
Path *getNearestPath(const Vector &pos, PathType pathType=PATH_NONE); Path *getNearestPath(const Vector &pos, PathType pathType=PATH_NONE);
Path *getNearestPath(Path *p, std::string name); 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; SceneEditor sceneEditor;
bool isSceneEditorActive() {return sceneEditor.isOn();} bool isSceneEditorActive() {return sceneEditor.isOn();}

View file

@ -6,6 +6,8 @@
#include "Vector.h" #include "Vector.h"
#include "GameEnums.h" #include "GameEnums.h"
class Path;
struct ElementEffect struct ElementEffect
{ {
public: public:
@ -191,5 +193,11 @@ private:
typedef std::vector<IngredientData*> IngredientDatas; typedef std::vector<IngredientData*> IngredientDatas;
struct UnderWaterResult
{
bool uw;
Path *waterbubble;
};
#endif #endif

View file

@ -105,20 +105,13 @@ void Path::setActive(bool v)
active = 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 (nodes.empty()) return false;
if (pathShape == PATHSHAPE_CIRCLE) Vector diff = pos - nodes[0].position;
{ return pathShape == PATHSHAPE_CIRCLE
Vector diff = pos - nodes[0].position; ? diff.isLength2DIn(rect.getWidth()*0.5f - radius)
return diff.isLength2DIn(this->rect.getWidth()*0.5f - radius); : rect.isCoordinateInside(diff, radius);
}
else
{
Vector rel = pos - nodes[0].position;
return rect.isCoordinateInside(rel);
}
return false;
} }
Vector Path::getEnterNormal() Vector Path::getEnterNormal()

View file

@ -96,7 +96,7 @@ public:
void setEmitter(const std::string& name); void setEmitter(const std::string& name);
PathNode *getPathNode(size_t idx); PathNode *getPathNode(size_t idx);
bool isCoordinateInside(const Vector &pos, int rad=0); bool isCoordinateInside(const Vector &pos, float rad=0) const;
void reverseNodes(); void reverseNodes();

View file

@ -7930,6 +7930,15 @@ luaFunc(findWall)
luaReturnNum(wall); 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) luaFunc(setCutscene)
{ {
dsq->setCutscene(getBool(L, 1), getBool(L, 2)); dsq->setCutscene(getBool(L, 1), getBool(L, 2));
@ -10796,6 +10805,7 @@ static const struct {
luaRegister(entity_alpha), luaRegister(entity_alpha),
luaRegister(findWall), luaRegister(findWall),
luaRegister(isUnderWater),
luaRegister(overrideZoom), luaRegister(overrideZoom),

View file

@ -59,7 +59,7 @@ public:
*x = x1 + ((*w) / 2); *x = x1 + ((*w) / 2);
*y = y1 + ((*h) / 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)); return ((vec.x >= x1-radius && vec.x <= x2+radius) && (vec.y >= y1-radius && vec.y <= y2+radius));
} }