1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-15 09:34:18 +02:00

#3 fix hang reach state; add hang swing animation

This commit is contained in:
XProger
2017-02-17 04:03:03 +03:00
parent c2aac325b7
commit f7b8568e44
3 changed files with 44 additions and 52 deletions

View File

@@ -14,7 +14,7 @@ struct Collision {
Collision() : side(NONE) {} Collision() : side(NONE) {}
Collision(TR::Level *level, int room, vec3 &pos, const vec3 &offset, const vec3 &velocity, float radius, float angle, int minHeight, int maxHeight, int maxAscent, int maxDescent) { Collision(TR::Level *level, int roomIndex, vec3 &pos, const vec3 &offset, const vec3 &velocity, float radius, float angle, int minHeight, int maxHeight, int maxAscent, int maxDescent) {
if (velocity.x > 0.0f || velocity.z > 0.0f) if (velocity.x > 0.0f || velocity.z > 0.0f)
angle = normalizeAngle(PI2 + vec2(velocity.z, velocity.x).angle()); angle = normalizeAngle(PI2 + vec2(velocity.z, velocity.x).angle());
pos += velocity; pos += velocity;
@@ -38,7 +38,9 @@ struct Collision {
int height = maxHeight - minHeight; int height = maxHeight - minHeight;
if (checkHeight(level, room, hpos, vec2(0.0f), height, 0xFFFFFF, 0xFFFFFF, side = NONE)) { getFloor(level, roomIndex, vec3(pos.x, hpos.y, pos.z));
if (checkHeight(level, roomIndex, hpos, vec2(0.0f), height, 0xFFFFFF, 0xFFFFFF, side = NONE)) {
pos -= velocity; pos -= velocity;
side = FRONT; side = FRONT;
return; return;
@@ -54,13 +56,13 @@ struct Collision {
side = BOTTOM; side = BOTTOM;
} }
if (checkHeight(level, room, hpos, f, height, maxAscent, maxDescent, FRONT)) { if (checkHeight(level, roomIndex, hpos, f, height, maxAscent, maxDescent, FRONT)) {
d = vec2(-velocity.x, -velocity.z); d = vec2(-velocity.x, -velocity.z);
q ^= 1; q ^= 1;
d[q] = getOffset(p[q] + f[q], p[q]); d[q] = getOffset(p[q] + f[q], p[q]);
} else if (checkHeight(level, room, hpos, l, height, maxAscent, maxDescent, LEFT)) { } else if (checkHeight(level, roomIndex, hpos, l, height, maxAscent, maxDescent, LEFT)) {
d[q] = getOffset(p[q] + l[q], p[q] + f[q]); d[q] = getOffset(p[q] + l[q], p[q] + f[q]);
} else if (checkHeight(level, room, hpos, r, height, maxAscent, maxDescent, RIGHT)) { } else if (checkHeight(level, roomIndex, hpos, r, height, maxAscent, maxDescent, RIGHT)) {
d[q] = getOffset(p[q] + r[q], p[q] + f[q]); d[q] = getOffset(p[q] + r[q], p[q] + f[q]);
} else } else
return; return;
@@ -68,13 +70,13 @@ struct Collision {
pos += vec3(d.x, 0.0f, d.y); pos += vec3(d.x, 0.0f, d.y);
} }
inline bool checkHeight(TR::Level *level, int room, const vec3 &pos, const vec2 &offset, int height, int maxAscent, int maxDescent, Side side) { inline bool checkHeight(TR::Level *level, int roomIndex, const vec3 &pos, const vec2 &offset, int height, int maxAscent, int maxDescent, Side side) {
TR::Level::FloorInfo info; TR::Level::FloorInfo info;
int py = int(pos.y); int py = int(pos.y);
level->getFloorInfo(room, int(pos.x + offset.x), py, int(pos.z + offset.y), info); level->getFloorInfo(roomIndex, int(pos.x + offset.x), py, int(pos.z + offset.y), info);
Info &inf = this->info[side]; Info &inf = this->info[side];
inf.room = info.roomNext != TR::NO_ROOM ? info.roomNext : room; inf.room = info.roomNext != TR::NO_ROOM ? info.roomNext : roomIndex;
inf.roomAbove = info.roomAbove; inf.roomAbove = info.roomAbove;
inf.roomBelow = info.roomBelow; inf.roomBelow = info.roomBelow;
inf.floor = info.floor; inf.floor = info.floor;
@@ -99,6 +101,18 @@ struct Collision {
return -from + 1025.0f; return -from + 1025.0f;
return -from - 1.0f; return -from - 1.0f;
} }
static int getFloor(TR::Level *level, int &roomIndex, const vec3 &pos) {
int dx, dz, x = int(pos.x), z = int(pos.z);
TR::Room::Sector *s = &level->getSector(roomIndex, x, z, dx, dz);
while (s->ceiling * 256 > pos.y && s->roomAbove != TR::NO_ROOM) {
roomIndex = s->roomAbove;
s = &level->getSector(roomIndex, x, z, dx, dz);
}
return s->floor * 256;
}
}; };
#endif #endif

View File

@@ -1572,7 +1572,7 @@ namespace TR {
info.ceiling = info.roomCeiling; info.ceiling = info.roomCeiling;
info.slantX = 0; info.slantX = 0;
info.slantZ = 0; info.slantZ = 0;
info.roomNext = 0xFF; info.roomNext = NO_ROOM;
info.roomBelow = s.roomBelow; info.roomBelow = s.roomBelow;
info.roomAbove = s.roomAbove; info.roomAbove = s.roomAbove;
info.floorIndex = s.floorIndex; info.floorIndex = s.floorIndex;
@@ -1581,16 +1581,17 @@ namespace TR {
info.trigCmdCount = 0; info.trigCmdCount = 0;
if (s.floor == -127) if (s.floor == -127)
return; return;
Room::Sector *sBelow = &s; Room::Sector *sBelow = &s;
while (sBelow->roomBelow != TR::NO_ROOM) sBelow = &getSector(sBelow->roomBelow, x, z, dx, dz); while (sBelow->roomBelow != NO_ROOM) sBelow = &getSector(sBelow->roomBelow, x, z, dx, dz);
info.floor = 256 * sBelow->floor; info.floor = 256 * sBelow->floor;
parseFloorData(info, sBelow->floorIndex, dx, dz); parseFloorData(info, sBelow->floorIndex, dx, dz);
if (info.roomNext == TR::NO_ROOM) { if (info.roomNext == NO_ROOM) {
Room::Sector *sAbove = &s; Room::Sector *sAbove = &s;
while (sAbove->roomAbove != TR::NO_ROOM) sAbove = &getSector(sAbove->roomAbove, x, z, dx, dz); while (sAbove->roomAbove != NO_ROOM) sAbove = &getSector(sAbove->roomAbove, x, z, dx, dz);
if (sAbove != sBelow) { if (sAbove != sBelow) {
info.ceiling = 256 * sAbove->ceiling; info.ceiling = 256 * sAbove->ceiling;
parseFloorData(info, sAbove->floorIndex, dx, dz); parseFloorData(info, sAbove->floorIndex, dx, dz);
@@ -1601,6 +1602,7 @@ namespace TR {
info.roomNext = tmp; info.roomNext = tmp;
} }
// entities collide // entities collide
if (info.trigCmdCount) { if (info.trigCmdCount) {
int sx = x / 1024; int sx = x / 1024;

View File

@@ -58,7 +58,6 @@ struct Lara : Character {
ANIM_CLIMB_JUMP = 26, ANIM_CLIMB_JUMP = 26,
ANIM_HANG_FALL = 28, ANIM_HANG_FALL = 28,
ANIM_HANG_WALL = 29,
ANIM_FALL = 34, ANIM_FALL = 34,
ANIM_SMASH_JUMP = 32, ANIM_SMASH_JUMP = 32,
@@ -98,7 +97,7 @@ struct Lara : Character {
ANIM_STAND_ROLL_BEGIN = 146, ANIM_STAND_ROLL_BEGIN = 146,
ANIM_STAND_ROLL_END = 147, ANIM_STAND_ROLL_END = 147,
ANIM_HANG_NOWALL = 150, ANIM_HANG_SWING = 150,
}; };
// http://www.tombraiderforums.com/showthread.php?t=211681 // http://www.tombraiderforums.com/showthread.php?t=211681
@@ -417,7 +416,7 @@ struct Lara : Character {
//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)
//reset(16, vec3(60907, 0, 39642), PI * 3 / 2); // level 2 (hang & climb) //reset(16, vec3(60907, 0, 39642), PI * 3 / 2); // level 2 (hang & climb)
reset(19, vec3(60843, 1024, 30557), PI); // level 2 (block) //reset(19, vec3(60843, 1024, 30557), PI); // level 2 (block)
//reset(7, vec3(64108, -512, 16514), -PI * 0.5f); // level 2 (bat trigger) //reset(7, vec3(64108, -512, 16514), -PI * 0.5f); // level 2 (bat trigger)
//reset(15, vec3(70082, -512, 26935), PI * 0.5f); // level 2 (bear) //reset(15, vec3(70082, -512, 26935), PI * 0.5f); // level 2 (bear)
//reset(63, vec3(31390, -2048, 33472), 0.0f); // level 2 (trap floor) //reset(63, vec3(31390, -2048, 33472), 0.0f); // level 2 (trap floor)
@@ -1299,56 +1298,33 @@ struct Lara : Character {
if (state == STATE_REACH && velocity.y < 0.0f) if (state == STATE_REACH && velocity.y < 0.0f)
return state; return state;
vec3 p = pos; Box bounds = animation.getBoundingBox(pos, 0);
vec3 p = vec3(pos.x, bounds.min.y, pos.z);
Collision c = Collision(level, getRoomIndex(), p, getDir() * 32.0f, vec3(0.0f), LARA_RADIUS, angleExt, 0, 0, 0, 0); Collision c = Collision(level, getRoomIndex(), p, getDir() * 32.0f, vec3(0.0f), LARA_RADIUS, angleExt, 0, 0, 0, 0);
if (c.side != Collision::FRONT) if (c.side != Collision::FRONT)
return state; return state;
Box bounds = animation.getBoundingBox(pos, 0);
int floor = c.info[Collision::FRONT].floor; int floor = c.info[Collision::FRONT].floor;
int hands = int(bounds.min.y); int hands = int(bounds.min.y);
if (abs(floor - hands) < 32) { if (abs(floor - hands) < 128) {
alignToWall(-LARA_RADIUS); alignToWall(-LARA_RADIUS);
pos.y = float(floor + LARA_HANG_OFFSET); pos.y = float(floor + LARA_HANG_OFFSET);
stand = STAND_HANG; stand = STAND_HANG;
updateEntity(); updateEntity();
if (state == STATE_REACH) { if (state == STATE_REACH) {
return STATE_HANG; // TODO: ANIM_HANG_WALL / ANIM_HANG_NOWALL vec3 p = pos + getDir() * 256.0f;
TR::Level::FloorInfo info;
level->getFloorInfo(getRoomIndex(), int(p.x), int(p.y), int(p.z), info);
int h = info.ceiling - floor;
return animation.setAnim((h > 0 && h < 400) ? ANIM_HANG_SWING : ANIM_HANG);
} else } else
return animation.setAnim(ANIM_HANG, -15); return animation.setAnim(ANIM_HANG, -15);
} }
/*
vec3 p = pos + getDir() * 128.0f;
TR::Level::FloorInfo info;
// TODO: use brain
info.roomAbove = getRoomIndex();
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.y, (int)p.z, info);
} while (info.ceiling > bounds.min.y && info.roomAbove != 0xFF);
if (abs(info.floor - int(bounds.min.y)) < 16) { // reach fall
alignToWall(LARA_RADIUS);
pos.y = info.floor + 724.0f;
updateEntity();
stand = STAND_HANG;
if (state == STATE_REACH) {
return STATE_HANG; // TODO: ANIM_HANG_WALL / ANIM_HANG_NOWALL
} else
return animation.setAnim(ANIM_HANG, -15);
}
*/
} }
if (state == STATE_FORWARD_JUMP) { if (state == STATE_FORWARD_JUMP) {
@@ -1850,6 +1826,8 @@ struct Lara : Character {
int maxAscent = 256 + 128; int maxAscent = 256 + 128;
int maxDescent = 0xFFFFFF; int maxDescent = 0xFFFFFF;
int room = getRoomIndex();
if (state == STATE_WALK || state == STATE_BACK) if (state == STATE_WALK || state == STATE_BACK)
maxDescent = maxAscent; maxDescent = maxAscent;
if (state == STATE_STEP_LEFT || state == STATE_STEP_RIGHT) if (state == STATE_STEP_LEFT || state == STATE_STEP_RIGHT)
@@ -1860,14 +1838,12 @@ struct Lara : Character {
maxHeight = 0; maxHeight = 0;
maxAscent = maxDescent = 64; maxAscent = maxDescent = 64;
offset = getDir() * (LARA_RADIUS + 32.0f); offset = getDir() * (LARA_RADIUS + 32.0f);
offset.y -= LARA_HANG_OFFSET; offset.y -= LARA_HANG_OFFSET + 32;
} }
if (stand == STAND_UNDERWATER) { if (stand == STAND_UNDERWATER) {
offset.y += LARA_HEIGHT_WATER * 0.5f; offset.y += LARA_HEIGHT_WATER * 0.5f;
} }
int room = getRoomIndex();
collision = Collision(level, room, pos, offset, vel, radius, angleExt, minHeight, maxHeight, maxAscent, maxDescent); collision = Collision(level, room, pos, offset, vel, radius, angleExt, minHeight, maxHeight, maxAscent, maxDescent);
if (stand != STAND_HANG && (collision.side == Collision::LEFT || collision.side == Collision::RIGHT)) { if (stand != STAND_HANG && (collision.side == Collision::LEFT || collision.side == Collision::RIGHT)) {