mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 20:58:07 +03:00
tr2/option_passport: add new game options
This adds NG+, Japanese, and Japanese NG+ options (as well as regular NG) to the new game page in the passport. Resolves #2731.
This commit is contained in:
parent
2aa0f2e161
commit
36ab43f0b3
16 changed files with 162 additions and 22 deletions
|
@ -600,9 +600,14 @@
|
|||
"PASSPORT_EXIT_GAME": "Exit Game",
|
||||
"PASSPORT_EXIT_TO_TITLE": "Exit to Title",
|
||||
"PASSPORT_LOAD_GAME": "Load Game",
|
||||
"PASSPORT_MODE_NEW_GAME": "New Game",
|
||||
"PASSPORT_MODE_NEW_GAME_JP": "Japanese NG",
|
||||
"PASSPORT_MODE_NEW_GAME_JP_PLUS": "Japanese NG+",
|
||||
"PASSPORT_MODE_NEW_GAME_PLUS": "New Game+",
|
||||
"PASSPORT_NEW_GAME": "New Game",
|
||||
"PASSPORT_SAVE_GAME": "Save Game",
|
||||
"PASSPORT_SELECT_LEVEL": "Select Level",
|
||||
"PASSPORT_SELECT_MODE": "Select Mode",
|
||||
"PAUSE_ARE_YOU_SURE": "Are you sure?",
|
||||
"PAUSE_CONTINUE": "Continue",
|
||||
"PAUSE_EXIT_TO_TITLE": "Exit to title?",
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
- added the bonus level game flow type, which allows for levels to be unlocked if all main game secrets are found (#2668)
|
||||
- added the ability for custom levels to have up to two of each secret type per level (#2674)
|
||||
- added BSON savegame support, removing the limits imposed by the OG 8KB file size, so allowing for storing more data and offering improved feature support (legacy save files can still be read, similar to TR1) (#2662)
|
||||
- added NG+, Japanese, and Japanese NG+ game mode options to the New Game page in the passport (#2731)
|
||||
- changed savegame files to be stored in the `saves` directory (#2087)
|
||||
- changed the default fog distance to 22 tiles cutting off at 30 tiles to match TR1X (#1622)
|
||||
- fixed the inability to completely mute the sounds, even at sound volume 0 (#2722)
|
||||
|
|
|
@ -179,6 +179,7 @@ as Notepad.
|
|||
- added a pause screen
|
||||
- added a photo mode feature
|
||||
- added combined support for The Golden Mask
|
||||
- added NG+, Japanese, and Japanese NG+ game mode options to the New Game page in the passport
|
||||
- changed inventory to pause the music rather than muting it
|
||||
- fixed killing the T-Rex with a grenade launcher crashing the game
|
||||
- fixed secret rewards not displaying shotgun ammo
|
||||
|
|
|
@ -55,3 +55,5 @@ CFG_INT32(g_Config, audio.sound_volume, 10)
|
|||
CFG_INT32(g_Config, audio.music_volume, 10)
|
||||
CFG_BOOL(g_Config, audio.enable_lara_mic, false)
|
||||
CFG_ENUM(g_Config, audio.underwater_music_mode, UMM_FULL, UNDERWATER_MUSIC_MODE)
|
||||
CFG_BOOL(g_Config, gameplay.enable_game_modes, true)
|
||||
CFG_BOOL(g_Config, profile.new_game_plus_unlock, false)
|
||||
|
|
|
@ -298,12 +298,6 @@ const SAVEGAME_INFO *Savegame_GetSavegameInfo(const int32_t slot_num)
|
|||
|
||||
void Savegame_InitCurrentInfo(void)
|
||||
{
|
||||
// TODO: remove both NG+ checks in this function once the TR1 NG options are
|
||||
// ported to TR2.
|
||||
if (TR_VERSION == 2 && Game_IsBonusFlagSet(GBF_NGPLUS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const GF_LEVEL_TABLE *const level_table = GF_GetLevelTable(GFLT_MAIN);
|
||||
for (int32_t i = 0; i < level_table->count; i++) {
|
||||
const GF_LEVEL *const level = &level_table->levels[i];
|
||||
|
@ -318,10 +312,6 @@ void Savegame_InitCurrentInfo(void)
|
|||
if (GF_GetFirstLevel() != nullptr) {
|
||||
Savegame_GetCurrentInfo(GF_GetFirstLevel())->flags.available = 1;
|
||||
}
|
||||
|
||||
#if TR_VERSION == 2
|
||||
Game_SetBonusFlag(GBF_NONE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Savegame_ResetCurrentInfo(const GF_LEVEL *const level)
|
||||
|
|
|
@ -83,6 +83,7 @@ typedef struct {
|
|||
bool enable_fmv;
|
||||
bool enable_auto_item_selection;
|
||||
int32_t turbo_speed;
|
||||
bool enable_game_modes;
|
||||
} gameplay;
|
||||
|
||||
struct {
|
||||
|
@ -112,4 +113,8 @@ typedef struct {
|
|||
int32_t scaler;
|
||||
float sizer;
|
||||
} rendering;
|
||||
|
||||
struct {
|
||||
bool new_game_plus_unlock;
|
||||
} profile;
|
||||
} CONFIG;
|
||||
|
|
|
@ -124,6 +124,11 @@ GS_DEFINE(PASSPORT_SAVE_GAME, "Save Game")
|
|||
GS_DEFINE(PASSPORT_NEW_GAME, "New Game")
|
||||
GS_DEFINE(PASSPORT_EXIT_GAME, "Exit Game")
|
||||
GS_DEFINE(PASSPORT_EXIT_TO_TITLE, "Exit to Title")
|
||||
GS_DEFINE(PASSPORT_SELECT_MODE, "Select Mode")
|
||||
GS_DEFINE(PASSPORT_MODE_NEW_GAME, "New Game")
|
||||
GS_DEFINE(PASSPORT_MODE_NEW_GAME_PLUS, "New Game+")
|
||||
GS_DEFINE(PASSPORT_MODE_NEW_GAME_JP, "Japanese NG")
|
||||
GS_DEFINE(PASSPORT_MODE_NEW_GAME_JP_PLUS, "Japanese NG+")
|
||||
GS_DEFINE(SOUND_SET_VOLUMES, "Set Volumes")
|
||||
GS_DEFINE(OSD_TRAPEZOID_FILTER_ON, "Trapezoid filter enabled")
|
||||
GS_DEFINE(OSD_TRAPEZOID_FILTER_OFF, "Trapezoid filter disabled")
|
||||
|
|
|
@ -34,6 +34,6 @@
|
|||
#define GRENADE_AMMO_QTY (GRENADE_AMMO_CLIP * 2) // = 2
|
||||
#define GRENADE_SPEED 200
|
||||
|
||||
// TODO: Japanese version uses 8
|
||||
#define FLARE_AMMO_QTY 6
|
||||
#define FLARE_AMMO_JAPANESE_QTY 8
|
||||
#endif
|
||||
|
|
|
@ -2,11 +2,6 @@ GS_DEFINE(PASSPORT_RESTART_LEVEL, "Restart Level")
|
|||
GS_DEFINE(PASSPORT_STORY_SO_FAR, "Story so far...")
|
||||
GS_DEFINE(PASSPORT_LEGACY_SELECT_LEVEL_1, "Legacy saves do not")
|
||||
GS_DEFINE(PASSPORT_LEGACY_SELECT_LEVEL_2, "support this feature.")
|
||||
GS_DEFINE(PASSPORT_SELECT_MODE, "Select Mode")
|
||||
GS_DEFINE(PASSPORT_MODE_NEW_GAME, "New Game")
|
||||
GS_DEFINE(PASSPORT_MODE_NEW_GAME_PLUS, "New Game+")
|
||||
GS_DEFINE(PASSPORT_MODE_NEW_GAME_JP, "Japanese NG")
|
||||
GS_DEFINE(PASSPORT_MODE_NEW_GAME_JP_PLUS, "Japanese NG+")
|
||||
GS_DEFINE(DETAIL_FPS, "FPS")
|
||||
GS_DEFINE(DETAIL_WATER_COLOR_R, "Water color (R)")
|
||||
GS_DEFINE(DETAIL_WATER_COLOR_G, "Water color (G)")
|
||||
|
|
|
@ -167,7 +167,8 @@ static DECLARE_GF_EVENT_HANDLER(M_HandleLevelComplete)
|
|||
const GF_LEVEL *const next_level = GF_GetLevelAfter(current_level);
|
||||
|
||||
if (current_level == GF_GetLastLevel()) {
|
||||
Game_SetBonusFlag(GBF_NGPLUS);
|
||||
g_Config.profile.new_game_plus_unlock = true;
|
||||
Config_Write();
|
||||
}
|
||||
|
||||
RESUME_INFO *const resume = Savegame_GetCurrentInfo(current_level);
|
||||
|
@ -270,9 +271,10 @@ void GF_PreSequenceHook(
|
|||
g_GF_LaraStartAnim = 0;
|
||||
g_GF_RemoveAmmo = false;
|
||||
g_GF_RemoveWeapons = false;
|
||||
// TODO: reset bonus flag if seq_ctx == GFSC_SAVED once S_LoadGame logic is
|
||||
// merged with overall save loading logic.
|
||||
Camera_GetCineData()->position.target_angle = DEG_90;
|
||||
if (seq_ctx == GFSC_SAVED) {
|
||||
Game_SetBonusFlag(GBF_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
GF_SEQUENCE_CONTEXT GF_SwitchSequenceContext(
|
||||
|
|
|
@ -293,7 +293,9 @@ int32_t Gun_FireWeapon(
|
|||
if (item_to_smash != NO_ITEM) {
|
||||
Gun_SmashItem(item_to_smash, weapon_type);
|
||||
}
|
||||
Gun_HitTarget(target, &hit_pos, winfo->damage);
|
||||
Gun_HitTarget(
|
||||
target, &hit_pos,
|
||||
winfo->damage * (Game_IsBonusFlagSet(GBF_JAPANESE) ? 2 : 1));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,18 @@
|
|||
#include "game/stats.h"
|
||||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/game/game.h>
|
||||
#include <libtrx/game/gun/const.h>
|
||||
#include <libtrx/utils.h>
|
||||
|
||||
static int32_t M_GetFlareQuantity(void);
|
||||
|
||||
static int32_t M_GetFlareQuantity(void)
|
||||
{
|
||||
return Game_IsBonusFlagSet(GBF_JAPANESE) ? FLARE_AMMO_JAPANESE_QTY
|
||||
: FLARE_AMMO_QTY;
|
||||
}
|
||||
|
||||
bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
|
||||
{
|
||||
const GAME_OBJECT_ID inv_obj_id = Inv_GetItemOption(obj_id);
|
||||
|
@ -23,7 +32,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
|
|||
for (int32_t i = 0; i < source->count; i++) {
|
||||
if (source->items[i]->object_id == inv_obj_id) {
|
||||
const int32_t qty =
|
||||
obj_id == O_FLARES_ITEM ? FLARE_AMMO_QTY : 1;
|
||||
obj_id == O_FLARES_ITEM ? M_GetFlareQuantity() : 1;
|
||||
source->qtys[i] += qty;
|
||||
CLAMPG(source->qtys[i], MAX_QTY);
|
||||
return true;
|
||||
|
@ -184,7 +193,7 @@ bool Inv_AddItem(const GAME_OBJECT_ID obj_id)
|
|||
|
||||
case O_FLARES_ITEM:
|
||||
case O_FLARES_OPTION:
|
||||
for (int32_t i = 0; i < FLARE_AMMO_QTY; i++) {
|
||||
for (int32_t i = 0; i < M_GetFlareQuantity(); i++) {
|
||||
Inv_AddItem(O_FLARE_ITEM);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/debug.h>
|
||||
#include <libtrx/game/ui/common.h>
|
||||
#include <libtrx/game/ui/widgets/requester.h>
|
||||
|
||||
typedef enum {
|
||||
M_ROLE_LOAD_GAME,
|
||||
|
@ -22,17 +24,27 @@ typedef enum {
|
|||
M_ROLE_EXIT,
|
||||
} M_PAGE_ROLE;
|
||||
|
||||
typedef enum {
|
||||
M_MODE_BROWSE,
|
||||
M_MODE_PICK_OPTION,
|
||||
} M_PAGE_MODE;
|
||||
|
||||
typedef struct {
|
||||
bool available;
|
||||
M_PAGE_ROLE role;
|
||||
} M_PAGE;
|
||||
|
||||
static struct {
|
||||
M_PAGE_MODE mode;
|
||||
int32_t current_page;
|
||||
int32_t active_page;
|
||||
int32_t selection;
|
||||
M_PAGE pages[3];
|
||||
bool page_ready;
|
||||
struct {
|
||||
bool is_ready;
|
||||
UI_WIDGET *ui;
|
||||
} requester;
|
||||
} m_State = { .active_page = -1 };
|
||||
|
||||
TEXTSTRING *m_SubtitleText = nullptr;
|
||||
|
@ -45,6 +57,8 @@ static void M_FlipRight(INVENTORY_ITEM *inv_item);
|
|||
static void M_Close(INVENTORY_ITEM *inv_item);
|
||||
static void M_ShowPage(const INVENTORY_ITEM *inv_item);
|
||||
static void M_HandleFlipInputs(void);
|
||||
static int32_t M_DisplayNewGameRequester(void);
|
||||
static void M_CloseRequester(void);
|
||||
|
||||
static void M_SetPage(
|
||||
const int32_t page, const M_PAGE_ROLE role, const bool available)
|
||||
|
@ -240,6 +254,39 @@ static void M_ShowPage(const INVENTORY_ITEM *const inv_item)
|
|||
Text_CentreH(m_SubtitleText, true);
|
||||
}
|
||||
m_State.selection = GF_GetFirstLevel()->num;
|
||||
if (m_State.mode == M_MODE_BROWSE) {
|
||||
if (g_InputDB.menu_confirm
|
||||
&& (g_Config.gameplay.enable_game_modes
|
||||
|| g_Config.profile.new_game_plus_unlock)) {
|
||||
g_Input = (INPUT_STATE) {};
|
||||
g_InputDB = (INPUT_STATE) {};
|
||||
m_State.mode = M_MODE_PICK_OPTION;
|
||||
}
|
||||
} else if (m_State.mode == M_MODE_PICK_OPTION) {
|
||||
const int32_t mode = M_DisplayNewGameRequester();
|
||||
if (mode > 0) {
|
||||
switch (mode) {
|
||||
case 0:
|
||||
Game_SetBonusFlag(GBF_NONE);
|
||||
break;
|
||||
case 1:
|
||||
Game_SetBonusFlag(GBF_NGPLUS);
|
||||
break;
|
||||
case 2:
|
||||
Game_SetBonusFlag(GBF_JAPANESE);
|
||||
break;
|
||||
case 3:
|
||||
Game_SetBonusFlag(GBF_JAPANESE | GBF_NGPLUS);
|
||||
break;
|
||||
default:
|
||||
Game_SetBonusFlag(GBF_NONE);
|
||||
break;
|
||||
}
|
||||
} else if (mode < 0) {
|
||||
g_Input = (INPUT_STATE) {};
|
||||
g_InputDB = (INPUT_STATE) {};
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case M_ROLE_EXIT:
|
||||
|
@ -278,12 +325,71 @@ static void M_HandleFlipInputs(void)
|
|||
}
|
||||
}
|
||||
|
||||
static int32_t M_DisplayNewGameRequester(void)
|
||||
{
|
||||
if (g_InputDB.menu_back) {
|
||||
M_CloseRequester();
|
||||
g_Input = (INPUT_STATE) {};
|
||||
g_InputDB = (INPUT_STATE) {};
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!m_State.requester.is_ready) {
|
||||
if (m_State.requester.ui == nullptr) {
|
||||
m_State.requester.ui = UI_Requester_Create((UI_REQUESTER_SETTINGS) {
|
||||
.is_selectable = true,
|
||||
.width = 160,
|
||||
.visible_rows = 4,
|
||||
});
|
||||
}
|
||||
UI_Requester_ClearRows(m_State.requester.ui);
|
||||
UI_Requester_SetTitle(m_State.requester.ui, GS(PASSPORT_SELECT_MODE));
|
||||
UI_Requester_AddRowC(
|
||||
m_State.requester.ui, GS(PASSPORT_MODE_NEW_GAME), nullptr);
|
||||
UI_Requester_AddRowC(
|
||||
m_State.requester.ui, GS(PASSPORT_MODE_NEW_GAME_PLUS), nullptr);
|
||||
UI_Requester_AddRowC(
|
||||
m_State.requester.ui, GS(PASSPORT_MODE_NEW_GAME_JP), nullptr);
|
||||
UI_Requester_AddRowC(
|
||||
m_State.requester.ui, GS(PASSPORT_MODE_NEW_GAME_JP_PLUS), nullptr);
|
||||
m_State.requester.ui->set_position(
|
||||
m_State.requester.ui,
|
||||
(UI_GetCanvasWidth()
|
||||
- m_State.requester.ui->get_width(m_State.requester.ui))
|
||||
/ 2,
|
||||
(UI_GetCanvasHeight()
|
||||
- m_State.requester.ui->get_height(m_State.requester.ui))
|
||||
/ 2);
|
||||
m_State.requester.is_ready = true;
|
||||
}
|
||||
|
||||
const int32_t choice = UI_Requester_GetSelectedRow(m_State.requester.ui);
|
||||
if (choice != -1) {
|
||||
M_CloseRequester();
|
||||
}
|
||||
return choice;
|
||||
}
|
||||
|
||||
static void M_CloseRequester(void)
|
||||
{
|
||||
if (m_State.requester.ui != nullptr) {
|
||||
m_State.requester.ui->free(m_State.requester.ui);
|
||||
m_State.requester.ui = nullptr;
|
||||
m_State.requester.is_ready = false;
|
||||
m_State.mode = M_MODE_BROWSE;
|
||||
}
|
||||
}
|
||||
|
||||
void Option_Passport_Control(INVENTORY_ITEM *const item, const bool is_busy)
|
||||
{
|
||||
if (m_State.active_page == -1) {
|
||||
M_DeterminePages();
|
||||
}
|
||||
|
||||
if (m_State.requester.ui != nullptr) {
|
||||
m_State.requester.ui->control(m_State.requester.ui);
|
||||
}
|
||||
|
||||
if (is_busy) {
|
||||
if (g_Config.input.enable_responsive_passport) {
|
||||
M_HandleFlipInputs();
|
||||
|
@ -328,10 +434,14 @@ void Option_Passport_Control(INVENTORY_ITEM *const item, const bool is_busy)
|
|||
|
||||
void Option_Passport_Draw(INVENTORY_ITEM *const item)
|
||||
{
|
||||
if (m_State.requester.ui != nullptr) {
|
||||
m_State.requester.ui->draw(m_State.requester.ui);
|
||||
}
|
||||
}
|
||||
|
||||
void Option_Passport_Shutdown(void)
|
||||
{
|
||||
M_RemoveAllText();
|
||||
M_CloseRequester();
|
||||
m_State.active_page = -1;
|
||||
}
|
||||
|
|
|
@ -46,6 +46,10 @@
|
|||
"Title": "Enable FMVs",
|
||||
"Description": "Enables FMVs playing."
|
||||
},
|
||||
"enable_game_modes": {
|
||||
"Title": "Enable game modes",
|
||||
"Description": "Allows new game plus options to be selected from the new game passport menu.\n- New Game+: unlocks all weapons with infinite ammo; enemies have double the HP.\n- Japanese NG: weapons do double damage and flare pickups contain 8 rather than 6.\n- Japanese NG+: combination of New Game+ and Japanese NG."
|
||||
},
|
||||
"fix_m16_accuracy": {
|
||||
"Title": "Fix M16 accuracy",
|
||||
"Description": "Fixes the accuracy of the M16 while Lara is running."
|
||||
|
|
|
@ -53,6 +53,10 @@
|
|||
"Title": "Abilita FMV",
|
||||
"Description": "Abilita la riproduzione dei filmati."
|
||||
},
|
||||
"enable_game_modes": {
|
||||
"Title": "Abilita le modalità di gioco",
|
||||
"Description": "Consente di selezionare diverse modalità di gioco dal menu passaporto.\n- Nuova Partita+: sblocca tutte le armi con munizioni infinite; i nemici hanno punti vita doppi.\n- NP giapponese: le armi infliggono danni doppi, i razzi di segnalazione contengono 8 anziché 6.\n- NP giapponese+: combinazione di Nuova Partita+ e NP giapponese."
|
||||
},
|
||||
"fix_m16_accuracy": {
|
||||
"Title": "Correggi precisione M16",
|
||||
"Description": "Corregge la precisione della mira dell'M16 quando Lara corre."
|
||||
|
|
|
@ -128,6 +128,11 @@
|
|||
"Field": "enable_fmv",
|
||||
"DataType": "Bool",
|
||||
"DefaultValue": true
|
||||
},
|
||||
{
|
||||
"Field": "enable_game_modes",
|
||||
"DataType": "Bool",
|
||||
"DefaultValue": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue