Electric Cleaner with vectors adngel (#1005)

* Add cleaner code;

* Do smooth turns

* Revert acceleration (not working properly yet)

* Update cleaner.cpp

* Fix AdjustStopperFlag function, modify turn speed

* Move electric cleaner into namespace

* Cleaning cleaner first pass

* Demagic turn tolerance, use bools

* Update ElectricCleaner.cpp

* Revert smooth turns

* Format code according to conventions, rename function

* cleaner update

* Updated

* Updated OCB to flag data.

* Formula simplified

* restored original radius

I had reduced while I was working on it, but that's not needed anymore.

* Update comment

* Temporary Fix: Method to detect pushables.

* Feedback applied

* Revert primitive variable from auto to float

---------

Co-authored-by: Troye <woopstombraider@gmail.com>
Co-authored-by: Lwmte <3331699+Lwmte@users.noreply.github.com>
Co-authored-by: Sezz <sezzary@outlook.com>
Co-authored-by: Kubsy <80340234+Kubsy@users.noreply.github.com>
This commit is contained in:
Adngel 2023-02-20 14:26:16 +01:00 committed by GitHub
parent 2a4404effe
commit 302eb9c93b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 475 additions and 8 deletions

View file

@ -168,6 +168,11 @@ CollisionResult GetCollision(int x, int y, int z, short roomNumber)
return result; return result;
} }
CollisionResult GetCollision(const GameVector& point)
{
return GetCollision(point.x, point.y, point.z, point.RoomNumber);
}
// A reworked legacy GetFloorHeight() function which writes data // A reworked legacy GetFloorHeight() function which writes data
// into a special CollisionResult struct instead of global variables. // into a special CollisionResult struct instead of global variables.
// It writes for both floor and ceiling heights at the same coordinates, meaning it should be used // It writes for both floor and ceiling heights at the same coordinates, meaning it should be used

View file

@ -126,6 +126,7 @@ CollisionResult GetCollision(ItemInfo* item);
CollisionResult GetCollision(ItemInfo* item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); CollisionResult GetCollision(ItemInfo* item, short headingAngle, float forward, float down = 0.0f, float right = 0.0f);
CollisionResult GetCollision(Vector3i pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f); CollisionResult GetCollision(Vector3i pos, int roomNumber, short headingAngle, float forward, float down = 0.0f, float right = 0.0f);
CollisionResult GetCollision(int x, int y, int z, short roomNumber); CollisionResult GetCollision(int x, int y, int z, short roomNumber);
CollisionResult GetCollision(const GameVector& point);
CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z); CollisionResult GetCollision(FloorInfo* floor, int x, int y, int z);
void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offset, bool resetRoom = false); void GetCollisionInfo(CollisionInfo* coll, ItemInfo* item, const Vector3i& offset, bool resetRoom = false);

View file

@ -2081,21 +2081,21 @@ TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT)
return TARGET_TYPE::NO_TARGET; return TARGET_TYPE::NO_TARGET;
} }
void AdjustStopperFlag(ItemInfo* item, int direction, bool set) void AdjustStopperFlag(ItemInfo* item, int direction)
{ {
int x = item->Pose.Position.x; int x = item->Pose.Position.x;
int z = item->Pose.Position.z; int z = item->Pose.Position.z;
auto* room = &g_Level.Rooms[item->RoomNumber]; auto* room = &g_Level.Rooms[item->RoomNumber];
auto* floor = GetSector(room, x - room->x, z - room->z); auto* floor = GetSector(room, x - room->x, z - room->z);
floor->Stopper = set; floor->Stopper = !floor->Stopper;
x = item->Pose.Position.x + SECTOR(1) * phd_sin(direction); x = item->Pose.Position.x + SECTOR(1) * phd_sin(direction);
z = item->Pose.Position.z + SECTOR(1) * phd_cos(direction); z = item->Pose.Position.z + SECTOR(1) * phd_cos(direction);
room = &g_Level.Rooms[GetCollision(x, item->Pose.Position.y, z, item->RoomNumber).RoomNumber]; room = &g_Level.Rooms[GetCollision(x, item->Pose.Position.y, z, item->RoomNumber).RoomNumber];
floor = GetSector(room, x - room->x, z - room->z); floor = GetSector(room, x - room->x, z - room->z);
floor->Stopper = set; floor->Stopper = !floor->Stopper;
} }
void InitialiseItemBoxData() void InitialiseItemBoxData()

