mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-16 01:54:38 +02:00
#11 controls mapping; saving settings
This commit is contained in:
@@ -448,7 +448,7 @@ struct Camera : ICamera {
|
|||||||
virtual void update() {
|
virtual void update() {
|
||||||
if (shake > 0.0f) {
|
if (shake > 0.0f) {
|
||||||
shake = max(0.0f, shake - Core::deltaTime);
|
shake = max(0.0f, shake - Core::deltaTime);
|
||||||
osJoyVibrate(Core::settings.controls[cameraIndex].joyIndex, clamp(shake, 0.0f, 1.0f), 0);
|
Input::setJoyVibrate(cameraIndex, clamp(shake, 0.0f, 1.0f), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == MODE_CUTSCENE) {
|
if (mode == MODE_CUTSCENE) {
|
||||||
|
34
src/core.h
34
src/core.h
@@ -164,12 +164,6 @@
|
|||||||
#define GENERATE_WATER_PLANE
|
#define GENERATE_WATER_PLANE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int osGetTime();
|
|
||||||
extern bool osSave(const char *name, const void *data, int size);
|
|
||||||
|
|
||||||
extern bool osJoyReady(int index);
|
|
||||||
extern void osJoyVibrate(int index, float L, float R);
|
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
extern void* osMutexInit ();
|
extern void* osMutexInit ();
|
||||||
@@ -177,6 +171,18 @@ extern void osMutexFree (void *obj);
|
|||||||
extern void osMutexLock (void *obj);
|
extern void osMutexLock (void *obj);
|
||||||
extern void osMutexUnlock (void *obj);
|
extern void osMutexUnlock (void *obj);
|
||||||
|
|
||||||
|
extern int osGetTime ();
|
||||||
|
|
||||||
|
extern bool osJoyReady (int index);
|
||||||
|
extern void osJoyVibrate (int index, float L, float R);
|
||||||
|
|
||||||
|
extern bool osCacheWrite (const char *name, const char *data, int size);
|
||||||
|
extern Stream* osCacheRead (const char *name);
|
||||||
|
|
||||||
|
extern bool osSaveGame (const char *data, int size);
|
||||||
|
extern Stream* osLoadGame ();
|
||||||
|
|
||||||
|
|
||||||
struct Mutex {
|
struct Mutex {
|
||||||
void *obj;
|
void *obj;
|
||||||
|
|
||||||
@@ -254,8 +260,8 @@ enum ControlKey {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct KeySet {
|
struct KeySet {
|
||||||
InputKey key;
|
uint8 key;
|
||||||
JoyKey joy;
|
uint8 joy;
|
||||||
|
|
||||||
KeySet() {}
|
KeySet() {}
|
||||||
KeySet(InputKey key, JoyKey joy) : key(key), joy(joy) {}
|
KeySet(InputKey key, JoyKey joy) : key(key), joy(joy) {}
|
||||||
@@ -285,10 +291,14 @@ namespace Core {
|
|||||||
#endif
|
#endif
|
||||||
} support;
|
} support;
|
||||||
|
|
||||||
|
#define SETTINGS_VERSION 1
|
||||||
|
|
||||||
struct Settings {
|
struct Settings {
|
||||||
enum Quality { LOW, MEDIUM, HIGH };
|
enum Quality { LOW, MEDIUM, HIGH };
|
||||||
enum Stereo { STEREO_OFF, STEREO_ON, STEREO_SPLIT };
|
enum Stereo { STEREO_OFF, STEREO_ON, STEREO_SPLIT };
|
||||||
|
|
||||||
|
uint8 version;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
@@ -342,7 +352,9 @@ namespace Core {
|
|||||||
KeySet keys[cMAX];
|
KeySet keys[cMAX];
|
||||||
} controls[2];
|
} controls[2];
|
||||||
|
|
||||||
uint8 playerIndex; // temporary, used only for setting controls
|
// temporary, used only for setting controls
|
||||||
|
uint8 playerIndex;
|
||||||
|
uint8 ctrlIndex;
|
||||||
} settings;
|
} settings;
|
||||||
|
|
||||||
bool resetState;
|
bool resetState;
|
||||||
@@ -1021,6 +1033,8 @@ namespace Core {
|
|||||||
whiteTex = new Texture(1, 1, Texture::RGBA, Texture::NEAREST, &data);
|
whiteTex = new Texture(1, 1, Texture::RGBA, Texture::NEAREST, &data);
|
||||||
|
|
||||||
// init settings
|
// init settings
|
||||||
|
settings.version = SETTINGS_VERSION;
|
||||||
|
|
||||||
settings.detail.setFilter (Core::Settings::HIGH);
|
settings.detail.setFilter (Core::Settings::HIGH);
|
||||||
settings.detail.setLighting (Core::Settings::HIGH);
|
settings.detail.setLighting (Core::Settings::HIGH);
|
||||||
settings.detail.setShadows (Core::Settings::HIGH);
|
settings.detail.setShadows (Core::Settings::HIGH);
|
||||||
@@ -1076,7 +1090,7 @@ namespace Core {
|
|||||||
ctrl.keys[ cDash ] = KeySet( ikNone, jkRT );
|
ctrl.keys[ cDash ] = KeySet( ikNone, jkRT );
|
||||||
ctrl.keys[ cRoll ] = KeySet( ikNone, jkB );
|
ctrl.keys[ cRoll ] = KeySet( ikNone, jkB );
|
||||||
ctrl.keys[ cInventory ] = KeySet( ikNone, jkSelect );
|
ctrl.keys[ cInventory ] = KeySet( ikNone, jkSelect );
|
||||||
ctrl.keys[ cStart ] = KeySet( ikEnter, jkStart );
|
ctrl.keys[ cStart ] = KeySet( ikNone, jkStart );
|
||||||
}
|
}
|
||||||
|
|
||||||
// use D key for jump in browsers
|
// use D key for jump in browsers
|
||||||
|
16
src/game.h
16
src/game.h
@@ -34,10 +34,22 @@ namespace Game {
|
|||||||
if (level) level->stopChannel(channel);
|
if (level) level->stopChannel(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void readSettings() {
|
||||||
|
Stream *stream = osCacheRead("settings");
|
||||||
|
if (!stream) return;
|
||||||
|
uint8 version;
|
||||||
|
stream->read(version);
|
||||||
|
if (version == SETTINGS_VERSION && stream->size == sizeof(Core::Settings))
|
||||||
|
stream->raw((char*)&Core::settings + 1, stream->size - 1); // read settings data right after version number
|
||||||
|
delete stream;
|
||||||
|
}
|
||||||
|
|
||||||
void init(Stream *lvl) {
|
void init(Stream *lvl) {
|
||||||
nextLevel = NULL;
|
nextLevel = NULL;
|
||||||
|
|
||||||
Core::init();
|
Core::init();
|
||||||
|
readSettings();
|
||||||
|
|
||||||
shaderCache = new ShaderCache();
|
shaderCache = new ShaderCache();
|
||||||
|
|
||||||
UI::init(level);
|
UI::init(level);
|
||||||
@@ -104,7 +116,7 @@ namespace Game {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
Input::update();
|
Input::update();
|
||||||
|
/*
|
||||||
if (level->camera) {
|
if (level->camera) {
|
||||||
if (Input::down[ikV]) { // third <-> first person view
|
if (Input::down[ikV]) { // third <-> first person view
|
||||||
level->camera->changeView(!level->camera->firstPerson);
|
level->camera->changeView(!level->camera->firstPerson);
|
||||||
@@ -122,7 +134,7 @@ namespace Game {
|
|||||||
level->loadGame(0);
|
level->loadGame(0);
|
||||||
Input::down[ikL] = false;
|
Input::down[ikL] = false;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if (!level->level.isTitle()) {
|
if (!level->level.isTitle()) {
|
||||||
if (Input::state[0][cStart]) level->addPlayer(0);
|
if (Input::state[0][cStart]) level->addPlayer(0);
|
||||||
if (Input::state[1][cStart]) level->addPlayer(1);
|
if (Input::state[1][cStart]) level->addPlayer(1);
|
||||||
|
@@ -38,8 +38,8 @@ namespace TR {
|
|||||||
|
|
||||||
VER_TR3_PC = VER_TR3 | VER_PC,
|
VER_TR3_PC = VER_TR3 | VER_PC,
|
||||||
VER_TR3_PSX = VER_TR3 | VER_PSX,
|
VER_TR3_PSX = VER_TR3 | VER_PSX,
|
||||||
|
|
||||||
VER_MAX = 0xFFFFFFFF,
|
VER_MAX = 0xFFFFFFFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum LevelID {
|
enum LevelID {
|
||||||
@@ -506,6 +506,9 @@ namespace TR {
|
|||||||
if (Stream::existsContent("data/JUNGLE.TR2"))
|
if (Stream::existsContent("data/JUNGLE.TR2"))
|
||||||
return VER_TR3_PC;
|
return VER_TR3_PC;
|
||||||
|
|
||||||
|
if (Stream::existsContent("DATA/JUNGLE.PSX"))
|
||||||
|
return VER_TR3_PSX;
|
||||||
|
|
||||||
useEasyStart = false;
|
useEasyStart = false;
|
||||||
return VER_UNKNOWN;
|
return VER_UNKNOWN;
|
||||||
}
|
}
|
||||||
@@ -542,6 +545,7 @@ namespace TR {
|
|||||||
}
|
}
|
||||||
case VER_TR2_PSX : sprintf(dst, "DATA/%s.PSX", LEVEL_INFO[id].name); break;
|
case VER_TR2_PSX : sprintf(dst, "DATA/%s.PSX", LEVEL_INFO[id].name); break;
|
||||||
case VER_TR3_PC : sprintf(dst, isCutsceneLevel(id) ? "cuts/%s.TR2" : "data/%s.TR2", LEVEL_INFO[id].name); break;
|
case VER_TR3_PC : sprintf(dst, isCutsceneLevel(id) ? "cuts/%s.TR2" : "data/%s.TR2", LEVEL_INFO[id].name); break;
|
||||||
|
case VER_TR3_PSX : sprintf(dst, isCutsceneLevel(id) ? "CUTS/%s.PSX" : "DATA/%s.PSX", LEVEL_INFO[id].name); break;
|
||||||
default : ASSERT(false);
|
default : ASSERT(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
22
src/input.h
22
src/input.h
@@ -7,7 +7,7 @@
|
|||||||
#define INPUT_JOY_COUNT 4
|
#define INPUT_JOY_COUNT 4
|
||||||
|
|
||||||
namespace Input {
|
namespace Input {
|
||||||
|
InputKey lastKey;
|
||||||
bool down[ikMAX];
|
bool down[ikMAX];
|
||||||
bool state[2][cMAX];
|
bool state[2][cMAX];
|
||||||
|
|
||||||
@@ -19,9 +19,10 @@ namespace Input {
|
|||||||
} mouse;
|
} mouse;
|
||||||
|
|
||||||
struct Joystick {
|
struct Joystick {
|
||||||
vec2 L, R;
|
vec2 L, R;
|
||||||
float LT, RT;
|
float LT, RT;
|
||||||
bool down[jkMAX];
|
JoyKey lastKey;
|
||||||
|
bool down[jkMAX];
|
||||||
} joy[INPUT_JOY_COUNT];
|
} joy[INPUT_JOY_COUNT];
|
||||||
|
|
||||||
struct Touch {
|
struct Touch {
|
||||||
@@ -77,6 +78,8 @@ namespace Input {
|
|||||||
default : ;
|
default : ;
|
||||||
}
|
}
|
||||||
down[key] = value;
|
down[key] = value;
|
||||||
|
|
||||||
|
if (value && key <= ikZ) lastKey = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPos(InputKey key, const vec2 &pos) {
|
void setPos(InputKey key, const vec2 &pos) {
|
||||||
@@ -95,7 +98,12 @@ namespace Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setJoyDown(int index, JoyKey key, bool value) {
|
void setJoyDown(int index, JoyKey key, bool value) {
|
||||||
|
if (joy[index].down[key] == value)
|
||||||
|
return;
|
||||||
|
|
||||||
joy[index].down[key] = value;
|
joy[index].down[key] = value;
|
||||||
|
|
||||||
|
if (value) joy[index].lastKey = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setJoyPos(int index, JoyKey key, const vec2 &pos) {
|
void setJoyPos(int index, JoyKey key, const vec2 &pos) {
|
||||||
@@ -109,6 +117,12 @@ namespace Input {
|
|||||||
setJoyDown(index, key, pos.x > 0.0f); // gamepad LT, RT auto-down state
|
setJoyDown(index, key, pos.x > 0.0f); // gamepad LT, RT auto-down state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setJoyVibrate(int playerIndex, float L, float R) {
|
||||||
|
if (!Core::settings.controls[playerIndex].vibration)
|
||||||
|
return;
|
||||||
|
osJoyVibrate(Core::settings.controls[playerIndex].joyIndex, L, R);
|
||||||
|
}
|
||||||
|
|
||||||
InputKey getTouch(int id) {
|
InputKey getTouch(int id) {
|
||||||
for (int i = 0; i < COUNT(touch); i++)
|
for (int i = 0; i < COUNT(touch); i++)
|
||||||
if (down[ikTouchA + i] && touch[i].id == id)
|
if (down[ikTouchA + i] && touch[i].id == id)
|
||||||
|
169
src/inventory.h
169
src/inventory.h
@@ -17,12 +17,15 @@
|
|||||||
#define TITLE_LOADING 64.0f
|
#define TITLE_LOADING 64.0f
|
||||||
#define LINE_HEIGHT 20.0f
|
#define LINE_HEIGHT 20.0f
|
||||||
|
|
||||||
|
static const struct OptionItem *waitForKey = NULL;
|
||||||
|
|
||||||
struct OptionItem {
|
struct OptionItem {
|
||||||
enum Type {
|
enum Type {
|
||||||
TYPE_TITLE,
|
TYPE_TITLE,
|
||||||
TYPE_EMPTY,
|
TYPE_EMPTY,
|
||||||
TYPE_BUTTON,
|
TYPE_BUTTON,
|
||||||
TYPE_PARAM,
|
TYPE_PARAM,
|
||||||
|
TYPE_KEY,
|
||||||
} type;
|
} type;
|
||||||
StringID title;
|
StringID title;
|
||||||
intptr_t offset;
|
intptr_t offset;
|
||||||
@@ -31,7 +34,11 @@ struct OptionItem {
|
|||||||
uint8 maxValue;
|
uint8 maxValue;
|
||||||
bool bar;
|
bool bar;
|
||||||
|
|
||||||
OptionItem(Type type = TYPE_EMPTY, StringID title = STR_NOT_IMPLEMENTED, intptr_t offset = 0, uint32 color = 0xFFFFFFFF, int icon = 0, uint8 maxValue = 0, bool bar = false) : type(type), title(title), offset(offset), color(color), icon(icon), maxValue(maxValue), bar(bar) {}
|
OptionItem(Type type = TYPE_EMPTY, int title = STR_NOT_IMPLEMENTED, intptr_t offset = 0, uint32 color = 0xFFFFFFFF, int icon = 0, uint8 maxValue = 0, bool bar = false) : type(type), title(StringID(title)), offset(offset), color(color), icon(icon), maxValue(maxValue), bar(bar) {}
|
||||||
|
|
||||||
|
void setValue(uint8 value, Core::Settings *settings) const {
|
||||||
|
*(uint8*)(intptr_t(settings) + offset) = value;
|
||||||
|
}
|
||||||
|
|
||||||
float drawParam(float x, float y, float w, StringID oStr, bool active, uint8 value) const {
|
float drawParam(float x, float y, float w, StringID oStr, bool active, uint8 value) const {
|
||||||
if (oStr != STR_NOT_IMPLEMENTED) {
|
if (oStr != STR_NOT_IMPLEMENTED) {
|
||||||
@@ -40,12 +47,22 @@ struct OptionItem {
|
|||||||
w = w * 0.5f - 32.0f;
|
w = w * 0.5f - 32.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
UI::textOut(vec2(x, y), StringID(color + int(value)), UI::aCenter, w); // color as StringID
|
StringID vStr = StringID(color + int(value));
|
||||||
if (active) {
|
|
||||||
|
uint8 alpha = 255;
|
||||||
|
if (type == TYPE_KEY && waitForKey == this) {
|
||||||
|
vStr = STR_PRESS_ANY_KEY;
|
||||||
|
float t = (Core::getTime() % 1000) / 1000.0f;
|
||||||
|
t = 0.2f + (sinf(t * PI * 2) * 0.5f + 0.5f) * 0.8f;
|
||||||
|
alpha = uint8(t * 255.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
UI::textOut(vec2(x, y), vStr, UI::aCenter, w, alpha, UI::SHADE_GRAY); // color as StringID
|
||||||
|
|
||||||
|
if (type == TYPE_PARAM && active) {
|
||||||
float maxWidth = UI::getTextSize(STR[color + value]).x;
|
float maxWidth = UI::getTextSize(STR[color + value]).x;
|
||||||
maxWidth = maxWidth * 0.5f + 8.0f;
|
maxWidth = maxWidth * 0.5f + 8.0f;
|
||||||
x += w * 0.5f;
|
x += w * 0.5f;
|
||||||
|
|
||||||
if (value > 0) UI::specOut(vec2(x - maxWidth - 16.0f, y), 108);
|
if (value > 0) UI::specOut(vec2(x - maxWidth - 16.0f, y), 108);
|
||||||
if (value < maxValue) UI::specOut(vec2(x + maxWidth, y), 109);
|
if (value < maxValue) UI::specOut(vec2(x + maxWidth, y), 109);
|
||||||
}
|
}
|
||||||
@@ -71,7 +88,7 @@ struct OptionItem {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case TYPE_TITLE :
|
case TYPE_TITLE :
|
||||||
UI::renderBar(UI::BAR_OPTION, vec2(x, y - LINE_HEIGHT + 6), vec2(w, LINE_HEIGHT - 6), 1.0f, 0x802288FF, 0, 0, 0);
|
UI::renderBar(UI::BAR_OPTION, vec2(x, y - LINE_HEIGHT + 6), vec2(w, LINE_HEIGHT - 6), 1.0f, 0x802288FF, 0, 0, 0);
|
||||||
UI::textOut(vec2(x, y), title, UI::aCenter, w, UI::SHADE_GRAY);
|
UI::textOut(vec2(x, y), title, UI::aCenter, w, 255, UI::SHADE_GRAY);
|
||||||
case TYPE_EMPTY : break;
|
case TYPE_EMPTY : break;
|
||||||
case TYPE_BUTTON : {
|
case TYPE_BUTTON : {
|
||||||
const char *caption = offset ? (char*)offset : STR[title];
|
const char *caption = offset ? (char*)offset : STR[title];
|
||||||
@@ -79,6 +96,7 @@ struct OptionItem {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TYPE_PARAM :
|
case TYPE_PARAM :
|
||||||
|
case TYPE_KEY :
|
||||||
return bar ? drawBar(x, y, w, active, value) : drawParam(x, y, w, title, active, value);
|
return bar ? drawBar(x, y, w, active, value) : drawParam(x, y, w, title, active, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,11 +134,27 @@ static const OptionItem optSound[] = {
|
|||||||
static const OptionItem optControls[] = {
|
static const OptionItem optControls[] = {
|
||||||
OptionItem( OptionItem::TYPE_TITLE, STR_SET_CONTROLS ),
|
OptionItem( OptionItem::TYPE_TITLE, STR_SET_CONTROLS ),
|
||||||
OptionItem( ),
|
OptionItem( ),
|
||||||
OptionItem( OptionItem::TYPE_PARAM, STR_NOT_IMPLEMENTED, SETTINGS( playerIndex ), STR_PLAYER_1, 0, 1 ),
|
OptionItem( OptionItem::TYPE_PARAM, STR_NOT_IMPLEMENTED , SETTINGS( playerIndex ), STR_PLAYER_1, 0, 1 ),
|
||||||
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_CONTROLS_GAMEPAD, SETTINGS( controls[0].joyIndex ), STR_GAMEPAD_1, 0, 3 ),
|
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_CONTROLS_GAMEPAD , SETTINGS( controls[0].joyIndex ), STR_GAMEPAD_1, 0, 3 ),
|
||||||
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_CONTROLS_VIBRATION, SETTINGS( controls[0].vibration ), STR_OFF, 0, 1 ),
|
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_CONTROLS_VIBRATION , SETTINGS( controls[0].vibration ), STR_OFF, 0, 1 ),
|
||||||
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_CONTROLS_RETARGET, SETTINGS( controls[0].retarget ), STR_OFF, 0, 1 ),
|
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_CONTROLS_RETARGET , SETTINGS( controls[0].retarget ), STR_OFF, 0, 1 ),
|
||||||
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_CONTROLS_MULTIAIM, SETTINGS( controls[0].multiaim ), STR_OFF, 0, 1 ),
|
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_CONTROLS_MULTIAIM , SETTINGS( controls[0].multiaim ), STR_OFF, 0, 1 ),
|
||||||
|
OptionItem( OptionItem::TYPE_PARAM, STR_NOT_IMPLEMENTED , SETTINGS( ctrlIndex ), STR_OPT_CONTROLS_KEYBOARD, 0, 1 ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cUp , SETTINGS( controls[0].keys[ cUp ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cDown , SETTINGS( controls[0].keys[ cDown ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cRight , SETTINGS( controls[0].keys[ cRight ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cLeft , SETTINGS( controls[0].keys[ cLeft ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cWalk , SETTINGS( controls[0].keys[ cWalk ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cJump , SETTINGS( controls[0].keys[ cJump ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cAction , SETTINGS( controls[0].keys[ cAction ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cWeapon , SETTINGS( controls[0].keys[ cWeapon ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cLook , SETTINGS( controls[0].keys[ cLook ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cDuck , SETTINGS( controls[0].keys[ cDuck ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cDash , SETTINGS( controls[0].keys[ cDash ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cRoll , SETTINGS( controls[0].keys[ cRoll ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cInventory , SETTINGS( controls[0].keys[ cInventory ] ), STR_KEY_FIRST ),
|
||||||
|
OptionItem( OptionItem::TYPE_KEY, STR_CTRL_FIRST + cStart , SETTINGS( controls[0].keys[ cStart ] ), STR_KEY_FIRST ),
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static OptionItem optControlsPlayer[COUNT(optControls)];
|
static OptionItem optControlsPlayer[COUNT(optControls)];
|
||||||
@@ -269,9 +303,19 @@ struct Inventory {
|
|||||||
case TR::Entity::INV_CONTROLS :
|
case TR::Entity::INV_CONTROLS :
|
||||||
ASSERT(optControls[2].offset == SETTINGS( playerIndex) );
|
ASSERT(optControls[2].offset == SETTINGS( playerIndex) );
|
||||||
for (int i = 0; i < COUNT(optControls); i++) {
|
for (int i = 0; i < COUNT(optControls); i++) {
|
||||||
optControlsPlayer[i] = optControls[i];
|
OptionItem &opt = optControlsPlayer[i];
|
||||||
if (i > 2)
|
opt = optControls[i];
|
||||||
optControlsPlayer[i].offset += sizeof(Core::Settings::Controls) * Core::settings.playerIndex;
|
|
||||||
|
if (i > 2 && i != 2 && i != 7)
|
||||||
|
opt.offset += sizeof(Core::Settings::Controls) * Core::settings.playerIndex;
|
||||||
|
|
||||||
|
if (i > 7) {
|
||||||
|
if (Core::settings.ctrlIndex == 1) {
|
||||||
|
opt.offset++; // add offset to joy
|
||||||
|
opt.color = STR_JOY_FIRST;
|
||||||
|
} else
|
||||||
|
opt.color = STR_KEY_FIRST;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
optCount = COUNT(optControlsPlayer);
|
optCount = COUNT(optControlsPlayer);
|
||||||
return optControlsPlayer;
|
return optControlsPlayer;
|
||||||
@@ -305,7 +349,7 @@ struct Inventory {
|
|||||||
uint8 &value = *(uint8*)(intptr_t(settings) + opt->offset);
|
uint8 &value = *(uint8*)(intptr_t(settings) + opt->offset);
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case cAction : return (opt->type == OptionItem::TYPE_BUTTON) ? opt : NULL;
|
case cAction : return (opt->type == OptionItem::TYPE_BUTTON || opt->type == OptionItem::TYPE_KEY) ? opt : NULL;
|
||||||
case cUp : nextSlot(slot, -1); break;
|
case cUp : nextSlot(slot, -1); break;
|
||||||
case cDown : nextSlot(slot, +1); break;
|
case cDown : nextSlot(slot, +1); break;
|
||||||
case cLeft :
|
case cLeft :
|
||||||
@@ -455,6 +499,8 @@ struct Inventory {
|
|||||||
|
|
||||||
phaseRing = phasePage = phaseChoose = phaseSelect = 0.0f;
|
phaseRing = phasePage = phaseChoose = phaseSelect = 0.0f;
|
||||||
memset(pageItemIndex, 0, sizeof(pageItemIndex));
|
memset(pageItemIndex, 0, sizeof(pageItemIndex));
|
||||||
|
|
||||||
|
waitForKey = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Inventory() {
|
~Inventory() {
|
||||||
@@ -584,6 +630,9 @@ struct Inventory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool toggle(int playerIndex = 0, Page curPage = PAGE_INVENTORY, TR::Entity::Type type = TR::Entity::LARA) {
|
bool toggle(int playerIndex = 0, Page curPage = PAGE_INVENTORY, TR::Entity::Type type = TR::Entity::LARA) {
|
||||||
|
if (!game->getLara(playerIndex))
|
||||||
|
return false;
|
||||||
|
|
||||||
this->playerIndex = playerIndex;
|
this->playerIndex = playerIndex;
|
||||||
titleTimer = 0.0f;
|
titleTimer = 0.0f;
|
||||||
|
|
||||||
@@ -714,6 +763,7 @@ struct Inventory {
|
|||||||
}
|
}
|
||||||
case TR::Entity::INV_CONTROLS :
|
case TR::Entity::INV_CONTROLS :
|
||||||
Core::settings.playerIndex = 0;
|
Core::settings.playerIndex = 0;
|
||||||
|
Core::settings.ctrlIndex = 0;
|
||||||
break;
|
break;
|
||||||
case TR::Entity::INV_DETAIL :
|
case TR::Entity::INV_DETAIL :
|
||||||
settings = Core::settings;
|
settings = Core::settings;
|
||||||
@@ -769,13 +819,6 @@ struct Inventory {
|
|||||||
nextLevel = level->getHomeId();
|
nextLevel = level->getHomeId();
|
||||||
toggle();
|
toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((key == cInventory || key == cJump) && phaseChoose == 1.0f) {
|
|
||||||
chosen = false;
|
|
||||||
item->anim->dir = 1.0f;
|
|
||||||
item->value = 1000;
|
|
||||||
item->angle = 0.0f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void optionChanged(Item *item, const OptionItem *opt, Core::Settings &settings) {
|
void optionChanged(Item *item, const OptionItem *opt, Core::Settings &settings) {
|
||||||
@@ -792,7 +835,17 @@ struct Inventory {
|
|||||||
game->playSound(TR::SND_PISTOLS_SHOT);
|
game->playSound(TR::SND_PISTOLS_SHOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt->title == STR_APPLY) {
|
if (item->type == TR::Entity::INV_CONTROLS && opt->type == OptionItem::TYPE_KEY) {
|
||||||
|
waitForKey = opt;
|
||||||
|
Input::lastKey = ikNone;
|
||||||
|
Input::joy[Core::settings.controls[Core::settings.playerIndex].joyIndex].lastKey = jkNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->type == TR::Entity::INV_SOUND || item->type == TR::Entity::INV_CONTROLS) {
|
||||||
|
game->applySettings(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item->type == TR::Entity::INV_DETAIL && opt->title == STR_APPLY) {
|
||||||
game->applySettings(settings);
|
game->applySettings(settings);
|
||||||
chosen = false;
|
chosen = false;
|
||||||
}
|
}
|
||||||
@@ -834,17 +887,17 @@ struct Inventory {
|
|||||||
Input::Joystick &joy = Input::joy[Core::settings.controls[playerIndex].joyIndex];
|
Input::Joystick &joy = Input::joy[Core::settings.controls[playerIndex].joyIndex];
|
||||||
|
|
||||||
ControlKey key = cMAX;
|
ControlKey key = cMAX;
|
||||||
if (Input::state[playerIndex][cAction])
|
if (Input::down[ikCtrl] || Input::down[ikEnter] || joy.down[jkA])
|
||||||
key = cAction;
|
key = cAction;
|
||||||
else if (Input::state[playerIndex][cInventory] || Input::state[playerIndex][cJump])
|
else if (Input::down[ikAlt] || joy.down[jkB] || Input::state[playerIndex][cInventory])
|
||||||
key = cInventory;
|
key = cInventory;
|
||||||
else if (Input::state[playerIndex][cLeft] || joy.L.x < -0.5f)
|
else if (Input::down[ikLeft] || joy.down[jkLeft] || joy.L.x < -0.5f)
|
||||||
key = cLeft;
|
key = cLeft;
|
||||||
else if (Input::state[playerIndex][cRight] || joy.L.x > 0.5f)
|
else if (Input::down[ikRight] || joy.down[jkRight] || joy.L.x > 0.5f)
|
||||||
key = cRight;
|
key = cRight;
|
||||||
else if (Input::state[playerIndex][cUp] || joy.L.y < -0.5f)
|
else if (Input::down[ikUp] || joy.down[jkUp] || joy.L.y < -0.5f)
|
||||||
key = cUp;
|
key = cUp;
|
||||||
else if (Input::state[playerIndex][cDown] || joy.L.y > 0.5f)
|
else if (Input::down[ikDown] || joy.down[jkDown] || joy.L.y > 0.5f)
|
||||||
key = cDown;
|
key = cDown;
|
||||||
|
|
||||||
Item *item = items[getGlobalIndex(page, index)];
|
Item *item = items[getGlobalIndex(page, index)];
|
||||||
@@ -876,8 +929,40 @@ struct Inventory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key != cMAX && lastKey != key && changeTimer == 0.0f && phaseChoose == 1.0f)
|
if (waitForKey) {
|
||||||
|
int newKey = -1;
|
||||||
|
if (Core::settings.ctrlIndex == 0 && Input::lastKey != ikNone) {
|
||||||
|
newKey = Input::lastKey;
|
||||||
|
} else {
|
||||||
|
JoyKey jk = Input::joy[Core::settings.controls[Core::settings.playerIndex].joyIndex].lastKey;
|
||||||
|
if (Core::settings.ctrlIndex == 1 && jk != jkNone)
|
||||||
|
newKey = jk;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newKey != -1) {
|
||||||
|
waitForKey->setValue(newKey, &Core::settings);
|
||||||
|
waitForKey = NULL;
|
||||||
|
lastKey = key;
|
||||||
|
game->applySettings(Core::settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key != cMAX && lastKey != key && changeTimer == 0.0f && phaseChoose == 1.0f) {
|
||||||
controlItem(item, key);
|
controlItem(item, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key == cInventory || key == cJump) && lastKey != key) {
|
||||||
|
lastKey = key;
|
||||||
|
if (chosen) {
|
||||||
|
if (phaseChoose == 1.0f) {
|
||||||
|
chosen = false;
|
||||||
|
item->anim->dir = 1.0f;
|
||||||
|
item->value = 1000;
|
||||||
|
item->angle = 0.0f;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
toggle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastKey = key;
|
lastKey = key;
|
||||||
@@ -1036,7 +1121,7 @@ struct Inventory {
|
|||||||
sprintf(buf, "%d %c", item->count, spec);
|
sprintf(buf, "%d %c", item->count, spec);
|
||||||
for (int i = 0; buf[i] != ' '; i++)
|
for (int i = 0; buf[i] != ' '; i++)
|
||||||
buf[i] -= 47;
|
buf[i] -= 47;
|
||||||
UI::textOut(pos, buf, UI::aRight, width, UI::SHADE_NONE);
|
UI::textOut(pos, buf, UI::aRight, width, 255, UI::SHADE_NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1270,13 +1355,13 @@ struct Inventory {
|
|||||||
UI::textOut(vec2(-eye, 32), pageTitle[page], UI::aCenter, UI::width);
|
UI::textOut(vec2(-eye, 32), pageTitle[page], UI::aCenter, UI::width);
|
||||||
|
|
||||||
if (canFlipPage(-1)) {
|
if (canFlipPage(-1)) {
|
||||||
UI::textOut(vec2(16 - eye, 32), "[", UI::aLeft, UI::width, UI::SHADE_NONE);
|
UI::textOut(vec2(16 - eye, 32), "[", UI::aLeft, UI::width);
|
||||||
UI::textOut(vec2(-eye, 32), "[", UI::aRight, UI::width - 20, UI::SHADE_NONE);
|
UI::textOut(vec2(-eye, 32), "[", UI::aRight, UI::width - 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canFlipPage(1)) {
|
if (canFlipPage(1)) {
|
||||||
UI::textOut(vec2(16 - eye, 480 - 16), "]", UI::aLeft, UI::width, UI::SHADE_NONE);
|
UI::textOut(vec2(16 - eye, 480 - 16), "]", UI::aLeft, UI::width);
|
||||||
UI::textOut(vec2(-eye, 480 - 16), "]", UI::aRight, UI::width - 20, UI::SHADE_NONE);
|
UI::textOut(vec2(-eye, 480 - 16), "]", UI::aRight, UI::width - 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == targetIndex)
|
if (index == targetIndex)
|
||||||
@@ -1284,15 +1369,13 @@ struct Inventory {
|
|||||||
|
|
||||||
// inventory controls help
|
// inventory controls help
|
||||||
float dx = 32.0f - eye;
|
float dx = 32.0f - eye;
|
||||||
UI::textOut(vec2(dx, 480 - 64), "Ctrl - Select", UI::aLeft, UI::width, UI::SHADE_NONE);
|
char buf[64];
|
||||||
if (chosen)
|
sprintf(buf, STR[STR_HELP_SELECT], STR[STR_KEY_FIRST + ikEnter] );
|
||||||
UI::textOut(vec2(0, 480 - 64),
|
UI::textOut(vec2(dx, 480 - 64), buf, UI::aLeft, UI::width);
|
||||||
#ifdef __EMSCRIPTEN__
|
if (chosen) {
|
||||||
"D"
|
sprintf(buf, STR[STR_HELP_BACK], STR[STR_KEY_FIRST + Core::settings.controls[playerIndex].keys[ cInventory ].key] );
|
||||||
#else
|
UI::textOut(vec2(0, 480 - 64), buf, UI::aRight, UI::width - dx);
|
||||||
"Alt"
|
}
|
||||||
#endif
|
|
||||||
" - Go Back", UI::aRight, UI::width - dx, UI::SHADE_NONE);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
25
src/lara.h
25
src/lara.h
@@ -253,6 +253,7 @@ struct Lara : Character {
|
|||||||
Camera *camera;
|
Camera *camera;
|
||||||
|
|
||||||
float hitTimer;
|
float hitTimer;
|
||||||
|
bool camChanged; // hit key detection to go first person view mode
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
//uint16 *dbgBoxes;
|
//uint16 *dbgBoxes;
|
||||||
@@ -431,7 +432,8 @@ struct Lara : Character {
|
|||||||
Lara(IGame *game, int entity) : Character(game, entity, LARA_MAX_HEALTH), dozy(false), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), braid(NULL) {
|
Lara(IGame *game, int entity) : Character(game, entity, LARA_MAX_HEALTH), dozy(false), wpnCurrent(Weapon::EMPTY), wpnNext(Weapon::EMPTY), braid(NULL) {
|
||||||
camera = new Camera(game, this);
|
camera = new Camera(game, this);
|
||||||
|
|
||||||
hitTimer = 0.0f;
|
hitTimer = 0.0f;
|
||||||
|
camChanged = false;
|
||||||
|
|
||||||
if (level->extra.laraSkin > -1)
|
if (level->extra.laraSkin > -1)
|
||||||
level->entities[entity].modelIndex = level->extra.laraSkin + 1;
|
level->entities[entity].modelIndex = level->extra.laraSkin + 1;
|
||||||
@@ -2652,6 +2654,14 @@ struct Lara : Character {
|
|||||||
// analog control
|
// analog control
|
||||||
rotFactor = vec2(1.0f);
|
rotFactor = vec2(1.0f);
|
||||||
|
|
||||||
|
if ((input & LOOK) && (input & ACTION)) {
|
||||||
|
if (!camChanged) {
|
||||||
|
camera->changeView(!camera->firstPerson);
|
||||||
|
camChanged = true;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
camChanged = false;
|
||||||
|
|
||||||
if (input & LOOK)
|
if (input & LOOK)
|
||||||
return input;
|
return input;
|
||||||
|
|
||||||
@@ -2700,7 +2710,14 @@ struct Lara : Character {
|
|||||||
|| state == STATE_USE_KEY
|
|| state == STATE_USE_KEY
|
||||||
|| state == STATE_USE_PUZZLE
|
|| state == STATE_USE_PUZZLE
|
||||||
|| state == STATE_SPECIAL
|
|| state == STATE_SPECIAL
|
||||||
|| state == STATE_REACH;
|
|| state == STATE_REACH
|
||||||
|
|| state == STATE_SWAN_DIVE
|
||||||
|
|| state == STATE_HANDSTAND
|
||||||
|
|| state == STATE_ROLL_1
|
||||||
|
|| state == STATE_ROLL_2
|
||||||
|
|| animation.index == ANIM_CLIMB_2
|
||||||
|
|| animation.index == ANIM_CLIMB_3
|
||||||
|
|| animation.index == ANIM_CLIMB_JUMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void doCustomCommand(int curFrame, int prevFrame) {
|
virtual void doCustomCommand(int curFrame, int prevFrame) {
|
||||||
@@ -2749,9 +2766,9 @@ struct Lara : Character {
|
|||||||
if (hitTimer > 0.0f) {
|
if (hitTimer > 0.0f) {
|
||||||
hitTimer -= Core::deltaTime;
|
hitTimer -= Core::deltaTime;
|
||||||
if (hitTimer > 0.0f)
|
if (hitTimer > 0.0f)
|
||||||
osJoyVibrate(Core::settings.controls[camera->cameraIndex].joyIndex, 0.5f, 0.5f);
|
Input::setJoyVibrate(camera->cameraIndex, 0.5f, 0.5f);
|
||||||
else
|
else
|
||||||
osJoyVibrate(Core::settings.controls[camera->cameraIndex].joyIndex, 0, 0);
|
Input::setJoyVibrate(camera->cameraIndex, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level->isCutsceneLevel())
|
if (level->isCutsceneLevel())
|
||||||
|
19
src/level.h
19
src/level.h
@@ -130,21 +130,24 @@ struct Level : IGame {
|
|||||||
save->size = ptr - data;
|
save->size = ptr - data;
|
||||||
save->version = level.version & TR::VER_VERSION;
|
save->version = level.version & TR::VER_VERSION;
|
||||||
|
|
||||||
Stream::write("savegame.dat", data, int(ptr - data));
|
osSaveGame(data, int(ptr - data));
|
||||||
delete[] data;
|
delete[] data;
|
||||||
|
|
||||||
LOG("Ok\n");
|
LOG("Ok\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void loadGame(int slot) {
|
virtual void loadGame(int slot) {
|
||||||
LOG("Lave Game... ");
|
LOG("Load Game... ");
|
||||||
|
|
||||||
|
Stream *stream = osLoadGame();
|
||||||
|
if (!stream)
|
||||||
|
return;
|
||||||
|
|
||||||
clearInventory();
|
clearInventory();
|
||||||
clearEntities();
|
clearEntities();
|
||||||
|
|
||||||
Stream stream("savegame.dat");
|
|
||||||
char *data;
|
char *data;
|
||||||
stream.read(data, stream.size);
|
stream->read(data, stream->size);
|
||||||
char *ptr = data;
|
char *ptr = data;
|
||||||
|
|
||||||
TR::SaveGame *save = (TR::SaveGame*)ptr;
|
TR::SaveGame *save = (TR::SaveGame*)ptr;
|
||||||
@@ -188,6 +191,7 @@ struct Level : IGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
delete[] data;
|
delete[] data;
|
||||||
|
delete stream;
|
||||||
|
|
||||||
// camera->room = lara->getRoomIndex();
|
// camera->room = lara->getRoomIndex();
|
||||||
// camera->pos = camera->destPos = lara->pos;
|
// camera->pos = camera->destPos = lara->pos;
|
||||||
@@ -233,6 +237,8 @@ struct Level : IGame {
|
|||||||
|
|
||||||
Core::settings = settings;
|
Core::settings = settings;
|
||||||
|
|
||||||
|
osCacheWrite("settings", (char*)&settings, sizeof(settings));
|
||||||
|
|
||||||
if (rebuildShaders) {
|
if (rebuildShaders) {
|
||||||
delete shaderCache;
|
delete shaderCache;
|
||||||
shaderCache = new ShaderCache();
|
shaderCache = new ShaderCache();
|
||||||
@@ -516,7 +522,7 @@ struct Level : IGame {
|
|||||||
switch (b.flags.mode) {
|
switch (b.flags.mode) {
|
||||||
case 0 : if (level.version & TR::VER_TR1) flags |= Sound::UNIQUE; break; // TODO check this
|
case 0 : if (level.version & TR::VER_TR1) flags |= Sound::UNIQUE; break; // TODO check this
|
||||||
case 1 : flags |= Sound::REPLAY; break;
|
case 1 : flags |= Sound::REPLAY; break;
|
||||||
case 2 : if (level.version & TR::VER_TR1) flags |= Sound::FLIPPED | Sound::UNFLIPPED | Sound::LOOP | Sound::UNIQUE; break;
|
case 2 : if (level.version & TR::VER_TR1) flags |= Sound::FLIPPED | Sound::UNFLIPPED | Sound::LOOP; break;
|
||||||
case 3 : if (!(level.version & TR::VER_TR1)) flags |= Sound::FLIPPED | Sound::UNFLIPPED | Sound::LOOP | Sound::UNIQUE; break;
|
case 3 : if (!(level.version & TR::VER_TR1)) flags |= Sound::FLIPPED | Sound::UNFLIPPED | Sound::LOOP | Sound::UNIQUE; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -549,7 +555,6 @@ struct Level : IGame {
|
|||||||
}
|
}
|
||||||
level->sndSoundtrack->setVolume(1.0f, 0.2f);
|
level->sndSoundtrack->setVolume(1.0f, 0.2f);
|
||||||
}
|
}
|
||||||
LOG("play soundtrack - %d\n", Core::getTime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void playTrack(uint8 track, bool restart = false) {
|
virtual void playTrack(uint8 track, bool restart = false) {
|
||||||
@@ -1408,7 +1413,7 @@ struct Level : IGame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Input::state[0][cInventory] || Input::state[1][cInventory]) && !level.isTitle() && inventory.titleTimer < 1.0f) {
|
if ((Input::state[0][cInventory] || Input::state[1][cInventory]) && !level.isTitle() && inventory.titleTimer < 1.0f && !inventory.active && inventory.lastKey == cMAX) {
|
||||||
int playerIndex = Input::state[0][cInventory] ? 0 : 1;
|
int playerIndex = Input::state[0][cInventory] ? 0 : 1;
|
||||||
|
|
||||||
if (player->health <= 0.0f)
|
if (player->health <= 0.0f)
|
||||||
|
12
src/mesh.h
12
src/mesh.h
@@ -553,8 +553,8 @@ struct MeshBuilder {
|
|||||||
m.geometry[1].ranges[0].iCount = 0;
|
m.geometry[1].ranges[0].iCount = 0;
|
||||||
m.geometry[2].ranges[0].iCount = 0;
|
m.geometry[2].ranges[0].iCount = 0;
|
||||||
// remove bottom triangles from skybox
|
// remove bottom triangles from skybox
|
||||||
if (m.geometry[0].ranges[0].iCount && ((level.version & TR::VER_TR3)))
|
//if (m.geometry[0].ranges[0].iCount && ((level.version & TR::VER_TR3)))
|
||||||
m.geometry[0].ranges[0].iCount -= 16 * 3;
|
// m.geometry[0].ranges[0].iCount -= 16 * 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ASSERT(vCount - vStartModel <= 0xFFFF);
|
ASSERT(vCount - vStartModel <= 0xFFFF);
|
||||||
@@ -1184,9 +1184,9 @@ struct MeshBuilder {
|
|||||||
Vertex &v = vertices[vCount + i];
|
Vertex &v = vertices[vCount + i];
|
||||||
v.normal = short4( 0, 0, 0, 0 );
|
v.normal = short4( 0, 0, 0, 0 );
|
||||||
if (color2 != 0 && (i == 0 || i == 3))
|
if (color2 != 0 && (i == 0 || i == 3))
|
||||||
v.color = *((ubyte4*)&color2);
|
v.light = *((ubyte4*)&color2);
|
||||||
else
|
else
|
||||||
v.color = *((ubyte4*)&color);
|
v.light = *((ubyte4*)&color);
|
||||||
|
|
||||||
short2 uv = tile.texCoord[i];
|
short2 uv = tile.texCoord[i];
|
||||||
|
|
||||||
@@ -1218,7 +1218,7 @@ struct MeshBuilder {
|
|||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
Vertex &v = vertices[vCount + i];
|
Vertex &v = vertices[vCount + i];
|
||||||
v.normal = short4( 0, 0, 0, 0 );
|
v.normal = short4( 0, 0, 0, 0 );
|
||||||
v.color = *((ubyte4*)&color1);
|
v.light = *((ubyte4*)&color1);
|
||||||
v.texCoord = uv;
|
v.texCoord = uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1238,7 +1238,7 @@ struct MeshBuilder {
|
|||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
Vertex &v = vertices[vCount + i];
|
Vertex &v = vertices[vCount + i];
|
||||||
v.normal = short4( 0, 0, 0, 0 );
|
v.normal = short4( 0, 0, 0, 0 );
|
||||||
v.color = *((ubyte4*)&color2);
|
v.light = *((ubyte4*)&color2);
|
||||||
v.texCoord = uv;
|
v.texCoord = uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -112,14 +112,34 @@ int osGetTime() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool osSave(const char *name, const void *data, int size) {
|
bool osCacheWrite(const char *name, const char *data, int size) {
|
||||||
FILE *f = fopen(name, "wb");
|
char path[255];
|
||||||
|
strcpy(path, Stream::cacheDir);
|
||||||
|
strcat(path, name);
|
||||||
|
FILE *f = fopen(path, "wb");
|
||||||
if (!f) return false;
|
if (!f) return false;
|
||||||
fwrite(data, size, 1, f);
|
fwrite(data, size, 1, f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stream* osCacheRead(const char *name) {
|
||||||
|
char path[255];
|
||||||
|
strcpy(path, Stream::cacheDir);
|
||||||
|
strcat(path, name);
|
||||||
|
if (!Stream::exists(path))
|
||||||
|
return NULL;
|
||||||
|
return new Stream(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool osSaveGame(const char *data, int size) {
|
||||||
|
return osCacheWrite("savegame", data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stream* osLoadGame() {
|
||||||
|
return osCacheRead("savegame");
|
||||||
|
}
|
||||||
|
|
||||||
// common input functions
|
// common input functions
|
||||||
InputKey keyToInputKey(int code) {
|
InputKey keyToInputKey(int code) {
|
||||||
static const int codes[] = {
|
static const int codes[] = {
|
||||||
@@ -168,8 +188,10 @@ typedef struct _XINPUT_VIBRATION
|
|||||||
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
|
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
|
||||||
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
|
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
|
||||||
|
|
||||||
DWORD (WINAPI *XInputGetState)(DWORD dwUserIndex, XINPUT_STATE* pState);
|
DWORD (WINAPI *XInputGetState) (DWORD dwUserIndex, XINPUT_STATE* pState) = NULL;
|
||||||
DWORD (WINAPI *XInputSetState)(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);
|
DWORD (WINAPI *XInputSetState) (DWORD dwUserIndex, XINPUT_VIBRATION* pVibration) = NULL;
|
||||||
|
void (WINAPI *XInputEnable) (BOOL enable) = NULL;
|
||||||
|
#define XInputGetProc(x) (x = (decltype(x))GetProcAddress(h, #x))
|
||||||
|
|
||||||
#define JOY_DEAD_ZONE_STICK 0.3f
|
#define JOY_DEAD_ZONE_STICK 0.3f
|
||||||
#define JOY_DEAD_ZONE_TRIGGER 0.01f
|
#define JOY_DEAD_ZONE_TRIGGER 0.01f
|
||||||
@@ -193,9 +215,12 @@ void joyInit() {
|
|||||||
memset(joyReady, 0, sizeof(joyReady));
|
memset(joyReady, 0, sizeof(joyReady));
|
||||||
|
|
||||||
HMODULE h = LoadLibrary("xinput1_3.dll");
|
HMODULE h = LoadLibrary("xinput1_3.dll");
|
||||||
|
if (h == NULL)
|
||||||
|
h = LoadLibrary("xinput9_1_0.dll");
|
||||||
|
|
||||||
XInputGetState = (decltype(XInputGetState))GetProcAddress(h, "XInputGetState");
|
XInputGetProc(XInputGetState);
|
||||||
XInputSetState = (decltype(XInputSetState))GetProcAddress(h, "XInputSetState");
|
XInputGetProc(XInputSetState);
|
||||||
|
XInputGetProc(XInputEnable);
|
||||||
|
|
||||||
for (int j = 0; j < INPUT_JOY_COUNT; j++) {
|
for (int j = 0; j < INPUT_JOY_COUNT; j++) {
|
||||||
if (XInputGetState) { // XInput
|
if (XInputGetState) { // XInput
|
||||||
@@ -403,6 +428,8 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
|
|||||||
switch (msg) {
|
switch (msg) {
|
||||||
// window
|
// window
|
||||||
case WM_ACTIVATE :
|
case WM_ACTIVATE :
|
||||||
|
if (XInputEnable)
|
||||||
|
XInputEnable(wParam != WA_INACTIVE);
|
||||||
Input::reset();
|
Input::reset();
|
||||||
break;
|
break;
|
||||||
case WM_SIZE:
|
case WM_SIZE:
|
||||||
|
15
src/shader.h
15
src/shader.h
@@ -80,7 +80,7 @@ struct Shader {
|
|||||||
// generate shader file path
|
// generate shader file path
|
||||||
if (Core::support.shaderBinary) {
|
if (Core::support.shaderBinary) {
|
||||||
uint32 hash = fnv32(defines, strlen(defines), fnv32(source, strlen(source)));
|
uint32 hash = fnv32(defines, strlen(defines), fnv32(source, strlen(source)));
|
||||||
sprintf(fileName, "%s%08X.xsh", Stream::cacheDir, hash);
|
sprintf(fileName, "%08X.xsh", hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
ID = glCreateProgram();
|
ID = glCreateProgram();
|
||||||
@@ -94,7 +94,7 @@ struct Shader {
|
|||||||
glGetProgramBinary(ID, size, NULL, &format, &data[8]);
|
glGetProgramBinary(ID, size, NULL, &format, &data[8]);
|
||||||
*(int*)(&data[0]) = format;
|
*(int*)(&data[0]) = format;
|
||||||
*(int*)(&data[4]) = size;
|
*(int*)(&data[4]) = size;
|
||||||
Stream::write(fileName, data, 8 + size);
|
osCacheWrite(fileName, data, 8 + size);
|
||||||
delete[] data;
|
delete[] data;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -145,17 +145,18 @@ struct Shader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool linkBinary(const char *fileName) {
|
bool linkBinary(const char *fileName) {
|
||||||
if (!Stream::exists(fileName))
|
Stream *stream = osCacheRead(fileName);
|
||||||
|
if (!stream)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
GLenum size, format;
|
GLenum size, format;
|
||||||
Stream stream(fileName);
|
stream->read(format);
|
||||||
stream.read(format);
|
stream->read(size);
|
||||||
stream.read(size);
|
|
||||||
char *data = new char[size];
|
char *data = new char[size];
|
||||||
stream.raw(data, size);
|
stream->raw(data, size);
|
||||||
glProgramBinary(ID, format, data, size);
|
glProgramBinary(ID, format, data, size);
|
||||||
delete[] data;
|
delete[] data;
|
||||||
|
delete stream;
|
||||||
|
|
||||||
return checkLink();
|
return checkLink();
|
||||||
}
|
}
|
||||||
|
@@ -14,11 +14,11 @@ varying vec4 vColor;
|
|||||||
|
|
||||||
attribute vec4 aCoord;
|
attribute vec4 aCoord;
|
||||||
attribute vec4 aTexCoord;
|
attribute vec4 aTexCoord;
|
||||||
attribute vec4 aColor;
|
attribute vec4 aLight;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vTexCoord = aTexCoord.xy;
|
vTexCoord = aTexCoord.xy;
|
||||||
vColor = aColor;
|
vColor = aLight;
|
||||||
gl_Position = uViewProj * vec4(aCoord.xy * uPosScale.zw + uPosScale.xy, 0.0, 1.0);
|
gl_Position = uViewProj * vec4(aCoord.xy * uPosScale.zw + uPosScale.xy, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
91
src/ui.h
91
src/ui.h
@@ -24,6 +24,9 @@ enum StringID {
|
|||||||
, STR_NOT_READY
|
, STR_NOT_READY
|
||||||
, STR_PLAYER_1
|
, STR_PLAYER_1
|
||||||
, STR_PLAYER_2
|
, STR_PLAYER_2
|
||||||
|
, STR_PRESS_ANY_KEY
|
||||||
|
, STR_HELP_SELECT
|
||||||
|
, STR_HELP_BACK
|
||||||
// inventory pages
|
// inventory pages
|
||||||
, STR_OPTION
|
, STR_OPTION
|
||||||
, STR_INVENTORY
|
, STR_INVENTORY
|
||||||
@@ -59,10 +62,20 @@ enum StringID {
|
|||||||
, STR_REVERBERATION
|
, STR_REVERBERATION
|
||||||
// controls options
|
// controls options
|
||||||
, STR_SET_CONTROLS
|
, STR_SET_CONTROLS
|
||||||
|
, STR_OPT_CONTROLS_KEYBOARD
|
||||||
, STR_OPT_CONTROLS_GAMEPAD
|
, STR_OPT_CONTROLS_GAMEPAD
|
||||||
, STR_OPT_CONTROLS_VIBRATION
|
, STR_OPT_CONTROLS_VIBRATION
|
||||||
, STR_OPT_CONTROLS_RETARGET
|
, STR_OPT_CONTROLS_RETARGET
|
||||||
, STR_OPT_CONTROLS_MULTIAIM
|
, STR_OPT_CONTROLS_MULTIAIM
|
||||||
|
// controls
|
||||||
|
, STR_CTRL_FIRST
|
||||||
|
, STR_CTRL_LAST = STR_CTRL_FIRST + cMAX - 1
|
||||||
|
// keys
|
||||||
|
, STR_KEY_FIRST
|
||||||
|
, STR_KEY_LAST = STR_KEY_FIRST + ikZ
|
||||||
|
// gamepad
|
||||||
|
, STR_JOY_FIRST
|
||||||
|
, STR_JOY_LAST = STR_JOY_FIRST + jkMAX - 1
|
||||||
// inventory items
|
// inventory items
|
||||||
, STR_UNKNOWN
|
, STR_UNKNOWN
|
||||||
, STR_PISTOLS
|
, STR_PISTOLS
|
||||||
@@ -83,32 +96,21 @@ enum StringID {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const char *helpText =
|
const char *helpText =
|
||||||
"Controls gamepad, touch and keyboard:@"
|
"Start - add second player or restore Lara@"
|
||||||
" Enter, Start (gamepad) - add second player or restore Lara@"
|
"H - Show or hide this help@"
|
||||||
" H - Show or hide this help@"
|
"ALT + ENTER - Fullscreen@"
|
||||||
" TAB - Inventory@"
|
"C - Look@"
|
||||||
" LEFT - Left@"
|
"R - Slow motion@"
|
||||||
" RIGHT - Right@"
|
"T - Fast motion@"
|
||||||
" UP - Run@"
|
"Roll - Up + Down@"
|
||||||
" DOWN - Back@"
|
"Step Left - Walk + Left@"
|
||||||
" SHIFT - Walk@"
|
"Step Right - Walk + Right@"
|
||||||
" SPACE - Draw Weapon@"
|
"Out of water - Up + Action@"
|
||||||
" CTRL - Action@"
|
"Handstand - Run + Walk@"
|
||||||
" D - Jump@"
|
"Swan dive - Run + Walk + Jump@"
|
||||||
" Z - Step Left@"
|
"First Person View - Look + Action@"
|
||||||
" X - Step Right@"
|
"DOZY on - Look + Duck + Action + Jump@"
|
||||||
" A - Roll@"
|
"DOZY off - Walk";
|
||||||
" C - Look # not implemented #@"
|
|
||||||
" V - First Person View@"
|
|
||||||
" R - slow motion@"
|
|
||||||
" T - fast motion@"
|
|
||||||
" ALT + ENTER - Fullscreen@@"
|
|
||||||
"Actions:@"
|
|
||||||
" Out of water - Run + Action@"
|
|
||||||
" Handstand - Run + Walk@"
|
|
||||||
" Swan dive - Run + Walk + jump@"
|
|
||||||
" DOZY on - Look + Step Right + Action + Jump@"
|
|
||||||
" DOZY off - Walk@";
|
|
||||||
|
|
||||||
|
|
||||||
const char *STR[STR_MAX] = {
|
const char *STR[STR_MAX] = {
|
||||||
@@ -131,6 +133,9 @@ const char *STR[STR_MAX] = {
|
|||||||
, "Not Ready"
|
, "Not Ready"
|
||||||
, "Player 1"
|
, "Player 1"
|
||||||
, "Player 2"
|
, "Player 2"
|
||||||
|
, "Press Any Key"
|
||||||
|
, "%s - Select"
|
||||||
|
, "%s - Go Back"
|
||||||
// inventory pages
|
// inventory pages
|
||||||
, "OPTION"
|
, "OPTION"
|
||||||
, "INVENTORY"
|
, "INVENTORY"
|
||||||
@@ -166,10 +171,20 @@ const char *STR[STR_MAX] = {
|
|||||||
, "Reverberation"
|
, "Reverberation"
|
||||||
// controls options
|
// controls options
|
||||||
, "Set Controls"
|
, "Set Controls"
|
||||||
|
, "Keyboard"
|
||||||
, "Gamepad"
|
, "Gamepad"
|
||||||
, "Vibration"
|
, "Vibration"
|
||||||
, "Retargeting"
|
, "Retargeting"
|
||||||
, "Multi-aiming"
|
, "Multi-aiming"
|
||||||
|
// controls
|
||||||
|
, "Left", "Right", "Up", "Down", "Jump", "Walk", "Action", "Draw Weapon", "Look", "Duck", "Dash", "Roll", "Inventory", "Start"
|
||||||
|
// keys
|
||||||
|
, "NONE", "LEFT", "RIGHT", "UP", "DOWN", "SPACE", "TAB", "ENTER", "ESCAPE", "SHIFT", "CTRL", "ALT"
|
||||||
|
, "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
|
||||||
|
, "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M"
|
||||||
|
, "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"
|
||||||
|
// gamepad
|
||||||
|
, "NONE", "A", "B", "X", "Y", "L BUMPER", "R BUMPER", "SELECT", "START", "L STICK", "R STICK", "L TRIGGER", "R TRIGGER", "D-LEFT", "D-RIGHT", "D-UP", "D-DOWN"
|
||||||
// inventory items
|
// inventory items
|
||||||
, "Unknown"
|
, "Unknown"
|
||||||
, "Pistols"
|
, "Pistols"
|
||||||
@@ -311,13 +326,13 @@ namespace UI {
|
|||||||
SHADE_GRAY = 2,
|
SHADE_GRAY = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
void textOut(const vec2 &pos, const char *text, Align align = aLeft, float width = 0, ShadeType shade = SHADE_ORANGE, bool isShadow = false) {
|
void textOut(const vec2 &pos, const char *text, Align align = aLeft, float width = 0, uint8 alpha = 255, ShadeType shade = SHADE_ORANGE, bool isShadow = false) {
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
|
|
||||||
TR::Level *level = game->getLevel();
|
TR::Level *level = game->getLevel();
|
||||||
|
|
||||||
if (shade && !isShadow && ((level->version & TR::VER_TR3)))
|
if (shade && !isShadow && ((level->version & TR::VER_TR3)))
|
||||||
textOut(pos + vec2(1, 1), text, align, width, shade, true);
|
textOut(pos + vec2(1, 1), text, align, width, alpha, shade, true);
|
||||||
|
|
||||||
MeshBuilder *mesh = game->getMesh();
|
MeshBuilder *mesh = game->getMesh();
|
||||||
int seq = level->extra.glyphs;
|
int seq = level->extra.glyphs;
|
||||||
@@ -354,18 +369,18 @@ namespace UI {
|
|||||||
|
|
||||||
TR::Color32 tColor, bColor;
|
TR::Color32 tColor, bColor;
|
||||||
if (isShadow) {
|
if (isShadow) {
|
||||||
tColor = bColor = TR::Color32(0, 0, 0, 255);
|
tColor = bColor = TR::Color32(0, 0, 0, alpha);
|
||||||
} else {
|
} else {
|
||||||
tColor = bColor = TR::Color32(255, 255, 255, 255);
|
tColor = bColor = TR::Color32(255, 255, 255, alpha);
|
||||||
|
|
||||||
if (shade && ((level->version & TR::VER_TR3))) {
|
if (shade && ((level->version & TR::VER_TR3))) {
|
||||||
if (shade == SHADE_ORANGE) {
|
if (shade == SHADE_ORANGE) {
|
||||||
tColor = TR::Color32(255, 190, 90, 255);
|
tColor = TR::Color32(255, 190, 90, alpha);
|
||||||
bColor = TR::Color32(140, 50, 10, 255);
|
bColor = TR::Color32(140, 50, 10, alpha);
|
||||||
}
|
}
|
||||||
if (shade == SHADE_GRAY) {
|
if (shade == SHADE_GRAY) {
|
||||||
tColor = TR::Color32(255, 255, 255, 255);
|
tColor = TR::Color32(255, 255, 255, alpha);
|
||||||
bColor = TR::Color32(128, 128, 128, 255);
|
bColor = TR::Color32(128, 128, 128, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -389,8 +404,8 @@ namespace UI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void textOut(const vec2 &pos, StringID str, Align align = aLeft, float width = 0, ShadeType shade = SHADE_ORANGE) {
|
void textOut(const vec2 &pos, StringID str, Align align = aLeft, float width = 0, uint8 alpha = 255, ShadeType shade = SHADE_ORANGE) {
|
||||||
textOut(pos, STR[str], align, width, shade);
|
textOut(pos, STR[str], align, width, alpha, shade);
|
||||||
}
|
}
|
||||||
|
|
||||||
void specOut(const vec2 &pos, char specChar) {
|
void specOut(const vec2 &pos, char specChar) {
|
||||||
@@ -508,10 +523,10 @@ namespace UI {
|
|||||||
void renderHelp() {
|
void renderHelp() {
|
||||||
// TODO: Core::eye offset
|
// TODO: Core::eye offset
|
||||||
if (showHelp)
|
if (showHelp)
|
||||||
textOut(vec2(0, 32), STR_HELP_TEXT, aRight, width - 32, UI::SHADE_GRAY);
|
textOut(vec2(32, 32), STR_HELP_TEXT, aLeft, width - 32, 255, UI::SHADE_GRAY);
|
||||||
else
|
else
|
||||||
if (helpTipTime > 0.0f)
|
if (helpTipTime > 0.0f)
|
||||||
textOut(vec2(0, height - 32), STR_HELP_PRESS, aCenter, width, UI::SHADE_ORANGE);
|
textOut(vec2(0, height - 32), STR_HELP_PRESS, aCenter, width, 255, UI::SHADE_ORANGE);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1211,10 +1211,6 @@ struct Stream {
|
|||||||
return exists(fileName);
|
return exists(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write(const char *name, const void *data, int size) {
|
|
||||||
osSave(name, data, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPos(int pos) {
|
void setPos(int pos) {
|
||||||
this->pos = pos;
|
this->pos = pos;
|
||||||
if (f) fseek(f, pos, SEEK_SET);
|
if (f) fseek(f, pos, SEEK_SET);
|
||||||
|
Reference in New Issue
Block a user