1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-13 16:44:50 +02:00

"Simple Items" selector in detail settings for pickups

This commit is contained in:
XProger
2018-11-23 06:49:25 +03:00
parent 7187171886
commit 2d12e141a8
8 changed files with 181 additions and 112 deletions

View File

@@ -199,6 +199,16 @@ struct Controller {
deactivate(true);
}
void updateModel() {
const TR::Model *model = getModel();
if (!model || model == animation.model)
return;
animation.setModel(model);
delete[] joints;
joints = new Basis[model->mCount];
}
bool fixRoomIndex() { // TODO: remove this and fix braid
vec3 p = getPos();
if (insideRoom(p, roomIndex))
@@ -1172,6 +1182,9 @@ struct Controller {
}
virtual void update() {
if (getEntity().modelIndex <= 0)
return;
if (explodeMask)
updateExplosion();
else
@@ -1345,14 +1358,35 @@ struct Controller {
return joints[index];
}
void renderSprite(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics, int frame) {
Basis b;
b.w = 1.0f;
b.pos = pos;
#ifdef MERGE_SPRITES
b.rot = Core::mViewInv.getRot();
#else
b.rot = quat(0, 0, 0, 1);
#endif
Core::setBasis(&b, 1);
mesh->renderSprite(-(getEntity().modelIndex + 1), frame);
}
virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) {
if (getEntity().modelIndex < 0) {
renderSprite(frustum, mesh, type, caustics, 0);
return;
}
ASSERT(getEntity().modelIndex > 0);
const TR::Model *model = getModel();
mat4 matrix = getMatrix();
Box box = animation.getBoundingBox(vec3(0, 0, 0), 0);
if (!explodeMask && frustum && !frustum->isVisible(matrix, box.min, box.max))
return;
const TR::Model *model = getModel();
ASSERT(model);
flags.rendered = true;

View File

@@ -230,7 +230,7 @@ namespace Core {
#endif
} support;
#define SETTINGS_VERSION 2
#define SETTINGS_VERSION 3
#define SETTINGS_READING 0xFF
struct Settings {
@@ -249,6 +249,7 @@ namespace Core {
};
uint8 quality[4];
};
uint8 simple;
uint8 vsync;
uint8 stereo;
void setFilter(Quality value) {
@@ -674,6 +675,7 @@ namespace Core {
settings.detail.setLighting (Core::Settings::HIGH);
settings.detail.setShadows (Core::Settings::HIGH);
settings.detail.setWater (Core::Settings::HIGH);
settings.detail.simple = false;
settings.detail.vsync = true;
settings.detail.stereo = Settings::STEREO_OFF;
settings.audio.music = 14;

View File

@@ -151,10 +151,10 @@
E( KEY_ITEM_2 ) \
E( KEY_ITEM_3 ) \
E( KEY_ITEM_4 ) \
E( INV_KEY_1 ) \
E( INV_KEY_2 ) \
E( INV_KEY_3 ) \
E( INV_KEY_4 ) \
E( INV_KEY_ITEM_1 ) \
E( INV_KEY_ITEM_2 ) \
E( INV_KEY_ITEM_3 ) \
E( INV_KEY_ITEM_4 ) \
E( KEY_HOLE_1 ) \
E( KEY_HOLE_2 ) \
E( KEY_HOLE_3 ) \
@@ -407,10 +407,10 @@
E( _KEY_ITEM_2 ) \
E( _KEY_ITEM_3 ) \
E( _KEY_ITEM_4 ) \
E( _INV_KEY_1 ) \
E( _INV_KEY_2 ) \
E( _INV_KEY_3 ) \
E( _INV_KEY_4 ) \
E( _INV_KEY_ITEM_1 ) \
E( _INV_KEY_ITEM_2 ) \
E( _INV_KEY_ITEM_3 ) \
E( _INV_KEY_ITEM_4 ) \
E( _KEY_HOLE_1 ) \
E( _KEY_HOLE_2 ) \
E( _KEY_HOLE_3 ) \
@@ -704,10 +704,10 @@
E( __KEY_ITEM_2 ) \
E( __KEY_ITEM_3 ) \
E( __KEY_ITEM_4 ) \
E( __INV_KEY_1 ) \
E( __INV_KEY_2 ) \
E( __INV_KEY_3 ) \
E( __INV_KEY_4 ) \
E( __INV_KEY_ITEM_1 ) \
E( __INV_KEY_ITEM_2 ) \
E( __INV_KEY_ITEM_3 ) \
E( __INV_KEY_ITEM_4 ) \
E( __KEY_HOLE_1 ) \
E( __KEY_HOLE_2 ) \
E( __KEY_HOLE_3 ) \
@@ -1617,10 +1617,10 @@ namespace TR {
REMAP_2( KEY_ITEM_2 );
REMAP_2( KEY_ITEM_3 );
REMAP_2( KEY_ITEM_4 );
REMAP_2( INV_KEY_1 );
REMAP_2( INV_KEY_2 );
REMAP_2( INV_KEY_3 );
REMAP_2( INV_KEY_4 );
REMAP_2( INV_KEY_ITEM_1 );
REMAP_2( INV_KEY_ITEM_2 );
REMAP_2( INV_KEY_ITEM_3 );
REMAP_2( INV_KEY_ITEM_4 );
REMAP_2( KEY_HOLE_1 );
REMAP_2( KEY_HOLE_2 );
REMAP_2( KEY_HOLE_3 );
@@ -1756,10 +1756,10 @@ namespace TR {
REMAP_3( KEY_ITEM_2 );
REMAP_3( KEY_ITEM_3 );
REMAP_3( KEY_ITEM_4 );
REMAP_3( INV_KEY_1 );
REMAP_3( INV_KEY_2 );
REMAP_3( INV_KEY_3 );
REMAP_3( INV_KEY_4 );
REMAP_3( INV_KEY_ITEM_1 );
REMAP_3( INV_KEY_ITEM_2 );
REMAP_3( INV_KEY_ITEM_3 );
REMAP_3( INV_KEY_ITEM_4 );
REMAP_3( KEY_HOLE_1 );
REMAP_3( KEY_HOLE_2 );
REMAP_3( KEY_HOLE_3 );
@@ -1866,10 +1866,10 @@ namespace TR {
|| type == INV_PUZZLE_2
|| type == INV_PUZZLE_3
|| type == INV_PUZZLE_4
|| type == INV_KEY_1
|| type == INV_KEY_2
|| type == INV_KEY_3
|| type == INV_KEY_4
|| type == INV_KEY_ITEM_1
|| type == INV_KEY_ITEM_2
|| type == INV_KEY_ITEM_3
|| type == INV_KEY_ITEM_4
|| type == INV_LEADBAR
|| type == INV_SCION;
}
@@ -1938,10 +1938,10 @@ namespace TR {
case PUZZLE_3 : return INV_PUZZLE_3;
case PUZZLE_4 : return INV_PUZZLE_4;
case KEY_ITEM_1 : return INV_KEY_1;
case KEY_ITEM_2 : return INV_KEY_2;
case KEY_ITEM_3 : return INV_KEY_3;
case KEY_ITEM_4 : return INV_KEY_4;
case KEY_ITEM_1 : return INV_KEY_ITEM_1;
case KEY_ITEM_2 : return INV_KEY_ITEM_2;
case KEY_ITEM_3 : return INV_KEY_ITEM_3;
case KEY_ITEM_4 : return INV_KEY_ITEM_4;
case LEADBAR : return INV_LEADBAR;
case SCION_PICKUP_QUALOPEC :
@@ -1971,10 +1971,10 @@ namespace TR {
case INV_PUZZLE_3 : return PUZZLE_3;
case INV_PUZZLE_4 : return PUZZLE_4;
case INV_KEY_1 : return KEY_ITEM_1;
case INV_KEY_2 : return KEY_ITEM_2;
case INV_KEY_3 : return KEY_ITEM_3;
case INV_KEY_4 : return KEY_ITEM_4;
case INV_KEY_ITEM_1 : return KEY_ITEM_1;
case INV_KEY_ITEM_2 : return KEY_ITEM_2;
case INV_KEY_ITEM_3 : return KEY_ITEM_3;
case INV_KEY_ITEM_4 : return KEY_ITEM_4;
case INV_LEADBAR : return LEADBAR;
case INV_SCION : return SCION_PICKUP_DROP;
@@ -3740,7 +3740,7 @@ namespace TR {
e.type = Entity::remap(version, e.type);
e.controller = NULL;
e.modelIndex = getModelIndex(e.type);
e.modelIndex = 0;
// turn off interpolation for some entities
e.flags.smooth = !((id == LVL_TR2_CUT_1 && (e.type == Entity::CUT_6 || e.type == Entity::CUT_8 || e.type == Entity::CUT_9))
@@ -3894,10 +3894,10 @@ namespace TR {
case Entity::INV_PUZZLE_3 : extra.inv.puzzle[2] = i; break;
case Entity::INV_PUZZLE_4 : extra.inv.puzzle[3] = i; break;
case Entity::INV_KEY_1 : extra.inv.key[0] = i; break;
case Entity::INV_KEY_2 : extra.inv.key[1] = i; break;
case Entity::INV_KEY_3 : extra.inv.key[2] = i; break;
case Entity::INV_KEY_4 : extra.inv.key[3] = i; break;
case Entity::INV_KEY_ITEM_1 : extra.inv.key[0] = i; break;
case Entity::INV_KEY_ITEM_2 : extra.inv.key[1] = i; break;
case Entity::INV_KEY_ITEM_3 : extra.inv.key[2] = i; break;
case Entity::INV_KEY_ITEM_4 : extra.inv.key[3] = i; break;
case Entity::INV_LEADBAR : extra.inv.leadbar = i; break;
case Entity::INV_SCION : extra.inv.scion = i; break;
@@ -3948,6 +3948,67 @@ namespace TR {
}
}
void initModelIndices(bool simpleItems) {
#define OVERRIDE(a) { TR::Entity::##a, TR::Entity::INV_##a }
struct {
TR::Entity::Type src, dst;
} overrides[] = {
// weapon
OVERRIDE(PISTOLS),
OVERRIDE(SHOTGUN),
OVERRIDE(MAGNUMS),
OVERRIDE(UZIS),
OVERRIDE(AUTOPISTOLS),
OVERRIDE(HARPOON),
OVERRIDE(M16),
OVERRIDE(GRENADE),
// ammo
OVERRIDE(AMMO_PISTOLS),
OVERRIDE(AMMO_SHOTGUN),
OVERRIDE(AMMO_MAGNUMS),
OVERRIDE(AMMO_UZIS),
OVERRIDE(AMMO_AUTOPISTOLS),
OVERRIDE(AMMO_HARPOON),
OVERRIDE(AMMO_M16),
OVERRIDE(AMMO_GRENADE),
// items
OVERRIDE(MEDIKIT_BIG),
OVERRIDE(MEDIKIT_SMALL),
OVERRIDE(FLARES),
// key items
OVERRIDE(KEY_ITEM_1),
OVERRIDE(KEY_ITEM_2),
OVERRIDE(KEY_ITEM_3),
OVERRIDE(KEY_ITEM_4),
// puzzle items
OVERRIDE(PUZZLE_1),
OVERRIDE(PUZZLE_2),
OVERRIDE(PUZZLE_3),
OVERRIDE(PUZZLE_4),
// other items
OVERRIDE(LEADBAR),
OVERRIDE(QUEST_ITEM_1),
OVERRIDE(QUEST_ITEM_2),
{ TR::Entity::SCION_PICKUP_QUALOPEC, TR::Entity::INV_SCION },
{ TR::Entity::SCION_PICKUP_DROP, TR::Entity::INV_SCION },
};
for (int i = 0; i < entitiesCount; i++) {
TR::Entity &e = entities[i];
e.modelIndex = getModelIndex(e.type);
if (!simpleItems) {
for (int j = 0; j < COUNT(overrides); j++)
if (e.type == overrides[j].src) {
e.modelIndex = getModelIndex(overrides[j].dst);
break;
}
}
}
#undef OVERRIDE
}
LevelID getTitleId() const {
return TR::getTitleId(version);
}

View File

@@ -126,6 +126,7 @@ static const OptionItem optDetail[] = {
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_DETAIL_LIGHTING, SETTINGS( detail.lighting ), STR_QUALITY_LOW, 0, 2 ),
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_DETAIL_SHADOWS, SETTINGS( detail.shadows ), STR_QUALITY_LOW, 0, 2 ),
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_DETAIL_WATER, SETTINGS( detail.water ), STR_QUALITY_LOW, 0, 2 ),
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_SIMPLE_ITEMS, SETTINGS( detail.simple ), STR_OFF, 0, 1 ),
#if defined(_OS_WIN) || defined(_OS_LINUX) || defined(_OS_PSP) || defined(_OS_RPI)
OptionItem( OptionItem::TYPE_PARAM, STR_OPT_DETAIL_VSYNC, SETTINGS( detail.vsync ), STR_OFF, 0, 1 ),
#endif
@@ -177,7 +178,6 @@ static const OptionItem optControls[] = {
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)];
@@ -272,10 +272,10 @@ struct Inventory {
case TR::Entity::INV_PUZZLE_3 : desc = Desc( STR_PUZZLE, PAGE_ITEMS, level->extra.inv.puzzle[2] ); break;
case TR::Entity::INV_PUZZLE_4 : desc = Desc( STR_PUZZLE, PAGE_ITEMS, level->extra.inv.puzzle[3] ); break;
case TR::Entity::INV_KEY_1 : desc = Desc( STR_KEY, PAGE_ITEMS, level->extra.inv.key[0] ); break;
case TR::Entity::INV_KEY_2 : desc = Desc( STR_KEY, PAGE_ITEMS, level->extra.inv.key[1] ); break;
case TR::Entity::INV_KEY_3 : desc = Desc( STR_KEY, PAGE_ITEMS, level->extra.inv.key[2] ); break;
case TR::Entity::INV_KEY_4 : desc = Desc( STR_KEY, PAGE_ITEMS, level->extra.inv.key[3] ); break;
case TR::Entity::INV_KEY_ITEM_1 : desc = Desc( STR_KEY, PAGE_ITEMS, level->extra.inv.key[0] ); break;
case TR::Entity::INV_KEY_ITEM_2 : desc = Desc( STR_KEY, PAGE_ITEMS, level->extra.inv.key[1] ); break;
case TR::Entity::INV_KEY_ITEM_3 : desc = Desc( STR_KEY, PAGE_ITEMS, level->extra.inv.key[2] ); break;
case TR::Entity::INV_KEY_ITEM_4 : desc = Desc( STR_KEY, PAGE_ITEMS, level->extra.inv.key[3] ); break;
case TR::Entity::INV_LEADBAR : desc = Desc( STR_LEAD_BAR, PAGE_ITEMS, level->extra.inv.leadbar ); break;
case TR::Entity::INV_SCION : desc = Desc( STR_SCION, PAGE_ITEMS, level->extra.inv.scion ); break;
@@ -641,15 +641,15 @@ struct Inventory {
}
if (level->id == TR::LVL_TR2_HOUSE) {
add(TR::Entity::INV_KEY_1);
add(TR::Entity::INV_KEY_ITEM_1);
add(TR::Entity::INV_PUZZLE_1);
}
#ifdef _DEBUG
addWeapons();
add(TR::Entity::INV_KEY_1, 3);
add(TR::Entity::INV_KEY_2, 3);
add(TR::Entity::INV_KEY_3, 3);
add(TR::Entity::INV_KEY_4, 3);
add(TR::Entity::INV_KEY_ITEM_1, 3);
add(TR::Entity::INV_KEY_ITEM_2, 3);
add(TR::Entity::INV_KEY_ITEM_3, 3);
add(TR::Entity::INV_KEY_ITEM_4, 3);
add(TR::Entity::INV_PUZZLE_1, 3);
add(TR::Entity::INV_PUZZLE_2, 3);

View File

@@ -1686,14 +1686,14 @@ struct Lara : Character {
game->playSound(TR::SND_HEALTH, pos, Sound::PAN);
//TODO: remove medikit item
break;
case TR::Entity::INV_PUZZLE_1 :
case TR::Entity::INV_PUZZLE_2 :
case TR::Entity::INV_PUZZLE_3 :
case TR::Entity::INV_PUZZLE_4 :
case TR::Entity::INV_KEY_1 :
case TR::Entity::INV_KEY_2 :
case TR::Entity::INV_KEY_3 :
case TR::Entity::INV_KEY_4 :
case TR::Entity::INV_PUZZLE_1 :
case TR::Entity::INV_PUZZLE_2 :
case TR::Entity::INV_PUZZLE_3 :
case TR::Entity::INV_PUZZLE_4 :
case TR::Entity::INV_KEY_ITEM_1 :
case TR::Entity::INV_KEY_ITEM_2 :
case TR::Entity::INV_KEY_ITEM_3 :
case TR::Entity::INV_KEY_ITEM_4 :
if (usedKey == item)
return false;
usedKey = item;

View File

@@ -348,10 +348,12 @@ struct Level : IGame {
if (settings.detail.filter != Core::settings.detail.filter)
atlas->setFilterQuality(settings.detail.filter);
bool rebuildMesh = settings.detail.water != Core::settings.detail.water;
bool rebuildMesh = settings.detail.water != Core::settings.detail.water;
bool rebuildAmbient = settings.detail.lighting != Core::settings.detail.lighting;
bool rebuildShadows = settings.detail.shadows != Core::settings.detail.shadows;
bool rebuildWater = settings.detail.water != Core::settings.detail.water;
bool rebuildWater = settings.detail.water != Core::settings.detail.water;
bool switchModels = settings.detail.simple != Core::settings.detail.simple;
bool rebuildShaders = rebuildWater || rebuildAmbient || rebuildShadows;
bool redraw = memcmp(&settings.detail, &Core::settings.detail, sizeof(settings.detail)) != 0;
@@ -392,6 +394,9 @@ struct Level : IGame {
if (redraw && inventory->active && !level.isTitle())
needRedrawTitleBG = true;
if (switchModels)
resetModels();
}
virtual TR::Level* getLevel() {
@@ -795,6 +800,8 @@ struct Level : IGame {
//==============================
Level(Stream &stream) : level(stream), waitTrack(false), isEnded(false), cutsceneWaitTimer(0.0f), animTexTimer(0.0f), statsTimeDelta(0.0f) {
level.initModelIndices(Core::settings.detail.simple == 1);
#ifdef _OS_PSP
GAPI::freeEDRAM();
#endif
@@ -819,7 +826,6 @@ struct Level : IGame {
initTextures();
mesh = new MeshBuilder(&level, atlas);
initOverrides();
initEntities();
shadow = NULL;
@@ -909,6 +915,16 @@ struct Level : IGame {
Sound::listenersCount = 1;
}
void resetModels() {
level.initModelIndices(Core::settings.detail.simple == 1);
for (int i = 0; i < level.entitiesCount; i++) {
TR::Entity &e = level.entities[i];
if (!e.controller) continue;
Controller *controller = (Controller*)e.controller;
controller->updateModel();
}
}
void addPlayer(int index) {
if (level.isCutsceneLevel()) return;
@@ -997,10 +1013,10 @@ struct Level : IGame {
case TR::Entity::GEARS_1 :
case TR::Entity::GEARS_2 :
case TR::Entity::GEARS_3 : return new Gear(this, index);
case TR::Entity::INV_KEY_1 :
case TR::Entity::INV_KEY_2 :
case TR::Entity::INV_KEY_3 :
case TR::Entity::INV_KEY_4 : return new KeyItemInv(this, index);
case TR::Entity::INV_KEY_ITEM_1 :
case TR::Entity::INV_KEY_ITEM_2 :
case TR::Entity::INV_KEY_ITEM_3 :
case TR::Entity::INV_KEY_ITEM_4 : return new KeyItemInv(this, index);
case TR::Entity::TRAP_FLOOR : return new TrapFloor(this, index);
case TR::Entity::CRYSTAL : return new Crystal(this, index);
case TR::Entity::TRAP_SWING_BLADE : return new TrapSwingBlade(this, index);
@@ -1109,7 +1125,7 @@ struct Level : IGame {
case TR::Entity::WINDOW_1 :
case TR::Entity::WINDOW_2 : return new BreakableWindow(this, index);
default : return (level.entities[index].modelIndex > 0) ? new Controller(this, index) : new Sprite(this, index, 0);
default : return new Controller(this, index);
}
}
@@ -1425,43 +1441,6 @@ struct Level : IGame {
#endif
}
void initOverrides() {
/*
for (int i = 0; i < level.entitiesCount; i++) {
int16 &id = level.entities[i].id;
switch (id) {
// weapon
case 84 : id = 99; break; // pistols
case 85 : id = 100; break; // shotgun
case 86 : id = 101; break; // magnums
case 87 : id = 102; break; // uzis
// ammo
case 88 : id = 103; break; // for pistols
case 89 : id = 104; break; // for shotgun
case 90 : id = 105; break; // for magnums
case 91 : id = 106; break; // for uzis
// medikit
case 93 : id = 108; break; // big
case 94 : id = 109; break; // small
// keys
case 110 : id = 114; break;
case 111 : id = 115; break;
case 112 : id = 116; break;
case 113 : id = 117; break;
case 126 : id = 127; break;
case 129 : id = 133; break;
case 130 : id = 134; break;
case 131 : id = 135; break;
case 132 : id = 136; break;
case 141 : id = 145; break;
case 142 : id = 146; break;
case 143 : id = 150; break;
case 144 : id = 150; break;
}
}
*/
}
void initReflections() {
for (int i = 0; i < level.entitiesBaseCount; i++) {
TR::Entity &e = level.entities[i];

View File

@@ -53,16 +53,7 @@ struct Sprite : Controller {
}
virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) {
Basis b;
b.w = 1.0f;
b.pos = pos;
#ifdef MERGE_SPRITES
b.rot = Core::mViewInv.getRot();
#else
b.rot = quat(0, 0, 0, 1);
#endif
Core::setBasis(&b, 1);
mesh->renderSprite(-(getEntity().modelIndex + 1), frame);
renderSprite(frustum, mesh, type, caustics, frame);
}
};

View File

@@ -68,6 +68,7 @@ enum StringID {
, STR_OPT_DETAIL_WATER
, STR_OPT_DETAIL_VSYNC
, STR_OPT_DETAIL_STEREO
, STR_OPT_SIMPLE_ITEMS
// sound options
, STR_SET_VOLUMES
, STR_REVERBERATION
@@ -196,6 +197,7 @@ const char *STR[STR_MAX] = {
, "Water"
, "VSync"
, "Stereo"
, "Simple Items"
// sound options
, "Set Volumes"
, "Reverberation"