mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-28 15:57:59 +03:00
Merge branch 'MontyTRC89:develop' into develop
This commit is contained in:
commit
c7c3451c1c
18 changed files with 108 additions and 83 deletions
|
@ -55,6 +55,7 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
|
||||||
* Changed Rome Hammer to not hurt player whilst deactivated.
|
* Changed Rome Hammer to not hurt player whilst deactivated.
|
||||||
* Changed Statue with blade damage, from 20 to 200.
|
* Changed Statue with blade damage, from 20 to 200.
|
||||||
* Changed sound effect that is triggered when using the `level.rumble` feature in a level. Sound effect now part of the default soundmap (ID 359) and additional hardcoded pitch shift has been removed.
|
* Changed sound effect that is triggered when using the `level.rumble` feature in a level. Sound effect now part of the default soundmap (ID 359) and additional hardcoded pitch shift has been removed.
|
||||||
|
* Changed hardcoded sound for RAISING_BLOCKS back to the soundID used in TRLE (ID 149)
|
||||||
* Changed Water sound condition to ShallowWater.
|
* Changed Water sound condition to ShallowWater.
|
||||||
* Enhanced Rolling Spindle detection to avoid them going down through pits.
|
* Enhanced Rolling Spindle detection to avoid them going down through pits.
|
||||||
* Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 )
|
* Enhanced Sentry Guns, with a new ItemFlags[3], to contain the ID of the inventory item that deactivates the sentry guns ( by default PUZZLE_ITEM5 )
|
||||||
|
|
|
@ -182,6 +182,10 @@ int FloorInfo::GetSurfaceHeight(int x, int z, bool isFloor) const
|
||||||
auto normal = tri.Plane.Normal();
|
auto normal = tri.Plane.Normal();
|
||||||
float relPlaneHeight = -((normal.x * sectorPoint.x) + (normal.z * sectorPoint.y)) / normal.y;
|
float relPlaneHeight = -((normal.x * sectorPoint.x) + (normal.z * sectorPoint.y)) / normal.y;
|
||||||
|
|
||||||
|
// Due to precision loss, we can't recover NO_HEIGHT constant from the plane, and must return original integer constant.
|
||||||
|
if (tri.Plane.D() == (float)NO_HEIGHT)
|
||||||
|
return NO_HEIGHT;
|
||||||
|
|
||||||
// Return sector floor or ceiling height. NOTE: Bridges ignored.
|
// Return sector floor or ceiling height. NOTE: Bridges ignored.
|
||||||
return (tri.Plane.D() + relPlaneHeight);
|
return (tri.Plane.D() + relPlaneHeight);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,13 +27,11 @@ using namespace TEN::Effects::Smoke;
|
||||||
|
|
||||||
constexpr auto ESCAPE_DIST = BLOCK(5);
|
constexpr auto ESCAPE_DIST = BLOCK(5);
|
||||||
constexpr auto STALK_DIST = BLOCK(3);
|
constexpr auto STALK_DIST = BLOCK(3);
|
||||||
constexpr auto REACHED_GOAL_RADIUS = 640;
|
constexpr auto REACHED_GOAL_RADIUS = BLOCK(0.625);
|
||||||
constexpr auto ATTACK_RANGE = SQUARE(BLOCK(3));
|
constexpr auto ATTACK_RANGE = SQUARE(BLOCK(3));
|
||||||
constexpr auto ESCAPE_CHANCE = 0x800;
|
constexpr auto ESCAPE_CHANCE = 0x800;
|
||||||
constexpr auto RECOVER_CHANCE = 0x100;
|
constexpr auto RECOVER_CHANCE = 0x100;
|
||||||
constexpr auto BIFF_AVOID_TURN = ANGLE(11.25f);
|
constexpr auto BIFF_AVOID_TURN = ANGLE(11.25f);
|
||||||
constexpr auto FEELER_DISTANCE = CLICK(2);
|
|
||||||
constexpr auto FEELER_ANGLE = ANGLE(45.0f);
|
|
||||||
constexpr auto CREATURE_AI_ROTATION_MAX = ANGLE(90.0f);
|
constexpr auto CREATURE_AI_ROTATION_MAX = ANGLE(90.0f);
|
||||||
constexpr auto CREATURE_JOINT_ROTATION_MAX = ANGLE(70.0f);
|
constexpr auto CREATURE_JOINT_ROTATION_MAX = ANGLE(70.0f);
|
||||||
|
|
||||||
|
@ -895,7 +893,7 @@ int CreatureCreature(short itemNumber)
|
||||||
{
|
{
|
||||||
auto* linked = &g_Level.Items[link];
|
auto* linked = &g_Level.Items[link];
|
||||||
|
|
||||||
if (link != itemNumber && linked != LaraItem && linked->Status == ITEM_ACTIVE && linked->HitPoints > 0) // TODO: deal with LaraItem global.
|
if (link != itemNumber && linked != LaraItem && linked->IsCreature() && linked->Status == ITEM_ACTIVE && linked->HitPoints > 0) // TODO: deal with LaraItem global.
|
||||||
{
|
{
|
||||||
int xDistance = abs(linked->Pose.Position.x - x);
|
int xDistance = abs(linked->Pose.Position.x - x);
|
||||||
int zDistance = abs(linked->Pose.Position.z - z);
|
int zDistance = abs(linked->Pose.Position.z - z);
|
||||||
|
@ -1043,7 +1041,7 @@ bool SearchLOT(LOTInfo* LOT, int depth)
|
||||||
if ((node->searchNumber & SEARCH_NUMBER) < (expand->searchNumber & SEARCH_NUMBER))
|
if ((node->searchNumber & SEARCH_NUMBER) < (expand->searchNumber & SEARCH_NUMBER))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (node->searchNumber & BLOCKED_SEARCH)
|
if (node->searchNumber & SEARCH_BLOCKED)
|
||||||
{
|
{
|
||||||
if ((node->searchNumber & SEARCH_NUMBER) == (expand->searchNumber & SEARCH_NUMBER))
|
if ((node->searchNumber & SEARCH_NUMBER) == (expand->searchNumber & SEARCH_NUMBER))
|
||||||
continue;
|
continue;
|
||||||
|
@ -1052,12 +1050,12 @@ bool SearchLOT(LOTInfo* LOT, int depth)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((node->searchNumber & SEARCH_NUMBER) == (expand->searchNumber & SEARCH_NUMBER) && !(expand->searchNumber & BLOCKED_SEARCH))
|
if ((node->searchNumber & SEARCH_NUMBER) == (expand->searchNumber & SEARCH_NUMBER) && !(expand->searchNumber & SEARCH_BLOCKED))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (g_Level.PathfindingBoxes[boxNumber].flags & LOT->BlockMask)
|
if (g_Level.PathfindingBoxes[boxNumber].flags & LOT->BlockMask)
|
||||||
{
|
{
|
||||||
expand->searchNumber = node->searchNumber | BLOCKED_SEARCH;
|
expand->searchNumber = node->searchNumber | SEARCH_BLOCKED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1557,7 +1555,7 @@ void CreatureAIInfo(ItemInfo* item, AI_INFO* AI)
|
||||||
AI->enemyZone |= BLOCKED;
|
AI->enemyZone |= BLOCKED;
|
||||||
}
|
}
|
||||||
else if (item->BoxNumber != NO_VALUE &&
|
else if (item->BoxNumber != NO_VALUE &&
|
||||||
creature->LOT.Node[item->BoxNumber].searchNumber == (creature->LOT.SearchNumber | BLOCKED_SEARCH))
|
creature->LOT.Node[item->BoxNumber].searchNumber == (creature->LOT.SearchNumber | SEARCH_BLOCKED))
|
||||||
{
|
{
|
||||||
AI->enemyZone |= BLOCKED;
|
AI->enemyZone |= BLOCKED;
|
||||||
}
|
}
|
||||||
|
@ -1786,7 +1784,7 @@ void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent)
|
||||||
auto* enemy = creature->Enemy;
|
auto* enemy = creature->Enemy;
|
||||||
auto* LOT = &creature->LOT;
|
auto* LOT = &creature->LOT;
|
||||||
|
|
||||||
if (item->BoxNumber == NO_VALUE || creature->LOT.Node[item->BoxNumber].searchNumber == (creature->LOT.SearchNumber | BLOCKED_SEARCH))
|
if (item->BoxNumber == NO_VALUE || creature->LOT.Node[item->BoxNumber].searchNumber == (creature->LOT.SearchNumber | SEARCH_BLOCKED))
|
||||||
creature->LOT.RequiredBox = NO_VALUE;
|
creature->LOT.RequiredBox = NO_VALUE;
|
||||||
|
|
||||||
if (creature->Mood != MoodType::Attack && creature->LOT.RequiredBox != NO_VALUE && !ValidBox(item, AI->zoneNumber, creature->LOT.TargetBox))
|
if (creature->Mood != MoodType::Attack && creature->LOT.RequiredBox != NO_VALUE && !ValidBox(item, AI->zoneNumber, creature->LOT.TargetBox))
|
||||||
|
@ -1909,7 +1907,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
int right = boxRight;
|
int right = boxRight;
|
||||||
int top = boxTop;
|
int top = boxTop;
|
||||||
int bottom = boxBottom;
|
int bottom = boxBottom;
|
||||||
int direction = ALL_CLIP;
|
int direction = CLIP_ALL;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -1949,7 +1947,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
if (target->z < (boxLeft + CLICK(2)))
|
if (target->z < (boxLeft + CLICK(2)))
|
||||||
target->z = boxLeft + CLICK(2);
|
target->z = boxLeft + CLICK(2);
|
||||||
|
|
||||||
if (direction & SECONDARY_CLIP)
|
if (direction & CLIP_SECONDARY)
|
||||||
return TARGET_TYPE::SECONDARY_TARGET;
|
return TARGET_TYPE::SECONDARY_TARGET;
|
||||||
|
|
||||||
if (boxTop > top)
|
if (boxTop > top)
|
||||||
|
@ -1964,10 +1962,10 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
{
|
{
|
||||||
target->z = (right - CLICK(2));
|
target->z = (right - CLICK(2));
|
||||||
|
|
||||||
if (direction != ALL_CLIP)
|
if (direction != CLIP_ALL)
|
||||||
return TARGET_TYPE::SECONDARY_TARGET;
|
return TARGET_TYPE::SECONDARY_TARGET;
|
||||||
|
|
||||||
direction |= (ALL_CLIP | SECONDARY_CLIP);
|
direction |= (CLIP_ALL | CLIP_SECONDARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (item->Pose.Position.z > boxRight && direction != CLIP_LEFT)
|
else if (item->Pose.Position.z > boxRight && direction != CLIP_LEFT)
|
||||||
|
@ -1979,7 +1977,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
if (target->z > boxRight - CLICK(2))
|
if (target->z > boxRight - CLICK(2))
|
||||||
target->z = boxRight - CLICK(2);
|
target->z = boxRight - CLICK(2);
|
||||||
|
|
||||||
if (direction & SECONDARY_CLIP)
|
if (direction & CLIP_SECONDARY)
|
||||||
return TARGET_TYPE::SECONDARY_TARGET;
|
return TARGET_TYPE::SECONDARY_TARGET;
|
||||||
|
|
||||||
if (boxTop > top)
|
if (boxTop > top)
|
||||||
|
@ -1994,10 +1992,10 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
{
|
{
|
||||||
target->z = left + CLICK(2);
|
target->z = left + CLICK(2);
|
||||||
|
|
||||||
if (direction != ALL_CLIP)
|
if (direction != CLIP_ALL)
|
||||||
return TARGET_TYPE::SECONDARY_TARGET;
|
return TARGET_TYPE::SECONDARY_TARGET;
|
||||||
|
|
||||||
direction |= (ALL_CLIP | SECONDARY_CLIP);
|
direction |= (CLIP_ALL | CLIP_SECONDARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2010,7 +2008,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
if (target->x < boxTop + CLICK(2))
|
if (target->x < boxTop + CLICK(2))
|
||||||
target->x = boxTop + CLICK(2);
|
target->x = boxTop + CLICK(2);
|
||||||
|
|
||||||
if (direction & SECONDARY_CLIP)
|
if (direction & CLIP_SECONDARY)
|
||||||
return TARGET_TYPE::SECONDARY_TARGET;
|
return TARGET_TYPE::SECONDARY_TARGET;
|
||||||
|
|
||||||
if (boxLeft > left)
|
if (boxLeft > left)
|
||||||
|
@ -2025,10 +2023,10 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
{
|
{
|
||||||
target->x = bottom - CLICK(2);
|
target->x = bottom - CLICK(2);
|
||||||
|
|
||||||
if (direction != ALL_CLIP)
|
if (direction != CLIP_ALL)
|
||||||
return TARGET_TYPE::SECONDARY_TARGET;
|
return TARGET_TYPE::SECONDARY_TARGET;
|
||||||
|
|
||||||
direction |= (ALL_CLIP | SECONDARY_CLIP);
|
direction |= (CLIP_ALL | CLIP_SECONDARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (item->Pose.Position.x > boxBottom && direction != CLIP_TOP)
|
else if (item->Pose.Position.x > boxBottom && direction != CLIP_TOP)
|
||||||
|
@ -2040,7 +2038,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
if (target->x > (boxBottom - CLICK(2)))
|
if (target->x > (boxBottom - CLICK(2)))
|
||||||
target->x = (boxBottom - CLICK(2));
|
target->x = (boxBottom - CLICK(2));
|
||||||
|
|
||||||
if (direction & SECONDARY_CLIP)
|
if (direction & CLIP_SECONDARY)
|
||||||
return TARGET_TYPE::SECONDARY_TARGET;
|
return TARGET_TYPE::SECONDARY_TARGET;
|
||||||
|
|
||||||
if (boxLeft > left)
|
if (boxLeft > left)
|
||||||
|
@ -2055,10 +2053,10 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
{
|
{
|
||||||
target->x = top + CLICK(2);
|
target->x = top + CLICK(2);
|
||||||
|
|
||||||
if (direction != ALL_CLIP)
|
if (direction != CLIP_ALL)
|
||||||
return TARGET_TYPE::SECONDARY_TARGET;
|
return TARGET_TYPE::SECONDARY_TARGET;
|
||||||
|
|
||||||
direction |= (ALL_CLIP | SECONDARY_CLIP);
|
direction |= (CLIP_ALL | CLIP_SECONDARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2069,7 +2067,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
{
|
{
|
||||||
target->z = LOT->Target.z;
|
target->z = LOT->Target.z;
|
||||||
}
|
}
|
||||||
else if (!(direction & SECONDARY_CLIP))
|
else if (!(direction & CLIP_SECONDARY))
|
||||||
{
|
{
|
||||||
if (target->z < (boxLeft + CLICK(2)))
|
if (target->z < (boxLeft + CLICK(2)))
|
||||||
target->z = boxLeft + CLICK(2);
|
target->z = boxLeft + CLICK(2);
|
||||||
|
@ -2081,7 +2079,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
{
|
{
|
||||||
target->x = LOT->Target.x;
|
target->x = LOT->Target.x;
|
||||||
}
|
}
|
||||||
else if (!(direction & SECONDARY_CLIP))
|
else if (!(direction & CLIP_SECONDARY))
|
||||||
{
|
{
|
||||||
if (target->x < (boxTop + CLICK(2)))
|
if (target->x < (boxTop + CLICK(2)))
|
||||||
target->x = boxTop + CLICK(2);
|
target->x = boxTop + CLICK(2);
|
||||||
|
@ -2098,7 +2096,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
break;
|
break;
|
||||||
} while (boxNumber != NO_VALUE);
|
} while (boxNumber != NO_VALUE);
|
||||||
|
|
||||||
if (!(direction & SECONDARY_CLIP))
|
if (!(direction & CLIP_SECONDARY))
|
||||||
{
|
{
|
||||||
if (target->z < (boxLeft + CLICK(2)))
|
if (target->z < (boxLeft + CLICK(2)))
|
||||||
target->z = boxLeft + CLICK(2);
|
target->z = boxLeft + CLICK(2);
|
||||||
|
@ -2106,7 +2104,7 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
|
||||||
target->z = boxRight - CLICK(2);
|
target->z = boxRight - CLICK(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(direction & SECONDARY_CLIP))
|
if (!(direction & CLIP_SECONDARY))
|
||||||
{
|
{
|
||||||
if (target->x < (boxTop + CLICK(2)))
|
if (target->x < (boxTop + CLICK(2)))
|
||||||
target->x = boxTop + CLICK(2);
|
target->x = boxTop + CLICK(2);
|
||||||
|
@ -2184,6 +2182,7 @@ bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
float stepDist = BLOCK(0.92f);
|
float stepDist = BLOCK(0.92f);
|
||||||
|
|
||||||
int vPos = item.Pose.Position.y;
|
int vPos = item.Pose.Position.y;
|
||||||
auto pointCollA = GetPointCollision(item, item.Pose.Orientation.y, stepDist);
|
auto pointCollA = GetPointCollision(item, item.Pose.Orientation.y, stepDist);
|
||||||
auto pointCollB = GetPointCollision(item, item.Pose.Orientation.y, stepDist * 2);
|
auto pointCollB = GetPointCollision(item, item.Pose.Orientation.y, stepDist * 2);
|
||||||
|
@ -2196,7 +2195,9 @@ bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType)
|
||||||
if (item.BoxNumber == creature.Enemy->BoxNumber ||
|
if (item.BoxNumber == creature.Enemy->BoxNumber ||
|
||||||
vPos >= (pointCollA.GetFloorHeight() - STEPUP_HEIGHT) ||
|
vPos >= (pointCollA.GetFloorHeight() - STEPUP_HEIGHT) ||
|
||||||
vPos >= (pointCollB.GetFloorHeight() + CLICK(1)) ||
|
vPos >= (pointCollB.GetFloorHeight() + CLICK(1)) ||
|
||||||
vPos <= (pointCollB.GetFloorHeight() - CLICK(1)))
|
vPos <= (pointCollB.GetFloorHeight() - CLICK(1)) ||
|
||||||
|
pointCollA.GetSector().PathfindingBoxID == NO_VALUE ||
|
||||||
|
pointCollB.GetSector().PathfindingBoxID == NO_VALUE)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2208,7 +2209,10 @@ bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType)
|
||||||
vPos >= (pointCollA.GetFloorHeight() - STEPUP_HEIGHT) ||
|
vPos >= (pointCollA.GetFloorHeight() - STEPUP_HEIGHT) ||
|
||||||
vPos >= (pointCollB.GetFloorHeight() - STEPUP_HEIGHT) ||
|
vPos >= (pointCollB.GetFloorHeight() - STEPUP_HEIGHT) ||
|
||||||
vPos >= (pointCollC.GetFloorHeight() + CLICK(1)) ||
|
vPos >= (pointCollC.GetFloorHeight() + CLICK(1)) ||
|
||||||
vPos <= (pointCollC.GetFloorHeight() - CLICK(1)))
|
vPos <= (pointCollC.GetFloorHeight() - CLICK(1)) ||
|
||||||
|
pointCollA.GetSector().PathfindingBoxID == NO_VALUE ||
|
||||||
|
pointCollB.GetSector().PathfindingBoxID == NO_VALUE ||
|
||||||
|
pointCollC.GetSector().PathfindingBoxID == NO_VALUE)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,29 +55,33 @@ struct OVERLAP
|
||||||
|
|
||||||
#define CreatureEffectFunction short(int x, int y, int z, short speed, short yRot, short roomNumber)
|
#define CreatureEffectFunction short(int x, int y, int z, short speed, short yRot, short roomNumber)
|
||||||
|
|
||||||
constexpr auto BOX_BLOCKED = (1 << 14); // unpassable for other enemies, always set for movable blocks & closed doors
|
// TODO: Following constants can be moved to new flag enums for improved clarity.
|
||||||
constexpr auto BOX_LAST = (1 << 15); // unpassable by large enemies (T-Rex, Centaur, etc), always set behind doors
|
|
||||||
|
|
||||||
constexpr auto REVERSE = 0x4000;
|
|
||||||
constexpr auto BLOCKABLE = 0x8000;
|
constexpr auto BLOCKABLE = 0x8000;
|
||||||
constexpr auto BLOCKED = 0x4000;
|
constexpr auto BLOCKED = 0x4000;
|
||||||
constexpr auto SEARCH_NUMBER = 0x7FFF;
|
|
||||||
constexpr auto BLOCKED_SEARCH = 0x8000;
|
constexpr auto SEARCH_NUMBER = INT_MAX;
|
||||||
constexpr auto BOX_JUMP = 0x800;
|
constexpr auto SEARCH_BLOCKED = (1 << 31);
|
||||||
constexpr auto BOX_MONKEY = 0x2000;
|
|
||||||
|
constexpr auto BOX_JUMP = 0x800;
|
||||||
|
constexpr auto BOX_MONKEY = 0x2000;
|
||||||
constexpr auto BOX_END_BIT = 0x8000;
|
constexpr auto BOX_END_BIT = 0x8000;
|
||||||
constexpr auto EXPAND_LEFT = 0x1;
|
|
||||||
constexpr auto EXPAND_RIGHT = 0x2;
|
constexpr auto EXPAND_LEFT = 0x1;
|
||||||
constexpr auto EXPAND_TOP = 0x4;
|
constexpr auto EXPAND_RIGHT = 0x2;
|
||||||
|
constexpr auto EXPAND_TOP = 0x4;
|
||||||
constexpr auto EXPAND_BOTTOM = 0x8;
|
constexpr auto EXPAND_BOTTOM = 0x8;
|
||||||
|
|
||||||
constexpr auto NO_FLYING = 0;
|
constexpr auto NO_FLYING = 0;
|
||||||
constexpr auto FLY_ZONE = 0x2000;
|
constexpr auto FLY_ZONE = 0x2000;
|
||||||
constexpr auto CLIP_LEFT = 0x1;
|
|
||||||
constexpr auto CLIP_RIGHT = 0x2;
|
constexpr auto CLIP_LEFT = 0x1;
|
||||||
constexpr auto CLIP_TOP = 0x4;
|
constexpr auto CLIP_RIGHT = 0x2;
|
||||||
|
constexpr auto CLIP_TOP = 0x4;
|
||||||
constexpr auto CLIP_BOTTOM = 0x8;
|
constexpr auto CLIP_BOTTOM = 0x8;
|
||||||
constexpr auto SECONDARY_CLIP = 0x10;
|
constexpr auto CLIP_ALL = (CLIP_LEFT | CLIP_RIGHT | CLIP_TOP | CLIP_BOTTOM);
|
||||||
constexpr auto ALL_CLIP = (CLIP_LEFT | CLIP_RIGHT | CLIP_TOP | CLIP_BOTTOM);
|
|
||||||
|
constexpr auto CLIP_SECONDARY = 0x10;
|
||||||
|
|
||||||
void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent);
|
void GetCreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent);
|
||||||
void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent);
|
void CreatureMood(ItemInfo* item, AI_INFO* AI, bool isViolent);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
#include "Game/Setup.h"
|
#include "Game/Setup.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
|
#include "Specific/trutils.h"
|
||||||
|
|
||||||
using namespace TEN::Collision::Room;
|
using namespace TEN::Collision::Room;
|
||||||
|
|
||||||
|
@ -205,6 +206,41 @@ void InitializeSlot(short itemNumber, bool makeTarget)
|
||||||
SlotsUsed++;
|
SlotsUsed++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TargetNearestEntity(ItemInfo& item, const std::vector<GAME_OBJECT_ID>& keyObjectIds, bool ignoreKeyObjectIds)
|
||||||
|
{
|
||||||
|
auto& creature = *GetCreatureInfo(&item);
|
||||||
|
|
||||||
|
float closestDistSqr = INFINITY;
|
||||||
|
for (auto& target : ActiveCreatures)
|
||||||
|
{
|
||||||
|
auto& targetItem = g_Level.Items[target->ItemNumber];
|
||||||
|
if (targetItem.Index == item.Index)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Ignore or specifically target key object IDs.
|
||||||
|
if (!keyObjectIds.empty() && (ignoreKeyObjectIds ? Contains(keyObjectIds, targetItem.ObjectNumber) : !Contains(keyObjectIds, targetItem.ObjectNumber)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (&targetItem != &item && targetItem.HitPoints > 0 && targetItem.Status != ITEM_INVISIBLE)
|
||||||
|
{
|
||||||
|
float distSqr = Vector3i::DistanceSquared(item.Pose.Position, targetItem.Pose.Position);
|
||||||
|
if (distSqr < closestDistSqr)
|
||||||
|
{
|
||||||
|
creature.Enemy = &targetItem;
|
||||||
|
closestDistSqr = distSqr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle player as special case.
|
||||||
|
if (!keyObjectIds.empty() && (ignoreKeyObjectIds ? Contains(keyObjectIds, ID_LARA) : !Contains(keyObjectIds, ID_LARA)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
float distToPlayerSqr = Vector3i::DistanceSquared(item.Pose.Position, LaraItem->Pose.Position);
|
||||||
|
if (distToPlayerSqr < closestDistSqr)
|
||||||
|
creature.Enemy = LaraItem;
|
||||||
|
}
|
||||||
|
|
||||||
void SetEntityTarget(short itemNum, short target)
|
void SetEntityTarget(short itemNum, short target)
|
||||||
{
|
{
|
||||||
auto* item = &g_Level.Items[itemNum];
|
auto* item = &g_Level.Items[itemNum];
|
||||||
|
|
|
@ -7,6 +7,7 @@ void InitializeLOTarray(int allocMem);
|
||||||
bool EnableEntityAI(short itemNum, bool always, bool makeTarget = true);
|
bool EnableEntityAI(short itemNum, bool always, bool makeTarget = true);
|
||||||
void InitializeSlot(short itemNum, bool makeTarget);
|
void InitializeSlot(short itemNum, bool makeTarget);
|
||||||
void SetEntityTarget(short itemNum, short target);
|
void SetEntityTarget(short itemNum, short target);
|
||||||
|
void TargetNearestEntity(ItemInfo& item, const std::vector<GAME_OBJECT_ID>& keyObjectIds = {}, bool ignoreKeyObjectIds = true);
|
||||||
void DisableEntityAI(short itemNumber);
|
void DisableEntityAI(short itemNumber);
|
||||||
void ClearLOT(LOTInfo* LOT);
|
void ClearLOT(LOTInfo* LOT);
|
||||||
void CreateZone(ItemInfo* item);
|
void CreateZone(ItemInfo* item);
|
||||||
|
|
|
@ -339,7 +339,7 @@ void Antitrigger(short const value, short const flags)
|
||||||
item->ItemFlags[1] = 100;
|
item->ItemFlags[1] = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
item->Flags &= ~(CODE_BITS | REVERSE);
|
item->Flags &= ~(CODE_BITS | IFLAG_REVERSE);
|
||||||
|
|
||||||
if (flags & ONESHOT)
|
if (flags & ONESHOT)
|
||||||
item->Flags |= ATONESHOT;
|
item->Flags |= ATONESHOT;
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
#include "Game/Setup.h"
|
#include "Game/Setup.h"
|
||||||
#include "Specific/level.h"
|
#include "Specific/level.h"
|
||||||
#include "Specific/trutils.h"
|
|
||||||
|
|
||||||
using namespace TEN::Collision::Point;
|
using namespace TEN::Collision::Point;
|
||||||
using namespace TEN::Utils;
|
using namespace TEN::Utils;
|
||||||
|
@ -18,31 +17,6 @@ CreatureInfo* GetCreatureInfo(ItemInfo* item)
|
||||||
return (CreatureInfo*)item->Data;
|
return (CreatureInfo*)item->Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector<GAME_OBJECT_ID>& keyObjectIds, bool ignoreKeyObjectIds)
|
|
||||||
{
|
|
||||||
float closestDistSqr = INFINITY;
|
|
||||||
for (int itemNumber = 0; itemNumber < g_Level.NumItems; itemNumber++)
|
|
||||||
{
|
|
||||||
auto* targetItem = &g_Level.Items[itemNumber];
|
|
||||||
if (targetItem == nullptr || targetItem->Index == item->Index)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Ignore or specifically target key object IDs.
|
|
||||||
if (ignoreKeyObjectIds ? Contains(keyObjectIds, targetItem->ObjectNumber) : !Contains(keyObjectIds, targetItem->ObjectNumber))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (targetItem != item && targetItem->HitPoints > 0 && targetItem->Status != ITEM_INVISIBLE)
|
|
||||||
{
|
|
||||||
float distSqr = Vector3i::DistanceSquared(item->Pose.Position, targetItem->Pose.Position);
|
|
||||||
if (distSqr < closestDistSqr)
|
|
||||||
{
|
|
||||||
creature->Enemy = targetItem;
|
|
||||||
closestDistSqr = distSqr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, bool canFloat)
|
bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, bool canFloat)
|
||||||
{
|
{
|
||||||
auto projectedPos = Geometry::TranslatePoint(item.Pose.Position, dir, dist);
|
auto projectedPos = Geometry::TranslatePoint(item.Pose.Position, dir, dist);
|
||||||
|
|
|
@ -18,5 +18,4 @@ enum LaraMeshMask
|
||||||
};
|
};
|
||||||
|
|
||||||
CreatureInfo* GetCreatureInfo(ItemInfo* item);
|
CreatureInfo* GetCreatureInfo(ItemInfo* item);
|
||||||
void TargetNearestEntity(ItemInfo* item, CreatureInfo* creature, const std::vector<GAME_OBJECT_ID>& keyObjectIds = {}, bool ignoreKeyObjectIds = true);
|
|
||||||
bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, bool canFloat);
|
bool IsNextSectorValid(const ItemInfo& item, const Vector3& dir, float dist, bool canFloat);
|
||||||
|
|
|
@ -411,7 +411,7 @@ namespace TEN::Entities::Doors
|
||||||
|
|
||||||
void ShutThatDoor(DOORPOS_DATA* doorPos, DOOR_DATA* dd)
|
void ShutThatDoor(DOORPOS_DATA* doorPos, DOOR_DATA* dd)
|
||||||
{
|
{
|
||||||
static const auto WALL_PLANE = Plane(-Vector3::UnitY, -CLICK(127));
|
static const auto WALL_PLANE = Plane(-Vector3::UnitY, (float)NO_HEIGHT);
|
||||||
|
|
||||||
FloorInfo* floor = doorPos->floor;
|
FloorInfo* floor = doorPos->floor;
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ namespace TEN::Entities::Creatures::TR3
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// NOTE: Ignores other small dinosaurs.
|
// NOTE: Ignores other small dinosaurs.
|
||||||
TargetNearestEntity(&item, &creature, RaptorIgnoredObjectIds);
|
TargetNearestEntity(item, RaptorIgnoredObjectIds);
|
||||||
|
|
||||||
AI_INFO ai;
|
AI_INFO ai;
|
||||||
if (item.AIBits)
|
if (item.AIBits)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "Game/animation.h"
|
#include "Game/animation.h"
|
||||||
#include "Game/control/box.h"
|
#include "Game/control/box.h"
|
||||||
|
#include "Game/control/lot.h"
|
||||||
#include "Game/effects/effects.h"
|
#include "Game/effects/effects.h"
|
||||||
#include "Game/effects/tomb4fx.h"
|
#include "Game/effects/tomb4fx.h"
|
||||||
#include "Game/Lara/lara.h"
|
#include "Game/Lara/lara.h"
|
||||||
|
@ -205,7 +206,7 @@ namespace TEN::Entities::Creatures::TR3
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TargetNearestEntity(&item, &creature, SealMutantAttackTargetObjectIds, false);
|
TargetNearestEntity(item, SealMutantAttackTargetObjectIds, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AI_INFO ai;
|
AI_INFO ai;
|
||||||
|
|
|
@ -95,7 +95,7 @@ namespace TEN::Entities::Creatures::TR3
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TargetNearestEntity(item, creature, FlamethrowerTargetIds, false);
|
TargetNearestEntity(*item, FlamethrowerTargetIds, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AI_INFO AI;
|
AI_INFO AI;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "Game/animation.h"
|
#include "Game/animation.h"
|
||||||
#include "Game/control/control.h"
|
#include "Game/control/control.h"
|
||||||
|
#include "Game/control/lot.h"
|
||||||
#include "Game/effects/effects.h"
|
#include "Game/effects/effects.h"
|
||||||
#include "Game/itemdata/creature_info.h"
|
#include "Game/itemdata/creature_info.h"
|
||||||
#include "Game/items.h"
|
#include "Game/items.h"
|
||||||
|
@ -286,7 +287,7 @@ namespace TEN::Entities::TR4
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TargetNearestEntity(item, creature);
|
TargetNearestEntity(*item);
|
||||||
}
|
}
|
||||||
|
|
||||||
AI_INFO ai;
|
AI_INFO ai;
|
||||||
|
|
|
@ -93,7 +93,7 @@ namespace TEN::Entities::Generic
|
||||||
|
|
||||||
void ShakeRaisingBlock(ItemInfo* item)
|
void ShakeRaisingBlock(ItemInfo* item)
|
||||||
{
|
{
|
||||||
SoundEffect(SFX_TR4_RAISING_BLOCK, &item->Pose);
|
SoundEffect(SFX_TR4_RAISING_BLOCK_2, &item->Pose);
|
||||||
|
|
||||||
if (item->TriggerFlags == 0)
|
if (item->TriggerFlags == 0)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -128,7 +128,7 @@ namespace TEN::Entities::Generic
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SoundEffect(SFX_TR4_RUMBLE_NEXTDOOR, &item->Pose);
|
SoundEffect(SFX_TR4_RAISING_BLOCK_2, &item->Pose);
|
||||||
item->Pose.Position.y -= 4;
|
item->Pose.Position.y -= 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ namespace TEN::Entities::Generic
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SoundEffect(SFX_TR4_RUMBLE_NEXTDOOR, &item->Pose);
|
SoundEffect(SFX_TR4_RAISING_BLOCK_2, &item->Pose);
|
||||||
item->Pose.Position.y += 4;
|
item->Pose.Position.y += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ void SmashObject(short itemNumber)
|
||||||
|
|
||||||
auto* box = &g_Level.PathfindingBoxes[room->Sectors[sector].PathfindingBoxID];
|
auto* box = &g_Level.PathfindingBoxes[room->Sectors[sector].PathfindingBoxID];
|
||||||
if (box->flags & 0x8000)
|
if (box->flags & 0x8000)
|
||||||
box->flags &= ~BOX_BLOCKED;
|
box->flags &= ~BLOCKED;
|
||||||
|
|
||||||
SoundEffect(SFX_TR5_SMASH_GLASS, &item->Pose);
|
SoundEffect(SFX_TR5_SMASH_GLASS, &item->Pose);
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,7 @@ enum SOUND_EFFECTS
|
||||||
SFX_TR4_LARA_DEATH3 = 146,
|
SFX_TR4_LARA_DEATH3 = 146,
|
||||||
SFX_TR4_ROLLING_BALL = 147,
|
SFX_TR4_ROLLING_BALL = 147,
|
||||||
SFX_TR4_RAISING_BLOCK = 148,
|
SFX_TR4_RAISING_BLOCK = 148,
|
||||||
SFX_TR4_RUMBLE_NEXTDOOR = 149,
|
SFX_TR4_RAISING_BLOCK_2 = 149,
|
||||||
SFX_TR4_LOOP_FOR_SMALL_FIRES = 150,
|
SFX_TR4_LOOP_FOR_SMALL_FIRES = 150,
|
||||||
SFX_TR4_CHAINS_LIBRARY = 151,
|
SFX_TR4_CHAINS_LIBRARY = 151,
|
||||||
SFX_TR4_VEHICLE_JEEP_START = 152,
|
SFX_TR4_VEHICLE_JEEP_START = 152,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue