Merge branch 'overhang_climbing' in to state_cleaning_tier_2

This commit is contained in:
Sezz 2022-01-26 12:47:38 +11:00
commit 131a60184b
31 changed files with 1413 additions and 97 deletions

View file

@ -23,4 +23,5 @@ anims.monkeyTurn180 = true;
anims.monkeyAutoJump = false;
anims.oscillateHang = true;
anims.pose = false;
anims.overhang = true;
SetAnimations(anims);

View file

@ -16,6 +16,7 @@
#include "Game/Lara/lara_one_gun.h"
#include "Game/Lara/lara_cheat.h"
#include "Game/Lara/lara_climb.h"
#include "Game/Lara/lara_overhang.h"
#include "Game/Lara/lara_initialise.h"
#include "Objects/TR2/Vehicles/snowmobile.h"
@ -203,19 +204,24 @@ function<LaraRoutineFunction> lara_control_routines[NUM_LARA_STATES + 1] =
lara_as_null,//140
lara_as_null,//141
lara_as_null,//142
lara_as_null,// 143 - Unused
lara_as_null,// 144 - Unused
lara_as_null,// 145 - Unused
lara_as_slopeclimb,//143
lara_as_slopeclimbup,//144
lara_as_slopeclimbdown,//145
lara_as_controlled_no_look,
lara_as_null,
lara_as_null,
lara_as_null,
lara_as_slopefall,//149
lara_as_stepoff_left,
lara_as_stepoff_right,
lara_as_turn_left_fast,
lara_as_controlled,
lara_as_controlled,
lara_as_controlled
lara_as_controlled,//155
lara_as_slopehang,
lara_as_slopeshimmy,
lara_as_sclimbstart,
lara_as_sclimbstop,
lara_as_sclimbend
};
function<LaraRoutineFunction> lara_collision_routines[NUM_LARA_STATES + 1] =
@ -363,19 +369,24 @@ function<LaraRoutineFunction> lara_collision_routines[NUM_LARA_STATES + 1] =
lara_void_func,
lara_void_func,
lara_void_func,
lara_void_func, // 143 - Unused
lara_void_func, // 144 - Unused
lara_void_func, // 145 - Unused
lara_void_func,
lara_col_slopeclimb,
lara_default_col, // lara_col_slopeclimbup
lara_default_col, // lara_col_slopeclimbdown
lara_void_func,
lara_void_func,
lara_void_func,
lara_default_col, // lara_col_slopefall
lara_default_col,
lara_default_col,
lara_col_turn_left_fast,
lara_default_col,
lara_default_col,
lara_default_col
lara_default_col,
lara_col_slopehang, // lara_col_slopehang
lara_col_slopeshimmy, // lara_col_slopeshimmy
lara_default_col, // lara_col_sclimbstart
lara_default_col, // lara_col_sclimbstop
lara_default_col // lara_col_sclimbend
};
void LaraControl(ITEM_INFO* item, COLL_INFO* coll)

View file

@ -7,6 +7,7 @@
#include "Game/control/control.h"
#include "Game/items.h"
#include "Game/Lara/lara.h"
#include "Game/Lara/lara_overhang.h"
#include "Specific/level.h"
#include "Specific/input.h"
@ -31,6 +32,22 @@ short GetClimbFlags(FLOOR_INFO* floor)
return result;
}
CLIMB_DIRECTION GetClimbDirection(short angle)
{
switch (GetQuadrant(angle))
{
default:
case NORTH:
return CLIMB_DIRECTION::North;
case EAST:
return CLIMB_DIRECTION::East;
case SOUTH:
return CLIMB_DIRECTION::South;
case WEST:
return CLIMB_DIRECTION::West;
}
}
void lara_col_climbend(ITEM_INFO* item, COLL_INFO* coll)
{
return;
@ -130,6 +147,8 @@ void lara_as_climbdown(ITEM_INFO* item, COLL_INFO* coll)
coll->Setup.EnableSpaz = false;
Camera.targetElevation = -ANGLE(45);
SlopeClimbDownExtra(item, coll);
}
void lara_col_climbing(ITEM_INFO* item, COLL_INFO* coll)
@ -312,7 +331,10 @@ void lara_col_climbstnc(ITEM_INFO* item, COLL_INFO* coll)
resultLeft = LaraTestClimbUpPos(item, coll->Setup.Radius, -CLICK(0.5f) - coll->Setup.Radius, &shiftLeft, &ledgeLeft);
if (!resultRight || !resultLeft)
{
LadderMonkeyExtra(item, coll);
return;
}
if (resultRight >= 0 && resultLeft >= 0)
{
@ -390,6 +412,8 @@ void lara_as_climbstnc(ITEM_INFO* item, COLL_INFO* coll)
Lara.moveAngle = item->pos.yRot + ANGLE(180);
}
}
SlopeClimbExtra(item, coll);
}
void lara_as_stepoff_left(ITEM_INFO* item, COLL_INFO* coll)

View file

