mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-21 09:21:08 +00:00
699c8225c6
and started to mark the angles - to be able to refacto them easier later on
566 lines
23 KiB
C++
566 lines
23 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "common/memstream.h"
|
|
#include "twine/actor.h"
|
|
#include "twine/animations.h"
|
|
#include "twine/collision.h"
|
|
#include "common/debug.h"
|
|
#include "common/util.h"
|
|
#include "twine/extra.h"
|
|
#include "twine/grid.h"
|
|
#include "twine/movements.h"
|
|
#include "twine/renderer.h"
|
|
#include "twine/resources.h"
|
|
#include "twine/scene.h"
|
|
#include "twine/twine.h"
|
|
|
|
namespace TwinE {
|
|
|
|
Collision::Collision(TwinEEngine *engine) : _engine(engine) {
|
|
}
|
|
|
|
bool Collision::standingOnActor(int32 actorIdx1, int32 actorIdx2) {
|
|
const ActorStruct *actor1 = _engine->_scene->getActor(actorIdx1);
|
|
const ActorStruct *actor2 = _engine->_scene->getActor(actorIdx2);
|
|
|
|
// Current actor (actor 1)
|
|
const int32 x1Left = _engine->_movements->processActorX + actor1->boudingBox.x.bottomLeft;
|
|
const int32 x1Right = _engine->_movements->processActorX + actor1->boudingBox.x.topRight;
|
|
|
|
const int32 y1Left = _engine->_movements->processActorY + actor1->boudingBox.y.bottomLeft;
|
|
const int32 y1Right = _engine->_movements->processActorY + actor1->boudingBox.y.topRight;
|
|
|
|
const int32 z1Left = _engine->_movements->processActorZ + actor1->boudingBox.z.bottomLeft;
|
|
const int32 z1Right = _engine->_movements->processActorZ + actor1->boudingBox.z.topRight;
|
|
|
|
// Actor 2
|
|
const int32 x2Left = actor2->x + actor2->boudingBox.x.bottomLeft;
|
|
const int32 x2Right = actor2->x + actor2->boudingBox.x.topRight;
|
|
|
|
const int32 y2Left = actor2->y + actor2->boudingBox.y.bottomLeft;
|
|
const int32 y2Right = actor2->y + actor2->boudingBox.y.topRight;
|
|
|
|
const int32 z2Left = actor2->z + actor2->boudingBox.z.bottomLeft;
|
|
const int32 z2Right = actor2->z + actor2->boudingBox.z.topRight;
|
|
|
|
if (x1Left >= x2Right) {
|
|
return false; // not standing
|
|
}
|
|
|
|
if (x1Right <= x2Left) {
|
|
return false;
|
|
}
|
|
|
|
if (y1Left > (y2Right + 1)) {
|
|
return false;
|
|
}
|
|
|
|
if (y1Left <= (y2Right - 0x100)) {
|
|
return false;
|
|
}
|
|
|
|
if (y1Right <= y2Left) {
|
|
return false;
|
|
}
|
|
|
|
if (z1Left >= z2Right) {
|
|
return false;
|
|
}
|
|
|
|
if (z1Right <= z2Left) {
|
|
return false;
|
|
}
|
|
|
|
return true; // standing
|
|
}
|
|
|
|
int32 Collision::getAverageValue(int32 var0, int32 var1, int32 var2, int32 var3) {
|
|
if (var3 <= 0) {
|
|
return var0;
|
|
}
|
|
|
|
if (var3 >= var2) {
|
|
return var1;
|
|
}
|
|
|
|
return (((var1 - var0) * var3) / var2) + var0;
|
|
}
|
|
|
|
void Collision::reajustActorPosition(ShapeType brickShape) {
|
|
if (brickShape == ShapeType::kNone) {
|
|
return;
|
|
}
|
|
|
|
const int32 brkX = (collisionX << 9) - 0x100;
|
|
const int32 brkY = collisionY << 8;
|
|
const int32 brkZ = (collisionZ << 9) - 0x100;
|
|
|
|
// double-side stairs
|
|
if (brickShape >= ShapeType::kDoubleSideStairsTop1 && brickShape <= ShapeType::kDoubleSideStairsRight2) {
|
|
switch (brickShape) {
|
|
case ShapeType::kDoubleSideStairsTop1:
|
|
if (_engine->_movements->processActorZ - collisionZ <= _engine->_movements->processActorX - collisionX) {
|
|
brickShape = ShapeType::kStairsTopLeft;
|
|
} else {
|
|
brickShape = ShapeType::kStairsTopRight;
|
|
}
|
|
break;
|
|
case ShapeType::kDoubleSideStairsBottom1:
|
|
if (_engine->_movements->processActorZ - collisionZ <= _engine->_movements->processActorX - collisionX) {
|
|
brickShape = ShapeType::kStairsBottomLeft;
|
|
} else {
|
|
brickShape = ShapeType::kStairsBottomRight;
|
|
}
|
|
break;
|
|
case ShapeType::kDoubleSideStairsLeft1:
|
|
if (512 - _engine->_movements->processActorX - collisionX <= _engine->_movements->processActorZ - collisionZ) {
|
|
brickShape = ShapeType::kStairsTopLeft;
|
|
} else {
|
|
brickShape = ShapeType::kStairsBottomLeft;
|
|
}
|
|
break;
|
|
case ShapeType::kDoubleSideStairsRight1:
|
|
if (512 - _engine->_movements->processActorX - collisionX <= _engine->_movements->processActorZ - collisionZ) {
|
|
brickShape = ShapeType::kStairsTopRight;
|
|
} else {
|
|
brickShape = ShapeType::kStairsBottomRight;
|
|
}
|
|
break;
|
|
case ShapeType::kDoubleSideStairsTop2:
|
|
if (_engine->_movements->processActorX - collisionX >= _engine->_movements->processActorZ - collisionZ) {
|
|
brickShape = ShapeType::kStairsTopRight;
|
|
} else {
|
|
brickShape = ShapeType::kStairsTopLeft;
|
|
}
|
|
break;
|
|
case ShapeType::kDoubleSideStairsBottom2:
|
|
if (_engine->_movements->processActorZ - collisionZ <= _engine->_movements->processActorX - collisionX) {
|
|
brickShape = ShapeType::kStairsBottomRight;
|
|
} else {
|
|
brickShape = ShapeType::kStairsBottomLeft;
|
|
}
|
|
break;
|
|
case ShapeType::kDoubleSideStairsLeft2:
|
|
if (512 - _engine->_movements->processActorX - collisionX <= _engine->_movements->processActorZ - collisionZ) {
|
|
brickShape = ShapeType::kStairsBottomLeft;
|
|
} else {
|
|
brickShape = ShapeType::kStairsTopLeft;
|
|
}
|
|
break;
|
|
case ShapeType::kDoubleSideStairsRight2:
|
|
if (512 - _engine->_movements->processActorX - collisionX <= _engine->_movements->processActorZ - collisionZ) {
|
|
brickShape = ShapeType::kStairsBottomRight;
|
|
} else {
|
|
brickShape = ShapeType::kStairsTopRight;
|
|
}
|
|
break;
|
|
default:
|
|
if (_engine->cfgfile.Debug) {
|
|
debug("Brick Shape %d unsupported", (int)brickShape);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (brickShape >= ShapeType::kStairsTopLeft && brickShape <= ShapeType::kStairsBottomRight) {
|
|
switch (brickShape) {
|
|
case ShapeType::kStairsTopLeft:
|
|
_engine->_movements->processActorY = brkY + getAverageValue(0, 256, 512, _engine->_movements->processActorX - brkX);
|
|
break;
|
|
case ShapeType::kStairsTopRight:
|
|
_engine->_movements->processActorY = brkY + getAverageValue(0, 256, 512, _engine->_movements->processActorZ - brkZ);
|
|
break;
|
|
case ShapeType::kStairsBottomLeft:
|
|
_engine->_movements->processActorY = brkY + getAverageValue(256, 0, 512, _engine->_movements->processActorZ - brkZ);
|
|
break;
|
|
case ShapeType::kStairsBottomRight:
|
|
_engine->_movements->processActorY = brkY + getAverageValue(256, 0, 512, _engine->_movements->processActorX - brkX);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
int32 Collision::checkCollisionWithActors(int32 actorIdx) {
|
|
ActorStruct *actor = _engine->_scene->getActor(actorIdx);
|
|
|
|
int32 xLeft = _engine->_movements->processActorX + actor->boudingBox.x.bottomLeft;
|
|
int32 xRight = _engine->_movements->processActorX + actor->boudingBox.x.topRight;
|
|
|
|
int32 yLeft = _engine->_movements->processActorY + actor->boudingBox.y.bottomLeft;
|
|
int32 yRight = _engine->_movements->processActorY + actor->boudingBox.y.topRight;
|
|
|
|
int32 zLeft = _engine->_movements->processActorZ + actor->boudingBox.z.bottomLeft;
|
|
int32 zRight = _engine->_movements->processActorZ + actor->boudingBox.z.topRight;
|
|
|
|
actor->collision = -1;
|
|
|
|
for (int32 a = 0; a < _engine->_scene->sceneNumActors; a++) {
|
|
ActorStruct *actorTest = _engine->_scene->getActor(a);
|
|
|
|
// aviod current processed actor
|
|
if (a != actorIdx && actorTest->entity != -1 && !actor->staticFlags.bComputeLowCollision && actorTest->standOn != actorIdx) {
|
|
const int32 xLeftTest = actorTest->x + actorTest->boudingBox.x.bottomLeft;
|
|
const int32 xRightTest = actorTest->x + actorTest->boudingBox.x.topRight;
|
|
|
|
const int32 yLeftTest = actorTest->y + actorTest->boudingBox.y.bottomLeft;
|
|
const int32 yRightTest = actorTest->y + actorTest->boudingBox.y.topRight;
|
|
|
|
const int32 zLeftTest = actorTest->z + actorTest->boudingBox.z.bottomLeft;
|
|
const int32 zRightTest = actorTest->z + actorTest->boudingBox.z.topRight;
|
|
|
|
if (xLeft < xRightTest && xRight > xLeftTest && yLeft < yRightTest && yRight > yLeftTest && zLeft < zRightTest && zRight > zLeftTest) {
|
|
actor->collision = a; // mark as collision with actor a
|
|
|
|
if (actorTest->staticFlags.bIsCarrierActor) {
|
|
if (actor->dynamicFlags.bIsFalling) {
|
|
_engine->_movements->processActorY = yRightTest - actor->boudingBox.y.bottomLeft + 1;
|
|
actor->standOn = a;
|
|
} else {
|
|
if (standingOnActor(actorIdx, a)) {
|
|
_engine->_movements->processActorY = yRightTest - actor->boudingBox.y.bottomLeft + 1;
|
|
actor->standOn = a;
|
|
} else {
|
|
int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(_engine->_movements->processActorX, _engine->_movements->processActorZ, actorTest->x, actorTest->z);
|
|
|
|
if (actorTest->staticFlags.bCanBePushed && !actor->staticFlags.bCanBePushed) {
|
|
actorTest->lastY = 0;
|
|
|
|
if (actorTest->staticFlags.bUseMiniZv) {
|
|
if (newAngle >= 0x80 && newAngle < 0x180 && actor->angle > 0x80 && actor->angle < 0x180) {
|
|
actorTest->lastX = 192;
|
|
}
|
|
if (newAngle >= 0x180 && newAngle < 0x280 && actor->angle > 0x180 && actor->angle < 0x280) {
|
|
actorTest->lastZ = -64;
|
|
}
|
|
if (newAngle >= 0x280 && newAngle < 0x380 && actor->angle > 0x280 && actor->angle < 0x380) {
|
|
actorTest->lastX = -64;
|
|
}
|
|
if ((newAngle >= 0x380 || newAngle < 0x80) && (actor->angle > 0x380 || actor->angle < 0x80)) {
|
|
actorTest->lastX = 192;
|
|
}
|
|
} else {
|
|
actorTest->lastX = _engine->_movements->processActorX - actor->collisionX;
|
|
actorTest->lastZ = _engine->_movements->processActorZ - actor->collisionZ;
|
|
}
|
|
}
|
|
|
|
if ((actorTest->boudingBox.x.topRight - actorTest->boudingBox.x.bottomLeft == actorTest->boudingBox.z.topRight - actorTest->boudingBox.z.bottomLeft) &&
|
|
(actor->boudingBox.x.topRight - actor->boudingBox.x.bottomLeft == actor->boudingBox.z.topRight - actor->boudingBox.z.bottomLeft)) {
|
|
if (newAngle < 0x180) {
|
|
_engine->_movements->processActorX = xLeftTest - actor->boudingBox.x.topRight;
|
|
}
|
|
if (newAngle >= 0x180 && newAngle < 0x280) {
|
|
_engine->_movements->processActorZ = zRightTest - actor->boudingBox.z.bottomLeft;
|
|
}
|
|
if (newAngle >= 0x280 && newAngle < 0x380) {
|
|
_engine->_movements->processActorX = xRightTest - actor->boudingBox.x.bottomLeft;
|
|
}
|
|
if (newAngle >= 0x380 || (newAngle < 0x380 && newAngle < 0x80)) {
|
|
_engine->_movements->processActorZ = zLeftTest - actor->boudingBox.z.topRight;
|
|
}
|
|
} else {
|
|
if (!actor->dynamicFlags.bIsFalling) {
|
|
_engine->_movements->processActorX = _engine->_movements->previousActorX;
|
|
_engine->_movements->processActorY = _engine->_movements->previousActorY;
|
|
_engine->_movements->processActorZ = _engine->_movements->previousActorZ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (standingOnActor(actorIdx, a)) {
|
|
_engine->_actor->hitActor(actorIdx, a, 1, -1);
|
|
}
|
|
|
|
int32 newAngle = _engine->_movements->getAngleAndSetTargetActorDistance(_engine->_movements->processActorX, _engine->_movements->processActorZ, actorTest->x, actorTest->z);
|
|
|
|
if (actorTest->staticFlags.bCanBePushed && !actor->staticFlags.bCanBePushed) {
|
|
actorTest->lastY = 0;
|
|
|
|
if (actorTest->staticFlags.bUseMiniZv) {
|
|
if (newAngle >= 0x80 && newAngle < 0x180 && actor->angle > 0x80 && actor->angle < 0x180) {
|
|
actorTest->lastX = 192;
|
|
}
|
|
if (newAngle >= 0x180 && newAngle < 0x280 && actor->angle > 0x180 && actor->angle < 0x280) {
|
|
actorTest->lastZ = -64;
|
|
}
|
|
if (newAngle >= 0x280 && newAngle < 0x380 && actor->angle > 0x280 && actor->angle < 0x380) {
|
|
actorTest->lastX = -64;
|
|
}
|
|
if ((newAngle >= 0x380 || newAngle < 0x80) && (actor->angle > 0x380 || actor->angle < 0x80)) {
|
|
actorTest->lastX = 192;
|
|
}
|
|
} else {
|
|
actorTest->lastX = _engine->_movements->processActorX - actor->collisionX;
|
|
actorTest->lastZ = _engine->_movements->processActorZ - actor->collisionZ;
|
|
}
|
|
}
|
|
|
|
if ((actorTest->boudingBox.x.topRight - actorTest->boudingBox.x.bottomLeft == actorTest->boudingBox.z.topRight - actorTest->boudingBox.z.bottomLeft) &&
|
|
(actor->boudingBox.x.topRight - actor->boudingBox.x.bottomLeft == actor->boudingBox.z.topRight - actor->boudingBox.z.bottomLeft)) {
|
|
if (newAngle < 0x180) {
|
|
_engine->_movements->processActorX = xLeftTest - actor->boudingBox.x.topRight;
|
|
}
|
|
if (newAngle >= 0x180 && newAngle < 0x280) {
|
|
_engine->_movements->processActorZ = zRightTest - actor->boudingBox.z.bottomLeft;
|
|
}
|
|
if (newAngle >= 0x280 && newAngle < 0x380) {
|
|
_engine->_movements->processActorX = xRightTest - actor->boudingBox.x.bottomLeft;
|
|
}
|
|
if (newAngle >= 0x380 || (newAngle < 0x380 && newAngle < 0x80)) {
|
|
_engine->_movements->processActorZ = zLeftTest - actor->boudingBox.z.topRight;
|
|
}
|
|
} else {
|
|
if (!actor->dynamicFlags.bIsFalling) {
|
|
_engine->_movements->processActorX = _engine->_movements->previousActorX;
|
|
_engine->_movements->processActorY = _engine->_movements->previousActorY;
|
|
_engine->_movements->processActorZ = _engine->_movements->previousActorZ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (actor->dynamicFlags.bIsHitting) {
|
|
_engine->_movements->rotateActor(0, 200, actor->angle);
|
|
|
|
xLeft = _engine->_renderer->destX + _engine->_movements->processActorX + actor->boudingBox.x.bottomLeft;
|
|
xRight = _engine->_renderer->destX + _engine->_movements->processActorX + actor->boudingBox.x.topRight;
|
|
|
|
yLeft = _engine->_movements->processActorY + actor->boudingBox.y.bottomLeft;
|
|
yRight = _engine->_movements->processActorY + actor->boudingBox.y.topRight;
|
|
|
|
zLeft = _engine->_renderer->destZ + _engine->_movements->processActorZ + actor->boudingBox.z.bottomLeft;
|
|
zRight = _engine->_renderer->destZ + _engine->_movements->processActorZ + actor->boudingBox.z.topRight;
|
|
|
|
for (int32 a = 0; a < _engine->_scene->sceneNumActors; a++) {
|
|
const ActorStruct *actorTest = _engine->_scene->getActor(a);
|
|
|
|
// aviod current processed actor
|
|
if (a != actorIdx && actorTest->entity != -1 && !actorTest->staticFlags.bIsHidden && actorTest->standOn != actorIdx) {
|
|
const int32 xLeftTest = actorTest->x + actorTest->boudingBox.x.bottomLeft;
|
|
const int32 xRightTest = actorTest->x + actorTest->boudingBox.x.topRight;
|
|
|
|
const int32 yLeftTest = actorTest->y + actorTest->boudingBox.y.bottomLeft;
|
|
const int32 yRightTest = actorTest->y + actorTest->boudingBox.y.topRight;
|
|
|
|
const int32 zLeftTest = actorTest->z + actorTest->boudingBox.z.bottomLeft;
|
|
const int32 zRightTest = actorTest->z + actorTest->boudingBox.z.topRight;
|
|
|
|
if (xLeft < xRightTest && xRight > xLeftTest && yLeft < yRightTest && yRight > yLeftTest && zLeft < zRightTest && zRight > zLeftTest) {
|
|
_engine->_actor->hitActor(actorIdx, a, actor->strengthOfHit, actor->angle + ANGLE_90);
|
|
actor->dynamicFlags.bIsHitting = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return actor->collision;
|
|
}
|
|
|
|
void Collision::checkHeroCollisionWithBricks(int32 x, int32 y, int32 z, int32 damageMask) {
|
|
ShapeType brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ);
|
|
|
|
_engine->_movements->processActorX += x;
|
|
_engine->_movements->processActorY += y;
|
|
_engine->_movements->processActorZ += z;
|
|
|
|
if (_engine->_movements->processActorX >= 0 && _engine->_movements->processActorZ >= 0 && _engine->_movements->processActorX <= 0x7E00 && _engine->_movements->processActorZ <= 0x7E00) {
|
|
reajustActorPosition(brickShape);
|
|
brickShape = _engine->_grid->getBrickShapeFull(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ, _engine->_actor->processActorPtr->boudingBox.y.topRight);
|
|
|
|
if (brickShape == ShapeType::kSolid) {
|
|
causeActorDamage |= damageMask;
|
|
brickShape = _engine->_grid->getBrickShapeFull(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->previousActorZ + z, _engine->_actor->processActorPtr->boudingBox.y.topRight);
|
|
|
|
if (brickShape == ShapeType::kSolid) {
|
|
brickShape = _engine->_grid->getBrickShapeFull(x + _engine->_movements->previousActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ, _engine->_actor->processActorPtr->boudingBox.y.topRight);
|
|
|
|
if (brickShape != ShapeType::kSolid) {
|
|
processCollisionX = _engine->_movements->previousActorX;
|
|
}
|
|
} else {
|
|
processCollisionZ = _engine->_movements->previousActorZ;
|
|
}
|
|
}
|
|
}
|
|
|
|
_engine->_movements->processActorX = processCollisionX;
|
|
_engine->_movements->processActorY = processCollisionY;
|
|
_engine->_movements->processActorZ = processCollisionZ;
|
|
}
|
|
|
|
void Collision::checkActorCollisionWithBricks(int32 x, int32 y, int32 z, int32 damageMask) {
|
|
ShapeType brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ);
|
|
|
|
_engine->_movements->processActorX += x;
|
|
_engine->_movements->processActorY += y;
|
|
_engine->_movements->processActorZ += z;
|
|
|
|
if (_engine->_movements->processActorX >= 0 && _engine->_movements->processActorZ >= 0 && _engine->_movements->processActorX <= 0x7E00 && _engine->_movements->processActorZ <= 0x7E00) {
|
|
reajustActorPosition(brickShape);
|
|
brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ);
|
|
|
|
if (brickShape == ShapeType::kSolid) {
|
|
causeActorDamage |= damageMask;
|
|
brickShape = _engine->_grid->getBrickShape(_engine->_movements->processActorX, _engine->_movements->processActorY, _engine->_movements->previousActorZ + z);
|
|
|
|
if (brickShape == ShapeType::kSolid) {
|
|
brickShape = _engine->_grid->getBrickShape(x + _engine->_movements->previousActorX, _engine->_movements->processActorY, _engine->_movements->processActorZ);
|
|
|
|
if (brickShape != ShapeType::kSolid) {
|
|
processCollisionX = _engine->_movements->previousActorX;
|
|
}
|
|
} else {
|
|
processCollisionZ = _engine->_movements->previousActorZ;
|
|
}
|
|
}
|
|
}
|
|
|
|
_engine->_movements->processActorX = processCollisionX;
|
|
_engine->_movements->processActorY = processCollisionY;
|
|
_engine->_movements->processActorZ = processCollisionZ;
|
|
}
|
|
|
|
void Collision::stopFalling() { // ReceptionObj()
|
|
if (IS_HERO(_engine->_animations->currentlyProcessedActorIdx)) {
|
|
const int32 fall = _engine->_scene->heroYBeforeFall - _engine->_movements->processActorY;
|
|
|
|
if (fall >= 2048) {
|
|
_engine->_extra->addExtraSpecial(_engine->_actor->processActorPtr->x, _engine->_actor->processActorPtr->y + 1000, _engine->_actor->processActorPtr->z, ExtraSpecialType::kHitStars);
|
|
_engine->_actor->processActorPtr->life--;
|
|
_engine->_animations->initAnim(AnimationTypes::kLandingHit, 2, AnimationTypes::kStanding, _engine->_animations->currentlyProcessedActorIdx);
|
|
} else if (fall > 10) {
|
|
_engine->_animations->initAnim(AnimationTypes::kLanding, 2, AnimationTypes::kStanding, _engine->_animations->currentlyProcessedActorIdx);
|
|
} else {
|
|
_engine->_animations->initAnim(AnimationTypes::kStanding, 0, AnimationTypes::kStanding, _engine->_animations->currentlyProcessedActorIdx);
|
|
}
|
|
|
|
_engine->_scene->heroYBeforeFall = 0;
|
|
} else {
|
|
_engine->_animations->initAnim(AnimationTypes::kLanding, 2, _engine->_actor->processActorPtr->animExtra, _engine->_animations->currentlyProcessedActorIdx);
|
|
}
|
|
|
|
_engine->_actor->processActorPtr->dynamicFlags.bIsFalling = 0;
|
|
}
|
|
|
|
int32 Collision::checkExtraCollisionWithActors(ExtraListStruct *extra, int32 actorIdx) {
|
|
Common::MemoryReadStream stream(_engine->_resources->spriteBoundingBoxPtr, _engine->_resources->spriteBoundingBoxSize);
|
|
stream.seek(extra->info0 * 16);
|
|
stream.skip(4);
|
|
|
|
const int32 xLeft = stream.readSint16LE() + extra->x;
|
|
const int32 xRight = stream.readSint16LE() + extra->x;
|
|
const int32 yLeft = stream.readSint16LE() + extra->y;
|
|
const int32 yRight = stream.readSint16LE() + extra->y;
|
|
const int32 zLeft = stream.readSint16LE() + extra->z;
|
|
const int32 zRight = stream.readSint16LE() + extra->z;
|
|
|
|
for (int32 a = 0; a < _engine->_scene->sceneNumActors; a++) {
|
|
const ActorStruct *actorTest = _engine->_scene->getActor(a);
|
|
|
|
if (a != actorIdx && actorTest->entity != -1) {
|
|
const int32 xLeftTest = actorTest->x + actorTest->boudingBox.x.bottomLeft;
|
|
const int32 xRightTest = actorTest->x + actorTest->boudingBox.x.topRight;
|
|
const int32 yLeftTest = actorTest->y + actorTest->boudingBox.y.bottomLeft;
|
|
const int32 yRightTest = actorTest->y + actorTest->boudingBox.y.topRight;
|
|
const int32 zLeftTest = actorTest->z + actorTest->boudingBox.z.bottomLeft;
|
|
const int32 zRightTest = actorTest->z + actorTest->boudingBox.z.topRight;
|
|
|
|
if (xLeft < xRightTest && xRight > xLeftTest && yLeft < yRightTest && yRight > yLeftTest && zLeft < zRightTest && zRight > zLeftTest) {
|
|
if (extra->strengthOfHit != 0) {
|
|
_engine->_actor->hitActor(actorIdx, a, extra->strengthOfHit, -1);
|
|
}
|
|
|
|
return a;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
bool Collision::checkExtraCollisionWithBricks(int32 x, int32 y, int32 z, int32 oldX, int32 oldY, int32 oldZ) {
|
|
if (_engine->_grid->getBrickShape(oldX, oldY, oldZ) != ShapeType::kNone) {
|
|
return true;
|
|
}
|
|
|
|
const int32 averageX = ABS(x + oldX) / 2;
|
|
const int32 averageY = ABS(y + oldY) / 2;
|
|
const int32 averageZ = ABS(z + oldZ) / 2;
|
|
|
|
if (_engine->_grid->getBrickShape(averageX, averageY, averageZ) != ShapeType::kNone) {
|
|
return true;
|
|
}
|
|
|
|
if (_engine->_grid->getBrickShape(ABS(oldX + averageX) / 2, ABS(oldY + averageY) / 2, ABS(oldZ + averageZ) / 2) != ShapeType::kNone) {
|
|
return true;
|
|
}
|
|
|
|
if (_engine->_grid->getBrickShape(ABS(x + averageX) / 2, ABS(y + averageY) / 2, ABS(z + averageZ) / 2) != ShapeType::kNone) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int32 Collision::checkExtraCollisionWithExtra(ExtraListStruct *extra, int32 extraIdx) {
|
|
Common::MemoryReadStream stream(_engine->_resources->spriteBoundingBoxPtr, _engine->_resources->spriteBoundingBoxSize);
|
|
stream.seek(extra->info0 * 16);
|
|
stream.skip(4);
|
|
|
|
const int32 xLeft = stream.readSint16LE() + extra->x;
|
|
const int32 xRight = stream.readSint16LE() + extra->x;
|
|
const int32 yLeft = stream.readSint16LE() + extra->y;
|
|
const int32 yRight = stream.readSint16LE() + extra->y;
|
|
const int32 zLeft = stream.readSint16LE() + extra->z;
|
|
const int32 zRight = stream.readSint16LE() + extra->z;
|
|
|
|
for (int32 i = 0; i < EXTRA_MAX_ENTRIES; i++) {
|
|
const ExtraListStruct *extraTest = &_engine->_extra->extraList[i];
|
|
if (i != extraIdx && extraTest->info0 != -1) {
|
|
// const int16 * spriteBoundingTest;
|
|
// spriteBoundingTest = (const int16*)(_engine->_resources->spriteBoundingBoxPtr + extraTest->info0 * 16 + 4);
|
|
const int32 xLeftTest = stream.readSint16LE() + extraTest->x;
|
|
const int32 xRightTest = stream.readSint16LE() + extraTest->x;
|
|
const int32 yLeftTest = stream.readSint16LE() + extraTest->y;
|
|
const int32 yRightTest = stream.readSint16LE() + extraTest->y;
|
|
const int32 zLeftTest = stream.readSint16LE() + extraTest->z;
|
|
const int32 zRightTest = stream.readSint16LE() + extraTest->z;
|
|
|
|
if (xLeft < xLeftTest) {
|
|
if (xLeft < xRightTest && xRight > xLeftTest && yLeft < yRightTest && yRight > yLeftTest && zLeft < zRightTest && zRight > zLeftTest) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
} // namespace TwinE
|