Skip to content

Commit

Permalink
console-cmd: search for valid teleport location
Browse files Browse the repository at this point in the history
Resolves #1486.
  • Loading branch information
rr- committed Sep 3, 2024
1 parent fc6a030 commit d6ca2c9
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- fixed `/tp` console command reporting teleport fails as success (#1484, regression from 4.1)
- fixed console commands causing improper ring shutdown with selected inventory item (#1460, regression from 3.0)
- fixed console input immediately ending demo (#1480, regression from 4.1)
- changed `/tp` console command to look for the closest place to teleport to when targeting items (#1484)
- improved level load times
- improved logs module names readability
- improved crash debug information on Windows
Expand Down
9 changes: 4 additions & 5 deletions src/game/console_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ static COMMAND_RESULT Console_Cmd_Teleport(const char *const args)
z += 0.5f;
}

if (Item_Teleport(g_LaraItem, x * WALL_L, y * WALL_L, z * WALL_L)) {
if (Lara_Cheat_Teleport(x * WALL_L, y * WALL_L, z * WALL_L)) {
Console_Log(GS(OSD_POS_SET_POS), x, y, z);
return CR_SUCCESS;
}
Expand Down Expand Up @@ -153,7 +153,7 @@ static COMMAND_RESULT Console_Cmd_Teleport(const char *const args)
int32_t x = x1 + Random_GetControl() * (x2 - x1) / 0x7FFF;
int32_t y = y1;
int32_t z = z1 + Random_GetControl() * (z2 - z1) / 0x7FFF;
if (Item_Teleport(g_LaraItem, x, y, z)) {
if (Lara_Cheat_Teleport(x, y, z)) {
Console_Log(GS(OSD_POS_SET_ROOM), room_num);
return CR_SUCCESS;
}
Expand Down Expand Up @@ -206,9 +206,8 @@ static COMMAND_RESULT Console_Cmd_Teleport(const char *const args)
}

if (best_item != NULL) {
if (Item_Teleport(
g_LaraItem, best_item->pos.x, best_item->pos.y,
best_item->pos.z)) {
if (Lara_Cheat_Teleport(
best_item->pos.x, best_item->pos.y, best_item->pos.z)) {
Console_Log(GS(OSD_POS_SET_ITEM), args);
} else {
Console_Log(GS(OSD_POS_SET_ITEM_FAIL), args);
Expand Down
27 changes: 0 additions & 27 deletions src/game/items.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include "config.h"
#include "game/anim.h"
#include "game/camera.h"
#include "game/carrier.h"
#include "game/interpolation.h"
#include "game/room.h"
Expand Down Expand Up @@ -248,32 +247,6 @@ void Item_NewRoom(int16_t item_num, int16_t room_num)
r->item_number = item_num;
}

bool Item_Teleport(ITEM_INFO *item, int32_t x, int32_t y, int32_t z)
{
int16_t room_num = Room_GetIndexFromPos(x, y, z);
if (room_num == NO_ROOM) {
return false;
}
const SECTOR_INFO *const sector = Room_GetSector(x, y, z, &room_num);
const int16_t height = Room_GetHeight(sector, x, y, z);
if (height != NO_HEIGHT) {
item->pos.x = x;
item->pos.y = y;
item->pos.z = z;
item->floor = height;
if (item->room_number != room_num) {
const int16_t item_num = item - g_Items;
Item_NewRoom(item_num, room_num);
}

if (item->object_number == O_LARA) {
Camera_ResetPosition();
}
return true;
}
return false;
}

void Item_UpdateRoom(ITEM_INFO *item, int32_t height)
{
int32_t x = item->pos.x;
Expand Down
1 change: 0 additions & 1 deletion src/game/items.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ bool Item_MovePosition(
int32_t velocity);
void Item_ShiftCol(ITEM_INFO *item, COLL_INFO *coll);
void Item_Translate(ITEM_INFO *item, int32_t x, int32_t y, int32_t z);
bool Item_Teleport(ITEM_INFO *item, int32_t x, int32_t y, int32_t z);
int32_t Item_GetDistance(const ITEM_INFO *item, const XYZ_32 *target);

bool Item_TestAnimEqual(ITEM_INFO *item, int16_t anim_index);
Expand Down
80 changes: 80 additions & 0 deletions src/game/lara/lara_cheat.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "game/lara/lara_cheat.h"

#include "game/camera.h"
#include "game/carrier.h"
#include "game/console.h"
#include "game/effects/exploding_death.h"
Expand All @@ -16,8 +17,10 @@
#include "global/const.h"
#include "global/types.h"
#include "global/vars.h"
#include "math/math_misc.h"

#include <libtrx/utils.h>
#include <libtrx/vector.h>

#include <stdbool.h>
#include <stddef.h>
Expand Down Expand Up @@ -368,3 +371,80 @@ bool Lara_Cheat_KillEnemy(const int16_t item_num)
Carrier_TestItemDrops(item_num);
return true;
}

bool Lara_Cheat_Teleport(int32_t x, int32_t y, int32_t z)
{
int16_t room_num = Room_GetIndexFromPos(x, y, z);
if (room_num == NO_ROOM) {
return false;
}

const SECTOR_INFO *sector = Room_GetSector(x, y, z, &room_num);
int16_t height = Room_GetHeight(sector, x, y, z);

if (height == NO_HEIGHT) {
// Sample a sphere of points around target x, y, z
// and teleport to the first available location.
VECTOR *const points = Vector_Create(sizeof(XYZ_32));

const int32_t radius = 5;
const int32_t unit = STEP_L;
for (int32_t dx = -radius; dx <= radius; dx++) {
for (int32_t dz = -radius; dz <= radius; dz++) {
if (SQUARE(dx) + SQUARE(dz) > SQUARE(radius)) {
continue;
}

const XYZ_32 point = {
.x = ROUND_TO_SECTOR(x + dx * unit) + WALL_L / 2,
.y = y,
.z = ROUND_TO_SECTOR(z + dz * unit) + WALL_L / 2,
};
sector = Room_GetSector(point.x, point.y, point.z, &room_num);
height = Room_GetHeight(sector, point.x, point.y, point.z);
if (height != NO_HEIGHT) {
Vector_Add(points, (void *)&point);
}
}
}

int32_t best_distance = INT32_MAX;
for (int32_t i = 0; i < points->count; i++) {
const XYZ_32 *const point = (const XYZ_32 *)Vector_Get(points, i);
const int32_t distance =
XYZ_32_GetDistance(point, &g_LaraItem->pos);
if (distance < best_distance) {
best_distance = distance;
x = point->x;
y = point->y;
z = point->z;
}
}

Vector_Free(points);
if (best_distance == INT32_MAX) {
return false;
}
}

sector = Room_GetSector(x, y, z, &room_num);
height = Room_GetHeight(sector, x, y, z);
if (height == NO_HEIGHT) {
return false;
}

g_LaraItem->pos.x = x;
g_LaraItem->pos.y = y;
g_LaraItem->pos.z = z;
g_LaraItem->floor = height;

if (g_LaraItem->room_number != room_num) {
const int16_t item_num = g_LaraItem - g_Items;
Item_NewRoom(item_num, room_num);
}

if (g_LaraItem->object_number == O_LARA) {
Camera_ResetPosition();
}
return true;
}
1 change: 1 addition & 0 deletions src/game/lara/lara_cheat.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ bool Lara_Cheat_GiveAllGuns(void);
bool Lara_Cheat_GiveAllItems(void);
bool Lara_Cheat_OpenNearestDoor(void);
bool Lara_Cheat_KillEnemy(int16_t item_num);
bool Lara_Cheat_Teleport(int32_t x, int32_t y, int32_t z);
11 changes: 11 additions & 0 deletions src/math/math_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,14 @@ int32_t Math_AngleMean(int32_t angle1, int32_t angle2, double ratio)

return result;
}

int32_t XYZ_32_GetDistance(const XYZ_32 *const pos1, const XYZ_32 *const pos2)
{
// clang-format off
return Math_Sqrt(
SQUARE(pos1->x - pos2->x) +
SQUARE(pos1->y - pos2->y) +
SQUARE(pos1->z - pos2->z)
);
// clang-format on
}
3 changes: 3 additions & 0 deletions src/math/math_misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

#include <stdint.h>

#include "global/types.h"

void Math_GetVectorAngles(int32_t x, int32_t y, int32_t z, int16_t *dest);
int32_t Math_AngleInCone(int32_t angle1, int32_t angle2, int32_t cone);
int32_t Math_AngleMean(int32_t angle1, int32_t angle2, double ratio);
int32_t XYZ_32_GetDistance(const XYZ_32 *pos1, const XYZ_32 *pos2);

0 comments on commit d6ca2c9

Please sign in to comment.