View file

@ -187,7 +187,7 @@ void CreatureAIInfo(ItemInfo* item, AI_INFO* AI);
TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT); TARGET_TYPE CalculateTarget(Vector3i* target, ItemInfo* item, LOTInfo* LOT);
bool CreatureAnimation(short itemNumber, short angle, short tilt); bool CreatureAnimation(short itemNumber, short angle, short tilt);
void CreatureHealth(ItemInfo* item); void CreatureHealth(ItemInfo* item);
void AdjustStopperFlag(ItemInfo* item, int direction, bool set); void AdjustStopperFlag(ItemInfo* item, int direction);
void InitialiseItemBoxData(); void InitialiseItemBoxData();
bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType); bool CanCreatureJump(ItemInfo& item, JumpDistance jumpDistType);

View file

@ -0,0 +1,422 @@
#include "framework.h"
#include "Objects/TR3/Trap/ElectricCleaner.h"
#include "Game/collision/collide_item.h"
#include "Game/control/box.h"
#include "Game/effects/item_fx.h"
#include "Game/effects/spark.h"
#include "Game/effects/tomb4fx.h"
#include "Game/Lara/lara_helpers.h"
#include "Specific/setup.h"
using namespace TEN::Effects::Items;
using namespace TEN::Effects::Spark;
// ItemFlags[0]: Rotation speed and heading angle.
// ItemFlags[1]: Flags, each bit is used to check the status of a flag
// b0: flagDoDetection
// b1: flagTurnRight
// b2: flagPriorityForward
// b3: flagAntiClockWiseOrder
// b4: flagStopAfterKill - If true the cleaner will stop when kills Lara.
// ItemFlags[2]: Movement velocity.
// ItemFlags[3, 4, 5]: Counters for dynamic lights and sparks.
// ItemFlags[6]: Goal direction angle.
// OCB:
// 0: Stop after killing the player.
// Anything else: Don't stop after killing the player.
namespace TEN::Entities::Traps
{
constexpr auto ELECTRIC_CLEANER_VELOCITY = BLOCK(1 / 16.0f);
constexpr auto ELECTRIC_CLEANER_TURN_RATE = 1024;
const auto ElectricCleanerHarmJoints = std::vector<unsigned int>{ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
std::vector <ItemInfo*> MyPushablesList = {};
void InitialiseElectricCleaner(short itemNumber)
{
auto& item = g_Level.Items[itemNumber];
// Align to the middle of the block.
item.Pose.Position.x = (item.Pose.Position.x & ~WALL_MASK) | (int)BLOCK(0.5f);
item.Pose.Position.z = (item.Pose.Position.z & ~WALL_MASK) | (int)BLOCK(0.5f);
// Init flags.
item.ItemFlags[0] = ELECTRIC_CLEANER_TURN_RATE;
item.ItemFlags[1] = 0;
item.ItemFlags[2] = ELECTRIC_CLEANER_VELOCITY;
item.ItemFlags[6] = item.Pose.Orientation.y;
item.Collidable = true;
if (item.TriggerFlags)
item.ItemFlags[1] &= ~(1 << 4); // Turn off 1st bit for flagStopAfterKill.
else
item.ItemFlags[1] |= (1 << 4); // Turn on 1st bit for flagStopAfterKill.
CollectLevelPushables(MyPushablesList);
}
void ElectricCleanerControl(short itemNumber)
{
auto& item = g_Level.Items[itemNumber];
auto& object = Objects[item.ObjectNumber];
auto& rotationVel = item.ItemFlags[0];
auto& moveVel = item.ItemFlags[2];
auto& goalAngle = item.ItemFlags[6];
if (!TriggerActive(&item))
{
if (moveVel > 0)
{
moveVel = 0;
SoundEffect(SFX_TR3_CLEANER_FUSEBOX, &item.Pose);
}
return;
}
if (moveVel <= 0)
return;
auto angleDifference = abs(TO_RAD(goalAngle) - TO_RAD(item.Pose.Orientation.y));
bool flagDoDetection = ((item.ItemFlags[1] & (1 << 0)) != 0);
bool flagTurnRight = ((item.ItemFlags[1] & (1 << 1)) != 0);
bool flagPriorityForward = ((item.ItemFlags[1] & (1 << 2)) != 0);
bool flagAntiClockWiseOrder = ((item.ItemFlags[1] & (1 << 3)) != 0);
auto col = GetCollision(item.Pose.Position.x, item.Pose.Position.y, item.Pose.Position.z, item.RoomNumber);
float yaw = TO_RAD(item.Pose.Orientation.y);
auto forwardDirection = Vector3(sin(yaw), 0, cos(yaw));
forwardDirection.Normalize();
auto rightDirection = Vector3(cos(yaw), 0, -sin(yaw));
rightDirection.Normalize();
if (angleDifference > TO_RAD(rotationVel))
{
if (flagTurnRight)
item.Pose.Orientation.y -= rotationVel;
else
item.Pose.Orientation.y += rotationVel;
// Recalculate new difference to check if we should force align with axis for safety check.
angleDifference = abs(TO_RAD(goalAngle) - TO_RAD(item.Pose.Orientation.y));
if (angleDifference <= TO_RAD(rotationVel))
item.Pose.Orientation.y = goalAngle;
}
else
{
if (flagDoDetection &&
(item.Pose.Position.x & WALL_MASK) == BLOCK(0.5f) &&
(item.Pose.Position.z & WALL_MASK) == BLOCK(0.5f))
{
//Do triggers
TestTriggers(&item, true);
//Search for next direction
Vector3 NewDirection;
if (flagPriorityForward)
{
if (flagAntiClockWiseOrder) //Forward Right Left
NewDirection = ElectricCleanerSearchDirections(item, forwardDirection, rightDirection, -rightDirection);
else //Forward Left Right
NewDirection = ElectricCleanerSearchDirections(item, forwardDirection, -rightDirection, rightDirection);
}
else
{
if (flagAntiClockWiseOrder) //Right Forward Left
NewDirection = ElectricCleanerSearchDirections(item, rightDirection, forwardDirection, -rightDirection);
else //Left Forward Right
NewDirection = ElectricCleanerSearchDirections(item, -rightDirection, forwardDirection, rightDirection);
}
if (NewDirection == Vector3::Zero) //Return back. (We already know is a valid one because it came from there).
NewDirection = -forwardDirection;
//Will turn left or right?
auto crossProductResult = NewDirection.Cross(forwardDirection);
if (crossProductResult.y > 0)
item.ItemFlags[1] |= (1 << 1); // Turn on 1st bit for flagTurnRight.
else if (crossProductResult.y < 0)
item.ItemFlags[1] &= ~(1 << 1); // Turn off 1st bit for flagTurnRight. (So it'll turn to the left)
//Store goal angle to control the rotation.
item.ItemFlags[6] = FROM_RAD(atan2(NewDirection.x, NewDirection.z));
if (item.Pose.Orientation.y - item.ItemFlags[6] == 0)
//If it doesn't have to rotate, do forward movement to keep smooth movement.
item.Pose.Position = item.Pose.Position + forwardDirection * moveVel;
else
//If it has to rotate, stop detection so it doesn't calculate collisions again while rotating in the same sector.
item.ItemFlags[1] &= ~(1 << 0); // Turn off 1st bit for flagDoDetection.
}
else
{
item.Pose.Position.y = col.Position.Floor;
//Is not in the center of a tile, keep moving forward.
item.Pose.Position = item.Pose.Position + forwardDirection * moveVel;
auto slope = col.Block->FloorSlope(0);
if (slope.LengthSquared() > 0) //If it's a slope, don't do turns.
item.ItemFlags[1] &= ~(1 << 0); // Turn off 1st bit for flagDoDetection.
else
item.ItemFlags[1] |= (1 << 0); // Turn on 1st bit for flagDoDetection.
}
}
AnimateItem(&item);
int probedRoomNumber = GetCollision(&item).RoomNumber;
if (item.RoomNumber != probedRoomNumber)
ItemNewRoom(itemNumber, probedRoomNumber);
auto radius = Vector2(object.radius, object.radius);
AlignEntityToSurface(&item, radius);
SpawnElectricCleanerSparks(item);
ElectricCleanerToItemCollision(item);
}
bool IsNextSectorValid(ItemInfo& item, const Vector3& dir)
{
GameVector detectionPoint = item.Pose.Position + dir * BLOCK(1);
detectionPoint.RoomNumber = item.RoomNumber;
auto col = GetCollision(detectionPoint);
//Is a wall
if (col.Block->IsWall(detectionPoint.x, detectionPoint.z))
return false;
//Is it a sliding slope?
if (col.Position.FloorSlope)
return false;
if (abs(col.FloorTilt.x) == 0 && abs(col.FloorTilt.y) == 0) //Is a flat tile
{
//Is a 1 click step (higher or lower).
int distanceToFloor = abs(col.Position.Floor - item.Pose.Position.y);
if (distanceToFloor >= CLICK(1))
return false;
}
else //Is a slope tile
{
//Is a 2 click step (higher or lower).
int distanceToFloor = abs(col.Position.Floor - item.Pose.Position.y);
if (distanceToFloor > CLICK(2))
return false;
short slopeAngle = ANGLE(0.0f);
if (col.FloorTilt.x > 0)
slopeAngle = -ANGLE(90.0f);
else if (col.FloorTilt.x < 0)
slopeAngle = ANGLE(90.0f);
if (col.FloorTilt.y > 0 && col.FloorTilt.y > abs(col.FloorTilt.x))
slopeAngle = ANGLE(180.0f);
else if (col.FloorTilt.y < 0 && -col.FloorTilt.y > abs(col.FloorTilt.x))
slopeAngle = ANGLE(0.0f);
auto angleDir = FROM_RAD(atan2(dir.x, dir.z));
auto alignment = slopeAngle - angleDir;
//Is slope not aligned with the direction?
if ((alignment != 32768) && (alignment != 0) && (alignment != -32768))
return false;
}
//Is diagonal floor?
if (col.Position.DiagonalStep)
return false;
//Is ceiling (square or diagonal) high enough?
int distanceToCeiling = abs(col.Position.Ceiling - col.Position.Floor);
int cleanerHeight = BLOCK(1); //TODO change it for the collision bounding box height.
if (distanceToCeiling < cleanerHeight)
return false;
//Is a non walkable tile? (So there is not any box)
if (col.Block->Box == NO_BOX)
return false;
//Is a blocked grey box (So it's an Isolated box)
if (g_Level.Boxes[col.Block->Box].flags & BLOCKABLE)
return false;
//Is a stopper tile? (There is still a shatter object).
if (col.Block->Stopper)
return false;
//Is there a pushable block?
if (CheckPushableList(MyPushablesList, detectionPoint.ToVector3()))
return false;
//If nothing of that happened, then it must be a valid sector.
return true;
}
Vector3 ElectricCleanerSearchDirections(ItemInfo& item, const Vector3& dir1, const Vector3& dir2, const Vector3& dir3)
{
if (IsNextSectorValid(item, dir1))
return dir1;
if (IsNextSectorValid(item, dir2))
return dir2;
if (IsNextSectorValid(item, dir3))
return dir3;
return Vector3::Zero;
}
void ElectricCleanerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
{
auto& item = g_Level.Items[itemNumber];
ObjectCollision(itemNumber, laraItem, coll);
if (item.TouchBits.Test(ElectricCleanerHarmJoints) && item.ItemFlags[2])
{
ItemElectricBurn(laraItem, -1);
laraItem->HitPoints = 0;
bool flagStopAfterKill = ((item.ItemFlags[1] & (1 << 4)) != 0);
if (flagStopAfterKill)
item.ItemFlags[2] = 0;
SoundEffect(SFX_TR3_CLEANER_FUSEBOX, &item.Pose);
}
}
void ElectricCleanerToItemCollision(ItemInfo& item)
{
auto backupPos = item.Pose.Position;
switch (item.Pose.Orientation.y)
{
case ANGLE(0.0f):
item.Pose.Position.z += BLOCK(0.5f);
break;
case ANGLE(90.0f):
item.Pose.Position.x += BLOCK(0.5f);
break;
case ANGLE(-180.0f):
item.Pose.Position.z -= BLOCK(0.5f);
break;
case ANGLE(-90.0f):
item.Pose.Position.x -= BLOCK(0.5f);
break;
}
if (GetCollidedObjects(&item, CLICK(1), true, CollidedItems, CollidedMeshes, true))
{
int lp = 0;
while (CollidedItems[lp] != nullptr)
{
if (Objects[CollidedItems[lp]->ObjectNumber].intelligent)
{
CollidedItems[lp]->HitPoints = 0;
ItemElectricBurn(CollidedItems[lp], 120);
}
lp++;
}
}
item.Pose.Position = backupPos;
}
void SpawnElectricCleanerSparks(ItemInfo& item)
{
static auto wireEndJoints = std::array<int, 3>{ 5, 9, 13 };
SoundEffect(SFX_TR3_CLEANER_LOOP, &item.Pose);
auto vel = Vector3i(
(Random::GenerateInt(0, 255) * 4) - 512,
Random::GenerateInt(0, 7) - 4,
(Random::GenerateInt(0, 255) * 4) - 512);
for (int i = 0; i < 3; i++)
{
if ((!(GetRandomControl() & 7) && !item.ItemFlags[3 + i]) || item.ItemFlags[3 + i])
{
if (!item.ItemFlags[3 + i])
item.ItemFlags[3 + i] = Random::GenerateInt(0, 12) + 8;
else
item.ItemFlags[3 + i]--;
int joint = wireEndJoints[i];
auto pos = GetJointPosition(&item, joint, Vector3i(-160, -8, 16));
byte c = Random::GenerateInt(0, 64) + 128;
TriggerDynamicLight(pos.x, pos.y, pos.z, 10, c >> 2, c >> 1, c);
auto& spark = GetFreeSparkParticle();
spark = {};
spark.active = true;
spark.age = 0;
float color = (192.0F + Random::GenerateFloat(0, 63.0F)) / 255.0F;
spark.sourceColor = Vector4(color / 4, color / 2, color, 1.0F);
color = (192.0F + Random::GenerateFloat(0, 63.0F)) / 255.0F;
spark.destinationColor = Vector4(color / 4, color / 2, color, 1.0F);
spark.life = Random::GenerateFloat(20, 27);
spark.friction = 1.2f;
spark.gravity = 1.5f;
spark.width = 8.0f;
spark.height = 96.0f;
auto v = vel.ToVector3();
v.Normalize(v);
spark.velocity = v;
spark.pos = pos.ToVector3();
spark.room = item.RoomNumber;
}
}
}
//TODO method to detect pushables while Pushable_Object get refactored.
void CollectLevelPushables(std::vector <ItemInfo* >& PushablesList)
{
for (int index = 0; index < g_Level.Items.size(); index++)
{
ItemInfo* currentItem = &g_Level.Items[index];
if (currentItem->ObjectNumber >= (ID_PUSHABLE_OBJECT1) &&
currentItem->ObjectNumber <= (ID_PUSHABLE_OBJECT10))
PushablesList.push_back(currentItem);
}
}
bool CheckPushableList(std::vector <ItemInfo* >& PushablesList, Vector3& refPoint)
{
auto pushableDistance = INFINITE;
for (int index = 0; index < PushablesList.size(); index++)
{
ItemInfo* currentObj = PushablesList[index];
if (currentObj == nullptr)
continue;
auto PushablePos = currentObj->Pose.Position.ToVector3();
auto currentDistance = Vector3::Distance(PushablePos, refPoint);
if (currentDistance < 1024)
return true;
}
return false;
}
}

View file

@ -0,0 +1,21 @@
#pragma once
struct CollisionInfo;
struct ItemInfo;
namespace TEN::Entities::Traps
{
void InitialiseElectricCleaner(short itemNumber);
void ElectricCleanerControl(short itemNumber);
void ElectricCleanerCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
bool IsNextSectorValid(ItemInfo& item, const Vector3& dir);
Vector3 ElectricCleanerSearchDirections(ItemInfo& item, const Vector3& dir1, const Vector3& dir2, const Vector3& dir3);
void ElectricCleanerToItemCollision(ItemInfo& item);
void SpawnElectricCleanerSparks(ItemInfo& item);
//TODO method to detect pushables while Pushable_Object get refactored.
void CollectLevelPushables (std::vector <ItemInfo*>& PushablesList);
bool CheckPushableList (std::vector <ItemInfo* >& PushablesList, Vector3& refPoint);
}

View file

@ -32,6 +32,7 @@
#include "Objects/Effects/Boss.h" #include "Objects/Effects/Boss.h"
// Traps // Traps
#include "Objects/TR3/Trap/ElectricCleaner.h"
#include "Objects/TR3/Trap/train.h" #include "Objects/TR3/Trap/train.h"
// Vehicles // Vehicles
@ -44,6 +45,7 @@
#include "Objects/Utils/object_helper.h" #include "Objects/Utils/object_helper.h"
using namespace TEN::Entities::Creatures::TR3; using namespace TEN::Entities::Creatures::TR3;
using namespace TEN::Entities::Traps;
using namespace TEN::Effects::Boss; using namespace TEN::Effects::Boss;
static void StartEntity(ObjectInfo* obj) static void StartEntity(ObjectInfo* obj)
@ -398,6 +400,18 @@ static void StartTrap(ObjectInfo* obj)
obj->collision = TrainCollision; obj->collision = TrainCollision;
obj->SetupHitEffect(true); obj->SetupHitEffect(true);
} }
obj = &Objects[ID_ELECTRIC_CLEANER];
if (obj->loaded)
{
obj->initialise = InitialiseElectricCleaner;
obj->control = ElectricCleanerControl;
obj->collision = ElectricCleanerCollision;
obj->shadowType = ShadowMode::All;
obj->HitPoints = NOT_TARGETABLE;
obj->nonLot = 1;
obj->radius = 512;
}
} }
static void StartVehicles(ObjectInfo* obj) static void StartVehicles(ObjectInfo* obj)

View file

@ -192,7 +192,7 @@ namespace TEN::Entities::Generic
if (pushable->hasFloorCeiling) if (pushable->hasFloorCeiling)
{ {
//AlterFloorHeight(item, -((item->triggerFlags - 64) * 256)); //AlterFloorHeight(item, -((item->triggerFlags - 64) * 256));
AdjustStopperFlag(item, item->ItemFlags[0] + 0x8000, false); AdjustStopperFlag(item, item->ItemFlags[0] + ANGLE(180));
} }
} }
@ -390,7 +390,7 @@ namespace TEN::Entities::Generic
if (pushable->hasFloorCeiling) if (pushable->hasFloorCeiling)
{ {
//AlterFloorHeight(item, -((item->triggerFlags - 64) * 256)); //AlterFloorHeight(item, -((item->triggerFlags - 64) * 256));
AdjustStopperFlag(item, item->ItemFlags[0] + 0x8000, false); AdjustStopperFlag(item, item->ItemFlags[0] + ANGLE(180));
} }
} }
@ -498,8 +498,7 @@ namespace TEN::Entities::Generic
if (pushable->hasFloorCeiling) if (pushable->hasFloorCeiling)
{ {
//AlterFloorHeight(item, ((item->triggerFlags - 64) * 256)); AdjustStopperFlag(pushableItem, pushableItem->ItemFlags[0]);
AdjustStopperFlag(pushableItem, pushableItem->ItemFlags[0], false);
} }
} }
else else