@ -1,14 +1,7 @@
#pragma once
#include "Game/collision/collide_room.h"
#include "Game/items.h"
enum class CLIMB_DIRECTION : short
{
North = 0x0100,
East = 0x0200,
South = 0x0400,
West = 0x0800
};
#include "Game/collision//floordata.h"
static CLIMB_DIRECTION LeftIntRightExtTab[4] =
{
@ -22,6 +15,7 @@ static CLIMB_DIRECTION LeftExtRightIntTab[4] =
short GetClimbFlags(int x, int y, int z, short roomNumber);
short GetClimbFlags(FLOOR_INFO* floor);
CLIMB_DIRECTION GetClimbDirection(short angle);
void lara_col_climbend(ITEM_INFO* item, COLL_INFO* coll);
void lara_as_climbend(ITEM_INFO* item, COLL_INFO* coll);

View file

@ -615,7 +615,8 @@ bool TestLaraObjectCollision(ITEM_INFO* item, short angle, int dist, int height,
item->pos.yPos += height;
item->pos.zPos += phd_cos(item->pos.yRot + angle) * dist + phd_sin(angle + ANGLE(90.0f) * sideSign) * abs(side);
auto result = GetCollidedObjects(item, LARA_RAD, 1, CollidedItems, CollidedMeshes, 0);
auto result = GetCollidedObjects(item, LARA_RAD, true, CollidedItems, CollidedMeshes, 0);
item->pos = oldPos;
return result;
}

View file

@ -6,6 +6,7 @@
#include "Game/collision/collide_item.h"
#include "Game/items.h"
#include "Game/Lara/lara.h"
#include "Game/Lara/lara_overhang.h"
#include "Game/Lara/lara_tests.h"
#include "Specific/input.h"
#include "Specific/level.h"
@ -69,6 +70,8 @@ void lara_as_hang(ITEM_INFO* item, COLL_INFO* coll)
Camera.targetAngle = 0;
Camera.targetElevation = -ANGLE(45.0f);
SlopeHangExtra(item, coll);
}
void lara_col_hang(ITEM_INFO* item, COLL_INFO* coll)

View file

@ -8,6 +8,8 @@
#include "Game/Lara/lara_tests.h"
#include "Game/Lara/lara_helpers.h"
#include "Game/Lara/lara_basic.h"
#include "Game/Lara/lara_overhang.h"
#include "Game/Lara/lara_slide.h"
#include "Scripting/GameFlowScript.h"
#include "Sound/sound.h"
#include "Specific/input.h"
@ -226,6 +228,8 @@ void lara_as_reach(ITEM_INFO* item, COLL_INFO* coll)
}
item->goalAnimState = LS_REACH;
// TODO: overhang
//SlopeReachExtra(item, coll);
}
// State: LS_REACH (11)

View file

