mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-15 09:34:18 +02:00
#23 fix items opacity; fix water mask for desktop NVIDIA cards; #22 fix lava trap; cutscene wait timer (for sound sync WIP); #15 extern osGetTime
This commit is contained in:
@@ -413,7 +413,7 @@ struct Controller {
|
||||
} while (!cmd.end);
|
||||
}
|
||||
|
||||
virtual void getSaveData(TR::SaveGame::Entity &data) {
|
||||
virtual bool getSaveData(TR::SaveGame::Entity &data) {
|
||||
const TR::Entity &e = getEntity();
|
||||
const TR::Model *m = getModel();
|
||||
if (entity < level->entitiesBaseCount) {
|
||||
@@ -439,6 +439,8 @@ struct Controller {
|
||||
data.animFrame = m ? animation.frameIndex : 0;
|
||||
|
||||
data.extraSize = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void setSaveData(const TR::SaveGame::Entity &data) {
|
||||
@@ -945,6 +947,7 @@ struct Controller {
|
||||
virtual void update() {
|
||||
updateAnimation(true);
|
||||
updateExplosion();
|
||||
updateLights(true);
|
||||
}
|
||||
|
||||
void updateLights(bool lerp = true) {
|
||||
@@ -1043,9 +1046,7 @@ struct Controller {
|
||||
}
|
||||
|
||||
void renderShadow(MeshBuilder *mesh) {
|
||||
const TR::Entity &entity = getEntity();
|
||||
|
||||
if (Core::pass != Core::passCompose || !entity.castShadow() || entity.isActor())
|
||||
if (Core::pass != Core::passCompose || level->isCutsceneLevel())
|
||||
return;
|
||||
|
||||
Box boxL = getBoundingBoxLocal();
|
||||
|
33
src/core.h
33
src/core.h
@@ -162,7 +162,8 @@ struct KeySet {
|
||||
|
||||
namespace Core {
|
||||
float deltaTime;
|
||||
int width, height;
|
||||
int lastTime;
|
||||
int width, height;
|
||||
|
||||
struct {
|
||||
int maxVectors;
|
||||
@@ -237,6 +238,17 @@ namespace Core {
|
||||
bool reverb;
|
||||
} audio;
|
||||
} settings;
|
||||
|
||||
bool resetState;
|
||||
|
||||
int getTime() {
|
||||
return osGetTime();
|
||||
}
|
||||
|
||||
void resetTime() {
|
||||
lastTime = getTime();
|
||||
resetState = true;
|
||||
}
|
||||
}
|
||||
|
||||
#include "input.h"
|
||||
@@ -444,8 +456,6 @@ struct Vertex {
|
||||
enum CullFace { cfNone, cfBack, cfFront };
|
||||
enum BlendMode { bmNone, bmAlpha, bmAdd, bmMult, bmPremult };
|
||||
|
||||
extern int getTime();
|
||||
|
||||
namespace Core {
|
||||
float eye;
|
||||
vec4 viewport, viewportDef;
|
||||
@@ -506,16 +516,16 @@ namespace Core {
|
||||
}
|
||||
|
||||
void stop() {
|
||||
if (fpsTime < getTime()) {
|
||||
if (fpsTime < Core::getTime()) {
|
||||
LOG("FPS: %d DIP: %d TRI: %d\n", fps, dips, tris);
|
||||
#ifdef PROFILE
|
||||
LOG("frame time: %d mcs\n", tFrame / 1000);
|
||||
#endif
|
||||
fps = frame;
|
||||
frame = 0;
|
||||
fpsTime = getTime() + 1000;
|
||||
fpsTime = Core::getTime() + 1000;
|
||||
} else
|
||||
frame++;
|
||||
frame++;
|
||||
}
|
||||
} stats;
|
||||
}
|
||||
@@ -723,6 +733,7 @@ namespace Core {
|
||||
#ifdef __RPI__
|
||||
settings.detail.setShadows(Core::Settings::LOW);
|
||||
#endif
|
||||
resetTime();
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
@@ -762,6 +773,16 @@ namespace Core {
|
||||
return cache.count++;
|
||||
}
|
||||
|
||||
bool update() {
|
||||
resetState = false;
|
||||
int time = getTime();
|
||||
if (time - lastTime <= 0)
|
||||
return false;
|
||||
deltaTime = (time - lastTime) * 0.001f;
|
||||
lastTime = time;
|
||||
return true;
|
||||
}
|
||||
|
||||
void validateRenderState() {
|
||||
int32 mask = renderState ^ active.renderState;
|
||||
if (!mask) return;
|
||||
|
17
src/enemy.h
17
src/enemy.h
@@ -77,17 +77,20 @@ struct Enemy : Character {
|
||||
delete path;
|
||||
}
|
||||
|
||||
virtual void getSaveData(TR::SaveGame::Entity &data) {
|
||||
virtual bool getSaveData(TR::SaveGame::Entity &data) {
|
||||
Character::getSaveData(data);
|
||||
data.extraSize = sizeof(data.extra.enemy);
|
||||
data.extra.enemy.health = uint16(health);
|
||||
data.extra.enemy.mood = uint16(mood);
|
||||
data.extra.enemy.health = health;
|
||||
data.extra.enemy.mood = mood;
|
||||
data.extra.enemy.targetBox = targetBox;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void setSaveData(const TR::SaveGame::Entity &data) {
|
||||
Character::setSaveData(data);
|
||||
health = float(data.extra.enemy.health);
|
||||
mood = Mood(data.extra.enemy.mood);
|
||||
health = data.extra.enemy.health;
|
||||
mood = Mood(data.extra.enemy.mood);
|
||||
targetBox = data.extra.enemy.targetBox;
|
||||
}
|
||||
|
||||
virtual bool activate() {
|
||||
@@ -1321,9 +1324,7 @@ struct Doppelganger : Enemy {
|
||||
|
||||
|
||||
struct ScionTarget : Enemy {
|
||||
float timer;
|
||||
|
||||
ScionTarget(IGame *game, int entity) : Enemy(game, entity, 5, 0, 0, 0), timer(0.0f) {}
|
||||
ScionTarget(IGame *game, int entity) : Enemy(game, entity, 5, 0, 0, 0) {}
|
||||
|
||||
virtual void update() {
|
||||
Controller::update();
|
||||
|
91
src/format.h
91
src/format.h
@@ -1648,10 +1648,10 @@ namespace TR {
|
||||
return type;
|
||||
|
||||
if (version & VER_TR2)
|
||||
type = TR::Entity::Type(type + TR2_TYPES_START);
|
||||
type = Type(type + TR2_TYPES_START);
|
||||
|
||||
if (version & VER_TR3)
|
||||
type = TR::Entity::Type(type + TR3_TYPES_START);
|
||||
type = Type(type + TR3_TYPES_START);
|
||||
|
||||
#define REMAP_2(TYPE) case _##TYPE : return TYPE
|
||||
#define REMAP_3(TYPE) case __##TYPE : return TYPE
|
||||
@@ -2327,6 +2327,25 @@ namespace TR {
|
||||
|
||||
struct SaveGame {
|
||||
|
||||
struct Item {
|
||||
uint16 type;
|
||||
uint16 count;
|
||||
};
|
||||
|
||||
struct Progress {
|
||||
uint32 size;
|
||||
uint32 time;
|
||||
uint32 distance;
|
||||
uint8 levelID;
|
||||
uint8 mediUsed;
|
||||
uint8 secrets;
|
||||
uint8 pickups;
|
||||
uint16 ammoUsed;
|
||||
uint8 kills;
|
||||
uint8 itemsCount;
|
||||
// Item items[itemsCount]
|
||||
};
|
||||
|
||||
struct Entity {
|
||||
// base
|
||||
int32 x, y, z;
|
||||
@@ -2338,64 +2357,56 @@ namespace TR {
|
||||
uint16 animIndex;
|
||||
uint16 animFrame;
|
||||
// common
|
||||
uint8 room;
|
||||
uint8 extraSize;
|
||||
uint16 room;
|
||||
uint16 extraSize;
|
||||
union Extra {
|
||||
struct {
|
||||
float velX, velY, velZ;
|
||||
uint16 angleX;
|
||||
uint16 health;
|
||||
uint16 oxygen;
|
||||
uint16 stamina;
|
||||
uint8 itemHands;
|
||||
uint8 itemBack;
|
||||
uint8 itemHolster;
|
||||
float angleX;
|
||||
float health;
|
||||
float oxygen;
|
||||
float stamina;
|
||||
float poison;
|
||||
float freeze;
|
||||
uint16 itemHands;
|
||||
uint16 itemBack;
|
||||
uint16 itemHolster;
|
||||
union {
|
||||
struct { uint8 wet:1, burn:1; };
|
||||
uint8 value;
|
||||
struct { uint16 wet:1, burn:1; };
|
||||
uint16 value;
|
||||
} flags;
|
||||
} lara;
|
||||
struct {
|
||||
uint16 health;
|
||||
float health;
|
||||
uint16 mood;
|
||||
uint16 targetBox;
|
||||
} enemy;
|
||||
|
||||
struct {
|
||||
int32 jointIndex;
|
||||
float sleep;
|
||||
} flame;
|
||||
} extra;
|
||||
};
|
||||
|
||||
struct Item {
|
||||
uint16 type;
|
||||
uint16 count;
|
||||
};
|
||||
|
||||
struct CurrentState {
|
||||
// EntityState entities[entitiesCount];
|
||||
ByteFlags flipmaps[MAX_FLIPMAP_COUNT];
|
||||
ByteFlags tracks[MAX_TRACKS_COUNT];
|
||||
|
||||
uint32 fogColor;
|
||||
uint16 secrets;
|
||||
uint16 fogColor;
|
||||
union {
|
||||
struct { uint16 track:8, flipped:1; };
|
||||
uint16 value;
|
||||
} flags;
|
||||
|
||||
ByteFlags flipmaps[MAX_FLIPMAP_COUNT];
|
||||
ByteFlags tracks[MAX_TRACKS_COUNT];
|
||||
uint16 entitiesCount;
|
||||
Progress progress;
|
||||
//Entity entities[entitiesCount];
|
||||
};
|
||||
|
||||
uint32 size;
|
||||
uint16 levelID;
|
||||
// full game stats
|
||||
uint16 mediUsed;
|
||||
uint16 pickups;
|
||||
uint16 secrets;
|
||||
uint32 kills;
|
||||
uint32 ammoUsed;
|
||||
uint32 distance;
|
||||
uint32 time;
|
||||
|
||||
uint16 itemsCount; // 0 -> skip inventory items array
|
||||
uint16 entitiesCount; // 0 -> skip current state
|
||||
|
||||
// Item items[itemsCount]
|
||||
int32 size;
|
||||
uint16 version;
|
||||
uint16 progressCount;
|
||||
// Progress progress[levelsCount];
|
||||
// CurrentState currentState;
|
||||
};
|
||||
|
||||
|
21
src/game.h
21
src/game.h
@@ -75,16 +75,21 @@ namespace Game {
|
||||
Core::deltaTime = dt;
|
||||
}
|
||||
|
||||
void update(float delta) {
|
||||
bool update() {
|
||||
PROFILE_MARKER("UPDATE");
|
||||
|
||||
if (!Core::update())
|
||||
return false;
|
||||
|
||||
float delta = Core::deltaTime;
|
||||
|
||||
if (nextLevel) {
|
||||
startLevel(nextLevel);
|
||||
nextLevel = NULL;
|
||||
}
|
||||
|
||||
if (level->isEnded)
|
||||
return;
|
||||
return true;
|
||||
|
||||
Input::update();
|
||||
|
||||
@@ -94,7 +99,7 @@ namespace Game {
|
||||
Input::down[ikV] = false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
if (Input::down[ikS]) {
|
||||
if (level->lara->canSaveGame())
|
||||
level->saveGame(0);
|
||||
@@ -105,16 +110,10 @@ namespace Game {
|
||||
level->loadGame(0);
|
||||
Input::down[ikL] = false;
|
||||
}
|
||||
*/
|
||||
|
||||
if (!level->level.isCutsceneLevel())
|
||||
delta = min(0.2f, delta);
|
||||
|
||||
if (level->cutsceneFirstFrame) {
|
||||
level->cutsceneFirstFrame = false;
|
||||
delta = 1.0f / 30.0f;
|
||||
}
|
||||
|
||||
Core::deltaTime = delta;
|
||||
UI::update();
|
||||
|
||||
@@ -122,7 +121,11 @@ namespace Game {
|
||||
Core::deltaTime = min(delta, 1.0f / 30.0f);
|
||||
Game::updateTick();
|
||||
delta -= Core::deltaTime;
|
||||
if (Core::resetState) // resetTime was called
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void render() {
|
||||
|
39
src/lara.h
39
src/lara.h
@@ -529,30 +529,33 @@ struct Lara : Character {
|
||||
return health > 0.0f && (state == STATE_STOP || state == STATE_TREAD || state == STATE_SURF_TREAD);
|
||||
}
|
||||
|
||||
virtual void getSaveData(TR::SaveGame::Entity &data) {
|
||||
virtual bool getSaveData(TR::SaveGame::Entity &data) {
|
||||
Character::getSaveData(data);
|
||||
data.extraSize = sizeof(data.extra.lara);
|
||||
data.extra.lara.velX = velocity.x;
|
||||
data.extra.lara.velY = velocity.y;
|
||||
data.extra.lara.velZ = velocity.z;
|
||||
data.extra.lara.angleX = TR::angle(normalizeAngle(angle.x)).value;
|
||||
data.extra.lara.health = uint16(health);
|
||||
data.extra.lara.oxygen = uint16(oxygen);
|
||||
// data.extra.lara.curWeapon = int8(wpnCurrent);
|
||||
// data.extra.lara.emptyHands = emptyHands();
|
||||
/*
|
||||
uint16 itemHands;
|
||||
uint16 itemBack;
|
||||
uint16 itemHolster;
|
||||
*/
|
||||
data.extra.lara.velX = velocity.x;
|
||||
data.extra.lara.velY = velocity.y;
|
||||
data.extra.lara.velZ = velocity.z;
|
||||
data.extra.lara.angleX = angle.x;
|
||||
data.extra.lara.health = health;
|
||||
data.extra.lara.oxygen = oxygen;
|
||||
data.extra.lara.stamina = 0.0f;
|
||||
data.extra.lara.poison = 0.0f;
|
||||
data.extra.lara.freeze = 0.0f;
|
||||
data.extra.lara.itemHands = TR::Entity::LARA;
|
||||
data.extra.lara.itemBack = TR::Entity::SHOTGUN;
|
||||
data.extra.lara.itemHolster = TR::Entity::PISTOLS;
|
||||
data.extra.lara.flags.value = 0;
|
||||
data.extra.lara.flags.burn = 0; // TODO
|
||||
data.extra.lara.flags.wet = 0; // TODO
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void setSaveData(const TR::SaveGame::Entity &data) {
|
||||
Character::setSaveData(data);
|
||||
velocity = vec3(data.extra.lara.velX, data.extra.lara.velY, data.extra.lara.velZ);
|
||||
angle.x = TR::angle(data.extra.lara.angleX);
|
||||
health = float(data.extra.lara.health);
|
||||
oxygen = float(data.extra.lara.oxygen);
|
||||
health = data.extra.lara.health;
|
||||
oxygen = data.extra.lara.oxygen;
|
||||
|
||||
layers[1].mask = layers[2].mask = layers[3].mask = 0;
|
||||
wpnState = Weapon::IS_HIDDEN;
|
||||
@@ -1998,8 +2001,8 @@ struct Lara : Character {
|
||||
effect = TR::Effect(cmd.args);
|
||||
break;
|
||||
case TR::Action::SECRET :
|
||||
if (!(level->state.secrets & (1 << cmd.args))) {
|
||||
level->state.secrets |= 1 << cmd.args;
|
||||
if (!(level->state.progress.secrets & (1 << cmd.args))) {
|
||||
level->state.progress.secrets |= 1 << cmd.args;
|
||||
if (!game->playSound(TR::SND_SECRET, pos))
|
||||
game->playTrack(TR::TRACK_TR1_SECRET);
|
||||
}
|
||||
|
142
src/level.h
142
src/level.h
@@ -46,11 +46,11 @@ struct Level : IGame {
|
||||
|
||||
bool lastTitle;
|
||||
bool isEnded;
|
||||
bool cutsceneFirstFrame;
|
||||
|
||||
TR::Effect effect;
|
||||
float effectTimer;
|
||||
int effectIdx;
|
||||
float cutsceneWaitTimer;
|
||||
|
||||
Texture *cube360;
|
||||
|
||||
@@ -105,40 +105,50 @@ struct Level : IGame {
|
||||
*save = level.save;
|
||||
ptr += sizeof(*save);
|
||||
|
||||
// inventory items
|
||||
save->itemsCount = 0;
|
||||
for (int i = 0; i < inventory.itemsCount; i++) {
|
||||
TR::SaveGame::Item *item = (TR::SaveGame::Item*)ptr;
|
||||
Inventory::Item *invItem = inventory.items[i];
|
||||
// save levels progress
|
||||
save->progressCount = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
bool saveCurrentState = true;
|
||||
|
||||
if (saveCurrentState) {
|
||||
TR::SaveGame::CurrentState *currentState = (TR::SaveGame::CurrentState*)ptr;
|
||||
ptr += sizeof(TR::SaveGame::CurrentState);
|
||||
|
||||
*currentState = level.state;
|
||||
|
||||
// inventory items
|
||||
currentState->progress.itemsCount = 0;
|
||||
for (int i = 0; i < inventory.itemsCount; i++) {
|
||||
TR::SaveGame::Item *item = (TR::SaveGame::Item*)ptr;
|
||||
Inventory::Item *invItem = inventory.items[i];
|
||||
|
||||
if (!TR::Entity::isPickup(TR::Entity::convFromInv(invItem->type))) continue;
|
||||
if (!TR::Entity::isPickup(TR::Entity::convFromInv(invItem->type))) continue;
|
||||
|
||||
item->type = invItem->type;
|
||||
item->count = invItem->count;
|
||||
item->type = invItem->type;
|
||||
item->count = invItem->count;
|
||||
|
||||
ptr += sizeof(*item);
|
||||
save->itemsCount++;
|
||||
ptr += sizeof(*item);
|
||||
currentState->progress.itemsCount++;
|
||||
}
|
||||
|
||||
// level entities
|
||||
currentState->entitiesCount = 0;
|
||||
for (int i = 0; i < level.entitiesCount; i++) {
|
||||
Controller *controller = (Controller*)level.entities[i].controller;
|
||||
TR::SaveGame::Entity *entity = (TR::SaveGame::Entity*)ptr;
|
||||
if (!controller || !controller->getSaveData(*entity)) continue;
|
||||
ptr += (sizeof(TR::SaveGame::Entity) - sizeof(TR::SaveGame::Entity::Extra)) + entity->extraSize;
|
||||
currentState->entitiesCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// level entities
|
||||
save->entitiesCount = 0;
|
||||
for (int i = 0; i < level.entitiesCount; i++) {
|
||||
Controller *controller = (Controller*)level.entities[i].controller;
|
||||
if (!controller || (controller->getEntity().isSprite() && !controller->getEntity().isPickup())) continue;
|
||||
TR::SaveGame::Entity *entity = (TR::SaveGame::Entity*)ptr;
|
||||
controller->getSaveData(*entity);
|
||||
ptr += (sizeof(TR::SaveGame::Entity) - sizeof(TR::SaveGame::Entity::Extra)) + entity->extraSize;
|
||||
save->entitiesCount++;
|
||||
}
|
||||
save->size = ptr - data;
|
||||
save->version = level.version & TR::VER_VERSION;
|
||||
|
||||
// current level state
|
||||
if (save->entitiesCount) {
|
||||
TR::SaveGame::CurrentState *state = (TR::SaveGame::CurrentState*)ptr;
|
||||
*state = level.state;
|
||||
ptr += sizeof(*state);
|
||||
}
|
||||
|
||||
//Stream::write("savegame.dat", data, int(ptr - data));
|
||||
Stream::write("savegame.dat", data, int(ptr - data));
|
||||
delete[] data;
|
||||
|
||||
LOG("Ok\n");
|
||||
@@ -160,15 +170,19 @@ struct Level : IGame {
|
||||
level.save = *save;
|
||||
ptr += sizeof(*save);
|
||||
|
||||
for (int i = 0; i < save->itemsCount; i++) {
|
||||
TR::SaveGame::Item *item = (TR::SaveGame::Item*)ptr;
|
||||
inventory.add(TR::Entity::Type(item->type), item->count, false);
|
||||
ptr += sizeof(*item);
|
||||
}
|
||||
if (save->size > (ptr - data)) { // has current state
|
||||
TR::SaveGame::CurrentState *currentState = (TR::SaveGame::CurrentState*)ptr;
|
||||
ptr += sizeof(TR::SaveGame::CurrentState);
|
||||
|
||||
if (save->entitiesCount) {
|
||||
level.state = *currentState;
|
||||
|
||||
for (int i = 0; i < save->entitiesCount; i++) {
|
||||
for (int i = 0; i < currentState->progress.itemsCount; i++) {
|
||||
TR::SaveGame::Item *item = (TR::SaveGame::Item*)ptr;
|
||||
inventory.add(TR::Entity::Type(item->type), item->count, false);
|
||||
ptr += sizeof(*item);
|
||||
}
|
||||
|
||||
for (int i = 0; i < currentState->entitiesCount; i++) {
|
||||
TR::SaveGame::Entity *entity = (TR::SaveGame::Entity*)ptr;
|
||||
|
||||
Controller *controller;
|
||||
@@ -186,17 +200,13 @@ struct Level : IGame {
|
||||
ptr += (sizeof(TR::SaveGame::Entity) - sizeof(TR::SaveGame::Entity::Extra)) + entity->extraSize;
|
||||
}
|
||||
|
||||
TR::SaveGame::CurrentState *state = (TR::SaveGame::CurrentState*)ptr;
|
||||
level.state = *state;
|
||||
ptr += sizeof(*state);
|
||||
|
||||
delete[] data;
|
||||
|
||||
uint8 track = level.state.flags.track;
|
||||
level.state.flags.track = 0;
|
||||
playTrack(track, true);
|
||||
}
|
||||
|
||||
delete[] data;
|
||||
|
||||
// camera->room = lara->getRoomIndex();
|
||||
// camera->pos = camera->destPos = lara->pos;
|
||||
LOG("Ok\n");
|
||||
@@ -516,11 +526,15 @@ struct Level : IGame {
|
||||
Level *level = (Level*)userData;
|
||||
|
||||
level->sndSoundtrack = Sound::play(stream, vec3(0.0f), 0.01f, 1.0f, Sound::MUSIC);
|
||||
if (level->sndSoundtrack)
|
||||
if (level->sndSoundtrack) {
|
||||
if (level->level.isCutsceneLevel()) {
|
||||
// level->sndSoundtrack->setVolume(0.0f, 0.0f);
|
||||
// level->sndCurrent = level->sndSoundtrack;
|
||||
Core::resetTime();
|
||||
}
|
||||
level->sndSoundtrack->setVolume(1.0f, 0.2f);
|
||||
|
||||
if (level->level.isCutsceneLevel())
|
||||
level->cutsceneFirstFrame = true;
|
||||
}
|
||||
LOG("play soundtrack - %d\n", Core::getTime());
|
||||
}
|
||||
|
||||
virtual void playTrack(uint8 track, bool restart = false) {
|
||||
@@ -575,7 +589,7 @@ struct Level : IGame {
|
||||
}
|
||||
//==============================
|
||||
|
||||
Level(Stream &stream) : level(stream), inventory(this), lara(NULL), isEnded(false), cutsceneFirstFrame(false) {
|
||||
Level(Stream &stream) : level(stream), inventory(this), lara(NULL), isEnded(false), cutsceneWaitTimer(0.0f) {
|
||||
params->time = 0.0f;
|
||||
|
||||
#ifdef _DEBUG
|
||||
@@ -632,12 +646,14 @@ struct Level : IGame {
|
||||
inventory.toggle(Inventory::PAGE_OPTION);
|
||||
}
|
||||
|
||||
effect = TR::Effect::NONE;
|
||||
cube360 = NULL;
|
||||
|
||||
sndSoundtrack = NULL;
|
||||
playTrack(0);
|
||||
sndCurrent = sndSoundtrack;
|
||||
|
||||
effect = TR::Effect::NONE;
|
||||
cube360 = NULL;
|
||||
Core::resetTime();
|
||||
}
|
||||
|
||||
virtual ~Level() {
|
||||
@@ -1252,10 +1268,24 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
void update() {
|
||||
if (level.isCutsceneLevel() && (lara->health > 0.0f && !sndSoundtrack && TR::LEVEL_INFO[level.id].ambientTrack != TR::NO_TRACK)) {
|
||||
if (camera->timer > 0.0f)
|
||||
loadNextLevel();
|
||||
return;
|
||||
if (level.isCutsceneLevel()) {
|
||||
if (!sndSoundtrack && TR::LEVEL_INFO[level.id].ambientTrack != TR::NO_TRACK) {
|
||||
if (camera->timer > 0.0f) // for the case that audio stops before animation ends
|
||||
loadNextLevel();
|
||||
return;
|
||||
}
|
||||
|
||||
if (cutsceneWaitTimer > 0.0f) {
|
||||
cutsceneWaitTimer -= Core::deltaTime;
|
||||
if (cutsceneWaitTimer > 0.0f)
|
||||
return;
|
||||
if (sndSoundtrack)
|
||||
sndSoundtrack->setVolume(1.0f, 0.0f);
|
||||
cutsceneWaitTimer = 0.0f;
|
||||
Core::resetTime();
|
||||
LOG("reset timer - %d\n", Core::getTime());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Input::state[cInventory] && !level.isTitle()) {
|
||||
@@ -1357,10 +1387,8 @@ struct Level : IGame {
|
||||
mesh->transparent = transp;
|
||||
for (int i = 0; i < level.entitiesCount; i++) {
|
||||
TR::Entity &e = level.entities[i];
|
||||
if (!e.controller) continue;
|
||||
int modelIndex = e.modelIndex;
|
||||
if (modelIndex != 0)
|
||||
renderEntity(e);
|
||||
if (!e.controller || e.modelIndex == 0) continue;
|
||||
renderEntity(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -388,7 +388,7 @@ struct MeshBuilder {
|
||||
addSprite(indices, vertices, iCount, vCount, vStartSprite, 0, 0, 0, sprite, TR::Color32(255, 255, 255, 255), TR::Color32(255, 255, 255, 255));
|
||||
}
|
||||
range.iCount = iCount - range.iStart;
|
||||
sequences[i].transp = 2;
|
||||
sequences[i].transp = 1; // alpha blending by default
|
||||
}
|
||||
ASSERT(vCount - vStartSprite <= 0xFFFF);
|
||||
|
||||
|
@@ -3,15 +3,24 @@
|
||||
|
||||
#include "game.h"
|
||||
|
||||
int lastTime, lastJoy = -1;
|
||||
int lastJoy = -1;
|
||||
EGLDisplay display;
|
||||
EGLSurface surface;
|
||||
EGLContext context;
|
||||
|
||||
int getTime() {
|
||||
int osGetTime() {
|
||||
return (int)emscripten_get_now();
|
||||
}
|
||||
|
||||
bool osSave(const char *name, const void *data, int size) {
|
||||
// TODO cookie? idb?
|
||||
FILE *f = fopen(name, "wb");
|
||||
if (!f) return false;
|
||||
fwrite(data, size, 1, f);
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void EMSCRIPTEN_KEEPALIVE snd_fill(Sound::Frame *frames, int count) {
|
||||
Sound::fill(frames, count);
|
||||
@@ -95,14 +104,10 @@ void joyUpdate() {
|
||||
void main_loop() {
|
||||
joyUpdate();
|
||||
|
||||
int time = getTime();
|
||||
if (time - lastTime <= 0)
|
||||
return;
|
||||
Game::update((time - lastTime) * 0.001f);
|
||||
lastTime = time;
|
||||
|
||||
Game::render();
|
||||
eglSwapBuffers(display, surface);
|
||||
if (Game::update()) {
|
||||
Game::render();
|
||||
eglSwapBuffers(display, surface);
|
||||
}
|
||||
}
|
||||
|
||||
bool initGL() {
|
||||
@@ -291,8 +296,6 @@ int main() {
|
||||
emscripten_run_script("snd_init()");
|
||||
resize();
|
||||
|
||||
lastTime = getTime();
|
||||
|
||||
emscripten_set_main_loop(main_loop, 0, true);
|
||||
|
||||
Game::deinit();
|
||||
|
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "game.h"
|
||||
|
||||
int getTime() {
|
||||
int osGetTime() {
|
||||
#ifdef DEBUG
|
||||
LARGE_INTEGER Freq, Count;
|
||||
QueryPerformanceFrequency(&Freq);
|
||||
@@ -28,6 +28,14 @@ int getTime() {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool osSave(const char *name, const void *data, int size) {
|
||||
FILE *f = fopen(name, "wb");
|
||||
if (!f) return false;
|
||||
fwrite(data, size, 1, f);
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
// common input functions
|
||||
InputKey keyToInputKey(int code) {
|
||||
static const int codes[] = {
|
||||
@@ -295,11 +303,16 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
|
||||
HGLRC initGL(HDC hDC) {
|
||||
PIXELFORMATDESCRIPTOR pfd;
|
||||
memset(&pfd, 0, sizeof(pfd));
|
||||
pfd.nSize = sizeof(pfd);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
pfd.cColorBits = 32;
|
||||
pfd.cDepthBits = 24;
|
||||
pfd.nSize = sizeof(pfd);
|
||||
pfd.nVersion = 1;
|
||||
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
|
||||
pfd.cColorBits = 32;
|
||||
pfd.cRedBits = 8;
|
||||
pfd.cGreenBits = 8;
|
||||
pfd.cBlueBits = 8;
|
||||
pfd.cAlphaBits = 8;
|
||||
pfd.cDepthBits = 24;
|
||||
pfd.cStencilBits = 8;
|
||||
|
||||
int format = ChoosePixelFormat(hDC, &pfd);
|
||||
SetPixelFormat(hDC, format, &pfd);
|
||||
@@ -356,7 +369,6 @@ int main(int argc, char** argv) {
|
||||
SetWindowLong(hWnd, GWL_WNDPROC, (LONG)&WndProc);
|
||||
ShowWindow(hWnd, SW_SHOWDEFAULT);
|
||||
|
||||
DWORD lastTime = getTime();
|
||||
MSG msg;
|
||||
|
||||
do {
|
||||
@@ -365,16 +377,10 @@ int main(int argc, char** argv) {
|
||||
DispatchMessage(&msg);
|
||||
} else {
|
||||
joyUpdate();
|
||||
|
||||
DWORD time = getTime();
|
||||
if (time <= lastTime)
|
||||
continue;
|
||||
|
||||
Game::update((time - lastTime) * 0.001f);
|
||||
lastTime = time;
|
||||
|
||||
Game::render();
|
||||
SwapBuffers(hDC);
|
||||
if (Game::update()) {
|
||||
Game::render();
|
||||
SwapBuffers(hDC);
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
Sleep(20);
|
||||
#endif
|
||||
|
@@ -15,8 +15,6 @@ struct Sprite : Controller {
|
||||
float time;
|
||||
vec3 velocity;
|
||||
|
||||
BlendMode blendMode;
|
||||
|
||||
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;
|
||||
|
@@ -126,7 +126,7 @@ struct Flame : Sprite {
|
||||
return flame;
|
||||
}
|
||||
|
||||
int jointIndex;
|
||||
int32 jointIndex;
|
||||
float sleep;
|
||||
|
||||
Flame(IGame *game, int entity) : Sprite(game, entity, false, Sprite::FRAME_ANIMATED), jointIndex(0), sleep(0.0f) {
|
||||
@@ -134,6 +134,20 @@ struct Flame : Sprite {
|
||||
activate();
|
||||
}
|
||||
|
||||
virtual bool getSaveData(TR::SaveGame::Entity &data) {
|
||||
Controller::getSaveData(data);
|
||||
data.extraSize = sizeof(data.extra.flame);
|
||||
data.extra.flame.jointIndex = jointIndex;
|
||||
data.extra.flame.sleep = sleep;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void setSaveData(const TR::SaveGame::Entity &data) {
|
||||
Controller::setSaveData(data);
|
||||
jointIndex = data.extra.flame.jointIndex;
|
||||
sleep = data.extra.flame.sleep;
|
||||
}
|
||||
|
||||
virtual void update() {
|
||||
Sprite::update();
|
||||
game->playSound(TR::SND_FLAME, pos, Sound::PAN);
|
||||
@@ -201,10 +215,14 @@ struct LavaParticle : Sprite {
|
||||
LavaParticle(IGame *game, int entity) : Sprite(game, entity, false, Sprite::FRAME_RANDOM), bounces(0) {
|
||||
float speed = randf() * LAVA_H_SPEED;
|
||||
velocity = vec3(cosf(angle.y) * speed, randf() * LAVA_V_SPEED, sinf(angle.y) * speed);
|
||||
blendMode = bmAdd;
|
||||
game->getMesh()->sequences[-(getEntity().modelIndex + 1)].transp = 2; // fix blending mode to additive
|
||||
activate();
|
||||
}
|
||||
|
||||
virtual bool getSaveData(TR::SaveGame::Entity &data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void update() {
|
||||
applyGravity(velocity.y);
|
||||
Sprite::update();
|
||||
@@ -1138,27 +1156,21 @@ struct MidasHand : Controller {
|
||||
};
|
||||
|
||||
struct TrapLava : Controller {
|
||||
bool done;
|
||||
|
||||
TrapLava(IGame *game, int entity) : Controller(game, entity), done(false) {}
|
||||
TrapLava(IGame *game, int entity) : Controller(game, entity) {}
|
||||
|
||||
virtual void update() {
|
||||
Character *lara = (Character*)level->laraController;
|
||||
if (lara->health > 0.0f && collide(lara))
|
||||
lara->hit(1001.0f, this, TR::HIT_LAVA);
|
||||
|
||||
if (done) {
|
||||
deactivate();
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 dir = getDir();
|
||||
pos += dir * (25.0f * 30.0f * Core::deltaTime);
|
||||
|
||||
roomIndex = getRoomIndex();
|
||||
TR::Room::Sector *s = level->getSector(roomIndex, int(pos.x + dir.x * 2048.0f), int(pos.y), int(pos.z + dir.z * 2048.0f));
|
||||
if (!s || s->floor * 256 != int(pos.y))
|
||||
done = true;
|
||||
return;
|
||||
|
||||
pos += dir * (25.0f * 30.0f * Core::deltaTime);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1411,6 +1423,10 @@ struct Bubble : Sprite {
|
||||
game->waterDrop(pos, 64.0f, 0.01f);
|
||||
}
|
||||
|
||||
virtual bool getSaveData(TR::SaveGame::Entity &data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void update() {
|
||||
pos.y -= speed * Core::deltaTime;
|
||||
angle.x += 30.0f * 13.0f * DEG2RAD * Core::deltaTime;
|
||||
@@ -1426,6 +1442,7 @@ struct Explosion : Sprite {
|
||||
|
||||
Explosion(IGame *game, int entity) : Sprite(game, entity, true, Sprite::FRAME_ANIMATED) {
|
||||
game->playSound(TR::SND_EXPLOSION, pos, 0);
|
||||
game->getMesh()->sequences[-(getEntity().modelIndex + 1)].transp = 2; // fix blending mode to additive
|
||||
}
|
||||
};
|
||||
|
||||
|
11
src/utils.h
11
src/utils.h
@@ -35,6 +35,9 @@
|
||||
#define LOG(...) __android_log_print(ANDROID_LOG_INFO,"OpenLara",__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
extern int osGetTime();
|
||||
extern bool osSave(const char *name, const void *data, int size);
|
||||
|
||||
#define DECL_ENUM(v) v,
|
||||
#define DECL_STR(v) #v,
|
||||
|
||||
@@ -1062,15 +1065,7 @@ struct Stream {
|
||||
}
|
||||
|
||||
static void write(const char *name, const void *data, int size) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
extern void osSave(const char *name, const void *data, int size);
|
||||
osSave(name, data, size);
|
||||
#else
|
||||
FILE *f = fopen(name, "wb");
|
||||
if (!f) return;
|
||||
fwrite(data, size, 1, f);
|
||||
fclose(f);
|
||||
#endif
|
||||
}
|
||||
|
||||
void setPos(int pos) {
|
||||
|
Reference in New Issue
Block a user