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