mirror of
https://github.com/XProger/OpenLara.git
synced 2025-01-17 21:09:00 +01:00
This commit is contained in:
parent
36fce871cb
commit
ba5ffaf977
BIN
bin/OpenLara.exe
BIN
bin/OpenLara.exe
Binary file not shown.
@ -57,8 +57,10 @@ struct Camera : Controller {
|
|||||||
|
|
||||||
virtual void update() {
|
virtual void update() {
|
||||||
int lookAt = -1;
|
int lookAt = -1;
|
||||||
if (owner->target > -1) lookAt = owner->target;
|
|
||||||
if (actTargetEntity > -1) lookAt = actTargetEntity;
|
if (actTargetEntity > -1) lookAt = actTargetEntity;
|
||||||
|
if (owner->target > -1) lookAt = owner->target;
|
||||||
|
|
||||||
|
owner->viewTarget = lookAt;
|
||||||
|
|
||||||
if (timer > 0.0f) {
|
if (timer > 0.0f) {
|
||||||
timer -= Core::deltaTime;
|
timer -= Core::deltaTime;
|
||||||
|
@ -52,7 +52,9 @@ struct Controller {
|
|||||||
meshes[i] = model->mStart + i;
|
meshes[i] = model->mStart + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void meshSwap(TR::Model *model, int mask) {
|
void meshSwap(TR::Model *model, int mask = 0xFFFFFFFF) {
|
||||||
|
if (!meshes) initMeshOverrides();
|
||||||
|
|
||||||
for (int i = 0; i < model->mCount; i++) {
|
for (int i = 0; i < model->mCount; i++) {
|
||||||
int index = model->mStart + i;
|
int index = model->mStart + i;
|
||||||
if (((1 << i) & mask) && level->meshOffsets[index])
|
if (((1 << i) & mask) && level->meshOffsets[index])
|
||||||
|
14
src/format.h
14
src/format.h
@ -9,6 +9,10 @@
|
|||||||
|
|
||||||
namespace TR {
|
namespace TR {
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FLOOR_BLOCK = -127,
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ANIM_CMD_NONE ,
|
ANIM_CMD_NONE ,
|
||||||
ANIM_CMD_OFFSET ,
|
ANIM_CMD_OFFSET ,
|
||||||
@ -387,6 +391,7 @@ namespace TR {
|
|||||||
PUZZLE_4 = 113, // sprite
|
PUZZLE_4 = 113, // sprite
|
||||||
|
|
||||||
HOLE_PUZZLE = 118,
|
HOLE_PUZZLE = 118,
|
||||||
|
HOLE_PUZZLE_SET = 122,
|
||||||
|
|
||||||
PICKUP = 126, // sprite
|
PICKUP = 126, // sprite
|
||||||
|
|
||||||
@ -766,6 +771,7 @@ namespace TR {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
Model *muzzleFlash;
|
Model *muzzleFlash;
|
||||||
|
Model *puzzleSet;
|
||||||
} extra;
|
} extra;
|
||||||
|
|
||||||
Level(const char *name, bool demo) {
|
Level(const char *name, bool demo) {
|
||||||
@ -899,7 +905,8 @@ namespace TR {
|
|||||||
memset(&extra, 0, sizeof(extra));
|
memset(&extra, 0, sizeof(extra));
|
||||||
for (int i = 0; i < modelsCount; i++)
|
for (int i = 0; i < modelsCount; i++)
|
||||||
switch (models[i].type) {
|
switch (models[i].type) {
|
||||||
case Entity::MUZZLE_FLASH : extra.muzzleFlash = &models[i]; break;
|
case Entity::MUZZLE_FLASH : extra.muzzleFlash = &models[i]; break;
|
||||||
|
case Entity::HOLE_PUZZLE_SET : extra.puzzleSet = &models[i]; break;
|
||||||
default : ;
|
default : ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1032,6 +1039,9 @@ namespace TR {
|
|||||||
info.trigger = Trigger::ACTIVATE;
|
info.trigger = Trigger::ACTIVATE;
|
||||||
info.trigCmdCount = 0;
|
info.trigCmdCount = 0;
|
||||||
|
|
||||||
|
if (s.floor == -127)
|
||||||
|
return;
|
||||||
|
|
||||||
Room::Sector *sBelow = &s;
|
Room::Sector *sBelow = &s;
|
||||||
while (sBelow->roomBelow != 0xFF) sBelow = &getSector(sBelow->roomBelow, x, z, dx, dz);
|
while (sBelow->roomBelow != 0xFF) sBelow = &getSector(sBelow->roomBelow, x, z, dx, dz);
|
||||||
info.floor = 256 * sBelow->floor;
|
info.floor = 256 * sBelow->floor;
|
||||||
@ -1072,7 +1082,7 @@ namespace TR {
|
|||||||
if (ey >= y - 128 && ey < info.floor)
|
if (ey >= y - 128 && ey < info.floor)
|
||||||
info.floor = ey;
|
info.floor = ey;
|
||||||
if (ey < y - 128 && ey > info.ceiling)
|
if (ey < y - 128 && ey > info.ceiling)
|
||||||
info.ceiling = ey + (e.type == Entity::TRAP_FLOOR ? 256 : 0);
|
info.ceiling = ey + (e.type == Entity::TRAP_FLOOR ? 0 : 256);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
65
src/lara.h
65
src/lara.h
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#define PICKUP_FRAME_GROUND 40
|
#define PICKUP_FRAME_GROUND 40
|
||||||
#define PICKUP_FRAME_UNDERWATER 16
|
#define PICKUP_FRAME_UNDERWATER 16
|
||||||
|
#define PUZZLE_FRAME 80
|
||||||
|
|
||||||
#define MAX_TRIGGER_ACTIONS 64
|
#define MAX_TRIGGER_ACTIONS 64
|
||||||
|
|
||||||
@ -193,8 +194,9 @@ struct Lara : Character {
|
|||||||
|
|
||||||
Inventory inventory;
|
Inventory inventory;
|
||||||
int lastPickUp;
|
int lastPickUp;
|
||||||
|
int viewTarget;
|
||||||
|
|
||||||
Lara(TR::Level *level, int entity, bool home) : Character(level, entity, 1000), home(home), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), chestOffset(pos) {
|
Lara(TR::Level *level, int entity, bool home) : Character(level, entity, 1000), home(home), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), chestOffset(pos), viewTarget(-1) {
|
||||||
animation.setAnim(ANIM_STAND);
|
animation.setAnim(ANIM_STAND);
|
||||||
getEntity().flags.active = 1;
|
getEntity().flags.active = 1;
|
||||||
initMeshOverrides();
|
initMeshOverrides();
|
||||||
@ -264,12 +266,12 @@ struct Lara : Character {
|
|||||||
pos = vec3(31390, -2048, 33472);
|
pos = vec3(31390, -2048, 33472);
|
||||||
angle = vec3(0.0f, 0.0f, 0.0f);
|
angle = vec3(0.0f, 0.0f, 0.0f);
|
||||||
getEntity().room = 63;
|
getEntity().room = 63;
|
||||||
|
*/
|
||||||
// level 2 (trap door)
|
// level 2 (trap door)
|
||||||
pos = vec3(21987, -1024, 29144);
|
pos = vec3(21987, -1024, 29144);
|
||||||
angle = vec3(0.0f, PI * 3.0f * 0.5f, 0.0f);
|
angle = vec3(0.0f, PI * 3.0f * 0.5f, 0.0f);
|
||||||
getEntity().room = 61;
|
getEntity().room = 61;
|
||||||
|
/*
|
||||||
// level 3a
|
// level 3a
|
||||||
pos = vec3(41015, 3584, 34494);
|
pos = vec3(41015, 3584, 34494);
|
||||||
angle = vec3(0.0f, -PI, 0.0f);
|
angle = vec3(0.0f, -PI, 0.0f);
|
||||||
@ -376,6 +378,15 @@ struct Lara : Character {
|
|||||||
return wpnCurrent == Weapon::EMPTY || arms[0].anim == Weapon::Anim::NONE;
|
return wpnCurrent == Weapon::EMPTY || arms[0].anim == Weapon::Anim::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool canLookAt() {
|
||||||
|
return (stand == STAND_GROUND || stand == STAND_SLIDE)
|
||||||
|
&& state != STATE_REACH
|
||||||
|
&& state != STATE_PUSH_BLOCK
|
||||||
|
&& state != STATE_PULL_BLOCK
|
||||||
|
&& state != STATE_PUSH_PULL_READY
|
||||||
|
&& state != STATE_PICK_UP;
|
||||||
|
}
|
||||||
|
|
||||||
bool canDrawWeapon() {
|
bool canDrawWeapon() {
|
||||||
return wpnCurrent != Weapon::EMPTY
|
return wpnCurrent != Weapon::EMPTY
|
||||||
&& emptyHands()
|
&& emptyHands()
|
||||||
@ -713,7 +724,8 @@ struct Lara : Character {
|
|||||||
} else
|
} else
|
||||||
animation.overrideMask &= ~(BODY_ARM_R | BODY_ARM_L);
|
animation.overrideMask &= ~(BODY_ARM_R | BODY_ARM_L);
|
||||||
|
|
||||||
lookAt(target);
|
|
||||||
|
lookAt(viewTarget);
|
||||||
|
|
||||||
if (wpnCurrent == Weapon::SHOTGUN)
|
if (wpnCurrent == Weapon::SHOTGUN)
|
||||||
aimShotgun();
|
aimShotgun();
|
||||||
@ -725,15 +737,16 @@ struct Lara : Character {
|
|||||||
float speed = 8.0f * Core::deltaTime;
|
float speed = 8.0f * Core::deltaTime;
|
||||||
quat rot;
|
quat rot;
|
||||||
|
|
||||||
|
bool can = canLookAt();
|
||||||
// chest
|
// chest
|
||||||
if ((stand == STAND_GROUND || stand == STAND_SLIDE) && aim(target, 7, vec4(-PI * 0.4f, PI * 0.4f, -PI * 0.9f, PI * 0.9f), rot))
|
if (can && aim(target, 7, vec4(-PI * 0.4f, PI * 0.4f, -PI * 0.9f, PI * 0.9f), rot))
|
||||||
rotChest = rotChest.slerp(quat(0, 0, 0, 1).slerp(rot, 0.5f), speed);
|
rotChest = rotChest.slerp(quat(0, 0, 0, 1).slerp(rot, 0.5f), speed);
|
||||||
else
|
else
|
||||||
rotChest = rotChest.slerp(quat(0, 0, 0, 1), speed);
|
rotChest = rotChest.slerp(quat(0, 0, 0, 1), speed);
|
||||||
animation.overrides[7] = rotChest * animation.overrides[7];
|
animation.overrides[7] = rotChest * animation.overrides[7];
|
||||||
|
|
||||||
// head
|
// head
|
||||||
if (aim(target, 14, vec4(-PI * 0.25f, PI * 0.25f, -PI * 0.5f, PI * 0.5f), rot))
|
if (can && aim(target, 14, vec4(-PI * 0.25f, PI * 0.25f, -PI * 0.5f, PI * 0.5f), rot))
|
||||||
rotHead = rotHead.slerp(rot, speed);
|
rotHead = rotHead.slerp(rot, speed);
|
||||||
else
|
else
|
||||||
rotHead = rotHead.slerp(quat(0, 0, 0, 1), speed);
|
rotHead = rotHead.slerp(quat(0, 0, 0, 1), speed);
|
||||||
@ -941,15 +954,21 @@ struct Lara : Character {
|
|||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
case TR::Level::Trigger::KEY :
|
case TR::Level::Trigger::KEY :
|
||||||
actionState = STATE_USE_KEY;
|
if (level->entities[info.trigCmd[0].args].flags.active)
|
||||||
|
return;
|
||||||
|
actionState = level->entities[info.trigCmd[0].args].type == TR::Entity::HOLE_KEY ? STATE_USE_KEY : STATE_USE_PUZZLE;
|
||||||
if (isActive || !isPressed(ACTION) || state == actionState || !emptyHands()) // TODO: STATE_USE_PUZZLE
|
if (isActive || !isPressed(ACTION) || state == actionState || !emptyHands()) // TODO: STATE_USE_PUZZLE
|
||||||
return;
|
return;
|
||||||
if (!checkAngle(level->entities[info.trigCmd[0].args].rotation))
|
if (!checkAngle(level->entities[info.trigCmd[0].args].rotation))
|
||||||
return;
|
return;
|
||||||
if (animation.canSetState(actionState) && !useItem(TR::Entity::NONE, level->entities[info.trigCmd[0].args].type)) {
|
if (animation.canSetState(actionState)) {
|
||||||
playSound(TR::SND_NO, pos, Sound::PAN);
|
if (false) { //!useItem(TR::Entity::NONE, level->entities[info.trigCmd[0].args].type)) {
|
||||||
|
playSound(TR::SND_NO, pos, Sound::PAN);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else
|
||||||
return;
|
return;
|
||||||
}
|
lastPickUp = info.trigCmd[0].args; // TODO: it's not pickup, it's key/puzzle hole
|
||||||
break;
|
break;
|
||||||
case TR::Level::Trigger::PICKUP :
|
case TR::Level::Trigger::PICKUP :
|
||||||
if (!isActive) // check if item is not picked up
|
if (!isActive) // check if item is not picked up
|
||||||
@ -964,6 +983,9 @@ struct Lara : Character {
|
|||||||
if (!animation.setState(actionState)) return;
|
if (!animation.setState(actionState)) return;
|
||||||
|
|
||||||
if (info.trigger == TR::Level::Trigger::SWITCH || info.trigger == TR::Level::Trigger::KEY) {
|
if (info.trigger == TR::Level::Trigger::SWITCH || info.trigger == TR::Level::Trigger::KEY) {
|
||||||
|
if (info.trigger == TR::Level::Trigger::KEY)
|
||||||
|
level->entities[info.trigCmd[0].args].flags.active = true;
|
||||||
|
|
||||||
TR::Entity &p = level->entities[info.trigCmd[0].args];
|
TR::Entity &p = level->entities[info.trigCmd[0].args];
|
||||||
angle.y = p.rotation;
|
angle.y = p.rotation;
|
||||||
angle.x = 0;
|
angle.x = 0;
|
||||||
@ -1370,14 +1392,23 @@ struct Lara : Character {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void doCustomCommand(int curFrame, int prevFrame) {
|
virtual void doCustomCommand(int curFrame, int prevFrame) {
|
||||||
if (state == STATE_PICK_UP) {
|
switch (state) {
|
||||||
TR::Entity &item = level->entities[lastPickUp];
|
case STATE_PICK_UP : {
|
||||||
if (!item.flags.invisible) {
|
TR::Entity &item = level->entities[lastPickUp];
|
||||||
int pickupFrame = stand == STAND_GROUND ? PICKUP_FRAME_GROUND : PICKUP_FRAME_UNDERWATER;
|
if (!item.flags.invisible) {
|
||||||
if (animation.isFrameActive(pickupFrame)) {
|
int pickupFrame = stand == STAND_GROUND ? PICKUP_FRAME_GROUND : PICKUP_FRAME_UNDERWATER;
|
||||||
item.flags.invisible = true;
|
if (animation.isFrameActive(pickupFrame)) {
|
||||||
inventory.add(item.type, 1);
|
item.flags.invisible = true;
|
||||||
|
inventory.add(item.type, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STATE_USE_PUZZLE : {
|
||||||
|
TR::Entity &item = level->entities[lastPickUp];
|
||||||
|
if (animation.isFrameActive(PUZZLE_FRAME))
|
||||||
|
((Controller*)item.controller)->meshSwap(level->extra.puzzleSet);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,7 +385,7 @@ struct Level {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void renderEntity(const TR::Entity &entity) {
|
void renderEntity(const TR::Entity &entity) {
|
||||||
// if (entity.room != lara->getRoomIndex()) return;
|
//if (entity.room != lara->getRoomIndex()) return;
|
||||||
if (entity.type == TR::Entity::NONE) return;
|
if (entity.type == TR::Entity::NONE) return;
|
||||||
ASSERT(entity.controller);
|
ASSERT(entity.controller);
|
||||||
|
|
||||||
@ -495,7 +495,7 @@ struct Level {
|
|||||||
// Debug::Level::portals(level);
|
// Debug::Level::portals(level);
|
||||||
// Debug::Level::meshes(level);
|
// Debug::Level::meshes(level);
|
||||||
Debug::Level::entities(level);
|
Debug::Level::entities(level);
|
||||||
// Debug::Level::info(level, lara->getEntity(), lara->animation);
|
Debug::Level::info(level, lara->getEntity(), lara->animation);
|
||||||
Debug::end();
|
Debug::end();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
15
src/sound.h
15
src/sound.h
@ -196,10 +196,9 @@ namespace Sound {
|
|||||||
OGG(Stream *stream, int channels) : Decoder(stream, channels), size(stream->size), pos(0) {
|
OGG(Stream *stream, int channels) : Decoder(stream, channels), size(stream->size), pos(0) {
|
||||||
buffer = new char[size]; // TODO: file streaming
|
buffer = new char[size]; // TODO: file streaming
|
||||||
stream->raw(buffer, size);
|
stream->raw(buffer, size);
|
||||||
int error;
|
|
||||||
alloc.alloc_buffer_length_in_bytes = 256 * 1024;
|
alloc.alloc_buffer_length_in_bytes = 256 * 1024;
|
||||||
alloc.alloc_buffer = new char[alloc.alloc_buffer_length_in_bytes];
|
alloc.alloc_buffer = new char[alloc.alloc_buffer_length_in_bytes];
|
||||||
ogg = stb_vorbis_open_memory((unsigned char*)buffer, size, &error, &alloc);
|
ogg = stb_vorbis_open_memory((unsigned char*)buffer, size, NULL, &alloc);
|
||||||
stb_vorbis_info info = stb_vorbis_get_info(ogg);
|
stb_vorbis_info info = stb_vorbis_get_info(ogg);
|
||||||
channels = info.channels;
|
channels = info.channels;
|
||||||
}
|
}
|
||||||
@ -220,7 +219,10 @@ namespace Sound {
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replay
|
virtual void replay() {
|
||||||
|
stb_vorbis_close(ogg);
|
||||||
|
ogg = stb_vorbis_open_memory((unsigned char*)buffer, size, NULL, &alloc);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -321,8 +323,11 @@ namespace Sound {
|
|||||||
while (i < count) {
|
while (i < count) {
|
||||||
int res = decoder->decode(&frames[i], count - i);
|
int res = decoder->decode(&frames[i], count - i);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
if (i == 0) isPlaying = false;
|
if (!(flags & Flags::LOOP)) {
|
||||||
break;
|
if (i == 0) isPlaying = false;
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
decoder->replay();
|
||||||
}
|
}
|
||||||
i += res;
|
i += res;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ struct Trigger : Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inState())
|
if (!inState() && entity.type != TR::Entity::HOLE_KEY && entity.type != TR::Entity::HOLE_PUZZLE)
|
||||||
animation.setState(state != baseState ? baseState : (entity.type == TR::Entity::TRAP_BLADE ? 2 : (baseState ^ 1)));
|
animation.setState(state != baseState ? baseState : (entity.type == TR::Entity::TRAP_BLADE ? 2 : (baseState ^ 1)));
|
||||||
|
|
||||||
updateAnimation(true);
|
updateAnimation(true);
|
||||||
@ -179,8 +179,45 @@ struct Block : Controller {
|
|||||||
|
|
||||||
|
|
||||||
struct Door : Trigger {
|
struct Door : Trigger {
|
||||||
|
int8 *floor[2], orig[2];
|
||||||
|
|
||||||
Door(TR::Level *level, int entity) : Trigger(level, entity, true) {}
|
Door(TR::Level *level, int entity) : Trigger(level, entity, true) {
|
||||||
|
TR::Entity &e = getEntity();
|
||||||
|
TR::Level::FloorInfo info;
|
||||||
|
vec3 p = pos - getDir() * 1024.0f;
|
||||||
|
|
||||||
|
level->getFloorInfo(e.room, (int)p.x, (int)p.y, (int)p.z, info);
|
||||||
|
int dx, dz;
|
||||||
|
TR::Room::Sector *s = &level->getSector(e.room, (int)p.x, (int)p.z, dx, dz);
|
||||||
|
|
||||||
|
orig[0] = *(floor[0] = &s->floor);
|
||||||
|
|
||||||
|
if (info.roomNext != 0xFF) {
|
||||||
|
s = &level->getSector(info.roomNext, e.x, e.z, dx, dz);
|
||||||
|
orig[1] = *(floor[1] = &s->floor);
|
||||||
|
} else
|
||||||
|
floor[1] = NULL;
|
||||||
|
|
||||||
|
updateBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateBlock() {
|
||||||
|
int8 v[2];
|
||||||
|
if (getEntity().flags.active) {
|
||||||
|
v[0] = orig[0];
|
||||||
|
v[1] = orig[1];
|
||||||
|
} else
|
||||||
|
v[0] = v[1] = TR::FLOOR_BLOCK;
|
||||||
|
|
||||||
|
if (floor[0]) *floor[0] = v[0];
|
||||||
|
if (floor[1]) *floor[1] = v[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool activate(ActionCommand *cmd) {
|
||||||
|
bool res = Trigger::activate(cmd);
|
||||||
|
updateBlock();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DoorFloor : Trigger {
|
struct DoorFloor : Trigger {
|
||||||
@ -235,7 +272,7 @@ struct TrapFloor : Trigger {
|
|||||||
e.room = info.roomBelow;
|
e.room = info.roomBelow;
|
||||||
|
|
||||||
if (pos.y > info.floor) {
|
if (pos.y > info.floor) {
|
||||||
pos.y = info.floor;
|
pos.y = (float)info.floor;
|
||||||
animation.setState(STATE_DOWN);
|
animation.setState(STATE_DOWN);
|
||||||
}
|
}
|
||||||
updateEntity();
|
updateEntity();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user