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:
@@ -142,10 +142,15 @@ struct Controller {
|
||||
} *explodeParts;
|
||||
|
||||
vec3 lastPos;
|
||||
mat4 matrix;
|
||||
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) {
|
||||
const TR::Entity &e = getEntity();
|
||||
lockMatrix = false;
|
||||
matrix.identity();
|
||||
|
||||
pos = vec3(float(e.x), float(e.y), float(e.z));
|
||||
angle = vec3(0.0f, e.rotation, 0.0f);
|
||||
roomIndex = e.room;
|
||||
@@ -1185,12 +1190,13 @@ struct Controller {
|
||||
if (level->isCutsceneLevel() && (getEntity().isActor() || getEntity().isLara()))
|
||||
return level->cutMatrix;
|
||||
|
||||
mat4 matrix;
|
||||
if (!lockMatrix) {
|
||||
matrix.identity();
|
||||
matrix.translate(pos);
|
||||
if (angle.y != 0.0f) matrix.rotateY(angle.y - animation.rot * animation.delta);
|
||||
if (angle.x != 0.0f) matrix.rotateX(angle.x);
|
||||
if (angle.z != 0.0f) matrix.rotateZ(angle.z);
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
@@ -1320,7 +1326,7 @@ struct Controller {
|
||||
}
|
||||
} else {
|
||||
Core::setBasis(joints, model->mCount);
|
||||
mesh->renderModel(getEntity().modelIndex - 1, caustics);
|
||||
mesh->renderModel(model->index, caustics);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -2064,7 +2064,7 @@ namespace TR {
|
||||
|
||||
struct Model {
|
||||
Entity::Type type;
|
||||
uint16 unused;
|
||||
uint16 index;
|
||||
uint16 mCount;
|
||||
uint16 mStart;
|
||||
uint32 node;
|
||||
@@ -2649,7 +2649,8 @@ namespace TR {
|
||||
Model &m = models[i];
|
||||
uint16 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.mStart);
|
||||
stream.read(m.node);
|
||||
|
63
src/lara.h
63
src/lara.h
@@ -244,6 +244,7 @@ struct Lara : Character {
|
||||
int pickupListCount;
|
||||
Controller *pickupList[32];
|
||||
KeyHole *keyHole;
|
||||
Controller *keyItem;
|
||||
Lightning *lightning;
|
||||
Texture *environment;
|
||||
vec2 rotFactor;
|
||||
@@ -454,6 +455,7 @@ struct Lara : Character {
|
||||
hitTime = 0.0f;
|
||||
|
||||
keyHole = NULL;
|
||||
keyItem = NULL;
|
||||
lightning = NULL;
|
||||
environment = NULL;
|
||||
|
||||
@@ -486,6 +488,8 @@ struct Lara : Character {
|
||||
//reset(33, vec3(48229, 4608, 78420), 270 * DEG2RAD); // level 1 (end)
|
||||
//reset(9, vec3(63008, 0, 37787), 0); // level 2 (switch)
|
||||
//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(61, vec3(27221, -1024, 29205), -PI * 0.5f); // level 2 (blade)
|
||||
//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(21, vec3(24106, -4352, 52089), 0); // level 6 (flame traps)
|
||||
//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(99, vec3(45562, -3328, 63366), 225 * DEG2RAD); // level 7a (flipmap)
|
||||
//reset(77, vec3(36943, -4096, 62821), 270 * DEG2RAD); // level 7b (heavy trigger)
|
||||
@@ -610,6 +615,9 @@ struct Lara : Character {
|
||||
health = LARA_MAX_HEALTH;
|
||||
oxygen = LARA_MAX_OXYGEN;
|
||||
|
||||
keyHole = NULL;
|
||||
keyItem = NULL;
|
||||
|
||||
if (room == TR::NO_ROOM) {
|
||||
stand = STAND_AIR;
|
||||
room = getRoomByPos(pos);
|
||||
@@ -1866,7 +1874,9 @@ struct Lara : Character {
|
||||
}
|
||||
|
||||
keyHole = controller;
|
||||
game->invUse(camera->cameraIndex, usedKey);
|
||||
|
||||
if (game->invUse(camera->cameraIndex, usedKey))
|
||||
keyItem = game->addEntity(usedKey, getRoomIndex(), pos, 0);
|
||||
|
||||
animation.setState(actionState);
|
||||
}
|
||||
@@ -2757,10 +2767,23 @@ struct Lara : Character {
|
||||
}
|
||||
case STATE_USE_KEY :
|
||||
case STATE_USE_PUZZLE : {
|
||||
if (keyHole && animation.isFrameActive(state == STATE_USE_PUZZLE ? PUZZLE_FRAME : KEY_FRAME)) {
|
||||
if (keyHole) {
|
||||
if (animation.isFrameActive(state == STATE_USE_PUZZLE ? PUZZLE_FRAME : KEY_FRAME)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -2817,6 +2840,42 @@ struct Lara : Character {
|
||||
|
||||
if (camera->mode != Camera::MODE_CUTSCENE && camera->mode != Camera::MODE_STATIC)
|
||||
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) {
|
||||
|
16
src/level.h
16
src/level.h
@@ -1444,16 +1444,8 @@ struct Level : IGame {
|
||||
void renderEntity(const TR::Entity &entity) {
|
||||
//if (entity.room != lara->getRoomIndex()) 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;
|
||||
|
||||
int roomIndex = controller->getRoomIndex();
|
||||
TR::Room &room = level.rooms[roomIndex];
|
||||
|
||||
@@ -1463,6 +1455,14 @@ struct Level : IGame {
|
||||
if (!entity.isLara() && !entity.isActor() && !room.flags.visible)
|
||||
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;
|
||||
|
||||
Shader::Type type = isModel ? Shader::ENTITY : Shader::SPRITE;
|
||||
|
@@ -1407,22 +1407,16 @@ struct KeyHole : Controller {
|
||||
virtual bool activate() {
|
||||
if (!Controller::activate()) return false;
|
||||
flags.active = TR::ACTIVE;
|
||||
swap();
|
||||
deactivate();
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void setSaveData(const TR::SaveGame::Entity &data) {
|
||||
Controller::setSaveData(data);
|
||||
if (flags.active == TR::ACTIVE)
|
||||
swap();
|
||||
}
|
||||
|
||||
void swap() {
|
||||
if (getEntity().isPuzzleHole()) {
|
||||
virtual const TR::Model* getModel() {
|
||||
if (getEntity().isPuzzleHole() && flags.active == TR::ACTIVE) {
|
||||
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() {}
|
||||
|
Reference in New Issue
Block a user