@ -10,6 +10,7 @@
#include "Game/Lara/lara.h"
#include "Game/Lara/lara_collide.h"
#include "Game/Lara/lara_helpers.h"
#include "Game/Lara/lara_overhang.h"
#include "Game/Lara/lara_tests.h"
#include "Specific/input.h"
#include "Specific/level.h"
@ -45,6 +46,12 @@ void lara_as_monkey_idle(ITEM_INFO* item, COLL_INFO* coll)
if (TrInput & IN_LOOK)
LookUpDown();
// TODO: overhang
//SlopeMonkeyExtra(item, coll);
// This check is needed to prevent stealing goal state from previously set.
//if (item->goalAnimState == LS_MONKEYSWING_IDLE)
// return;
if (TrInput & IN_LEFT)
{
info->turnRate -= LARA_TURN_RATE;

View file

@ -183,7 +183,7 @@ void HarpoonBoltControl(short itemNumber)
bool explodeItem = true;
// Found possible collided items and statics
GetCollidedObjects(item, HARPOON_HIT_RADIUS, 1, &CollidedItems[0], &CollidedMeshes[0], 1);
GetCollidedObjects(item, HARPOON_HIT_RADIUS, true, &CollidedItems[0], &CollidedMeshes[0], 1);
// If no collided items and meshes are found, then exit the loop
if (!CollidedItems[0] && !CollidedMeshes[0])
@ -590,7 +590,7 @@ void GrenadeControl(short itemNumber)
// Step 1: done only if explosion, try to smash all objects in the blast radius
// Found possible collided items and statics
GetCollidedObjects(item, radius, 1, &CollidedItems[0], &CollidedMeshes[0], false);
GetCollidedObjects(item, radius, true, &CollidedItems[0], &CollidedMeshes[0], false);
if (explode)
{
@ -843,7 +843,7 @@ void RocketControl(short itemNumber)
// Step 1: done only if explosion, try to smash all objects in the blast radius
// Found possible collided items and statics
GetCollidedObjects(item, radius, 1, &CollidedItems[0], &CollidedMeshes[0], true);
GetCollidedObjects(item, radius, true, &CollidedItems[0], &CollidedMeshes[0], true);
// If no collided items and meshes are found, then exit the loop
if (!CollidedItems[0] && !CollidedMeshes[0])
@ -1330,7 +1330,7 @@ void CrossbowBoltControl(short itemNumber)
// Step 1: done only if explosion, try to smash all objects in the blast radius
// Found possible collided items and statics
GetCollidedObjects(item, radius, 1, &CollidedItems[0], &CollidedMeshes[0], true);
GetCollidedObjects(item, radius, true, &CollidedItems[0], &CollidedMeshes[0], true);
// If no collided items and meshes are found, then exit the loop
if (!CollidedItems[0] && !CollidedMeshes[0])

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,25 @@
#pragma once
#include "Specific/trmath.h"
struct ITEM_INFO;
struct COLL_INFO;
void lara_col_slopeclimb(ITEM_INFO* lara, COLL_INFO* coll);
void lara_as_slopeclimb(ITEM_INFO* lara, COLL_INFO* coll);
void lara_as_slopefall(ITEM_INFO* lara, COLL_INFO* coll);
void lara_col_slopehang(ITEM_INFO* lara, COLL_INFO* coll);
void lara_as_slopehang(ITEM_INFO* lara, COLL_INFO* coll);
void lara_col_slopeshimmy(ITEM_INFO* lara, COLL_INFO* coll);
void lara_as_slopeshimmy(ITEM_INFO* lara, COLL_INFO* coll);
void lara_as_slopeclimbup(ITEM_INFO* lara, COLL_INFO* coll);
void lara_as_slopeclimbdown(ITEM_INFO* lara, COLL_INFO* coll);
void lara_as_sclimbstart(ITEM_INFO* lara, COLL_INFO* coll);
void lara_as_sclimbstop(ITEM_INFO* lara, COLL_INFO* coll);
void lara_as_sclimbend(ITEM_INFO* lara, COLL_INFO* coll);
void SlopeHangExtra(ITEM_INFO* lara, COLL_INFO* coll);
void SlopeReachExtra(ITEM_INFO* lara, COLL_INFO* coll);
void SlopeClimbExtra(ITEM_INFO* lara, COLL_INFO* coll);
void SlopeClimbDownExtra(ITEM_INFO* lara, COLL_INFO* coll);
void SlopeMonkeyExtra(ITEM_INFO* lara, COLL_INFO* coll);
void LadderMonkeyExtra(ITEM_INFO* lara, COLL_INFO* coll);

View file

@ -177,19 +177,24 @@ enum LARA_STATE
LS_SHIMMY_45_OUTER_RIGHT = 140,
LS_SHIMMY_45_INNER_LEFT = 141,
LS_SHIMMY_45_INNER_RIGHT = 142,
LS_UNUSED1 = 143, // Foot hang leftovers - may be safely reused
LS_UNUSED2 = 144, // Foot hang leftovers - may be safely reused
LS_UNUSED3 = 145, // Foot hang leftovers - may be safely reused
LS_SLOPE_CLIMB_IDLE = 143,
LS_SLOPE_CLIMB_UP = 144,
LS_SLOPE_CLIMB_DOWN = 145,
LS_COGWHEEL_UNGRAB = 146,
LS_STEP_UP = 147,
LS_STEP_DOWN = 148,
LS_UNUSED4 = 149, // Vestige of step back down; a new state can be added in its place.
LS_SLOPE_CLIMB_FALL = 149,
LS_LADDER_DISMOUNT_LEFT = 150,
LS_LADDER_DISMOUNT_RIGHT = 151,
LS_TURN_LEFT_FAST = 152,
LS_CRAWL_EXIT_DOWN_STEP = 153,
LS_CRAWL_EXIT_JUMP = 154,
LS_CRAWL_EXIT_FLIP = 155,
LS_SLOPE_CLIMB_HANG = 156,
LS_SLOPE_CLIMB_SHIMMY = 157,
LS_SLOPE_CLIMB_START = 158,
LS_SLOPE_CLIMB_STOP = 159,
LS_SLOPE_CLIMB_END = 160,
LS_MONKEY_BACK,
@ -714,7 +719,7 @@ enum LARA_ANIM
LA_ONWATER_TO_CROUCH_1CLICK = 481, // Pull up 1-click from tread > stand
LA_ONWATER_TO_CROUCH_0CLICK = 482, // Pull up 0-click from tread > stand
LA_ONWATER_TO_CROUCH_M1CLICK = 483, // Pull up -1-click from tread > stand
LA_UNUSED1 = 484, // Foot hang leftovers - may be safely reused
LA_LADDER_TO_MONKEY = 484, // Foot hang leftovers - may be safely reused
LA_UNUSED2 = 485, // Foot hang leftovers - may be safely reused
LA_UNUSED3 = 486, // Foot hang leftovers - may be safely reused
LA_UNUSED4 = 487, // Foot hang leftovers - may be safely reused
@ -736,6 +741,45 @@ enum LARA_ANIM
LA_POSE_CONTINUE = 503, // AFK pose (looped)
LA_POSE_END = 504, // AFK pose > stand
LA_OVERHANG_IDLE_LEFT,
LA_OVERHANG_IDLE_RIGHT,
LA_OVERHANG_CLIMB_UP_LEFT,
LA_OVERHANG_CLIMB_UP_RIGHT,
LA_OVERHANG_CLIMB_DOWN_LEFT,
LA_OVERHANG_CLIMB_DOWN_RIGHT,
LA_OVERHANG_DROP_LEFT,
LA_OVERHANG_DROP_RIGHT,
LA_OVERHANG_IDLE_2_HANG_LEFT,
LA_OVERHANG_IDLE_2_HANG_RIGHT,
LA_OVERHANG_HANG_2_IDLE_LEFT,
LA_OVERHANG_HANG_2_IDLE_RIGHT,
LA_OVERHANG_HANG_SWING,
LA_OVERHANG_HANG_LOOP,
LA_OVERHANG_HANG_DROP,
LA_OVERHANG_SHIMMY_LEFT,
LA_OVERHANG_SHIMMY_LEFT_STOP,
LA_OVERHANG_SHIMMY_RIGHT,
LA_OVERHANG_SHIMMY_RIGHT_STOP,
LA_OVERHANG_LEDGE_VAULT_START,
LA_OVERHANG_LEDGE_VAULT,
LA_OVERHANG_LADDER_SLOPE_CONCAVE,
LA_OVERHANG_SLOPE_LADDER_CONCAVE,
LA_OVERHANG_LADDER_SLOPE_CONVEX,
LA_OVERHANG_SLOPE_LADDER_CONVEX_START,
LA_OVERHANG_SLOPE_LADDER_CONVEX,
LA_OVERHANG_MONKEY_SLOPE_CONCAVE,
LA_OVERHANG_SLOPE_MONKEY_CONCAVE,
LA_OVERHANG_SLOPE_MONKEY_CONCAVE_END,
LA_OVERHANG_MONKEY_SLOPE_CONVEX,
LA_OVERHANG_MONKEY_SLOPE_CONVEX_END,
LA_OVERHANG_SLOPE_MONKEY_CONVEX,
LA_OVERHANG_EXIT_MONKEY_FORWARD,
LA_OVERHANG_EXIT_MONKEY_IDLE,
LA_OVERHANG_EXIT_LADDER,
LA_OVERHANG_EXIT_VAULT,
LA_OVERHANG_EXIT_DROP,
LA_OVERHANG_EXIT_HANG,
NUM_LARA_ANIMS
// TRASHED ANIMS (please reuse slots before going any higher and remove entries from this list as you go):

View file

@ -287,6 +287,11 @@ int GetFrame(ITEM_INFO* item, ANIM_FRAME* framePtr[], int* rate)
return(interp);
}
short GetCurrentRelativeFrameNumber(ITEM_INFO* item)
{
return item->frameNumber - GetFrameNumber(item, 0);
}
short GetFrameNumber(ITEM_INFO* item, short frameToStart)
{
return GetFrameNumber(item->objectNumber, item->animNumber, frameToStart);
@ -302,7 +307,9 @@ int GetFrameCount(short animNumber)
if (animNumber < 0 || g_Level.Anims.size() <= animNumber)
return 0;
return &g_Level.Anims[animNumber].frameEnd - &g_Level.Anims[animNumber].frameBase;
int end = g_Level.Anims[animNumber].frameEnd;
int base = g_Level.Anims[animNumber].frameBase;
return (end - base);
}
int GetNextAnimState(ITEM_INFO* item)

View file

@ -56,6 +56,7 @@ struct BONE_MUTATOR
void AnimateItem(ITEM_INFO* item);
void TranslateItem(ITEM_INFO* item, int x, int y, int z);
void SetAnimation(ITEM_INFO* item, short animIndex, short frameToStart = 0);
short GetCurrentRelativeFrameNumber(ITEM_INFO* item);
short GetFrameNumber(ITEM_INFO* item, short frameToStart);
short GetFrameNumber(short objectID, short animNumber, short frameToStart);
int GetFrameCount(short animNumber);

View file

@ -1190,23 +1190,23 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
if (collResult.Position.FloorSlope && oldCollResult.Position.Floor < collResult.Position.Floor)
{
yang = (long)((unsigned short)item->pos.yRot);
if (collResult.FloorTiltX < 0)
if (collResult.FloorTilt.x < 0)
{
if (yang >= 0x8000)
bs = 1;
}
else if (collResult.FloorTiltX > 0)
else if (collResult.FloorTilt.x > 0)
{
if (yang <= 0x8000)
bs = 1;
}
if (collResult.FloorTiltZ < 0)
if (collResult.FloorTilt.y < 0)
{
if (yang >= 0x4000 && yang <= 0xc000)
bs = 1;
}
else if (collResult.FloorTiltZ > 0)
else if (collResult.FloorTilt.y > 0)
{
if (yang <= 0x4000 || yang >= 0xc000)
bs = 1;
@ -1257,7 +1257,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
item->speed -= (item->speed / 4);
if (collResult.FloorTiltX < 0 && ((abs(collResult.FloorTiltX)) - (abs(collResult.FloorTiltZ)) >= 2)) // Hit angle = 0x4000
if (collResult.FloorTilt.x < 0 && ((abs(collResult.FloorTilt.x)) - (abs(collResult.FloorTilt.y)) >= 2)) // Hit angle = 0x4000
{
if (((unsigned short)item->pos.yRot) > 0x8000)
{
@ -1269,7 +1269,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
{
if (item->speed < 32)
{
item->speed -= collResult.FloorTiltX * 2;
item->speed -= collResult.FloorTilt.x * 2;
if ((unsigned short)item->pos.yRot > 0x4000 && (unsigned short)item->pos.yRot < 0xc000)
{
item->pos.yRot -= 4096;
@ -1290,7 +1290,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
item->fallspeed = 0;
}
}
else if (collResult.FloorTiltX > 0 && ((abs(collResult.FloorTiltX)) - (abs(collResult.FloorTiltZ)) >= 2)) // Hit angle = 0xc000
else if (collResult.FloorTilt.x > 0 && ((abs(collResult.FloorTilt.x)) - (abs(collResult.FloorTilt.y)) >= 2)) // Hit angle = 0xc000
{
if (((unsigned short)item->pos.yRot) < 0x8000)
{
@ -1302,7 +1302,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
{
if (item->speed < 32)
{
item->speed += collResult.FloorTiltX * 2;
item->speed += collResult.FloorTilt.x * 2;
if ((unsigned short)item->pos.yRot > 0xc000 || (unsigned short)item->pos.yRot < 0x4000)
{
item->pos.yRot -= 4096;
@ -1323,7 +1323,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
item->fallspeed = 0;
}
}
else if (collResult.FloorTiltZ < 0 && ((abs(collResult.FloorTiltZ)) - (abs(collResult.FloorTiltX)) >= 2)) // Hit angle = 0
else if (collResult.FloorTilt.y < 0 && ((abs(collResult.FloorTilt.y)) - (abs(collResult.FloorTilt.x)) >= 2)) // Hit angle = 0
{
if (((unsigned short)item->pos.yRot) > 0x4000 && ((unsigned short)item->pos.yRot) < 0xc000)
{
@ -1335,7 +1335,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
{
if (item->speed < 32)
{
item->speed -= collResult.FloorTiltZ * 2;
item->speed -= collResult.FloorTilt.y * 2;
if ((unsigned short)item->pos.yRot < 0x8000)
{
@ -1357,7 +1357,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
item->fallspeed = 0;
}
}
else if (collResult.FloorTiltZ > 0 && ((abs(collResult.FloorTiltZ)) - (abs(collResult.FloorTiltX)) >= 2)) // Hit angle = 0x8000
else if (collResult.FloorTilt.y > 0 && ((abs(collResult.FloorTilt.y)) - (abs(collResult.FloorTilt.x)) >= 2)) // Hit angle = 0x8000
{
if (((unsigned short)item->pos.yRot) > 0xc000 || ((unsigned short)item->pos.yRot) < 0x4000)
{
@ -1369,7 +1369,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
{
if (item->speed < 32)
{
item->speed += collResult.FloorTiltZ * 2;
item->speed += collResult.FloorTilt.y * 2;
if ((unsigned short)item->pos.yRot > 0x8000)
{
@ -1391,7 +1391,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
item->fallspeed = 0;
}
}
else if (collResult.FloorTiltX < 0 && collResult.FloorTiltZ < 0) // Hit angle = 0x2000
else if (collResult.FloorTilt.x < 0 && collResult.FloorTilt.y < 0) // Hit angle = 0x2000
{
if (((unsigned short)item->pos.yRot) > 0x6000 && ((unsigned short)item->pos.yRot) < 0xe000)
{
@ -1403,7 +1403,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
{
if (item->speed < 32)
{
item->speed += (-collResult.FloorTiltX) + (-collResult.FloorTiltZ);
item->speed += (-collResult.FloorTilt.x) + (-collResult.FloorTilt.y);
if ((unsigned short)item->pos.yRot > 0x2000 && (unsigned short)item->pos.yRot < 0xa000)
{
item->pos.yRot -= 4096;
@ -1424,7 +1424,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
item->fallspeed = 0;
}
}
else if (collResult.FloorTiltX < 0 && collResult.FloorTiltZ > 0) // Hit angle = 0x6000
else if (collResult.FloorTilt.x < 0 && collResult.FloorTilt.y > 0) // Hit angle = 0x6000
{
if (((unsigned short)item->pos.yRot) > 0xa000 || ((unsigned short)item->pos.yRot) < 0x2000)
{
@ -1436,7 +1436,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
{
if (item->speed < 32)
{
item->speed += (-collResult.FloorTiltX) + collResult.FloorTiltZ;
item->speed += (-collResult.FloorTilt.x) + collResult.FloorTilt.y;
if ((unsigned short)item->pos.yRot < 0xe000 && (unsigned short)item->pos.yRot > 0x6000)
{
item->pos.yRot -= 4096;
@ -1457,7 +1457,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
item->fallspeed = 0;
}
}
else if (collResult.FloorTiltX > 0 && collResult.FloorTiltZ > 0) // Hit angle = 0xa000
else if (collResult.FloorTilt.x > 0 && collResult.FloorTilt.y > 0) // Hit angle = 0xa000
{
if (((unsigned short)item->pos.yRot) > 0xe000 || ((unsigned short)item->pos.yRot) < 0x6000)
{
@ -1469,7 +1469,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
{
if (item->speed < 32)
{
item->speed += collResult.FloorTiltX + collResult.FloorTiltZ;
item->speed += collResult.FloorTilt.x + collResult.FloorTilt.y;
if ((unsigned short)item->pos.yRot < 0x2000 || (unsigned short)item->pos.yRot > 0xa000)
{
item->pos.yRot -= 4096;
@ -1490,7 +1490,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
item->fallspeed = 0;
}
}
else if (collResult.FloorTiltX > 0 && collResult.FloorTiltZ < 0) // Hit angle = 0xe000
else if (collResult.FloorTilt.x > 0 && collResult.FloorTilt.y < 0) // Hit angle = 0xe000
{
if (((unsigned short)item->pos.yRot) > 0x2000 && ((unsigned short)item->pos.yRot) < 0xa000)
{
@ -1502,7 +1502,7 @@ void DoProjectileDynamics(short itemNumber, int x, int y, int z, int xv, int yv,
{
if (item->speed < 32)
{
item->speed += collResult.FloorTiltX + (-collResult.FloorTiltZ);
item->speed += collResult.FloorTilt.x + (-collResult.FloorTilt.y);
if ((unsigned short)item->pos.yRot < 0x6000 || (unsigned short)item->pos.yRot > 0xe000)
{
item->pos.yRot -= 4096;

View file

@ -176,26 +176,20 @@ COLL_RESULT GetCollisionResult(FLOOR_INFO* floor, int x, int y, int z)
// Return probed bottom block into result.
result.BottomBlock = floor;
// Get floor tilts.
auto floorTilts = floor->FloorTiltXZ(x, z);
result.FloorTiltX = floorTilts.first;
result.FloorTiltZ = floorTilts.second;
// Get tilts.
result.FloorTilt = floor->TiltXZ(x, z, true);
result.CeilingTilt = floor->TiltXZ(x, z, false);
// Get ceiling tilts.
auto ceilingTilts = floor->CeilingTiltXZ(x, z);
result.CeilingTiltX = ceilingTilts.first;
result.CeilingTiltZ = ceilingTilts.second;
// Split, bridge and slope data.
// Split, bridge and slope data
result.Position.DiagonalStep = floor->FloorIsDiagonalStep();
result.Position.SplitAngle = floor->FloorCollision.SplitAngle;
result.Position.Bridge = result.BottomBlock->InsideBridge(x, result.Position.Floor, z, true, false);
result.Position.FloorSlope = result.Position.Bridge < 0 && (abs(floorTilts.first) > 2 || abs(floorTilts.second) > 2);
result.Position.CeilingSlope = abs(ceilingTilts.first) > 2 || abs(ceilingTilts.second) > 2;
result.Position.FloorSlope = result.Position.Bridge < 0 && ((abs(result.FloorTilt.x) > 2 || (abs(result.FloorTilt.y)) > 2));
result.Position.CeilingSlope = abs(result.CeilingTilt.x) > 2 || abs(result.CeilingTilt.y) > 2;
// TODO: check if we need to keep here this slope vs. bridge check from legacy GetTiltType.
if ((y + CLICK(2)) < floor->FloorHeight(x, z))
result.FloorTiltZ = result.FloorTiltX = 0;
// TODO: check if we need to keep here this slope vs. bridge check from legacy GetTiltType
if ((y + CLICK(2)) < (floor->FloorHeight(x, z)))
result.FloorTilt = Vector2::Zero;
return result;
}
@ -293,10 +287,10 @@ void GetCollisionInfo(COLL_INFO* coll, ITEM_INFO* item, PHD_VECTOR offset, bool
// TEST 1: TILT AND NEAREST LEDGE CALCULATION
auto collResult = GetCollisionResult(x, item->pos.yPos, z, item->roomNumber);
coll->FloorTiltX = collResult.FloorTiltX;
coll->FloorTiltZ = collResult.FloorTiltZ;
coll->CeilingTiltX = collResult.CeilingTiltX;
coll->CeilingTiltZ = collResult.CeilingTiltZ;
coll->FloorTiltX = (int)collResult.FloorTilt.x;
coll->FloorTiltZ = (int)collResult.FloorTilt.y;
coll->CeilingTiltX = (int)collResult.CeilingTilt.x;
coll->CeilingTiltZ = (int)collResult.CeilingTilt.y;
coll->NearestLedgeAngle = GetNearestLedgeAngle(item, coll, coll->NearestLedgeDistance);
// Debug angle and distance

View file

@ -59,11 +59,8 @@ struct COLL_RESULT
FLOOR_INFO* BottomBlock;
COLL_POSITION Position;
int FloorTiltX;
int FloorTiltZ;
int CeilingTiltX;
int CeilingTiltZ;
Vector2 FloorTilt;
Vector2 CeilingTilt;
};
struct COLL_SETUP

View file

@ -29,22 +29,13 @@ int FLOOR_INFO::SectorPlaneCeiling(int x, int z) const
return vector.x < 0 ? 0 : 1;
}
std::pair<int, int> FLOOR_INFO::FloorTiltXZ(int x, int z) const
Vector2 FLOOR_INFO::TiltXZ(int x, int z, bool floor) const
{
auto plane = FloorCollision.Planes[SectorPlane(x, z)];
auto plane = floor ? FloorCollision.Planes[SectorPlane(x, z)] : CeilingCollision.Planes[SectorPlane(x, z)];
auto tiltX = (int)-(plane.x * WALL_SIZE / STEP_SIZE);
auto tiltZ = (int)-(plane.y * WALL_SIZE / STEP_SIZE);
return std::make_pair(tiltX, tiltZ);
}
std::pair<int, int> FLOOR_INFO::CeilingTiltXZ(int x, int z) const
{
auto plane = CeilingCollision.Planes[SectorPlaneCeiling(x, z)];
auto tiltX = (int)-(plane.x * WALL_SIZE / STEP_SIZE);
auto tiltZ = (int)-(plane.y * WALL_SIZE / STEP_SIZE);
return std::make_pair(tiltX, tiltZ);
return Vector2(tiltX, tiltZ);
}
bool FLOOR_INFO::FloorIsSplit() const

View file

@ -5,6 +5,14 @@
constexpr auto WALL_PLANE = Vector3(0, 0, -CLICK(127));
enum class CLIMB_DIRECTION : short
{
North = 0x0100,
East = 0x0200,
South = 0x0400,
West = 0x0800
};
enum class FLOOR_MATERIAL : unsigned char
{
Mud = 0,
@ -45,6 +53,23 @@ struct SECTOR_FLAGS
bool MarkTriggerer;
bool MarkTriggererActive; // TODO: IT NEEDS TO BE WRITTEN/READ FROM SAVEGAMES!
bool ClimbPossible(CLIMB_DIRECTION direction)
{
switch (direction)
{
case CLIMB_DIRECTION::North:
return ClimbNorth;
case CLIMB_DIRECTION::South:
return ClimbSouth;
case CLIMB_DIRECTION::East:
return ClimbEast;
case CLIMB_DIRECTION::West:
return ClimbWest;
}
return false;
}
};
class FLOOR_INFO
@ -64,8 +89,7 @@ class FLOOR_INFO
int SectorPlane(int x, int z) const;
int SectorPlaneCeiling(int x, int z) const;
std::pair<int, int> FLOOR_INFO::FloorTiltXZ(int x, int z) const;
std::pair<int, int> FLOOR_INFO::CeilingTiltXZ(int x, int z) const;
Vector2 FLOOR_INFO::TiltXZ(int x, int z, bool floor) const;
bool FloorIsSplit() const;
bool FloorIsDiagonalStep() const;
bool CeilingIsDiagonalStep() const;

View file

@ -158,10 +158,10 @@ namespace Footprints {
auto c2 = GetCollisionResult(p2.x, footPos.y - STEP_SIZE, p2.z, item->roomNumber);
auto c3 = GetCollisionResult(p3.x, footPos.y - STEP_SIZE, p3.z, item->roomNumber);
// Don't process footprint placement if all foot corners aren't on the same FloorTilt level
if ((c0.FloorTiltX != c1.FloorTiltX) || (c1.FloorTiltX != c2.FloorTiltX) || (c2.FloorTiltX != c3.FloorTiltX))
// Don't process footprint placement if all foot corners aren't on the same tilt level
if ((c0.FloorTilt.x != c1.FloorTilt.x) || (c1.FloorTilt.x != c2.FloorTilt.x) || (c2.FloorTilt.x != c3.FloorTilt.x))
return;
if ((c0.FloorTiltZ != c1.FloorTiltZ) || (c1.FloorTiltZ != c2.FloorTiltZ) || (c2.FloorTiltZ != c3.FloorTiltZ))
if ((c0.FloorTilt.y != c1.FloorTilt.y) || (c1.FloorTilt.y != c2.FloorTilt.y) || (c2.FloorTilt.y != c3.FloorTilt.y))
return;
// Don't process footprint placement if all foot corners aren't on the same height

View file

@ -233,7 +233,7 @@ namespace TEN::Entities::Generic
DoProjectileDynamics(itemNumber, oldX, oldY, oldZ, xv, item->fallspeed, zv);
if (GetCollidedObjects(item, 0, 1, CollidedItems, CollidedMeshes, 0))
if (GetCollidedObjects(item, 0, true, CollidedItems, CollidedMeshes, 0))
{
LaraCollision.Setup.EnableObjectPush = true;
if (CollidedItems)

View file

@ -32,7 +32,7 @@ std::optional<int> BridgeCeiling(short itemNumber, int x, int y, int z)
if (bboxHeight.has_value() && tilt != 0)
{
const auto height = item->pos.yPos + tilt * (GetOffset(item->pos.yRot, x, z) / 4 + SECTOR(1) / 8);
return std::optional{ height + SECTOR(1) / 16 }; // To be customized with Lua
return std::optional{ height + CLICK(1) }; // To be customized with Lua
}
return bboxHeight;
}

View file

@ -118,7 +118,7 @@ void ControlCentaurBomb(short itemNumber)
int n = 0;
bool foundCollidedObjects = false;
GetCollidedObjects(item, HARPOON_HIT_RADIUS, 1, &CollidedItems[0], &CollidedMeshes[0], 0);
GetCollidedObjects(item, HARPOON_HIT_RADIUS, true, &CollidedItems[0], &CollidedMeshes[0], 0);
if (!CollidedItems[0] && !CollidedMeshes[0])
return;

View file

@ -685,7 +685,7 @@ bool TestBlockPull(ITEM_INFO* item, int blockhite, short quadrant)
int oldZ = item->pos.zPos;
item->pos.xPos = x;
item->pos.zPos = z;
GetCollidedObjects(item, 256, 1, &CollidedItems[0], 0, 1);
GetCollidedObjects(item, 256, true, &CollidedItems[0], 0, 1);
item->pos.xPos = oldX;
item->pos.zPos = oldZ;
@ -748,7 +748,7 @@ bool TestBlockPull(ITEM_INFO* item, int blockhite, short quadrant)
oldZ = LaraItem->pos.zPos;
LaraItem->pos.xPos = x;
LaraItem->pos.zPos = z;
GetCollidedObjects(LaraItem, 256, 1, &CollidedItems[0], 0, 1);
GetCollidedObjects(LaraItem, 256, true, &CollidedItems[0], 0, 1);
LaraItem->pos.xPos = oldX;
LaraItem->pos.zPos = oldZ;

View file

@ -114,7 +114,7 @@ void ExplosionControl(short itemNumber)
}
}
}
GetCollidedObjects(item, 2048, 1, CollidedItems, CollidedMeshes, 1);
GetCollidedObjects(item, 2048, true, CollidedItems, CollidedMeshes, 1);
if (CollidedItems[0] || CollidedMeshes[0])
{
i = 0;

View file

@ -970,6 +970,7 @@ enum GAME_OBJECT_ID : short
ID_BRIDGE_TILT2, // OK
ID_BRIDGE_TILT3,
ID_BRIDGE_TILT4,
ID_BRIDGE_CUSTOM,
ID_HORIZON = 1350,
ID_BINOCULAR_GRAPHICS,

View file

@ -16,6 +16,7 @@ void GameScriptAnimations::Register(sol::state* lua)
"monkeyTurn180", &GameScriptAnimations::MonkeyTurn180,
"monkeyAutoJump", &GameScriptAnimations::MonkeyAutoJump,
"oscillateHang", &GameScriptAnimations::OscillateHang,
"pose", &GameScriptAnimations::Pose
"pose", &GameScriptAnimations::Pose,
"overhang", &GameScriptAnimations::Overhang
);
}

View file

@ -16,6 +16,7 @@ struct GameScriptAnimations
bool MonkeyAutoJump; // Auto jump to monkey swing when pressing UP + ACTION beneath
bool OscillateHang; // Grab thin ledge animation from TR1 and 2
bool Pose; // Crossed arms AFK posing
bool Overhang; // Overhang functionality by Krys
static void Register(sol::state* lua);
};

View file

@ -19,6 +19,7 @@ constexpr auto RADIAN = 0.01745329252f;
constexpr auto ONE_DEGREE = 182;
constexpr auto PREDICTIVE_SCALE_FACTOR = 14;
constexpr auto WALL_SIZE = 1024;
constexpr auto WALL_MASK = WALL_SIZE - 1;
constexpr auto STEP_SIZE = WALL_SIZE / 4;
constexpr auto STOP_SIZE = WALL_SIZE / 2;
constexpr auto GRID_SNAP_SIZE = STEP_SIZE / 2;

View file

@ -164,6 +164,7 @@ CALL gen.bat</Command>
<ClInclude Include="Game\effects\footprint.h" />
<ClInclude Include="Game\Lara\lara_helpers.h" />
<ClInclude Include="Game\Lara\lara_jump.h" />
<ClInclude Include="Game\Lara\lara_overhang.h" />
<ClInclude Include="Game\Lara\lara_test_structs.h" />
<ClInclude Include="Objects\Generic\Object\burning_torch.h" />
<ClInclude Include="Objects\Generic\Object\polerope.h" />
@ -568,6 +569,7 @@ CALL gen.bat</Command>
<ClCompile Include="Game\Lara\lara_jump.cpp" />
<ClCompile Include="Game\Lara\lara_monkey.cpp" />
<ClCompile Include="Game\Lara\lara_objects.cpp" />
<ClCompile Include="Game\Lara\lara_overhang.cpp" />
<ClCompile Include="Game\Lara\lara_slide.cpp" />
<ClCompile Include="Game\Lara\lara_tests.cpp" />
<ClCompile Include="Game\effects\lightning.cpp" />

View file

@ -319,6 +319,7 @@
<ClCompile Include="Game\control\flipeffect.cpp" />
<ClCompile Include="Objects\Generic\Traps\traps.cpp" />
<ClCompile Include="Objects\Generic\Switches\switch.cpp" />
<ClCompile Include="Game\Lara\lara_overhang.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
@ -713,6 +714,7 @@
<ClInclude Include="Game\control\flipeffect.h" />
<ClInclude Include="Objects\Generic\Traps\traps.h" />
<ClInclude Include="Objects\Generic\Switches\switch.h" />
<ClInclude Include="Game\Lara\lara_overhang.h" />
<ClInclude Include="Game\Lara\lara_test_structs.h" />
</ItemGroup>
<ItemGroup>