1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-08 06:06:51 +02:00

fix gears mesh swap on LEVEL3A; attach puzzle and key items to the hand and keyhole;

This commit is contained in:
XProger
2018-07-18 04:59:57 +03:00
parent 3885af71f5
commit 6969f5f904
5 changed files with 92 additions and 32 deletions

View File

@@ -142,10 +142,15 @@ struct Controller {
} *explodeParts; } *explodeParts;
vec3 lastPos; vec3 lastPos;
mat4 matrix;
bool invertAim; bool invertAim;
bool lockMatrix;
Controller(IGame *game, int entity) : next(NULL), game(game), level(game->getLevel()), entity(entity), animation(level, getModel(), level->entities[entity].flags.smooth), state(animation.state), layers(0), explodeMask(0), explodeParts(0), lastPos(0), invertAim(false) { Controller(IGame *game, int entity) : next(NULL), game(game), level(game->getLevel()), entity(entity), animation(level, getModel(), level->entities[entity].flags.smooth), state(animation.state), layers(0), explodeMask(0), explodeParts(0), lastPos(0), invertAim(false) {
const TR::Entity &e = getEntity(); const TR::Entity &e = getEntity();
lockMatrix = false;
matrix.identity();
pos = vec3(float(e.x), float(e.y), float(e.z)); pos = vec3(float(e.x), float(e.y), float(e.z));
angle = vec3(0.0f, e.rotation, 0.0f); angle = vec3(0.0f, e.rotation, 0.0f);
roomIndex = e.room; roomIndex = e.room;
@@ -1185,12 +1190,13 @@ struct Controller {
if (level->isCutsceneLevel() && (getEntity().isActor() || getEntity().isLara())) if (level->isCutsceneLevel() && (getEntity().isActor() || getEntity().isLara()))
return level->cutMatrix; return level->cutMatrix;
mat4 matrix; if (!lockMatrix) {
matrix.identity(); matrix.identity();
matrix.translate(pos); matrix.translate(pos);
if (angle.y != 0.0f) matrix.rotateY(angle.y - animation.rot * animation.delta); if (angle.y != 0.0f) matrix.rotateY(angle.y - animation.rot * animation.delta);
if (angle.x != 0.0f) matrix.rotateX(angle.x); if (angle.x != 0.0f) matrix.rotateX(angle.x);
if (angle.z != 0.0f) matrix.rotateZ(angle.z); if (angle.z != 0.0f) matrix.rotateZ(angle.z);
}
return matrix; return matrix;
} }
@@ -1320,7 +1326,7 @@ struct Controller {
} }
} else { } else {
Core::setBasis(joints, model->mCount); Core::setBasis(joints, model->mCount);
mesh->renderModel(getEntity().modelIndex - 1, caustics); mesh->renderModel(model->index, caustics);
} }
} }

View File

@@ -2064,7 +2064,7 @@ namespace TR {
struct Model { struct Model {
Entity::Type type; Entity::Type type;
uint16 unused; uint16 index;
uint16 mCount; uint16 mCount;
uint16 mStart; uint16 mStart;
uint32 node; uint32 node;
@@ -2649,7 +2649,8 @@ namespace TR {
Model &m = models[i]; Model &m = models[i];
uint16 type; uint16 type;
m.type = Entity::Type(stream.read(type)); m.type = Entity::Type(stream.read(type));
stream.read(m.unused); stream.seek(sizeof(m.index));
m.index = i;
stream.read(m.mCount); stream.read(m.mCount);
stream.read(m.mStart); stream.read(m.mStart);
stream.read(m.node); stream.read(m.node);

View File

@@ -244,6 +244,7 @@ struct Lara : Character {
int pickupListCount; int pickupListCount;
Controller *pickupList[32]; Controller *pickupList[32];
KeyHole *keyHole; KeyHole *keyHole;
Controller *keyItem;
Lightning *lightning; Lightning *lightning;
Texture *environment; Texture *environment;
vec2 rotFactor; vec2 rotFactor;
@@ -454,6 +455,7 @@ struct Lara : Character {
hitTime = 0.0f; hitTime = 0.0f;
keyHole = NULL; keyHole = NULL;
keyItem = NULL;
lightning = NULL; lightning = NULL;
environment = NULL; environment = NULL;
@@ -486,6 +488,8 @@ struct Lara : Character {
//reset(33, vec3(48229, 4608, 78420), 270 * DEG2RAD); // level 1 (end) //reset(33, vec3(48229, 4608, 78420), 270 * DEG2RAD); // level 1 (end)
//reset(9, vec3(63008, 0, 37787), 0); // level 2 (switch) //reset(9, vec3(63008, 0, 37787), 0); // level 2 (switch)
//reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool) //reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool)
//reset(5, vec3(55398, 0, 29246), -PI * 0.5f); // level 2 (key hole)
//reset(71, vec3(12473, -768, 30208), -PI * 0.5f); // level 2 (puzzle hole)
//reset(26, vec3(71980, 1546, 19000), 270 * DEG2RAD); // level 2 (underwater switch) //reset(26, vec3(71980, 1546, 19000), 270 * DEG2RAD); // level 2 (underwater switch)
//reset(61, vec3(27221, -1024, 29205), -PI * 0.5f); // level 2 (blade) //reset(61, vec3(27221, -1024, 29205), -PI * 0.5f); // level 2 (blade)
//reset(43, vec3(31400, -2560, 25200), PI); // level 2 (reach) //reset(43, vec3(31400, -2560, 25200), PI); // level 2 (reach)
@@ -508,6 +512,7 @@ struct Lara : Character {
//reset(19, vec3(41418, -3707, 58863), 270 * DEG2RAD); // level 5 (triangle) //reset(19, vec3(41418, -3707, 58863), 270 * DEG2RAD); // level 5 (triangle)
//reset(21, vec3(24106, -4352, 52089), 0); // level 6 (flame traps) //reset(21, vec3(24106, -4352, 52089), 0); // level 6 (flame traps)
//reset(73, vec3(73372, 122, 51687), PI * 0.5f); // level 6 (midas hand) //reset(73, vec3(73372, 122, 51687), PI * 0.5f); // level 6 (midas hand)
//reset(20, vec3(25088, -5120, 17593), PI); // level 6 (puzzle slots)
//reset(64, vec3(36839, -2560, 48769), 270 * DEG2RAD); // level 6 (flipmap effect) //reset(64, vec3(36839, -2560, 48769), 270 * DEG2RAD); // level 6 (flipmap effect)
//reset(99, vec3(45562, -3328, 63366), 225 * DEG2RAD); // level 7a (flipmap) //reset(99, vec3(45562, -3328, 63366), 225 * DEG2RAD); // level 7a (flipmap)
//reset(77, vec3(36943, -4096, 62821), 270 * DEG2RAD); // level 7b (heavy trigger) //reset(77, vec3(36943, -4096, 62821), 270 * DEG2RAD); // level 7b (heavy trigger)
@@ -609,6 +614,9 @@ struct Lara : Character {
visibleMask = 0xFFFFFFFF; visibleMask = 0xFFFFFFFF;
health = LARA_MAX_HEALTH; health = LARA_MAX_HEALTH;
oxygen = LARA_MAX_OXYGEN; oxygen = LARA_MAX_OXYGEN;
keyHole = NULL;
keyItem = NULL;
if (room == TR::NO_ROOM) { if (room == TR::NO_ROOM) {
stand = STAND_AIR; stand = STAND_AIR;
@@ -1866,7 +1874,9 @@ struct Lara : Character {
} }
keyHole = controller; keyHole = controller;
game->invUse(camera->cameraIndex, usedKey);
if (game->invUse(camera->cameraIndex, usedKey))
keyItem = game->addEntity(usedKey, getRoomIndex(), pos, 0);
animation.setState(actionState); animation.setState(actionState);
} }
@@ -2755,11 +2765,24 @@ struct Lara : Character {
} }
break; break;
} }
case STATE_USE_KEY : case STATE_USE_KEY :
case STATE_USE_PUZZLE : { case STATE_USE_PUZZLE : {
if (keyHole && animation.isFrameActive(state == STATE_USE_PUZZLE ? PUZZLE_FRAME : KEY_FRAME)) { if (keyHole) {
keyHole->activate(); if (animation.isFrameActive(state == STATE_USE_PUZZLE ? PUZZLE_FRAME : KEY_FRAME)) {
keyHole = NULL; keyHole->activate();
if (keyItem) {
if (state == STATE_USE_KEY) {
mat4 &m = keyItem->matrix;
m = keyHole->getMatrix();
m.translate(vec3(0, -590, 484));
m.rotateX(PI * 0.5f);
} else
game->removeEntity(keyItem);
}
keyItem = NULL;
keyHole = NULL;
}
} }
break; break;
} }
@@ -2817,6 +2840,42 @@ struct Lara : Character {
if (camera->mode != Camera::MODE_CUTSCENE && camera->mode != Camera::MODE_STATIC) if (camera->mode != Camera::MODE_CUTSCENE && camera->mode != Camera::MODE_STATIC)
camera->mode = (emptyHands() || health <= 0.0f) ? Camera::MODE_FOLLOW : Camera::MODE_COMBAT; camera->mode = (emptyHands() || health <= 0.0f) ? Camera::MODE_FOLLOW : Camera::MODE_COMBAT;
if (keyItem) {
keyItem->flags.invisible = animation.frameIndex < (state == STATE_USE_KEY ? 70 : 30);
keyItem->lockMatrix = true;
mat4 &m = keyItem->matrix;
Basis b;
if (state == STATE_USE_KEY) {
b = getJoint(10);
b.rot = b.rot * quat(vec3(0, 1, 0), PI * 0.5f);
b.translate(vec3(0, 120, 0));
} else {
vec3 rot(0.0f);
// TODO: hardcode item-hand alignment 8)
rot.x = -PI * 0.5f;
if (animation.frameIndex < 55)
b = getJoint(13);
else
b = getJoint(10);
b.translate(vec3(0, 48, 0));
if (rot.x != 0.0f) b.rot = b.rot * quat(vec3(1, 0, 0), rot.x);
if (rot.y != 0.0f) b.rot = b.rot * quat(vec3(0, 1, 0), rot.y);
if (rot.z != 0.0f) b.rot = b.rot * quat(vec3(0, 0, 1), rot.z);
}
keyItem->joints[0] = b;
m.identity();
m.setRot(b.rot);
m.setPos(b.pos);
//m = getMatrix();
}
} }
virtual void updateAnimation(bool commands) { virtual void updateAnimation(bool commands) {

View File

@@ -1444,16 +1444,8 @@ struct Level : IGame {
void renderEntity(const TR::Entity &entity) { void renderEntity(const TR::Entity &entity) {
//if (entity.room != lara->getRoomIndex()) return; //if (entity.room != lara->getRoomIndex()) return;
if (Core::pass == Core::passShadow && !entity.castShadow()) return; if (Core::pass == Core::passShadow && !entity.castShadow()) return;
bool isModel = entity.modelIndex > 0;
if (isModel) {
if (!mesh->models[entity.modelIndex - 1].geometry[mesh->transparent].count) return;
} else {
if (mesh->sequences[-(entity.modelIndex + 1)].transp != mesh->transparent) return;
}
Controller *controller = (Controller*)entity.controller; Controller *controller = (Controller*)entity.controller;
int roomIndex = controller->getRoomIndex(); int roomIndex = controller->getRoomIndex();
TR::Room &room = level.rooms[roomIndex]; TR::Room &room = level.rooms[roomIndex];
@@ -1463,6 +1455,14 @@ struct Level : IGame {
if (!entity.isLara() && !entity.isActor() && !room.flags.visible) if (!entity.isLara() && !entity.isActor() && !room.flags.visible)
return; return;
bool isModel = entity.modelIndex > 0;
if (isModel) {
if (!mesh->models[controller->getModel()->index].geometry[mesh->transparent].count) return;
} else {
if (mesh->sequences[-(entity.modelIndex + 1)].transp != mesh->transparent) return;
}
float intensity = controller->intensity < 0.0f ? intensityf(room.ambient) : controller->intensity; float intensity = controller->intensity < 0.0f ? intensityf(room.ambient) : controller->intensity;
Shader::Type type = isModel ? Shader::ENTITY : Shader::SPRITE; Shader::Type type = isModel ? Shader::ENTITY : Shader::SPRITE;

View File

@@ -1407,22 +1407,16 @@ struct KeyHole : Controller {
virtual bool activate() { virtual bool activate() {
if (!Controller::activate()) return false; if (!Controller::activate()) return false;
flags.active = TR::ACTIVE; flags.active = TR::ACTIVE;
swap();
deactivate(); deactivate();
return true; return true;
} }
virtual void setSaveData(const TR::SaveGame::Entity &data) { virtual const TR::Model* getModel() {
Controller::setSaveData(data); if (getEntity().isPuzzleHole() && flags.active == TR::ACTIVE) {
if (flags.active == TR::ACTIVE)
swap();
}
void swap() {
if (getEntity().isPuzzleHole()) {
int doneIdx = TR::Entity::convToInv(TR::Entity::getItemForHole(getEntity().type)) - TR::Entity::INV_PUZZLE_1; int doneIdx = TR::Entity::convToInv(TR::Entity::getItemForHole(getEntity().type)) - TR::Entity::INV_PUZZLE_1;
meshSwap(0, level->extra.puzzleDone[doneIdx]); return &level->models[level->extra.puzzleDone[doneIdx]];
} }
return Controller::getModel();
} }
virtual void update() {} virtual void update() {}