mirror of
https://github.com/XProger/OpenLara.git
synced 2025-03-13 23:59:41 +01:00
#13 trap floors & doors; fix debug render
This commit is contained in:
parent
ddf9ae25cc
commit
36fce871cb
16
src/camera.h
16
src/camera.h
@ -21,7 +21,7 @@ struct Camera : Controller {
|
||||
int actTargetEntity, actCamera;
|
||||
|
||||
Camera(TR::Level *level, Lara *owner) : Controller(level, owner ? owner->entity : 0), owner(owner), frustum(new Frustum()), timer(0.0f), actTargetEntity(-1), actCamera(-1) {
|
||||
fov = 80.0f;
|
||||
fov = 65.0f;
|
||||
znear = 128;
|
||||
zfar = 100.0f * 1024.0f;
|
||||
angleAdv = vec3(0.0f);
|
||||
@ -130,27 +130,27 @@ struct Camera : Controller {
|
||||
|
||||
if (actCamera <= -1) {
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(room, (int)pos.x, (int)pos.z, info);
|
||||
level->getFloorInfo(room, (int)pos.x, (int)pos.y, (int)pos.z, info);
|
||||
|
||||
int lastRoom = room;
|
||||
|
||||
if (info.roomNext != 255)
|
||||
room = info.roomNext;
|
||||
|
||||
if (pos.y < info.ceiling) {
|
||||
if (pos.y < info.roomCeiling) {
|
||||
if (info.roomAbove != 255)
|
||||
room = info.roomAbove;
|
||||
else
|
||||
if (info.ceiling != 0xffff8100)
|
||||
pos.y = (float)info.ceiling;
|
||||
if (info.roomCeiling != 0xffff8100)
|
||||
pos.y = (float)info.roomCeiling;
|
||||
}
|
||||
|
||||
if (pos.y > info.floor) {
|
||||
if (pos.y > info.roomFloor) {
|
||||
if (info.roomBelow != 255)
|
||||
room = info.roomBelow;
|
||||
else
|
||||
if (info.floor != 0xffff8100)
|
||||
pos.y = (float)info.floor;
|
||||
if (info.roomFloor != 0xffff8100)
|
||||
pos.y = (float)info.roomFloor;
|
||||
}
|
||||
|
||||
// play underwater sound when camera goes under water
|
||||
|
@ -41,19 +41,19 @@ struct Character : Controller {
|
||||
virtual void checkRoom() {
|
||||
TR::Level::FloorInfo info;
|
||||
TR::Entity &e = getEntity();
|
||||
level->getFloorInfo(e.room, e.x, e.z, info);
|
||||
level->getFloorInfo(e.room, e.x, e.y, e.z, info);
|
||||
|
||||
if (info.roomNext != 0xFF)
|
||||
e.room = info.roomNext;
|
||||
|
||||
if (info.roomBelow != 0xFF && e.y > info.floor)
|
||||
e.room = info.roomBelow;
|
||||
if (info.roomBelow != 0xFF && e.y > info.roomFloor)
|
||||
e.room = info.roomBelow;
|
||||
|
||||
if (info.roomAbove != 0xFF && e.y <= info.ceiling) {
|
||||
if (info.roomAbove != 0xFF && e.y <= info.roomCeiling) {
|
||||
if (stand == STAND_UNDERWATER && !level->rooms[info.roomAbove].flags.water) {
|
||||
stand = STAND_ONWATER;
|
||||
velocity.y = 0;
|
||||
pos.y = float(info.ceiling);
|
||||
pos.y = float(info.roomCeiling);
|
||||
updateEntity();
|
||||
} else
|
||||
if (stand != STAND_ONWATER)
|
||||
|
@ -24,13 +24,14 @@ struct Controller {
|
||||
int mCount;
|
||||
|
||||
struct ActionCommand {
|
||||
int emitter;
|
||||
TR::Action action;
|
||||
int value;
|
||||
float timer;
|
||||
ActionCommand *next;
|
||||
|
||||
ActionCommand() {}
|
||||
ActionCommand(TR::Action action, int value, float timer, ActionCommand *next = NULL) : action(action), value(value), timer(timer), next(next) {}
|
||||
ActionCommand(int emitter, TR::Action action, int value, float timer, ActionCommand *next = NULL) : emitter(emitter), action(action), value(value), timer(timer), next(next) {}
|
||||
} *actionCommand;
|
||||
|
||||
Controller(TR::Level *level, int entity) : level(level), entity(entity), animation(level, getModel()), state(animation.state), actionCommand(NULL), mCount(0), meshes(NULL) {
|
||||
@ -223,10 +224,10 @@ struct Controller {
|
||||
sz = pz / 1024 * 1024 + 512;
|
||||
|
||||
if (lr != room || lx != sx || lz != sz) {
|
||||
level->getFloorInfo(room, sx, sz, info);
|
||||
level->getFloorInfo(room, sx, py, sz, info);
|
||||
if (info.roomNext != 0xFF) {
|
||||
room = info.roomNext;
|
||||
level->getFloorInfo(room, sx, sz, info);
|
||||
level->getFloorInfo(room, sx, py, sz, info);
|
||||
}
|
||||
lr = room;
|
||||
lx = sx;
|
||||
@ -234,9 +235,9 @@ struct Controller {
|
||||
}
|
||||
|
||||
if (isCamera) {
|
||||
if (py > info.floor && info.roomBelow != 0xFF)
|
||||
if (py > info.roomFloor && info.roomBelow != 0xFF)
|
||||
room = info.roomBelow;
|
||||
else if (py < info.ceiling && info.roomAbove != 0xFF)
|
||||
else if (py < info.roomCeiling && info.roomAbove != 0xFF)
|
||||
room = info.roomAbove;
|
||||
else if (py > info.floor || py < info.ceiling) {
|
||||
int minX = px / 1024 * 1024;
|
||||
@ -248,14 +249,14 @@ struct Controller {
|
||||
dir = (pos - from).normal();
|
||||
}
|
||||
} else {
|
||||
if (py > info.floor) {
|
||||
if (py > info.roomFloor) {
|
||||
if (info.roomBelow != 0xFF)
|
||||
room = info.roomBelow;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (py < info.ceiling) {
|
||||
if (py < info.roomCeiling) {
|
||||
if (info.roomAbove != 0xFF)
|
||||
room = info.roomAbove;
|
||||
else
|
||||
@ -277,45 +278,7 @@ struct Controller {
|
||||
if (rand() % 10 <= 6) return;
|
||||
playSound(TR::SND_BUBBLE, pos, Sound::Flags::PAN);
|
||||
}
|
||||
/*
|
||||
void collide() {
|
||||
TR::Entity &entity = getEntity();
|
||||
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(entity.room, entity.x, entity.z, info);
|
||||
|
||||
if (info.roomNext != 0xFF)
|
||||
entity.room = info.roomNext;
|
||||
|
||||
if (entity.y > info.floor) {
|
||||
if (info.roomBelow == 0xFF) {
|
||||
if (entity.y > info.floor) {
|
||||
entity.y = info.floor;
|
||||
pos.y = entity.y;
|
||||
velocity.y = 0.0f;
|
||||
}
|
||||
} else
|
||||
entity.room = info.roomBelow;
|
||||
}
|
||||
|
||||
int height = getHeight();
|
||||
if (entity.y - height < info.ceiling) {
|
||||
if (info.roomAbove == 0xFF) {
|
||||
pos.y = entity.y = info.ceiling + height;
|
||||
if (velocity.y < 0.0f)
|
||||
velocity.y = GRAVITY;
|
||||
} else {
|
||||
if (stand == STAND_UNDERWATER && !level->rooms[info.roomAbove].flags.water) {
|
||||
stand = STAND_ONWATER;
|
||||
velocity.y = 0;
|
||||
pos.y = info.ceiling;
|
||||
} else
|
||||
if (stand != STAND_ONWATER && entity.y < info.ceiling)
|
||||
entity.room = info.roomAbove;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
void activateNext() { // activate next entity (for triggers)
|
||||
if (!actionCommand || !actionCommand->next) {
|
||||
actionCommand = NULL;
|
||||
@ -480,7 +443,7 @@ struct Controller {
|
||||
|
||||
if (TR::castShadow(entity.type)) {
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(entity.room, entity.x, entity.z, info, true);
|
||||
level->getFloorInfo(entity.room, entity.x, entity.y, entity.z, info);
|
||||
renderShadow(mesh, vec3(float(entity.x), info.floor - 16.0f, float(entity.z)), box.center(), box.size() * 0.8f, angle.y);
|
||||
}
|
||||
}
|
||||
|
156
src/debug.h
156
src/debug.h
@ -184,85 +184,72 @@ namespace Debug {
|
||||
|
||||
namespace Level {
|
||||
|
||||
void debugFloor(const TR::Level &level, int roomIndex, int x, int z) {
|
||||
void debugFloor(const TR::Level &level, int roomIndex, int x, int y, int z) {
|
||||
TR::Level::FloorInfo info;
|
||||
level.getFloorInfo(roomIndex, x, z, info);
|
||||
level.getFloorInfo(roomIndex, x, y, z, info);
|
||||
|
||||
vec3 f = vec3(x, info.floor, z);
|
||||
vec3 c = vec3(x, info.ceiling, z);
|
||||
vec3 vf[4] = { f, f + vec3(1024, 0, 0), f + vec3(1024, 0, 1024), f + vec3(0, 0, 1024) };
|
||||
vec3 vc[4] = { c, c + vec3(1024, 0, 0), c + vec3(1024, 0, 1024), c + vec3(0, 0, 1024) };
|
||||
vec3 rf[4], rc[4], f[4], c[4];
|
||||
|
||||
|
||||
int sx = 256 * info.slantX;
|
||||
int sz = 256 * info.slantZ;
|
||||
int offsets[4][2] = { { 1, 1 }, { 1023, 1 }, { 1023, 1023 }, { 1, 1023 } };
|
||||
|
||||
if (sx > 0) {
|
||||
vf[0].y += sx;
|
||||
vf[3].y += sx;
|
||||
} else {
|
||||
vf[1].y -= sx;
|
||||
vf[2].y -= sx;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
level.getFloorInfo(roomIndex, x + offsets[i][0], y, z + offsets[i][1], info);
|
||||
rf[i] = vec3( x + offsets[i][0], info.roomFloor - 4, z + offsets[i][1] );
|
||||
rc[i] = vec3( x + offsets[i][0], info.roomCeiling + 4, z + offsets[i][1] );
|
||||
f[i] = vec3( x + offsets[i][0], info.floor - 4, z + offsets[i][1] );
|
||||
c[i] = vec3( x + offsets[i][0], info.ceiling + 4, z + offsets[i][1] );
|
||||
if (info.roomBelow == 0xFF) rf[i].y = f[i].y;
|
||||
if (info.roomAbove == 0xFF) rc[i].y = c[i].y;
|
||||
}
|
||||
|
||||
if (sz > 0) {
|
||||
vf[0].y += sz;
|
||||
vf[1].y += sz;
|
||||
} else {
|
||||
vf[3].y -= sz;
|
||||
vf[2].y -= sz;
|
||||
}
|
||||
/*
|
||||
} else { // ceiling
|
||||
if (sx < 0) {
|
||||
p[0].y += sx;
|
||||
p[3].y += sx;
|
||||
} else {
|
||||
p[1].y -= sx;
|
||||
p[2].y -= sx;
|
||||
}
|
||||
|
||||
if (sz > 0) {
|
||||
p[0].y -= sz;
|
||||
p[1].y -= sz;
|
||||
} else {
|
||||
p[3].y += sz;
|
||||
p[2].y += sz;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for (int i = 0; i < 5; i++)
|
||||
glVertex3fv((GLfloat*)&vf[i % 4]);
|
||||
glEnd();
|
||||
|
||||
glColor3f(1, 0, 0);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for (int i = 0; i < 5; i++)
|
||||
glVertex3fv((GLfloat*)&vc[i % 4]);
|
||||
glEnd();
|
||||
|
||||
if (info.roomNext != 0xFF) {
|
||||
glColor4f(0.0f, 0.0f, 1.0f, 0.5f);
|
||||
glColor4f(0.0f, 0.0f, 1.0f, 0.1f);
|
||||
glBegin(GL_QUADS);
|
||||
for (int i = 3; i >= 0; i--)
|
||||
glVertex3fv((GLfloat*)&vf[i]);
|
||||
glVertex3fv((GLfloat*)&f[3]);
|
||||
glVertex3fv((GLfloat*)&f[2]);
|
||||
glVertex3fv((GLfloat*)&f[1]);
|
||||
glVertex3fv((GLfloat*)&f[0]);
|
||||
glEnd();
|
||||
} else {
|
||||
|
||||
glColor4f(0.0f, 1.0f, 0.0f, 0.1f);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex3fv((GLfloat*)&f[3]);
|
||||
glVertex3fv((GLfloat*)&f[2]);
|
||||
glVertex3fv((GLfloat*)&f[1]);
|
||||
glVertex3fv((GLfloat*)&f[0]);
|
||||
glEnd();
|
||||
|
||||
if (info.trigCmdCount > 0)
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
else
|
||||
glColor4f(0.0f, 1.0f, 0.0f, 0.25f);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for (int i = 0; i < 5; i++)
|
||||
glVertex3fv((GLfloat*)&rf[i % 4]);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 0.1f);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex3fv((GLfloat*)&c[0]);
|
||||
glVertex3fv((GLfloat*)&c[1]);
|
||||
glVertex3fv((GLfloat*)&c[2]);
|
||||
glVertex3fv((GLfloat*)&c[3]);
|
||||
glEnd();
|
||||
|
||||
if (info.roomAbove != 0xFF) {
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
glBegin(GL_QUADS);
|
||||
for (int i = 3; i >= 0; i--) {
|
||||
vec3 v = vf[i];
|
||||
v.y -= 32.0f;
|
||||
glVertex3fv((GLfloat*)&v);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
if (info.trigCmdCount > 0)
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
else
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 0.25f);
|
||||
glBegin(GL_LINE_STRIP);
|
||||
for (int i = 0; i < 5; i++)
|
||||
glVertex3fv((GLfloat*)&rc[i % 4]);
|
||||
glEnd();
|
||||
|
||||
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
/*
|
||||
if (boxIndex == 0xFFFF) {
|
||||
glBegin(GL_LINES);
|
||||
@ -292,37 +279,14 @@ namespace Debug {
|
||||
} while (!(o++)->end);
|
||||
}
|
||||
|
||||
void debugSectors(const TR::Level &level, const vec3 &pos, int roomIndex) {
|
||||
void sectors(const TR::Level &level, int roomIndex, int y) {
|
||||
TR::Room &room = level.rooms[roomIndex];
|
||||
|
||||
vec3 p = (pos - vec3(room.info.x, 0, room.info.z)) * vec3(1.0f / 1024.0f, 1, 1.0f / 1024.0f);
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
// glDisable(GL_DEPTH_TEST);
|
||||
for (int z = 0; z < room.zSectors; z++)
|
||||
for (int x = 0; x < room.xSectors; x++) {
|
||||
TR::Room::Sector &s = room.sectors[x * room.zSectors + z];
|
||||
float floor = s.floor * 256;
|
||||
/*
|
||||
if (s.boxIndex < 0xFFFF) {
|
||||
auto &b = level.boxes[s.boxIndex];
|
||||
// floor = b.floor;
|
||||
}
|
||||
*/
|
||||
vec3 f(x * 1024 + room.info.x, floor - 1, z * 1024 + room.info.z);
|
||||
vec3 c(x * 1024 + room.info.x, s.ceiling * 256 + 1, z * 1024 + room.info.z);
|
||||
|
||||
bool current = (int)p.x == x && (int)p.z == z;
|
||||
debugFloor(level, roomIndex, room.info.x + x * 1024, room.info.z + z * 1024);
|
||||
/*
|
||||
if (current && s.boxIndex != 0xFFFF && level.boxes[s.boxIndex].overlap != 0xFFFF) {
|
||||
glColor4f(0.0f, 1.0f, 0.0f, 0.25f);
|
||||
debugBox(level.boxes[s.boxIndex]);
|
||||
glColor4f(1.0f, 1.0f, 0.0f, 0.25f);
|
||||
debugOverlaps(level, s.boxIndex);
|
||||
}
|
||||
*/
|
||||
}
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
for (int x = 0; x < room.xSectors; x++)
|
||||
debugFloor(level, roomIndex, room.info.x + x * 1024, y, room.info.z + z * 1024);
|
||||
// glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void rooms(const TR::Level &level, const vec3 &pos, int roomIndex) {
|
||||
@ -334,7 +298,7 @@ namespace Debug {
|
||||
|
||||
if (i == roomIndex) {
|
||||
//if (lara->insideRoom(Core::viewPos, i)) {
|
||||
debugSectors(level, pos, i);
|
||||
// sectors(level, i);
|
||||
glColor3f(0, 1, 0);
|
||||
} else
|
||||
glColor3f(1, 1, 1);
|
||||
@ -526,7 +490,7 @@ namespace Debug {
|
||||
Debug::Draw::text(vec2(16, 48), vec4(1.0f), buf);
|
||||
|
||||
TR::Level::FloorInfo info;
|
||||
level.getFloorInfo(entity.room, entity.x, entity.z, info);
|
||||
level.getFloorInfo(entity.room, entity.x, entity.y, entity.z, info);
|
||||
sprintf(buf, "floor = %d, roomBelow = %d, roomAbove = %d, height = %d", info.floorIndex, info.roomBelow, info.roomAbove, info.floor - info.ceiling);
|
||||
Debug::Draw::text(vec2(16, 64), vec4(1.0f), buf);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ struct Enemy : Character {
|
||||
vec3 p = pos;
|
||||
pos += velocity * Core::deltaTime * 30.0f;
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(getRoomIndex(), (int)pos.x, (int)pos.z, info, true);
|
||||
level->getFloorInfo(getRoomIndex(), (int)pos.x, (int)pos.y, (int)pos.z, info);
|
||||
if (pos.y - info.floor > 1024) {
|
||||
pos = p;
|
||||
return;
|
||||
|
81
src/format.h
81
src/format.h
@ -420,7 +420,7 @@ namespace TR {
|
||||
angle rotation;
|
||||
int16 intensity;
|
||||
union {
|
||||
struct { uint16 unused:7, clear:1, invisible:1, active:5, unused2:1, rendered:1; };
|
||||
struct { uint16 unused:7, clear:1, invisible:1, active:5, collision:1, rendered:1; };
|
||||
uint16 value;
|
||||
} flags;
|
||||
// not exists in file
|
||||
@ -736,9 +736,10 @@ namespace TR {
|
||||
};
|
||||
|
||||
struct FloorInfo {
|
||||
int roomFloor, roomCeiling;
|
||||
int roomNext, roomBelow, roomAbove;
|
||||
int floor, ceiling;
|
||||
int slantX, slantZ;
|
||||
int roomNext, roomBelow, roomAbove;
|
||||
int floorIndex;
|
||||
int kill;
|
||||
int trigCmdCount;
|
||||
@ -1013,15 +1014,17 @@ namespace TR {
|
||||
return room.sectors[sx * room.zSectors + sz];
|
||||
}
|
||||
|
||||
void getFloorInfo(int roomIndex, int x, int z, FloorInfo &info, bool actual = false, int prevRoom = 0xFF) const {
|
||||
void getFloorInfo(int roomIndex, int x, int y, int z, FloorInfo &info) const {
|
||||
int dx, dz;
|
||||
Room::Sector &s = getSector(roomIndex, x, z, dx, dz);
|
||||
|
||||
info.floor = 256 * (int)s.floor;
|
||||
info.ceiling = 256 * (int)s.ceiling;
|
||||
info.roomFloor = 256 * s.floor;
|
||||
info.roomCeiling = 256 * s.ceiling;
|
||||
info.floor = info.roomFloor;
|
||||
info.ceiling = info.roomCeiling;
|
||||
info.slantX = 0;
|
||||
info.slantZ = 0;
|
||||
info.roomNext = 255;
|
||||
info.roomNext = 0xFF;
|
||||
info.roomBelow = s.roomBelow;
|
||||
info.roomAbove = s.roomAbove;
|
||||
info.floorIndex = s.floorIndex;
|
||||
@ -1029,23 +1032,60 @@ namespace TR {
|
||||
info.trigger = Trigger::ACTIVATE;
|
||||
info.trigCmdCount = 0;
|
||||
|
||||
if (actual) {
|
||||
if (info.roomBelow != 0xFF && info.roomBelow != prevRoom) {
|
||||
FloorInfo tmp;
|
||||
getFloorInfo(info.roomBelow, x, z, tmp, true, roomIndex);
|
||||
info.floor = tmp.floor;
|
||||
}
|
||||
Room::Sector *sBelow = &s;
|
||||
while (sBelow->roomBelow != 0xFF) sBelow = &getSector(sBelow->roomBelow, x, z, dx, dz);
|
||||
info.floor = 256 * sBelow->floor;
|
||||
parseFloorData(info, sBelow->floorIndex, dx, dz);
|
||||
|
||||
if (info.roomAbove != 0xFF && info.roomAbove != prevRoom) {
|
||||
FloorInfo tmp;
|
||||
getFloorInfo(info.roomAbove, x, z, tmp, true, roomIndex);
|
||||
info.ceiling = tmp.ceiling;
|
||||
if (info.roomNext == 0xFF) {
|
||||
Room::Sector *sAbove = &s;
|
||||
while (sAbove->roomAbove != 0xFF) sAbove = &getSector(sAbove->roomAbove, x, z, dx, dz);
|
||||
if (sAbove != sBelow) {
|
||||
info.ceiling = 256 * sAbove->ceiling;
|
||||
parseFloorData(info, sAbove->floorIndex, dx, dz);
|
||||
}
|
||||
} else {
|
||||
int tmp = info.roomNext;
|
||||
getFloorInfo(tmp, x, y, z, info);
|
||||
info.roomNext = tmp;
|
||||
}
|
||||
|
||||
if (!s.floorIndex) return;
|
||||
// entities collide
|
||||
if (info.trigCmdCount) {
|
||||
int sx = x / 1024;
|
||||
int sz = z / 1024;
|
||||
|
||||
FloorData *fd = &floors[s.floorIndex];
|
||||
for (int i = 0; i < info.trigCmdCount; i++) {
|
||||
FloorData::TriggerCommand cmd = info.trigCmd[i];
|
||||
if (cmd.action != Action::ACTIVATE) continue;
|
||||
|
||||
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::DOOR_FLOOR_1 :
|
||||
case Entity::DOOR_FLOOR_2 :
|
||||
case Entity::TRAP_FLOOR : {
|
||||
int ey = e.y - (e.type == Entity::TRAP_FLOOR ? 512 : 0);
|
||||
if (ey >= y - 128 && ey < info.floor)
|
||||
info.floor = ey;
|
||||
if (ey < y - 128 && ey > info.ceiling)
|
||||
info.ceiling = ey + (e.type == Entity::TRAP_FLOOR ? 256 : 0);
|
||||
break;
|
||||
}
|
||||
|
||||
default : ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void parseFloorData(FloorInfo &info, int floorIndex, int dx, int dz) const {
|
||||
if (!floorIndex) return;
|
||||
|
||||
FloorData *fd = &floors[floorIndex];
|
||||
FloorData::Command cmd;
|
||||
|
||||
do {
|
||||
@ -1083,7 +1123,7 @@ namespace TR {
|
||||
ASSERT(info.trigCmdCount < MAX_TRIGGER_COMMANDS);
|
||||
trigCmd = (*fd++).triggerCmd; // trigger action
|
||||
info.trigCmd[info.trigCmdCount++] = trigCmd;
|
||||
} while (!trigCmd.end);
|
||||
} while (!trigCmd.end);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1096,10 +1136,9 @@ namespace TR {
|
||||
|
||||
} while (!cmd.end);
|
||||
|
||||
if (actual && info.roomNext != 0xFF)
|
||||
getFloorInfo(info.roomNext, x, z, info, actual, prevRoom);
|
||||
}
|
||||
|
||||
|
||||
}; // struct Level
|
||||
|
||||
bool castShadow(Entity::Type type) {
|
||||
|
@ -14,7 +14,7 @@ namespace Game {
|
||||
Core::init();
|
||||
level = new Level("LEVEL2_DEMO.PHD", true, false);
|
||||
//level = new Level("GYM.PHD", false, true);
|
||||
//level = new Level("LEVEL4.PHD", false, false);
|
||||
//level = new Level("LEVEL8A.PHD", false, false);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
//Sound::play(Sound::openWAD("05_Lara's_Themes.wav"), 1, 1, 0);
|
||||
|
52
src/lara.h
52
src/lara.h
@ -195,6 +195,7 @@ struct Lara : Character {
|
||||
int lastPickUp;
|
||||
|
||||
Lara(TR::Level *level, int entity, bool home) : Character(level, entity, 1000), home(home), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), chestOffset(pos) {
|
||||
animation.setAnim(ANIM_STAND);
|
||||
getEntity().flags.active = 1;
|
||||
initMeshOverrides();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
@ -218,12 +219,12 @@ struct Lara : Character {
|
||||
pos = vec3(43182, 2473, 51556);
|
||||
angle = vec3(0.0f, PI * 0.5f, 0.0f);
|
||||
getEntity().room = 12;
|
||||
*/
|
||||
|
||||
// level 2 (pool)
|
||||
pos = vec3(70067, -256, 29104);
|
||||
angle = vec3(0.0f, -0.68f, 0.0f);
|
||||
getEntity().room = 15;
|
||||
/*
|
||||
|
||||
// level 2 (blade)
|
||||
pos = vec3(27221, -1024, 29205);
|
||||
angle = vec3(0.0f, PI * 0.5f, 0.0f);
|
||||
@ -258,16 +259,27 @@ struct Lara : Character {
|
||||
pos = vec3(70082, -512, 26935);
|
||||
angle = vec3(0.0f, PI * 0.5f, 0.0f);
|
||||
getEntity().room = 15;
|
||||
|
||||
|
||||
// level 2 (trap floor)
|
||||
pos = vec3(31390, -2048, 33472);
|
||||
angle = vec3(0.0f, 0.0f, 0.0f);
|
||||
getEntity().room = 63;
|
||||
|
||||
// level 2 (trap door)
|
||||
pos = vec3(21987, -1024, 29144);
|
||||
angle = vec3(0.0f, PI * 3.0f * 0.5f, 0.0f);
|
||||
getEntity().room = 61;
|
||||
|
||||
// level 3a
|
||||
pos = vec3(41015, 3584, 34494);
|
||||
angle = vec3(0.0f, -PI, 0.0f);
|
||||
getEntity().room = 51;
|
||||
|
||||
|
||||
// level 1
|
||||
pos = vec3(20215, 6656, 52942);
|
||||
angle = vec3(0.0f, PI, 0.0f);
|
||||
getEntity().room = 14;
|
||||
|
||||
*/
|
||||
updateEntity();
|
||||
#endif
|
||||
@ -838,8 +850,8 @@ struct Lara : Character {
|
||||
vec3 dst = pos + getDir() * 32.0f;
|
||||
|
||||
TR::Level::FloorInfo infoCur, infoDst;
|
||||
level->getFloorInfo(getEntity().room, (int)pos.x, (int)pos.z, infoCur),
|
||||
level->getFloorInfo(infoCur.roomAbove, (int)dst.x, (int)dst.z, infoDst);
|
||||
level->getFloorInfo(getEntity().room, (int)pos.x, (int)pos.y, (int)pos.z, infoCur),
|
||||
level->getFloorInfo(infoCur.roomAbove, (int)dst.x, (int)dst.y, (int)dst.z, infoDst);
|
||||
|
||||
int h = int(pos.y - infoDst.floor);
|
||||
|
||||
@ -907,7 +919,7 @@ struct Lara : Character {
|
||||
|
||||
TR::Entity &e = getEntity();
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(e.room, e.x, e.z, info);
|
||||
level->getFloorInfo(e.room, e.x, e.y, e.z, info);
|
||||
|
||||
if (!info.trigCmdCount) return; // has no trigger
|
||||
bool isActive = level->entities[info.trigCmd[0].args].flags.active != 0;
|
||||
@ -976,10 +988,10 @@ struct Lara : Character {
|
||||
TR::FloorData::TriggerCommand &cmd = info.trigCmd[i];
|
||||
switch (cmd.action) {
|
||||
case TR::Action::CAMERA_SWITCH :
|
||||
*actionItem = ActionCommand(cmd.action, cmd.args, (float)info.trigCmd[++i].delay); // camera switch uses next command for delay timer
|
||||
*actionItem = ActionCommand(entity, cmd.action, cmd.args, (float)info.trigCmd[++i].delay); // camera switch uses next command for delay timer
|
||||
break;
|
||||
default :
|
||||
*actionItem = ActionCommand(cmd.action, cmd.args, info.trigInfo.timer);
|
||||
*actionItem = ActionCommand(entity, cmd.action, cmd.args, info.trigInfo.timer);
|
||||
}
|
||||
|
||||
actionItem->next = (i < info.trigCmdCount - 1) ? actionItem + 1 : NULL;
|
||||
@ -1027,7 +1039,7 @@ struct Lara : Character {
|
||||
|
||||
TR::Entity &e = getEntity();
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(e.room, e.x, e.z, info, true);
|
||||
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 (e.y + 8 >= info.floor && (abs(info.slantX) > 2 || abs(info.slantZ) > 2)) {
|
||||
@ -1077,12 +1089,12 @@ struct Lara : Character {
|
||||
TR::Level::FloorInfo info;
|
||||
|
||||
info.roomAbove = getRoomIndex();
|
||||
level->getFloorInfo(info.roomAbove, (int)pos.x, (int)pos.z, info);
|
||||
level->getFloorInfo(info.roomAbove, (int)pos.x, (int)pos.y, (int)pos.z, info);
|
||||
if (info.roomAbove == 0xFF)
|
||||
info.roomAbove = getRoomIndex();
|
||||
|
||||
do {
|
||||
level->getFloorInfo(info.roomAbove, (int)p.x, (int)p.z, info, true);
|
||||
level->getFloorInfo(info.roomAbove, (int)p.x, (int)p.y, (int)p.z, info);
|
||||
} while (info.ceiling > p.y - LARA_HANG_OFFSET && info.roomAbove != 0xFF);
|
||||
|
||||
if (abs(int(info.floor - (p.y - LARA_HANG_OFFSET))) < 16) {
|
||||
@ -1145,7 +1157,7 @@ struct Lara : Character {
|
||||
if ((input & (FORTH | ACTION)) == (FORTH | ACTION) && (animation.index == ANIM_STAND || animation.index == ANIM_STAND_NORMAL) && emptyHands()) { // TODO: get rid of animation.index
|
||||
vec3 p = pos + getDir() * 64.0f;
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(getRoomIndex(), (int)p.x, (int)p.z, info, true);
|
||||
level->getFloorInfo(getRoomIndex(), (int)p.x, (int)p.y, (int)p.z, info);
|
||||
int h = (int)pos.y - info.floor;
|
||||
|
||||
int aIndex = animation.index;
|
||||
@ -1233,7 +1245,7 @@ struct Lara : Character {
|
||||
|
||||
if (state != STATE_SLIDE && state != STATE_SLIDE_BACK) {
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(e.room, e.x, e.z, info);
|
||||
level->getFloorInfo(e.room, e.x, e.y, e.z, info);
|
||||
|
||||
int sx = abs(info.slantX), sz = abs(info.slantZ);
|
||||
// get direction
|
||||
@ -1269,7 +1281,7 @@ struct Lara : Character {
|
||||
// possibility check
|
||||
TR::Level::FloorInfo info;
|
||||
vec3 p = pos + getDir() * 128.0f;
|
||||
level->getFloorInfo(getRoomIndex(), (int)p.x, (int)p.z, info, true);
|
||||
level->getFloorInfo(getRoomIndex(), (int)p.x, (int)p.y, (int)p.z, info);
|
||||
if (info.floor - info.ceiling >= 768)
|
||||
return (input & WALK) ? STATE_HANDSTAND : STATE_HANG_UP;
|
||||
}
|
||||
@ -1464,11 +1476,11 @@ struct Lara : Character {
|
||||
TR::Level::FloorInfo info;
|
||||
if (stand == STAND_HANG) {
|
||||
vec3 p = pos + getDir() * 128.0f;
|
||||
level->getFloorInfo(e.room, (int)p.x, (int)p.z, info);
|
||||
level->getFloorInfo(e.room, (int)p.x, (int)p.y, (int)p.z, info);
|
||||
if (info.roomAbove != 0xFF && info.floor >= e.y - LARA_HANG_OFFSET)
|
||||
level->getFloorInfo(info.roomAbove, (int)p.x, (int)p.z, info);
|
||||
level->getFloorInfo(info.roomAbove, (int)p.x, (int)p.y, (int)p.z, info);
|
||||
} else
|
||||
level->getFloorInfo(e.room, e.x, e.z, info);
|
||||
level->getFloorInfo(e.room, e.x, e.y, e.z, info);
|
||||
|
||||
vec3 v(sinf(angleExt), 0.0f, cosf(angleExt));
|
||||
velocity = info.getSlant(v) * speed;
|
||||
@ -1509,7 +1521,7 @@ struct Lara : Character {
|
||||
|
||||
TR::Entity &e = getEntity();
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(e.room, (int)pos.x, (int)pos.z, info, true);
|
||||
level->getFloorInfo(e.room, (int)pos.x, (int)pos.y, (int)pos.z, info);
|
||||
|
||||
// get frame to get height
|
||||
TR::Animation *anim = animation;
|
||||
@ -1583,7 +1595,7 @@ struct Lara : Character {
|
||||
canPassGap = f >= 220.0f; // check dist to floor
|
||||
if (canPassGap) { // check end of hang layer
|
||||
vec3 d = pos + getDir() * 128.0f;
|
||||
level->getFloorInfo(info.roomAbove != 0xFF ? info.roomAbove : getRoomIndex(), (int)d.x, (int)d.z, info, true);
|
||||
level->getFloorInfo(info.roomAbove != 0xFF ? info.roomAbove : getRoomIndex(), (int)d.x, (int)d.y, (int)d.z, info);
|
||||
canPassGap = fabsf((pos.y - LARA_HANG_OFFSET) - info.floor) < 64.0f;
|
||||
}
|
||||
break;
|
||||
|
21
src/level.h
21
src/level.h
@ -83,9 +83,15 @@ struct Level {
|
||||
case TR::Entity::DOOR_6 :
|
||||
case TR::Entity::DOOR_BIG_1 :
|
||||
case TR::Entity::DOOR_BIG_2 :
|
||||
entity.controller = new Door(&level, i);
|
||||
break;
|
||||
case TR::Entity::DOOR_FLOOR_1 :
|
||||
case TR::Entity::DOOR_FLOOR_2 :
|
||||
entity.controller = new DoorFloor(&level, i);
|
||||
break;
|
||||
case TR::Entity::TRAP_FLOOR :
|
||||
entity.controller = new TrapFloor(&level, i);
|
||||
break;
|
||||
case TR::Entity::TRAP_BLADE :
|
||||
case TR::Entity::TRAP_SPIKES :
|
||||
entity.controller = new Trigger(&level, i, true);
|
||||
@ -238,6 +244,8 @@ struct Level {
|
||||
|
||||
Shader *sh = setRoomShader(room, 1.0f);
|
||||
|
||||
Core::lightColor[0] = vec4(0, 0, 0, 1);
|
||||
|
||||
sh->bind();
|
||||
sh->setParam(uColor, Core::color);
|
||||
sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
|
||||
@ -264,12 +272,11 @@ struct Level {
|
||||
rMesh.flags.rendered = true;
|
||||
|
||||
// set light parameters
|
||||
getLight(offset, roomIndex);
|
||||
//getLight(offset, roomIndex);
|
||||
|
||||
if (rMesh.intensity >= 0) {
|
||||
Core::ambient = vec3(intensity(rMesh.intensity) / 255.0f);
|
||||
Core::ambient = vec3(0.0);
|
||||
sh->setParam(uAmbient, Core::ambient);
|
||||
// Core::ambient = vec3(intensity(rMesh.intensity) / 255.0f);
|
||||
sh->setParam(uAmbient, vec3(0.0f));//Core::ambient);
|
||||
}
|
||||
|
||||
// render static mesh
|
||||
@ -378,6 +385,7 @@ struct Level {
|
||||
}
|
||||
|
||||
void renderEntity(const TR::Entity &entity) {
|
||||
// if (entity.room != lara->getRoomIndex()) return;
|
||||
if (entity.type == TR::Entity::NONE) return;
|
||||
ASSERT(entity.controller);
|
||||
|
||||
@ -483,10 +491,11 @@ struct Level {
|
||||
Debug::begin();
|
||||
// Debug::Level::rooms(level, lara->pos, lara->getEntity().room);
|
||||
// Debug::Level::lights(level);
|
||||
Debug::Level::sectors(level, lara->getRoomIndex(), (int)lara->pos.y);
|
||||
// Debug::Level::portals(level);
|
||||
// Debug::Level::meshes(level);
|
||||
// Debug::Level::entities(level);
|
||||
Debug::Level::info(level, lara->getEntity(), lara->animation);
|
||||
Debug::Level::entities(level);
|
||||
// Debug::Level::info(level, lara->getEntity(), lara->animation);
|
||||
Debug::end();
|
||||
#endif
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ struct Trigger : Controller {
|
||||
|
||||
Trigger(TR::Level *level, int entity, bool immediate) : Controller(level, entity), immediate(immediate), timer(0.0f) {
|
||||
baseState = state;
|
||||
getEntity().flags.collision = false;
|
||||
}
|
||||
|
||||
bool inState() {
|
||||
@ -73,7 +74,7 @@ struct Dart : Controller {
|
||||
pos = pos + velocity * (Core::deltaTime * 30.0f);
|
||||
updateEntity();
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(getRoomIndex(), (int)pos.x, (int)pos.z, info);
|
||||
level->getFloorInfo(getRoomIndex(), (int)pos.x, (int)pos.y, (int)pos.z, info);
|
||||
if (pos.y > info.floor || pos.y < info.ceiling || !insideRoom(pos, getRoomIndex())) {
|
||||
if (!inWall) {
|
||||
TR::Entity &e = getEntity();
|
||||
@ -144,7 +145,7 @@ struct Block : Controller {
|
||||
void updateFloor(bool rise) {
|
||||
TR::Entity &e = getEntity();
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(e.room, e.x, e.z, info);
|
||||
level->getFloorInfo(e.room, e.x, e.y, e.z, info);
|
||||
if (info.roomNext != 0xFF)
|
||||
e.room = info.roomNext;
|
||||
int dx, dz;
|
||||
@ -157,7 +158,7 @@ struct Block : Controller {
|
||||
vec3 dir = getDir() * (push ? 1024.0f : -2048.0f);
|
||||
TR::Entity &e = getEntity();
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(e.room, e.x + (int)dir.x, e.z + (int)dir.z, info, true);
|
||||
level->getFloorInfo(e.room, e.x + (int)dir.x, e.y, e.z + (int)dir.z, info);
|
||||
if ((info.slantX | info.slantZ) || info.floor != e.y)
|
||||
return false;
|
||||
if (!animation.setState(push ? STATE_PUSH : STATE_PULL))
|
||||
@ -176,4 +177,70 @@ struct Block : Controller {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Door : Trigger {
|
||||
|
||||
Door(TR::Level *level, int entity) : Trigger(level, entity, true) {}
|
||||
};
|
||||
|
||||
struct DoorFloor : Trigger {
|
||||
|
||||
DoorFloor(TR::Level *level, int entity) : Trigger(level, entity, true) {
|
||||
getEntity().flags.collision = true;
|
||||
}
|
||||
|
||||
virtual bool activate(ActionCommand *cmd) {
|
||||
bool res = Trigger::activate(cmd);
|
||||
getEntity().flags.collision = !getEntity().flags.active;
|
||||
return res;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct TrapFloor : Trigger {
|
||||
|
||||
enum {
|
||||
STATE_STATIC,
|
||||
STATE_SHAKE,
|
||||
STATE_FALL,
|
||||
STATE_DOWN,
|
||||
};
|
||||
float velocity;
|
||||
|
||||
TrapFloor(TR::Level *level, int entity) : Trigger(level, entity, true), velocity(0) {
|
||||
TR::Entity &e = getEntity();
|
||||
e.flags.collision = true;
|
||||
}
|
||||
|
||||
virtual bool activate(ActionCommand *cmd) {
|
||||
TR::Entity &e = level->entities[cmd->emitter];
|
||||
if (e.type != TR::Entity::LARA) return true;
|
||||
int ey = (int)pos.y - 512; // real floor object position
|
||||
return (abs(e.y - ey) <= 8) ? Trigger::activate(cmd) : true;
|
||||
}
|
||||
|
||||
virtual void update() {
|
||||
Trigger::update();
|
||||
if (state == STATE_FALL) {
|
||||
TR::Entity &e = getEntity();
|
||||
e.flags.collision = false;
|
||||
velocity += GRAVITY * 30 * Core::deltaTime;
|
||||
pos.y += velocity * Core::deltaTime;
|
||||
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(e.room, e.x, (int)pos.y, e.z, info);
|
||||
|
||||
if (pos.y > info.roomFloor && info.roomBelow != 0xFF)
|
||||
e.room = info.roomBelow;
|
||||
|
||||
if (pos.y > info.floor) {
|
||||
pos.y = info.floor;
|
||||
animation.setState(STATE_DOWN);
|
||||
}
|
||||
updateEntity();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user