fix-TR4-knight-templar (#900)

* fix-TR4-knight-templar
* Fix formatting; use "for each" loop
* Use references; formatting
* Formatting
* fixed attack static shatter
* fixed if undead

Co-authored-by: Sezz <sezzary@outlook.com>
This commit is contained in:
Nemoel-Tomo 2022-12-11 14:28:26 +01:00 committed by GitHub
parent 64fc8c05cf
commit 5b8540836d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 54 additions and 40 deletions

View file

@ -1557,7 +1557,7 @@ void HandleProjectile(ItemInfo& item, ItemInfo& emitter, const Vector3i& prevPos
if (isExplosive)
{
doExplosion = isExplosive;
if (type != ProjectileType::FlashGrenade)
if (type != ProjectileType::FlashGrenade && !currentObject.undead)
DoExplosiveDamage(emitter, *currentItem, item, damage);
}
else if (type == ProjectileType::Poison)
@ -1568,7 +1568,7 @@ void HandleProjectile(ItemInfo& item, ItemInfo& emitter, const Vector3i& prevPos
if (currentItem->IsLara())
GetLaraInfo(currentItem)->PoisonPotency += 5;
}
else
else if (!currentObject.undead)
{
DoDamage(currentItem, damage);
}

View file

@ -1486,10 +1486,13 @@ void TriggerFireFlame(int x, int y, int z, FlameType type, const Vector3& color1
}
}
void TriggerMetalSparks(int x, int y, int z, int xv, int yv, int zv, int additional)
void TriggerMetalSparks(int x, int y, int z, int xv, int yv, int zv, const Vector3& color, int additional)
{
int dx = LaraItem->Pose.Position.x - x;
int dz = LaraItem->Pose.Position.z - z;
int colorR = std::clamp(int(color.x * UCHAR_MAX), 0, UCHAR_MAX);
int colorG = std::clamp(int(color.y * UCHAR_MAX), 0, UCHAR_MAX);
int colorB = std::clamp(int(color.z * UCHAR_MAX), 0, UCHAR_MAX);
if (dx >= -16384 && dx <= 16384 && dz >= -16384 && dz <= 16384)
{
@ -1497,14 +1500,14 @@ void TriggerMetalSparks(int x, int y, int z, int xv, int yv, int zv, int additio
auto* spark = GetFreeParticle();
spark->dG = (r & 0x7F) + 64;
spark->dB = -64 - (r & 0x7F) + 64;
spark->dG = colorG;
spark->dB = colorB;
spark->life = 10;
spark->sLife = 10;
spark->sR = 255;
spark->sG = 255;
spark->sB = 255;
spark->dR = 255;
spark->sR = colorR;
spark->sG = colorG;
spark->sB = colorB;
spark->dR = colorR;
spark->x = (r & 7) + x - 3;
spark->on = 1;
spark->colFadeSpeed = 3;
@ -1512,7 +1515,7 @@ void TriggerMetalSparks(int x, int y, int z, int xv, int yv, int zv, int additio
spark->y = ((r >> 3) & 7) + y - 3;
spark->blendMode = BLEND_MODES::BLENDMODE_ADDITIVE;
spark->friction = 34;
spark->scalar = 1;
spark->scalar = 2;
spark->z = ((r >> 6) & 7) + z - 3;
spark->flags = 2;
spark->xVel = (byte)(r >> 2) + xv - 128;

View file

@ -221,7 +221,7 @@ void TriggerDynamicLight(int x, int y, int z, short falloff, byte r, byte g, byt
void TriggerRocketFlame(int x, int y, int z, int xv, int yv, int zv, int itemNumber);
void TriggerRocketSmoke(int x, int y, int z, int bodyPart);
void TriggerFlashSmoke(int x, int y, int z, short roomNumber);
void TriggerMetalSparks(int x, int y, int z, int xv, int yv, int zv, int additional);
void TriggerMetalSparks(int x, int y, int z, int xv, int yv, int zv, const Vector3& color, int additional);
void TriggerAttackFlame(const Vector3i& pos, const Vector3& color, int scale);
void WadeSplash(ItemInfo* item, int wh, int wd);
void Splash(ItemInfo* item);

View file

@ -521,7 +521,7 @@ namespace TEN::Entities::TR4
}
else
{
TriggerMetalSparks(pos1.x, pos1.y, pos1.z, -1, -1, 0, 1);
TriggerMetalSparks(pos1.x, pos1.y, pos1.z, -1, -1, 0, Vector3(1.0f, 1.0f, 0.3f), 1);
TriggerDynamicLight(
pos1.x, pos1.y, pos1.z,
10,
@ -557,7 +557,7 @@ namespace TEN::Entities::TR4
96 - ((random >> 6) & 0x1F),
128 - ((random >> 4) & 0x1F));
TriggerMetalSparks(pos1.x, pos1.y, pos1.z, -1, -1, 0, 1);
TriggerMetalSparks(pos1.x, pos1.y, pos1.z, -1, -1, 0, Vector3(1.0f, 1.0f, 0.3f), 1);
}
break;

View file

@ -11,21 +11,20 @@
#include "Game/misc.h"
#include "Sound/sound.h"
#include "Specific/level.h"
#include "Math/Random.h"
#include "Math/Math.h"
#include "Specific/setup.h"
using namespace TEN::Math::Random;
using std::vector;
using namespace TEN::Math;
namespace TEN::Entities::TR4
{
constexpr auto KNIGHT_TEMPLAR_SWORD_ATTACK_DAMAGE = 120;
#define KTEMPLAR_IDLE_TURN_RATE_MAX ANGLE(2.0f)
#define KTEMPLAR_WALK_TURN_RATE_MAX ANGLE(7.0f)
const auto KTEMPLAR_IDLE_TURN_RATE_MAX = ANGLE(2.0f);
const auto KTEMPLAR_WALK_TURN_RATE_MAX = ANGLE(7.0f);
const auto KnightTemplarBite = BiteInfo(Vector3::Zero, 11);
const vector<unsigned int> KnightTemplarSwordAttackJoints = { 10, 11 };
const std::vector<unsigned int> KnightTemplarSwordAttackJoints = { 10, 11 };
enum KnightTemplarState
{
@ -86,10 +85,11 @@ namespace TEN::Entities::TR4
(item->Animation.AnimNumber - object->animIndex) == KTEMPLAR_ANIM_WALK_FORWARD_LEFT_2 ||
(item->Animation.AnimNumber - object->animIndex) == KTEMPLAR_ANIM_WALK_FORWARD_RIGHT_2)
{
if (TestProbability(0.5f))
if (Random::TestProbability(1 / 2.0f))
{
auto color = Vector3(0.9f, 0.8f, 0.6f);
auto pos = GetJointPosition(item, 10, Vector3i(0, 48, 448));
TriggerMetalSparks(pos.x, pos.y, pos.z, (GetRandomControl() & 0x1FF) - 256, -128 - (GetRandomControl() & 0x7F), (GetRandomControl() & 0x1FF) - 256, 0);
TriggerMetalSparks(pos.x, pos.y, pos.z, (GetRandomControl() & 0x1FF) - 256, -128 - (GetRandomControl() & 0x7F), (GetRandomControl() & 0x1FF) - 256, color, 0);
}
}
@ -132,24 +132,30 @@ namespace TEN::Entities::TR4
creature->MaxTurn = KTEMPLAR_IDLE_TURN_RATE_MAX;
creature->Flags = 0;
if (AI.distance > pow(SECTOR(0.67f), 2))
if (AI.distance > SQUARE(BLOCK(2 / 3.0f)))
{
if (Lara.TargetEntity == item)
item->Animation.TargetState = KTEMPLAR_STATE_SHIELD;
}
else if (TestProbability(0.5f))
else if (Random::TestProbability(1 / 2.0f))
{
item->Animation.TargetState = KTEMPLAR_STATE_SWORD_ATTACK_2;
else if (TestProbability(0.5f))
}
else if (Random::TestProbability(1 / 2.0f))
{
item->Animation.TargetState = KTEMPLAR_STATE_SWORD_ATTACK_1;
}
else
{
item->Animation.TargetState = KTEMPLAR_STATE_SWORD_ATTACK_3;
}
break;
case KTEMPLAR_STATE_WALK_FORWARD:
creature->MaxTurn = KTEMPLAR_WALK_TURN_RATE_MAX;
if (Lara.TargetEntity == item || AI.distance <= pow(SECTOR(0.67f), 2))
if (Lara.TargetEntity == item || AI.distance <= SQUARE(BLOCK(2 / 3.0f)))
item->Animation.TargetState = KTEMPLAR_STATE_IDLE;
break;
@ -167,7 +173,9 @@ namespace TEN::Entities::TR4
item->Pose.Orientation.y -= ANGLE(1.0f);
}
else
{
item->Pose.Orientation.y += AI.angle;
}
frameNumber = item->Animation.FrameNumber;
frameBase = g_Level.Anims[item->Animation.AnimNumber].frameBase;
@ -176,28 +184,24 @@ namespace TEN::Entities::TR4
{
auto pos = GetJointPosition(item, LM_LINARM);
auto* room = &g_Level.Rooms[item->RoomNumber];
FloorInfo* currentFloor = &room->floor[(pos.z - room->z) / SECTOR(1) + (pos.z - room->x) / SECTOR(1) * room->zSize];
auto& room = g_Level.Rooms[item->RoomNumber];
auto& currentFloor = room.floor[(pos.z - room.z) / BLOCK(1) + (pos.x - room.x) / BLOCK(1) * room.zSize];
if (currentFloor->Stopper)
if (currentFloor.Stopper)
{
for (int i = 0; i < room->mesh.size(); i++)
for (auto& mesh : room.mesh)
{
auto* mesh = &room->mesh[i];
if (floor(pos.x) == floor(mesh->pos.Position.x) &&
floor(pos.z) == floor(mesh->pos.Position.z) &&
StaticObjects[mesh->staticNumber].shatterType != SHT_NONE)
if (abs(pos.x - mesh.pos.Position.x) < SECTOR(1) &&
abs(pos.z - mesh.pos.Position.z) < SECTOR(1) &&
StaticObjects[mesh.staticNumber].shatterType == SHT_NONE)
{
ShatterObject(nullptr, mesh, -64, LaraItem->RoomNumber, 0);
ShatterObject(nullptr, &mesh, -64, LaraItem->RoomNumber, 0);
SoundEffect(SFX_TR4_SMASH_ROCK, &item->Pose);
currentFloor->Stopper = false;
currentFloor.Stopper = false;
TestTriggers(pos.x, pos.y, pos.z, item->RoomNumber, true);
}
mesh++;
}
}
@ -223,19 +227,25 @@ namespace TEN::Entities::TR4
item->Pose.Orientation.y -= ANGLE(1.0f);
}
else
{
item->Pose.Orientation.y += AI.angle;
}
if (item->HitStatus)
{
if (TestProbability(0.5f))
if (Random::TestProbability(1 / 2.0f))
item->Animation.TargetState = KTEMPLAR_STATE_SHIELD_HIT_1;
else
item->Animation.TargetState = KTEMPLAR_STATE_SHIELD_HIT_2;
}
else if (AI.distance <= pow(SECTOR(0.67f), 2) || Lara.TargetEntity != item)
else if (AI.distance <= SQUARE(BLOCK(2 / 3.0f)) || Lara.TargetEntity != item)
{
item->Animation.TargetState = KTEMPLAR_STATE_IDLE;
}
else
{
item->Animation.TargetState = KTEMPLAR_STATE_SHIELD;
}
break;

View file

@ -307,6 +307,7 @@ namespace TEN::Entities
obj->pivotLength = 50;
obj->radius = 128;
obj->intelligent = true;
obj->undead = true;
obj->ZoneType = ZoneType::Basic;
g_Level.Bones[obj->boneIndex + 6 * 4] |= ROT_X | ROT_Y;
g_Level.Bones[obj->boneIndex + 7 * 4] |= ROT_Y;