View file

@ -357,6 +357,7 @@ enum GAME_OBJECT_ID : short
ID_TRAIN, ID_TRAIN,
ID_EXPLOSION, ID_EXPLOSION,
ID_DAMOCLES_SWORD, ID_DAMOCLES_SWORD,
ID_ELECTRIC_CLEANER,
ID_PUZZLE_ITEM1 = 500, ID_PUZZLE_ITEM1 = 500,
ID_PUZZLE_ITEM2, ID_PUZZLE_ITEM2,

View file

@ -364,6 +364,7 @@ The following constants are inside ObjID.
TRAIN TRAIN
EXPLOSION EXPLOSION
DAMOCLES_SWORD DAMOCLES_SWORD
ELECTRIC_CLEANER
PUZZLE_ITEM1 PUZZLE_ITEM1
PUZZLE_ITEM2 PUZZLE_ITEM2
PUZZLE_ITEM3 PUZZLE_ITEM3
@ -1531,6 +1532,7 @@ static const std::unordered_map<std::string, GAME_OBJECT_ID> kObjIDs {
{ "TRAIN", ID_TRAIN }, { "TRAIN", ID_TRAIN },
{ "EXPLOSION", ID_EXPLOSION }, { "EXPLOSION", ID_EXPLOSION },
{ "DAMOCLES_SWORD", ID_DAMOCLES_SWORD }, { "DAMOCLES_SWORD", ID_DAMOCLES_SWORD },
{ "ELECTRIC_CLEANER", ID_ELECTRIC_CLEANER },
{ "PUZZLE_ITEM1", ID_PUZZLE_ITEM1 }, { "PUZZLE_ITEM1", ID_PUZZLE_ITEM1 },
{ "PUZZLE_ITEM2", ID_PUZZLE_ITEM2 }, { "PUZZLE_ITEM2", ID_PUZZLE_ITEM2 },
{ "PUZZLE_ITEM3", ID_PUZZLE_ITEM3 }, { "PUZZLE_ITEM3", ID_PUZZLE_ITEM3 },

View file

@ -169,6 +169,7 @@ CALL gen.bat</Command>
<ClInclude Include="Game\Hud\PickupSummary.h" /> <ClInclude Include="Game\Hud\PickupSummary.h" />
<ClInclude Include="Math\Objects\AxisAngle.h" /> <ClInclude Include="Math\Objects\AxisAngle.h" />
<ClInclude Include="Objects\TR1\Trap\DamoclesSword.h" /> <ClInclude Include="Objects\TR1\Trap\DamoclesSword.h" />
<ClInclude Include="Objects\TR3\Trap\ElectricCleaner.h" />
<ClInclude Include="Objects\TR3\Entity\Compsognathus.h" /> <ClInclude Include="Objects\TR3\Entity\Compsognathus.h" />
<ClInclude Include="Objects\TR5\Entity\HeavyGuard.h" /> <ClInclude Include="Objects\TR5\Entity\HeavyGuard.h" />
<ClInclude Include="Objects\TR3\Entity\Lizard.h" /> <ClInclude Include="Objects\TR3\Entity\Lizard.h" />
@ -648,6 +649,7 @@ CALL gen.bat</Command>
<ClCompile Include="Game\Hud\PickupSummary.cpp" /> <ClCompile Include="Game\Hud\PickupSummary.cpp" />
<ClCompile Include="Math\Objects\AxisAngle.cpp" /> <ClCompile Include="Math\Objects\AxisAngle.cpp" />
<ClCompile Include="Objects\TR1\Trap\DamoclesSword.cpp" /> <ClCompile Include="Objects\TR1\Trap\DamoclesSword.cpp" />
<ClCompile Include="Objects\TR3\Trap\ElectricCleaner.cpp" />
<ClCompile Include="Objects\TR3\Entity\Compsognathus.cpp" /> <ClCompile Include="Objects\TR3\Entity\Compsognathus.cpp" />
<ClCompile Include="Objects\TR5\Entity\HeavyGuard.cpp" /> <ClCompile Include="Objects\TR5\Entity\HeavyGuard.cpp" />
<ClCompile Include="Objects\TR3\Entity\Lizard.cpp" /> <ClCompile Include="Objects\TR3\Entity\Lizard.cpp" />