1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-17 18:36:43 +02:00

#8 fix underwater sound for flipped rooms; #22 add lightning bolt effect;

This commit is contained in:
XProger
2017-10-08 01:11:03 +03:00
parent 09b48b4b50
commit 1b1a073a72
8 changed files with 156 additions and 31 deletions

View File

@@ -60,7 +60,7 @@ struct Camera : ICamera {
}
virtual int getRoomIndex() const {
return room;
return (level->isFlipped && level->rooms[room].alternateRoom > -1) ? level->rooms[room].alternateRoom : room;
}
virtual void checkRoom() {

View File

@@ -764,7 +764,7 @@ namespace TR {
opaque = true;
if (type == SWITCH || type == SWITCH_WATER)
opaque = true;
if (type == PUZZLE_HOLE_1) // LEVEL3A cogs
if (type == PUZZLE_HOLE_1 || type == LIGHTNING) // LEVEL3A cogs
opaque = false;
}
};

View File

@@ -228,6 +228,7 @@ struct Lara : Character {
TR::Entity::Type usedKey;
TR::Entity *pickupEntity;
KeyHole *keyHole;
Lightning *lightning;
int roomPrev; // water out from room
vec2 rotFactor;
@@ -410,6 +411,9 @@ struct Lara : Character {
damageTime = LARA_DAMAGE_TIME;
hitTime = 0.0f;
keyHole = NULL;
lightning = NULL;
getEntity().flags.active = 1;
initMeshOverrides();
@@ -1341,10 +1345,11 @@ struct Lara : Character {
Character::hit(damage, enemy, hitType);
switch (hitType) {
case TR::HIT_BLADE : addBloodBlade(); break;
case TR::HIT_SPIKES : addBloodSpikes(); break;
case TR::HIT_SLAM : addBloodSlam(enemy); break;
default : ;
case TR::HIT_BLADE : addBloodBlade(); break;
case TR::HIT_SPIKES : addBloodSpikes(); break;
case TR::HIT_SLAM : addBloodSlam(enemy); break;
case TR::HIT_LIGHTNING : lightning = (Lightning*)enemy; break;
default : ;
}
if (health > 0.0f)
@@ -2321,8 +2326,17 @@ struct Lara : Character {
if (Input::state[cWeapon]) input |= WEAPON;
// scion debug (TODO: remove)
if (Input::down[ikP] && level->id == TR::LEVEL_3B)
reset(5, vec3(73394, 3840, 60758), 0); // level 3b (scion)
if (Input::down[ikP]) {
switch (level->id) {
case TR::LEVEL_3B :
reset(5, vec3(73394, 3840, 60758), 0); // level 3b (scion)
break;
case TR::LEVEL_4 :
reset(18, vec3(34914, 11008, 41315), 90 * DEG2RAD); // main hall
break;
default : game->playSound(TR::SND_NO, pos, Sound::PAN);
}
}
// analog control
rotFactor = vec2(1.0f);
@@ -2470,7 +2484,7 @@ struct Lara : Character {
switch (stand) {
case STAND_AIR :
velocity.y += (velocity.y >= 128.0f ? 30.0f : GRAVITY) * Core::deltaTime;
if (velocity.y >= 154.0f)
if (velocity.y >= 154.0f && state == STATE_FALL)
game->playSound(TR::SND_SCREAM, pos, Sound::PAN);
/*
if (state == STATE_FALL || state == STATE_FAST_DIVE) {
@@ -2636,7 +2650,14 @@ struct Lara : Character {
}
};
hitDir = -1;
if (lightning && lightning->flash && !lightning->armed) {
if (hitDir == -1)
hitTime = 0.0f;
hitDir = int(randf() * 4);
} else {
hitDir = -1;
lightning = NULL;
}
return false;
}

View File

@@ -504,6 +504,8 @@ struct Level : IGame {
static void fillCallback(int id, int width, int height, int tileX, int tileY, void *userData, void *data) {
static const uint32 barColor[UI::BAR_MAX][25] = {
// flash bar
{ 0x00000000, 0xFFA20058, 0xFFFFFFFF, 0xFFA20058, 0x00000000 },
// health bar
{ 0xFF2C5D71, 0xFF5E81AE, 0xFF2C5D71, 0xFF1B4557, 0xFF16304F },
// oxygen bar
@@ -548,6 +550,7 @@ struct Level : IGame {
uvCount = 4;
switch (id) {
case UI::BAR_FLASH :
case UI::BAR_HEALTH :
case UI::BAR_OXYGEN :
case UI::BAR_OPTION :
@@ -661,14 +664,10 @@ struct Level : IGame {
tiles->add(uv, texIdx++);
}
// add health bar
tiles->add(short4(2048, 2048, 2048, 2048 + 4), texIdx++);
// add oxygen bar
tiles->add(short4(4096, 4096, 4096, 4096 + 4), texIdx++);
// add option bar
tiles->add(short4(8192, 8192, 8192 + 4, 8192 + 4), texIdx++);
// add white color
tiles->add(short4(2048, 2048, 2048, 2048), texIdx++);
// add common textures
const short2 bar[UI::BAR_MAX] = { {0, 4}, {0, 4}, {0, 4}, {4, 4}, {0, 0} };
for (int i = 0; i < UI::BAR_MAX; i++)
tiles->add(short4(i * 32, 4096, i * 32 + bar[i].x, 4096 + bar[i].y), texIdx++);
// get result texture
atlas = tiles->pack();
@@ -993,10 +992,19 @@ struct Level : IGame {
setupBinding();
}
// TODO: opqque/transparent pass for rooms and entities
void renderEntities(bool opaque) {
for (int i = 0; i < level.entitiesCount; i++) {
int modelIndex = level.entities[i].modelIndex;
if ((modelIndex < 0 && !opaque) || (modelIndex > 0 && mesh->models[modelIndex - 1].opaque == opaque))
renderEntity(level.entities[i]);
}
}
void renderEntities() {
PROFILE_MARKER("ENTITIES");
for (int i = 0; i < level.entitiesCount; i++)
renderEntity(level.entities[i]);
renderEntities(true);
renderEntities(false);
for (int i = 0; i < level.entitiesCount; i++) {
TR::Entity &entity = level.entities[i];

View File

@@ -5,8 +5,8 @@
#include "format.h"
TR::ObjectTexture barTile[4 /* UI::BAR_MAX */];
TR::ObjectTexture &whiteTile = barTile[3];
TR::ObjectTexture barTile[5 /* UI::BAR_MAX */];
TR::ObjectTexture &whiteTile = barTile[4]; // BAR_WHITE
struct MeshRange {
int iStart;

View File

@@ -353,7 +353,7 @@ struct Block : Controller {
pos.y += Core::deltaTime * velocity * 30.0f;
if (pos.y >= info.floor) {
velocity = 0.0f;
pos.y = info.floor;
pos.y = float(info.floor);
game->setEffect(this, TR::Effect::FLOOR_SHAKE);
game->playSound(TR::SND_BOULDER, pos, Sound::PAN);
deactivate(true);
@@ -839,7 +839,7 @@ struct ThorHammer : Controller {
#define LIGHTNING_DAMAGE 400
struct Lightning : Controller {
Basis target;
vec3 target;
float timer;
bool flash;
bool armed;
@@ -850,6 +850,8 @@ struct Lightning : Controller {
if (isActive()) {
timer -= Core::deltaTime;
Character *lara = (Character*)level->laraController;
if (timer <= 0.0f) {
if (flash) {
level->isFlipped = false;
@@ -861,17 +863,15 @@ struct Lightning : Controller {
flash = true;
timer = 20.0f / 30.0f;
Character *lara = (Character*)level->laraController;
bool hasTargets = getModel()->mCount > 1; // LEVEL4 has, LEVEL10C not
if ((lara->pos - pos).length() < (hasTargets ? 2560.0f : 1024.0f)) {
lara->hit(LIGHTNING_DAMAGE, this, TR::HIT_LIGHTNING);
armed = false;
} else if (!hasTargets) {
//
target = pos + vec3(0.0f, 1024.0f, 0.0f);
} else
animation.getJoints(getMatrix(), int(randf() * 5), false, &target);
target = animation.getJoints(getMatrix(), 1 + int(randf() * 5)).pos;
}
game->playSound(TR::SND_LIGHTNING, pos, Sound::PAN);
}
@@ -883,10 +883,105 @@ struct Lightning : Controller {
}
}
void divide(vec3 *points, int L, int R, float spread) {
int M = (L + R) / 2;
if (M == L || M == R) return;
points[M] = (points[L] + points[R]) * 0.5f + (vec3(randf(), randf(), randf()) - 0.5f) * spread;
spread *= 0.5f;
divide(points, L, M, spread);
divide(points, M, R, spread);
}
short4 toCoord(const vec3 &v, int16 joint) {
return short4(int16(v.x), int16(v.y), int16(v.z), joint);
}
void setVertex(Vertex &v, const vec3 &coord, int16 joint, int idx) {
v.coord = toCoord(coord, joint);
v.normal = { 0, -1, 0, 0 };
v.texCoord = { barTile[0].texCoord[idx].x, barTile[0].texCoord[idx].y, 32767, 32767 };
v.param = { 0, 0, 0, 0 };
v.color = { 255, 255, 255, 255 };
}
void renderPolyline(const vec3 &start, const vec3 &end, float width, float spread, int depth) {
vec3 points[9];
points[0] = start;
points[8] = end;
divide(points, 0, 8, spread);
Index indices[(COUNT(points) - 1) * 6];
Vertex vertices[COUNT(points) * 2];
int iCount = 0;
int vCount = 0;
int count = COUNT(points);
// build indices
for (int i = 0; i < count - 1; i++) {
indices[iCount++] = vCount;
indices[iCount++] = vCount + 1;
indices[iCount++] = vCount + 2;
indices[iCount++] = vCount + 1;
indices[iCount++] = vCount + 3;
indices[iCount++] = vCount + 2;
vCount += 2;
}
vCount += 2;
ASSERT(iCount == (count - 1) * 6);
ASSERT(vCount == count * 2);
// build vertices
vec3 dir = Core::mViewInv.dir.xyz;
vCount = 0;
vec3 n;
for (int i = 0; i < count; i++) {
if (i < count - 1)
n = dir.cross(points[i + 1] - points[i]).normal() * width;
setVertex(vertices[vCount++], points[i] - n, 0, 0);
setVertex(vertices[vCount++], points[i] + n, 0, 3);
}
ASSERT(vCount == count * 2);
game->getMesh()->renderBuffer(indices, iCount, vertices, vCount);
if (depth > 0) {
for (int i = 0; i < 2; i++) {
vec3 a = points[int(randf() * (count - 1))];
vec3 b = a;
b.x += (randf() - 0.5f) * spread;
b.y = points[count - 1].y;
b.z += (randf() - 0.5f) * spread;
renderPolyline(a, b, width * 0.75f, spread * 0.5f, depth - 1);
}
}
}
virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) {
Controller::render(frustum, mesh, type, caustics);
if (!flash) return;
// TODO
if (!armed)
target = game->getLara()->pos;
Basis b = animation.getJoints(getMatrix(), 0);
b.rot = quat(0, 0, 0, 1);
game->setShader(Core::pass, Shader::FLASH, false, false);
Core::active.shader->setParam(uMaterial, vec4(0.0f, 0.0f, 0.0f, 1.0f));
Core::active.shader->setParam(uBasis, b);
Core::setCulling(cfNone);
Core::setBlending(bmAdd);
Core::setDepthWrite(false);
renderPolyline(vec3(0.0f), target - b.pos, 64.0f, 512.0f, 1);
Core::setDepthWrite(true);
Core::setBlending(bmNone);
Core::setCulling(cfFront);
}
};

View File

@@ -204,6 +204,7 @@ namespace UI {
#define MAX_CHARS DYN_MESH_QUADS
enum BarType {
BAR_FLASH,
BAR_HEALTH,
BAR_OXYGEN,
BAR_OPTION,

View File

@@ -204,8 +204,8 @@ struct vec2 {
struct vec3 {
union {
struct { vec2 xy; };
struct { float x, y, z; };
struct { vec2 xy; };
};
vec3() {}
@@ -271,9 +271,9 @@ struct vec3 {
struct vec4 {
union {
struct { float x, y, z, w; };
struct { vec2 xy, zw; };
struct { vec3 xyz; };
struct { float x, y, z, w; };
};
vec4() {}