mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-30 16:57:57 +03:00
Merge branch 'develop' of https://github.com/MontyTRC89/TombEngine into develop
This commit is contained in:
commit
cdcb4ae37b
136 changed files with 1037 additions and 1458 deletions
|
@ -1,16 +1,26 @@
|
|||
Version 1.0.9
|
||||
=============
|
||||
|
||||
- Fix Cold bar triggered when room is dry (only trigger if and only if the room is water).
|
||||
- Fix spiky wall speed value.
|
||||
- Change speed by giving an OCB number to it or lua (Moveable::SetItemFlags[0]).
|
||||
- Fix crash if little beetle does not exist in wad to load bats emitter.
|
||||
- Fix gunflash rendering and position for entities.
|
||||
- Fix snowmobile driver crashing the game.
|
||||
- Fix knifethrower not throwing knife.
|
||||
- Add TR1 Cowboy.
|
||||
- Add TR3 Wall mounted blade.
|
||||
- Add TR3 Claw mutant.
|
||||
- Add removable puzzles from puzzle holes and puzzle dones.
|
||||
- employed by setting the trigger type as "Switch" for either puzzle hole or puzzle done.
|
||||
- Employed by setting the trigger type as "Switch" for either puzzle hole or puzzle done.
|
||||
- Can be mixed with puzzle done and puzzle holes of the same or different type.
|
||||
- Fix Cold bar triggered when room is dry (only trigger if and only if the room is water).
|
||||
- Fix spiky wall speed value.
|
||||
- Change speed by giving an OCB number to it or lua (Moveable::SetItemFlags[0]).
|
||||
- Fix spiky wall being too slow when triggered.
|
||||
- Add missing gunflash for some entities, also include dynamic light and smoke to all gunflashes.
|
||||
- Add reusable keys for key holes
|
||||
- Employed by setting the trigger type as "Switch" for key hole.
|
||||
- Allow key hole Animation to be played via OCB number.
|
||||
- Default 0 OCB will play Lara use key animation.
|
||||
- Any positive OCB number will play the animation according to the OCB number.
|
||||
- Add log reports if title level or other levels don't exist.
|
||||
|
||||
Lua API changes:
|
||||
* Add function String::SetTranslated()
|
||||
|
|
|
@ -277,7 +277,7 @@ Timer = {
|
|||
|
||||
--- Get the total time for a timer.
|
||||
-- This is the amount of time the timer will start with, as well as when starting a new loop
|
||||
-- @function myTimer:GetRemainingTime
|
||||
-- @function myTimer:GetTotalTime
|
||||
-- @treturn float the timer's total time
|
||||
GetTotalTime = function(t)
|
||||
return LevelVars.Engine.Timer.timers[t.name].totalTime
|
||||
|
|
|
@ -21,7 +21,8 @@ namespace TEN::Hud
|
|||
{
|
||||
void StatusBar::Initialize(float value)
|
||||
{
|
||||
Value = std::clamp(value, 0.0f, 1.0f);
|
||||
Value =
|
||||
TargetValue = std::clamp(value, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
void StatusBar::Update(float value)
|
||||
|
|
|
@ -280,7 +280,7 @@ WeaponInfo Weapons[(int)LaraWeaponType::NumWeapons] =
|
|||
BLOCK(8),
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
SFX_TR4_UZI_FIRE,
|
||||
0
|
||||
|
@ -781,6 +781,7 @@ void AimWeapon(ItemInfo& laraItem, ArmInfo& arm, const WeaponInfo& weaponInfo)
|
|||
arm.Orientation.InterpolateConstant(targetArmOrient, weaponInfo.AimSpeed);
|
||||
}
|
||||
|
||||
// TODO: include snowmobile gun in GetAmmo(), else it won't be able to shoot if lara control it. TokyoSU: 21/04/2023
|
||||
FireWeaponType FireWeapon(LaraWeaponType weaponType, ItemInfo& targetEntity, ItemInfo& laraItem, const EulerAngles& armOrient)
|
||||
{
|
||||
auto& player = *GetLaraInfo(&laraItem);
|
||||
|
|
|
@ -664,6 +664,16 @@ Vector3i GetJointPosition(ItemInfo* item, int jointIndex, const Vector3i& relOff
|
|||
return GetJointPosition(*item, jointIndex, relOffset);
|
||||
}
|
||||
|
||||
Vector3i GetJointPosition(ItemInfo* item, const CreatureBiteInfo& bite)
|
||||
{
|
||||
return GetJointPosition(item, bite.BoneID, bite.Position);
|
||||
}
|
||||
|
||||
Vector3i GetJointPosition(const ItemInfo& item, const CreatureBiteInfo& bite)
|
||||
{
|
||||
return GetJointPosition(item, bite.BoneID, bite.Position);
|
||||
}
|
||||
|
||||
Vector3 GetJointOffset(GAME_OBJECT_ID objectID, int jointIndex)
|
||||
{
|
||||
const auto& object = Objects[objectID];
|
||||
|
|
|
@ -10,6 +10,7 @@ class Pose;
|
|||
class Vector3i;
|
||||
struct ItemInfo;
|
||||
struct ObjectInfo;
|
||||
struct CreatureBiteInfo;
|
||||
|
||||
// NOTES:
|
||||
// animNumber: Relative animation number.
|
||||
|
@ -145,6 +146,9 @@ void DrawAnimatingItem(ItemInfo* item);
|
|||
|
||||
Vector3i GetJointPosition(const ItemInfo& item, int jointIndex, const Vector3i& relOffset = Vector3i::Zero);
|
||||
Vector3i GetJointPosition(ItemInfo* item, int jointIndex, const Vector3i& relOffset = Vector3i::Zero);
|
||||
Vector3i GetJointPosition(ItemInfo* item, const CreatureBiteInfo& bite);
|
||||
Vector3i GetJointPosition(const ItemInfo& item, const CreatureBiteInfo& bite);
|
||||
|
||||
Vector3 GetJointOffset(GAME_OBJECT_ID objectID, int jointIndex);
|
||||
Quaternion GetBoneOrientation(const ItemInfo& item, int boneIndex);
|
||||
float GetBoneLength(GAME_OBJECT_ID objectID, int boneIndex);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "Game/collision/collide_room.h"
|
||||
#include "Game/control/control.h"
|
||||
#include "Game/control/lot.h"
|
||||
#include "Game/effects/smoke.h"
|
||||
#include "Game/effects/tomb4fx.h"
|
||||
#include "Game/itemdata/creature_info.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
|
@ -21,6 +22,8 @@
|
|||
#include "Objects/TR5/Object/tr5_pushableblock.h"
|
||||
#include "Renderer/Renderer11.h"
|
||||
|
||||
using namespace TEN::Effects::Smoke;
|
||||
|
||||
constexpr auto ESCAPE_DIST = SECTOR(5);
|
||||
constexpr auto STALK_DIST = SECTOR(3);
|
||||
constexpr auto REACHED_GOAL_RADIUS = 640;
|
||||
|
@ -32,6 +35,7 @@ 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_JOINT_ROTATION_MAX = ANGLE(70.0f);
|
||||
constexpr auto GUN_EFFECT_CREATURE_YSHIFT = 75;
|
||||
|
||||
#ifdef CREATURE_AI_PRIORITY_OPTIMIZATION
|
||||
constexpr int HIGH_PRIO_RANGE = 8;
|
||||
|
@ -577,15 +581,15 @@ void CreatureKill(ItemInfo* creatureItem, int creatureAnimNumber, int playerAnim
|
|||
Camera.targetElevation = -ANGLE(25.0f);
|
||||
}
|
||||
|
||||
short CreatureEffect2(ItemInfo* item, BiteInfo bite, short velocity, short angle, std::function<CreatureEffectFunction> func)
|
||||
short CreatureEffect2(ItemInfo* item, const CreatureBiteInfo& bite, short velocity, short angle, std::function<CreatureEffectFunction> func)
|
||||
{
|
||||
auto pos = GetJointPosition(item, bite.meshNum, Vector3i(bite.Position));
|
||||
auto pos = GetJointPosition(item, bite);
|
||||
return func(pos.x, pos.y, pos.z, velocity, angle, item->RoomNumber);
|
||||
}
|
||||
|
||||
short CreatureEffect(ItemInfo* item, BiteInfo bite, std::function<CreatureEffectFunction> func)
|
||||
short CreatureEffect(ItemInfo* item, const CreatureBiteInfo& bite, std::function<CreatureEffectFunction> func)
|
||||
{
|
||||
auto pos = GetJointPosition(item, bite.meshNum, Vector3i(bite.Position));
|
||||
auto pos = GetJointPosition(item, bite);
|
||||
return func(pos.x, pos.y, pos.z, item->Animation.Velocity.z, item->Pose.Orientation.y, item->RoomNumber);
|
||||
}
|
||||
|
||||
|
@ -722,12 +726,30 @@ short CreatureTurn(ItemInfo* item, short maxTurn)
|
|||
return angle;
|
||||
}
|
||||
|
||||
static void PlayGunEffectForCreature(ItemInfo* item, const CreatureMuzzleflashInfo& muzzleFlash)
|
||||
{
|
||||
if (muzzleFlash.Delay == 0) return;
|
||||
auto muzzleNewpos = muzzleFlash.Bite;
|
||||
auto pos = GetJointPosition(item, muzzleNewpos);
|
||||
TriggerDynamicLight(pos.x, pos.y, pos.z, 15, 128, 64, 16);
|
||||
if (muzzleFlash.UseSmoke)
|
||||
{
|
||||
// NOTE: Fix the smoke position,
|
||||
// avoiding creating new variable in CreatureMuzzleflashInfo for a smoke biteInfo
|
||||
muzzleNewpos.Position.y -= GUN_EFFECT_CREATURE_YSHIFT;
|
||||
auto smokePos = GetJointPosition(item, muzzleNewpos);
|
||||
TriggerGunSmokeParticles(smokePos.x, smokePos.y, smokePos.z, 0, 0, 0, 1, LaraWeaponType::Pistol, 12, item->RoomNumber);
|
||||
}
|
||||
}
|
||||
|
||||
bool CreatureAnimation(short itemNumber, short angle, short tilt)
|
||||
{
|
||||
auto* item = &g_Level.Items[itemNumber];
|
||||
|
||||
if (!item->IsCreature())
|
||||
return false;
|
||||
auto* creature = GetCreatureInfo(item);
|
||||
PlayGunEffectForCreature(item, creature->MuzzleFlash[0]);
|
||||
PlayGunEffectForCreature(item, creature->MuzzleFlash[1]);
|
||||
|
||||
auto prevPos = item->Pose.Position;
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
#include "Specific/level.h"
|
||||
#include "Math/Math.h"
|
||||
|
||||
struct BiteInfo;
|
||||
struct CreatureInfo;
|
||||
struct ItemInfo;
|
||||
struct LOTInfo;
|
||||
struct CreatureBiteInfo;
|
||||
|
||||
enum class JumpDistance
|
||||
{
|
||||
|
@ -20,55 +20,6 @@ enum TARGET_TYPE
|
|||
SECONDARY_TARGET
|
||||
};
|
||||
|
||||
struct OBJECT_BONES
|
||||
{
|
||||
short bone0;
|
||||
short bone1;
|
||||
short bone2;
|
||||
short bone3;
|
||||
|
||||
OBJECT_BONES()
|
||||
{
|
||||
this->bone0 = 0;
|
||||
this->bone1 = 0;
|
||||
this->bone2 = 0;
|
||||
this->bone3 = 0;
|
||||
}
|
||||
|
||||
OBJECT_BONES(short all)
|
||||
{
|
||||
this->bone0 = all;
|
||||
this->bone1 = all;
|
||||
this->bone2 = all;
|
||||
this->bone3 = all;
|
||||
}
|
||||
|
||||
OBJECT_BONES(short angleY, short angleX)
|
||||
{
|
||||
this->bone0 = angleY;
|
||||
this->bone1 = angleX;
|
||||
this->bone2 = angleY;
|
||||
this->bone3 = angleX;
|
||||
}
|
||||
|
||||
OBJECT_BONES(short angleY, short angleX, bool total)
|
||||
{
|
||||
this->bone0 = angleY;
|
||||
this->bone1 = angleX;
|
||||
|
||||
if (total)
|
||||
{
|
||||
this->bone2 = angleY;
|
||||
this->bone3 = angleX;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->bone2 = 0;
|
||||
this->bone3 = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct AI_INFO
|
||||
{
|
||||
int zoneNumber;
|
||||
|
@ -99,30 +50,6 @@ struct OVERLAP
|
|||
int flags;
|
||||
};
|
||||
|
||||
struct BiteInfo
|
||||
{
|
||||
Vector3 Position = Vector3::Zero;
|
||||
int meshNum = 0;
|
||||
|
||||
BiteInfo()
|
||||
{
|
||||
this->Position = Vector3::Zero;
|
||||
this->meshNum = 0;
|
||||
}
|
||||
|
||||
BiteInfo(const Vector3& pos, int meshNumber)
|
||||
{
|
||||
this->Position = pos;
|
||||
this->meshNum = meshNumber;
|
||||
}
|
||||
|
||||
BiteInfo(float xPos, float yPos, float zPos, int meshNumber)
|
||||
{
|
||||
this->Position = Vector3(xPos, yPos, zPos);
|
||||
this->meshNum = meshNumber;
|
||||
}
|
||||
};
|
||||
|
||||
#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
|
||||
|
@ -164,8 +91,8 @@ short AIGuard(CreatureInfo* creature);
|
|||
void AlertNearbyGuards(ItemInfo* item);
|
||||
void AlertAllGuards(short itemNumber);
|
||||
void CreatureKill(ItemInfo* item, int entityKillAnim, int laraExtraKillAnim, int entityKillState, int laraKillState);
|
||||
short CreatureEffect2(ItemInfo* item, BiteInfo bite, short velocity, short angle, std::function<CreatureEffectFunction> func);
|
||||
short CreatureEffect(ItemInfo* item, BiteInfo bite, std::function<CreatureEffectFunction> func);
|
||||
short CreatureEffect2(ItemInfo* item, const CreatureBiteInfo& bite, short velocity, short angle, std::function<CreatureEffectFunction> func);
|
||||
short CreatureEffect(ItemInfo* item, const CreatureBiteInfo& bite, std::function<CreatureEffectFunction> func);
|
||||
void CreatureUnderwater(ItemInfo* item, int depth);
|
||||
void CreatureFloat(short itemNumber);
|
||||
void CreatureJoint(ItemInfo* item, short joint, short required, short maxAngle = ANGLE(70.0f));
|
||||
|
|
|
@ -271,7 +271,6 @@ unsigned CALLBACK GameMain(void *)
|
|||
else
|
||||
g_Renderer.RenderTitleImage();
|
||||
|
||||
|
||||
// Execute the Lua gameflow and play the game.
|
||||
g_GameFlow->DoFlow();
|
||||
|
||||
|
|
|
@ -146,6 +146,12 @@ void InitializeSlot(short itemNumber, bool makeTarget)
|
|||
|
||||
break;
|
||||
|
||||
case LotType::SnowmobileGun:
|
||||
creature->LOT.Step = CLICK(1);
|
||||
creature->LOT.Drop = -BLOCK(1);
|
||||
creature->LOT.Zone = ZoneType::Human;
|
||||
break;
|
||||
|
||||
// Can climb.
|
||||
case LotType::Human:
|
||||
creature->LOT.Step = BLOCK(1);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "Game/savegame.h"
|
||||
#include "Game/spotcam.h"
|
||||
#include "Objects/Generic/Switches/generic_switch.h"
|
||||
#include "Objects/Generic/puzzles_keys.h"
|
||||
#include "Objects/objectslist.h"
|
||||
#include "Objects/TR3/Vehicles/kayak.h"
|
||||
#include "Sound/sound.h"
|
||||
|
@ -82,7 +83,8 @@ bool GetKeyTrigger(ItemInfo* item)
|
|||
return true;
|
||||
}
|
||||
|
||||
int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch)
|
||||
// NOTE: attatchedToSwitch parameter unused.
|
||||
int GetSwitchTrigger(ItemInfo* item, short* itemNumbersPtr, int attatchedToSwitch)
|
||||
{
|
||||
auto triggerIndex = GetTriggerIndex(item);
|
||||
|
||||
|
@ -95,14 +97,14 @@ int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch)
|
|||
return 0;
|
||||
|
||||
trigger += 2;
|
||||
short* current = itemNos;
|
||||
short* currentPtr = itemNumbersPtr;
|
||||
int k = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (TRIG_BITS(*trigger) == TO_OBJECT && item != &g_Level.Items[*trigger & VALUE_BITS])
|
||||
{
|
||||
current[k] = *trigger & VALUE_BITS;
|
||||
currentPtr[k] = *trigger & VALUE_BITS;
|
||||
++k;
|
||||
}
|
||||
|
||||
|
@ -121,8 +123,11 @@ int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch)
|
|||
int SwitchTrigger(short itemNumber, short timer)
|
||||
{
|
||||
auto& item = g_Level.Items[itemNumber];
|
||||
const auto& player = Lara;
|
||||
|
||||
if ((item.ObjectNumber >= ID_PUZZLE_DONE1 && item.ObjectNumber <= ID_PUZZLE_DONE16) && item.ItemFlags[1])
|
||||
// Handle reusable receptacles.
|
||||
if (item.ObjectNumber >= ID_PUZZLE_DONE1 && item.ObjectNumber <= ID_PUZZLE_DONE16 &&
|
||||
item.ItemFlags[1] != 0)
|
||||
{
|
||||
item.Flags |= IFLAG_ACTIVATION_MASK;
|
||||
item.Status = ITEM_ACTIVE;
|
||||
|
@ -131,7 +136,8 @@ int SwitchTrigger(short itemNumber, short timer)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if ((item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16) && item.ItemFlags[1])
|
||||
if (item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16 &&
|
||||
item.ItemFlags[1] != 0)
|
||||
{
|
||||
item.Flags |= IFLAG_ACTIVATION_MASK;
|
||||
item.Status = ITEM_DEACTIVATED;
|
||||
|
@ -142,11 +148,42 @@ int SwitchTrigger(short itemNumber, short timer)
|
|||
|
||||
if ((item.ObjectNumber >= ID_PUZZLE_DONE1 && item.ObjectNumber <= ID_PUZZLE_DONE16) ||
|
||||
(item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle reusable receptacles.
|
||||
if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16 &&
|
||||
item.ItemFlags[1] != 0 &&
|
||||
(item.ItemFlags[5] == (int)ReusableReceptacleState::Empty || item.ItemFlags[5] == (int)ReusableReceptacleState::None) &&
|
||||
player.Control.HandStatus != HandStatus::Busy)
|
||||
{
|
||||
item.Flags |= IFLAG_ACTIVATION_MASK;
|
||||
item.Status = ITEM_ACTIVE;
|
||||
item.ItemFlags[5] = (int)ReusableReceptacleState::Done;
|
||||
item.ItemFlags[1] = false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16 &&
|
||||
item.ItemFlags[1] != 0 && item.ItemFlags[5] == (int)ReusableReceptacleState::Done &&
|
||||
player.Control.HandStatus != HandStatus::Busy)
|
||||
{
|
||||
item.Flags |= IFLAG_ACTIVATION_MASK;
|
||||
item.Status = ITEM_DEACTIVATED;
|
||||
item.ItemFlags[5] = (int)ReusableReceptacleState::Empty;
|
||||
item.ItemFlags[1] = false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (item.ObjectNumber >= ID_KEY_HOLE1 && item.ObjectNumber <= ID_KEY_HOLE16)
|
||||
return 0;
|
||||
|
||||
// Handle switches.
|
||||
if (item.Status == ITEM_DEACTIVATED)
|
||||
{
|
||||
if ((!item.Animation.ActiveState && item.ObjectNumber != ID_JUMP_SWITCH || item.Animation.ActiveState == 1 && item.ObjectNumber == ID_JUMP_SWITCH) &&
|
||||
if (((item.Animation.ActiveState == 0 && item.ObjectNumber != ID_JUMP_SWITCH) ||
|
||||
(item.Animation.ActiveState == 1 && item.ObjectNumber == ID_JUMP_SWITCH)) &&
|
||||
timer > 0)
|
||||
{
|
||||
item.Timer = timer;
|
||||
|
@ -158,23 +195,23 @@ int SwitchTrigger(short itemNumber, short timer)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (item.TriggerFlags >= 0 || item.Animation.ActiveState)
|
||||
if (item.TriggerFlags >= 0 || item.Animation.ActiveState != 0)
|
||||
{
|
||||
RemoveActiveItem(itemNumber);
|
||||
|
||||
item.Status = ITEM_NOT_ACTIVE;
|
||||
if (!item.ItemFlags[0] == 0)
|
||||
item.Flags |= ONESHOT;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else //if ((item.ObjectNumber >= ID_PUZZLE_DONE1 && item.ObjectNumber <= ID_PUZZLE_DONE16) && item.ItemFlags[1] == 0 ||
|
||||
//(item.ObjectNumber >= ID_PUZZLE_HOLE1 && item.ObjectNumber <= ID_PUZZLE_HOLE16) && item.ItemFlags[1] == 0)
|
||||
else
|
||||
{
|
||||
item.Status = ITEM_ACTIVE;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (item.Status)
|
||||
else if (item.Status != 0)
|
||||
{
|
||||
if (item.ObjectNumber == ID_AIRLOCK_SWITCH &&
|
||||
item.Animation.AnimNumber == GetAnimIndex(item, 2) &&
|
||||
|
@ -193,15 +230,18 @@ int SwitchTrigger(short itemNumber, short timer)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int KeyTrigger(short itemNum)
|
||||
int KeyTrigger(short itemNumber)
|
||||
{
|
||||
ItemInfo* item = &g_Level.Items[itemNum];
|
||||
int oldkey;
|
||||
auto* item = &g_Level.Items[itemNumber];
|
||||
const auto& player = Lara;
|
||||
|
||||
if ((item->Status != ITEM_ACTIVE || Lara.Control.HandStatus == HandStatus::Busy) && (!KeyTriggerActive || Lara.Control.HandStatus != HandStatus::Busy))
|
||||
if ((item->Status != ITEM_ACTIVE || player.Control.HandStatus == HandStatus::Busy) &&
|
||||
(!KeyTriggerActive || player.Control.HandStatus != HandStatus::Busy))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
oldkey = KeyTriggerActive;
|
||||
int oldkey = KeyTriggerActive;
|
||||
|
||||
if (!oldkey)
|
||||
item->Status = ITEM_DEACTIVATED;
|
||||
|
@ -211,9 +251,9 @@ int KeyTrigger(short itemNum)
|
|||
return oldkey;
|
||||
}
|
||||
|
||||
bool PickupTrigger(short itemNum)
|
||||
bool PickupTrigger(short itemNumber)
|
||||
{
|
||||
ItemInfo* item = &g_Level.Items[itemNum];
|
||||
auto* item = &g_Level.Items[itemNumber];
|
||||
|
||||
if (((item->Flags & IFLAG_CLEAR_BODY) && (item->Flags & IFLAG_KILLED)) ||
|
||||
item->Status != ITEM_INVISIBLE ||
|
||||
|
@ -223,7 +263,7 @@ bool PickupTrigger(short itemNum)
|
|||
return false;
|
||||
}
|
||||
|
||||
KillItem(itemNum);
|
||||
KillItem(itemNumber);
|
||||
item->Flags |= IFLAG_CLEAR_BODY;
|
||||
|
||||
return true;
|
||||
|
@ -260,6 +300,7 @@ void RefreshCamera(short type, short* data)
|
|||
}
|
||||
else
|
||||
targetOk = 0;
|
||||
|
||||
break;
|
||||
|
||||
case TO_TARGET:
|
||||
|
@ -273,7 +314,7 @@ void RefreshCamera(short type, short* data)
|
|||
|
||||
if (Camera.item)
|
||||
if (!targetOk || (targetOk == 2 && Camera.item->LookedAt && Camera.item != Camera.lastItem))
|
||||
Camera.item = NULL;
|
||||
Camera.item = nullptr;
|
||||
|
||||
if (Camera.number == -1 && Camera.timer > 0)
|
||||
Camera.timer = -1;
|
||||
|
@ -521,8 +562,8 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, VolumeActivator activat
|
|||
short targetType = 0;
|
||||
short trigger = 0;
|
||||
|
||||
ItemInfo* item = NULL;
|
||||
ItemInfo* cameraItem = NULL;
|
||||
ItemInfo* item = nullptr;
|
||||
ItemInfo* cameraItem = nullptr;
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -784,12 +825,12 @@ void TestTriggers(int x, int y, int z, FloorInfo* floor, VolumeActivator activat
|
|||
FlipEffect = newEffect;
|
||||
}
|
||||
|
||||
void TestTriggers(ItemInfo* item, bool heavy, int heavyFlags)
|
||||
void TestTriggers(ItemInfo* item, bool isHeavy, int heavyFlags)
|
||||
{
|
||||
auto roomNum = item->RoomNumber;
|
||||
auto floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNum);
|
||||
auto roomNumber = item->RoomNumber;
|
||||
auto floor = GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &roomNumber);
|
||||
|
||||
TestTriggers(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, floor, item->Index, heavy, heavyFlags);
|
||||
TestTriggers(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, floor, item->Index, isHeavy, heavyFlags);
|
||||
}
|
||||
|
||||
void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFlags)
|
||||
|
|
|
@ -67,16 +67,16 @@ extern int TriggerTimer;
|
|||
extern int KeyTriggerActive;
|
||||
|
||||
bool GetKeyTrigger(ItemInfo* item);
|
||||
int GetSwitchTrigger(ItemInfo* item, short* itemNos, int attatchedToSwitch);
|
||||
int GetSwitchTrigger(ItemInfo* item, short* itemNumbersPtr, int attatchedToSwitch);
|
||||
int SwitchTrigger(short itemNumber, short timer);
|
||||
int KeyTrigger(short itemNum);
|
||||
bool PickupTrigger(short itemNum);
|
||||
int KeyTrigger(short itemNumber);
|
||||
bool PickupTrigger(short itemNumber);
|
||||
void RefreshCamera(short type, short* data);
|
||||
int TriggerActive(ItemInfo* item);
|
||||
short* GetTriggerIndex(FloorInfo* floor, int x, int y, int z);
|
||||
short* GetTriggerIndex(ItemInfo* item);
|
||||
void TestTriggers(int x, int y, int z, short roomNumber, bool heavy, int heavyFlags = 0);
|
||||
void TestTriggers(ItemInfo* item, bool heavy, int heavyFlags = 0);
|
||||
void TestTriggers(ItemInfo* item, bool isHeavy, int heavyFlags = 0);
|
||||
void ProcessSectorFlags(ItemInfo* item);
|
||||
|
||||
void Antitrigger(short const value, short const flags = 0);
|
||||
|
|
|
@ -52,7 +52,7 @@ int SplashCount = 0;
|
|||
Vector3i NodeVectors[ParticleNodeOffsetIDs::NodeMax];
|
||||
NODEOFFSET_INFO NodeOffsets[ParticleNodeOffsetIDs::NodeMax] =
|
||||
{
|
||||
{ -16, 40, 160, -LM_LHAND, false }, // TR5 offset 0, TODO: This mesh is invalid as it can't be negative. -- TokyoSU 23.02.20
|
||||
{ -16, 40, 160, 13, false }, // TR5 offset 0
|
||||
{ -16, -8, 160, 0, false }, // TR5 offset 1
|
||||
{ 0, 0, 256, 8, false }, // TR5 offset 2
|
||||
{ 0, 0, 256, 17, false }, // TR5 offset 3
|
||||
|
|
|
@ -113,6 +113,11 @@ namespace TEN::Effects::Smoke
|
|||
//TODO: add additional "Weapon Special" param or something. Currently initial == 2 means Rocket Launcher backwards smoke.
|
||||
//TODO: Refactor different weapon types out of it
|
||||
void TriggerGunSmokeParticles(int x, int y, int z, int xv, int yv, int zv, byte initial, LaraWeaponType weaponType, byte count)
|
||||
{
|
||||
TriggerGunSmokeParticles(x, y, z, xv, yv, zv, initial, weaponType, count, LaraItem->RoomNumber);
|
||||
}
|
||||
|
||||
void TriggerGunSmokeParticles(int x, int y, int z, int xv, int yv, int zv, byte initial, LaraWeaponType weaponType, byte count, short roomNumber)
|
||||
{
|
||||
auto& s = GetFreeSmokeParticle();
|
||||
s = {};
|
||||
|
@ -124,7 +129,7 @@ namespace TEN::Effects::Smoke
|
|||
|
||||
s.velocity = direction;
|
||||
s.gravity = -.1f;
|
||||
s.affectedByWind = TestEnvironment(ENV_FLAG_WIND, LaraItem);
|
||||
s.affectedByWind = TestEnvironment(ENV_FLAG_WIND, x, y, z, roomNumber);
|
||||
s.sourceColor = Vector4(.4f, .4f, .4f, 1);
|
||||
s.destinationColor = Vector4(0, 0, 0, 0);
|
||||
|
||||
|
@ -135,7 +140,7 @@ namespace TEN::Effects::Smoke
|
|||
float size = Random::GenerateFloat(48, 80);
|
||||
s.sourceSize = size * 2;
|
||||
s.destinationSize = size * 8;
|
||||
s.sourceColor = {0.75,0.75,1,1};
|
||||
s.sourceColor = { 0.75,0.75,1,1 };
|
||||
s.terminalVelocity = 0;
|
||||
s.friction = 0.82f;
|
||||
s.life = Random::GenerateFloat(60, 90);
|
||||
|
@ -188,7 +193,7 @@ namespace TEN::Effects::Smoke
|
|||
s.position += Vector3(Random::GenerateFloat(-8, 8), Random::GenerateFloat(-8, 8), Random::GenerateFloat(-8, 8));
|
||||
s.angularVelocity = Random::GenerateFloat(-PI_DIV_4, PI_DIV_4);
|
||||
s.angularDrag = 0.95f;
|
||||
s.room = LaraItem->RoomNumber;
|
||||
s.room = roomNumber;
|
||||
}
|
||||
|
||||
void TriggerQuadExhaustSmoke(int x, int y, int z, short angle, int velocity, int moving)
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace TEN::Effects::Smoke
|
|||
void DisableSmokeParticles();
|
||||
void TriggerFlareSmoke(const Vector3& pos, const Vector3& direction, int life, int room);
|
||||
void TriggerGunSmokeParticles(int x, int y, int z, int xv, int yv, int zv, byte initial, LaraWeaponType weaponType, byte count);
|
||||
void TriggerGunSmokeParticles(int x, int y, int z, int xv, int yv, int zv, byte initial, LaraWeaponType weaponType, byte count, short roomNumber);
|
||||
void TriggerQuadExhaustSmoke(int x, int y, int z, short angle, int velocity, int moving);
|
||||
void TriggerRocketSmoke(int x, int y, int z);
|
||||
void TriggerBreathSmoke(long x, long y, long z, short angle);
|
||||
|
|
|
@ -335,6 +335,11 @@ void ThrowFire(int itemNum, int meshIndex, Vector3i offset, Vector3i speed)
|
|||
}
|
||||
}
|
||||
|
||||
void ThrowFire(int itemNum, const CreatureBiteInfo& bite, Vector3i speed)
|
||||
{
|
||||
ThrowFire(itemNum, bite.BoneID, bite.Position, speed);
|
||||
}
|
||||
|
||||
void ThrowPoison(int itemNum, int meshIndex, Vector3i offset, Vector3i speed, Vector3 color)
|
||||
{
|
||||
auto* item = &g_Level.Items[itemNum];
|
||||
|
@ -343,11 +348,15 @@ void ThrowPoison(int itemNum, int meshIndex, Vector3i offset, Vector3i speed, Ve
|
|||
{
|
||||
auto* spark = SetupPoisonSpark(color);
|
||||
AttachAndCreateSpark(spark, item, meshIndex, offset, speed);
|
||||
|
||||
spark->flags = SP_POISON | SP_SCALE | SP_DEF | SP_ROTATE | SP_EXPDEF;
|
||||
}
|
||||
}
|
||||
|
||||
void ThrowPoison(int itemNum, const CreatureBiteInfo& bite, Vector3i speed, Vector3 color)
|
||||
{
|
||||
ThrowPoison(itemNum, bite.BoneID, bite.Position, speed, color);
|
||||
}
|
||||
|
||||
void UpdateFireProgress()
|
||||
{
|
||||
TriggerGlobalStaticFlame();
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
enum class LaraWeaponType;
|
||||
struct ItemInfo;
|
||||
struct CreatureBiteInfo;
|
||||
|
||||
enum BodyPartFlags
|
||||
{
|
||||
|
@ -234,7 +235,9 @@ void TriggerGlobalFireSmoke();
|
|||
void TriggerGlobalFireFlame();
|
||||
void TriggerPilotFlame(int itemNum, int nodeIndex);
|
||||
void ThrowFire(int itemNum, int meshIndex, Vector3i offset, Vector3i speed);
|
||||
void ThrowFire(int itemNum, const CreatureBiteInfo& bite, Vector3i speed);
|
||||
void ThrowPoison(int itemNum, int meshIndex, Vector3i offset, Vector3i speed, Vector3 color);
|
||||
void ThrowPoison(int itemNum, const CreatureBiteInfo& bite, Vector3i speed, Vector3 color);
|
||||
void UpdateFireProgress();
|
||||
void ClearFires();
|
||||
void AddFire(int x, int y, int z, short roomNum, float size, short fade);
|
||||
|
|
9
TombEngine/Game/itemdata/creature_info.cpp
Normal file
9
TombEngine/Game/itemdata/creature_info.cpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include "framework.h"
|
||||
#include "Game/itemdata/creature_info.h"
|
||||
|
||||
#include "Game/items.h"
|
||||
|
||||
bool CreatureInfo::IsTargetAlive()
|
||||
{
|
||||
return ((Enemy != nullptr) && (Enemy->HitPoints > 0));
|
||||
}
|
|
@ -71,6 +71,62 @@ struct LOTInfo
|
|||
bool CanMonkey = false;
|
||||
};
|
||||
|
||||
struct CreatureBiteInfo
|
||||
{
|
||||
Vector3i Position = Vector3i::Zero;
|
||||
int BoneID = -1;
|
||||
|
||||
CreatureBiteInfo() {}
|
||||
|
||||
CreatureBiteInfo(const Vector3i& pos, int boneID)
|
||||
{
|
||||
Position = pos;
|
||||
BoneID = boneID;
|
||||
}
|
||||
|
||||
CreatureBiteInfo(int x, int y, int z, int boneID)
|
||||
{
|
||||
Position = Vector3i(x, y, z);
|
||||
BoneID = boneID;
|
||||
}
|
||||
};
|
||||
|
||||
struct CreatureMuzzleflashInfo
|
||||
{
|
||||
CreatureBiteInfo Bite = {};
|
||||
|
||||
int Delay = 0;
|
||||
bool SwitchToMuzzle2 = false; // Changes muzzle object to ID_GUNFLASH2.
|
||||
bool ApplyXRotation = true; // Applies X axis rotation for muzzleflash (required for creatures).
|
||||
bool ApplyZRotation = true; // Applies Y axis rotation for muzzleflash (required for creatures).
|
||||
bool UseSmoke = true; // Determines if CreatureAnimation calls TriggerGunSmokeParticles().
|
||||
|
||||
CreatureMuzzleflashInfo() {}
|
||||
|
||||
CreatureMuzzleflashInfo(const Vector3i& pos, int boneID, int delay, bool changeToMuzzle2 = false)
|
||||
{
|
||||
Bite = CreatureBiteInfo(pos, boneID);
|
||||
Delay = delay;
|
||||
SwitchToMuzzle2 = changeToMuzzle2;
|
||||
}
|
||||
|
||||
CreatureMuzzleflashInfo(const CreatureBiteInfo& bite, int delay, bool changeToMuzzle2 = false)
|
||||
{
|
||||
Bite = bite;
|
||||
Delay = delay;
|
||||
SwitchToMuzzle2 = changeToMuzzle2;
|
||||
}
|
||||
|
||||
CreatureMuzzleflashInfo(const CreatureBiteInfo& bite, int delay, bool changeToMuzzle2 = false, bool applyXRot = true, bool applyZRot = true)
|
||||
{
|
||||
Bite = bite;
|
||||
Delay = delay;
|
||||
SwitchToMuzzle2 = changeToMuzzle2;
|
||||
ApplyXRotation = applyXRot;
|
||||
ApplyZRotation = applyZRot;
|
||||
}
|
||||
};
|
||||
|
||||
struct CreatureInfo
|
||||
{
|
||||
int ItemNumber = -1;
|
||||
|
@ -96,11 +152,13 @@ struct CreatureInfo
|
|||
bool MonkeySwingAhead = false;
|
||||
bool ReachedGoal = false;
|
||||
|
||||
short FiredWeapon = 0;
|
||||
CreatureMuzzleflashInfo MuzzleFlash[2];
|
||||
short Tosspad = 0;
|
||||
short LocationAI = 0;
|
||||
short Flags = 0;
|
||||
|
||||
bool IsTargetAlive();
|
||||
|
||||
#ifdef CREATURE_AI_PRIORITY_OPTIMIZATION
|
||||
CreatureAIPriority Priority = CreatureAIPriority::None;
|
||||
size_t FramesSinceLOTUpdate = 0;
|
||||
|
|
|
@ -115,7 +115,7 @@ void ControlMissile(short fxNumber)
|
|||
EffectNewRoom(fxNumber, pointColl.RoomNumber);
|
||||
|
||||
if (fx.objectNumber == ID_KNIFETHROWER_KNIFE)
|
||||
fx.pos.Orientation.z += ANGLE(3.0f); // Update knife rotation over time.
|
||||
fx.pos.Orientation.z += ANGLE(30.0f); // Update knife rotation over time.
|
||||
|
||||
switch (fx.objectNumber)
|
||||
{
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "Game/misc.h"
|
||||
#include "Sound/sound.h"
|
||||
|
||||
bool ShotLara(ItemInfo* item, AI_INFO* AI, BiteInfo gun, short extraRotation, int damage)
|
||||
bool ShotLara(ItemInfo* item, AI_INFO* AI, const CreatureBiteInfo& gun, short extraRotation, int damage)
|
||||
{
|
||||
auto* creature = GetCreatureInfo(item);
|
||||
auto* enemy = creature->Enemy;
|
||||
|
@ -79,9 +79,10 @@ bool ShotLara(ItemInfo* item, AI_INFO* AI, BiteInfo gun, short extraRotation, in
|
|||
|
||||
short GunMiss(int x, int y, int z, short velocity, short yRot, short roomNumber)
|
||||
{
|
||||
// TODO: Remove the -128 and fix the Ricochet effect going on the floor ! TokyoSU: 28/04/2023
|
||||
auto pos = GameVector(
|
||||
LaraItem->Pose.Position.x + ((GetRandomControl() - 0x4000) << 9) / 0x7FFF,
|
||||
LaraItem->Floor,
|
||||
LaraItem->Floor - 128,
|
||||
LaraItem->Pose.Position.z + ((GetRandomControl() - 0x4000) << 9) / 0x7FFF,
|
||||
LaraItem->RoomNumber);
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#pragma once
|
||||
#include "Game/control/box.h"
|
||||
|
||||
struct CreatureBiteInfo;
|
||||
constexpr auto MAX_VISIBILITY_DISTANCE = SECTOR(8);
|
||||
|
||||
bool ShotLara(ItemInfo* item, AI_INFO* AI, BiteInfo gun, short extraRotation, int damage);
|
||||
bool ShotLara(ItemInfo* item, AI_INFO* AI, const CreatureBiteInfo& gun, short extraRotation, int damage);
|
||||
short GunMiss(int x, int y, int z, short velocity, short yRot, short roomNumber);
|
||||
short GunHit(int x, int y, int z, short velocity, short yRot, short roomNumber);
|
||||
short GunShot(int x, int y, int z, short velocity, short yRot, short roomNumber);
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "Game/room.h"
|
||||
#include "Objects/Generic/Object/rope.h"
|
||||
#include "Objects/Generic/Switches/fullblock_switch.h"
|
||||
#include "Objects/Generic/Traps/traps.h"
|
||||
#include "Objects/Generic/puzzles_keys.h"
|
||||
#include "Objects/Sink.h"
|
||||
#include "Objects/TR4/Entity/tr4_beetle_swarm.h"
|
||||
|
@ -527,8 +526,7 @@ bool SaveGame::Save(int slot)
|
|||
flatbuffers::Offset<Save::Short> shortOffset;
|
||||
flatbuffers::Offset<Save::Int> intOffset;
|
||||
|
||||
if (Objects[itemToSerialize.ObjectNumber].intelligent
|
||||
&& itemToSerialize.Data.is<CreatureInfo>())
|
||||
if (Objects[itemToSerialize.ObjectNumber].intelligent && itemToSerialize.IsCreature())
|
||||
{
|
||||
auto creature = GetCreatureInfo(&itemToSerialize);
|
||||
|
||||
|
@ -538,12 +536,10 @@ bool SaveGame::Save(int slot)
|
|||
auto jointRotationsOffset = fbb.CreateVector(jointRotations);
|
||||
|
||||
Save::CreatureBuilder creatureBuilder{ fbb };
|
||||
|
||||
creatureBuilder.add_alerted(creature->Alerted);
|
||||
creatureBuilder.add_can_jump(creature->LOT.CanJump);
|
||||
creatureBuilder.add_can_monkey(creature->LOT.CanMonkey);
|
||||
creatureBuilder.add_enemy(creature->Enemy - g_Level.Items.data());
|
||||
creatureBuilder.add_fired_weapon(creature->FiredWeapon);
|
||||
creatureBuilder.add_flags(creature->Flags);
|
||||
creatureBuilder.add_friendly(creature->Friendly);
|
||||
creatureBuilder.add_head_left(creature->HeadLeft);
|
||||
|
@ -555,6 +551,8 @@ bool SaveGame::Save(int slot)
|
|||
creatureBuilder.add_joint_rotation(jointRotationsOffset);
|
||||
creatureBuilder.add_jump_ahead(creature->JumpAhead);
|
||||
creatureBuilder.add_location_ai(creature->LocationAI);
|
||||
creatureBuilder.add_weapon_delay1(creature->MuzzleFlash[0].Delay);
|
||||
creatureBuilder.add_weapon_delay2(creature->MuzzleFlash[1].Delay);
|
||||
creatureBuilder.add_maximum_turn(creature->MaxTurn);
|
||||
creatureBuilder.add_monkey_swing_ahead(creature->MonkeySwingAhead);
|
||||
creatureBuilder.add_mood((int)creature->Mood);
|
||||
|
@ -1545,13 +1543,14 @@ bool SaveGame::Load(int slot)
|
|||
creature->LOT.CanMonkey = savedCreature->can_monkey();
|
||||
if (savedCreature->enemy() >= 0)
|
||||
creature->Enemy = &g_Level.Items[savedCreature->enemy()];
|
||||
creature->FiredWeapon = savedCreature->fired_weapon();
|
||||
creature->Flags = savedCreature->flags();
|
||||
creature->Friendly = savedCreature->friendly();
|
||||
creature->HeadLeft = savedCreature->head_left();
|
||||
creature->HeadRight = savedCreature->head_right();
|
||||
creature->HurtByLara = savedCreature->hurt_by_lara();
|
||||
creature->LocationAI = savedCreature->location_ai();
|
||||
creature->MuzzleFlash[0].Delay = savedCreature->weapon_delay1();
|
||||
creature->MuzzleFlash[1].Delay = savedCreature->weapon_delay2();
|
||||
creature->LOT.IsAmphibious = savedCreature->is_amphibious();
|
||||
creature->LOT.IsJumping = savedCreature->is_jumping();
|
||||
creature->LOT.IsMonkeying = savedCreature->is_monkeying();
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "Game/items.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Lara/lara_collide.h"
|
||||
#include "Objects/Generic/Traps/traps.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/clock.h"
|
||||
#include "Specific/level.h"
|
||||
|
|
|
@ -1,299 +0,0 @@
|
|||
#include "framework.h"
|
||||
#include "traps.h"
|
||||
#include "Game/items.h"
|
||||
#include "Game/effects/effects.h"
|
||||
#include "Game/effects/tomb4fx.h"
|
||||
#include "Game/effects/weather.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/collision/collide_room.h"
|
||||
#include "Game/collision/collide_item.h"
|
||||
#include "Game/collision/sphere.h"
|
||||
#include "Game/camera.h"
|
||||
#include "tr5_light.h"
|
||||
#include "Game/animation.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/Input/Input.h"
|
||||
#include "Game/room.h"
|
||||
#include "Sound/sound.h"
|
||||
|
||||
using namespace TEN::Effects::Environment;
|
||||
|
||||
static short WreckingBallData[2] = {0, 0};
|
||||
|
||||
void InitialiseWreckingBall(short itemNumber)
|
||||
{
|
||||
ItemInfo* item;
|
||||
short room;
|
||||
|
||||
item = &g_Level.Items[itemNumber];
|
||||
item->ItemFlags[3] = FindAllItems(ID_ANIMATING16)[0];
|
||||
room = item->RoomNumber;
|
||||
item->Pose.Position.y = GetCeiling(GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room), item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z) + 1644;
|
||||
GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room);
|
||||
if (room != item->RoomNumber)
|
||||
ItemNewRoom(itemNumber, room);
|
||||
}
|
||||
|
||||
void WreckingBallCollision(short itemNumber, ItemInfo* l, CollisionInfo* coll)
|
||||
{
|
||||
ItemInfo* item;
|
||||
int x, y, z, test;
|
||||
short damage;
|
||||
|
||||
item = &g_Level.Items[itemNumber];
|
||||
if (TestBoundsCollide(item, l, coll->Setup.Radius))
|
||||
{
|
||||
x = l->Pose.Position.x;
|
||||
y = l->Pose.Position.y;
|
||||
z = l->Pose.Position.z;
|
||||
test = (x & 1023) > 256 && (x & 1023) < 768 && (z & 1023) > 256 && (z & 1023) < 768;
|
||||
damage = item->Animation.Velocity.y > 0 ? 96 : 0;
|
||||
if (ItemPushItem(item, l, coll, coll->Setup.EnableSpasm, 1))
|
||||
{
|
||||
if (test)
|
||||
DoDamage(l, INT_MAX);
|
||||
else
|
||||
DoDamage(l, damage);
|
||||
|
||||
x -= l->Pose.Position.x;
|
||||
y -= l->Pose.Position.y;
|
||||
z -= l->Pose.Position.z;
|
||||
if (damage)
|
||||
{
|
||||
for (int i = 14 + (GetRandomControl() & 3); i > 0; --i)
|
||||
{
|
||||
TriggerBlood(l->Pose.Position.x + (GetRandomControl() & 63) - 32, l->Pose.Position.y - (GetRandomControl() & 511) - 256,
|
||||
l->Pose.Position.z + (GetRandomControl() & 63) - 32, -1, 1);
|
||||
}
|
||||
}
|
||||
if (!coll->Setup.EnableObjectPush || test)
|
||||
{
|
||||
l->Pose.Position.x += x;
|
||||
l->Pose.Position.y += y;
|
||||
l->Pose.Position.z += z;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WreckingBallControl(short itemNumber)
|
||||
{
|
||||
ItemInfo* item, *item2;
|
||||
int test, x, z, oldX, oldZ, wx, wz, flagX, flagZ, height, dx, dz, ceilingX, ceilingZ, adx, adz;
|
||||
short room;
|
||||
|
||||
item = &g_Level.Items[itemNumber];
|
||||
test = 1;
|
||||
item2 = &g_Level.Items[item->ItemFlags[3]];
|
||||
if (LaraItem->Pose.Position.x >= 45056 && LaraItem->Pose.Position.x <= 57344 && LaraItem->Pose.Position.z >= 26624 && LaraItem->Pose.Position.z <= 43008
|
||||
|| item->ItemFlags[2] < 900)
|
||||
{
|
||||
if (item->ItemFlags[2] < 900)
|
||||
{
|
||||
if (!item->ItemFlags[2] || !(GlobalCounter & 0x3F))
|
||||
{
|
||||
WreckingBallData[0] = GetRandomControl() % 7 - 3;
|
||||
WreckingBallData[1] = GetRandomControl() % 7 - 3;
|
||||
}
|
||||
x = (WreckingBallData[0] << 10) + 51712;
|
||||
z = (WreckingBallData[1] << 10) + 34304;
|
||||
test = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = LaraItem->Pose.Position.x;
|
||||
z = LaraItem->Pose.Position.z;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 51200;
|
||||
z = 33792;
|
||||
test = 0;
|
||||
}
|
||||
if (item->ItemFlags[2] < 900)
|
||||
++item->ItemFlags[2];
|
||||
|
||||
if (item->ItemFlags[1] <= 0)
|
||||
{
|
||||
oldX = item->Pose.Position.x;
|
||||
oldZ = item->Pose.Position.z;
|
||||
x = x & 0xFFFFFE00 | 0x200;
|
||||
z = z & 0xFFFFFE00 | 0x200;
|
||||
dx = x - item->Pose.Position.x;
|
||||
dz = z - item->Pose.Position.z;
|
||||
wx = 0;
|
||||
if (dx < 0)
|
||||
wx = -1024;
|
||||
else if (dx > 0)
|
||||
wx = 1024;
|
||||
wz = 0;
|
||||
if (dz < 0)
|
||||
wz = -1024;
|
||||
else if (dz > 0)
|
||||
wz = 1024;
|
||||
room = item->RoomNumber;
|
||||
ceilingX = GetCeiling(GetFloor(item->Pose.Position.x + wx, item2->Pose.Position.y, item->Pose.Position.z, &room), item->Pose.Position.x + wx, item2->Pose.Position.y, item->Pose.Position.z);
|
||||
room = item->RoomNumber;
|
||||
ceilingZ = GetCeiling(GetFloor(item->Pose.Position.x, item2->Pose.Position.y, item->Pose.Position.z + wz, &room), item->Pose.Position.x, item2->Pose.Position.y, item->Pose.Position.z + wz);
|
||||
if (ceilingX <= item2->Pose.Position.y && ceilingX != NO_HEIGHT)
|
||||
flagX = 1;
|
||||
else
|
||||
flagX = 0;
|
||||
if (ceilingZ <= item2->Pose.Position.y && ceilingZ != NO_HEIGHT)
|
||||
flagZ = 1;
|
||||
else
|
||||
flagZ = 0;
|
||||
if (!item->ItemFlags[0])
|
||||
{
|
||||
if (flagX && dx && (abs(dx) > abs(dz) || !flagZ || GetRandomControl() & 1))
|
||||
{
|
||||
item->ItemFlags[0] = 1;
|
||||
}
|
||||
else if (flagZ && dz)
|
||||
{
|
||||
item->ItemFlags[0] = 2;
|
||||
}
|
||||
}
|
||||
if (item->ItemFlags[0] == 1)
|
||||
{
|
||||
SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_B_LOOP, &item->Pose);
|
||||
adx = abs(dx);
|
||||
if (adx >= 32)
|
||||
adx = 32;
|
||||
if (dx > 0)
|
||||
{
|
||||
item->Pose.Position.x += adx;
|
||||
}
|
||||
else if (dx < 0)
|
||||
{
|
||||
item->Pose.Position.x -= adx;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->ItemFlags[0] = 0;
|
||||
}
|
||||
}
|
||||
if (item->ItemFlags[0] == 2)
|
||||
{
|
||||
SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_B_LOOP, &item->Pose);
|
||||
adz = abs(dz);
|
||||
if (adz >= 32)
|
||||
adz = 32;
|
||||
if (dz > 0)
|
||||
{
|
||||
item->Pose.Position.z += adz;
|
||||
}
|
||||
else if (dz < 0)
|
||||
{
|
||||
item->Pose.Position.z -= adz;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->ItemFlags[0] = 0;
|
||||
}
|
||||
}
|
||||
if (item->ItemFlags[1] == -1 && (oldX != item->Pose.Position.x || oldZ != item->Pose.Position.z))
|
||||
{
|
||||
item->ItemFlags[1] = 0;
|
||||
SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_A, &item->Pose);
|
||||
}
|
||||
if ((item->Pose.Position.x & 0x3FF) == 512 && (item->Pose.Position.z & 0x3FF) == 512)
|
||||
item->ItemFlags[0] = 0;
|
||||
if (x == item->Pose.Position.x && z == item->Pose.Position.z && test)
|
||||
{
|
||||
if (item->ItemFlags[1] != -1)
|
||||
{
|
||||
StopSoundEffect(SFX_TR5_BASE_CLAW_MOTOR_B_LOOP);
|
||||
SoundEffect(SFX_TR5_BASE_CLAW_MOTOR_C, &item->Pose);
|
||||
}
|
||||
item->ItemFlags[1] = 1;
|
||||
item->TriggerFlags = 30;
|
||||
}
|
||||
}
|
||||
else if (item->ItemFlags[1] == 1)
|
||||
{
|
||||
if (!item->TriggerFlags)
|
||||
{
|
||||
--item->TriggerFlags;
|
||||
}
|
||||
else if (!item->Animation.ActiveState)
|
||||
{
|
||||
item->Animation.TargetState = 1;
|
||||
}
|
||||
else if (item->Animation.FrameNumber == g_Level.Anims[item->Animation.AnimNumber].frameEnd)
|
||||
{
|
||||
SoundEffect(SFX_TR5_BASE_CLAW_DROP, &item->Pose);
|
||||
++item->ItemFlags[1];
|
||||
item->Animation.Velocity.y = 6;
|
||||
item->Pose.Position.y += item->Animation.Velocity.y;
|
||||
}
|
||||
}
|
||||
else if (item->ItemFlags[1] == 2)
|
||||
{
|
||||
item->Animation.Velocity.y += 24;
|
||||
item->Pose.Position.y += item->Animation.Velocity.y;
|
||||
room = item->RoomNumber;
|
||||
height = GetFloorHeight(GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room), item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z);
|
||||
if (height < item->Pose.Position.y)
|
||||
{
|
||||
item->Pose.Position.y = height;
|
||||
if (item->Animation.Velocity.y > 48)
|
||||
{
|
||||
BounceCamera(item, 64, 8192);
|
||||
item->Animation.Velocity.y = -item->Animation.Velocity.y / 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
++item->ItemFlags[1];
|
||||
item->Animation.Velocity.y = 0;
|
||||
}
|
||||
}
|
||||
else if (height - item->Pose.Position.y < 1536 && item->Animation.ActiveState)
|
||||
{
|
||||
item->Animation.TargetState = 0;
|
||||
}
|
||||
}
|
||||
else if (item->ItemFlags[1] == 3)
|
||||
{
|
||||
item->Animation.Velocity.y -= 3;
|
||||
item->Pose.Position.y += item->Animation.Velocity.y;
|
||||
if (item->Pose.Position.y < item2->Pose.Position.y + 1644)
|
||||
{
|
||||
StopSoundEffect(SFX_TR5_BASE_CLAW_WINCH_UP_LOOP);
|
||||
item->ItemFlags[0] = 1;
|
||||
item->Pose.Position.y = item2->Pose.Position.y + 1644;
|
||||
if (item->Animation.Velocity.y < -32)
|
||||
{
|
||||
SoundEffect(SFX_TR5_BASE_CLAW_TOP_IMPACT, &item->Pose, SoundEnvironment::Land, 1.0f, 0.5f);
|
||||
item->Animation.Velocity.y = -item->Animation.Velocity.y / 8;
|
||||
BounceCamera(item, 16, 8192);
|
||||
}
|
||||
else
|
||||
{
|
||||
item->ItemFlags[1] = -1;
|
||||
item->Animation.Velocity.y = 0;
|
||||
item->ItemFlags[0] = 0;
|
||||
}
|
||||
}
|
||||
else if (!item->ItemFlags[0])
|
||||
{
|
||||
SoundEffect(SFX_TR5_BASE_CLAW_WINCH_UP_LOOP, &item->Pose);
|
||||
}
|
||||
}
|
||||
item2->Pose.Position.x = item->Pose.Position.x;
|
||||
item2->Pose.Position.z = item->Pose.Position.z;
|
||||
room = item->RoomNumber;
|
||||
item2->Pose.Position.y = GetCeiling(GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room), item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z);
|
||||
GetFloor(item2->Pose.Position.x, item2->Pose.Position.y, item2->Pose.Position.z, &room);
|
||||
if (room != item2->RoomNumber)
|
||||
ItemNewRoom(item->ItemFlags[3], room);
|
||||
TriggerAlertLight(item2->Pose.Position.x, item2->Pose.Position.y + 64, item2->Pose.Position.z, 255, 64, 0, 64 * (GlobalCounter & 0x3F), item2->RoomNumber, 24);
|
||||
TriggerAlertLight(item2->Pose.Position.x, item2->Pose.Position.y + 64, item2->Pose.Position.z, 255, 64, 0, 64 * (GlobalCounter - 32) & 0xFFF, item2->RoomNumber, 24);
|
||||
room = item->RoomNumber;
|
||||
GetFloor(item->Pose.Position.x, item->Pose.Position.y, item->Pose.Position.z, &room);
|
||||
if (room != item->RoomNumber)
|
||||
ItemNewRoom(itemNumber, room);
|
||||
AnimateItem(item);
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
struct CollisionInfo;
|
||||
struct ItemInfo;
|
||||
|
||||
void InitializeFallingBlock(short itemNumber);
|
||||
void InitializeWreckingBall(short itemNumber);
|
||||
void WreckingBallCollision(short itemNumber, ItemInfo* l, CollisionInfo* coll);
|
||||
void WreckingBallControl(short itemNumber);
|
|
@ -33,13 +33,6 @@ enum class PuzzleType
|
|||
AnimAfter
|
||||
};
|
||||
|
||||
enum PuzzleHoleType
|
||||
{
|
||||
None = 0,
|
||||
Done = 1,
|
||||
Hole = 2
|
||||
};
|
||||
|
||||
ObjectCollisionBounds PuzzleBounds =
|
||||
{
|
||||
GameBoundingBox(
|
||||
|
@ -67,7 +60,7 @@ const ObjectCollisionBounds KeyHoleBounds =
|
|||
void InitializePuzzleHole(short itemNumber)
|
||||
{
|
||||
auto& receptacleItem = g_Level.Items[itemNumber];
|
||||
receptacleItem.ItemFlags[5] = PuzzleHoleType::Hole;
|
||||
receptacleItem.ItemFlags[5] = (int)ReusableReceptacleState::Empty;
|
||||
}
|
||||
|
||||
void InitializePuzzleDone(short itemNumber)
|
||||
|
@ -83,8 +76,8 @@ void PuzzleHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co
|
|||
auto& receptacleItem = g_Level.Items[itemNumber];
|
||||
auto& player = GetLaraInfo(*laraItem);
|
||||
|
||||
//Start level with the right object when loading the game.
|
||||
if (receptacleItem.ItemFlags[5] == PuzzleHoleType::Done)
|
||||
// Start level with correct object when loading game.
|
||||
if (receptacleItem.ItemFlags[5] == (int)ReusableReceptacleState::Done)
|
||||
{
|
||||
receptacleItem.ObjectNumber += GAME_OBJECT_ID{ ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1 };
|
||||
SetAnimation(receptacleItem, 0);
|
||||
|
@ -163,7 +156,7 @@ void PuzzleHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co
|
|||
}
|
||||
}
|
||||
|
||||
RemoveObjectFromInventory(static_cast<GAME_OBJECT_ID>(receptacleItem.ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1)), 1);
|
||||
RemoveObjectFromInventory(GAME_OBJECT_ID(receptacleItem.ObjectNumber - (ID_PUZZLE_HOLE1 - ID_PUZZLE_ITEM1)), 1);
|
||||
|
||||
if (puzzleType == PuzzleType::Specfic)
|
||||
{
|
||||
|
@ -244,8 +237,8 @@ void PuzzleDoneCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co
|
|||
return;
|
||||
AnimateItem(&receptacleItem);
|
||||
|
||||
//Start level with the right object when loading the game.
|
||||
if (receptacleItem.ItemFlags[5] == PuzzleHoleType::Hole)
|
||||
// Start level with correct object when loading game.
|
||||
if (receptacleItem.ItemFlags[5] == (int)ReusableReceptacleState::Empty)
|
||||
{
|
||||
receptacleItem.ObjectNumber = GAME_OBJECT_ID(receptacleItem.ObjectNumber - (ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1));
|
||||
SetAnimation(receptacleItem, 0);
|
||||
|
@ -253,12 +246,12 @@ void PuzzleDoneCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* co
|
|||
return;
|
||||
}
|
||||
|
||||
//Activate triggers when startig the level for the first time
|
||||
if (receptacleItem.ItemFlags[5] == PuzzleHoleType::None)
|
||||
// Activate triggers when startig level for first time.
|
||||
if (receptacleItem.ItemFlags[5] == (int)ReusableReceptacleState::None)
|
||||
{
|
||||
receptacleItem.ItemFlags[1] = true;
|
||||
TestTriggers(receptacleItem.Pose.Position.x, receptacleItem.Pose.Position.y, receptacleItem.Pose.Position.z, receptacleItem.RoomNumber, false, 0);
|
||||
receptacleItem.ItemFlags[5] = PuzzleHoleType::Done;
|
||||
receptacleItem.ItemFlags[5] = (int)ReusableReceptacleState::Done;
|
||||
}
|
||||
|
||||
auto puzzleType = PuzzleType::Normal;
|
||||
|
@ -341,7 +334,7 @@ void PuzzleDone(ItemInfo* item, short itemNumber)
|
|||
item->ItemFlags[1] = true;
|
||||
|
||||
item->ObjectNumber += GAME_OBJECT_ID{ ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1 };
|
||||
item->ItemFlags[5] = PuzzleHoleType::Done;
|
||||
item->ItemFlags[5] = (int)ReusableReceptacleState::Done;
|
||||
SetAnimation(item, 0);
|
||||
item->ResetModelToDefault();
|
||||
}
|
||||
|
@ -371,7 +364,7 @@ void PuzzleHole(ItemInfo* item, short itemNumber)
|
|||
item->ItemFlags[1] = true;
|
||||
|
||||
item->ObjectNumber = GAME_OBJECT_ID(item->ObjectNumber - (ID_PUZZLE_DONE1 - ID_PUZZLE_HOLE1));
|
||||
item->ItemFlags[5] = PuzzleHoleType::Hole;
|
||||
item->ItemFlags[5] = (int)ReusableReceptacleState::Empty;
|
||||
SetAnimation(item, 0);
|
||||
item->ResetModelToDefault();
|
||||
}
|
||||
|
@ -441,35 +434,27 @@ void DoPuzzle()
|
|||
// Keys
|
||||
void KeyHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||
{
|
||||
auto* laraInfo = GetLaraInfo(laraItem);
|
||||
auto* keyHoleItem = &g_Level.Items[itemNumber];
|
||||
auto* player = GetLaraInfo(laraItem);
|
||||
|
||||
if (g_Level.Items[itemNumber].TriggerFlags == 1 &&
|
||||
keyHoleItem->ObjectNumber == ID_KEY_HOLE8)
|
||||
{
|
||||
if (keyHoleItem->ItemFlags[3])
|
||||
{
|
||||
keyHoleItem->ItemFlags[3]--;
|
||||
if (!keyHoleItem->ItemFlags[3])
|
||||
keyHoleItem->MeshBits = 2;
|
||||
}
|
||||
}
|
||||
short* triggerIndexPtr = GetTriggerIndex(keyHoleItem);
|
||||
short triggerType = (*(triggerIndexPtr++) >> 8) & 0x3F;
|
||||
|
||||
bool actionReady = (TrInput & IN_ACTION || g_Gui.GetInventoryItemChosen() != NO_ITEM);
|
||||
bool isActionReady = (IsHeld(In::Action) || g_Gui.GetInventoryItemChosen() != NO_ITEM);
|
||||
|
||||
bool laraAvailable = !BinocularRange &&
|
||||
bool isPlayerAvailable = !BinocularRange &&
|
||||
laraItem->Animation.ActiveState == LS_IDLE &&
|
||||
laraItem->Animation.AnimNumber == LA_STAND_IDLE;
|
||||
|
||||
bool actionActive = laraInfo->Control.IsMoving && laraInfo->Context.InteractedItem == itemNumber;
|
||||
bool actionActive = player->Control.IsMoving && player->Context.InteractedItem == itemNumber;
|
||||
|
||||
if (actionActive || (actionReady && laraAvailable))
|
||||
if (actionActive || (isActionReady && isPlayerAvailable))
|
||||
{
|
||||
if (TestLaraPosition(KeyHoleBounds, keyHoleItem, laraItem))
|
||||
{
|
||||
if (!laraInfo->Control.IsMoving) //TROYE INVENTORY FIX ME
|
||||
if (!player->Control.IsMoving)
|
||||
{
|
||||
if (keyHoleItem->Status != ITEM_NOT_ACTIVE)
|
||||
if (keyHoleItem->Status != ITEM_NOT_ACTIVE && triggerType != TRIGGER_TYPES::SWITCH)
|
||||
return;
|
||||
|
||||
if (g_Gui.GetInventoryItemChosen() == NO_ITEM)
|
||||
|
@ -483,46 +468,42 @@ void KeyHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
|||
if (g_Gui.GetInventoryItemChosen() != keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1))
|
||||
return;
|
||||
|
||||
laraInfo->Context.InteractedItem = itemNumber;
|
||||
player->Context.InteractedItem = itemNumber;
|
||||
}
|
||||
|
||||
if (laraInfo->Context.InteractedItem != itemNumber)
|
||||
if (player->Context.InteractedItem != itemNumber)
|
||||
return;
|
||||
|
||||
if (MoveLaraPosition(KeyHolePosition, keyHoleItem, laraItem))
|
||||
{
|
||||
if (keyHoleItem->ObjectNumber == ID_KEY_HOLE8)
|
||||
laraItem->Animation.AnimNumber = LA_KEYCARD_USE;
|
||||
if (triggerType != TRIGGER_TYPES::SWITCH)
|
||||
{
|
||||
RemoveObjectFromInventory(GAME_OBJECT_ID(keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1)), 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveObjectFromInventory(static_cast<GAME_OBJECT_ID>(keyHoleItem->ObjectNumber - (ID_KEY_HOLE1 - ID_KEY_ITEM1)), 1);
|
||||
laraItem->Animation.AnimNumber = LA_USE_KEY;
|
||||
keyHoleItem->ItemFlags[1] = true;
|
||||
}
|
||||
|
||||
laraItem->Animation.AnimNumber = keyHoleItem->TriggerFlags;
|
||||
|
||||
laraItem->Animation.ActiveState = LS_INSERT_KEY;
|
||||
laraItem->Animation.FrameNumber = g_Level.Anims[laraItem->Animation.AnimNumber].frameBase;
|
||||
laraInfo->Control.IsMoving = false;
|
||||
player->Control.IsMoving = false;
|
||||
ResetPlayerFlex(laraItem);
|
||||
laraInfo->Control.HandStatus = HandStatus::Busy;
|
||||
player->Control.HandStatus = HandStatus::Busy;
|
||||
keyHoleItem->Flags |= TRIGGERED;
|
||||
keyHoleItem->Status = ITEM_ACTIVE;
|
||||
|
||||
if (keyHoleItem->TriggerFlags == 1 && keyHoleItem->ObjectNumber == ID_KEY_HOLE8)
|
||||
{
|
||||
keyHoleItem->ItemFlags[3] = 92;
|
||||
g_Gui.SetInventoryItemChosen(NO_ITEM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g_Gui.SetInventoryItemChosen(NO_ITEM);
|
||||
return;
|
||||
}
|
||||
|
||||
if (laraInfo->Control.IsMoving && laraInfo->Context.InteractedItem == itemNumber)
|
||||
if (player->Control.IsMoving && player->Context.InteractedItem == itemNumber)
|
||||
{
|
||||
laraInfo->Control.IsMoving = false;
|
||||
laraInfo->Control.HandStatus = HandStatus::Free;
|
||||
player->Control.IsMoving = false;
|
||||
player->Control.HandStatus = HandStatus::Free;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -3,6 +3,13 @@
|
|||
struct CollisionInfo;
|
||||
struct ItemInfo;
|
||||
|
||||
enum class ReusableReceptacleState
|
||||
{
|
||||
None = 0,
|
||||
Done = 1,
|
||||
Empty = 2
|
||||
};
|
||||
|
||||
// Puzzles
|
||||
void PuzzleHoleCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
|
||||
void PuzzleDoneCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll);
|
||||
|
|
|
@ -18,8 +18,8 @@ namespace TEN::Entities::Creatures::TR1
|
|||
constexpr auto COWBOY_WALK_TURN_RATE_MAX = ANGLE(3.0f);
|
||||
constexpr auto COWBOY_RUN_TURN_RATE_MAX = ANGLE(6.0f);
|
||||
|
||||
const auto CowboyGunLeft = BiteInfo(Vector3(1.0f, 200.0f, 40.0f), 5);
|
||||
const auto CowboyGunRight = BiteInfo(Vector3(-1.0f, 200.0f, 40.0f), 8);
|
||||
const auto CowboyGunLeft = CreatureBiteInfo(Vector3(1.0f, 200.0f, 40.0f), 5);
|
||||
const auto CowboyGunRight = CreatureBiteInfo(Vector3(-1.0f, 200.0f, 40.0f), 8);
|
||||
|
||||
enum CowboyState
|
||||
{
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace TEN::Entities::Creatures::TR1
|
|||
constexpr auto APE_RUN_TURN_RATE_MAX = ANGLE(5.0f);
|
||||
constexpr auto APE_DISPLAY_ANGLE = ANGLE(45.0f);
|
||||
|
||||
const auto ApeBite = BiteInfo(Vector3(0.0f, -19.0f, 75.0f), 15);
|
||||
const auto ApeBite = CreatureBiteInfo(Vector3i(0, -19, 75), 15);
|
||||
const auto ApeAttackJoints = std::vector<unsigned int>{ 8, 9, 10, 11, 12, 13, 14, 15 };
|
||||
|
||||
enum ApeState
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace TEN::Entities::Creatures::TR1
|
|||
constexpr auto BEAR_WALK_TURN_RATE_MAX = ANGLE(2.0f);
|
||||
constexpr auto BEAR_RUN_TURN_RATE_MAX = ANGLE(5.0f);
|
||||
|
||||
const auto BearBite = BiteInfo(Vector3(0.0f, 96.0f, 335.0f), 14);
|
||||
const auto BearBite = CreatureBiteInfo(Vector3i(0, 96, 335), 14);
|
||||
const auto BearAttackJoints = std::vector<unsigned int>{ 2, 3, 5, 6, 14, 17 };
|
||||
|
||||
enum BearState
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace TEN::Entities::Creatures::TR1
|
|||
constexpr auto BIG_RAT_RUN_TURN_RATE_MAX = ANGLE(6.0f);
|
||||
constexpr auto BIG_RAT_SWIM_TURN_RATE_MAX = ANGLE(3.0f);
|
||||
|
||||
const auto BigRatBite = BiteInfo(Vector3(0.0f, -11.0f, 108.0f), 3);
|
||||
const auto BigRatBite = CreatureBiteInfo(Vector3i(0, -11, 108), 3);
|
||||
|
||||
enum BigRatState
|
||||
{
|
||||
|
@ -163,7 +163,7 @@ namespace TEN::Entities::Creatures::TR1
|
|||
break;
|
||||
}
|
||||
|
||||
if (ai.ahead && item->TouchBits.Test(BigRatBite.meshNum))
|
||||
if (ai.ahead && item->TouchBits.Test(BigRatBite.BoneID))
|
||||
{
|
||||
item->Animation.TargetState = BIG_RAT_STATE_IDLE;
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ namespace TEN::Entities::Creatures::TR1
|
|||
|
||||
case BIG_RAT_STATE_LAND_BITE_ATTACK:
|
||||
if (item->Animation.RequiredState == NO_STATE && ai.ahead &&
|
||||
item->TouchBits.Test(BigRatBite.meshNum))
|
||||
item->TouchBits.Test(BigRatBite.BoneID))
|
||||
{
|
||||
DoDamage(creature->Enemy, BIG_RAT_BITE_ATTACK_DAMAGE);
|
||||
CreatureEffect(item, BigRatBite, DoBloodSplat);
|
||||
|
@ -192,7 +192,7 @@ namespace TEN::Entities::Creatures::TR1
|
|||
|
||||
case BIG_RAT_STATE_POUNCE_ATTACK:
|
||||
if (item->Animation.RequiredState == NO_STATE && ai.ahead &&
|
||||
item->TouchBits.Test(BigRatBite.meshNum))
|
||||
item->TouchBits.Test(BigRatBite.BoneID))
|
||||
{
|
||||
DoDamage(creature->Enemy, BIG_RAT_POUNCE_ATTACK_DAMAGE);
|
||||
CreatureEffect(item, BigRatBite, DoBloodSplat);
|
||||
|
@ -216,14 +216,14 @@ namespace TEN::Entities::Creatures::TR1
|
|||
break;
|
||||
}
|
||||
|
||||
if (ai.ahead && item->TouchBits.Test(BigRatBite.meshNum))
|
||||
if (ai.ahead && item->TouchBits.Test(BigRatBite.BoneID))
|
||||
item->Animation.TargetState = BIG_RAT_STATE_SWIM_BITE_ATTACK;
|
||||
|
||||
break;
|
||||
|
||||
case BIG_RAT_STATE_SWIM_BITE_ATTACK:
|
||||
if (item->Animation.RequiredState == NO_STATE && ai.ahead &&
|
||||
item->TouchBits.Test(BigRatBite.meshNum))
|
||||
item->TouchBits.Test(BigRatBite.BoneID))
|
||||
{
|
||||
DoDamage(creature->Enemy, BIG_RAT_BITE_ATTACK_DAMAGE);
|
||||
CreatureEffect(item, BigRatBite, DoBloodSplat);
|
||||
|
|
|
@ -29,8 +29,8 @@ namespace TEN::Entities::Creatures::TR1
|
|||
|
||||
constexpr auto CENTAUR_TURN_RATE_MAX = ANGLE(4.0f);
|
||||
|
||||
const auto CentaurRocketBite = BiteInfo(Vector3(11.0f, 415.0f, 41.0f), 13);
|
||||
const auto CentaurRearBite = BiteInfo(Vector3(50.0f, 30.0f, 0.0f), 5);
|
||||
const auto CentaurRocketBite = CreatureBiteInfo(Vector3(11, 415, 41), 13);
|
||||
const auto CentaurRearBite = CreatureBiteInfo(Vector3(50, 30, 0), 5);
|
||||
const auto CentaurAttackJoints = std::vector<unsigned int>{ 0, 3, 4, 7, 8, 16, 17 };
|
||||
|
||||
enum CentaurState
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace TEN::Entities::Creatures::TR1
|
|||
constexpr auto NATLA_FLY_ANGLE_SPEED = ANGLE(5.0f);
|
||||
constexpr auto NATLA_SHOOT_ANGLE = ANGLE(30.0f);
|
||||
|
||||
const auto NatlaGunBite = BiteInfo(Vector3(5.0f, 220.0f, 7.0f), 4);
|
||||
const auto NatlaGunBite = CreatureBiteInfo(Vector3i(5, 220, 7), 4);
|
||||
|
||||
enum NatlaState
|
||||
{
|
||||
|
|
|
@ -39,9 +39,9 @@ namespace TEN::Entities::Creatures::TR1
|
|||
constexpr auto WINGED_MUTANT_WALK_FORWARD_TURN_RATE_MAX = ANGLE(2.0f);
|
||||
constexpr auto WINGED_MUTANT_RUN_FORWARD_TURN_RATE_MAX = ANGLE(6.0f);
|
||||
|
||||
const auto WingedMutantBite = BiteInfo(Vector3(-27.0f, 98.0f, 0.0f), 10);
|
||||
const auto WingedMutantRocketBite = BiteInfo(Vector3(51.0f, 213.0f, 0.0f), 14);
|
||||
const auto WingedMutantShardBite = BiteInfo(Vector3(-35.0f, 269.0f, 0.0f), 9);
|
||||
const auto WingedMutantBite = CreatureBiteInfo(Vector3i(-27, 98, 0), 10);
|
||||
const auto WingedMutantRocketBite = CreatureBiteInfo(Vector3i(51, 213, 0), 14);
|
||||
const auto WingedMutantShardBite = CreatureBiteInfo(Vector3i(-35, 269, 0), 9);
|
||||
const auto WingedMutantJoints = std::vector<unsigned int>{ 9, 10, 14 };
|
||||
|
||||
enum WingedMutantState
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace TEN::Entities::Creatures::TR1
|
|||
constexpr auto WOLF_RUN_TURN_RATE_MAX = ANGLE(5.0f);
|
||||
constexpr auto WOLF_STALK_TURN_RATE_MAX = ANGLE(2.0f);
|
||||
|
||||
const auto WolfBite = BiteInfo(Vector3(0.0f, -14.0f, 174.0f), 6);
|
||||
const auto WolfBite = CreatureBiteInfo(Vector3i(0, -14, 174), 6);
|
||||
const auto WolfAttackJoints = std::vector<unsigned int>{ 0, 1, 2, 3, 6, 8, 9, 10, 12, 13, 14 };
|
||||
|
||||
enum WolfState
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
#include "Objects/TR1/Entity/tr1_giant_mutant.h" // OK
|
||||
#include "Objects/TR1/Entity/tr1_wolf.h" // OK
|
||||
#include "Objects/TR1/Entity/tr1_big_rat.h" // OK
|
||||
#include "Objects/TR1/Entity/tr1_centaur.h"
|
||||
#include "Objects/TR1/Entity/tr1_winged_mutant.h"
|
||||
#include "Objects/TR1/Entity/tr1_centaur.h" // OK
|
||||
#include "Objects/TR1/Entity/tr1_winged_mutant.h" // OK
|
||||
#include "Objects/Utils/object_helper.h"
|
||||
|
||||
// Traps
|
||||
|
@ -157,7 +157,6 @@ static void StartEntity(ObjectInfo* obj)
|
|||
obj->control = WingedMutantControl;
|
||||
obj->collision = CreatureCollision;
|
||||
obj->shadowType = ShadowMode::All;
|
||||
obj->hitEffect = HitEffect::Blood;
|
||||
obj->pivotLength = 150;
|
||||
obj->radius = BLOCK(1 / 3.0f);
|
||||
obj->HitPoints = 50;
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
constexpr auto BARRACUDA_IDLE_ATTACK_RANGE = SQUARE(BLOCK(0.67f));
|
||||
constexpr auto BARRACUDA_SWIM_FAST_ATTACK_RANGE = SQUARE(BLOCK(0.34f));
|
||||
|
||||
const auto BarracudaBite = BiteInfo(Vector3(2.0f, -60.0f, 121.0f), 7);
|
||||
const auto BarracudaBite = CreatureBiteInfo(Vector3i(2, -60, 121), 7);
|
||||
const auto BarracudaAttackJoints = std::vector<unsigned int>{ 5, 6, 7 };
|
||||
|
||||
enum BarracudaState
|
||||
|
|
|
@ -21,8 +21,8 @@ namespace TEN::Entities::Creatures::TR2
|
|||
|
||||
constexpr auto BIRD_MONSTER_WALK_TURN_RATE_MAX = ANGLE(4.0f);
|
||||
|
||||
const auto BirdMonsterBiteLeft = BiteInfo(Vector3(0.0f, 224.0f, 0.0f), 19);
|
||||
const auto BirdMonsterBiteRight = BiteInfo(Vector3(0.0f, 224.0f, 0.0f), 22);
|
||||
const auto BirdMonsterBiteLeft = CreatureBiteInfo(Vector3i(0, 224, 0), 19);
|
||||
const auto BirdMonsterBiteRight = CreatureBiteInfo(Vector3i(0, 224, 0), 22);
|
||||
const auto BirdMonsterAttackLeftJoints = std::vector<unsigned int>{ 18, 19 };
|
||||
const auto BirdMonsterAttackRightJoints = std::vector<unsigned int>{ 21, 22 };
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
constexpr auto DRAGON_SWIPE_ATTACK_DAMAGE = 250;
|
||||
constexpr auto DRAGON_CONTACT_DAMAGE = 10;
|
||||
|
||||
const auto DragonMouthBite = BiteInfo(Vector3(35.0f, 171.0f, 1168.0f), 12);
|
||||
const auto DragonMouthBite = CreatureBiteInfo(Vector3i(35, 171, 1168), 12);
|
||||
const auto DragonSwipeAttackJointsLeft = std::vector<unsigned int>{ 24, 25, 26, 27, 28, 29, 30 };
|
||||
const auto DragonSwipeAttackJointsRight = std::vector<unsigned int>{ 1, 2, 3, 4, 5, 6, 7 };
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
|
||||
namespace TEN::Entities::Creatures::TR2
|
||||
{
|
||||
const auto EagleBite = BiteInfo(Vector3(15.0f, 46.0f, 21.0f), 6);
|
||||
const auto CrowBite = BiteInfo(Vector3(2.0f, 10.0f, 60.0f), 14);
|
||||
const auto EagleBite = CreatureBiteInfo(Vector3i(15, 46, 21), 6);
|
||||
const auto CrowBite = CreatureBiteInfo(Vector3i(2, 10, 60), 14);
|
||||
|
||||
enum EagleOrCrowState
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "Game/Lara/lara.h"
|
||||
#include "Game/misc.h"
|
||||
#include "Game/people.h"
|
||||
#include "Game/missile.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/level.h"
|
||||
|
@ -24,8 +25,8 @@ namespace TEN::Entities::Creatures::TR2
|
|||
|
||||
// TODO: Ranges.
|
||||
|
||||
const auto KnifeBiteLeft = BiteInfo(Vector3::Zero, 5);
|
||||
const auto KnifeBiteRight = BiteInfo(Vector3::Zero, 8);
|
||||
const auto KnifeBiteLeft = CreatureBiteInfo(Vector3i::Zero, 5);
|
||||
const auto KnifeBiteRight = CreatureBiteInfo(Vector3i::Zero, 8);
|
||||
|
||||
enum KnifeThrowerState
|
||||
{
|
||||
|
@ -70,55 +71,23 @@ namespace TEN::Entities::Creatures::TR2
|
|||
KTHROWER_ANIM_DEATH = 23
|
||||
};
|
||||
|
||||
void KnifeControl(short fxNumber)
|
||||
{
|
||||
auto* fx = &EffectList[fxNumber];
|
||||
|
||||
if (fx->counter <= 0)
|
||||
{
|
||||
KillEffect(fxNumber);
|
||||
return;
|
||||
}
|
||||
else
|
||||
fx->counter--;
|
||||
|
||||
int speed = fx->speed * phd_cos(fx->pos.Orientation.x);
|
||||
fx->pos.Position.z += speed * phd_cos(fx->pos.Orientation.y);
|
||||
fx->pos.Position.x += speed * phd_sin(fx->pos.Orientation.y);
|
||||
fx->pos.Position.y += fx->speed * phd_sin(-fx->pos.Orientation.x);
|
||||
|
||||
auto probe = GetCollision(fx->pos.Position.x, fx->pos.Position.y, fx->pos.Position.z, fx->roomNumber);
|
||||
|
||||
if (fx->pos.Position.y >= probe.Position.Floor ||
|
||||
fx->pos.Position.y <= probe.Position.Ceiling)
|
||||
{
|
||||
KillEffect(fxNumber);
|
||||
return;
|
||||
}
|
||||
|
||||
if (probe.RoomNumber != fx->roomNumber)
|
||||
EffectNewRoom(fxNumber, probe.RoomNumber);
|
||||
|
||||
fx->pos.Orientation.z += ANGLE(30.0f);
|
||||
|
||||
if (ItemNearLara(fx->pos.Position, 200))
|
||||
{
|
||||
DoDamage(LaraItem, KNIFE_PROJECTILE_DAMAGE);
|
||||
|
||||
fx->pos.Orientation.y = LaraItem->Pose.Orientation.y;
|
||||
fx->speed = LaraItem->Animation.Velocity.z;
|
||||
fx->frameNumber = fx->counter = 0;
|
||||
|
||||
DoBloodSplat(fx->pos.Position.x, fx->pos.Position.y, fx->pos.Position.z, 80, fx->pos.Orientation.y, fx->roomNumber);
|
||||
SoundEffect(SFX_TR2_CRUNCH2, &fx->pos);
|
||||
KillEffect(fxNumber);
|
||||
}
|
||||
}
|
||||
|
||||
short ThrowKnife(int x, int y, int z, short velocity, short yRot, short roomNumber)
|
||||
{
|
||||
short fxNumber = 0;
|
||||
// TODO: add fx parameters
|
||||
short fxNumber = CreateNewEffect(roomNumber);
|
||||
if (fxNumber != NO_ITEM)
|
||||
{
|
||||
auto* fx = &EffectList[fxNumber];
|
||||
fx->objectNumber = ID_KNIFETHROWER_KNIFE;
|
||||
fx->pos.Position.x = x;
|
||||
fx->pos.Position.y = y;
|
||||
fx->pos.Position.z = z;
|
||||
fx->speed = velocity;
|
||||
fx->pos.Orientation.y = yRot;
|
||||
fx->fallspeed = 0;
|
||||
fx->flag2 = KNIFE_PROJECTILE_DAMAGE;
|
||||
fx->color = Vector4::One;
|
||||
ShootAtLara(*fx);
|
||||
}
|
||||
return fxNumber;
|
||||
}
|
||||
|
||||
|
@ -264,7 +233,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
|
||||
if (!creature->Flags)
|
||||
{
|
||||
CreatureEffect(item, KnifeBiteLeft, ThrowKnife);
|
||||
CreatureEffect2(item, KnifeBiteLeft, 100, torso, ThrowKnife);
|
||||
creature->Flags = 1;
|
||||
}
|
||||
|
||||
|
@ -276,7 +245,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
|
||||
if (!creature->Flags)
|
||||
{
|
||||
CreatureEffect(item, KnifeBiteRight, ThrowKnife);
|
||||
CreatureEffect2(item, KnifeBiteRight, 100, torso, ThrowKnife);
|
||||
creature->Flags = 1;
|
||||
}
|
||||
|
||||
|
@ -288,8 +257,8 @@ namespace TEN::Entities::Creatures::TR2
|
|||
|
||||
if (!creature->Flags)
|
||||
{
|
||||
CreatureEffect(item, KnifeBiteLeft, ThrowKnife);
|
||||
CreatureEffect(item, KnifeBiteRight, ThrowKnife);
|
||||
CreatureEffect2(item, KnifeBiteLeft, 100, torso, ThrowKnife);
|
||||
CreatureEffect2(item, KnifeBiteRight, 100, torso, ThrowKnife);
|
||||
creature->Flags = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,5 @@
|
|||
|
||||
namespace TEN::Entities::Creatures::TR2
|
||||
{
|
||||
void KnifeControl(short fxNumber);
|
||||
void KnifeThrowerControl(short itemNumber);
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
|
||||
namespace TEN::Entities::Creatures::TR2
|
||||
{
|
||||
const auto MercenaryUziBite = BiteInfo(Vector3(0.0f, 150.0f, 19.0f), 17);
|
||||
const auto MercenaryAutoPistolBite = BiteInfo(Vector3(0.0f, 230.0f, 9.0f), 17);
|
||||
const auto MercenaryUziBite = CreatureBiteInfo(Vector3i(0, 200, 19), 17);
|
||||
const auto MercenaryAutoPistolBite = CreatureBiteInfo(Vector3i(0, 230, 9), 17);
|
||||
|
||||
// TODO
|
||||
enum MercenaryState
|
||||
|
@ -41,6 +41,9 @@ namespace TEN::Entities::Creatures::TR2
|
|||
auto extraHeadRot = EulerAngles::Zero;
|
||||
auto extraTorsoRot = EulerAngles::Zero;
|
||||
|
||||
if (creature->MuzzleFlash[0].Delay != 0)
|
||||
creature->MuzzleFlash[0].Delay--;
|
||||
|
||||
if (item->HitPoints <= 0)
|
||||
{
|
||||
if (item->Animation.ActiveState != 13)
|
||||
|
@ -163,8 +166,13 @@ namespace TEN::Entities::Creatures::TR2
|
|||
extraTorsoRot.y = AI.angle;
|
||||
}
|
||||
|
||||
if (item->Animation.FrameNumber == GetFrameIndex(item, 0))
|
||||
{
|
||||
if (!ShotLara(item, &AI, MercenaryUziBite, extraTorsoRot.y, 8))
|
||||
item->Animation.TargetState = 1;
|
||||
creature->MuzzleFlash[0].Bite = MercenaryUziBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
}
|
||||
|
||||
if (AI.distance < pow(SECTOR(2), 2))
|
||||
item->Animation.TargetState = 1;
|
||||
|
@ -179,8 +187,13 @@ namespace TEN::Entities::Creatures::TR2
|
|||
extraTorsoRot.y = AI.angle;
|
||||
}
|
||||
|
||||
if (item->Animation.FrameNumber == GetFrameIndex(item, 0))
|
||||
{
|
||||
if (!ShotLara(item, &AI, MercenaryUziBite, extraTorsoRot.y, 8))
|
||||
item->Animation.TargetState = 1;
|
||||
creature->MuzzleFlash[0].Bite = MercenaryUziBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
}
|
||||
|
||||
if (AI.distance < pow(SECTOR(2), 2))
|
||||
item->Animation.TargetState = 2;
|
||||
|
@ -210,6 +223,9 @@ namespace TEN::Entities::Creatures::TR2
|
|||
auto extraHeadRot = EulerAngles::Zero;
|
||||
auto extraTorsoRot = EulerAngles::Zero;
|
||||
|
||||
if (creature->MuzzleFlash[0].Delay != 0)
|
||||
creature->MuzzleFlash[0].Delay--;
|
||||
|
||||
if (item->HitPoints <= 0)
|
||||
{
|
||||
if (item->Animation.ActiveState != 11)
|
||||
|
@ -330,12 +346,13 @@ namespace TEN::Entities::Creatures::TR2
|
|||
extraTorsoRot.x = AI.xAngle;
|
||||
extraTorsoRot.y = AI.angle;
|
||||
|
||||
if (!creature->Flags)
|
||||
if (creature->Flags == 0)
|
||||
{
|
||||
if (GetRandomControl() < 0x2000)
|
||||
item->Animation.TargetState = 2;
|
||||
|
||||
ShotLara(item, &AI, MercenaryAutoPistolBite, extraTorsoRot.y, 50);
|
||||
creature->MuzzleFlash[0].Bite = MercenaryAutoPistolBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
creature->Flags = 1;
|
||||
}
|
||||
}
|
||||
|
@ -353,11 +370,12 @@ namespace TEN::Entities::Creatures::TR2
|
|||
if (AI.distance < pow(SECTOR(2), 2))
|
||||
item->Animation.TargetState = 3;
|
||||
|
||||
if (creature->Flags != 1)
|
||||
if (creature->Flags == 0)
|
||||
{
|
||||
if (!ShotLara(item, &AI, MercenaryAutoPistolBite, extraTorsoRot.y, 50))
|
||||
item->Animation.TargetState = 3;
|
||||
|
||||
creature->MuzzleFlash[0].Bite = MercenaryAutoPistolBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
creature->Flags = 1;
|
||||
}
|
||||
}
|
||||
|
@ -395,7 +413,8 @@ namespace TEN::Entities::Creatures::TR2
|
|||
{
|
||||
if (!ShotLara(item, &AI, MercenaryAutoPistolBite, extraTorsoRot.y, 50))
|
||||
item->Animation.TargetState = 3;
|
||||
|
||||
creature->MuzzleFlash[0].Bite = MercenaryAutoPistolBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
creature->Flags = 2;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
namespace TEN::Entities::Creatures::TR2
|
||||
{
|
||||
const auto MonkBite = BiteInfo(Vector3(-23.0f, 16.0f, 265.0f), 14);
|
||||
const auto MonkBite = CreatureBiteInfo(Vector3i(-23, 16, 265), 14);
|
||||
|
||||
bool MonksAttackLara;
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
|
||||
constexpr auto RAT_TURN_RATE_MAX = ANGLE(6.0f);
|
||||
|
||||
const auto RatBite = BiteInfo(Vector3(0.0f, 0.0f, 57.0f), 2);
|
||||
const auto RatBite = CreatureBiteInfo(Vector3i(0, 0, 57), 2);
|
||||
|
||||
enum RatState
|
||||
{
|
||||
|
@ -131,7 +131,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
|
||||
case RAT_STATE_POUNCE_ATTACK:
|
||||
if (item->Animation.RequiredState == NO_STATE &&
|
||||
item->TouchBits.Test(RatBite.meshNum))
|
||||
item->TouchBits.Test(RatBite.BoneID))
|
||||
{
|
||||
item->Animation.RequiredState = RAT_STATE_IDLE;
|
||||
DoDamage(creature->Enemy, RAT_ATTACK_DAMAGE);
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
{
|
||||
constexpr auto SHARK_BITE_ATTACK_DAMAGE = 400;
|
||||
|
||||
const auto SharkBite = BiteInfo(Vector3(17.0f, -22.0f, 344.0f), 12);
|
||||
const auto SharkBite = CreatureBiteInfo(Vector3i(17, -22, 344), 12);
|
||||
const auto SharkBiteAttackJoints = std::vector<unsigned int>{ 10, 12, 13 };
|
||||
|
||||
void SharkControl(short itemNumber)
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
constexpr auto SILENCER_WALK_TURN_RATE_MAX = ANGLE(5.0f);
|
||||
constexpr auto SILENCER_RUN_TURN_RATE_MAX = ANGLE(5.0f);
|
||||
|
||||
const auto SilencerGunBite = BiteInfo(Vector3(3.0f, 331.0f, 56.0f), 10);
|
||||
const auto SilencerGunBite = CreatureBiteInfo(Vector3(-10, 360, 60), 10);
|
||||
|
||||
enum SilencerState
|
||||
{
|
||||
|
@ -87,6 +87,9 @@ namespace TEN::Entities::Creatures::TR2
|
|||
auto extraHeadRot = EulerAngles::Zero;
|
||||
auto extraTorsoRot = EulerAngles::Zero;
|
||||
|
||||
if (creature->MuzzleFlash[0].Delay != 0)
|
||||
creature->MuzzleFlash[0].Delay--;
|
||||
|
||||
if (item->HitPoints <= 0)
|
||||
{
|
||||
if (item->Animation.ActiveState != SILENCER_STATE_DEATH_1 &&
|
||||
|
@ -279,9 +282,11 @@ namespace TEN::Entities::Creatures::TR2
|
|||
else
|
||||
extraHeadRot.y = AI.angle;
|
||||
|
||||
if (!creature->Flags)
|
||||
if (creature->Flags == 0 && item->Animation.FrameNumber == GetFrameIndex(item, 0))
|
||||
{
|
||||
ShotLara(item, &AI, SilencerGunBite, extraTorsoRot.y, SILENCER_SHOOT_ATTACK_DAMAGE);
|
||||
creature->MuzzleFlash[0].Bite = SilencerGunBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
creature->Flags = 1;
|
||||
}
|
||||
|
||||
|
@ -298,11 +303,14 @@ namespace TEN::Entities::Creatures::TR2
|
|||
else
|
||||
extraHeadRot.y = AI.angle;
|
||||
|
||||
if (item->Animation.RequiredState == NO_STATE)
|
||||
if (item->Animation.RequiredState == NO_STATE &&
|
||||
(item->Animation.AnimNumber == GetAnimIndex(*item, SILENCER_ANIM_RUN_FORWARD_SHOOT_LEFT) && item->Animation.FrameNumber == GetFrameIndex(item, 1) ||
|
||||
item->Animation.AnimNumber == GetAnimIndex(*item, SILENCER_ANIM_RUN_FORWARD_SHOOT_RIGHT) && item->Animation.FrameNumber == GetFrameIndex(item, 3)))
|
||||
{
|
||||
if (!ShotLara(item, &AI, SilencerGunBite, extraTorsoRot.y, SILENCER_SHOOT_ATTACK_DAMAGE))
|
||||
item->Animation.TargetState = SILENCER_STATE_RUN_FORWARD;
|
||||
|
||||
creature->MuzzleFlash[0].Bite = SilencerGunBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
item->Animation.RequiredState = SILENCER_STATE_RUN_SHOOT;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
#include "Game/collision/sphere.h"
|
||||
#include "Game/control/box.h"
|
||||
#include "Game/control/lot.h"
|
||||
#include "Game/effects/smoke.h"
|
||||
#include "Game/itemdata/creature_info.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/misc.h"
|
||||
#include "Game/people.h"
|
||||
#include "Objects/TR2/Vehicles/skidoo.h"
|
||||
|
@ -17,15 +19,19 @@
|
|||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
using namespace TEN::Effects::Smoke;
|
||||
|
||||
namespace TEN::Entities::Creatures::TR2
|
||||
{
|
||||
constexpr auto SMAN_WAIT_RANGE = SQUARE(BLOCK(4));
|
||||
|
||||
const auto SkidooBiteLeft = BiteInfo(Vector3(240.0f, -190.0f, 540.0f), 0);
|
||||
const auto SkidooBiteRight = BiteInfo(Vector3(-240.0f, -190.0f, 540.0f), 0);
|
||||
const auto SkidooBiteLeft = CreatureBiteInfo(Vector3i(240, -80, 540), 0);
|
||||
const auto SkidooBiteRight = CreatureBiteInfo(Vector3i(-240, -80, 540), 0);
|
||||
const auto SkidooBiteSmokeLeft = CreatureBiteInfo(Vector3i(240, -80, 450), 0);
|
||||
const auto SkidooBiteSmokeRight = CreatureBiteInfo(Vector3i(-240, -80, 450), 0);
|
||||
|
||||
constexpr auto SMAN_MIN_TURN = ANGLE(2.0f);
|
||||
constexpr auto SMAN_TARGET_ANGLE = ANGLE(15.0f);
|
||||
constexpr auto SMAN_TARGET_ANGLE = ANGLE(30.0f);
|
||||
|
||||
enum SnowmobileManState
|
||||
{
|
||||
|
@ -45,30 +51,34 @@ namespace TEN::Entities::Creatures::TR2
|
|||
SMAN_ANIM_DEATH = 10
|
||||
};
|
||||
|
||||
void InitializeSkidooMan(short itemNumber)
|
||||
static void CreateSnowmobileGun(ItemInfo* driver)
|
||||
{
|
||||
short skidooItemNumber = CreateItem();
|
||||
if (skidooItemNumber != NO_ITEM)
|
||||
short snowmobileNumber = CreateItem();
|
||||
if (snowmobileNumber != NO_ITEM)
|
||||
{
|
||||
auto* riderItem = &g_Level.Items[itemNumber];
|
||||
auto* skidooItem = &g_Level.Items[skidooItemNumber];
|
||||
|
||||
skidooItem->ObjectNumber = ID_SNOWMOBILE_GUN;
|
||||
skidooItem->Pose.Position = riderItem->Pose.Position;
|
||||
skidooItem->Pose.Orientation.y = riderItem->Pose.Orientation.y;
|
||||
skidooItem->RoomNumber = riderItem->RoomNumber;
|
||||
skidooItem->Flags = ITEM_INVISIBLE;
|
||||
skidooItem->Model.Color = Vector4(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
|
||||
InitializeItem(skidooItemNumber);
|
||||
|
||||
// The rider remembers his skidoo.
|
||||
riderItem->Data = skidooItemNumber;
|
||||
|
||||
g_Level.NumItems++;
|
||||
auto* snowmobileGunItem = &g_Level.Items[snowmobileNumber];
|
||||
snowmobileGunItem->Pose.Position = driver->Pose.Position;
|
||||
snowmobileGunItem->Pose.Orientation.y = driver->Pose.Orientation.y;
|
||||
snowmobileGunItem->RoomNumber = driver->RoomNumber;
|
||||
snowmobileGunItem->ObjectNumber = ID_SNOWMOBILE_GUN;
|
||||
snowmobileGunItem->Model.Color = driver->Model.Color;
|
||||
snowmobileGunItem->Flags = IFLAG_ACTIVATION_MASK;
|
||||
InitializeItem(snowmobileNumber); g_Level.NumItems++;
|
||||
driver->Data = snowmobileNumber; // Register the snowmobile gun for the driver to control it.
|
||||
}
|
||||
else
|
||||
TENLog("Can't create skidoo for rider!", LogLevel::Error);
|
||||
{
|
||||
TENLog("Failed to create the ID_SNOWMOBILE_GUN from ID_SNOWMOBILE_DRIVER.", LogLevel::Warning);
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeSkidooMan(short itemNumber)
|
||||
{
|
||||
auto* item = &g_Level.Items[itemNumber];
|
||||
if (item->Flags & IFLAG_REVERSE)
|
||||
item->Status &= ~ITEM_INVISIBLE;
|
||||
else
|
||||
item->Status = ITEM_INVISIBLE;
|
||||
}
|
||||
|
||||
void SkidooManCollision(short itemNumber, ItemInfo* laraItem, CollisionInfo* coll)
|
||||
|
@ -95,60 +105,67 @@ namespace TEN::Entities::Creatures::TR2
|
|||
|
||||
void SkidooManControl(short riderItemNumber)
|
||||
{
|
||||
auto* riderItem = &g_Level.Items[riderItemNumber];
|
||||
if (!riderItem->Data)
|
||||
auto* rider = &g_Level.Items[riderItemNumber];
|
||||
if (!rider->Data)
|
||||
{
|
||||
TENLog("Rider data does not contain the skidoo itemNumber!", LogLevel::Error);
|
||||
// Create the snowmobile.
|
||||
CreateSnowmobileGun(rider);
|
||||
if (!rider->Data)
|
||||
TENLog("Rider data does not contain the skidoo itemNumber !", LogLevel::Error);
|
||||
return;
|
||||
}
|
||||
|
||||
short itemNumber = (short)riderItem->Data;
|
||||
auto* item = &g_Level.Items[itemNumber];
|
||||
short itemNumber = (short)rider->Data;
|
||||
auto* skidoo = &g_Level.Items[itemNumber];
|
||||
|
||||
if (!item->Data)
|
||||
if (!skidoo->Data)
|
||||
{
|
||||
EnableEntityAI(itemNumber, true);
|
||||
item->Status = ITEM_ACTIVE;
|
||||
skidoo->Status = ITEM_ACTIVE;
|
||||
}
|
||||
|
||||
auto* creatureInfo = GetCreatureInfo(item);
|
||||
auto* creatureInfo = GetCreatureInfo(skidoo);
|
||||
short angle = 0;
|
||||
int damage;
|
||||
|
||||
if (creatureInfo->MuzzleFlash[0].Delay != 0)
|
||||
creatureInfo->MuzzleFlash[0].Delay--;
|
||||
if (creatureInfo->MuzzleFlash[1].Delay != 0)
|
||||
creatureInfo->MuzzleFlash[1].Delay--;
|
||||
|
||||
AI_INFO AI;
|
||||
if (item->HitPoints <= 0)
|
||||
if (skidoo->HitPoints <= 0)
|
||||
{
|
||||
if (riderItem->Animation.ActiveState != SMAN_STATE_DEATH)
|
||||
if (rider->Animation.ActiveState != SMAN_STATE_DEATH)
|
||||
{
|
||||
riderItem->Pose.Position = item->Pose.Position;
|
||||
riderItem->Pose.Orientation.y = item->Pose.Orientation.y;
|
||||
riderItem->RoomNumber = item->RoomNumber;
|
||||
rider->Pose.Position = skidoo->Pose.Position;
|
||||
rider->Pose.Orientation.y = skidoo->Pose.Orientation.y;
|
||||
rider->RoomNumber = skidoo->RoomNumber;
|
||||
|
||||
riderItem->Animation.AnimNumber = Objects[ID_SNOWMOBILE_DRIVER].animIndex + SMAN_ANIM_DEATH;
|
||||
riderItem->Animation.FrameNumber = g_Level.Anims[riderItem->Animation.AnimNumber].frameBase;
|
||||
riderItem->Animation.ActiveState = SMAN_STATE_DEATH;
|
||||
rider->Animation.AnimNumber = Objects[ID_SNOWMOBILE_DRIVER].animIndex + SMAN_ANIM_DEATH;
|
||||
rider->Animation.FrameNumber = g_Level.Anims[rider->Animation.AnimNumber].frameBase;
|
||||
rider->Animation.ActiveState = SMAN_STATE_DEATH;
|
||||
|
||||
if (Lara.TargetEntity == item)
|
||||
if (Lara.TargetEntity == skidoo)
|
||||
Lara.TargetEntity = nullptr;
|
||||
}
|
||||
else
|
||||
AnimateItem(riderItem);
|
||||
AnimateItem(rider);
|
||||
|
||||
if (item->Animation.ActiveState == SMAN_STATE_MOVING || item->Animation.ActiveState == SMAN_STATE_WAIT)
|
||||
item->Animation.TargetState = SMAN_STATE_WAIT;
|
||||
if (skidoo->Animation.ActiveState == SMAN_STATE_MOVING || skidoo->Animation.ActiveState == SMAN_STATE_WAIT)
|
||||
skidoo->Animation.TargetState = SMAN_STATE_WAIT;
|
||||
else
|
||||
item->Animation.TargetState = SMAN_STATE_MOVING;
|
||||
skidoo->Animation.TargetState = SMAN_STATE_MOVING;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreatureAIInfo(item, &AI);
|
||||
CreatureAIInfo(skidoo, &AI);
|
||||
|
||||
GetCreatureMood(item, &AI, true);
|
||||
CreatureMood(item, &AI, true);
|
||||
GetCreatureMood(skidoo, &AI, true);
|
||||
CreatureMood(skidoo, &AI, true);
|
||||
|
||||
angle = CreatureTurn(item, ANGLE(3.0f));
|
||||
angle = CreatureTurn(skidoo, ANGLE(3.0f));
|
||||
|
||||
switch (item->Animation.ActiveState)
|
||||
switch (skidoo->Animation.ActiveState)
|
||||
{
|
||||
case SMAN_STATE_WAIT:
|
||||
if (creatureInfo->Mood == MoodType::Bored)
|
||||
|
@ -156,98 +173,119 @@ namespace TEN::Entities::Creatures::TR2
|
|||
else if (abs(AI.angle) < SMAN_TARGET_ANGLE && AI.distance < SMAN_WAIT_RANGE)
|
||||
break;
|
||||
|
||||
item->Animation.TargetState = SMAN_STATE_MOVING;
|
||||
skidoo->Animation.TargetState = SMAN_STATE_MOVING;
|
||||
break;
|
||||
|
||||
case SMAN_STATE_MOVING:
|
||||
if (creatureInfo->Mood == MoodType::Bored)
|
||||
item->Animation.TargetState = SMAN_STATE_WAIT;
|
||||
skidoo->Animation.TargetState = SMAN_STATE_WAIT;
|
||||
else if (abs(AI.angle) < SMAN_TARGET_ANGLE && AI.distance < SMAN_WAIT_RANGE)
|
||||
item->Animation.TargetState = SMAN_STATE_WAIT;
|
||||
skidoo->Animation.TargetState = SMAN_STATE_WAIT;
|
||||
else if (angle < -SMAN_MIN_TURN)
|
||||
item->Animation.TargetState = SMAN_STATE_START_LEFT;
|
||||
skidoo->Animation.TargetState = SMAN_STATE_START_LEFT;
|
||||
else if (angle > SMAN_MIN_TURN)
|
||||
item->Animation.TargetState = SMAN_STATE_START_RIGHT;
|
||||
skidoo->Animation.TargetState = SMAN_STATE_START_RIGHT;
|
||||
|
||||
break;
|
||||
|
||||
case SMAN_STATE_START_LEFT:
|
||||
case SMAN_STATE_LEFT:
|
||||
if (angle < -SMAN_MIN_TURN)
|
||||
item->Animation.TargetState = SMAN_STATE_LEFT;
|
||||
skidoo->Animation.TargetState = SMAN_STATE_LEFT;
|
||||
else
|
||||
item->Animation.TargetState = SMAN_STATE_MOVING;
|
||||
skidoo->Animation.TargetState = SMAN_STATE_MOVING;
|
||||
|
||||
break;
|
||||
|
||||
case SMAN_STATE_START_RIGHT:
|
||||
case SMAN_STATE_RIGHT:
|
||||
if (angle < -SMAN_MIN_TURN)
|
||||
item->Animation.TargetState = SMAN_STATE_LEFT;
|
||||
skidoo->Animation.TargetState = SMAN_STATE_LEFT;
|
||||
else
|
||||
item->Animation.TargetState = SMAN_STATE_MOVING;
|
||||
skidoo->Animation.TargetState = SMAN_STATE_MOVING;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (riderItem->Animation.ActiveState != SMAN_STATE_DEATH)
|
||||
if (rider->Animation.ActiveState != SMAN_STATE_DEATH)
|
||||
{
|
||||
if (!creatureInfo->Flags && abs(AI.angle) < SMAN_TARGET_ANGLE && LaraItem->HitPoints > 0)
|
||||
if (creatureInfo->Flags == 0 && abs(AI.angle) < SMAN_TARGET_ANGLE && creatureInfo->Enemy->HitPoints > 0)
|
||||
{
|
||||
damage = (Lara.Context.Vehicle != NO_ITEM) ? 10 : 50;
|
||||
int damage = (creatureInfo->Enemy->IsLara() && GetLaraInfo(creatureInfo->Enemy)->Context.Vehicle != NO_ITEM) ? 10 : 50;
|
||||
|
||||
if (ShotLara(item, &AI, SkidooBiteLeft, 0, damage) + ShotLara(item, &AI, SkidooBiteRight, 0, damage))
|
||||
creatureInfo->Flags = 5;
|
||||
ShotLara(skidoo, &AI, SkidooBiteLeft, 0, damage);
|
||||
auto jointPos = GetJointPosition(skidoo, SkidooBiteSmokeLeft);
|
||||
TriggerGunSmokeParticles(jointPos.x, jointPos.y, jointPos.z, 0, 0, 0, 1, LaraWeaponType::Snowmobile, 16, skidoo->RoomNumber);
|
||||
creatureInfo->MuzzleFlash[0].Bite = SkidooBiteLeft;
|
||||
creatureInfo->MuzzleFlash[0].Delay = 1;
|
||||
creatureInfo->MuzzleFlash[0].SwitchToMuzzle2 = true;
|
||||
creatureInfo->MuzzleFlash[0].ApplyXRotation = false;
|
||||
creatureInfo->MuzzleFlash[0].UseSmoke = false;
|
||||
|
||||
ShotLara(skidoo, &AI, SkidooBiteRight, 0, damage);
|
||||
jointPos = GetJointPosition(skidoo, SkidooBiteSmokeRight);
|
||||
TriggerGunSmokeParticles(jointPos.x, jointPos.y, jointPos.z, 0, 0, 0, 1, LaraWeaponType::Snowmobile, 16, skidoo->RoomNumber);
|
||||
creatureInfo->MuzzleFlash[1].Bite = SkidooBiteRight;
|
||||
creatureInfo->MuzzleFlash[1].Delay = 1;
|
||||
creatureInfo->MuzzleFlash[1].SwitchToMuzzle2 = true;
|
||||
creatureInfo->MuzzleFlash[1].ApplyXRotation = false;
|
||||
creatureInfo->MuzzleFlash[1].UseSmoke = false;
|
||||
|
||||
creatureInfo->Flags = 4;
|
||||
}
|
||||
|
||||
if (creatureInfo->Flags)
|
||||
if (creatureInfo->Flags != 0)
|
||||
{
|
||||
SoundEffect(SFX_TR4_BADDY_UZI, &item->Pose);
|
||||
SoundEffect(SFX_TR4_BADDY_UZI, &skidoo->Pose);
|
||||
creatureInfo->Flags--;
|
||||
}
|
||||
}
|
||||
|
||||
if (item->Animation.ActiveState == SMAN_STATE_WAIT)
|
||||
if (skidoo->Animation.ActiveState == SMAN_STATE_WAIT)
|
||||
{
|
||||
SoundEffect(SFX_TR2_VEHICLE_SNOWMOBILE_IDLE, &item->Pose);
|
||||
SoundEffect(SFX_TR2_VEHICLE_SNOWMOBILE_IDLE, &skidoo->Pose);
|
||||
creatureInfo->JointRotation[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
creatureInfo->JointRotation[0] = (creatureInfo->JointRotation[0] == 1) ? 2 : 1;
|
||||
DoSnowEffect(item);
|
||||
SoundEffect(SFX_TR2_VEHICLE_SNOWMOBILE_IDLE, &item->Pose, SoundEnvironment::Land, 0.5f + item->Animation.Velocity.z / 100.0f); // SKIDOO_MAX_VELOCITY. TODO: Check actual sound!
|
||||
DoSnowEffect(skidoo);
|
||||
SoundEffect(SFX_TR2_VEHICLE_SNOWMOBILE_IDLE, &skidoo->Pose, SoundEnvironment::Land, 0.5f + skidoo->Animation.Velocity.z / 100.0f); // SKIDOO_MAX_VELOCITY. TODO: Check actual sound!
|
||||
}
|
||||
|
||||
CreatureAnimation(itemNumber, angle, 0);
|
||||
|
||||
if (riderItem->Animation.ActiveState != SMAN_STATE_DEATH)
|
||||
if (rider->Animation.ActiveState != SMAN_STATE_DEATH)
|
||||
{
|
||||
riderItem->Pose.Position = item->Pose.Position;
|
||||
riderItem->Pose.Orientation.y = item->Pose.Orientation.y;
|
||||
rider->Pose.Position = skidoo->Pose.Position;
|
||||
rider->Pose.Orientation.y = skidoo->Pose.Orientation.y;
|
||||
|
||||
if (item->RoomNumber != riderItem->RoomNumber)
|
||||
ItemNewRoom(riderItemNumber, item->RoomNumber);
|
||||
if (skidoo->RoomNumber != rider->RoomNumber)
|
||||
ItemNewRoom(riderItemNumber, skidoo->RoomNumber);
|
||||
|
||||
riderItem->Animation.AnimNumber = item->Animation.AnimNumber + (Objects[ID_SNOWMOBILE_DRIVER].animIndex - Objects[ID_SNOWMOBILE_GUN].animIndex);
|
||||
riderItem->Animation.FrameNumber = item->Animation.FrameNumber + (g_Level.Anims[riderItem->Animation.AnimNumber].frameBase - g_Level.Anims[item->Animation.AnimNumber].frameBase);
|
||||
rider->Animation.AnimNumber = skidoo->Animation.AnimNumber + (Objects[ID_SNOWMOBILE_DRIVER].animIndex - Objects[ID_SNOWMOBILE_GUN].animIndex);
|
||||
rider->Animation.FrameNumber = skidoo->Animation.FrameNumber + (g_Level.Anims[rider->Animation.AnimNumber].frameBase - g_Level.Anims[skidoo->Animation.AnimNumber].frameBase);
|
||||
}
|
||||
else if (riderItem->Status == ITEM_DEACTIVATED &&
|
||||
item->Animation.Velocity.z == 0 &&
|
||||
item->Animation.Velocity.y == 0)
|
||||
else if (rider->Status == ITEM_DEACTIVATED &&
|
||||
skidoo->Animation.Velocity.z == 0 &&
|
||||
skidoo->Animation.Velocity.y == 0)
|
||||
{
|
||||
RemoveActiveItem(riderItemNumber);
|
||||
riderItem->Collidable = false;
|
||||
riderItem->HitPoints = NOT_TARGETABLE;
|
||||
riderItem->Flags |= IFLAG_INVISIBLE;
|
||||
rider->Collidable = false;
|
||||
rider->HitPoints = NOT_TARGETABLE;
|
||||
rider->Flags |= IFLAG_INVISIBLE;
|
||||
|
||||
DisableEntityAI(itemNumber);
|
||||
item->ObjectNumber = ID_SNOWMOBILE;
|
||||
item->Status = ITEM_DEACTIVATED;
|
||||
InitializeSkidoo(itemNumber);
|
||||
skidoo->ObjectNumber = ID_SNOWMOBILE;
|
||||
skidoo->Status = ITEM_DEACTIVATED;
|
||||
|
||||
((SkidooInfo*)item->Data)->Armed = true;
|
||||
InitializeSkidoo(itemNumber);
|
||||
if (skidoo->Data.is<SkidooInfo>())
|
||||
{
|
||||
auto* skidooData = (SkidooInfo*)skidoo->Data;
|
||||
skidooData->Armed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,8 +34,8 @@ namespace TEN::Entities::Creatures::TR2
|
|||
|
||||
constexpr auto SPEAR_GUARDIAN_SWAPMESH_TIME = 3;
|
||||
|
||||
const auto SpearGuardianBiteLeft = BiteInfo(Vector3(0.0f, 0.0f, 920.0f), 11);
|
||||
const auto SpearGuardianBiteRight = BiteInfo(Vector3(0.0f, 0.0f, 920.0f), 18);
|
||||
const auto SpearGuardianBiteLeft = CreatureBiteInfo(Vector3i(0, 0, 920), 11);
|
||||
const auto SpearGuardianBiteRight = CreatureBiteInfo(Vector3i(0, 0, 920), 18);
|
||||
|
||||
enum SpearGuardianState
|
||||
{
|
||||
|
@ -108,7 +108,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
{
|
||||
auto& creature = *GetCreatureInfo(&item);
|
||||
|
||||
if (!(creature.Flags & 1) && item.TouchBits.Test(SpearGuardianBiteRight.meshNum))
|
||||
if (!(creature.Flags & 1) && item.TouchBits.Test(SpearGuardianBiteRight.BoneID))
|
||||
{
|
||||
DoDamage(creature.Enemy, damage);
|
||||
CreatureEffect(&item, SpearGuardianBiteRight, DoBloodSplat);
|
||||
|
@ -116,7 +116,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
SoundEffect(SFX_TR2_CRUNCH2, &item.Pose);
|
||||
}
|
||||
|
||||
if (!(creature.Flags & 2) && item.TouchBits.Test(SpearGuardianBiteLeft.meshNum))
|
||||
if (!(creature.Flags & 2) && item.TouchBits.Test(SpearGuardianBiteLeft.BoneID))
|
||||
{
|
||||
DoDamage(creature.Enemy, damage);
|
||||
CreatureEffect(&item, SpearGuardianBiteLeft, DoBloodSplat);
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
constexpr auto SMALL_SPIDER_TURN_RATE_MAX = ANGLE(8.0f);
|
||||
constexpr auto BIG_SPIDER_TURN_RATE_MAX = ANGLE(4.0f);
|
||||
|
||||
const auto SpiderBite = BiteInfo(Vector3(0.0f, 0.0f, 41.0f), 1);
|
||||
const auto SpiderBite = CreatureBiteInfo(Vector3i(0, 0, 41), 1);
|
||||
|
||||
enum SpiderState
|
||||
{
|
||||
|
@ -72,7 +72,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
|
||||
void DoSpiderBloodEffect(ItemInfo& item)
|
||||
{
|
||||
auto pos = GetJointPosition(&item, SpiderBite.meshNum, SpiderBite.Position);
|
||||
auto pos = GetJointPosition(&item, SpiderBite);
|
||||
DoBloodSplat(pos.x, pos.y, pos.z, 10, item.Pose.Position.y, item.RoomNumber);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
|
||||
constexpr auto SWORD_GUARDIAN_MESH_SWAP_TIME = 3;
|
||||
|
||||
const auto SwordBite = BiteInfo(Vector3(0.0f, 37.0f, 550.0f), 15);
|
||||
const auto SwordBite = CreatureBiteInfo(Vector3i(0, 37, 550), 15);
|
||||
|
||||
enum SwordGuardianState
|
||||
{
|
||||
|
@ -352,7 +352,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
extraTorsoRot.y = ai.angle;
|
||||
}
|
||||
|
||||
if (!creature->Flags && item->TouchBits.Test(SwordBite.meshNum))
|
||||
if (!creature->Flags && item->TouchBits.Test(SwordBite.BoneID))
|
||||
{
|
||||
DoDamage(creature->Enemy, SWORD_GUARDIAN_ATTACK_DAMAGE);
|
||||
CreatureEffect(item, SwordBite, DoBloodSplat);
|
||||
|
|
|
@ -12,8 +12,8 @@
|
|||
|
||||
namespace TEN::Entities::Creatures::TR2
|
||||
{
|
||||
const auto WorkerDualGunBiteLeft = BiteInfo(Vector3(-2.0f, 275.0f, 23.0f), 6);
|
||||
const auto WorkerDualGunBiteRight = BiteInfo(Vector3(2.0f, 275.0f, 23.0f), 10);
|
||||
const auto WorkerDualGunBiteLeft = CreatureBiteInfo(Vector3i(-2, 340, 23), 6);
|
||||
const auto WorkerDualGunBiteRight = CreatureBiteInfo(Vector3i(2, 340, 23), 10);
|
||||
|
||||
// TODO
|
||||
enum WorkerDualGunState
|
||||
|
@ -40,6 +40,11 @@ namespace TEN::Entities::Creatures::TR2
|
|||
auto extraHeadRot = EulerAngles::Zero;
|
||||
auto extraTorsoRot = EulerAngles::Zero;
|
||||
|
||||
if (creature->MuzzleFlash[0].Delay != 0)
|
||||
creature->MuzzleFlash[0].Delay--;
|
||||
if (creature->MuzzleFlash[1].Delay != 0)
|
||||
creature->MuzzleFlash[1].Delay--;
|
||||
|
||||
if (item->HitPoints <= 0)
|
||||
{
|
||||
if (item->Animation.ActiveState != 11)
|
||||
|
@ -223,9 +228,11 @@ namespace TEN::Entities::Creatures::TR2
|
|||
extraTorsoRot.y = AI.angle;
|
||||
}
|
||||
|
||||
if (!creature->Flags)
|
||||
if (creature->Flags == 0 && TestAnimFrame(*item, 0))
|
||||
{
|
||||
ShotLara(item, &AI, WorkerDualGunBiteLeft, extraTorsoRot.y, 50);
|
||||
creature->MuzzleFlash[0].Bite = WorkerDualGunBiteLeft;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
creature->Flags = 1;
|
||||
}
|
||||
|
||||
|
@ -238,9 +245,11 @@ namespace TEN::Entities::Creatures::TR2
|
|||
extraTorsoRot.y = AI.angle;
|
||||
}
|
||||
|
||||
if (!creature->Flags)
|
||||
if (creature->Flags == 0 && TestAnimFrame(*item, 0))
|
||||
{
|
||||
ShotLara(item, &AI, WorkerDualGunBiteRight, extraTorsoRot.y, 50);
|
||||
creature->MuzzleFlash[0].Bite = WorkerDualGunBiteRight;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
creature->Flags = 1;
|
||||
}
|
||||
|
||||
|
@ -269,10 +278,14 @@ namespace TEN::Entities::Creatures::TR2
|
|||
extraTorsoRot.y = AI.angle;
|
||||
}
|
||||
|
||||
if (!creature->Flags)
|
||||
if (creature->Flags == 0 && item->Animation.FrameNumber == GetFrameIndex(item, 0))
|
||||
{
|
||||
ShotLara(item, &AI, WorkerDualGunBiteLeft, extraTorsoRot.y, 50);
|
||||
ShotLara(item, &AI, WorkerDualGunBiteRight, extraTorsoRot.y, 50);
|
||||
creature->MuzzleFlash[0].Bite = WorkerDualGunBiteLeft;
|
||||
creature->MuzzleFlash[0].Delay = 1;
|
||||
creature->MuzzleFlash[1].Bite = WorkerDualGunBiteRight;
|
||||
creature->MuzzleFlash[1].Delay = 1;
|
||||
creature->Flags = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
constexpr auto WORKER_FLAME_RUN_TURN_RATE_MAX = ANGLE(10.0f);
|
||||
|
||||
const auto WorkerFlamethrowerOffset = Vector3i(0, 140, 0);
|
||||
const auto WorkerFlamethrowerBite = BiteInfo(Vector3(0.0f, 250.0f, 32.0f), 9);
|
||||
const auto WorkerFlamethrowerBite = CreatureBiteInfo(Vector3(0.0f, 250.0f, 32.0f), 9);
|
||||
|
||||
enum WorkerFlamethrowerState
|
||||
{
|
||||
|
@ -70,8 +70,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
auto extraHeadRot = EulerAngles::Zero;
|
||||
auto extraTorsoRot = EulerAngles::Zero;
|
||||
|
||||
auto pos = GetJointPosition(item, WorkerFlamethrowerBite.meshNum, Vector3i(WorkerFlamethrowerBite.Position));
|
||||
|
||||
auto pos = GetJointPosition(item, WorkerFlamethrowerBite.BoneID, WorkerFlamethrowerBite.Position);
|
||||
if (item->HitPoints <= 0)
|
||||
{
|
||||
if (item->Animation.ActiveState != WORKER_FLAME_STATE_DEATH)
|
||||
|
@ -82,12 +81,12 @@ namespace TEN::Entities::Creatures::TR2
|
|||
if (item->Animation.ActiveState != WORKER_FLAME_STATE_ATTACK && item->Animation.ActiveState != WORKER_FLAME_STATE_WALK_FORWARD_ATTACK)
|
||||
{
|
||||
TriggerDynamicLight(pos.x, pos.y, pos.z, (GetRandomControl() & 4) + 10, (GetRandomControl() & 7) + 128, (GetRandomControl() & 7) + 64, GetRandomControl() & 7);
|
||||
TriggerPilotFlame(itemNumber, WorkerFlamethrowerBite.meshNum);
|
||||
TriggerPilotFlame(itemNumber, WorkerFlamethrowerBite.BoneID);
|
||||
}
|
||||
else
|
||||
{
|
||||
TriggerDynamicLight(pos.x, pos.y, pos.z, (GetRandomControl() & 4) + 14, (GetRandomControl() & 7) + 128, (GetRandomControl() & 7) + 64, GetRandomControl() & 7);
|
||||
ThrowFire(itemNumber, WorkerFlamethrowerBite.meshNum, WorkerFlamethrowerOffset, WorkerFlamethrowerOffset);
|
||||
ThrowFire(itemNumber, WorkerFlamethrowerBite.BoneID, WorkerFlamethrowerOffset, WorkerFlamethrowerOffset);
|
||||
}
|
||||
|
||||
AI_INFO AI;
|
||||
|
|
|
@ -13,16 +13,34 @@
|
|||
|
||||
namespace TEN::Entities::Creatures::TR2
|
||||
{
|
||||
const auto WorkerMachineGunBite = BiteInfo(Vector3(0.0f, 308.0f, 32.0f), 9);
|
||||
const auto WorkerMachineGunBite = CreatureBiteInfo(Vector3i(0, 380, 37), 9);
|
||||
|
||||
// TODO
|
||||
enum WorkerMachineGunState
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
// TODO
|
||||
enum WorkerMachineGunAnim
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
void InitializeWorkerMachineGun(short itemNumber)
|
||||
{
|
||||
auto* item = &g_Level.Items[itemNumber];
|
||||
|
||||
InitializeCreature(itemNumber);
|
||||
SetAnimation(item, 12);
|
||||
}
|
||||
|
||||
static void Shoot(ItemInfo* item, CreatureInfo* creature, AI_INFO* ai, const EulerAngles& extraTorsoRot)
|
||||
{
|
||||
ShotLara(item, ai, WorkerMachineGunBite, extraTorsoRot.y, 30);
|
||||
creature->MuzzleFlash[0].Bite = WorkerMachineGunBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
}
|
||||
|
||||
void WorkerMachineGunControl(short itemNumber)
|
||||
{
|
||||
if (!CreatureActive(itemNumber))
|
||||
|
@ -36,6 +54,9 @@ namespace TEN::Entities::Creatures::TR2
|
|||
auto extraHeadRot = EulerAngles::Zero;
|
||||
auto extraTorsoRot = EulerAngles::Zero;
|
||||
|
||||
if (creature->MuzzleFlash[0].Delay != 0)
|
||||
creature->MuzzleFlash[0].Delay--;
|
||||
|
||||
if (item->HitPoints <= 0)
|
||||
{
|
||||
if (item->Animation.ActiveState != 7)
|
||||
|
@ -191,13 +212,19 @@ namespace TEN::Entities::Creatures::TR2
|
|||
extraTorsoRot.y = AI.angle;
|
||||
}
|
||||
|
||||
if (creature->Flags)
|
||||
creature->Flags--;
|
||||
else
|
||||
if (item->Animation.AnimNumber == GetAnimIndex(*item, 2))
|
||||
{
|
||||
ShotLara(item, &AI, WorkerMachineGunBite, extraTorsoRot.y, 30);
|
||||
creature->FiredWeapon = 1;
|
||||
creature->Flags = 5;
|
||||
if (item->Animation.FrameNumber == GetFrameIndex(item, 0))
|
||||
Shoot(item, creature, &AI, extraTorsoRot);
|
||||
else if (item->Animation.FrameNumber == GetFrameIndex(item, 6))
|
||||
Shoot(item, creature, &AI, extraTorsoRot);
|
||||
else if (item->Animation.FrameNumber == GetFrameIndex(item, 12))
|
||||
Shoot(item, creature, &AI, extraTorsoRot);
|
||||
}
|
||||
else if (item->Animation.AnimNumber == GetAnimIndex(*item, 21) &&
|
||||
item->Animation.FrameNumber == GetFrameIndex(item, 0))
|
||||
{
|
||||
Shoot(item, creature, &AI, extraTorsoRot);
|
||||
}
|
||||
|
||||
if (item->Animation.TargetState != 1 &&
|
||||
|
@ -215,14 +242,14 @@ namespace TEN::Entities::Creatures::TR2
|
|||
extraTorsoRot.y = AI.angle;
|
||||
}
|
||||
|
||||
if (creature->Flags)
|
||||
creature->Flags--;
|
||||
else
|
||||
{
|
||||
ShotLara(item, &AI, WorkerMachineGunBite, extraTorsoRot.y, 30);
|
||||
creature->FiredWeapon = 1;
|
||||
creature->Flags = 5;
|
||||
}
|
||||
if (item->Animation.FrameNumber == GetFrameIndex(item, 0))
|
||||
Shoot(item, creature, &AI, extraTorsoRot);
|
||||
else if (item->Animation.FrameNumber == GetFrameIndex(item, 2))
|
||||
Shoot(item, creature, &AI, extraTorsoRot);
|
||||
else if (item->Animation.FrameNumber == GetFrameIndex(item, 6))
|
||||
Shoot(item, creature, &AI, extraTorsoRot);
|
||||
else if (item->Animation.FrameNumber == GetFrameIndex(item, 12))
|
||||
Shoot(item, creature, &AI, extraTorsoRot);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
{
|
||||
constexpr auto WORKER_SHOTGUN_NUM_SHOTS = 6;
|
||||
|
||||
const auto WorkerShotgunBite = BiteInfo(Vector3(0.0f, 281.0f, 40.0f), 9);
|
||||
const auto WorkerShotgunBite = CreatureBiteInfo(Vector3i(0, 350, 40), 9);
|
||||
|
||||
// TODO
|
||||
enum ShotgunWorkerState
|
||||
|
@ -30,7 +30,7 @@ namespace TEN::Entities::Creatures::TR2
|
|||
|
||||
};
|
||||
|
||||
void ShotLaraWithShotgun(ItemInfo* item, AI_INFO* info, BiteInfo bite, short angleY, int damage)
|
||||
void ShotLaraWithShotgun(ItemInfo* item, AI_INFO* info, const CreatureBiteInfo& bite, short angleY, int damage)
|
||||
{
|
||||
for (int i = 0; i < WORKER_SHOTGUN_NUM_SHOTS; i++)
|
||||
ShotLara(item, info, bite, angleY, damage);
|
||||
|
@ -57,12 +57,8 @@ namespace TEN::Entities::Creatures::TR2
|
|||
auto extraHeadRot = EulerAngles::Zero;
|
||||
auto extraTorsoRot = EulerAngles::Zero;
|
||||
|
||||
if (creature->FiredWeapon)
|
||||
{
|
||||
auto pos = GetJointPosition(item, WorkerShotgunBite.meshNum, Vector3i(WorkerShotgunBite.Position));
|
||||
TriggerDynamicLight(pos.x, pos.y, pos.z, (creature->FiredWeapon * 2) + 4, 24, 16, 4);
|
||||
creature->FiredWeapon--;
|
||||
}
|
||||
if (creature->MuzzleFlash[0].Delay != 0)
|
||||
creature->MuzzleFlash[0].Delay--;
|
||||
|
||||
if (item->HitPoints <= 0)
|
||||
{
|
||||
|
@ -202,10 +198,11 @@ namespace TEN::Entities::Creatures::TR2
|
|||
extraTorsoRot.y = AI.angle;
|
||||
}
|
||||
|
||||
if (!creature->Flags)
|
||||
if (creature->Flags == 0)
|
||||
{
|
||||
ShotLaraWithShotgun(item, &AI, WorkerShotgunBite, extraTorsoRot.y, 25);
|
||||
creature->FiredWeapon = 2;
|
||||
creature->MuzzleFlash[0].Bite = WorkerShotgunBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
creature->Flags = 1;
|
||||
}
|
||||
|
||||
|
@ -224,10 +221,11 @@ namespace TEN::Entities::Creatures::TR2
|
|||
extraTorsoRot.y = AI.angle;
|
||||
}
|
||||
|
||||
if (!creature->Flags)
|
||||
if (creature->Flags == 0)
|
||||
{
|
||||
creature->MuzzleFlash[0].Bite = WorkerShotgunBite;
|
||||
creature->MuzzleFlash[0].Delay = 1;
|
||||
ShotLaraWithShotgun(item, &AI, WorkerShotgunBite, extraTorsoRot.y, 25);
|
||||
creature->FiredWeapon = 2;
|
||||
creature->Flags = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@ using namespace TEN::Math;
|
|||
|
||||
namespace TEN::Entities::Creatures::TR2
|
||||
{
|
||||
const auto YetiBiteLeft = BiteInfo(Vector3(12.0f, 101.0f, 19.0f), 13);
|
||||
const auto YetiBiteRight = BiteInfo(Vector3(12.0f, 101.0f, 19.0f), 10);
|
||||
const auto YetiBiteLeft = CreatureBiteInfo(Vector3i(12, 101, 19), 13);
|
||||
const auto YetiBiteRight = CreatureBiteInfo(Vector3i(12, 101, 19), 10);
|
||||
const auto YetiAttackJoints1 = std::vector<unsigned int>{ 10, 12 }; // TODO: Rename.
|
||||
const auto YetiAttackJoints2 = std::vector<unsigned int>{ 8, 9, 10 };
|
||||
|
||||
|
|
|
@ -129,9 +129,6 @@ namespace TEN::Entities::Vehicles
|
|||
skidooItem->Status = ITEM_ACTIVE;
|
||||
}
|
||||
|
||||
if (skidooItem->ObjectNumber == ID_SNOWMOBILE_GUN)
|
||||
skidoo->Armed = true;
|
||||
|
||||
skidoo->MomentumAngle = skidooItem->Pose.Orientation.y;
|
||||
}
|
||||
|
||||
|
@ -204,6 +201,7 @@ namespace TEN::Entities::Vehicles
|
|||
bool TestSkidooDismount(ItemInfo* skidooItem, ItemInfo* laraItem)
|
||||
{
|
||||
auto* lara = GetLaraInfo(laraItem);
|
||||
auto* skidoo = GetSkidooInfo(skidooItem);
|
||||
|
||||
if (lara->Context.Vehicle != NO_ITEM)
|
||||
{
|
||||
|
@ -220,6 +218,8 @@ namespace TEN::Entities::Vehicles
|
|||
laraItem->Pose.Orientation.x = 0;
|
||||
laraItem->Pose.Orientation.z = 0;
|
||||
lara->Control.HandStatus = HandStatus::Free;
|
||||
if (skidoo->Armed)
|
||||
lara->Control.Weapon.GunType = lara->Control.Weapon.LastGunType;
|
||||
SetLaraVehicle(laraItem, nullptr);
|
||||
}
|
||||
else if (laraItem->Animation.ActiveState == SKIDOO_STATE_JUMP_OFF &&
|
||||
|
@ -248,6 +248,9 @@ namespace TEN::Entities::Vehicles
|
|||
laraItem->Animation.IsAirborne = true;
|
||||
lara->Control.MoveAngle = skidooItem->Pose.Orientation.y;
|
||||
lara->Control.HandStatus = HandStatus::Free;
|
||||
lara->Control.Weapon.GunType = lara->Control.Weapon.LastGunType;
|
||||
if (skidoo->Armed)
|
||||
lara->Control.Weapon.GunType = lara->Control.Weapon.LastGunType;
|
||||
skidooItem->Collidable = false;
|
||||
skidooItem->Flags |= IFLAG_INVISIBLE;
|
||||
|
||||
|
@ -663,7 +666,7 @@ namespace TEN::Entities::Vehicles
|
|||
FindNewTarget(*laraItem, weapon);
|
||||
AimWeapon(*laraItem, lara->RightArm, weapon);
|
||||
|
||||
if (TrInput & VEHICLE_IN_FIRE && !skidooItem->ItemFlags[0])
|
||||
if (IsHeld(In::DrawWeapon) && !skidooItem->ItemFlags[0])
|
||||
{
|
||||
auto angles = EulerAngles(
|
||||
lara->RightArm.Orientation.x,
|
||||
|
@ -671,14 +674,13 @@ namespace TEN::Entities::Vehicles
|
|||
0
|
||||
);
|
||||
|
||||
if ((int)FireWeapon(LaraWeaponType::Pistol, *lara->TargetEntity, *laraItem, angles) +
|
||||
(int)FireWeapon(LaraWeaponType::Pistol, *lara->TargetEntity, *laraItem, angles))
|
||||
{
|
||||
skidoo->FlashTimer = 2;
|
||||
FireWeapon(LaraWeaponType::Snowmobile, *lara->TargetEntity, *laraItem, angles);
|
||||
FireWeapon(LaraWeaponType::Snowmobile, *lara->TargetEntity, *laraItem, angles);
|
||||
//lara->LeftArm.GunFlash = 1;
|
||||
//lara->RightArm.GunFlash = 1;
|
||||
SoundEffect(weapon.SampleNum, &laraItem->Pose);
|
||||
skidooItem->ItemFlags[0] = 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (skidooItem->ItemFlags[0])
|
||||
skidooItem->ItemFlags[0]--;
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "Specific/level.h"
|
||||
#include "Specific/setup.h"
|
||||
|
||||
#include "Game/missile.h"
|
||||
|
||||
// Creatures
|
||||
#include "Objects/TR2/Entity/tr2_barracuda.h" // OK
|
||||
#include "Objects/TR2/Entity/tr2_bird_monster.h" // OK
|
||||
|
@ -145,7 +147,6 @@ static void StartEntity(ObjectInfo* obj)
|
|||
obj->control = SilencerControl;
|
||||
obj->shadowType = ShadowMode::All;
|
||||
obj->HitPoints = 25;
|
||||
obj->biteOffset = 0;
|
||||
obj->radius = 102;
|
||||
obj->pivotLength = 50;
|
||||
obj->intelligent = true;
|
||||
|
@ -163,7 +164,6 @@ static void StartEntity(ObjectInfo* obj)
|
|||
obj->control = SilencerControl;
|
||||
obj->shadowType = ShadowMode::All;
|
||||
obj->HitPoints = 25;
|
||||
obj->biteOffset = 0;
|
||||
obj->radius = 102;
|
||||
obj->pivotLength = 50;
|
||||
obj->intelligent = true;
|
||||
|
@ -181,7 +181,6 @@ static void StartEntity(ObjectInfo* obj)
|
|||
obj->control = SilencerControl;
|
||||
obj->shadowType = ShadowMode::All;
|
||||
obj->HitPoints = 25;
|
||||
obj->biteOffset = 0;
|
||||
obj->radius = 102;
|
||||
obj->pivotLength = 50;
|
||||
obj->intelligent = true;
|
||||
|
@ -197,7 +196,6 @@ static void StartEntity(ObjectInfo* obj)
|
|||
obj->collision = CreatureCollision;
|
||||
obj->control = WorkerShotgunControl;
|
||||
obj->shadowType = ShadowMode::All;
|
||||
obj->biteOffset = 0;
|
||||
obj->HitPoints = 25;
|
||||
obj->pivotLength = 50;
|
||||
obj->radius = 102;
|
||||
|
@ -315,10 +313,6 @@ static void StartEntity(ObjectInfo* obj)
|
|||
obj->SetupHitEffect();
|
||||
}
|
||||
|
||||
obj = &Objects[ID_KNIFETHROWER_KNIFE];
|
||||
if (obj->loaded)
|
||||
obj->control = KnifeControl;
|
||||
|
||||
obj = &Objects[ID_MERCENARY_UZI];
|
||||
if (obj->loaded)
|
||||
{
|
||||
|
@ -478,22 +472,23 @@ static void StartEntity(ObjectInfo* obj)
|
|||
obj->pivotLength = 0;
|
||||
obj->radius = 256;
|
||||
obj->intelligent = true;
|
||||
obj->LotType = LotType::SnowmobileGun;
|
||||
obj->SetupHitEffect();
|
||||
}
|
||||
|
||||
obj = &Objects[ID_SNOWMOBILE_DRIVER];
|
||||
if (obj->loaded)
|
||||
{
|
||||
CheckIfSlotExists(ID_SNOWMOBILE_GUN, "ID_SNOWMOBILE_DRIVER", "ID_SNOWMOBILE_GUN");
|
||||
obj->Initialize = InitializeSkidooMan;
|
||||
obj->control = SkidooManControl;
|
||||
obj->HitPoints = 1;
|
||||
obj->SetupHitEffect(true);
|
||||
}
|
||||
}
|
||||
|
||||
static void StartObject(ObjectInfo* obj)
|
||||
{
|
||||
|
||||
InitProjectile(obj, ControlMissile, ID_KNIFETHROWER_KNIFE);
|
||||
}
|
||||
|
||||
static void StartTrap(ObjectInfo* obj)
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
constexpr auto COMPY_PLAYER_ALERT_VELOCITY = 15;
|
||||
constexpr auto COMPY_HIT_FLAG = 1;
|
||||
|
||||
const auto CompyBite = BiteInfo(Vector3::Zero, 2);
|
||||
const auto CompyBite = CreatureBiteInfo(Vector3i::Zero, 2);
|
||||
const auto CompyAttackJoints = std::vector<unsigned int>{ 1, 2 };
|
||||
|
||||
enum CompyState
|
||||
|
|
|
@ -27,9 +27,9 @@ namespace TEN::Entities::Creatures::TR3
|
|||
|
||||
constexpr auto LIZARD_VAULT_SHIFT = 260;
|
||||
|
||||
const auto LizardBiteAttackBite = BiteInfo(Vector3(0.0f, -120.0f, 120.0f), 10);
|
||||
const auto LizardSwipeAttackBite = BiteInfo(Vector3::Zero, 5);
|
||||
const auto LizardGasBite = BiteInfo(Vector3(0.0f, -64.0f, 56.0f), 9);
|
||||
const auto LizardBiteAttackBite = CreatureBiteInfo(Vector3i(0, -120, 120), 10);
|
||||
const auto LizardSwipeAttackBite = CreatureBiteInfo(Vector3i::Zero, 5);
|
||||
const auto LizardGasBite = CreatureBiteInfo(Vector3i(0, -64, 56), 9);
|
||||
const auto LizardSwipeAttackJoints = std::vector<unsigned int>{ 5 };
|
||||
const auto LizardBiteAttackJoints = std::vector<unsigned int>{ 10 };
|
||||
|
||||
|
@ -72,14 +72,13 @@ namespace TEN::Entities::Creatures::TR3
|
|||
(g_Level.Boxes[creature.Enemy->BoxNumber].flags & BLOCKABLE));
|
||||
}
|
||||
|
||||
static void SpawnLizardGas(int itemNumber, const BiteInfo& bite, int speed)
|
||||
static void SpawnLizardGas(int itemNumber, const CreatureBiteInfo& bite, int speed)
|
||||
{
|
||||
static constexpr auto numPoisonThrows = 2;
|
||||
|
||||
for (int i = 0; i < numPoisonThrows; i++)
|
||||
ThrowPoison(itemNumber, bite.meshNum, Vector3i(bite.Position), Vector3i(0.0f, -100.0f, speed << 2), Vector3(0.0f, 1.0f, 0.0f));
|
||||
|
||||
ThrowPoison(itemNumber, bite.meshNum, Vector3i(bite.Position), Vector3i(0.0f, -100.0f, speed << 1), Vector3(0.0f, 1.0f, 0.0f));
|
||||
ThrowPoison(itemNumber, bite, Vector3i(0.0f, -100.0f, speed << 2), Vector3(0.0f, 1.0f, 0.0f));
|
||||
ThrowPoison(itemNumber, bite, Vector3i(0.0f, -100.0f, speed << 1), Vector3(0.0f, 1.0f, 0.0f));
|
||||
}
|
||||
|
||||
void LizardControl(short itemNumber)
|
||||
|
|
|
@ -36,8 +36,8 @@ namespace TEN::Entities::Creatures::TR3
|
|||
constexpr auto PUNA_EXPLOSION_MAIN_COLOR = Vector4(0.0f, 0.7f, 0.3f, 0.5f);
|
||||
constexpr auto PUNA_EXPLOSION_SECOND_COLOR = Vector4(0.1f, 0.3f, 0.7f, 0.5f);
|
||||
|
||||
const auto PunaBossHeadBite = BiteInfo(Vector3::Zero, 8);
|
||||
const auto PunaBossHandBite = BiteInfo(Vector3::Zero, 14);
|
||||
const auto PunaBossHeadBite = CreatureBiteInfo(Vector3i::Zero, 8);
|
||||
const auto PunaBossHandBite = CreatureBiteInfo(Vector3i::Zero, 14);
|
||||
|
||||
enum PunaState
|
||||
{
|
||||
|
@ -68,7 +68,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
if (!item.TestFlags((int)BossItemFlags::Object, (short)BossFlagValue::Lizard))
|
||||
return NO_ITEM;
|
||||
|
||||
auto pos = GetJointPosition(&item, PunaBossHeadBite.meshNum).ToVector3();
|
||||
auto pos = GetJointPosition(&item, PunaBossHeadBite).ToVector3();
|
||||
auto orient = Geometry::GetOrientToPoint(pos, target);
|
||||
return (orient.y - item.Pose.Orientation.y);
|
||||
}
|
||||
|
@ -213,11 +213,11 @@ namespace TEN::Entities::Creatures::TR3
|
|||
}
|
||||
}
|
||||
|
||||
static void SpawnPunaLightning(ItemInfo& item, const Vector3& pos, const BiteInfo& bite, bool isSummon)
|
||||
static void SpawnPunaLightning(ItemInfo& item, const Vector3& pos, const CreatureBiteInfo& bite, bool isSummon)
|
||||
{
|
||||
const auto& creature = *GetCreatureInfo(&item);
|
||||
|
||||
auto origin = GameVector(GetJointPosition(&item, bite.meshNum, bite.Position), item.RoomNumber);
|
||||
auto origin = GameVector(GetJointPosition(&item, bite), item.RoomNumber);
|
||||
|
||||
if (isSummon)
|
||||
{
|
||||
|
|
|
@ -33,8 +33,8 @@ namespace TEN::Entities::Creatures::TR3
|
|||
constexpr auto SHIVA_SWAPMESH_TIME = 3;
|
||||
constexpr auto PLAYER_ANIM_SHIVA_DEATH = 7; // TODO: Move to LaraExtraAnims enum.
|
||||
|
||||
const auto ShivaBiteLeft = BiteInfo(Vector3(0.0f, 0.0f, 920.0f), 13);
|
||||
const auto ShivaBiteRight = BiteInfo(Vector3(0.0f, 0.0f, 920.0f), 22);
|
||||
const auto ShivaBiteLeft = CreatureBiteInfo(Vector3i(0, 0, 920), 13);
|
||||
const auto ShivaBiteRight = CreatureBiteInfo(Vector3i(0, 0, 920), 22);
|
||||
const auto ShivaAttackLeftJoints = std::vector<unsigned int>{ 10, 13 };
|
||||
const auto ShivaAttackRightJoints = std::vector<unsigned int>{ 22, 25 };
|
||||
|
||||
|
|
|
@ -63,9 +63,9 @@ namespace TEN::Entities::Creatures::TR3
|
|||
|
||||
constexpr auto SOPHIALEIGH_VAULT_SHIFT = 96;
|
||||
|
||||
const auto SophiaLeighStaffBite = BiteInfo(Vector3(-28.0f, 56.0f, 356.0f), 10);
|
||||
const auto SophiaLeighLeftBite = BiteInfo(Vector3(-72.0f, 48.0f, 356.0f), 10);
|
||||
const auto SophiaLeighRightBite = BiteInfo(Vector3(16.0f, 48.0f, 304.0f), 10);
|
||||
const auto SophiaLeighStaffBite = CreatureBiteInfo(Vector3i(-28, 56, 356), 10);
|
||||
const auto SophiaLeighLeftBite = CreatureBiteInfo(Vector3i(-72, 48, 356), 10);
|
||||
const auto SophiaLeighRightBite = CreatureBiteInfo(Vector3i(16, 48, 304), 10);
|
||||
|
||||
struct SophiaData
|
||||
{
|
||||
|
@ -243,7 +243,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
}
|
||||
}
|
||||
|
||||
static void SpawnSophiaLeighProjectileBolt(ItemInfo& item, ItemInfo* enemy, const BiteInfo& bite, SophiaData* data, bool isBoltLarge, short angleAdd)
|
||||
static void SpawnSophiaLeighProjectileBolt(ItemInfo& item, ItemInfo* enemy, const CreatureBiteInfo& bite, SophiaData* data, bool isBoltLarge, short angleAdd)
|
||||
{
|
||||
int fxNumber = CreateNewEffect(item.RoomNumber);
|
||||
if (fxNumber == NO_ITEM)
|
||||
|
@ -253,7 +253,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
|
||||
auto boltType = isBoltLarge ? (short)MissileType::SophiaLeighLarge : (short)MissileType::SophiaLeighNormal;
|
||||
|
||||
fx.pos.Position = GetJointPosition(&item, bite.meshNum, bite.Position);
|
||||
fx.pos.Position = GetJointPosition(&item, bite);
|
||||
fx.pos.Orientation.x = item.Pose.Orientation.x + data->torsoXAngle;
|
||||
|
||||
if (enemy->IsLara())
|
||||
|
|
|
@ -28,8 +28,8 @@ namespace TEN::Entities::Creatures::TR3
|
|||
|
||||
constexpr auto WaspVenomSackLightColor = Vector4(0.0f, 0.35f, 0.0f, 1.0f);
|
||||
|
||||
const auto WaspBite = BiteInfo(Vector3(0.0f, 0.0f, -260.0f), 12);
|
||||
const auto WaspVenomSackBite = BiteInfo(Vector3::Zero, 10);
|
||||
const auto WaspBite = CreatureBiteInfo(Vector3i(0, 0, -260), 12);
|
||||
const auto WaspVenomSackBite = CreatureBiteInfo(Vector3i::Zero, 10);
|
||||
|
||||
enum WaspMutantState
|
||||
{
|
||||
|
@ -112,7 +112,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
item.ItemFlags[0] = 0;
|
||||
|
||||
// Spawn light.
|
||||
auto pos = GetJointPosition(&item, WaspVenomSackBite.meshNum, WaspVenomSackBite.Position);
|
||||
auto pos = GetJointPosition(&item, WaspVenomSackBite);
|
||||
TriggerDynamicLight(
|
||||
pos.x, pos.y, pos.z,
|
||||
item.ItemFlags[0],
|
||||
|
@ -276,7 +276,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
item.Animation.RequiredState = WASP_STATE_FLY_FORWARD;
|
||||
}
|
||||
|
||||
if (!creature.Flags && item.TouchBits.Test(WaspBite.meshNum))
|
||||
if (!creature.Flags && item.TouchBits.Test(WaspBite.BoneID))
|
||||
{
|
||||
DoDamage(creature.Enemy, WASP_DAMAGE);
|
||||
CreatureEffect2(&item, WaspBite, 10, item.Pose.Orientation.y, DoBloodSplat);
|
||||
|
|
|
@ -36,9 +36,9 @@ namespace TEN::Entities::Creatures::TR3
|
|||
constexpr auto CIVVY_TARGET_ALERT_VELOCITY = 10.0f;
|
||||
constexpr auto CIVVY_VAULT_SHIFT = 260;
|
||||
|
||||
const auto CivvyBiteRight = BiteInfo(Vector3::Zero, 13);
|
||||
const auto CivvyBiteLeft = BiteInfo(Vector3::Zero, 10);
|
||||
const auto CivvyAttackJoints = std::vector<unsigned int>{ (unsigned int)CivvyBiteLeft.meshNum, (unsigned int)CivvyBiteRight.meshNum };
|
||||
const auto CivvyBiteLeft = CreatureBiteInfo(Vector3i::Zero, 10);
|
||||
const auto CivvyBiteRight = CreatureBiteInfo(Vector3i::Zero, 13);
|
||||
const auto CivvyAttackJoints = std::vector<unsigned int>{ 10, 13 };
|
||||
|
||||
const auto CivvyExcludedTargets = std::vector<GAME_OBJECT_ID>
|
||||
{
|
||||
|
|
|
@ -35,9 +35,9 @@ namespace TEN::Entities::Creatures::TR3
|
|||
constexpr auto CLAW_MUTANT_WALK_TURN_RATE_MAX = ANGLE(3.0f);
|
||||
constexpr auto CLAW_MUTANT_RUN_TURN_RATE_MAX = ANGLE(4.0f);
|
||||
|
||||
const auto ClawMutantLeftBite = BiteInfo(Vector3(19.0f, -13.0f, 3.0f), 7);
|
||||
const auto ClawMutantRightBite = BiteInfo(Vector3(19.0f, -13.0f, 3.0f), 4);
|
||||
const auto ClawMutantTailBite = BiteInfo(Vector3(-32.0f, -16.0f, -119.0f), 13);
|
||||
const auto ClawMutantLeftBite = CreatureBiteInfo(Vector3i(19, -13, 3), 7);
|
||||
const auto ClawMutantRightBite = CreatureBiteInfo(Vector3i(19, -13, 3), 4);
|
||||
const auto ClawMutantTailBite = CreatureBiteInfo(Vector3i(-32, -16, -119), 13);
|
||||
|
||||
enum ClawMutantState
|
||||
{
|
||||
|
@ -164,7 +164,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
|
||||
auto& fx = EffectList[plasmaBall];
|
||||
|
||||
auto jointPos = GetJointPosition(item, ClawMutantTailBite.meshNum, ClawMutantTailBite.Position);
|
||||
auto jointPos = GetJointPosition(item, ClawMutantTailBite.BoneID, ClawMutantTailBite.Position);
|
||||
auto orient = Geometry::GetOrientToPoint(jointPos.ToVector3(), enemyPos.ToVector3());
|
||||
|
||||
fx.pos.Position = jointPos;
|
||||
|
@ -207,14 +207,14 @@ namespace TEN::Entities::Creatures::TR3
|
|||
|
||||
static void DamageTargetWithClaw(ItemInfo& source, ItemInfo& target)
|
||||
{
|
||||
if (source.ItemFlags[5] == 0 && source.TouchBits.Test(ClawMutantLeftBite.meshNum))
|
||||
if (source.ItemFlags[5] == 0 && source.TouchBits.Test(ClawMutantLeftBite.BoneID))
|
||||
{
|
||||
DoDamage(&target, CLAW_MUTANT_CLAW_ATTACK_DAMAGE / 2);
|
||||
CreatureEffect2(&source, ClawMutantLeftBite, 10, source.Pose.Orientation.y, DoBloodSplat);
|
||||
source.ItemFlags[5] = 1;
|
||||
}
|
||||
|
||||
if (source.ItemFlags[6] == 0 && source.TouchBits.Test(ClawMutantRightBite.meshNum))
|
||||
if (source.ItemFlags[6] == 0 && source.TouchBits.Test(ClawMutantRightBite.BoneID))
|
||||
{
|
||||
DoDamage(&target, CLAW_MUTANT_CLAW_ATTACK_DAMAGE / 2);
|
||||
CreatureEffect2(&source, ClawMutantRightBite, 10, source.Pose.Orientation.y, DoBloodSplat);
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
constexpr auto COBRA_DISTURBANCE_VELOCITY = 15.0f;
|
||||
constexpr auto COBRA_SLEEP_FRAME = 45;
|
||||
|
||||
const auto CobraBite = BiteInfo(Vector3::Zero, 13);
|
||||
const auto CobraBite = CreatureBiteInfo(Vector3i::Zero, 13);
|
||||
const auto CobraAttackJoints = std::vector<unsigned int>{ 13 };
|
||||
|
||||
enum CobraState
|
||||
|
|
|
@ -27,8 +27,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
|
||||
constexpr auto FLAMETHROWER_WALK_TURN_RATE_MAX = ANGLE(5.0f);
|
||||
|
||||
const auto FlamethrowerOffset = Vector3i(0, 340, 0);
|
||||
const auto FlamethrowerBite = BiteInfo(Vector3(0.0f, 340.0f, 64.0f), 7);
|
||||
const auto FlamethrowerBite = CreatureBiteInfo(Vector3i(0, 340, 64), 7);
|
||||
|
||||
// TODO
|
||||
enum FlamethrowerState
|
||||
|
@ -64,10 +63,9 @@ namespace TEN::Entities::Creatures::TR3
|
|||
short tilt = 0;
|
||||
auto extraHeadRot = EulerAngles::Zero;
|
||||
auto extraTorsoRot = EulerAngles::Zero;
|
||||
|
||||
auto pos = GetJointPosition(item, FlamethrowerBite.meshNum, Vector3i(FlamethrowerBite.Position));
|
||||
|
||||
auto pos = GetJointPosition(item, FlamethrowerBite);
|
||||
int randomInt = GetRandomControl();
|
||||
|
||||
if (item->Animation.ActiveState != 6 && item->Animation.ActiveState != 11)
|
||||
{
|
||||
TriggerDynamicLight(pos.x, pos.y, pos.z, (randomInt & 3) + 6, 24 - ((randomInt / 16) & 3), 16 - ((randomInt / 64) & 3), randomInt & 3);
|
||||
|
@ -308,10 +306,10 @@ namespace TEN::Entities::Creatures::TR3
|
|||
item->Animation.TargetState = FLAMETHROWER_STATE_IDLE;
|
||||
|
||||
if (creature->Flags < 40)
|
||||
ThrowFire(itemNumber, FlamethrowerBite.meshNum, FlamethrowerOffset, Vector3i(0, creature->Flags * 1.5f, 0));
|
||||
ThrowFire(itemNumber, FlamethrowerBite, Vector3i(0, creature->Flags * 1.5f, 0));
|
||||
else
|
||||
{
|
||||
ThrowFire(itemNumber, FlamethrowerBite.meshNum, FlamethrowerOffset, Vector3i(0, (Random::GenerateInt() & 63) + 12, 0));
|
||||
ThrowFire(itemNumber, FlamethrowerBite, Vector3i(0, (Random::GenerateInt() & 63) + 12, 0));
|
||||
if (realEnemy)
|
||||
{
|
||||
/*code*/
|
||||
|
@ -342,10 +340,10 @@ namespace TEN::Entities::Creatures::TR3
|
|||
item->Animation.TargetState = FLAMETHROWER_STATE_WALK_FORWARD;
|
||||
|
||||
if (creature->Flags < 40)
|
||||
ThrowFire(itemNumber, FlamethrowerBite.meshNum, FlamethrowerOffset, Vector3i(0, creature->Flags * 1.5f, 0));
|
||||
ThrowFire(itemNumber, FlamethrowerBite, Vector3i(0, creature->Flags * 1.5f, 0));
|
||||
else
|
||||
{
|
||||
ThrowFire(itemNumber, FlamethrowerBite.meshNum, FlamethrowerOffset, Vector3i(0, (GetRandomControl() & 63) + 12, 0));
|
||||
ThrowFire(itemNumber, FlamethrowerBite, Vector3i(0, (GetRandomControl() & 63) + 12, 0));
|
||||
if (realEnemy)
|
||||
{
|
||||
/*code*/
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
|
||||
// TODO: Range constants.
|
||||
|
||||
const auto MonkeyBite = BiteInfo(Vector3(10.0f, 10.0f, 11.0f), 13);
|
||||
const auto MonkeyBite = CreatureBiteInfo(Vector3i(10, 10, 11), 13);
|
||||
const auto MonkeyAttackJoints = std::vector<unsigned int>{ 10, 13 };
|
||||
|
||||
enum MonkeyState
|
||||
|
|
|
@ -21,7 +21,7 @@ using namespace TEN::Math;
|
|||
|
||||
namespace TEN::Entities::Creatures::TR3
|
||||
{
|
||||
const auto MPGunBite = BiteInfo(Vector3(0.0f, 160.0f, 40.0f), 13);
|
||||
const auto MPGunBite = CreatureBiteInfo(Vector3i(0, 225, 50), 13);
|
||||
|
||||
enum MPGunState
|
||||
{
|
||||
|
@ -67,13 +67,8 @@ namespace TEN::Entities::Creatures::TR3
|
|||
short head = 0;
|
||||
auto extraTorsoRot = EulerAngles::Zero;
|
||||
|
||||
if (creature->FiredWeapon)
|
||||
{
|
||||
auto pos = GetJointPosition(item, MPGunBite.meshNum, Vector3i(MPGunBite.Position));
|
||||
TriggerDynamicLight(pos.x, pos.y, pos.z, (creature->FiredWeapon * 2) + 4, 24, 16, 4);
|
||||
|
||||
creature->FiredWeapon--;
|
||||
}
|
||||
if (creature->MuzzleFlash[0].Delay != 0)
|
||||
creature->MuzzleFlash[0].Delay--;
|
||||
|
||||
if (item->BoxNumber != NO_BOX && (g_Level.Boxes[item->BoxNumber].flags & BLOCKED))
|
||||
{
|
||||
|
@ -98,14 +93,14 @@ namespace TEN::Entities::Creatures::TR3
|
|||
|
||||
if (Targetable(item, &AI))
|
||||
{
|
||||
if (AI.angle > -ANGLE(45.0f) &&
|
||||
AI.angle < ANGLE(45.0f))
|
||||
if (AI.angle > -ANGLE(45.0f) && AI.angle < ANGLE(45.0f))
|
||||
{
|
||||
head = AI.angle;
|
||||
extraTorsoRot.y = AI.angle;
|
||||
ShotLara(item, &AI, MPGunBite, extraTorsoRot.y, 32);
|
||||
creature->MuzzleFlash[0].Bite = MPGunBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
SoundEffect(SFX_TR3_OIL_SMG_FIRE, &item->Pose, SoundEnvironment::Land, 1.0f, 0.7f);
|
||||
creature->FiredWeapon = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -330,6 +325,12 @@ namespace TEN::Entities::Creatures::TR3
|
|||
extraTorsoRot.y = AI.angle;
|
||||
}
|
||||
|
||||
if (item->Animation.FrameNumber == GetFrameIndex(item, 0))
|
||||
{
|
||||
creature->MuzzleFlash[0].Bite = MPGunBite;
|
||||
creature->MuzzleFlash[0].Delay = 1;
|
||||
}
|
||||
|
||||
if (item->Animation.RequiredState == MPGUN_STATE_WAIT)
|
||||
item->Animation.TargetState = MPGUN_STATE_WAIT;
|
||||
|
||||
|
@ -346,6 +347,8 @@ namespace TEN::Entities::Creatures::TR3
|
|||
{
|
||||
if (!ShotLara(item, &AI, MPGunBite, extraTorsoRot.y, 32))
|
||||
item->Animation.TargetState = MPGUN_STATE_WAIT;
|
||||
creature->MuzzleFlash[0].Bite = MPGunBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
}
|
||||
else if (item->HitStatus && Random::TestProbability(0.25f) && cover)
|
||||
{
|
||||
|
@ -368,6 +371,8 @@ namespace TEN::Entities::Creatures::TR3
|
|||
{
|
||||
if (!ShotLara(item, &AI, MPGunBite, extraTorsoRot.y, 32))
|
||||
item->Animation.TargetState = MPGUN_STATE_WAIT;
|
||||
creature->MuzzleFlash[0].Bite = MPGunBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
}
|
||||
else if (item->HitStatus && Random::TestProbability(0.25f) && cover)
|
||||
{
|
||||
|
@ -391,6 +396,8 @@ namespace TEN::Entities::Creatures::TR3
|
|||
{
|
||||
if (!ShotLara(item, &AI, MPGunBite, extraTorsoRot.y, 32))
|
||||
item->Animation.RequiredState = MPGUN_STATE_WALK;
|
||||
creature->MuzzleFlash[0].Bite = MPGunBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
}
|
||||
else if (item->HitStatus && Random::TestProbability(0.25f) && cover)
|
||||
{
|
||||
|
@ -418,6 +425,8 @@ namespace TEN::Entities::Creatures::TR3
|
|||
{
|
||||
if (!ShotLara(item, &AI, MPGunBite, extraTorsoRot.y, 32))
|
||||
item->Animation.TargetState = MPGUN_STATE_WALK;
|
||||
creature->MuzzleFlash[0].Bite = MPGunBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
}
|
||||
|
||||
if (AI.distance < pow(SECTOR(1.5f), 2))
|
||||
|
@ -461,6 +470,8 @@ namespace TEN::Entities::Creatures::TR3
|
|||
{
|
||||
if (!ShotLara(item, &AI, MPGunBite, extraTorsoRot.y, 32) || Random::TestProbability(1 / 8.0f))
|
||||
item->Animation.TargetState = MPGUN_STATE_CROUCHED;
|
||||
creature->MuzzleFlash[0].Bite = MPGunBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -18,8 +18,8 @@ using namespace TEN::Math;
|
|||
|
||||
namespace TEN::Entities::Creatures::TR3
|
||||
{
|
||||
const auto MPStickBite1 = BiteInfo(Vector3(247.0f, 10.0f, 11.0f), 13);
|
||||
const auto MPStickBite2 = BiteInfo(Vector3(0.0f, 0.0f, 100.0f), 6);
|
||||
const auto MPStickBite1 = CreatureBiteInfo(Vector3i(247, 10, 11), 13);
|
||||
const auto MPStickBite2 = CreatureBiteInfo(Vector3i(0, 0, 100), 6);
|
||||
const auto MPStickPunchAttackJoints = std::vector<unsigned int>{ 10, 13 };
|
||||
const auto MPStickKickAttackJoints = std::vector<unsigned int>{ 5, 6 };
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
constexpr auto RAPTOR_RUN_TURN_RATE_MAX = ANGLE(2.0f);
|
||||
constexpr auto RAPTOR_ATTACK_TURN_RATE_MAX = ANGLE(2.0f);
|
||||
|
||||
const auto RaptorBite = BiteInfo(Vector3(0.0f, 66.0f, 318.0f), 22);
|
||||
const auto RaptorBite = CreatureBiteInfo(Vector3i(0, 66, 318), 22);
|
||||
const auto RaptorAttackJoints = std::vector<unsigned int>{ 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23 };
|
||||
|
||||
enum RaptorState
|
||||
|
|
|
@ -16,10 +16,9 @@
|
|||
namespace TEN::Entities::Creatures::TR3
|
||||
{
|
||||
constexpr auto SCUBA_DIVER_ATTACK_DAMAGE = 50;
|
||||
|
||||
constexpr auto SCUBA_DIVER_SWIM_TURN_RATE_MAX = ANGLE(3.0f);
|
||||
|
||||
const auto ScubaGunBite = BiteInfo(Vector3(17.0f, 164.0f, 44.0f), 18);
|
||||
const auto ScubaGunBite = CreatureBiteInfo(Vector3i(17, 164, 44), 18);
|
||||
|
||||
enum ScubaDiverState
|
||||
{
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
|
||||
constexpr auto TIGER_PLAYER_ALERT_VELOCITY = 10.0f;
|
||||
|
||||
const auto TigerBite = BiteInfo(Vector3(19.0f, -13.0f, 3.0f), 26);
|
||||
const auto TigerBite = CreatureBiteInfo(Vector3i(19, -13, 3), 26);
|
||||
const auto TigerSwipeAttackJoints = std::vector<unsigned int>{ 14, 15, 16 };
|
||||
const auto TigerBiteAttackJoints = std::vector<unsigned int>{ 22, 25, 26 };
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ namespace TEN::Entities::Creatures::TR3
|
|||
constexpr auto TONY_EXPLOSION_COUNT_MAX = 60;
|
||||
constexpr auto TONY_EFFECT_COLOR = Vector4(0.8f, 0.4f, 0.0f, 0.5f);
|
||||
|
||||
const auto TonyLeftHandBite = BiteInfo(Vector3::Zero, 10);
|
||||
const auto TonyRightHandBite = BiteInfo(Vector3::Zero, 13);
|
||||
const auto TonyLeftHandBite = CreatureBiteInfo(Vector3i::Zero, 10);
|
||||
const auto TonyRightHandBite = CreatureBiteInfo(Vector3i::Zero, 13);
|
||||
|
||||
// I can't set it to the TonyFlame struct since the control of the
|
||||
// flame use fxNumber as argument or that FX_INFO have no void* to hold custom data.
|
||||
|
@ -654,14 +654,14 @@ namespace TEN::Entities::Creatures::TR3
|
|||
g = (g * bright) / 16;
|
||||
b = (b * bright) / 16;
|
||||
|
||||
auto handPos = GetJointPosition(item, TonyLeftHandBite.meshNum);
|
||||
auto handPos = GetJointPosition(item, TonyLeftHandBite);
|
||||
TriggerTonyFlame(itemNumber, 13);
|
||||
TriggerDynamicLight(handPos.x, handPos.y, handPos.z, 12, r, g, b);
|
||||
|
||||
if (item->Animation.ActiveState == TONY_STATE_SHOOT_CEILING ||
|
||||
item->Animation.ActiveState == TONY_STATE_FLIPMAP)
|
||||
{
|
||||
handPos = GetJointPosition(item, TonyRightHandBite.meshNum);
|
||||
handPos = GetJointPosition(item, TonyRightHandBite);
|
||||
TriggerTonyFlame(itemNumber, 14);
|
||||
TriggerDynamicLight(handPos.x, handPos.y, handPos.z, 12, r, g, b);
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ namespace TEN::Entities::Creatures::TR3
|
|||
{
|
||||
constexpr auto TRIBESMAN_DART_DAMAGE = -25; // NOTE: Negative value gives poison.
|
||||
|
||||
const auto TribesmanAxeBite = BiteInfo(Vector3(0.0f, 56.0f, 265.0f), 13);
|
||||
const auto TribesmanDartBite1 = BiteInfo(Vector3(0.0f, 0.0f, -200.0f), 13);
|
||||
const auto TribesmanDartBite2 = BiteInfo(Vector3(8.0f, 40.0f, -248.0f), 13);
|
||||
const auto TribesmanAxeBite = CreatureBiteInfo(Vector3i(0, 56, 265), 13);
|
||||
const auto TribesmanDartBite1 = CreatureBiteInfo(Vector3i(0, 0, -200), 13);
|
||||
const auto TribesmanDartBite2 = CreatureBiteInfo(Vector3i(8, 40, -248), 13);
|
||||
const auto TribesmanAxeAttackJoints = std::vector<unsigned int>{ 13 };
|
||||
const auto TribesmanDartAttackJoints = std::vector<unsigned int>{ 10, 13 }; // TODO: Check.
|
||||
|
||||
|
@ -371,7 +371,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
dartItem->ObjectNumber = ID_DARTS;
|
||||
dartItem->RoomNumber = item->RoomNumber;
|
||||
|
||||
auto pos1 = GetJointPosition(item, TribesmanDartBite1.meshNum, Vector3i(TribesmanDartBite1.Position));
|
||||
auto pos1 = GetJointPosition(item, TribesmanDartBite1);
|
||||
auto pos2 = GetJointPosition(LaraItem, LM_TORSO);
|
||||
auto orient = Geometry::GetOrientToPoint(pos1.ToVector3(), pos2.ToVector3());
|
||||
|
||||
|
@ -389,7 +389,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
|
||||
pos1 = Vector3i(TribesmanDartBite2.Position);
|
||||
pos1.z += 96;
|
||||
pos1 = GetJointPosition(item, TribesmanDartBite2.meshNum, pos1);
|
||||
pos1 = GetJointPosition(item, TribesmanDartBite2.BoneID, pos1);
|
||||
|
||||
TriggerDartSmoke(pos1.x, pos1.y, pos1.z, 0, 0, true);
|
||||
TriggerDartSmoke(pos1.x, pos1.y, pos1.z, 0, 0, true);
|
||||
|
|
|
@ -32,8 +32,8 @@ namespace TEN::Entities::Traps
|
|||
SetAnimation(item, WALL_MOUNTED_BLADE_ANIM_IDLE);
|
||||
|
||||
// Used for GenericSphereBoxCollision.
|
||||
item.ItemFlags[0] = WALL_MOUNTED_BLADE_JOINT;
|
||||
item.ItemFlags[3] = WALL_MOUNTED_BLADE_HARM_DAMAGE;
|
||||
item.ItemFlags[0] = WALL_MOUNTED_BLADE_JOINT; // Damaging mesh joint.
|
||||
item.ItemFlags[3] = 0; // Set the Damage initially to 0 to avoid player being damaged when the blade is disabled.
|
||||
item.ItemFlags[4] = 1; // NOTE: avoid the blade pushing lara in GenericSphereBoxCollision() !
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace TEN::Entities::Vehicles
|
|||
VehicleMountType::Back
|
||||
};
|
||||
|
||||
const auto BigGunBite = BiteInfo(Vector3(0, 0, BGUN_ROCKET_SPAWN_DISTANCE), 2);
|
||||
const auto BigGunBite = CreatureBiteInfo(Vector3i(0, 0, BGUN_ROCKET_SPAWN_DISTANCE), 2);
|
||||
|
||||
enum BigGunState
|
||||
{
|
||||
|
@ -125,7 +125,7 @@ namespace TEN::Entities::Vehicles
|
|||
|
||||
auto* projectileItem = &g_Level.Items[itemNumber];
|
||||
projectileItem->ObjectNumber = ID_ROCKET;
|
||||
auto pos = GetJointPosition(bigGunItem, BigGunBite.meshNum, BigGunBite.Position);
|
||||
auto pos = GetJointPosition(bigGunItem, BigGunBite);
|
||||
auto probe = GetCollision(pos.x, pos.y, pos.z, bigGunItem->RoomNumber);
|
||||
projectileItem->RoomNumber = probe.RoomNumber;
|
||||
projectileItem->Pose.Position = pos;
|
||||
|
|
|
@ -27,14 +27,14 @@ using namespace TEN::Math;
|
|||
|
||||
namespace TEN::Entities::Vehicles
|
||||
{
|
||||
BiteInfo QuadBikeEffectsPositions[6] =
|
||||
const CreatureBiteInfo QuadBikeEffectsPositions[6] =
|
||||
{
|
||||
{ -56, -32, -380, 0 },
|
||||
{ 56, -32, -380, 0 },
|
||||
{ -8, 180, -48, 3 },
|
||||
{ 8, 180, -48, 4 },
|
||||
{ 90, 180, -32, 6 },
|
||||
{ -90, 180, -32, 7 }
|
||||
CreatureBiteInfo(Vector3i(-56, -32, -380), 0),
|
||||
CreatureBiteInfo(Vector3i(56, -32, -380), 0),
|
||||
CreatureBiteInfo(Vector3i(-8, 180, -48), 3),
|
||||
CreatureBiteInfo(Vector3i(8, 180, -48), 4),
|
||||
CreatureBiteInfo(Vector3i(90, 180, -32), 6),
|
||||
CreatureBiteInfo(Vector3i(-90, 180, -32), 7)
|
||||
};
|
||||
const vector<VehicleMountType> QuadBikeMountTypes =
|
||||
{
|
||||
|
@ -1207,8 +1207,7 @@ namespace TEN::Entities::Vehicles
|
|||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
auto pos = GetJointPosition(quadBikeItem, QuadBikeEffectsPositions[i].meshNum, Vector3i(QuadBikeEffectsPositions[i].Position));
|
||||
|
||||
auto pos = GetJointPosition(quadBikeItem, QuadBikeEffectsPositions[i]);
|
||||
angle = quadBikeItem->Pose.Orientation.y + ((i == 0) ? 0x9000 : 0x7000);
|
||||
if (quadBikeItem->Animation.Velocity.z > 32)
|
||||
{
|
||||
|
|
|
@ -84,15 +84,16 @@ namespace TEN::Entities::Vehicles
|
|||
#define UPV_LEAN_RATE ANGLE(0.6f)
|
||||
#define UPV_LEAN_MAX ANGLE(10.0f)
|
||||
|
||||
BiteInfo UPVBites[6] =
|
||||
const CreatureBiteInfo UPVBites[6] =
|
||||
{
|
||||
{ 0, 0, 0, 3 },
|
||||
{ 0, 96, 256, 0 },
|
||||
{ -128, 0, 64, 1 },
|
||||
{ 0, 0, -64, 1 },
|
||||
{ 128, 0, 64, 2 },
|
||||
{ 0, 0, -64, 2 }
|
||||
CreatureBiteInfo(Vector3i(0, 0, 0), 3),
|
||||
CreatureBiteInfo(Vector3i(0, 96, 256), 0),
|
||||
CreatureBiteInfo(Vector3i(-128, 0, 64), 1),
|
||||
CreatureBiteInfo(Vector3i(0, 0, -64), 1),
|
||||
CreatureBiteInfo(Vector3i(128, 0, 64), 2),
|
||||
CreatureBiteInfo(Vector3i(0, 0, -64), 2)
|
||||
};
|
||||
|
||||
const std::vector<VehicleMountType> UPVMountTypes =
|
||||
{
|
||||
VehicleMountType::LevelStart,
|
||||
|
@ -304,7 +305,7 @@ namespace TEN::Entities::Vehicles
|
|||
|
||||
if (UPV->Velocity)
|
||||
{
|
||||
auto pos = GetJointPosition(UPVItem, UPVBites[UPV_BITE_TURBINE].meshNum, Vector3i(UPVBites[UPV_BITE_TURBINE].Position)).ToVector3();
|
||||
auto pos = GetJointPosition(UPVItem, UPVBites[UPV_BITE_TURBINE]).ToVector3();
|
||||
TriggerUPVMist(pos.x, pos.y + UPV_SHIFT, pos.z, abs(UPV->Velocity) / VEHICLE_VELOCITY_SCALE, UPVItem->Pose.Orientation.y + ANGLE(180.0f));
|
||||
|
||||
auto sphere = BoundingSphere(pos, BLOCK(1 / 32.0f));
|
||||
|
@ -322,7 +323,7 @@ namespace TEN::Entities::Vehicles
|
|||
for (int lp = 0; lp < 2; lp++)
|
||||
{
|
||||
int random = 31 - (GetRandomControl() & 3);
|
||||
auto pos = GetJointPosition(UPVItem, UPVBites[UPV_BITE_FRONT_LIGHT].meshNum, Vector3i(
|
||||
auto pos = GetJointPosition(UPVItem, UPVBites[UPV_BITE_FRONT_LIGHT].BoneID, Vector3i(
|
||||
UPVBites[UPV_BITE_FRONT_LIGHT].Position.x,
|
||||
UPVBites[UPV_BITE_FRONT_LIGHT].Position.y,
|
||||
(int)UPVBites[UPV_BITE_FRONT_LIGHT].Position.z << (lp * 6)
|
||||
|
|
|
@ -242,7 +242,6 @@ static void StartEntity(ObjectInfo* obj)
|
|||
obj->radius = 102;
|
||||
obj->intelligent = true;
|
||||
obj->pivotLength = 0;
|
||||
obj->biteOffset = 0;
|
||||
obj->SetBoneRotationFlags(6, ROT_X | ROT_Y);
|
||||
obj->SetBoneRotationFlags(13, ROT_Y);
|
||||
obj->SetupHitEffect();
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "Game/people.h"
|
||||
#include "Game/room.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/Generic/Traps/traps.h"
|
||||
#include "Objects/TR4/Entity/WraithInfo.h"
|
||||
#include "Objects/objectslist.h"
|
||||
#include "Sound/sound.h"
|
||||
|
|
|
@ -35,9 +35,9 @@ namespace TEN::Entities::TR4
|
|||
constexpr auto AHMET_VIEW_ANGLE = ANGLE(45.0f);
|
||||
constexpr auto AHMET_ENEMY_ANGLE = ANGLE(90.0f);
|
||||
|
||||
const auto AhmetBiteLeft = BiteInfo(Vector3::Zero, 16);
|
||||
const auto AhmetBiteRight = BiteInfo(Vector3::Zero, 22);
|
||||
const auto AhmetBiteJaw = BiteInfo(Vector3::Zero, 11);
|
||||
const auto AhmetBiteLeft = CreatureBiteInfo(Vector3i::Zero, 16);
|
||||
const auto AhmetBiteRight = CreatureBiteInfo(Vector3i::Zero, 22);
|
||||
const auto AhmetBiteJaw = CreatureBiteInfo(Vector3i::Zero, 11);
|
||||
const auto AhmetSwipeAttackLeftJoints = std::vector<unsigned int>{ 14, 15, 16, 17 };
|
||||
const auto AhmetSwipeAttackRightJoints = std::vector<unsigned int>{ 20, 21, 22, 23 };
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace TEN::Entities::TR4
|
|||
constexpr auto NO_BABOON_COUNT = -2;
|
||||
constexpr auto NO_CROWBAR_SWITCH_FOUND = -1;
|
||||
|
||||
const auto BaboonBite = BiteInfo(Vector3(10.0f, 10.0f, 11.0f), 4);
|
||||
const auto BaboonBite = CreatureBiteInfo(Vector3i(10, 10, 11), 4);
|
||||
const auto BaboonAttackJoints = std::vector<unsigned int>{ 11, 12 };
|
||||
const auto BaboonAttackRightJoints = std::vector<unsigned int>{ 1, 2, 3, 5, 8, 9 };
|
||||
const auto BaboonJumpAttackJoints = std::vector<unsigned int>{ 3, 4, 8 };
|
||||
|
|
|
@ -54,8 +54,8 @@ namespace TEN::Entities::TR4
|
|||
{
|
||||
constexpr auto BADDY_UZI_AMMO = 24;
|
||||
|
||||
const auto BaddyGunBite = BiteInfo(Vector3(0.0f, -16.0f, 200.0f), 11);
|
||||
const auto BaddySwordBite = BiteInfo(Vector3::Zero, 15);
|
||||
const auto BaddyGunBite = CreatureBiteInfo(Vector3i(-5, 200, 50), 11);
|
||||
const auto BaddySwordBite = CreatureBiteInfo(Vector3i::Zero, 15);
|
||||
const auto BaddySwordAttackJoints = std::vector<unsigned int>{ 14, 15, 16 };
|
||||
|
||||
enum BaddyState
|
||||
|
@ -330,6 +330,9 @@ namespace TEN::Entities::TR4
|
|||
// TODO: better add a second control routine for baddy 2 instead of mixing them?
|
||||
short objectNumber = (Objects[ID_BADDY2].loaded ? ID_BADDY2 : ID_BADDY1);
|
||||
|
||||
if (creature->MuzzleFlash[0].Delay != 0)
|
||||
creature->MuzzleFlash[0].Delay--;
|
||||
|
||||
bool roll = false;
|
||||
bool jump = false;
|
||||
|
||||
|
@ -419,14 +422,6 @@ namespace TEN::Entities::TR4
|
|||
|
||||
item->ItemFlags[1] = item->RoomNumber;
|
||||
|
||||
// Handle baddy firing.
|
||||
if (creature->FiredWeapon)
|
||||
{
|
||||
auto pos = GetJointPosition(item, BaddyGunBite.meshNum, Vector3i(BaddyGunBite.Position));
|
||||
TriggerDynamicLight(pos.x, pos.y, pos.z, 4 * creature->FiredWeapon + 8, 24, 16, 4);
|
||||
creature->FiredWeapon--;
|
||||
}
|
||||
|
||||
CollisionResult probe;
|
||||
|
||||
if (item->HitPoints <= 0)
|
||||
|
@ -1158,13 +1153,13 @@ namespace TEN::Entities::TR4
|
|||
break;
|
||||
}
|
||||
|
||||
creature->FiredWeapon = 1;
|
||||
|
||||
if (!item->HitStatus)
|
||||
item->ItemFlags[2]--;
|
||||
|
||||
if (!ShotLara(item, &AI, BaddyGunBite, joint1, 15))
|
||||
item->Animation.TargetState = BADDY_STATE_IDLE;
|
||||
creature->MuzzleFlash[0].Bite = BaddyGunBite;
|
||||
creature->MuzzleFlash[0].Delay = 2;
|
||||
|
||||
break;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace TEN::Entities::TR4
|
|||
|
||||
constexpr auto BAT_ANGLE = ANGLE(20.0f);
|
||||
|
||||
const auto BatBite = BiteInfo(Vector3(0.0f, 16.0f, 45.0f), 4);
|
||||
const auto BatBite = CreatureBiteInfo(Vector3i(0, 16, 45), 4);
|
||||
|
||||
enum BatState
|
||||
{
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace TEN::Entities::TR4
|
|||
constexpr auto BIG_BEETLE_ATTACK_RANGE = SQUARE(CLICK(1));
|
||||
constexpr auto BIG_BEETLE_AWARE_RANGE = SQUARE(CLICK(12));
|
||||
|
||||
const auto BigBeetleBite = BiteInfo(Vector3::Zero, 12);
|
||||
const auto BigBeetleBite = CreatureBiteInfo(Vector3i::Zero, 12);
|
||||
const auto BigBeetleAttackJoints = std::vector<unsigned int>{ 5, 6 };
|
||||
|
||||
enum BigBeetleState
|
||||
|
|
|
@ -26,12 +26,10 @@ namespace TEN::Entities::TR4
|
|||
constexpr auto BIG_SCORPION_ATTACK_RANGE = SQUARE(BLOCK(1.35));
|
||||
constexpr auto BIG_SCORPION_RUN_RANGE = SQUARE(BLOCK(2));
|
||||
|
||||
const auto BigScorpionBite1 = BiteInfo(Vector3::Zero, 8);
|
||||
const auto BigScorpionBite2 = BiteInfo(Vector3::Zero, 23);
|
||||
const auto BigScorpionBite1 = CreatureBiteInfo(Vector3i::Zero, 8);
|
||||
const auto BigScorpionBite2 = CreatureBiteInfo(Vector3i::Zero, 23);
|
||||
const auto BigScorpionAttackJoints = std::vector<unsigned int>{ 8, 20, 21, 23, 24 };
|
||||
|
||||
int CutSeqNum;
|
||||
|
||||
enum BigScorpionState
|
||||
{
|
||||
// No state 0.
|
||||
|
@ -87,7 +85,6 @@ namespace TEN::Entities::TR4
|
|||
{
|
||||
if (item->TriggerFlags > 0 && item->TriggerFlags < 7)
|
||||
{
|
||||
CutSeqNum = 4;
|
||||
SetAnimation(item, BSCORPION_ANIM_DEATH);
|
||||
item->Status = ITEM_INVISIBLE;
|
||||
creature->MaxTurn = 0;
|
||||
|
@ -114,11 +111,6 @@ namespace TEN::Entities::TR4
|
|||
SetAnimation(item, BSCORPION_ANIM_DEATH);
|
||||
}
|
||||
}
|
||||
else if (CutSeqNum == 4)
|
||||
{
|
||||
item->Animation.FrameNumber = g_Level.Anims[item->Animation.AnimNumber].frameEnd - 1;
|
||||
item->Status = ITEM_INVISIBLE;
|
||||
}
|
||||
else if (item->Animation.ActiveState == BSCORPION_STATE_DEATH && item->Status == ITEM_INVISIBLE)
|
||||
item->Status = ITEM_ACTIVE;
|
||||
}
|
||||
|
@ -287,10 +279,7 @@ namespace TEN::Entities::TR4
|
|||
}
|
||||
}
|
||||
|
||||
if (!CutSeqNum)
|
||||
CreatureAnimation(itemNumber, angle, 0);
|
||||
|
||||
auto radius = Vector2(object->radius, object->radius * 1.33f);
|
||||
AlignEntityToSurface(item, radius);
|
||||
AlignEntityToSurface(item, Vector2(object->radius, object->radius * 1.33f));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace TEN::Entities::TR4
|
|||
constexpr auto CROC_STATE_RUN_TURN_RATE_MAX = ANGLE(5.0f);
|
||||
constexpr auto CROC_STATE_SWIM_TURN_RATE_MAX = ANGLE(3.0f);
|
||||
|
||||
const auto CrocodileBite = BiteInfo(Vector3(0.0f, -100.0f, 500.0f), 9);
|
||||
const auto CrocodileBite = CreatureBiteInfo(Vector3i(0, -100, 500), 9);
|
||||
const auto CrocodileBiteAttackJoints = std::vector<unsigned int>{ 8, 9 };
|
||||
|
||||
enum CrocodileState
|
||||
|
@ -115,7 +115,7 @@ namespace TEN::Entities::TR4
|
|||
auto* item = &g_Level.Items[itemNumber];
|
||||
auto* object = &Objects[item->ObjectNumber];
|
||||
auto* creature = GetCreatureInfo(item);
|
||||
|
||||
auto head = EulerAngles::Zero, torso = EulerAngles::Zero;
|
||||
short angle = 0;
|
||||
short boneAngle = 0;
|
||||
AI_INFO AI;
|
||||
|
@ -298,28 +298,26 @@ namespace TEN::Entities::TR4
|
|||
}
|
||||
}
|
||||
|
||||
OBJECT_BONES boneRot;
|
||||
if (item->Animation.ActiveState == CROC_STATE_IDLE || item->Animation.ActiveState == CROC_STATE_BITE_ATTACK || item->Animation.ActiveState == CROC_STATE_WATER_BITE_ATTACK)
|
||||
{
|
||||
boneRot.bone0 = AI.angle / 3;
|
||||
boneRot.bone1 = AI.angle / 2;
|
||||
boneRot.bone2 = 0;
|
||||
boneRot.bone3 = 0;
|
||||
head.y = AI.angle / 3;
|
||||
head.x = AI.angle / 2;
|
||||
torso.y = 0;
|
||||
torso.x = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
boneRot.bone0 = boneAngle;
|
||||
boneRot.bone1 = boneAngle;
|
||||
boneRot.bone2 = -boneAngle;
|
||||
boneRot.bone3 = -boneAngle;
|
||||
head.y = boneAngle;
|
||||
head.x = boneAngle;
|
||||
torso.y = -boneAngle;
|
||||
torso.x = -boneAngle;
|
||||
}
|
||||
|
||||
CreatureTilt(item, 0);
|
||||
CreatureJoint(item, 0, boneRot.bone0);
|
||||
CreatureJoint(item, 1, boneRot.bone1);
|
||||
CreatureJoint(item, 2, boneRot.bone2);
|
||||
CreatureJoint(item, 3, boneRot.bone3);
|
||||
|
||||
CreatureJoint(item, 0, head.y);
|
||||
CreatureJoint(item, 1, head.x);
|
||||
CreatureJoint(item, 2, torso.y);
|
||||
CreatureJoint(item, 3, torso.x);
|
||||
CreatureAnimation(itemNumber, angle, 0);
|
||||
|
||||
if (item->Animation.ActiveState < CROC_STATE_SWIM_FORWARD)
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace TEN::Entities::TR4
|
|||
constexpr auto DOG_BITE_ATTACK_RANGE = SQUARE(BLOCK(0.55));
|
||||
constexpr auto DOG_JUMP_ATTACK_RANGE = SQUARE(BLOCK(1));
|
||||
|
||||
const auto DogBite = BiteInfo(Vector3(0.0f, 0.0f, 100.0f), 3.0f);
|
||||
const auto DogBite = CreatureBiteInfo(Vector3i(0, 0, 100), 3);
|
||||
const auto DogJumpAttackJoints = std::vector<unsigned int>{ 3, 6, 9, 10, 13, 14 };
|
||||
const auto DogBiteAttackJoints = std::vector<unsigned int>{ 3, 6 };
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ namespace TEN::Entities::TR4
|
|||
{
|
||||
constexpr auto GUIDE_ATTACK_DAMAGE = 20;
|
||||
|
||||
const auto GuideBite1 = BiteInfo(Vector3(0.0f, 20.0f, 180.0f), 18);
|
||||
const auto GuideBite2 = BiteInfo(Vector3(30.0f, 80.0f, 50.0f), 15);
|
||||
const auto GuideBite1 = CreatureBiteInfo(Vector3i(0, 20, 180), 18);
|
||||
const auto GuideBite2 = CreatureBiteInfo(Vector3i(30, 80, 50), 15);
|
||||
const auto GuideLeftFingerSwapJoints = std::vector<unsigned int>{ 15 };
|
||||
const auto GuideRightHandSwapJoints = std::vector<unsigned int>{ 18 };
|
||||
const auto GuideHeadSwapJoints = std::vector<unsigned int>{ 21 };
|
||||
|
@ -119,7 +119,7 @@ namespace TEN::Entities::TR4
|
|||
// Ignite torch.
|
||||
if (item->ItemFlags[1] == 2)
|
||||
{
|
||||
auto pos = GetJointPosition(item, GuideBite1.meshNum, Vector3i(GuideBite1.Position));
|
||||
auto pos = GetJointPosition(item, GuideBite1);
|
||||
TriggerFireFlame(pos.x, pos.y - 20, pos.z, FlameType::Trail);
|
||||
SoundEffect(SFX_TR4_LOOP_FOR_SMALL_FIRES, &item->Pose);
|
||||
|
||||
|
@ -479,7 +479,7 @@ namespace TEN::Entities::TR4
|
|||
break;
|
||||
|
||||
case GUIDE_STATE_IGNITE_TORCH:
|
||||
pos1 = GetJointPosition(item, GuideBite2.meshNum, Vector3i(GuideBite2.Position));
|
||||
pos1 = GetJointPosition(item, GuideBite2);
|
||||
frameNumber = item->Animation.FrameNumber - g_Level.Anims[item->Animation.AnimNumber].frameBase;
|
||||
random = GetRandomControl();
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace TEN::Entities::TR4
|
|||
constexpr auto HAMMERHEAD_BITE_ATTACK_DAMAGE = 120;
|
||||
constexpr auto HAMMERHEAD_ATTACK_RANGE = SQUARE(BLOCK(0.66f));
|
||||
|
||||
const auto HammerheadBite = BiteInfo(Vector3::Zero, 12);
|
||||
const auto HammerheadBite = CreatureBiteInfo(Vector3i::Zero, 12);
|
||||
const auto HammerheadBiteAttackJoints = std::vector<unsigned int>{ 10, 12, 13 };
|
||||
|
||||
enum HammerheadState
|
||||
|
|
|
@ -30,11 +30,11 @@ namespace TEN::Entities::TR4
|
|||
constexpr auto HARPY_SWOOP_ATTACK_DAMAGE = 10;
|
||||
constexpr auto HARPY_STINGER_POISON_POTENCY = 8;
|
||||
|
||||
const auto HarpyBite1 = BiteInfo(Vector3::Zero, 4);
|
||||
const auto HarpyBite2 = BiteInfo(Vector3::Zero, 2);
|
||||
const auto HarpyBite3 = BiteInfo(Vector3::Zero, 15);
|
||||
const auto HarpyAttack1 = BiteInfo(Vector3(0.0f, 128.0f, 0.0f), 2);
|
||||
const auto HarpyAttack2 = BiteInfo(Vector3(0.0f, 128.0f, 0.0f), 4);
|
||||
const auto HarpyBite1 = CreatureBiteInfo(Vector3i::Zero, 4);
|
||||
const auto HarpyBite2 = CreatureBiteInfo(Vector3i::Zero, 2);
|
||||
const auto HarpyBite3 = CreatureBiteInfo(Vector3i::Zero, 15);
|
||||
const auto HarpyAttack1 = CreatureBiteInfo(Vector3i(0, 128, 0), 2);
|
||||
const auto HarpyAttack2 = CreatureBiteInfo(Vector3i(0, 128, 0), 4);
|
||||
const auto HarpySwoopAttackJoints = std::vector<unsigned int>{ 2, 4, 15 };
|
||||
const auto HarpyStingerAttackJoints = std::vector<unsigned int>{ 2, 4 };
|
||||
|
||||
|
@ -105,8 +105,8 @@ namespace TEN::Entities::TR4
|
|||
{
|
||||
item->ItemFlags[0]++;
|
||||
|
||||
auto rh = GetJointPosition(item, HarpyAttack1.meshNum, Vector3i(HarpyAttack1.Position));
|
||||
auto lr = GetJointPosition(item, HarpyAttack2.meshNum, Vector3i(HarpyAttack2.Position));
|
||||
auto rh = GetJointPosition(item, HarpyAttack1);
|
||||
auto lr = GetJointPosition(item, HarpyAttack2);
|
||||
|
||||
int sG = (GetRandomControl() & 0x7F) + 32;
|
||||
int sR = sG;
|
||||
|
@ -149,7 +149,7 @@ namespace TEN::Entities::TR4
|
|||
{
|
||||
if (item->ItemFlags[0] <= 65 && GlobalCounter & 1)
|
||||
{
|
||||
auto pos3 = GetJointPosition(item, HarpyAttack1.meshNum, Vector3i(HarpyAttack1.Position.x, HarpyAttack1.Position.y * 2, HarpyAttack1.Position.z));
|
||||
auto pos3 = GetJointPosition(item, HarpyAttack1.BoneID, Vector3i(HarpyAttack1.Position.x, HarpyAttack1.Position.y * 2, HarpyAttack1.Position.z));
|
||||
auto orient = Geometry::GetOrientToPoint(lr.ToVector3(), rh.ToVector3());
|
||||
auto pose = Pose(rh, orient);
|
||||
TriggerHarpyMissile(&pose, item->RoomNumber, 2);
|
||||
|
@ -157,7 +157,7 @@ namespace TEN::Entities::TR4
|
|||
|
||||
if (item->ItemFlags[0] >= 61 && item->ItemFlags[0] <= 65 && !(GlobalCounter & 1))
|
||||
{
|
||||
auto pos3 = GetJointPosition(item, HarpyAttack2.meshNum, Vector3i(HarpyAttack2.Position.x, HarpyAttack2.Position.y * 2, HarpyAttack2.Position.z));
|
||||
auto pos3 = GetJointPosition(item, HarpyAttack2.BoneID, Vector3i(HarpyAttack2.Position.x, HarpyAttack2.Position.y * 2, HarpyAttack2.Position.z));
|
||||
auto orient = Geometry::GetOrientToPoint(lr.ToVector3(), rh.ToVector3());
|
||||
auto pose = Pose(rh, orient);
|
||||
TriggerHarpyMissile(&pose, item->RoomNumber, 2);
|
||||
|
|
|
@ -20,17 +20,16 @@ using namespace TEN::Math;
|
|||
|
||||
namespace TEN::Entities::TR4
|
||||
{
|
||||
const auto HorsemanBite1 = BiteInfo(Vector3::Zero, 6);
|
||||
const auto HorsemanBite2 = BiteInfo(Vector3::Zero, 14);
|
||||
const auto HorsemanBite3 = BiteInfo(Vector3::Zero, 10);
|
||||
const auto HorsemanBite1 = CreatureBiteInfo(Vector3i::Zero, 6);
|
||||
const auto HorsemanBite2 = CreatureBiteInfo(Vector3i::Zero, 14);
|
||||
const auto HorsemanBite3 = CreatureBiteInfo(Vector3i::Zero, 10);
|
||||
const auto HorsemanAxeAttackJoints = std::vector<unsigned int>{ 5, 6 };
|
||||
const auto HorsemanKickAttackJoints = std::vector<unsigned int>{ 14 };
|
||||
const auto HorsemanMountedAttackJoints = std::vector<unsigned int>{ 5, 6, 10 };
|
||||
const auto HorsemanShieldAttackJoints = std::vector<unsigned int>{ 10 };
|
||||
|
||||
const auto HorseBite1 = BiteInfo(Vector3::Zero, 13);
|
||||
const auto HorseBite2 = BiteInfo(Vector3::Zero, 17);
|
||||
const auto HorseBite3 = BiteInfo(Vector3::Zero, 19);
|
||||
const auto HorseBite1 = CreatureBiteInfo(Vector3i::Zero, 13);
|
||||
const auto HorseBite2 = CreatureBiteInfo(Vector3i::Zero, 17);
|
||||
const auto HorseBite3 = CreatureBiteInfo(Vector3i::Zero, 19);
|
||||
|
||||
enum HorsemanState
|
||||
{
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace TEN::Entities::TR4
|
|||
constexpr auto KTEMPLAR_IDLE_TURN_RATE_MAX = ANGLE(2.0f);
|
||||
constexpr auto KTEMPLAR_WALK_TURN_RATE_MAX = ANGLE(7.0f);
|
||||
|
||||
const auto KnightTemplarBite = BiteInfo(Vector3::Zero, 11);
|
||||
const auto KnightTemplarBite = CreatureBiteInfo(Vector3i::Zero, 11);
|
||||
const auto KnightTemplarSwordAttackJoints = std::vector<unsigned int>{ 10, 11 };
|
||||
|
||||
enum KnightTemplarState
|
||||
|
|
|
@ -28,8 +28,8 @@ namespace TEN::Entities::TR4
|
|||
constexpr auto MUMMY_WALK_TURN_RATE_MAX = ANGLE(7.0f);
|
||||
constexpr auto MUMMY_ATTACK_TURN_RATE_MAX = ANGLE(7.0f);
|
||||
|
||||
const auto MummyBite1 = BiteInfo(Vector3::Zero, 11);
|
||||
const auto MummyBite2 = BiteInfo(Vector3::Zero, 14);
|
||||
const auto MummyBite1 = CreatureBiteInfo(Vector3i::Zero, 11);
|
||||
const auto MummyBite2 = CreatureBiteInfo(Vector3i::Zero, 14);
|
||||
const auto MummySwipeAttackJoints = std::vector<unsigned int>{ 11, 14 };
|
||||
|
||||
enum MummyState
|
||||
|
|
|
@ -271,7 +271,7 @@ namespace TEN::Entities::TR4
|
|||
auto* item = &g_Level.Items[itemNumber];
|
||||
auto* creature = GetCreatureInfo(item);
|
||||
|
||||
OBJECT_BONES mutantJoint;
|
||||
auto head = EulerAngles::Zero, torso = EulerAngles::Zero;
|
||||
int frameNumber;
|
||||
short angle = 0;
|
||||
short headY = 0;
|
||||
|
@ -286,7 +286,7 @@ namespace TEN::Entities::TR4
|
|||
AI_INFO AI;
|
||||
MutantAIFix(item, &AI);
|
||||
|
||||
RotateHeadToTarget(item, creature, 9, headY);
|
||||
RotateHeadToTarget(item, creature, 9, head.y);
|
||||
GetCreatureMood(item, &AI, true);
|
||||
CreatureMood(item, &AI, true);
|
||||
|
||||
|
@ -350,14 +350,16 @@ namespace TEN::Entities::TR4
|
|||
}
|
||||
|
||||
if (item->Animation.ActiveState != MUTANT_STATE_LOCUST_ATTACK_1)
|
||||
mutantJoint = OBJECT_BONES(headY, AI.xAngle, true);
|
||||
else
|
||||
mutantJoint = OBJECT_BONES(0);
|
||||
{
|
||||
head.x = AI.xAngle;
|
||||
torso.x = AI.xAngle;
|
||||
torso.y = AI.angle;
|
||||
}
|
||||
|
||||
CreatureJoint(item, 0, mutantJoint.bone0);
|
||||
CreatureJoint(item, 1, mutantJoint.bone1);
|
||||
CreatureJoint(item, 2, mutantJoint.bone2);
|
||||
CreatureJoint(item, 3, mutantJoint.bone3);
|
||||
CreatureJoint(item, 0, head.y);
|
||||
CreatureJoint(item, 1, head.x);
|
||||
CreatureJoint(item, 2, torso.y);
|
||||
CreatureJoint(item, 3, torso.x);
|
||||
CreatureAnimation(itemNumber, angle, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace TEN::Entities::TR4
|
|||
constexpr auto SAS_WALK_RANGE = SQUARE(BLOCK(2));
|
||||
constexpr auto SAS_SHOOT_RANGE = SQUARE(BLOCK(3));
|
||||
|
||||
const auto SasGunBite = BiteInfo(Vector3(0.0f, 550.0f, 84.0f), 7);
|
||||
const auto SasGunBite = CreatureBiteInfo(Vector3i(0, 420, 80), 7);
|
||||
|
||||
const auto SasDragBodyPosition = Vector3i(0, 0, -460);
|
||||
const auto SasDragBounds = ObjectCollisionBounds
|
||||
|
@ -145,13 +145,8 @@ namespace TEN::Entities::TR4
|
|||
short joint1 = 0;
|
||||
short joint2 = 0;
|
||||
|
||||
// Handle SAS firing.
|
||||
if (creature.FiredWeapon)
|
||||
{
|
||||
auto pos = GetJointPosition(&item, SasGunBite.meshNum, Vector3i(SasGunBite.Position));
|
||||
TriggerDynamicLight(pos.x, pos.y, pos.z, 10, 24, 16, 4);
|
||||
creature.FiredWeapon--;
|
||||
}
|
||||
if (creature.MuzzleFlash[0].Delay != 0)
|
||||
creature.MuzzleFlash[0].Delay--;
|
||||
|
||||
if (item.HitPoints > 0)
|
||||
{
|
||||
|
@ -522,14 +517,15 @@ namespace TEN::Entities::TR4
|
|||
joint1 = AI.xAngle;
|
||||
}
|
||||
|
||||
if (creature.Flags)
|
||||
if (creature.Flags != 0)
|
||||
{
|
||||
creature.Flags -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShotLara(&item, &AI, SasGunBite, joint0, SAS_SHOT_DAMAGE);
|
||||
creature.FiredWeapon = 3;
|
||||
creature.MuzzleFlash[0].Bite = SasGunBite;
|
||||
creature.MuzzleFlash[0].Delay = 2;
|
||||
creature.Flags = 5;
|
||||
}
|
||||
|
||||
|
@ -540,9 +536,6 @@ namespace TEN::Entities::TR4
|
|||
item.Animation.TargetState = SAS_STATE_WAIT;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (FlashGrenadeAftershockTimer > 100 &&
|
||||
|
@ -659,7 +652,7 @@ namespace TEN::Entities::TR4
|
|||
grenadeItem->ObjectNumber = ID_GRENADE;
|
||||
grenadeItem->RoomNumber = item.RoomNumber;
|
||||
|
||||
auto pos = GetJointPosition(&item, SasGunBite.meshNum, Vector3i(SasGunBite.Position));
|
||||
auto pos = GetJointPosition(&item, SasGunBite);
|
||||
grenadeItem->Pose.Position = pos;
|
||||
|
||||
auto floorHeight = GetCollision(pos.x, pos.y, pos.z, grenadeItem->RoomNumber).Position.Floor;
|
||||
|
|
|
@ -21,7 +21,7 @@ using namespace TEN::Gui;
|
|||
namespace TEN::Entities::TR4
|
||||
{
|
||||
const auto SentryGunFlameOffset = Vector3i(-140, 0, 0);
|
||||
const auto SentryGunBite = BiteInfo(Vector3::Zero, 8);
|
||||
const auto SentryGunBite = CreatureBiteInfo(Vector3i::Zero, 8);
|
||||
|
||||
void InitializeSentryGun(short itemNumber)
|
||||
{
|
||||
|
@ -51,7 +51,7 @@ namespace TEN::Entities::TR4
|
|||
{
|
||||
if (item->ItemFlags[0])
|
||||
{
|
||||
auto pos = GetJointPosition(item, SentryGunBite.meshNum, Vector3i(SentryGunBite.Position));
|
||||
auto pos = GetJointPosition(item, SentryGunBite);
|
||||
TriggerDynamicLight(pos.x, pos.y, pos.z, 4 * item->ItemFlags[0] + 12, 24, 16, 4);
|
||||
item->ItemFlags[0]--;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue