STARK: Prevent string pulling from making April walk on disabled faces

Fixes #1494.
This commit is contained in:
Bastien Bouclet 2018-11-21 14:22:22 +01:00
parent 191113819b
commit c5185ee753
4 changed files with 24 additions and 4 deletions

View File

@ -64,7 +64,7 @@ void Floor::computePointHeightInFace(Math::Vector3d &point, uint32 faceIndex) co
int32 Floor::findFaceHitByRay(const Math::Ray &ray, Math::Vector3d &intersection) const {
for (uint32 i = 0; i < _faces.size(); i++) {
// TODO: Check the ray's intersection with an AABB first if this ends up being slow
if (_faces[i]->intersectRay(ray, intersection)) {
if (_faces[i]->isEnabled() && _faces[i]->intersectRay(ray, intersection)) {
return i;
}
}
@ -76,7 +76,7 @@ int32 Floor::findFaceClosestToRay(const Math::Ray &ray, Math::Vector3d &center)
float minDistance = FLT_MAX;
int32 minFace = -1;
for (uint32 i = 0; i < _faces.size(); i++) {
if (_faces[i]->hasVertices()) {
if (_faces[i]->isEnabled() && _faces[i]->hasVertices()) {
float distance = _faces[i]->distanceToRay(ray);
if (distance < minDistance) {
minFace = i;
@ -103,7 +103,7 @@ FloorFace *Floor::getFace(uint32 index) const {
bool Floor::isSegmentInside(const Math::Line3d &segment) const {
// The segment is inside the floor if at least one of its extremities is,
// and it does not cross any floor border
// and it does not cross any floor border / disabled floor faces
int32 beginFace = findFaceContainingPoint(segment.begin());
if (beginFace < 0) {
@ -111,9 +111,14 @@ bool Floor::isSegmentInside(const Math::Line3d &segment) const {
return false;
}
if (!_faces[beginFace]->isEnabled()) {
// The segment begin point is not enabled
return false;
}
for (uint i = 0; i < _edges.size(); i++) {
const FloorEdge &edge = _edges[i];
if (edge.isFloorBorder() && edge.intersectsSegment(this, segment)) {
if ((edge.isFloorBorder() || !edge.isEnabled()) && edge.intersectsSegment(this, segment)) {
return false;
}
}

View File

@ -150,6 +150,8 @@ public:
/**
* Check if a ray is intersecting the floor
*
* Faces where walking is disabled are ignored.
*
* @param ray The ray
* @param intersection The intersection between the ray and the floor. Only valid when the return value is positive.
* @return -1 if no face contains the point, the hit face index otherwise
@ -159,6 +161,8 @@ public:
/**
* Find the floor face center closest to the ray
*
* Faces where walking is disabled are ignored.
*
* @param ray The ray
* @param center The closest face center to the ray. Only valid when the return value is positive.
* @return -1 if no face was found, the face index with its center closest to the ray otherwise

View File

@ -178,6 +178,16 @@ void FloorFace::enable(bool e) {
}
}
bool FloorFace::isEnabled() const {
for (uint i = 0; i < _edges.size(); i++) {
if (_edges[i]->isEnabled()) {
return true;
}
}
return false;
}
void FloorFace::readData(Formats::XRCReadStream *stream) {
for (uint i = 0; i < ARRAYSIZE(_indices); i++) {
_indices[i] = stream->readSint16LE();

View File

@ -102,6 +102,7 @@ public:
/** Allow or disallow characters to walk on this face */
void enable(bool enable);
bool isEnabled() const;
protected:
void readData(Formats::XRCReadStream *stream) override;