mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-04-28 20:58:07 +03:00
tr2: add 60 fps
This commit is contained in:
parent
9b7577eef1
commit
8a0c695b02
60 changed files with 436 additions and 343 deletions
|
@ -388,6 +388,7 @@ Not all options are turned on by default. Refer to `TR1X_ConfigTool.exe` for det
|
|||
- added ability to use Lara's underwater swimming physics from TR2+
|
||||
- added ability to wade, similar to TR2+
|
||||
- added Lara's exit-water-to-medium-height animation from TR2+
|
||||
- added support for 60 FPS rendering
|
||||
- added a pause screen
|
||||
- added a choice whether to play NG or NG+ without having to play the entire game
|
||||
- added Japanese mode (guns deal twice the damage, inspired by JP release of TR3); available for both NG and NG+
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
## [Unreleased](https://github.com/LostArtefacts/TRX/compare/tr2-0.9.2...develop) - ××××-××-××
|
||||
- added support for 60 FPS rendering
|
||||
- added a `/cheats` console command
|
||||
- added a `/wireframe` console command (#2500)
|
||||
- added a `/fps` console command
|
||||
- fixed smashed windows blocking enemy pathing after loading a save (#2535)
|
||||
- fixed several instances of the camera going out of bounds (#1034)
|
||||
- fixed Lara getting stuck in a T-pose after jumping/falling and then dying before reaching fast fall speed (#2575)
|
||||
|
|
|
@ -81,6 +81,10 @@ Currently supported commands:
|
|||
- `/speed {num}`
|
||||
Retrieves or sets current game speed.
|
||||
|
||||
- `/fps`
|
||||
- `/fps {num}`
|
||||
Retrieves or sets current frames per second.
|
||||
|
||||
- `/set {option}`
|
||||
- `/set {option} {value}`
|
||||
Retrieves or assigns a new value to the given configuration option. Some options need a game re-launch to apply. The option names use `-` rather than `_`.
|
||||
|
|
|
@ -39,6 +39,7 @@ game with new enhancements and features.
|
|||
- step bug
|
||||
- free flare from underwater pickup
|
||||
- drifting into walls during underwater pickups
|
||||
- added support for 60 FPS rendering
|
||||
- added a pause screen
|
||||
- added a photo mode feature
|
||||
- changed inventory to pause the music rather than muting it
|
||||
|
|
|
@ -24,6 +24,7 @@ CFG_BOOL(g_Config, visuals.use_pcx_fov, true)
|
|||
CFG_DOUBLE(g_Config, ui.text_scale, 1.0)
|
||||
CFG_DOUBLE(g_Config, ui.bar_scale, 1.0)
|
||||
CFG_BOOL(g_Config, ui.enable_photo_mode_ui, true)
|
||||
CFG_INT32(g_Config, rendering.fps, 60)
|
||||
CFG_ENUM(g_Config, rendering.screenshot_format, SCREENSHOT_FORMAT_JPEG, SCREENSHOT_FORMAT)
|
||||
CFG_ENUM(g_Config, rendering.render_mode, RM_HARDWARE, RENDER_MODE)
|
||||
CFG_ENUM(g_Config, rendering.aspect_mode, AM_ANY, ASPECT_MODE)
|
||||
|
|
|
@ -133,6 +133,9 @@ void Config_Sanitize(void)
|
|||
}
|
||||
CLAMP(g_Config.rendering.nearest_adjustment, 0, 256);
|
||||
CLAMP(g_Config.rendering.linear_adjustment, 0, 256);
|
||||
if (g_Config.rendering.fps != 30 && g_Config.rendering.fps != 60) {
|
||||
g_Config.rendering.fps = 30;
|
||||
}
|
||||
|
||||
CLAMP(g_Config.visuals.fov, 30, 150);
|
||||
CLAMP(g_Config.ui.bar_scale, 0.5, 2.0);
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
#include "game/camera/common.h"
|
||||
|
||||
#include "game/camera/vars.h"
|
||||
#include "game/rooms/const.h"
|
||||
|
||||
static bool m_IsChunky = false;
|
||||
|
||||
bool Camera_IsChunky(void)
|
||||
|
@ -9,3 +14,8 @@ void Camera_SetChunky(const bool is_chunky)
|
|||
{
|
||||
m_IsChunky = is_chunky;
|
||||
}
|
||||
|
||||
void Camera_Reset(void)
|
||||
{
|
||||
g_Camera.pos.room_num = NO_ROOM;
|
||||
}
|
||||
|
|
|
@ -1,19 +1,49 @@
|
|||
#include "game/interpolation.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "game/camera/vars.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/lara/common.h"
|
||||
#include "game/lara/hair.h"
|
||||
#include "game/rooms.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define REMEMBER(target, member) (target)->interp.prev.member = (target)->member
|
||||
|
||||
#define COMMIT(target, member) (target)->interp.result.member = (target)->member
|
||||
|
||||
#define INTERPOLATE_F(target, member, ratio) \
|
||||
(target)->interp.result.member = ((target)->interp.prev.member) \
|
||||
+ (((target)->member - ((target)->interp.prev.member)) * (ratio));
|
||||
|
||||
#define INTERPOLATE(target, member, ratio, max_diff) \
|
||||
if (ABS(((target)->member) - ((target)->interp.prev.member)) \
|
||||
>= (max_diff)) { \
|
||||
COMMIT((target), member); \
|
||||
} else { \
|
||||
INTERPOLATE_F(target, member, ratio); \
|
||||
}
|
||||
|
||||
#define INTERPOLATE_ROT(target, member, ratio, max_diff) \
|
||||
if (!Math_AngleInCone( \
|
||||
(target)->member, (target)->interp.prev.member, (max_diff))) { \
|
||||
COMMIT((target), member); \
|
||||
} else { \
|
||||
INTERPOLATE_ROT_F(target, member, ratio); \
|
||||
}
|
||||
|
||||
#define INTERPOLATE_ROT_F(target, member, ratio) \
|
||||
(target)->interp.result.member = Math_AngleMean( \
|
||||
(target)->interp.prev.member, (target)->member, (ratio))
|
||||
|
||||
static bool m_IsEnabled = true;
|
||||
static double m_Rate = 0.0;
|
||||
|
||||
static int32_t M_GetFPS(void)
|
||||
{
|
||||
#if TR_VERSION == 1
|
||||
return g_Config.rendering.fps;
|
||||
#elif TR_VERSION == 2
|
||||
return 30;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Interpolation_IsEnabled(void)
|
||||
|
@ -43,3 +73,178 @@ void Interpolation_SetRate(double rate)
|
|||
{
|
||||
m_Rate = rate;
|
||||
}
|
||||
|
||||
void Interpolation_Commit(void)
|
||||
{
|
||||
const double ratio = Interpolation_GetRate();
|
||||
|
||||
if (g_Camera.pos.room_num != NO_ROOM) {
|
||||
INTERPOLATE(&g_Camera, shift, ratio, 128);
|
||||
INTERPOLATE(&g_Camera, pos.x, ratio, 512);
|
||||
INTERPOLATE(&g_Camera, pos.y, ratio, 512);
|
||||
INTERPOLATE(&g_Camera, pos.z, ratio, 512);
|
||||
INTERPOLATE(&g_Camera, target.x, ratio, 512);
|
||||
INTERPOLATE(&g_Camera, target.y, ratio, 512);
|
||||
INTERPOLATE(&g_Camera, target.z, ratio, 512);
|
||||
|
||||
g_Camera.interp.room_num = g_Camera.pos.room_num;
|
||||
Room_GetSector(
|
||||
g_Camera.interp.result.pos.x,
|
||||
g_Camera.interp.result.pos.y + g_Camera.interp.result.shift,
|
||||
g_Camera.interp.result.pos.z, &g_Camera.interp.room_num);
|
||||
}
|
||||
|
||||
LARA_INFO *const lara = Lara_GetLaraInfo();
|
||||
INTERPOLATE_ROT(&lara->left_arm, rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&lara->left_arm, rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&lara->left_arm, rot.z, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&lara->right_arm, rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&lara->right_arm, rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&lara->right_arm, rot.z, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(lara, torso_rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(lara, torso_rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(lara, torso_rot.z, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(lara, head_rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(lara, head_rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(lara, head_rot.z, ratio, DEG_45);
|
||||
|
||||
for (int i = 0; i < Item_GetTotalCount(); i++) {
|
||||
ITEM *const item = Item_Get(i);
|
||||
bool is_erratic = false;
|
||||
#if TR_VERSION == 1
|
||||
is_erratic |= item->object_id == O_BAT;
|
||||
#endif
|
||||
if ((item->flags & IF_KILLED) || item->status == IS_INACTIVE
|
||||
|| is_erratic) {
|
||||
COMMIT(item, pos.x);
|
||||
COMMIT(item, pos.y);
|
||||
COMMIT(item, pos.z);
|
||||
COMMIT(item, rot.x);
|
||||
COMMIT(item, rot.y);
|
||||
COMMIT(item, rot.z);
|
||||
continue;
|
||||
}
|
||||
|
||||
const int32_t max_xz = item->object_id == O_DART ? 200 : 128;
|
||||
const int32_t max_y = MAX(128, item->fall_speed * 2);
|
||||
INTERPOLATE(item, pos.x, ratio, max_xz);
|
||||
INTERPOLATE(item, pos.y, ratio, max_y);
|
||||
INTERPOLATE(item, pos.z, ratio, max_xz);
|
||||
INTERPOLATE_ROT(item, rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(item, rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(item, rot.z, ratio, DEG_45);
|
||||
}
|
||||
|
||||
ITEM *const lara_item = Lara_GetItem();
|
||||
if (lara_item != nullptr) {
|
||||
INTERPOLATE(lara_item, pos.x, ratio, 128);
|
||||
INTERPOLATE(
|
||||
lara_item, pos.y, ratio, MAX(128, lara_item->fall_speed * 2));
|
||||
INTERPOLATE(lara_item, pos.z, ratio, 128);
|
||||
INTERPOLATE_ROT(lara_item, rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(lara_item, rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(lara_item, rot.z, ratio, DEG_45);
|
||||
}
|
||||
|
||||
int16_t effect_num = Effect_GetActiveNum();
|
||||
while (effect_num != NO_EFFECT) {
|
||||
EFFECT *const effect = Effect_Get(effect_num);
|
||||
INTERPOLATE(effect, pos.x, ratio, 128);
|
||||
INTERPOLATE(effect, pos.y, ratio, MAX(128, effect->fall_speed * 2));
|
||||
INTERPOLATE(effect, pos.z, ratio, 128);
|
||||
INTERPOLATE_ROT(effect, rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(effect, rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(effect, rot.z, ratio, DEG_45);
|
||||
effect_num = effect->next_active;
|
||||
}
|
||||
|
||||
if (Lara_Hair_IsActive()) {
|
||||
for (int i = 0; i < Lara_Hair_GetSegmentCount(); i++) {
|
||||
HAIR_SEGMENT *const hair = Lara_Hair_GetSegment(i);
|
||||
INTERPOLATE(hair, pos.x, ratio, 128);
|
||||
INTERPOLATE(
|
||||
hair, pos.y, ratio, MAX(128, lara_item->fall_speed * 2));
|
||||
INTERPOLATE(hair, pos.z, ratio, 128);
|
||||
INTERPOLATE_ROT(hair, rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(hair, rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(hair, rot.z, ratio, DEG_45);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Interpolation_Remember(void)
|
||||
{
|
||||
if (g_Camera.pos.room_num != NO_ROOM) {
|
||||
REMEMBER(&g_Camera, shift);
|
||||
REMEMBER(&g_Camera, pos.x);
|
||||
REMEMBER(&g_Camera, pos.y);
|
||||
REMEMBER(&g_Camera, pos.z);
|
||||
REMEMBER(&g_Camera, target.x);
|
||||
REMEMBER(&g_Camera, target.y);
|
||||
REMEMBER(&g_Camera, target.z);
|
||||
}
|
||||
|
||||
LARA_INFO *const lara = Lara_GetLaraInfo();
|
||||
REMEMBER(&lara->left_arm, rot.x);
|
||||
REMEMBER(&lara->left_arm, rot.y);
|
||||
REMEMBER(&lara->left_arm, rot.z);
|
||||
REMEMBER(&lara->right_arm, rot.x);
|
||||
REMEMBER(&lara->right_arm, rot.y);
|
||||
REMEMBER(&lara->right_arm, rot.z);
|
||||
REMEMBER(lara, torso_rot.x);
|
||||
REMEMBER(lara, torso_rot.y);
|
||||
REMEMBER(lara, torso_rot.z);
|
||||
REMEMBER(lara, head_rot.x);
|
||||
REMEMBER(lara, head_rot.y);
|
||||
REMEMBER(lara, head_rot.z);
|
||||
|
||||
for (int i = 0; i < Item_GetTotalCount(); i++) {
|
||||
ITEM *const item = Item_Get(i);
|
||||
REMEMBER(item, pos.x);
|
||||
REMEMBER(item, pos.y);
|
||||
REMEMBER(item, pos.z);
|
||||
REMEMBER(item, rot.x);
|
||||
REMEMBER(item, rot.y);
|
||||
REMEMBER(item, rot.z);
|
||||
}
|
||||
|
||||
ITEM *const lara_item = Lara_GetItem();
|
||||
if (lara_item != nullptr) {
|
||||
REMEMBER(lara_item, pos.x);
|
||||
REMEMBER(lara_item, pos.y);
|
||||
REMEMBER(lara_item, pos.z);
|
||||
REMEMBER(lara_item, rot.x);
|
||||
REMEMBER(lara_item, rot.y);
|
||||
REMEMBER(lara_item, rot.z);
|
||||
}
|
||||
|
||||
int16_t effect_num = Effect_GetActiveNum();
|
||||
while (effect_num != NO_EFFECT) {
|
||||
EFFECT *const effect = Effect_Get(effect_num);
|
||||
REMEMBER(effect, pos.x);
|
||||
REMEMBER(effect, pos.y);
|
||||
REMEMBER(effect, pos.z);
|
||||
REMEMBER(effect, rot.x);
|
||||
REMEMBER(effect, rot.y);
|
||||
REMEMBER(effect, rot.z);
|
||||
effect_num = effect->next_active;
|
||||
}
|
||||
|
||||
if (Lara_Hair_IsActive()) {
|
||||
for (int i = 0; i < Lara_Hair_GetSegmentCount(); i++) {
|
||||
HAIR_SEGMENT *const hair = Lara_Hair_GetSegment(i);
|
||||
REMEMBER(hair, pos.x);
|
||||
REMEMBER(hair, pos.y);
|
||||
REMEMBER(hair, pos.z);
|
||||
REMEMBER(hair, rot.x);
|
||||
REMEMBER(hair, rot.y);
|
||||
REMEMBER(hair, rot.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Interpolation_RememberItem(ITEM *item)
|
||||
{
|
||||
item->interp.prev.pos = item->pos;
|
||||
item->interp.prev.rot = item->rot;
|
||||
}
|
||||
|
|
|
@ -92,6 +92,7 @@ typedef struct {
|
|||
} window;
|
||||
|
||||
struct {
|
||||
int32_t fps;
|
||||
RENDER_MODE render_mode;
|
||||
ASPECT_MODE aspect_mode;
|
||||
bool enable_zbuffer;
|
||||
|
|
|
@ -4,3 +4,4 @@ extern void Camera_Update(void);
|
|||
extern void Camera_Apply(void);
|
||||
bool Camera_IsChunky(void);
|
||||
void Camera_SetChunky(bool is_chunky);
|
||||
void Camera_Reset(void);
|
||||
|
|
|
@ -34,6 +34,9 @@ typedef struct {
|
|||
// used for the manual camera control
|
||||
int16_t additional_angle;
|
||||
int16_t additional_elevation;
|
||||
#else
|
||||
XYZ_32 mic_pos;
|
||||
#endif
|
||||
|
||||
struct {
|
||||
struct {
|
||||
|
@ -43,9 +46,6 @@ typedef struct {
|
|||
} result, prev;
|
||||
int16_t room_num;
|
||||
} interp;
|
||||
#else
|
||||
XYZ_32 mic_pos;
|
||||
#endif
|
||||
} CAMERA_INFO;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "effects/common.h"
|
||||
#include "effects/const.h"
|
||||
#include "effects/types.h"
|
||||
|
|
14
src/libtrx/include/libtrx/game/effects/common.h
Normal file
14
src/libtrx/include/libtrx/game/effects/common.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "./types.h"
|
||||
|
||||
extern void Effect_InitialiseArray(void);
|
||||
extern void Effect_Control(void);
|
||||
|
||||
extern EFFECT *Effect_Get(int16_t effect_num);
|
||||
extern int16_t Effect_GetNum(const EFFECT *effect);
|
||||
extern int16_t Effect_GetActiveNum(void);
|
||||
extern int16_t Effect_Create(int16_t room_num);
|
||||
extern void Effect_Kill(int16_t effect_num);
|
||||
extern void Effect_NewRoom(int16_t effect_num, int16_t room_num);
|
||||
extern void Effect_Draw(int16_t effect_num);
|
|
@ -24,12 +24,10 @@ typedef struct {
|
|||
int16_t counter;
|
||||
int16_t shade;
|
||||
|
||||
#if TR_VERSION == 1
|
||||
struct {
|
||||
struct {
|
||||
XYZ_32 pos;
|
||||
XYZ_16 rot;
|
||||
} result, prev;
|
||||
} interp;
|
||||
#endif
|
||||
} EFFECT;
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "items/types.h"
|
||||
|
||||
bool Interpolation_IsEnabled(void);
|
||||
void Interpolation_Disable(void);
|
||||
void Interpolation_Enable(void);
|
||||
|
||||
double Interpolation_GetRate(void);
|
||||
void Interpolation_SetRate(double rate);
|
||||
|
||||
void Interpolation_Commit(void);
|
||||
void Interpolation_Remember(void);
|
||||
void Interpolation_RememberItem(ITEM *item);
|
||||
|
|
|
@ -69,12 +69,10 @@ typedef struct {
|
|||
uint16_t pad : 7; // 0x0200…0x8000
|
||||
#endif
|
||||
|
||||
#if TR_VERSION == 1
|
||||
struct {
|
||||
struct {
|
||||
XYZ_32 pos;
|
||||
XYZ_16 rot;
|
||||
} result, prev;
|
||||
} interp;
|
||||
#endif
|
||||
} ITEM;
|
||||
|
|
21
src/libtrx/include/libtrx/game/lara/hair.h
Normal file
21
src/libtrx/include/libtrx/game/lara/hair.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include "../math.h"
|
||||
|
||||
typedef struct {
|
||||
XYZ_32 pos;
|
||||
XYZ_16 rot;
|
||||
struct {
|
||||
struct {
|
||||
XYZ_32 pos;
|
||||
XYZ_16 rot;
|
||||
} result, prev;
|
||||
} interp;
|
||||
} HAIR_SEGMENT;
|
||||
|
||||
extern void Lara_Hair_Initialise(void);
|
||||
extern bool Lara_Hair_IsActive(void);
|
||||
extern void Lara_Hair_Draw(void);
|
||||
|
||||
extern int32_t Lara_Hair_GetSegmentCount(void);
|
||||
extern HAIR_SEGMENT *Lara_Hair_GetSegment(int32_t n);
|
|
@ -89,6 +89,12 @@ typedef struct {
|
|||
int16_t lock;
|
||||
XYZ_16 rot;
|
||||
int16_t flash_gun;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
XYZ_16 rot;
|
||||
} result, prev;
|
||||
} interp;
|
||||
} LARA_ARM;
|
||||
|
||||
typedef struct {
|
||||
|
@ -142,6 +148,13 @@ typedef struct {
|
|||
AMMO_INFO grenade_ammo;
|
||||
AMMO_INFO m16_ammo;
|
||||
CREATURE *creature;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
XYZ_16 head_rot;
|
||||
XYZ_16 torso_rot;
|
||||
} result, prev;
|
||||
} interp;
|
||||
} LARA_INFO;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -32,6 +32,8 @@ int16_t Room_GetIndexFromPos(int32_t x, int32_t y, int32_t z);
|
|||
int32_t Room_FindByPos(int32_t x, int32_t y, int32_t z);
|
||||
BOUNDS_32 Room_GetWorldBounds(void);
|
||||
|
||||
extern SECTOR *Room_GetSector(
|
||||
int32_t x, int32_t y, int32_t z, int16_t *room_num);
|
||||
SECTOR *Room_GetWorldSector(const ROOM *room, int32_t x_pos, int32_t z_pos);
|
||||
SECTOR *Room_GetUnitSector(
|
||||
const ROOM *room, int32_t x_sector, int32_t z_sector);
|
||||
|
|
|
@ -613,11 +613,6 @@ void Camera_Initialise(void)
|
|||
Camera_Update();
|
||||
}
|
||||
|
||||
void Camera_Reset(void)
|
||||
{
|
||||
g_Camera.pos.room_num = NO_ROOM;
|
||||
}
|
||||
|
||||
void Camera_ResetPosition(void)
|
||||
{
|
||||
ASSERT(g_LaraItem != nullptr);
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <stdint.h>
|
||||
|
||||
void Camera_Initialise(void);
|
||||
void Camera_Reset(void);
|
||||
void Camera_ResetPosition(void);
|
||||
void Camera_UpdateCutscene(void);
|
||||
void Camera_RefreshFromTrigger(const TRIGGER *trigger);
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "game/game.h"
|
||||
#include "game/game_flow.h"
|
||||
#include "game/input.h"
|
||||
#include "game/interpolation.h"
|
||||
#include "game/items.h"
|
||||
#include "game/lara/common.h"
|
||||
#include "game/lara/hair.h"
|
||||
|
@ -19,6 +18,7 @@
|
|||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/debug.h>
|
||||
#include <libtrx/game/interpolation.h>
|
||||
#include <libtrx/memory.h>
|
||||
|
||||
static void M_InitialiseLara(const GF_LEVEL *level);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include "game/game_flow.h"
|
||||
#include "game/game_string.h"
|
||||
#include "game/input.h"
|
||||
#include "game/interpolation.h"
|
||||
#include "game/item_actions.h"
|
||||
#include "game/lara/cheat.h"
|
||||
#include "game/lara/common.h"
|
||||
|
@ -24,6 +23,7 @@
|
|||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/debug.h>
|
||||
#include <libtrx/game/interpolation.h>
|
||||
#include <libtrx/log.h>
|
||||
|
||||
#define MODIFY_CONFIG() \
|
||||
|
|
|
@ -1,13 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
#include <libtrx/game/effects.h>
|
||||
|
||||
void Effect_InitialiseArray(void);
|
||||
EFFECT *Effect_Get(int16_t effect_num);
|
||||
int16_t Effect_GetNum(const EFFECT *effect);
|
||||
int16_t Effect_GetActiveNum(void);
|
||||
void Effect_Control(void);
|
||||
int16_t Effect_Create(int16_t room_num);
|
||||
void Effect_Kill(int16_t effect_num);
|
||||
void Effect_NewRoom(int16_t effect_num, int16_t room_num);
|
||||
void Effect_Draw(int16_t effect_num);
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "game/effects.h"
|
||||
#include "game/game_flow.h"
|
||||
#include "game/input.h"
|
||||
#include "game/interpolation.h"
|
||||
#include "game/inventory.h"
|
||||
#include "game/item_actions.h"
|
||||
#include "game/lara/cheat.h"
|
||||
|
@ -23,6 +22,7 @@
|
|||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/debug.h>
|
||||
#include <libtrx/game/interpolation.h>
|
||||
#include <libtrx/game/ui/common.h>
|
||||
|
||||
#define FRAME_BUFFER(key) \
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "game/game.h"
|
||||
|
||||
#include "game/camera.h"
|
||||
#include "game/interpolation.h"
|
||||
#include "game/lara/draw.h"
|
||||
#include "game/lara/hair.h"
|
||||
#include "game/output.h"
|
||||
|
@ -12,6 +11,7 @@
|
|||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/game/interpolation.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
|
|
@ -1,210 +0,0 @@
|
|||
#include "game/interpolation.h"
|
||||
|
||||
#include "game/camera.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/items.h"
|
||||
#include "game/lara/hair.h"
|
||||
#include "game/room.h"
|
||||
#include "global/const.h"
|
||||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/game/math.h>
|
||||
#include <libtrx/utils.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define REMEMBER(target, member) (target)->interp.prev.member = (target)->member
|
||||
|
||||
#define COMMIT(target, member) (target)->interp.result.member = (target)->member
|
||||
|
||||
#define INTERPOLATE_F(target, member, ratio) \
|
||||
(target)->interp.result.member = ((target)->interp.prev.member) \
|
||||
+ (((target)->member - ((target)->interp.prev.member)) * (ratio));
|
||||
|
||||
#define INTERPOLATE(target, member, ratio, max_diff) \
|
||||
if (ABS(((target)->member) - ((target)->interp.prev.member)) \
|
||||
>= (max_diff)) { \
|
||||
COMMIT((target), member); \
|
||||
} else { \
|
||||
INTERPOLATE_F(target, member, ratio); \
|
||||
}
|
||||
|
||||
#define INTERPOLATE_ROT(target, member, ratio, max_diff) \
|
||||
if (!Math_AngleInCone( \
|
||||
(target)->member, (target)->interp.prev.member, (max_diff))) { \
|
||||
COMMIT((target), member); \
|
||||
} else { \
|
||||
INTERPOLATE_ROT_F(target, member, ratio); \
|
||||
}
|
||||
|
||||
#define INTERPOLATE_ROT_F(target, member, ratio) \
|
||||
(target)->interp.result.member = Math_AngleMean( \
|
||||
(target)->interp.prev.member, (target)->member, (ratio))
|
||||
|
||||
void Interpolation_Commit(void)
|
||||
{
|
||||
const double ratio = Interpolation_GetRate();
|
||||
|
||||
if (g_Camera.pos.room_num != NO_ROOM) {
|
||||
INTERPOLATE(&g_Camera, shift, ratio, 128);
|
||||
INTERPOLATE(&g_Camera, pos.x, ratio, 512);
|
||||
INTERPOLATE(&g_Camera, pos.y, ratio, 512);
|
||||
INTERPOLATE(&g_Camera, pos.z, ratio, 512);
|
||||
INTERPOLATE(&g_Camera, target.x, ratio, 512);
|
||||
INTERPOLATE(&g_Camera, target.y, ratio, 512);
|
||||
INTERPOLATE(&g_Camera, target.z, ratio, 512);
|
||||
|
||||
g_Camera.interp.room_num = g_Camera.pos.room_num;
|
||||
Room_GetSector(
|
||||
g_Camera.interp.result.pos.x,
|
||||
g_Camera.interp.result.pos.y + g_Camera.interp.result.shift,
|
||||
g_Camera.interp.result.pos.z, &g_Camera.interp.room_num);
|
||||
}
|
||||
|
||||
INTERPOLATE_ROT(&g_Lara.left_arm, rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&g_Lara.left_arm, rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&g_Lara.left_arm, rot.z, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&g_Lara.right_arm, rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&g_Lara.right_arm, rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&g_Lara.right_arm, rot.z, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&g_Lara, torso_rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&g_Lara, torso_rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&g_Lara, torso_rot.z, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&g_Lara, head_rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&g_Lara, head_rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(&g_Lara, head_rot.z, ratio, DEG_45);
|
||||
|
||||
for (int i = 0; i < Item_GetTotalCount(); i++) {
|
||||
ITEM *const item = Item_Get(i);
|
||||
if ((item->flags & IF_KILLED) || item->status == IS_INACTIVE
|
||||
|| item->object_id == O_BAT) {
|
||||
COMMIT(item, pos.x);
|
||||
COMMIT(item, pos.y);
|
||||
COMMIT(item, pos.z);
|
||||
COMMIT(item, rot.x);
|
||||
COMMIT(item, rot.y);
|
||||
COMMIT(item, rot.z);
|
||||
continue;
|
||||
}
|
||||
|
||||
const int32_t max_xz = item->object_id == O_DART ? 200 : 128;
|
||||
const int32_t max_y = MAX(128, item->fall_speed * 2);
|
||||
INTERPOLATE(item, pos.x, ratio, max_xz);
|
||||
INTERPOLATE(item, pos.y, ratio, max_y);
|
||||
INTERPOLATE(item, pos.z, ratio, max_xz);
|
||||
INTERPOLATE_ROT(item, rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(item, rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(item, rot.z, ratio, DEG_45);
|
||||
}
|
||||
|
||||
if (g_LaraItem) {
|
||||
INTERPOLATE(g_LaraItem, pos.x, ratio, 128);
|
||||
INTERPOLATE(
|
||||
g_LaraItem, pos.y, ratio, MAX(128, g_LaraItem->fall_speed * 2));
|
||||
INTERPOLATE(g_LaraItem, pos.z, ratio, 128);
|
||||
INTERPOLATE_ROT(g_LaraItem, rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(g_LaraItem, rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(g_LaraItem, rot.z, ratio, DEG_45);
|
||||
}
|
||||
|
||||
int16_t effect_num = Effect_GetActiveNum();
|
||||
while (effect_num != NO_EFFECT) {
|
||||
EFFECT *const effect = Effect_Get(effect_num);
|
||||
INTERPOLATE(effect, pos.x, ratio, 128);
|
||||
INTERPOLATE(effect, pos.y, ratio, MAX(128, effect->fall_speed * 2));
|
||||
INTERPOLATE(effect, pos.z, ratio, 128);
|
||||
INTERPOLATE_ROT(effect, rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(effect, rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(effect, rot.z, ratio, DEG_45);
|
||||
effect_num = effect->next_active;
|
||||
}
|
||||
|
||||
if (Lara_Hair_IsActive()) {
|
||||
for (int i = 0; i < Lara_Hair_GetSegmentCount(); i++) {
|
||||
HAIR_SEGMENT *const hair = Lara_Hair_GetSegment(i);
|
||||
INTERPOLATE(hair, pos.x, ratio, 128);
|
||||
INTERPOLATE(
|
||||
hair, pos.y, ratio, MAX(128, g_LaraItem->fall_speed * 2));
|
||||
INTERPOLATE(hair, pos.z, ratio, 128);
|
||||
INTERPOLATE_ROT(hair, rot.x, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(hair, rot.y, ratio, DEG_45);
|
||||
INTERPOLATE_ROT(hair, rot.z, ratio, DEG_45);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Interpolation_Remember(void)
|
||||
{
|
||||
if (g_Camera.pos.room_num != NO_ROOM) {
|
||||
REMEMBER(&g_Camera, shift);
|
||||
REMEMBER(&g_Camera, pos.x);
|
||||
REMEMBER(&g_Camera, pos.y);
|
||||
REMEMBER(&g_Camera, pos.z);
|
||||
REMEMBER(&g_Camera, target.x);
|
||||
REMEMBER(&g_Camera, target.y);
|
||||
REMEMBER(&g_Camera, target.z);
|
||||
}
|
||||
|
||||
REMEMBER(&g_Lara.left_arm, rot.x);
|
||||
REMEMBER(&g_Lara.left_arm, rot.y);
|
||||
REMEMBER(&g_Lara.left_arm, rot.z);
|
||||
REMEMBER(&g_Lara.right_arm, rot.x);
|
||||
REMEMBER(&g_Lara.right_arm, rot.y);
|
||||
REMEMBER(&g_Lara.right_arm, rot.z);
|
||||
REMEMBER(&g_Lara, torso_rot.x);
|
||||
REMEMBER(&g_Lara, torso_rot.y);
|
||||
REMEMBER(&g_Lara, torso_rot.z);
|
||||
REMEMBER(&g_Lara, head_rot.x);
|
||||
REMEMBER(&g_Lara, head_rot.y);
|
||||
REMEMBER(&g_Lara, head_rot.z);
|
||||
|
||||
for (int i = 0; i < Item_GetTotalCount(); i++) {
|
||||
ITEM *const item = Item_Get(i);
|
||||
REMEMBER(item, pos.x);
|
||||
REMEMBER(item, pos.y);
|
||||
REMEMBER(item, pos.z);
|
||||
REMEMBER(item, rot.x);
|
||||
REMEMBER(item, rot.y);
|
||||
REMEMBER(item, rot.z);
|
||||
}
|
||||
|
||||
if (g_LaraItem) {
|
||||
REMEMBER(g_LaraItem, pos.x);
|
||||
REMEMBER(g_LaraItem, pos.y);
|
||||
REMEMBER(g_LaraItem, pos.z);
|
||||
REMEMBER(g_LaraItem, rot.x);
|
||||
REMEMBER(g_LaraItem, rot.y);
|
||||
REMEMBER(g_LaraItem, rot.z);
|
||||
}
|
||||
|
||||
int16_t effect_num = Effect_GetActiveNum();
|
||||
while (effect_num != NO_EFFECT) {
|
||||
EFFECT *const effect = Effect_Get(effect_num);
|
||||
REMEMBER(effect, pos.x);
|
||||
REMEMBER(effect, pos.y);
|
||||
REMEMBER(effect, pos.z);
|
||||
REMEMBER(effect, rot.x);
|
||||
REMEMBER(effect, rot.y);
|
||||
REMEMBER(effect, rot.z);
|
||||
effect_num = effect->next_active;
|
||||
}
|
||||
|
||||
if (Lara_Hair_IsActive()) {
|
||||
for (int i = 0; i < Lara_Hair_GetSegmentCount(); i++) {
|
||||
HAIR_SEGMENT *const hair = Lara_Hair_GetSegment(i);
|
||||
REMEMBER(hair, pos.x);
|
||||
REMEMBER(hair, pos.y);
|
||||
REMEMBER(hair, pos.z);
|
||||
REMEMBER(hair, rot.x);
|
||||
REMEMBER(hair, rot.y);
|
||||
REMEMBER(hair, rot.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Interpolation_RememberItem(ITEM *item)
|
||||
{
|
||||
item->interp.prev.pos = item->pos;
|
||||
item->interp.prev.rot = item->rot;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "global/types.h"
|
||||
|
||||
#include <libtrx/game/interpolation.h>
|
||||
|
||||
void Interpolation_Commit(void);
|
||||
void Interpolation_Remember(void);
|
||||
void Interpolation_RememberItem(ITEM *item);
|
|
@ -6,7 +6,6 @@
|
|||
#include "game/game_flow.h"
|
||||
#include "game/game_string.h"
|
||||
#include "game/input.h"
|
||||
#include "game/interpolation.h"
|
||||
#include "game/inventory.h"
|
||||
#include "game/inventory_ring/vars.h"
|
||||
#include "game/lara/common.h"
|
||||
|
@ -24,6 +23,7 @@
|
|||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/game/interpolation.h>
|
||||
#include <libtrx/game/inventory_ring/priv.h>
|
||||
#include <libtrx/memory.h>
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "game/game.h"
|
||||
#include "game/input.h"
|
||||
#include "game/interpolation.h"
|
||||
#include "game/inventory_ring.h"
|
||||
#include "game/objects/common.h"
|
||||
#include "game/option.h"
|
||||
|
@ -15,6 +14,7 @@
|
|||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/game/interpolation.h>
|
||||
#include <libtrx/game/inventory_ring/priv.h>
|
||||
#include <libtrx/game/matrix.h>
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "game/carrier.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/interpolation.h"
|
||||
#include "game/random.h"
|
||||
#include "game/room.h"
|
||||
#include "game/shell.h"
|
||||
|
@ -12,6 +11,7 @@
|
|||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/game/interpolation.h>
|
||||
#include <libtrx/game/math.h>
|
||||
#include <libtrx/game/matrix.h>
|
||||
#include <libtrx/utils.h>
|
||||
|
|
|
@ -2,24 +2,7 @@
|
|||
|
||||
#include "global/types.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <libtrx/game/lara/hair.h>
|
||||
|
||||
typedef struct {
|
||||
XYZ_32 pos;
|
||||
XYZ_16 rot;
|
||||
struct {
|
||||
struct {
|
||||
XYZ_32 pos;
|
||||
XYZ_16 rot;
|
||||
} result, prev;
|
||||
} interp;
|
||||
} HAIR_SEGMENT;
|
||||
|
||||
bool Lara_Hair_IsActive(void);
|
||||
void Lara_Hair_Initialise(void);
|
||||
void Lara_Hair_SetLaraType(GAME_OBJECT_ID lara_type);
|
||||
void Lara_Hair_Control(void);
|
||||
void Lara_Hair_Draw(void);
|
||||
|
||||
int32_t Lara_Hair_GetSegmentCount(void);
|
||||
HAIR_SEGMENT *Lara_Hair_GetSegment(int32_t n);
|
||||
|
|
|
@ -175,8 +175,8 @@ static void M_Draw(const ITEM *const item)
|
|||
Item_GetFrames(item, frmptr, &rate);
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_TranslateAbs32(item->pos);
|
||||
Matrix_Rot16(item->rot);
|
||||
Matrix_TranslateAbs32(item->interp.result.pos);
|
||||
Matrix_Rot16(item->interp.result.rot);
|
||||
|
||||
int32_t clip = Output_GetObjectBounds(&frmptr[0]->bounds);
|
||||
if (!clip) {
|
||||
|
|
|
@ -12,7 +12,6 @@ int32_t Room_FindGridShift(int32_t src, int32_t dst);
|
|||
void Room_GetNewRoom(int32_t x, int32_t y, int32_t z, int16_t room_num);
|
||||
void Room_GetNearByRooms(
|
||||
int32_t x, int32_t y, int32_t z, int32_t r, int32_t h, int16_t room_num);
|
||||
SECTOR *Room_GetSector(int32_t x, int32_t y, int32_t z, int16_t *room_num);
|
||||
int16_t Room_GetWaterHeight(int32_t x, int32_t y, int32_t z, int16_t room_num);
|
||||
|
||||
void Room_TestTriggers(const ITEM *item);
|
||||
|
|
|
@ -124,7 +124,6 @@ sources = [
|
|||
'game/gun/gun_rifle.c',
|
||||
'game/inject.c',
|
||||
'game/input.c',
|
||||
'game/interpolation.c',
|
||||
'game/inventory.c',
|
||||
'game/inventory_ring/control.c',
|
||||
'game/inventory_ring/draw.c',
|
||||
|
|
|
@ -139,8 +139,8 @@ void Flare_DrawInAir(const ITEM *const item)
|
|||
ANIM_FRAME *frames[2];
|
||||
Item_GetFrames(item, frames, &rate);
|
||||
Matrix_Push();
|
||||
Matrix_TranslateAbs32(item->pos);
|
||||
Matrix_Rot16(item->rot);
|
||||
Matrix_TranslateAbs32(item->interp.result.pos);
|
||||
Matrix_Rot16(item->interp.result.rot);
|
||||
const int32_t clip = Output_GetObjectBounds(&frames[0]->bounds);
|
||||
if (clip != 0) {
|
||||
Output_CalculateObjectLighting(item, &frames[0]->bounds);
|
||||
|
|
|
@ -959,8 +959,8 @@ void Skidoo_Draw(const ITEM *const item)
|
|||
const int32_t frac = Item_GetFrames(item, frames, &rate);
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_TranslateAbs32(item->pos);
|
||||
Matrix_Rot16(item->rot);
|
||||
Matrix_TranslateAbs32(item->interp.result.pos);
|
||||
Matrix_Rot16(item->interp.result.rot);
|
||||
|
||||
const int32_t clip = Output_GetObjectBounds(&frames[0]->bounds);
|
||||
if (!clip) {
|
||||
|
|
|
@ -989,6 +989,9 @@ void Camera_Apply(void)
|
|||
{
|
||||
M_EnsureEnvironment();
|
||||
Matrix_LookAt(
|
||||
g_Camera.pos.x, g_Camera.pos.y + g_Camera.shift, g_Camera.pos.z,
|
||||
g_Camera.target.x, g_Camera.target.y, g_Camera.target.z, g_Camera.roll);
|
||||
g_Camera.interp.result.pos.x,
|
||||
g_Camera.interp.result.pos.y + g_Camera.interp.result.shift,
|
||||
g_Camera.interp.result.pos.z, g_Camera.interp.result.target.x,
|
||||
g_Camera.interp.result.target.y, g_Camera.interp.result.target.z,
|
||||
g_Camera.roll);
|
||||
}
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
|
||||
int32_t Clock_GetCurrentFPS(void)
|
||||
{
|
||||
return LOGIC_FPS;
|
||||
return g_Config.rendering.fps;
|
||||
}
|
||||
|
|
|
@ -503,10 +503,10 @@ int32_t Collide_GetSpheres(
|
|||
pos.y = 0;
|
||||
pos.z = 0;
|
||||
Matrix_Push();
|
||||
Matrix_TranslateAbs32(item->pos);
|
||||
Matrix_TranslateAbs32(item->interp.result.pos);
|
||||
}
|
||||
|
||||
Matrix_Rot16(item->rot);
|
||||
Matrix_Rot16(item->interp.result.rot);
|
||||
|
||||
const ANIM_FRAME *const frame = Item_GetBestFrame(item);
|
||||
Matrix_TranslateRel16(frame->offset);
|
||||
|
|
|
@ -11,6 +11,7 @@ typedef struct {
|
|||
static COMMAND_TO_OPTION_MAP m_CommandToOptionMap[] = {
|
||||
{ "cheats", &g_Config.gameplay.enable_cheats },
|
||||
{ "wireframe", &g_Config.rendering.enable_wireframe },
|
||||
{ "fps", &g_Config.rendering.fps },
|
||||
{ nullptr, nullptr },
|
||||
};
|
||||
|
||||
|
@ -31,4 +32,4 @@ static COMMAND_RESULT M_Entrypoint(const COMMAND_CONTEXT *const ctx)
|
|||
return CR_FAILURE;
|
||||
}
|
||||
|
||||
REGISTER_CONSOLE_COMMAND("cheats|wireframe", M_Entrypoint)
|
||||
REGISTER_CONSOLE_COMMAND("cheats|wireframe|fps", M_Entrypoint)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/debug.h>
|
||||
#include <libtrx/game/interpolation.h>
|
||||
#include <libtrx/utils.h>
|
||||
|
||||
static CAMERA_INFO m_LocalCamera = {};
|
||||
|
@ -58,6 +59,7 @@ void Cutscene_End(void)
|
|||
|
||||
GF_COMMAND Cutscene_Control(void)
|
||||
{
|
||||
Interpolation_Remember();
|
||||
M_FixAudioDrift();
|
||||
|
||||
Input_Update();
|
||||
|
@ -96,8 +98,9 @@ GF_COMMAND Cutscene_Control(void)
|
|||
void Cutscene_Draw(void)
|
||||
{
|
||||
g_CameraUnderwater = false;
|
||||
Interpolation_Commit();
|
||||
Camera_Apply();
|
||||
Room_DrawAllRooms(g_Camera.pos.room_num);
|
||||
Room_DrawAllRooms(g_Camera.interp.room_num);
|
||||
Output_DrawPolyList();
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/debug.h>
|
||||
#include <libtrx/game/interpolation.h>
|
||||
#include <libtrx/log.h>
|
||||
|
||||
typedef struct {
|
||||
|
@ -126,6 +127,7 @@ bool Demo_Start(const int32_t level_num)
|
|||
ASSERT(GF_GetCurrentLevel() == p->level);
|
||||
|
||||
M_PrepareConfig(p);
|
||||
Interpolation_Remember();
|
||||
|
||||
const uint32_t *const data = Demo_GetData();
|
||||
if (data == nullptr) {
|
||||
|
|
|
@ -161,8 +161,9 @@ void Effect_Draw(const int16_t effect_num)
|
|||
|
||||
if (effect->object_id == O_GLOW) {
|
||||
Output_DrawSprite(
|
||||
(effect->rot.y << 16) | (uint16_t)effect->rot.x, effect->pos.x,
|
||||
effect->pos.y, effect->pos.z, Object_Get(O_GLOW)->mesh_idx,
|
||||
(effect->rot.y << 16) | (uint16_t)effect->rot.x,
|
||||
effect->interp.result.pos.x, effect->interp.result.pos.y,
|
||||
effect->interp.result.pos.z, Object_Get(O_GLOW)->mesh_idx,
|
||||
effect->shade, effect->frame_num);
|
||||
return;
|
||||
}
|
||||
|
@ -171,15 +172,16 @@ void Effect_Draw(const int16_t effect_num)
|
|||
Output_DrawSprite(
|
||||
SPRITE_ABS | (obj->semi_transparent ? SPRITE_SEMI_TRANS : 0)
|
||||
| SPRITE_SHADE,
|
||||
effect->pos.x, effect->pos.y, effect->pos.z,
|
||||
obj->mesh_idx - effect->frame_num, effect->shade, 0);
|
||||
effect->interp.result.pos.x, effect->interp.result.pos.y,
|
||||
effect->interp.result.pos.z, obj->mesh_idx - effect->frame_num,
|
||||
effect->shade, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_TranslateAbs32(effect->pos);
|
||||
Matrix_TranslateAbs32(effect->interp.result.pos);
|
||||
if (g_MatrixPtr->_23 > g_PhdNearZ && g_MatrixPtr->_23 < g_PhdFarZ) {
|
||||
Matrix_Rot16(effect->rot);
|
||||
Matrix_Rot16(effect->interp.result.rot);
|
||||
if (obj->mesh_count) {
|
||||
Output_CalculateStaticLight(effect->shade);
|
||||
Object_DrawMesh(obj->mesh_idx, -1, false);
|
||||
|
|
|
@ -1,13 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
#include <libtrx/game/effects.h>
|
||||
|
||||
void Effect_InitialiseArray(void);
|
||||
void Effect_Control(void);
|
||||
EFFECT *Effect_Get(int16_t effect_num);
|
||||
int16_t Effect_GetNum(const EFFECT *effect);
|
||||
int16_t Effect_GetActiveNum(void);
|
||||
int16_t Effect_Create(int16_t room_num);
|
||||
void Effect_Kill(int16_t effect_num);
|
||||
void Effect_NewRoom(int16_t effect_num, int16_t room_num);
|
||||
void Effect_Draw(int16_t effect_num);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/game/interpolation.h>
|
||||
|
||||
bool Game_Start(const GF_LEVEL *const level, const GF_SEQUENCE_CONTEXT seq_ctx)
|
||||
{
|
||||
|
@ -29,6 +30,7 @@ bool Game_Start(const GF_LEVEL *const level, const GF_SEQUENCE_CONTEXT seq_ctx)
|
|||
|
||||
g_OverlayStatus = 1;
|
||||
Camera_Initialise();
|
||||
Interpolation_Remember();
|
||||
Stats_StartTimer();
|
||||
return true;
|
||||
}
|
||||
|
@ -52,6 +54,7 @@ void Game_Resume(void)
|
|||
|
||||
GF_COMMAND Game_Control(const bool demo_mode)
|
||||
{
|
||||
Interpolation_Remember();
|
||||
if (g_GameFlow.cheat_keys) {
|
||||
Lara_Cheat_CheckKeys();
|
||||
}
|
||||
|
@ -154,8 +157,9 @@ GF_COMMAND Game_Control(const bool demo_mode)
|
|||
|
||||
void Game_Draw(bool draw_overlay)
|
||||
{
|
||||
Interpolation_Commit();
|
||||
Camera_Apply();
|
||||
Room_DrawAllRooms(g_Camera.pos.room_num);
|
||||
Room_DrawAllRooms(g_Camera.interp.room_num);
|
||||
Output_DrawPolyList();
|
||||
if (draw_overlay) {
|
||||
Overlay_DrawGameInfo();
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/game/interpolation.h>
|
||||
#include <libtrx/game/inventory_ring/priv.h>
|
||||
#include <libtrx/game/matrix.h>
|
||||
#include <libtrx/game/objects/names.h>
|
||||
|
@ -745,6 +746,7 @@ static GF_COMMAND M_Control(INV_RING *const ring)
|
|||
}
|
||||
|
||||
Sound_EndScene();
|
||||
Interpolation_Remember();
|
||||
return (GF_COMMAND) { .action = GF_NOOP };
|
||||
}
|
||||
|
||||
|
@ -844,7 +846,7 @@ INV_RING *InvRing_Open(const INVENTORY_MODE mode)
|
|||
}
|
||||
|
||||
g_Inv_Mode = mode;
|
||||
|
||||
Interpolation_Remember();
|
||||
if (!Game_IsInGym()) {
|
||||
Stats_StartTimer();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "game/overlay.h"
|
||||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/game/interpolation.h>
|
||||
#include <libtrx/game/inventory_ring/priv.h>
|
||||
#include <libtrx/game/matrix.h>
|
||||
|
||||
|
@ -111,6 +112,10 @@ void InvRing_Draw(INV_RING *const ring)
|
|||
|
||||
ring->camera.pos.z = ring->radius + 598;
|
||||
|
||||
if (ring->mode == INV_TITLE_MODE) {
|
||||
Interpolation_Commit();
|
||||
}
|
||||
|
||||
XYZ_32 view_pos;
|
||||
XYZ_16 view_rot;
|
||||
InvRing_GetView(ring, &view_pos, &view_rot);
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
#include "global/const.h"
|
||||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/config.h>
|
||||
#include <libtrx/debug.h>
|
||||
#include <libtrx/game/interpolation.h>
|
||||
#include <libtrx/game/math.h>
|
||||
#include <libtrx/game/matrix.h>
|
||||
#include <libtrx/utils.h>
|
||||
|
@ -329,6 +331,7 @@ int32_t Item_GetFrames(const ITEM *item, ANIM_FRAME *frmptr[], int32_t *rate)
|
|||
{
|
||||
const ANIM *const anim = Item_GetAnim(item);
|
||||
const int32_t cur_frame_num = item->frame_num - anim->frame_base;
|
||||
const int32_t last_frame_num = anim->frame_end - anim->frame_base;
|
||||
const int32_t key_frame_span = anim->interpolation;
|
||||
const int32_t key_frame_shift = cur_frame_num % key_frame_span;
|
||||
const int32_t first_key_frame_num = cur_frame_num / key_frame_span;
|
||||
|
@ -347,8 +350,31 @@ int32_t Item_GetFrames(const ITEM *item, ANIM_FRAME *frmptr[], int32_t *rate)
|
|||
|
||||
frmptr[0] = &anim->frame_ptr[first_key_frame_num];
|
||||
frmptr[1] = &anim->frame_ptr[second_key_frame_num];
|
||||
*rate = denominator;
|
||||
return numerator;
|
||||
|
||||
// OG
|
||||
if (g_Config.rendering.fps == 30) {
|
||||
*rate = denominator;
|
||||
return numerator;
|
||||
}
|
||||
|
||||
// interpolated
|
||||
if (item != g_LaraItem && !item->active) {
|
||||
*rate = denominator;
|
||||
return numerator;
|
||||
}
|
||||
|
||||
const double clock_ratio = Interpolation_GetRate() - 0.5;
|
||||
const double final =
|
||||
(key_frame_shift + clock_ratio) / (double)key_frame_span;
|
||||
const double interp_frame_num =
|
||||
(first_key_frame_num * key_frame_span) + (final * key_frame_span);
|
||||
if (interp_frame_num >= last_frame_num) {
|
||||
*rate = denominator;
|
||||
return numerator;
|
||||
}
|
||||
|
||||
*rate = 10;
|
||||
return final * 10;
|
||||
}
|
||||
|
||||
BOUNDS_16 *Item_GetBoundsAccurate(const ITEM *const item)
|
||||
|
|
|
@ -66,8 +66,8 @@ void Lara_Draw(const ITEM *const item)
|
|||
saved_matrix = *g_MatrixPtr;
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_TranslateAbs32(item->pos);
|
||||
Matrix_Rot16(item->rot);
|
||||
Matrix_TranslateAbs32(item->interp.result.pos);
|
||||
Matrix_Rot16(item->interp.result.rot);
|
||||
const MATRIX item_matrix = *g_MatrixPtr;
|
||||
const int32_t clip = Output_GetObjectBounds(&frame->bounds);
|
||||
if (!clip) {
|
||||
|
@ -105,7 +105,7 @@ void Lara_Draw(const ITEM *const item)
|
|||
}
|
||||
|
||||
Matrix_Rot16(mesh_rots[LM_TORSO]);
|
||||
Matrix_Rot16(g_Lara.torso_rot);
|
||||
Matrix_Rot16(g_Lara.interp.result.torso_rot);
|
||||
Output_DrawObjectMesh(g_Lara.mesh_ptrs[LM_TORSO], clip);
|
||||
|
||||
Matrix_Push();
|
||||
|
@ -113,7 +113,7 @@ void Lara_Draw(const ITEM *const item)
|
|||
mesh_rots_c = mesh_rots;
|
||||
Matrix_Rot16(mesh_rots[LM_HEAD]);
|
||||
mesh_rots = mesh_rots_c;
|
||||
Matrix_Rot16(g_Lara.head_rot);
|
||||
Matrix_Rot16(g_Lara.interp.result.head_rot);
|
||||
Output_DrawObjectMesh(g_Lara.mesh_ptrs[LM_HEAD], clip);
|
||||
|
||||
*g_MatrixPtr = saved_matrix;
|
||||
|
@ -184,7 +184,7 @@ void Lara_Draw(const ITEM *const item)
|
|||
g_MatrixPtr->_20 = item_matrix._20;
|
||||
g_MatrixPtr->_21 = item_matrix._21;
|
||||
g_MatrixPtr->_22 = item_matrix._22;
|
||||
Matrix_Rot16(g_Lara.right_arm.rot);
|
||||
Matrix_Rot16(g_Lara.right_arm.interp.result.rot);
|
||||
const ANIM *anim = Anim_GetAnim(g_Lara.right_arm.anim_num);
|
||||
mesh_rots =
|
||||
g_Lara.right_arm
|
||||
|
@ -212,7 +212,7 @@ void Lara_Draw(const ITEM *const item)
|
|||
g_MatrixPtr->_20 = item_matrix._20;
|
||||
g_MatrixPtr->_21 = item_matrix._21;
|
||||
g_MatrixPtr->_22 = item_matrix._22;
|
||||
Matrix_Rot16(g_Lara.left_arm.rot);
|
||||
Matrix_Rot16(g_Lara.left_arm.interp.result.rot);
|
||||
anim = Anim_GetAnim(g_Lara.left_arm.anim_num);
|
||||
mesh_rots =
|
||||
g_Lara.left_arm
|
||||
|
@ -297,8 +297,8 @@ void Lara_Draw_I(
|
|||
MATRIX saved_matrix = *g_MatrixPtr;
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_TranslateAbs32(item->pos);
|
||||
Matrix_Rot16(item->rot);
|
||||
Matrix_TranslateAbs32(item->interp.result.pos);
|
||||
Matrix_Rot16(item->interp.result.rot);
|
||||
|
||||
const int32_t clip = Output_GetObjectBounds(&frame1->bounds);
|
||||
|
||||
|
@ -341,7 +341,7 @@ void Lara_Draw_I(
|
|||
}
|
||||
|
||||
Matrix_Rot16_ID(mesh_rots_1[LM_TORSO], mesh_rots_2[LM_TORSO]);
|
||||
Matrix_Rot16_I(g_Lara.torso_rot);
|
||||
Matrix_Rot16_I(g_Lara.interp.result.torso_rot);
|
||||
Output_DrawObjectMesh_I(g_Lara.mesh_ptrs[LM_TORSO], clip);
|
||||
|
||||
Matrix_Push_I();
|
||||
|
@ -351,7 +351,7 @@ void Lara_Draw_I(
|
|||
Matrix_Rot16_ID(mesh_rots_1[LM_HEAD], mesh_rots_2[LM_HEAD]);
|
||||
mesh_rots_1 = mesh_rots_1_c;
|
||||
mesh_rots_2 = mesh_rots_2_c;
|
||||
Matrix_Rot16_I(g_Lara.head_rot);
|
||||
Matrix_Rot16_I(g_Lara.interp.result.head_rot);
|
||||
Output_DrawObjectMesh_I(g_Lara.mesh_ptrs[LM_HEAD], clip);
|
||||
|
||||
*g_MatrixPtr = saved_matrix;
|
||||
|
@ -418,7 +418,7 @@ void Lara_Draw_I(
|
|||
Matrix_Push_I();
|
||||
Matrix_TranslateRel32_I(bone[7].pos);
|
||||
Matrix_InterpolateArm();
|
||||
Matrix_Rot16(g_Lara.right_arm.rot);
|
||||
Matrix_Rot16(g_Lara.right_arm.interp.result.rot);
|
||||
const ANIM *anim = Anim_GetAnim(g_Lara.right_arm.anim_num);
|
||||
mesh_rots_1 =
|
||||
g_Lara.right_arm
|
||||
|
@ -438,7 +438,7 @@ void Lara_Draw_I(
|
|||
Matrix_Push_I();
|
||||
Matrix_TranslateRel32_I(bone[10].pos);
|
||||
Matrix_InterpolateArm();
|
||||
Matrix_Rot16(g_Lara.left_arm.rot);
|
||||
Matrix_Rot16(g_Lara.left_arm.interp.result.rot);
|
||||
anim = Anim_GetAnim(g_Lara.left_arm.anim_num);
|
||||
mesh_rots_1 =
|
||||
g_Lara.left_arm
|
||||
|
|
|
@ -8,17 +8,13 @@
|
|||
#include "global/vars.h"
|
||||
|
||||
#include <libtrx/game/lara/common.h>
|
||||
#include <libtrx/game/lara/hair.h>
|
||||
#include <libtrx/game/math.h>
|
||||
#include <libtrx/game/matrix.h>
|
||||
#include <libtrx/utils.h>
|
||||
|
||||
#define HAIR_SEGMENTS 6
|
||||
|
||||
typedef struct {
|
||||
XYZ_32 pos;
|
||||
XYZ_16 rot;
|
||||
} HAIR_SEGMENT;
|
||||
|
||||
static bool m_IsFirstHair;
|
||||
static SPHERE m_HairSpheres[HAIR_SEGMENTS - 1];
|
||||
static XYZ_32 m_HairVelocity[HAIR_SEGMENTS + 1];
|
||||
|
@ -53,7 +49,7 @@ static void M_CalculateSpheres(const ANIM_FRAME *const frame)
|
|||
}
|
||||
|
||||
Matrix_Rot16(mesh_rots[LM_TORSO]);
|
||||
Matrix_Rot16(g_Lara.torso_rot);
|
||||
Matrix_Rot16(g_Lara.interp.result.torso_rot);
|
||||
Matrix_Push();
|
||||
mesh = g_Lara.mesh_ptrs[LM_TORSO];
|
||||
Matrix_TranslateRel16(mesh->center);
|
||||
|
@ -88,7 +84,7 @@ static void M_CalculateSpheres(const ANIM_FRAME *const frame)
|
|||
|
||||
Matrix_TranslateRel32(bone[LM_HEAD - 1].pos);
|
||||
Matrix_Rot16(mesh_rots[LM_HEAD]);
|
||||
Matrix_Rot16(g_Lara.head_rot);
|
||||
Matrix_Rot16(g_Lara.interp.result.head_rot);
|
||||
|
||||
Matrix_Push();
|
||||
mesh = g_Lara.mesh_ptrs[LM_HEAD];
|
||||
|
@ -131,7 +127,7 @@ static void M_CalculateSpheres_I(
|
|||
}
|
||||
|
||||
Matrix_Rot16_ID(mesh_rots_1[LM_TORSO], mesh_rots_2[LM_TORSO]);
|
||||
Matrix_Rot16_I(g_Lara.torso_rot);
|
||||
Matrix_Rot16_I(g_Lara.interp.result.torso_rot);
|
||||
|
||||
Matrix_Push_I();
|
||||
mesh = g_Lara.mesh_ptrs[LM_TORSO];
|
||||
|
@ -171,7 +167,7 @@ static void M_CalculateSpheres_I(
|
|||
|
||||
Matrix_TranslateRel32_I(bone[LM_HEAD - 1].pos);
|
||||
Matrix_Rot16_ID(mesh_rots_1[LM_HEAD], mesh_rots_2[LM_HEAD]);
|
||||
Matrix_Rot16_I(g_Lara.head_rot);
|
||||
Matrix_Rot16_I(g_Lara.interp.result.head_rot);
|
||||
|
||||
Matrix_Push_I();
|
||||
mesh = g_Lara.mesh_ptrs[LM_HEAD];
|
||||
|
@ -393,10 +389,25 @@ void Lara_Hair_Draw(void)
|
|||
for (int32_t i = 0; i < HAIR_SEGMENTS; i++) {
|
||||
const HAIR_SEGMENT *const s = &m_HairSegments[i];
|
||||
Matrix_Push();
|
||||
Matrix_TranslateAbs32(s->pos);
|
||||
Matrix_RotY(s->rot.y);
|
||||
Matrix_RotX(s->rot.x);
|
||||
Matrix_TranslateAbs32(s->interp.result.pos);
|
||||
Matrix_RotY(s->interp.result.rot.y);
|
||||
Matrix_RotX(s->interp.result.rot.x);
|
||||
Object_DrawMesh(obj->mesh_idx + i, 1, false);
|
||||
Matrix_Pop();
|
||||
}
|
||||
}
|
||||
|
||||
bool Lara_Hair_IsActive(void)
|
||||
{
|
||||
return Object_Get(O_LARA_HAIR)->loaded && Object_Get(O_LARA)->loaded;
|
||||
}
|
||||
|
||||
int32_t Lara_Hair_GetSegmentCount(void)
|
||||
{
|
||||
return HAIR_SEGMENTS;
|
||||
}
|
||||
|
||||
HAIR_SEGMENT *Lara_Hair_GetSegment(const int32_t n)
|
||||
{
|
||||
return &m_HairSegments[n];
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
void Lara_Hair_Initialise(void);
|
||||
#include <libtrx/game/lara/hair.h>
|
||||
|
||||
void Lara_Hair_Control(bool in_cutscene);
|
||||
void Lara_Hair_Draw(void);
|
||||
|
|
|
@ -386,4 +386,6 @@ void Level_Unload(void)
|
|||
if (Output_GetBackgroundType() == BK_OBJECT) {
|
||||
Output_UnloadBackground();
|
||||
}
|
||||
|
||||
Camera_Reset();
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@ void Object_DrawAnimatingItem(const ITEM *item)
|
|||
}
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_TranslateAbs32(item->pos);
|
||||
Matrix_Rot16(item->rot);
|
||||
Matrix_TranslateAbs32(item->interp.result.pos);
|
||||
Matrix_Rot16(item->interp.result.rot);
|
||||
|
||||
const int32_t clip = Output_GetObjectBounds(&frames[0]->bounds);
|
||||
if (!clip) {
|
||||
|
@ -134,14 +134,15 @@ void Object_DrawUnclippedItem(const ITEM *const item)
|
|||
void Object_DrawSpriteItem(const ITEM *const item)
|
||||
{
|
||||
Output_CalculateStaticMeshLight(
|
||||
item->pos, item->shade, Room_Get(item->room_num));
|
||||
item->interp.result.pos, item->shade, Room_Get(item->room_num));
|
||||
|
||||
const OBJECT *const obj = Object_Get(item->object_id);
|
||||
|
||||
Output_DrawSprite(
|
||||
SPRITE_ABS | (obj->semi_transparent ? SPRITE_SEMI_TRANS : 0)
|
||||
| SPRITE_SHADE,
|
||||
item->pos.x, item->pos.y, item->pos.z, obj->mesh_idx - item->frame_num,
|
||||
item->interp.result.pos.x, item->interp.result.pos.y,
|
||||
item->interp.result.pos.z, obj->mesh_idx - item->frame_num,
|
||||
Output_GetLightAdder() + 4096, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ void XianWarrior_Draw(const ITEM *item)
|
|||
}
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_TranslateAbs32(item->pos);
|
||||
Matrix_Rot16(item->rot);
|
||||
Matrix_TranslateAbs32(item->interp.result.pos);
|
||||
Matrix_Rot16(item->interp.result.rot);
|
||||
|
||||
const int32_t clip = Output_GetObjectBounds(&frames[0]->bounds);
|
||||
if (clip == 0) {
|
||||
|
|
|
@ -100,8 +100,8 @@ static void M_Control(const int16_t item_num)
|
|||
static void M_Draw(const ITEM *const item)
|
||||
{
|
||||
Matrix_Push();
|
||||
Matrix_TranslateAbs32(item->pos);
|
||||
Matrix_RotY(item->rot.y);
|
||||
Matrix_TranslateAbs32(item->interp.result.pos);
|
||||
Matrix_RotY(item->interp.result.rot.y);
|
||||
|
||||
MATRIX *const mptr = g_MatrixPtr;
|
||||
mptr->_00 = (mptr->_00 * item->timer) >> 8;
|
||||
|
|
|
@ -811,7 +811,8 @@ void Output_InsertShadow(
|
|||
g_FltWinCenterY = (float)(g_PhdWinCenterY);
|
||||
|
||||
Matrix_Push();
|
||||
Matrix_TranslateAbs(item->pos.x, item->floor, item->pos.z);
|
||||
Matrix_TranslateAbs(
|
||||
item->interp.result.pos.x, item->floor, item->interp.result.pos.z);
|
||||
Matrix_RotY(item->rot.y);
|
||||
if (M_CalcObjectVertices(shadow_info.vertex, shadow_info.vertex_count)) {
|
||||
Render_InsertTransOctagon(g_PhdVBuf, 24);
|
||||
|
|
|
@ -15,8 +15,6 @@ int16_t Room_GetTiltType(const SECTOR *sector, int32_t x, int32_t y, int32_t z);
|
|||
// TODO: poor abstraction
|
||||
void Room_InitCinematic(void);
|
||||
|
||||
SECTOR *Room_GetSector(int32_t x, int32_t y, int32_t z, int16_t *room_num);
|
||||
|
||||
int32_t Room_GetWaterHeight(int32_t x, int32_t y, int32_t z, int16_t room_num);
|
||||
|
||||
void Room_TestTriggers(const ITEM *item);
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
"Title": "Enable more responsive passport",
|
||||
"Description": "Disables blocking user input when passport flips pages, scheduling the page flips instead."
|
||||
},
|
||||
"fps": {
|
||||
"Title": "FPS",
|
||||
"Description": "Controls the framerate at which to render the game."
|
||||
},
|
||||
"enable_3d_pickups": {
|
||||
"Title": "3D pickups",
|
||||
"Description": "Enables 3D models to be rendered in place of the sprites for pickup items."
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
"jpg",
|
||||
"png"
|
||||
],
|
||||
"fps": [
|
||||
"30",
|
||||
"60"
|
||||
],
|
||||
"aspect_mode": [
|
||||
"any",
|
||||
"16:9",
|
||||
|
@ -131,6 +135,12 @@
|
|||
"DataType": "Bool",
|
||||
"DefaultValue": true
|
||||
},
|
||||
{
|
||||
"Field": "fps",
|
||||
"DataType": "Enum",
|
||||
"EnumKey": "fps",
|
||||
"DefaultValue": "60"
|
||||
},
|
||||
{
|
||||
"Field": "aspect_mode",
|
||||
"DataType": "Enum",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue