2021-09-15 11:13:47 +03:00
|
|
|
#include <algorithm>
|
2020-05-23 14:26:06 +02:00
|
|
|
#include "framework.h"
|
2021-09-08 18:31:35 +03:00
|
|
|
#include "Specific\trmath.h"
|
2020-05-23 14:26:06 +02:00
|
|
|
#include "smoke.h"
|
|
|
|
#include "room.h"
|
2021-09-19 23:41:26 +03:00
|
|
|
#include "control/control.h"
|
2020-05-23 14:26:06 +02:00
|
|
|
#include "level.h"
|
2020-05-28 16:48:36 +02:00
|
|
|
#include "setup.h"
|
|
|
|
#include "lara.h"
|
2021-09-08 18:31:35 +03:00
|
|
|
#include "Specific\prng.h"
|
2021-09-15 11:13:47 +03:00
|
|
|
#include "effects\weather.h"
|
2021-09-25 16:00:30 +03:00
|
|
|
#include "items.h"
|
2021-09-25 11:27:47 +02:00
|
|
|
|
2021-09-15 11:13:47 +03:00
|
|
|
using namespace TEN::Effects::Environment;
|
2021-08-30 18:03:21 +03:00
|
|
|
using namespace TEN::Math::Random;
|
2021-09-15 11:13:47 +03:00
|
|
|
|
2021-08-30 18:03:21 +03:00
|
|
|
namespace TEN {
|
2020-05-28 16:48:36 +02:00
|
|
|
namespace Effects {
|
|
|
|
namespace Smoke {
|
2021-10-04 03:09:32 +03:00
|
|
|
|
2020-05-28 16:48:36 +02:00
|
|
|
std::array<SmokeParticle, 128> SmokeParticles;
|
2021-10-04 03:09:32 +03:00
|
|
|
|
|
|
|
SmokeParticle& GetFreeSmokeParticle()
|
2020-08-16 16:01:24 +02:00
|
|
|
{
|
2021-10-04 03:09:32 +03:00
|
|
|
for (int i = 0; i < SmokeParticles.size(); i++)
|
|
|
|
{
|
|
|
|
if (!SmokeParticles[i].active)
|
2020-08-16 16:01:24 +02:00
|
|
|
return SmokeParticles[i];
|
|
|
|
}
|
|
|
|
return SmokeParticles[0];
|
|
|
|
}
|
2021-10-04 03:09:32 +03:00
|
|
|
|
|
|
|
void DisableSmokeParticles()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < SmokeParticles.size(); i++)
|
|
|
|
SmokeParticles[i].active = false;
|
|
|
|
}
|
|
|
|
|
2020-05-28 16:48:36 +02:00
|
|
|
void UpdateSmokeParticles()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < SmokeParticles.size(); i++) {
|
|
|
|
SmokeParticle& s = SmokeParticles[i];
|
|
|
|
if (!s.active)continue;
|
|
|
|
s.age += 1;
|
|
|
|
if (s.age > s.life) {
|
|
|
|
s.active = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
s.velocity.y += s.gravity;
|
|
|
|
if (s.terminalVelocity != 0) {
|
|
|
|
float velocityLength = s.velocity.Length();
|
|
|
|
if (velocityLength > s.terminalVelocity) {
|
|
|
|
s.velocity *= (s.terminalVelocity / velocityLength);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
s.position += s.velocity;
|
|
|
|
if (s.affectedByWind) {
|
2020-07-21 09:56:47 +02:00
|
|
|
if (g_Level.Rooms[s.room].flags & ENV_FLAG_WIND) {
|
2021-09-15 11:13:47 +03:00
|
|
|
s.position.x += Weather.Wind().x;
|
|
|
|
s.position.z += Weather.Wind().z;
|
2020-05-28 16:48:36 +02:00
|
|
|
}
|
|
|
|
}
|
2020-09-16 11:45:54 +02:00
|
|
|
float normalizedLife = std::clamp(s.age / s.life,0.0f,1.0f);
|
2020-05-28 16:48:36 +02:00
|
|
|
s.size = lerp(s.sourceSize, s.destinationSize, normalizedLife);
|
|
|
|
s.angularVelocity *= s.angularDrag;
|
|
|
|
s.rotation += s.angularVelocity;
|
|
|
|
s.color = DirectX::SimpleMath::Vector4::Lerp(s.sourceColor, s.destinationColor, normalizedLife);
|
2020-09-16 11:45:54 +02:00
|
|
|
int numSprites = -Objects[ID_SMOKE_SPRITES].nmeshes;
|
|
|
|
s.sprite = lerp(0, numSprites - 1, normalizedLife);
|
2020-05-28 16:48:36 +02:00
|
|
|
}
|
|
|
|
}
|
2020-05-23 14:26:06 +02:00
|
|
|
|
2020-05-28 16:48:36 +02:00
|
|
|
void TriggerFlareSmoke(const DirectX::SimpleMath::Vector3& pos, DirectX::SimpleMath::Vector3& direction, int age, int room) {
|
|
|
|
using namespace DirectX::SimpleMath;
|
2021-10-04 03:09:32 +03:00
|
|
|
SmokeParticle & s = GetFreeSmokeParticle();
|
2020-05-28 16:48:36 +02:00
|
|
|
s = {};
|
|
|
|
s.position = pos;
|
|
|
|
s.age = 0;
|
|
|
|
constexpr float d = 0.2f;
|
2021-09-17 16:07:53 +03:00
|
|
|
Vector3 randomDir = Vector3(GenerateFloat(-d, d), GenerateFloat(-d, d), GenerateFloat(-d, d));
|
2020-05-28 16:48:36 +02:00
|
|
|
Vector3 dir;
|
|
|
|
(direction + randomDir).Normalize(dir);
|
2021-09-17 16:07:53 +03:00
|
|
|
s.velocity = dir * GenerateFloat(7, 9);
|
2020-05-28 16:48:36 +02:00
|
|
|
s.gravity = -0.2f;
|
2021-09-17 16:07:53 +03:00
|
|
|
s.friction = GenerateFloat(0.7f, 0.85f);
|
2020-05-28 16:48:36 +02:00
|
|
|
s.sourceColor = Vector4(1, 131 / 255.0f, 100 / 255.0f, 1);
|
2020-09-16 11:45:54 +02:00
|
|
|
s.destinationColor = Vector4(1, 1, 1, 0);
|
2021-09-17 16:07:53 +03:00
|
|
|
s.life = GenerateFloat(25, 35);
|
|
|
|
s.angularVelocity = GenerateFloat(-0.3f, 0.3f);
|
2020-09-16 11:45:54 +02:00
|
|
|
s.angularDrag = 0.97f;
|
2021-09-17 16:07:53 +03:00
|
|
|
s.sourceSize = age > 4 ? GenerateFloat(16, 24) : GenerateFloat(100, 128);
|
|
|
|
s.destinationSize = age > 4 ? GenerateFloat(160, 200) : GenerateFloat(256, 300);
|
2020-05-28 16:48:36 +02:00
|
|
|
s.affectedByWind = true;
|
|
|
|
s.active = true;
|
|
|
|
s.room = room;
|
2020-05-23 14:26:06 +02:00
|
|
|
}
|
2021-10-04 03:09:32 +03:00
|
|
|
|
2020-09-13 21:03:46 +02:00
|
|
|
//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, int weaponType, byte count)
|
2020-05-28 16:48:36 +02:00
|
|
|
{
|
2021-10-04 03:09:32 +03:00
|
|
|
SmokeParticle& s = GetFreeSmokeParticle();
|
2020-05-28 16:48:36 +02:00
|
|
|
s = {};
|
|
|
|
s.active = true;
|
|
|
|
s.position = Vector3(x, y, z);
|
2020-08-16 16:01:24 +02:00
|
|
|
Vector3 dir = Vector3(xv, yv, zv);
|
|
|
|
dir.Normalize();
|
|
|
|
s.velocity = dir;
|
2020-05-28 16:48:36 +02:00
|
|
|
s.gravity = -.1f;
|
2020-07-21 09:56:47 +02:00
|
|
|
s.affectedByWind = g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WIND;
|
2020-05-28 16:48:36 +02:00
|
|
|
s.sourceColor = Vector4(.4, .4, .4, 1);
|
|
|
|
s.destinationColor = Vector4(0, 0, 0, 0);
|
2020-05-23 14:26:06 +02:00
|
|
|
|
2020-05-28 16:48:36 +02:00
|
|
|
if (initial)
|
|
|
|
{
|
2020-09-13 21:03:46 +02:00
|
|
|
if(weaponType == LARA_WEAPON_TYPE::WEAPON_ROCKET_LAUNCHER){
|
2021-09-17 16:07:53 +03:00
|
|
|
float size = GenerateFloat(48, 80);
|
2020-09-13 21:03:46 +02:00
|
|
|
s.sourceSize = size * 2;
|
|
|
|
|
|
|
|
s.destinationSize = size * 8;
|
|
|
|
s.sourceColor = {0.75,0.75,1,1};
|
|
|
|
s.terminalVelocity = 0;
|
|
|
|
s.friction = 0.82f;
|
2021-09-17 16:07:53 +03:00
|
|
|
s.life = GenerateFloat(60, 90);
|
2020-09-13 21:03:46 +02:00
|
|
|
if(initial == 1){
|
2021-09-17 16:07:53 +03:00
|
|
|
float size = GenerateFloat(48, 80);
|
2020-09-13 21:03:46 +02:00
|
|
|
s.sourceSize = size * 2;
|
|
|
|
s.destinationSize = size * 16;
|
|
|
|
s.velocity = getRandomVectorInCone(dir,25);
|
2021-09-17 16:07:53 +03:00
|
|
|
s.velocity *= GenerateFloat(0, 32);
|
2020-09-13 21:03:46 +02:00
|
|
|
} else{
|
2021-09-17 16:07:53 +03:00
|
|
|
float size = GenerateFloat(48, 80);
|
2020-09-13 21:03:46 +02:00
|
|
|
s.sourceSize = size;
|
|
|
|
s.destinationSize = size * 8;
|
|
|
|
s.velocity = getRandomVectorInCone(dir,3);
|
2021-09-17 16:07:53 +03:00
|
|
|
s.velocity *= GenerateFloat(0, 16);
|
2020-09-13 21:03:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
} else{
|
2021-09-17 16:07:53 +03:00
|
|
|
float size = GenerateFloat(48, 73);
|
2020-09-13 21:03:46 +02:00
|
|
|
s.sourceSize = size * 2;
|
|
|
|
s.destinationSize = size * 8;
|
|
|
|
s.terminalVelocity = 0;
|
|
|
|
s.friction = 0.88f;
|
2021-09-17 16:07:53 +03:00
|
|
|
s.life = GenerateFloat(60, 90);
|
2020-09-13 21:03:46 +02:00
|
|
|
s.velocity = getRandomVectorInCone(dir, 10);
|
2021-09-17 16:07:53 +03:00
|
|
|
s.velocity *= GenerateFloat(16, 30);
|
2020-09-13 21:03:46 +02:00
|
|
|
}
|
2020-05-28 16:48:36 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-01 08:46:07 +02:00
|
|
|
float size = (float)((GetRandomControl() & 0x0F) + 48); // -TriggerGunSmoke_SubFunction(weaponType);
|
2020-09-13 21:03:46 +02:00
|
|
|
if(weaponType == LARA_WEAPON_TYPE::WEAPON_ROCKET_LAUNCHER){
|
|
|
|
s.sourceColor = {0.75,0.75,1,1};
|
2020-07-01 08:46:07 +02:00
|
|
|
|
2020-09-13 21:03:46 +02:00
|
|
|
}
|
2020-05-28 16:48:36 +02:00
|
|
|
s.sourceSize = size / 2;
|
2020-07-01 08:46:07 +02:00
|
|
|
s.destinationSize = size * 4;
|
|
|
|
s.terminalVelocity = 0;
|
|
|
|
s.friction = 0.97f;
|
2021-09-17 16:07:53 +03:00
|
|
|
s.life = GenerateFloat(42, 62);
|
|
|
|
s.velocity *= GenerateFloat(16, 40);
|
2020-07-01 08:46:07 +02:00
|
|
|
|
2020-05-28 16:48:36 +02:00
|
|
|
}
|
|
|
|
s.position = Vector3(x, y, z);
|
2021-09-17 16:07:53 +03:00
|
|
|
s.position += Vector3(GenerateFloat(-8, 8), GenerateFloat(-8, 8), GenerateFloat(-8, 8));
|
|
|
|
s.angularVelocity = GenerateFloat(-PI / 4, PI / 4);
|
2020-07-01 08:46:07 +02:00
|
|
|
|
2020-08-16 16:01:24 +02:00
|
|
|
s.angularDrag = 0.95f;
|
2020-05-28 16:48:36 +02:00
|
|
|
s.room = LaraItem->roomNumber;
|
2020-07-01 08:46:07 +02:00
|
|
|
|
2020-05-28 16:48:36 +02:00
|
|
|
}
|
|
|
|
|
2020-09-12 13:49:09 +02:00
|
|
|
void TriggerQuadExhaustSmoke(int x, int y, int z, short angle, int speed, int moving)
|
|
|
|
{
|
2021-10-04 03:09:32 +03:00
|
|
|
SmokeParticle& s = GetFreeSmokeParticle();
|
2020-09-12 13:49:09 +02:00
|
|
|
s = {};
|
2021-09-17 16:07:53 +03:00
|
|
|
s.position = Vector3(x, y, z) + Vector3(GenerateFloat(8, 16), GenerateFloat(8, 16), GenerateFloat(8, 16));
|
2020-09-12 13:49:09 +02:00
|
|
|
float xVel = std::sin(TO_RAD(angle))*speed;
|
|
|
|
float zVel = std::cos(TO_RAD(angle))*speed;
|
2021-09-17 16:07:53 +03:00
|
|
|
s.velocity = Vector3(xVel, GenerateFloat(-1, 4), zVel);
|
2020-09-12 13:49:09 +02:00
|
|
|
s.sourceColor = Vector4(1, 1, 1, 1);
|
|
|
|
s.destinationColor = Vector4(0, 0, 0, 0);
|
2021-09-17 16:07:53 +03:00
|
|
|
s.sourceSize = GenerateFloat(8,24);
|
2020-09-12 13:49:09 +02:00
|
|
|
s.active = true;
|
|
|
|
s.affectedByWind = true;
|
|
|
|
s.friction = 0.999f;
|
|
|
|
s.gravity = -0.1f;
|
2021-09-17 16:07:53 +03:00
|
|
|
s.life = GenerateFloat(16, 24);
|
|
|
|
s.destinationSize = GenerateFloat(128, 160);
|
|
|
|
s.angularVelocity = GenerateFloat(-1, 1);
|
|
|
|
s.angularDrag = GenerateFloat(0.97, 0.999);
|
2020-09-12 13:49:09 +02:00
|
|
|
}
|
|
|
|
|
2020-09-13 21:03:46 +02:00
|
|
|
void TriggerRocketSmoke(int x, int y, int z, int bodyPart)
|
|
|
|
{
|
2021-10-04 03:09:32 +03:00
|
|
|
SmokeParticle& s = GetFreeSmokeParticle();
|
2020-09-13 21:03:46 +02:00
|
|
|
s = {};
|
2021-09-17 16:07:53 +03:00
|
|
|
s.position = Vector3(x, y, z) + Vector3(GenerateFloat(8, 16), GenerateFloat(8, 16), GenerateFloat(8, 16));
|
2020-09-13 21:03:46 +02:00
|
|
|
s.sourceColor = Vector4(0.8, 0.8, 1, 1);
|
|
|
|
s.destinationColor = Vector4(0, 0, 0, 0);
|
2021-09-17 16:07:53 +03:00
|
|
|
s.sourceSize = GenerateFloat(32, 64);
|
2020-09-13 21:03:46 +02:00
|
|
|
s.active = true;
|
2021-09-17 16:07:53 +03:00
|
|
|
s.velocity = getRandomVector() * GenerateFloat(1, 3);
|
2020-09-13 21:03:46 +02:00
|
|
|
s.affectedByWind = true;
|
|
|
|
s.friction = 0.979f;
|
|
|
|
s.gravity = -0.1f;
|
2021-09-17 16:07:53 +03:00
|
|
|
s.life = GenerateFloat(80, 120);
|
|
|
|
s.destinationSize = GenerateFloat(1024, 1152);
|
|
|
|
s.angularVelocity = GenerateFloat(-0.6, 0.6);
|
|
|
|
s.angularDrag = GenerateFloat(0.87, 0.99);
|
2020-09-13 21:03:46 +02:00
|
|
|
}
|
2020-05-28 16:48:36 +02:00
|
|
|
}
|
2020-05-23 14:26:06 +02:00
|
|
|
}
|
|
|
|
}
|