From 261a86e9c0d65400cbd8815584620254b5ba6a73 Mon Sep 17 00:00:00 2001 From: XProger Date: Wed, 20 Sep 2017 01:40:04 +0300 Subject: [PATCH] #8 fix camera targeting; #22 add drawbridge controller, fix items brightness; fix slide bug (for negative velocity.y) --- src/camera.h | 12 ++++++--- src/format.h | 38 ++++++++++++++++++++++++---- src/lara.h | 69 ++++++++++++++++++++++++++++++++------------------- src/level.h | 14 ++++++++--- src/trigger.h | 16 ++++++++++++ 5 files changed, 112 insertions(+), 37 deletions(-) diff --git a/src/camera.h b/src/camera.h index 6f59c37..48a3ebf 100644 --- a/src/camera.h +++ b/src/camera.h @@ -113,10 +113,13 @@ struct Camera : ICamera { this->viewIndex = viewIndex; this->timer = timer; this->speed = speed; - lastDest = pos; + lastDest = destPos; - if (viewIndex > -1) - room = level->cameras[viewIndex].room; + if (viewIndex > -1) { + TR::Camera &cam = level->cameras[viewIndex]; + room = cam.room; + pos = vec3(float(cam.x), float(cam.y), float(cam.z)); + } } vec3 getViewPoint() { @@ -129,6 +132,9 @@ struct Camera : ICamera { } void resetTarget(const vec3 &viewPoint) { + if (state == STATE_STATIC) + pos = destPos = lastDest; + timer = -1.0f; state = STATE_FOLLOW; viewTarget = NULL; diff --git a/src/format.h b/src/format.h index 8585494..8fb4807 100644 --- a/src/format.h +++ b/src/format.h @@ -52,7 +52,7 @@ E( TRAP_BOULDER ) \ E( TRAP_DART ) \ E( TRAP_DARTGUN ) \ - E( DOOR_LIFT ) \ + E( DRAWBRIDGE ) \ E( TRAP_SLAM ) \ E( TRAP_SWORD ) \ E( HAMMER_HANDLE ) \ @@ -232,7 +232,7 @@ namespace TR { EARTHQUAKE , FLOOD , UNK1 , - UNK2 , + STAIRS2SLOPE , UNK3 , UNK4 , EXPLOSION , @@ -277,6 +277,7 @@ namespace TR { SND_INV_PAGE = 115, SND_HEALTH = 116, + SND_EFFECT_8 = 119, SND_DART = 151, SND_SECRET = 173, @@ -629,7 +630,7 @@ namespace TR { } bool isDoor() const { - return (type >= DOOR_1 && type <= DOOR_6) || type == DOOR_LIFT; + return type >= DOOR_1 && type <= DOOR_6; } bool isItem() const { @@ -659,6 +660,16 @@ namespace TR { return isLara() || isEnemy() || isActor(); } + void getAxis(int &dx, int &dz) { + switch (rotation.value / 0x4000) { + case 0 : dx = 0; dz = -1; break; + case 1 : dx = -1; dz = 0; break; + case 2 : dx = 0, dz = 1; break; + case 3 : dx = 1, dz = 0; break; + default : dx = 0; dz = 0; break; + } + } + static Type convToInv(Type type) { switch (type) { case PISTOLS : return INV_PISTOLS; @@ -2174,12 +2185,12 @@ namespace TR { Entity &e = entities[cmd.args]; if (!e.flags.collision) continue; - if (sx != e.x / 1024 || sz != e.z / 1024) continue; - switch (e.type) { case Entity::TRAP_DOOR_1 : case Entity::TRAP_DOOR_2 : case Entity::TRAP_FLOOR : { + if (sx != e.x / 1024 || sz != e.z / 1024) + break; int ey = e.y - (e.type == Entity::TRAP_FLOOR ? 512 : 0); if (ey >= y - 128 && ey < info.floor) info.floor = ey; @@ -2187,9 +2198,26 @@ namespace TR { info.ceiling = ey + (e.type == Entity::TRAP_FLOOR ? 0 : 256); break; } + case Entity::DRAWBRIDGE : { + if (e.flags.active != TR::ACTIVE) continue; + int dirX, dirZ; + e.getAxis(dirX, dirZ); + if ((e.x / 1024 + dirX * 1 == sx && e.z / 1024 + dirZ * 1 == sz) || + (e.x / 1024 + dirX * 2 == sx && e.z / 1024 + dirZ * 2 == sz)) { + int ey = e.y; + if (ey >= y - 128 && ey < info.floor) + info.floor = ey; + if (ey < y - 128 && ey > info.ceiling) + info.ceiling = ey + 256; + } + break; + } case Entity::BRIDGE_0 : case Entity::BRIDGE_1 : case Entity::BRIDGE_2 : { + if (sx != e.x / 1024 || sz != e.z / 1024) + break; + int s = (e.type == Entity::BRIDGE_1) ? 1 : (e.type == Entity::BRIDGE_2) ? 2 : 0; diff --git a/src/lara.h b/src/lara.h index e925911..76cc274 100644 --- a/src/lara.h +++ b/src/lara.h @@ -460,6 +460,8 @@ struct Lara : Character { //reset(5, vec3(73394, 3840, 60758), 0); // level 3b (scion) //reset(20, vec3(57724, 6656, 61941), 90 * DEG2RAD); // level 3b (boulder) //reset(99, vec3(45562, -3328, 63366), 225 * DEG2RAD); // level 7a (flipmap) + //reset(57, vec3(54844, -3328, 53145), 0); // level 8b (bridge switch) + //reset(12, vec3(34236, -2415, 14974), 0); // level 8b (sphinx) //reset(0, vec3(40913, -1012, 42252), PI); // level 8c //reset(10, vec3(90443, 11264 - 256, 114614), PI, STAND_ONWATER); // villa mortal 2 #endif @@ -1639,6 +1641,10 @@ struct Lara : Character { bool needFlip = false; TR::Effect effect = TR::Effect::NONE; + int cameraIndex = -1; + Controller *cameraTarget = NULL; + Camera *camera = (Camera*)level->cameraController; + while (cmdIndex < info.trigCmdCount) { TR::FloorData::TriggerCommand &cmd = info.trigCmd[cmdIndex++]; @@ -1667,8 +1673,6 @@ struct Lara : Character { break; } case TR::Action::CAMERA_SWITCH : { - Camera *camera = (Camera*)level->cameraController; - TR::FloorData::TriggerCommand &cam = info.trigCmd[cmdIndex++]; if (level->cameras[cmd.args].flags.once) break; @@ -1678,11 +1682,14 @@ struct Lara : Character { if (info.trigger == TR::Level::Trigger::SWITCH && info.trigInfo.timer && switchIsDown) break; - {//if (info.trigger == TR::Level::Trigger::SWITCH || cmd.args != camera->viewIndexLast) { + if (info.trigger == TR::Level::Trigger::SWITCH || cmd.args != camera->viewIndexLast) { level->cameras[cmd.args].flags.once |= cam.once; camera->setView(cmd.args, cam.timer == 1 ? EPS : float(cam.timer), cam.speed * 8.0f); } + if (cmd.args == camera->viewIndexLast) + cameraIndex = cmd.args; + break; } case TR::Action::FLOW : @@ -1715,7 +1722,7 @@ struct Lara : Character { needFlip = true; break; case TR::Action::CAMERA_TARGET : - ((Camera*)level->cameraController)->viewTarget = (Controller*)level->entities[cmd.args].controller; + cameraTarget = (Controller*)level->entities[cmd.args].controller; break; case TR::Action::END : game->loadLevel(level->id == TR::LEVEL_10C ? TR::TITLE : TR::LevelID(level->id + 1)); @@ -1759,6 +1766,12 @@ struct Lara : Character { } } + if (cameraTarget && (camera->state == Camera::STATE_STATIC || cameraIndex == -1)) + camera->viewTarget = cameraTarget; + + if (!cameraTarget && cameraIndex > -1) + camera->viewIndex = cameraIndex; + if (needFlip) { level->isFlipped = !level->isFlipped; game->setEffect(effect, 0); @@ -1799,7 +1812,7 @@ struct Lara : Character { TR::Level::FloorInfo info; level->getFloorInfo(e.room, e.x, e.y, e.z, info); - if (stand == STAND_SLIDE || (stand == STAND_AIR && velocity.y > 0) || stand == STAND_GROUND) { + if (stand == STAND_SLIDE || stand == STAND_AIR || stand == STAND_GROUND) { if (e.y + 8 >= info.floor && (abs(info.slantX) > 2 || abs(info.slantZ) > 2)) { if (stand == STAND_AIR) playSound(TR::SND_LANDING, pos, Sound::Flags::PAN); @@ -2444,7 +2457,7 @@ struct Lara : Character { collisionOffset = vec3(0.0f); - if (checkCollisions() || (velocity + collisionOffset).length2() >= 1.0f) + if (checkCollisions() || (velocity + collisionOffset).length2() >= 1.0f) // TODO: stop & smash anim move(); if (getEntity().type != TR::Entity::LARA) { @@ -2482,25 +2495,27 @@ struct Lara : Character { collisionOffset += meshBox.pushOut2D(box); } - if (!canHitAnim()) { - hitDir = -1; - return false; - } - // check enemies & doors - Controller *controller = Controller::first; - do { - TR::Entity &e = controller->getEntity(); + for (int i = 0; i < level->entitiesBaseCount; i++) { + TR::Entity &e = level->entities[i]; + Controller *controller = (Controller*)e.controller; if (e.isEnemy()) { if (e.type != TR::Entity::ENEMY_REX && (!e.flags.active || ((Character*)controller)->health <= 0)) continue; - } else - if (!e.isDoor()) continue; + } else { + if (!e.isDoor() && !(e.type == TR::Entity::DRAWBRIDGE && e.flags.active != TR::ACTIVE)) continue; + + TR::Entity &entity = getEntity(); + if (abs(entity.x - e.x) > 1024 || abs(entity.z - e.z) > 1024 || abs(entity.y - e.y) > 2048) continue; + } + vec3 dir = pos - vec3(0.0f, 128.0f, 0.0f) - controller->pos; vec3 p = dir.rotateY(controller->angle.y); Box box = controller->getBoundingBoxLocal(); + box.expand(vec3(LARA_RADIUS, 0.0f, LARA_RADIUS)); + if (!box.contains(p)) continue; @@ -2516,19 +2531,21 @@ struct Lara : Character { if (e.type == TR::Entity::ENEMY_REX && ((Character*)controller)->health <= 0) return true; - if (e.isDoor()) + if (e.isDoor() || e.type == TR::Entity::DRAWBRIDGE) return true; - // get hit dir - if (hitDir == -1) { - if (health > 0) - playSound(TR::SND_HIT, pos, Sound::PAN); - hitTime = 0.0f; - } + if (canHitAnim()) { + // get hit dir + if (hitDir == -1) { + if (health > 0) + playSound(TR::SND_HIT, pos, Sound::PAN); + hitTime = 0.0f; + } - hitDir = angleQuadrant(dir.rotateY(angle.y + PI * 0.5f).angleY()); - return true; - } while ((controller = controller->next)); + hitDir = angleQuadrant(dir.rotateY(angle.y + PI * 0.5f).angleY()); + return true; + } + }; hitDir = -1; return false; diff --git a/src/level.h b/src/level.h index d572bd8..dac5725 100644 --- a/src/level.h +++ b/src/level.h @@ -205,6 +205,10 @@ struct Level : IGame { sample->setVolume(0.0f, 4.0f); } + if (effect == TR::Effect::STAIRS2SLOPE) { + playSound(TR::SND_EFFECT_8, vec3(), 0); + } + this->effect = effect; this->effectTimer = 0.0f; } @@ -393,6 +397,9 @@ struct Level : IGame { case TR::Entity::TRAP_DARTGUN : entity.controller = new TrapDartgun(this, i); break; + case TR::Entity::DRAWBRIDGE : + entity.controller = new Drawbridge(this, i); + break; case TR::Entity::BLOCK_1 : case TR::Entity::BLOCK_2 : case TR::Entity::BLOCK_3 : @@ -400,7 +407,7 @@ struct Level : IGame { entity.controller = new Block(this, i); break; case TR::Entity::MOVING_BLOCK : - entity.controller = new MovingBlock(this, i); + entity.controller = new MovingBlock(this, i); break; case TR::Entity::TRAP_CEILING_1 : case TR::Entity::TRAP_CEILING_2 : @@ -873,8 +880,9 @@ struct Level : IGame { type = Shader::MIRROR; if (type == Shader::SPRITE) { - float alpha = (entity.type == TR::Entity::SMOKE || entity.type == TR::Entity::WATER_SPLASH) ? 0.75f : 1.0f; - setRoomParams(roomIndex, type, 0.5f, intensityf(lum), controller->specular, alpha, isModel ? !mesh->models[entity.modelIndex - 1].opaque : true); + float alpha = (entity.type == TR::Entity::SMOKE || entity.type == TR::Entity::WATER_SPLASH) ? 0.75f : 1.0; + float diffuse = entity.isItem() ? 1.0f : 0.5f; + setRoomParams(roomIndex, type, diffuse, intensityf(lum), controller->specular, alpha, isModel ? !mesh->models[entity.modelIndex - 1].opaque : true); } else setRoomParams(roomIndex, type, 1.0f, intensityf(lum), controller->specular, 1.0f, isModel ? !mesh->models[entity.modelIndex - 1].opaque : true); diff --git a/src/trigger.h b/src/trigger.h index 4992703..1d5698d 100644 --- a/src/trigger.h +++ b/src/trigger.h @@ -498,6 +498,22 @@ struct Bridge : Controller { } }; +struct Drawbridge : Controller { + enum { + STATE_UP, + STATE_DOWN, + }; + + Drawbridge(IGame *game, int entity) : Controller(game, entity) { + getEntity().flags.collision = true; + } + + virtual void update() { + updateAnimation(true); + animation.setState(isActive() ? STATE_DOWN : STATE_UP); + } +}; + struct Crystal : Controller { Texture *environment;