mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-14 00:54:05 +02:00
#11 controls mapping; saving settings
This commit is contained in:
@@ -448,7 +448,7 @@ struct Camera : ICamera {
|
||||
virtual void update() {
|
||||
if (shake > 0.0f) {
|
||||
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) {
|
||||
|
34
src/core.h
34
src/core.h
@@ -164,12 +164,6 @@
|
||||
#define GENERATE_WATER_PLANE
|
||||
#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"
|
||||
|
||||
extern void* osMutexInit ();
|
||||
@@ -177,6 +171,18 @@ extern void osMutexFree (void *obj);
|
||||
extern void osMutexLock (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 {
|
||||
void *obj;
|
||||
|
||||
@@ -254,8 +260,8 @@ enum ControlKey {
|
||||
};
|
||||
|
||||
struct KeySet {
|
||||
InputKey key;
|
||||
JoyKey joy;
|
||||
uint8 key;
|
||||
uint8 joy;
|
||||
|
||||
KeySet() {}
|
||||
KeySet(InputKey key, JoyKey joy) : key(key), joy(joy) {}
|
||||
@@ -285,10 +291,14 @@ namespace Core {
|
||||
#endif
|
||||
} support;
|
||||
|
||||
#define SETTINGS_VERSION 1
|
||||
|
||||
struct Settings {
|
||||
enum Quality { LOW, MEDIUM, HIGH };
|
||||
enum Stereo { STEREO_OFF, STEREO_ON, STEREO_SPLIT };
|
||||
|
||||
uint8 version;
|
||||
|
||||
struct {
|
||||
union {
|
||||
struct {
|
||||
@@ -342,7 +352,9 @@ namespace Core {
|
||||
KeySet keys[cMAX];
|
||||
} controls[2];
|
||||
|
||||
uint8 playerIndex; // temporary, used only for setting controls
|
||||
// temporary, used only for setting controls
|
||||
uint8 playerIndex;
|
||||
uint8 ctrlIndex;
|
||||
} settings;
|
||||
|
||||
bool resetState;
|
||||
@@ -1021,6 +1033,8 @@ namespace Core {
|
||||
whiteTex = new Texture(1, 1, Texture::RGBA, Texture::NEAREST, &data);
|
||||
|
||||
// init settings
|
||||
settings.version = SETTINGS_VERSION;
|
||||
|
||||
settings.detail.setFilter (Core::Settings::HIGH);
|
||||
settings.detail.setLighting (Core::Settings::HIGH);
|
||||
settings.detail.setShadows (Core::Settings::HIGH);
|
||||
@@ -1076,7 +1090,7 @@ namespace Core {
|
||||
ctrl.keys[ cDash ] = KeySet( ikNone, jkRT );
|
||||
ctrl.keys[ cRoll ] = KeySet( ikNone, jkB );
|
||||
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
|
||||
|
16
src/game.h
16
src/game.h
@@ -34,10 +34,22 @@ namespace Game {
|
||||
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) {
|
||||
nextLevel = NULL;
|
||||
|
||||
Core::init();
|
||||
readSettings();
|
||||
|
||||
shaderCache = new ShaderCache();
|
||||
|
||||
UI::init(level);
|
||||
@@ -104,7 +116,7 @@ namespace Game {
|
||||
return true;
|
||||
|
||||
Input::update();
|
||||
|
||||
/*
|
||||
if (level->camera) {
|
||||
if (Input::down[ikV]) { // third <-> first person view
|
||||
level->camera->changeView(!level->camera->firstPerson);
|
||||
@@ -122,7 +134,7 @@ namespace Game {
|
||||
level->loadGame(0);
|
||||
Input::down[ikL] = false;
|
||||
}
|
||||
|
||||
*/
|
||||
if (!level->level.isTitle()) {
|
||||
if (Input::state[0][cStart]) level->addPlayer(0);
|
||||
if (Input::state[1][cStart]) level->addPlayer(1);
|
||||
|
@@ -38,8 +38,8 @@ namespace TR {
|
||||
|
||||
VER_TR3_PC = VER_TR3 | VER_PC,
|
||||
VER_TR3_PSX = VER_TR3 | VER_PSX,
|
||||
|
||||
VER_MAX = 0xFFFFFFFF,
|
||||
|
||||
VER_MAX = 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
enum LevelID {
|
||||
@@ -506,6 +506,9 @@ namespace TR {
|
||||
if (Stream::existsContent("data/JUNGLE.TR2"))
|
||||
return VER_TR3_PC;
|
||||
|
||||
if (Stream::existsContent("DATA/JUNGLE.PSX"))
|
||||
return VER_TR3_PSX;
|
||||
|
||||
useEasyStart = false;
|
||||
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_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);
|
||||
}
|
||||
} else {
|
||||
|
22
src/input.h
22
src/input.h
@@ -7,7 +7,7 @@
|
||||
#define INPUT_JOY_COUNT 4
|
||||
|
||||
namespace Input {
|
||||
|
||||
InputKey lastKey;
|
||||
bool down[ikMAX];
|
||||
bool state[2][cMAX];
|
||||
|
||||
@@ -19,9 +19,10 @@ namespace Input {
|
||||
} mouse;
|
||||
|
||||
struct Joystick {
|
||||
vec2 L, R;
|
||||
float LT, RT;
|
||||
bool down[jkMAX];
|
||||
vec2 L, R;
|
||||
float LT, RT;
|
||||
JoyKey lastKey;
|
||||
bool down[jkMAX];
|
||||
} joy[INPUT_JOY_COUNT];
|
||||
|
||||
struct Touch {
|
||||
@@ -77,6 +78,8 @@ namespace Input {
|
||||
default : ;
|
||||
}
|
||||
down[key] = value;
|
||||
|
||||
if (value && key <= ikZ) lastKey = key;
|
||||
}
|
||||
|
||||
void setPos(InputKey key, const vec2 &pos) {
|
||||
@@ -95,7 +98,12 @@ namespace Input {
|
||||
}
|
||||
|
||||
void setJoyDown(int index, JoyKey key, bool value) {
|
||||
if (joy[index].down[key] == value)
|
||||
return;
|
||||
|
||||
joy[index].down[key] = value;
|
||||
|
||||
if (value) joy[index].lastKey = key;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
for (int i = 0; i < COUNT(touch); i++)
|
||||
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 LINE_HEIGHT 20.0f
|
||||
|
||||
static const struct OptionItem *waitForKey = NULL;
|
||||
|
||||
struct OptionItem {
|
||||
enum Type {
|
||||
TYPE_TITLE,
|
||||
TYPE_EMPTY,
|
||||
TYPE_BUTTON,
|
||||
TYPE_PARAM,
|
||||
TYPE_KEY,
|
||||
} type;
|
||||
StringID title;
|
||||
intptr_t offset;
|
||||
@@ -31,7 +34,11 @@ struct OptionItem {
|
||||
uint8 maxValue;
|
||||
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 {
|
||||
if (oStr != STR_NOT_IMPLEMENTED) {
|
||||
@@ -40,12 +47,22 @@ struct OptionItem {
|
||||
w = w * 0.5f - 32.0f;
|
||||
}
|
||||
|
||||
UI::textOut(vec2(x, y), StringID(color + int(value)), UI::aCenter, w); // color as StringID
|
||||
if (active) {
|
||||
StringID vStr = StringID(color + int(value));
|
||||
|
||||
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;
|
||||
maxWidth = maxWidth * 0.5f + 8.0f;
|
||||
x += w * 0.5f;
|
||||
|
||||
if (value > 0) UI::specOut(vec2(x - maxWidth - 16.0f, y), 108);
|
||||
if (value < maxValue) UI::specOut(vec2(x + maxWidth, y), 109);
|
||||
}
|
||||
@@ -71,7 +88,7 @@ struct OptionItem {
|
||||
switch (type) {
|
||||
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::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_BUTTON : {
|
||||
const char *caption = offset ? (char*)offset : STR[title];
|
||||
@@ -79,6 +96,7 @@ struct OptionItem {
|
||||
break;
|
||||
}
|
||||
case TYPE_PARAM :
|
||||
case TYPE_KEY :
|
||||
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[] = {
|
||||
OptionItem( OptionItem::TYPE_TITLE, STR_SET_CONTROLS ),
|
||||
OptionItem( ),
|
||||
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_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_MULTIAIM, SETTINGS( controls[0].multiaim ), STR_OFF, 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_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_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)];
|
||||
@@ -269,9 +303,19 @@ struct Inventory {
|
||||
case TR::Entity::INV_CONTROLS :
|
||||
ASSERT(optControls[2].offset == SETTINGS( playerIndex) );
|
||||
for (int i = 0; i < COUNT(optControls); i++) {
|
||||
optControlsPlayer[i] = optControls[i];
|
||||
if (i > 2)
|
||||
optControlsPlayer[i].offset += sizeof(Core::Settings::Controls) * Core::settings.playerIndex;
|
||||
OptionItem &opt = optControlsPlayer[i];
|
||||
opt = optControls[i];
|
||||
|
||||
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);
|
||||
return optControlsPlayer;
|
||||
@@ -305,7 +349,7 @@ struct Inventory {
|
||||
uint8 &value = *(uint8*)(intptr_t(settings) + opt->offset);
|
||||
|
||||
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 cDown : nextSlot(slot, +1); break;
|
||||
case cLeft :
|
||||
@@ -455,6 +499,8 @@ struct Inventory {
|
||||
|
||||
phaseRing = phasePage = phaseChoose = phaseSelect = 0.0f;
|
||||
memset(pageItemIndex, 0, sizeof(pageItemIndex));
|
||||
|
||||
waitForKey = NULL;
|
||||
}
|
||||
|
||||
~Inventory() {
|
||||
@@ -584,6 +630,9 @@ struct Inventory {
|
||||
}
|
||||
|
||||
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;
|
||||
titleTimer = 0.0f;
|
||||
|
||||
@@ -714,6 +763,7 @@ struct Inventory {
|
||||
}
|
||||
case TR::Entity::INV_CONTROLS :
|
||||
Core::settings.playerIndex = 0;
|
||||
Core::settings.ctrlIndex = 0;
|
||||
break;
|
||||
case TR::Entity::INV_DETAIL :
|
||||
settings = Core::settings;
|
||||
@@ -769,13 +819,6 @@ struct Inventory {
|
||||
nextLevel = level->getHomeId();
|
||||
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) {
|
||||
@@ -792,7 +835,17 @@ struct Inventory {
|
||||
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);
|
||||
chosen = false;
|
||||
}
|
||||
@@ -834,17 +887,17 @@ struct Inventory {
|
||||
Input::Joystick &joy = Input::joy[Core::settings.controls[playerIndex].joyIndex];
|
||||
|
||||
ControlKey key = cMAX;
|
||||
if (Input::state[playerIndex][cAction])
|
||||
if (Input::down[ikCtrl] || Input::down[ikEnter] || joy.down[jkA])
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -1036,7 +1121,7 @@ struct Inventory {
|
||||
sprintf(buf, "%d %c", item->count, spec);
|
||||
for (int i = 0; buf[i] != ' '; i++)
|
||||
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);
|
||||
|
||||
if (canFlipPage(-1)) {
|
||||
UI::textOut(vec2(16 - eye, 32), "[", UI::aLeft, UI::width, UI::SHADE_NONE);
|
||||
UI::textOut(vec2(-eye, 32), "[", UI::aRight, UI::width - 20, UI::SHADE_NONE);
|
||||
UI::textOut(vec2(16 - eye, 32), "[", UI::aLeft, UI::width);
|
||||
UI::textOut(vec2(-eye, 32), "[", UI::aRight, UI::width - 20);
|
||||
}
|
||||
|
||||
if (canFlipPage(1)) {
|
||||
UI::textOut(vec2(16 - eye, 480 - 16), "]", UI::aLeft, UI::width, UI::SHADE_NONE);
|
||||
UI::textOut(vec2(-eye, 480 - 16), "]", UI::aRight, UI::width - 20, 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);
|
||||
}
|
||||
|
||||
if (index == targetIndex)
|
||||
@@ -1284,15 +1369,13 @@ struct Inventory {
|
||||
|
||||
// inventory controls help
|
||||
float dx = 32.0f - eye;
|
||||
UI::textOut(vec2(dx, 480 - 64), "Ctrl - Select", UI::aLeft, UI::width, UI::SHADE_NONE);
|
||||
if (chosen)
|
||||
UI::textOut(vec2(0, 480 - 64),
|
||||
#ifdef __EMSCRIPTEN__
|
||||
"D"
|
||||
#else
|
||||
"Alt"
|
||||
#endif
|
||||
" - Go Back", UI::aRight, UI::width - dx, UI::SHADE_NONE);
|
||||
char buf[64];
|
||||
sprintf(buf, STR[STR_HELP_SELECT], STR[STR_KEY_FIRST + ikEnter] );
|
||||
UI::textOut(vec2(dx, 480 - 64), buf, UI::aLeft, UI::width);
|
||||
if (chosen) {
|
||||
sprintf(buf, STR[STR_HELP_BACK], STR[STR_KEY_FIRST + Core::settings.controls[playerIndex].keys[ cInventory ].key] );
|
||||
UI::textOut(vec2(0, 480 - 64), buf, UI::aRight, UI::width - dx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
25
src/lara.h
25
src/lara.h
@@ -253,6 +253,7 @@ struct Lara : Character {
|
||||
Camera *camera;
|
||||
|
||||
float hitTimer;
|
||||
bool camChanged; // hit key detection to go first person view mode
|
||||
|
||||
#ifdef _DEBUG
|
||||
//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) {
|
||||
camera = new Camera(game, this);
|
||||
|
||||
hitTimer = 0.0f;
|
||||
hitTimer = 0.0f;
|
||||
camChanged = false;
|
||||
|
||||
if (level->extra.laraSkin > -1)
|
||||
level->entities[entity].modelIndex = level->extra.laraSkin + 1;
|
||||
@@ -2652,6 +2654,14 @@ struct Lara : Character {
|
||||
// analog control
|
||||
rotFactor = vec2(1.0f);
|
||||
|
||||
if ((input & LOOK) && (input & ACTION)) {
|
||||
if (!camChanged) {
|
||||
camera->changeView(!camera->firstPerson);
|
||||
camChanged = true;
|
||||
}
|
||||
} else
|
||||
camChanged = false;
|
||||
|
||||
if (input & LOOK)
|
||||
return input;
|
||||
|
||||
@@ -2700,7 +2710,14 @@ struct Lara : Character {
|
||||
|| state == STATE_USE_KEY
|
||||
|| state == STATE_USE_PUZZLE
|
||||
|| 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) {
|
||||
@@ -2749,9 +2766,9 @@ struct Lara : Character {
|
||||
if (hitTimer > 0.0f) {
|
||||
hitTimer -= Core::deltaTime;
|
||||
if (hitTimer > 0.0f)
|
||||
osJoyVibrate(Core::settings.controls[camera->cameraIndex].joyIndex, 0.5f, 0.5f);
|
||||
Input::setJoyVibrate(camera->cameraIndex, 0.5f, 0.5f);
|
||||
else
|
||||
osJoyVibrate(Core::settings.controls[camera->cameraIndex].joyIndex, 0, 0);
|
||||
Input::setJoyVibrate(camera->cameraIndex, 0, 0);
|
||||
}
|
||||
|
||||
if (level->isCutsceneLevel())
|
||||
|
19
src/level.h
19
src/level.h
@@ -130,21 +130,24 @@ struct Level : IGame {
|
||||
save->size = ptr - data;
|
||||
save->version = level.version & TR::VER_VERSION;
|
||||
|
||||
Stream::write("savegame.dat", data, int(ptr - data));
|
||||
osSaveGame(data, int(ptr - data));
|
||||
delete[] data;
|
||||
|
||||
LOG("Ok\n");
|
||||
}
|
||||
|
||||
virtual void loadGame(int slot) {
|
||||
LOG("Lave Game... ");
|
||||
LOG("Load Game... ");
|
||||
|
||||
Stream *stream = osLoadGame();
|
||||
if (!stream)
|
||||
return;
|
||||
|
||||
clearInventory();
|
||||
clearEntities();
|
||||
|
||||
Stream stream("savegame.dat");
|
||||
char *data;
|
||||
stream.read(data, stream.size);
|
||||
stream->read(data, stream->size);
|
||||
char *ptr = data;
|
||||
|
||||
TR::SaveGame *save = (TR::SaveGame*)ptr;
|
||||
@@ -188,6 +191,7 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
delete[] data;
|
||||
delete stream;
|
||||
|
||||
// camera->room = lara->getRoomIndex();
|
||||
// camera->pos = camera->destPos = lara->pos;
|
||||
@@ -233,6 +237,8 @@ struct Level : IGame {
|
||||
|
||||
Core::settings = settings;
|
||||
|
||||
osCacheWrite("settings", (char*)&settings, sizeof(settings));
|
||||
|
||||
if (rebuildShaders) {
|
||||
delete shaderCache;
|
||||
shaderCache = new ShaderCache();
|
||||
@@ -516,7 +522,7 @@ struct Level : IGame {
|
||||
switch (b.flags.mode) {
|
||||
case 0 : if (level.version & TR::VER_TR1) flags |= Sound::UNIQUE; break; // TODO check this
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -549,7 +555,6 @@ struct Level : IGame {
|
||||
}
|
||||
level->sndSoundtrack->setVolume(1.0f, 0.2f);
|
||||
}
|
||||
LOG("play soundtrack - %d\n", Core::getTime());
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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[2].ranges[0].iCount = 0;
|
||||
// remove bottom triangles from skybox
|
||||
if (m.geometry[0].ranges[0].iCount && ((level.version & TR::VER_TR3)))
|
||||
m.geometry[0].ranges[0].iCount -= 16 * 3;
|
||||
//if (m.geometry[0].ranges[0].iCount && ((level.version & TR::VER_TR3)))
|
||||
// m.geometry[0].ranges[0].iCount -= 16 * 3;
|
||||
}
|
||||
}
|
||||
ASSERT(vCount - vStartModel <= 0xFFFF);
|
||||
@@ -1184,9 +1184,9 @@ struct MeshBuilder {
|
||||
Vertex &v = vertices[vCount + i];
|
||||
v.normal = short4( 0, 0, 0, 0 );
|
||||
if (color2 != 0 && (i == 0 || i == 3))
|
||||
v.color = *((ubyte4*)&color2);
|
||||
v.light = *((ubyte4*)&color2);
|
||||
else
|
||||
v.color = *((ubyte4*)&color);
|
||||
v.light = *((ubyte4*)&color);
|
||||
|
||||
short2 uv = tile.texCoord[i];
|
||||
|
||||
@@ -1218,7 +1218,7 @@ struct MeshBuilder {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Vertex &v = vertices[vCount + i];
|
||||
v.normal = short4( 0, 0, 0, 0 );
|
||||
v.color = *((ubyte4*)&color1);
|
||||
v.light = *((ubyte4*)&color1);
|
||||
v.texCoord = uv;
|
||||
}
|
||||
|
||||
@@ -1238,7 +1238,7 @@ struct MeshBuilder {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Vertex &v = vertices[vCount + i];
|
||||
v.normal = short4( 0, 0, 0, 0 );
|
||||
v.color = *((ubyte4*)&color2);
|
||||
v.light = *((ubyte4*)&color2);
|
||||
v.texCoord = uv;
|
||||
}
|
||||
|
||||
|
@@ -112,14 +112,34 @@ int osGetTime() {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool osSave(const char *name, const void *data, int size) {
|
||||
FILE *f = fopen(name, "wb");
|
||||
bool osCacheWrite(const char *name, const char *data, int size) {
|
||||
char path[255];
|
||||
strcpy(path, Stream::cacheDir);
|
||||
strcat(path, name);
|
||||
FILE *f = fopen(path, "wb");
|
||||
if (!f) return false;
|
||||
fwrite(data, size, 1, f);
|
||||
fclose(f);
|
||||
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
|
||||
InputKey keyToInputKey(int code) {
|
||||
static const int codes[] = {
|
||||
@@ -168,8 +188,10 @@ typedef struct _XINPUT_VIBRATION
|
||||
#define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
|
||||
#define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
|
||||
|
||||
DWORD (WINAPI *XInputGetState)(DWORD dwUserIndex, XINPUT_STATE* pState);
|
||||
DWORD (WINAPI *XInputSetState)(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);
|
||||
DWORD (WINAPI *XInputGetState) (DWORD dwUserIndex, XINPUT_STATE* pState) = NULL;
|
||||
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_TRIGGER 0.01f
|
||||
@@ -193,9 +215,12 @@ void joyInit() {
|
||||
memset(joyReady, 0, sizeof(joyReady));
|
||||
|
||||
HMODULE h = LoadLibrary("xinput1_3.dll");
|
||||
if (h == NULL)
|
||||
h = LoadLibrary("xinput9_1_0.dll");
|
||||
|
||||
XInputGetState = (decltype(XInputGetState))GetProcAddress(h, "XInputGetState");
|
||||
XInputSetState = (decltype(XInputSetState))GetProcAddress(h, "XInputSetState");
|
||||
XInputGetProc(XInputGetState);
|
||||
XInputGetProc(XInputSetState);
|
||||
XInputGetProc(XInputEnable);
|
||||
|
||||
for (int j = 0; j < INPUT_JOY_COUNT; j++) {
|
||||
if (XInputGetState) { // XInput
|
||||
@@ -403,6 +428,8 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
|
||||
switch (msg) {
|
||||
// window
|
||||
case WM_ACTIVATE :
|
||||
if (XInputEnable)
|
||||
XInputEnable(wParam != WA_INACTIVE);
|
||||
Input::reset();
|
||||
break;
|
||||
case WM_SIZE:
|
||||
|
15
src/shader.h
15
src/shader.h
@@ -80,7 +80,7 @@ struct Shader {
|
||||
// generate shader file path
|
||||
if (Core::support.shaderBinary) {
|
||||
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();
|
||||
@@ -94,7 +94,7 @@ struct Shader {
|
||||
glGetProgramBinary(ID, size, NULL, &format, &data[8]);
|
||||
*(int*)(&data[0]) = format;
|
||||
*(int*)(&data[4]) = size;
|
||||
Stream::write(fileName, data, 8 + size);
|
||||
osCacheWrite(fileName, data, 8 + size);
|
||||
delete[] data;
|
||||
#endif
|
||||
}
|
||||
@@ -145,17 +145,18 @@ struct Shader {
|
||||
}
|
||||
|
||||
bool linkBinary(const char *fileName) {
|
||||
if (!Stream::exists(fileName))
|
||||
Stream *stream = osCacheRead(fileName);
|
||||
if (!stream)
|
||||
return false;
|
||||
|
||||
GLenum size, format;
|
||||
Stream stream(fileName);
|
||||
stream.read(format);
|
||||
stream.read(size);
|
||||
stream->read(format);
|
||||
stream->read(size);
|
||||
char *data = new char[size];
|
||||
stream.raw(data, size);
|
||||
stream->raw(data, size);
|
||||
glProgramBinary(ID, format, data, size);
|
||||
delete[] data;
|
||||
delete stream;
|
||||
|
||||
return checkLink();
|
||||
}
|
||||
|
@@ -14,11 +14,11 @@ varying vec4 vColor;
|
||||
|
||||
attribute vec4 aCoord;
|
||||
attribute vec4 aTexCoord;
|
||||
attribute vec4 aColor;
|
||||
attribute vec4 aLight;
|
||||
|
||||
void main() {
|
||||
vTexCoord = aTexCoord.xy;
|
||||
vColor = aColor;
|
||||
vColor = aLight;
|
||||
gl_Position = uViewProj * vec4(aCoord.xy * uPosScale.zw + uPosScale.xy, 0.0, 1.0);
|
||||
}
|
||||
#else
|
||||
|
91
src/ui.h
91
src/ui.h
@@ -24,6 +24,9 @@ enum StringID {
|
||||
, STR_NOT_READY
|
||||
, STR_PLAYER_1
|
||||
, STR_PLAYER_2
|
||||
, STR_PRESS_ANY_KEY
|
||||
, STR_HELP_SELECT
|
||||
, STR_HELP_BACK
|
||||
// inventory pages
|
||||
, STR_OPTION
|
||||
, STR_INVENTORY
|
||||
@@ -59,10 +62,20 @@ enum StringID {
|
||||
, STR_REVERBERATION
|
||||
// controls options
|
||||
, STR_SET_CONTROLS
|
||||
, STR_OPT_CONTROLS_KEYBOARD
|
||||
, STR_OPT_CONTROLS_GAMEPAD
|
||||
, STR_OPT_CONTROLS_VIBRATION
|
||||
, STR_OPT_CONTROLS_RETARGET
|
||||
, 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
|
||||
, STR_UNKNOWN
|
||||
, STR_PISTOLS
|
||||
@@ -83,32 +96,21 @@ enum StringID {
|
||||
};
|
||||
|
||||
const char *helpText =
|
||||
"Controls gamepad, touch and keyboard:@"
|
||||
" Enter, Start (gamepad) - add second player or restore Lara@"
|
||||
" H - Show or hide this help@"
|
||||
" TAB - Inventory@"
|
||||
" LEFT - Left@"
|
||||
" RIGHT - Right@"
|
||||
" UP - Run@"
|
||||
" DOWN - Back@"
|
||||
" SHIFT - Walk@"
|
||||
" SPACE - Draw Weapon@"
|
||||
" CTRL - Action@"
|
||||
" D - Jump@"
|
||||
" Z - Step Left@"
|
||||
" X - Step Right@"
|
||||
" A - Roll@"
|
||||
" 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@";
|
||||
"Start - add second player or restore Lara@"
|
||||
"H - Show or hide this help@"
|
||||
"ALT + ENTER - Fullscreen@"
|
||||
"C - Look@"
|
||||
"R - Slow motion@"
|
||||
"T - Fast motion@"
|
||||
"Roll - Up + Down@"
|
||||
"Step Left - Walk + Left@"
|
||||
"Step Right - Walk + Right@"
|
||||
"Out of water - Up + Action@"
|
||||
"Handstand - Run + Walk@"
|
||||
"Swan dive - Run + Walk + Jump@"
|
||||
"First Person View - Look + Action@"
|
||||
"DOZY on - Look + Duck + Action + Jump@"
|
||||
"DOZY off - Walk";
|
||||
|
||||
|
||||
const char *STR[STR_MAX] = {
|
||||
@@ -131,6 +133,9 @@ const char *STR[STR_MAX] = {
|
||||
, "Not Ready"
|
||||
, "Player 1"
|
||||
, "Player 2"
|
||||
, "Press Any Key"
|
||||
, "%s - Select"
|
||||
, "%s - Go Back"
|
||||
// inventory pages
|
||||
, "OPTION"
|
||||
, "INVENTORY"
|
||||
@@ -166,10 +171,20 @@ const char *STR[STR_MAX] = {
|
||||
, "Reverberation"
|
||||
// controls options
|
||||
, "Set Controls"
|
||||
, "Keyboard"
|
||||
, "Gamepad"
|
||||
, "Vibration"
|
||||
, "Retargeting"
|
||||
, "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
|
||||
, "Unknown"
|
||||
, "Pistols"
|
||||
@@ -311,13 +326,13 @@ namespace UI {
|
||||
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;
|
||||
|
||||
TR::Level *level = game->getLevel();
|
||||
|
||||
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();
|
||||
int seq = level->extra.glyphs;
|
||||
@@ -354,18 +369,18 @@ namespace UI {
|
||||
|
||||
TR::Color32 tColor, bColor;
|
||||
if (isShadow) {
|
||||
tColor = bColor = TR::Color32(0, 0, 0, 255);
|
||||
tColor = bColor = TR::Color32(0, 0, 0, alpha);
|
||||
} 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 == SHADE_ORANGE) {
|
||||
tColor = TR::Color32(255, 190, 90, 255);
|
||||
bColor = TR::Color32(140, 50, 10, 255);
|
||||
tColor = TR::Color32(255, 190, 90, alpha);
|
||||
bColor = TR::Color32(140, 50, 10, alpha);
|
||||
}
|
||||
if (shade == SHADE_GRAY) {
|
||||
tColor = TR::Color32(255, 255, 255, 255);
|
||||
bColor = TR::Color32(128, 128, 128, 255);
|
||||
tColor = TR::Color32(255, 255, 255, alpha);
|
||||
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) {
|
||||
textOut(pos, STR[str], align, width, shade);
|
||||
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, alpha, shade);
|
||||
}
|
||||
|
||||
void specOut(const vec2 &pos, char specChar) {
|
||||
@@ -508,10 +523,10 @@ namespace UI {
|
||||
void renderHelp() {
|
||||
// TODO: Core::eye offset
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
static void write(const char *name, const void *data, int size) {
|
||||
osSave(name, data, size);
|
||||
}
|
||||
|
||||
void setPos(int pos) {
|
||||
this->pos = pos;
|
||||
if (f) fseek(f, pos, SEEK_SET);
|
||||
|
Reference in New Issue
Block a user