mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-11 23:54:09 +02:00
37
src/camera.h
37
src/camera.h
@@ -58,7 +58,7 @@ struct Camera : ICamera {
|
||||
}
|
||||
|
||||
virtual int getRoomIndex() const {
|
||||
return viewIndex > -1 ? level->cameras[viewIndex].room : room;
|
||||
return room;
|
||||
}
|
||||
|
||||
virtual void checkRoom() {
|
||||
@@ -114,6 +114,9 @@ struct Camera : ICamera {
|
||||
this->timer = timer;
|
||||
this->speed = speed;
|
||||
lastDest = pos;
|
||||
|
||||
if (viewIndex > -1)
|
||||
room = level->cameras[viewIndex].room;
|
||||
}
|
||||
|
||||
vec3 getViewPoint() {
|
||||
@@ -125,6 +128,14 @@ struct Camera : ICamera {
|
||||
return p;
|
||||
}
|
||||
|
||||
void resetTarget(const vec3 &viewPoint) {
|
||||
timer = -1.0f;
|
||||
state = STATE_FOLLOW;
|
||||
viewTarget = NULL;
|
||||
viewIndex = -1;
|
||||
target = viewPoint;
|
||||
}
|
||||
|
||||
virtual void update() {
|
||||
if (shake > 0.0f)
|
||||
shake = max(0.0f, shake - Core::deltaTime);
|
||||
@@ -214,23 +225,6 @@ struct Camera : ICamera {
|
||||
|
||||
vec3 viewPoint = getViewPoint();
|
||||
|
||||
if (timer > 0.0f) {
|
||||
timer -= Core::deltaTime;
|
||||
if (timer <= 0.0f) {
|
||||
timer = -1.0f;
|
||||
state = STATE_FOLLOW;
|
||||
viewTarget = owner->viewTarget = NULL;
|
||||
viewIndex = -1;
|
||||
target = viewPoint;
|
||||
if (room != getRoomIndex())
|
||||
pos = lastDest;
|
||||
}
|
||||
} else
|
||||
viewIndex = -1;
|
||||
|
||||
if (timer < 0.0f)
|
||||
viewTarget = NULL;
|
||||
|
||||
if (firstPerson && viewIndex == -1) {
|
||||
Basis head = owner->animation.getJoints(owner->getMatrix(), 14, true);
|
||||
Basis eye(quat(0.0f, 0.0f, 0.0f, 1.0f), vec3(0.0f, -40.0f, 10.0f));
|
||||
@@ -282,6 +276,13 @@ struct Camera : ICamera {
|
||||
}
|
||||
pos = pos.lerp(destPos, Core::deltaTime * lerpFactor);
|
||||
|
||||
if (timer > 0.0f) {
|
||||
timer -= Core::deltaTime;
|
||||
if (timer <= 0.0f)
|
||||
resetTarget(viewPoint);
|
||||
} else
|
||||
resetTarget(target);
|
||||
|
||||
if (viewIndex == -1)
|
||||
checkRoom();
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ struct ICamera {
|
||||
ICamera() : reflectPlane(NULL) {}
|
||||
|
||||
virtual void setup(bool calcMatrices) {}
|
||||
virtual int getRoomIndex() const { return TR::NO_ROOM; }
|
||||
};
|
||||
|
||||
struct IGame {
|
||||
@@ -247,8 +248,8 @@ struct Controller {
|
||||
e.rotation = angle.y;
|
||||
}
|
||||
|
||||
bool insideRoom(const vec3 &pos, int room) const {
|
||||
TR::Room &r = level->rooms[room];
|
||||
bool insideRoom(const vec3 &pos, int roomIndex) const {
|
||||
TR::Room &r = level->rooms[roomIndex];
|
||||
vec3 min = vec3((float)r.info.x + 1024, (float)r.info.yTop, (float)r.info.z + 1024);
|
||||
vec3 max = min + vec3(float((r.xSectors - 1) * 1024), float(r.info.yBottom - r.info.yTop), float((r.zSectors - 1) * 1024));
|
||||
|
||||
|
@@ -658,7 +658,7 @@ namespace Debug {
|
||||
sprintf(buf, "DIP = %d, TRI = %d, SND = %d, active = %d", Core::stats.dips, Core::stats.tris, Sound::channelsCount, activeCount);
|
||||
Debug::Draw::text(vec2(16, y += 16), vec4(1.0f), buf);
|
||||
vec3 angle = ((Controller*)entity.controller)->angle * RAD2DEG;
|
||||
sprintf(buf, "pos = (%d, %d, %d), angle = (%d, %d), room = %d", entity.x, entity.y, entity.z, (int)angle.x, (int)angle.y, ((Controller*)entity.controller)->getRoomIndex());
|
||||
sprintf(buf, "pos = (%d, %d, %d), angle = (%d, %d), room = %d (camera: %d)", entity.x, entity.y, entity.z, (int)angle.x, (int)angle.y, ((Controller*)entity.controller)->getRoomIndex(), ((ICamera*)level.cameraController)->getRoomIndex());
|
||||
Debug::Draw::text(vec2(16, y += 16), vec4(1.0f), buf);
|
||||
int rate = anim.anims[anim.index].frameRate;
|
||||
sprintf(buf, "state = %d, anim = %d, next = %d, rate = %d, frame = %.2f / %d (%f)", anim.state, anim.index, anim.next, rate, anim.time * 30.0f, anim.framesCount, anim.delta);
|
||||
|
108
src/lara.h
108
src/lara.h
@@ -454,7 +454,8 @@ struct Lara : Character {
|
||||
//reset(51, vec3(41015, 3584, 34494), -PI); // level 3a (t-rex)
|
||||
//reset(5, vec3(38643, -3072, 92370), PI * 0.5f); // level 3a (gears)
|
||||
//reset(43, vec3(64037, 6656, 48229), PI); // level 3b (movingblock)
|
||||
//reset(5, vec3(73394, 3840, 60758), 0); // level 3b (scion)
|
||||
//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(0, vec3(40913, -1012, 42252), PI); // level 8c
|
||||
//reset(10, vec3(90443, 11264 - 256, 114614), PI, STAND_ONWATER); // villa mortal 2
|
||||
@@ -1181,38 +1182,37 @@ struct Lara : Character {
|
||||
vec3 from = pos - vec3(0, 650, 0);
|
||||
|
||||
Controller *c = Controller::first;
|
||||
while (c) {
|
||||
if (level->entities[c->entity].isEnemy()) {
|
||||
Character *enemy = (Character*)c;
|
||||
if (enemy->health > 0) {
|
||||
do {
|
||||
if (!level->entities[c->entity].isEnemy())
|
||||
continue;
|
||||
|
||||
Box box = enemy->getBoundingBox();
|
||||
vec3 p = box.center();
|
||||
p.y = box.min.y + (box.max.y - box.min.y) / 3.0f;
|
||||
Character *enemy = (Character*)c;
|
||||
if (enemy->health <= 0)
|
||||
continue;
|
||||
|
||||
Box box = enemy->getBoundingBox();
|
||||
vec3 p = box.center();
|
||||
p.y = box.min.y + (box.max.y - box.min.y) / 3.0f;
|
||||
|
||||
vec3 v = p - pos;
|
||||
if (dir.dot(v.normal()) > 0.5f) { // target is on sight -60..+60 degrees
|
||||
vec3 v = p - pos;
|
||||
if (dir.dot(v.normal()) <= 0.5f)
|
||||
continue; // target is out of view range -60..+60 degrees
|
||||
|
||||
float d = v.length();
|
||||
float d = v.length();
|
||||
|
||||
if ((d < dist[0] || d < dist[1]) && checkOcclusion(from, p, d)) {
|
||||
if ((d > dist[0] && d > dist[1]) || !checkOcclusion(from, p, d))
|
||||
continue;
|
||||
|
||||
if (d < dist[0]) {
|
||||
target2 = target1;
|
||||
dist[1] = dist[0];
|
||||
target1 = enemy;
|
||||
dist[0] = d;
|
||||
} else if (d < dist[1]) {
|
||||
target2 = enemy;
|
||||
dist[1] = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (d < dist[0]) {
|
||||
target2 = target1;
|
||||
dist[1] = dist[0];
|
||||
target1 = enemy;
|
||||
dist[0] = d;
|
||||
} else if (d < dist[1]) {
|
||||
target2 = enemy;
|
||||
dist[1] = d;
|
||||
}
|
||||
|
||||
c = c->next;
|
||||
}
|
||||
} while ((c = c->next));
|
||||
|
||||
if (!target2 || dist[1] > dist[0] * 4)
|
||||
target2 = target1;
|
||||
@@ -1295,16 +1295,42 @@ struct Lara : Character {
|
||||
|
||||
damageTime = LARA_DAMAGE_TIME;
|
||||
|
||||
Character::hit(damage, enemy);
|
||||
if (damage == REX_DAMAGE) { // T-Rex attack (fatal)
|
||||
pos = enemy->pos;
|
||||
angle = enemy->angle;
|
||||
if (health > 0.0f) {
|
||||
if (damage == BOULDER_DAMAGE_GROUND) {
|
||||
if (stand == STAND_GROUND) {
|
||||
animation.setAnim(level->models[TR::MODEL_LARA_SPEC].animation + 2);
|
||||
angle = enemy->angle;
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(getRoomIndex(), int(pos.x), int(pos.y), int(pos.z), info);
|
||||
vec3 d = getDir();
|
||||
vec3 v = info.getSlant(d);
|
||||
angle.x = -acos(d.dot(v));
|
||||
int roomIndex = getRoomIndex();
|
||||
v = ((TrapBoulder*)enemy)->velocity * 60.0f;
|
||||
for (int i = 0; i < 15; i++) {
|
||||
vec3 p = pos + vec3(randf() * 512.0f - 256.0f, -randf() * 512.0f, randf() * 512.0f - 256.0f);
|
||||
int index = Sprite::add(game, TR::Entity::BLOOD, roomIndex, int(p.x), int(p.y), int(p.z), Sprite::FRAME_ANIMATED);
|
||||
if (index > -1)
|
||||
((Sprite*)level->entities[index].controller)->velocity = v;
|
||||
}
|
||||
} else if (stand == STAND_AIR) {
|
||||
damage = BOULDER_DAMAGE_AIR * 30.0f * Core::deltaTime;
|
||||
} else
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
meshSwap(1, TR::MODEL_LARA_SPEC, BODY_UPPER | BODY_LOWER);
|
||||
meshSwap(2, level->extra.weapons[Weapon::SHOTGUN], 0);
|
||||
meshSwap(3, level->extra.weapons[Weapon::UZIS], 0);
|
||||
if (damage == REX_DAMAGE) { // T-Rex attack (fatal)
|
||||
pos = enemy->pos;
|
||||
angle = enemy->angle;
|
||||
|
||||
animation.setAnim(level->models[TR::MODEL_LARA_SPEC].animation + 1);
|
||||
meshSwap(1, TR::MODEL_LARA_SPEC, BODY_UPPER | BODY_LOWER);
|
||||
meshSwap(2, level->extra.weapons[Weapon::SHOTGUN], 0);
|
||||
meshSwap(3, level->extra.weapons[Weapon::UZIS], 0);
|
||||
|
||||
animation.setAnim(level->models[TR::MODEL_LARA_SPEC].animation + 1);
|
||||
}
|
||||
|
||||
Character::hit(damage, enemy);
|
||||
}
|
||||
|
||||
if (health <= 0)
|
||||
@@ -2428,12 +2454,12 @@ struct Lara : Character {
|
||||
}
|
||||
|
||||
// check enemies & doors
|
||||
for (int i = 0; i < level->entitiesCount; i++) {
|
||||
TR::Entity &e = level->entities[i];
|
||||
Controller *controller = (Controller*)e.controller;
|
||||
Controller *controller = Controller::first;
|
||||
do {
|
||||
TR::Entity &e = controller->getEntity();
|
||||
|
||||
if (e.isEnemy()) {
|
||||
if (e.type != TR::Entity::ENEMY_REX && (!e.flags.active || ((Character*)e.controller)->health <= 0)) continue;
|
||||
if (e.type != TR::Entity::ENEMY_REX && (!e.flags.active || ((Character*)controller)->health <= 0)) continue;
|
||||
} else
|
||||
if (!e.isDoor()) continue;
|
||||
|
||||
@@ -2454,7 +2480,7 @@ struct Lara : Character {
|
||||
collisionOffset += vec3(p.x, 0.0f, p.z);
|
||||
}
|
||||
|
||||
if (e.type == TR::Entity::ENEMY_REX && ((Character*)e.controller)->health <= 0)
|
||||
if (e.type == TR::Entity::ENEMY_REX && ((Character*)controller)->health <= 0)
|
||||
return true;
|
||||
if (e.isDoor())
|
||||
return true;
|
||||
@@ -2468,7 +2494,7 @@ struct Lara : Character {
|
||||
|
||||
hitDir = angleQuadrant(dir.rotateY(angle.y + PI * 0.5f).angleY());
|
||||
return true;
|
||||
}
|
||||
} while ((controller = controller->next));
|
||||
|
||||
hitDir = -1;
|
||||
return false;
|
||||
|
@@ -322,10 +322,10 @@ struct Level : IGame {
|
||||
entity.controller = new TrapSpikes(this, i);
|
||||
break;
|
||||
case TR::Entity::TRAP_BOULDER :
|
||||
entity.controller = new Boulder(this, i);
|
||||
entity.controller = new TrapBoulder(this, i);
|
||||
break;
|
||||
case TR::Entity::TRAP_DARTGUN :
|
||||
entity.controller = new Dartgun(this, i);
|
||||
entity.controller = new TrapDartgun(this, i);
|
||||
break;
|
||||
case TR::Entity::BLOCK_1 :
|
||||
case TR::Entity::BLOCK_2 :
|
||||
|
@@ -13,8 +13,9 @@ struct Sprite : Controller {
|
||||
bool instant;
|
||||
int frame, flag;
|
||||
float time;
|
||||
vec3 velocity;
|
||||
|
||||
Sprite(IGame *game, int entity, bool instant = true, int frame = FRAME_ANIMATED) : Controller(game, entity), instant(instant), flag(frame), time(0.0f) {
|
||||
Sprite(IGame *game, int entity, bool instant = true, int frame = FRAME_ANIMATED) : Controller(game, entity), instant(instant), flag(frame), time(0), velocity(0) {
|
||||
if (frame >= 0) { // specific frame
|
||||
this->frame = frame;
|
||||
} else if (frame == FRAME_RANDOM) { // random frame
|
||||
@@ -57,6 +58,8 @@ struct Sprite : Controller {
|
||||
if (instant && time >= (1.0f / SPRITE_FPS))
|
||||
remove = true;
|
||||
|
||||
pos += velocity * Core::deltaTime;
|
||||
|
||||
if (remove) {
|
||||
level->entityRemove(entity);
|
||||
delete this;
|
||||
|
@@ -94,13 +94,13 @@ struct Dart : Controller {
|
||||
}
|
||||
};
|
||||
|
||||
struct Dartgun : Controller {
|
||||
struct TrapDartgun : Controller {
|
||||
enum {
|
||||
STATE_IDLE,
|
||||
STATE_FIRE
|
||||
};
|
||||
|
||||
Dartgun(IGame *game, int entity) : Controller(game, entity) {}
|
||||
TrapDartgun(IGame *game, int entity) : Controller(game, entity) {}
|
||||
|
||||
virtual bool activate() {
|
||||
if (!Controller::activate())
|
||||
@@ -136,15 +136,59 @@ struct Dartgun : Controller {
|
||||
}
|
||||
};
|
||||
|
||||
struct Boulder : Controller {
|
||||
#define BOULDER_DAMAGE_GROUND 1001
|
||||
#define BOULDER_DAMAGE_AIR 100
|
||||
|
||||
Boulder(IGame *game, int entity) : Controller(game, entity) {}
|
||||
struct TrapBoulder : Controller {
|
||||
enum {
|
||||
STATE_FALL,
|
||||
STATE_ROLL,
|
||||
};
|
||||
|
||||
vec3 velocity;
|
||||
|
||||
TrapBoulder(IGame *game, int entity) : Controller(game, entity), velocity(0) {}
|
||||
|
||||
virtual void update() {
|
||||
if (getEntity().flags.active == TR::ACTIVE) {
|
||||
updateAnimation(true);
|
||||
updateEntity();
|
||||
if (activeState != asActive) return;
|
||||
|
||||
TR::Level::FloorInfo info;
|
||||
level->getFloorInfo(getRoomIndex(), int(pos.x), int(pos.y), int(pos.z), info);
|
||||
|
||||
vec3 dir = getDir();
|
||||
|
||||
if (pos.y >= info.floor - 256) {
|
||||
pos.y = info.floor;
|
||||
velocity = dir * animation.getSpeed();
|
||||
if (state != STATE_ROLL)
|
||||
animation.setState(STATE_ROLL);
|
||||
} else {
|
||||
if (velocity.y == 0.0f)
|
||||
velocity.y = 10.0f;
|
||||
velocity.y += GRAVITY * Core::deltaTime;
|
||||
animation.setState(STATE_FALL);
|
||||
}
|
||||
|
||||
vec3 p = pos;
|
||||
pos += velocity * (30.0f * Core::deltaTime);
|
||||
|
||||
if (info.roomNext != TR::NO_ROOM)
|
||||
getEntity().room = info.roomNext;
|
||||
|
||||
vec3 v = pos + getDir() * 512.0f;
|
||||
level->getFloorInfo(getRoomIndex(), int(v.x), int(v.y), int(v.z), info);
|
||||
if (pos.y > info.floor) {
|
||||
pos = p;
|
||||
deactivate();
|
||||
return;
|
||||
}
|
||||
|
||||
Controller *lara = (Controller*)level->laraController;
|
||||
if (collide(lara))
|
||||
lara->hit(BOULDER_DAMAGE_GROUND, this);
|
||||
|
||||
updateAnimation(true);
|
||||
updateEntity();
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user