mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-28 07:47:57 +03:00
Tomo - fireflies (#1597)
* tests only - nothing to see * update * update * update * update corpse * update savegame, formatting * import develop * formatting * fix broken streamer vertex * update firefly streamer spawn * update effect * Add in objects for fireflies * fixed all reviews, formatting, changing on-off cycle * formatting * reduced the emitted light to two lights per cluster * adding antitrigger * formatting * fixed corpse * fixed a bug with corpse * fixed corpse fall bug * formatting * Small refactors * Fix merge --------- Co-authored-by: Stranger1992 <84292688+Stranger1992@users.noreply.github.com> Co-authored-by: Lwmte <3331699+Lwmte@users.noreply.github.com>
This commit is contained in:
parent
8e5f045d02
commit
9469a0e63a
17 changed files with 1220 additions and 71 deletions
|
@ -952,6 +952,7 @@ DOPPELGANGER_ORIGIN
|
|||
CORPSE
|
||||
WRAITH_TRAP
|
||||
WATERFALL_EMITTER
|
||||
FIREFLY_EMITTER
|
||||
MESHSWAP1
|
||||
MESHSWAP2
|
||||
MESHSWAP3
|
||||
|
@ -1132,6 +1133,7 @@ AIR_BAR_TEXTURE
|
|||
DASH_BAR_TEXTURE
|
||||
SFX_BAR_TEXTURE
|
||||
WATERFALL_SPRITES
|
||||
FIREFLY_SPRITES
|
||||
CROSSHAIR_GRAPHICS
|
||||
SPEEDOMETER_GRAPHICS
|
||||
CUSTOM_BAR_GRAPHICS
|
||||
|
@ -1410,6 +1412,7 @@ AIR_BAR_TEXTURE
|
|||
DASH_BAR_TEXTURE
|
||||
SFX_BAR_TEXTURE
|
||||
WATERFALL_SPRITES
|
||||
FIREFLY_SPRITES
|
||||
CROSSHAIR_GRAPHICS
|
||||
SPEEDOMETER_GRAPHICS
|
||||
CUSTOM_BAR_GRAPHICS
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "Objects/TR4/Entity/tr4_beetle_swarm.h"
|
||||
#include "Objects/Utils/object_helper.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Objects/Effects/Fireflies.h"
|
||||
|
||||
using namespace TEN::Effects::Hair;
|
||||
using namespace TEN::Entities;
|
||||
|
@ -200,6 +201,7 @@ void InitializeSpecialEffects()
|
|||
|
||||
TEN::Entities::TR4::ClearBeetleSwarm();
|
||||
TEN::Entities::Creatures::TR3::ClearFishSwarm();
|
||||
TEN::Effects::Fireflies::ClearFireflySwarm();
|
||||
}
|
||||
|
||||
void CustomObjects()
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include "Specific/Input/Input.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Specific/winmain.h"
|
||||
#include "Objects/Effects/Fireflies.h"
|
||||
|
||||
using namespace std::chrono;
|
||||
using namespace TEN::Effects;
|
||||
|
@ -89,6 +90,7 @@ using namespace TEN::Math;
|
|||
using namespace TEN::Renderer;
|
||||
using namespace TEN::Entities::Creatures::TR3;
|
||||
using namespace TEN::Entities::Effects;
|
||||
using namespace TEN::Effects::Fireflies;
|
||||
|
||||
constexpr auto DEATH_NO_INPUT_TIMEOUT = 10 * FPS;
|
||||
constexpr auto DEATH_INPUT_TIMEOUT = 3 * FPS;
|
||||
|
@ -211,6 +213,7 @@ GameStatus GamePhase(bool insideMenu)
|
|||
UpdateLocusts();
|
||||
UpdateUnderwaterBloodParticles();
|
||||
UpdateFishSwarm();
|
||||
UpdateFireflySwarm();
|
||||
UpdateGlobalLensFlare();
|
||||
|
||||
// Update HUD.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "Game/Setup.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Objects/Effects/Fireflies.h"
|
||||
#include "Objects/Generic/puzzles_keys.h"
|
||||
#include "Objects/TR3/Entity/FishSwarm.h"
|
||||
#include "Objects/TR4/Entity/tr4_beetle_swarm.h"
|
||||
|
@ -29,6 +30,7 @@ using namespace TEN::Effects::Environment;
|
|||
using namespace TEN::Effects::Footprint;
|
||||
using namespace TEN::Effects::Hair;
|
||||
using namespace TEN::Entities::Creatures::TR3;
|
||||
using namespace TEN::Effects::Fireflies;
|
||||
|
||||
int FlipEffect;
|
||||
|
||||
|
@ -90,6 +92,7 @@ void ClearSwarmEnemies(ItemInfo* item)
|
|||
ClearBeetleSwarm();
|
||||
ClearLocusts();
|
||||
ClearFishSwarm();
|
||||
ClearFireflySwarm();
|
||||
}
|
||||
|
||||
void FlashOrange(ItemInfo* item)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "Game/control/flipeffect.h"
|
||||
#include "Game/control/lot.h"
|
||||
#include "Game/control/volume.h"
|
||||
#include "Objects/Effects/Fireflies.h"
|
||||
#include "Game/effects/item_fx.h"
|
||||
#include "Game/effects/effects.h"
|
||||
#include "Game/effects/weather.h"
|
||||
|
@ -43,8 +44,9 @@
|
|||
using namespace flatbuffers;
|
||||
using namespace TEN::Collision::Floordata;
|
||||
using namespace TEN::Control::Volumes;
|
||||
using namespace TEN::Effects::Items;
|
||||
using namespace TEN::Effects::Environment;
|
||||
using namespace TEN::Effects::Fireflies;
|
||||
using namespace TEN::Effects::Items;
|
||||
using namespace TEN::Entities::Creatures::TR3;
|
||||
using namespace TEN::Entities::Generic;
|
||||
using namespace TEN::Entities::Switches;
|
||||
|
@ -924,6 +926,38 @@ const std::vector<byte> SaveGame::Build()
|
|||
}
|
||||
auto fishSwarmOffset = fbb.CreateVector(fishSwarm);
|
||||
|
||||
std::vector<flatbuffers::Offset<Save::FireflyData>> fireflySwarm;
|
||||
for (const auto& firefly : FireflySwarm)
|
||||
{
|
||||
Save::FireflyDataBuilder fireflySave{ fbb };
|
||||
fireflySave.add_sprite_index(firefly.SpriteSeqID);
|
||||
fireflySave.add_sprite_id(firefly.SpriteID);
|
||||
fireflySave.add_blend_mode((int)firefly.blendMode);
|
||||
fireflySave.add_scalar(firefly.scalar);
|
||||
fireflySave.add_position(&FromVector3(firefly.Position));
|
||||
fireflySave.add_room_number(firefly.RoomNumber);
|
||||
fireflySave.add_position_target(&FromVector3(firefly.PositionTarget));
|
||||
fireflySave.add_orientation(&FromEulerAngles(firefly.Orientation));
|
||||
fireflySave.add_velocity(firefly.Velocity);
|
||||
fireflySave.add_target_item_number((firefly.TargetItemPtr == nullptr) ? -1 : firefly.TargetItemPtr->Index);
|
||||
fireflySave.add_z_vel(firefly.zVel);
|
||||
fireflySave.add_life(firefly.Life);
|
||||
fireflySave.add_number(firefly.Number);
|
||||
fireflySave.add_d_r(firefly.rB);
|
||||
fireflySave.add_d_g(firefly.gB);
|
||||
fireflySave.add_d_b(firefly.bB);
|
||||
fireflySave.add_r(firefly.r);
|
||||
fireflySave.add_g(firefly.g);
|
||||
fireflySave.add_b(firefly.b);
|
||||
fireflySave.add_on(firefly.on);
|
||||
fireflySave.add_size(firefly.size);
|
||||
fireflySave.add_rot_Ang(firefly.rotAng);
|
||||
|
||||
auto fireflySaveOffset = fireflySave.Finish();
|
||||
fireflySwarm.push_back(fireflySaveOffset);
|
||||
}
|
||||
auto fireflySwarmOffset = fbb.CreateVector(fireflySwarm);
|
||||
|
||||
// TODO: In future, we should save only active FX, not whole array.
|
||||
// This may come together with Monty's branch merge -- Lwmte, 10.07.22
|
||||
|
||||
|
@ -1545,6 +1579,7 @@ const std::vector<byte> SaveGame::Build()
|
|||
sgb.add_next_item_active(NextItemActive);
|
||||
sgb.add_items(serializedItemsOffset);
|
||||
sgb.add_fish_swarm(fishSwarmOffset);
|
||||
sgb.add_firefly_swarm(fireflySwarmOffset);
|
||||
sgb.add_fxinfos(serializedEffectsOffset);
|
||||
sgb.add_next_fx_free(NextFxFree);
|
||||
sgb.add_next_fx_active(NextFxActive);
|
||||
|
@ -2289,6 +2324,38 @@ static void ParseEffects(const Save::SaveGame* s)
|
|||
FishSwarm.push_back(fish);
|
||||
}
|
||||
|
||||
// Load firefly swarm.
|
||||
for (int i = 0; i < s->firefly_swarm()->size(); i++)
|
||||
{
|
||||
const auto& fireflySave = s->firefly_swarm()->Get(i);
|
||||
auto firefly = FireflyData{};
|
||||
|
||||
firefly.SpriteSeqID = fireflySave->sprite_index();
|
||||
firefly.SpriteID = fireflySave->sprite_id();
|
||||
firefly.blendMode = (BlendMode)fireflySave->blend_mode();
|
||||
firefly.scalar = fireflySave->scalar();
|
||||
firefly.Position = ToVector3(fireflySave->position());
|
||||
firefly.RoomNumber = fireflySave->room_number();
|
||||
firefly.PositionTarget = ToVector3(fireflySave->position_target());
|
||||
firefly.Orientation = ToEulerAngles(fireflySave->orientation());
|
||||
firefly.Velocity = fireflySave->velocity();
|
||||
firefly.TargetItemPtr = (fireflySave->target_item_number() == -1) ? nullptr : &g_Level.Items[fireflySave->target_item_number()];
|
||||
firefly.zVel = fireflySave->z_vel();
|
||||
firefly.Life = fireflySave->life();
|
||||
firefly.Number = fireflySave->number();
|
||||
firefly.rB = fireflySave->d_r();
|
||||
firefly.gB = fireflySave->d_g();
|
||||
firefly.bB = fireflySave->d_b();
|
||||
firefly.r = fireflySave->r();
|
||||
firefly.g = fireflySave->g();
|
||||
firefly.b = fireflySave->b();
|
||||
firefly.on = fireflySave->on();
|
||||
firefly.size = fireflySave->size();
|
||||
firefly.rotAng = fireflySave->rot_Ang();
|
||||
|
||||
FireflySwarm.push_back(firefly);
|
||||
}
|
||||
|
||||
// Load particles.
|
||||
for (int i = 0; i < s->particles()->size(); i++)
|
||||
{
|
||||
|
|
445
TombEngine/Objects/Effects/Fireflies.cpp
Normal file
445
TombEngine/Objects/Effects/Fireflies.cpp
Normal file
|
@ -0,0 +1,445 @@
|
|||
#include "framework.h"
|
||||
#include "Objects/Effects/Fireflies.h"
|
||||
|
||||
#include "Game/collision/collide_item.h"
|
||||
#include "Game/collision/collide_room.h"
|
||||
#include "Game/collision/Point.h"
|
||||
#include "Game/control/box.h"
|
||||
#include "Game/control/flipeffect.h"
|
||||
#include "Game/effects/effects.h"
|
||||
#include "Game/effects/Streamer.h"
|
||||
#include "Game/effects/tomb4fx.h"
|
||||
#include "Game/items.h"
|
||||
#include "Game/Lara/lara.h"
|
||||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/misc.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Renderer/Renderer.h"
|
||||
#include "Specific/clock.h"
|
||||
#include "Specific/level.h"
|
||||
|
||||
using namespace TEN::Collision::Point;
|
||||
using namespace TEN::Math;
|
||||
using namespace TEN::Renderer;
|
||||
using namespace TEN::Effects::Streamer;
|
||||
|
||||
namespace TEN::Effects::Fireflies
|
||||
{
|
||||
constexpr auto FIREFLY_COHESION_FACTOR = 600.1f;
|
||||
constexpr auto FIREFLY_SPACING_FACTOR = 600.0f;
|
||||
constexpr auto FIREFLY_CATCH_UP_FACTOR = 0.2f;
|
||||
constexpr auto FIREFLY_TARGET_DISTANCE_MAX = SQUARE(BLOCK(1.0f));
|
||||
constexpr auto FIREFLY_BASE_SEPARATION_DISTANCE = 10.0f;
|
||||
constexpr auto FIREFLY_FLEE_DISTANCE = BLOCK(0.7);
|
||||
constexpr auto MAX_FIREFLIES = 92;
|
||||
constexpr auto DEFAULT_FIREFLY_COUNT = 20;
|
||||
constexpr auto FIREFLY_RISE_UP_FACTOR = 200;
|
||||
constexpr auto MAX_AREA_RANGE = 8;
|
||||
constexpr auto LIGHT_ALPHA_CYCLE_DURATION = 120.0f;
|
||||
|
||||
std::vector<FireflyData> FireflySwarm = {};
|
||||
std::unordered_map<int, int> nextFireflyNumberMap; // Numbering the Fireflies for Streamer effect.
|
||||
|
||||
void InitializeFireflySwarm(short itemNumber)
|
||||
{
|
||||
auto& item = g_Level.Items[itemNumber];
|
||||
|
||||
item.Animation.Velocity.z = Random::GenerateFloat(32.0f, 160.0f);
|
||||
|
||||
item.HitPoints = DEFAULT_FIREFLY_COUNT;
|
||||
item.ItemFlags[FirefliesItemFlags::TargetItemPtr] = item.Index;
|
||||
item.ItemFlags[FirefliesItemFlags::Light] = 1; // 0 = Turn off light effect, 1 = turn on light (DEFAULT).
|
||||
|
||||
item.ItemFlags[FirefliesItemFlags::TriggerFlags] = std::clamp((int)item.TriggerFlags, -MAX_AREA_RANGE, MAX_AREA_RANGE);
|
||||
|
||||
item.ItemFlags[FirefliesItemFlags::Spawncounter] = 0;
|
||||
item.ItemFlags[FirefliesItemFlags::RemoveFliesEffect] = 0;
|
||||
|
||||
// Firefly numbers that has the light.
|
||||
item.ItemFlags[FirefliesItemFlags::LightIndex1] = NO_VALUE;
|
||||
item.ItemFlags[FirefliesItemFlags::LightIndex2] = NO_VALUE;
|
||||
}
|
||||
|
||||
void SpawnFireflySwarm(ItemInfo& item, int triggerFlags)
|
||||
{
|
||||
constexpr auto VEL_MAX = 34.0f;
|
||||
constexpr auto VEL_MIN = 6.0f;
|
||||
|
||||
// Create new firefly.
|
||||
auto& firefly = GetNewEffect(FireflySwarm, MAX_FIREFLIES);
|
||||
|
||||
unsigned char r = 255;
|
||||
unsigned char g = 255;
|
||||
unsigned char b = 255;
|
||||
|
||||
if (triggerFlags >= 0)
|
||||
{
|
||||
float brightnessShift = Random::GenerateFloat(-0.1f, 0.1f);
|
||||
r = std::clamp(item.Model.Color.x / 2.0f + brightnessShift, 0.0f, 1.0f) * UCHAR_MAX;
|
||||
g = std::clamp(item.Model.Color.y / 2.0f + brightnessShift, 0.0f, 1.0f) * UCHAR_MAX;
|
||||
b = std::clamp(item.Model.Color.z / 2.0f + brightnessShift, 0.0f, 1.0f) * UCHAR_MAX;
|
||||
|
||||
firefly.SpriteSeqID = ID_FIREFLY_SPRITES;
|
||||
firefly.SpriteID = 0;
|
||||
firefly.blendMode = BlendMode::Additive;
|
||||
firefly.scalar = 3.0f;
|
||||
firefly.size = 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
firefly.SpriteSeqID = ID_FIREFLY_SPRITES;
|
||||
firefly.SpriteID = 1;
|
||||
firefly.blendMode = BlendMode::Subtractive;
|
||||
firefly.scalar = 1.2f;
|
||||
firefly.size = 1.2f;
|
||||
}
|
||||
|
||||
firefly.r = firefly.rB = r;
|
||||
firefly.g = firefly.gB = g;
|
||||
firefly.b = firefly.bB = b;
|
||||
|
||||
firefly.rotAng = ANGLE(0.0f);
|
||||
|
||||
if (item.TriggerFlags > 8)
|
||||
firefly.rotAng = ANGLE(90.0f);
|
||||
|
||||
firefly.on = true;
|
||||
|
||||
firefly.Position = item.Pose.Position.ToVector3();
|
||||
firefly.RoomNumber = item.RoomNumber;
|
||||
firefly.Orientation = item.Pose.Orientation;
|
||||
firefly.Velocity = Random::GenerateFloat(VEL_MIN, VEL_MAX);
|
||||
firefly.zVel = 0.3f;
|
||||
|
||||
firefly.Life = Random::GenerateInt(1, 400);
|
||||
firefly.TargetItemPtr = &g_Level.Items[item.ItemFlags[FirefliesItemFlags::TargetItemPtr]];
|
||||
|
||||
int& nextFireflyNumber = nextFireflyNumberMap[item.Index];
|
||||
firefly.Number = nextFireflyNumber++;
|
||||
}
|
||||
|
||||
void ControlFireflySwarm(short itemNumber)
|
||||
{
|
||||
auto& item = g_Level.Items[itemNumber];
|
||||
|
||||
if (!TriggerActive(&item))
|
||||
{
|
||||
// Remove all fireflies associated with this item.
|
||||
RemoveFireflies(item);
|
||||
|
||||
// Reset ItemFlags.
|
||||
if (item.HitPoints == NOT_TARGETABLE)
|
||||
item.HitPoints = item.ItemFlags[FirefliesItemFlags::Spawncounter];
|
||||
|
||||
item.ItemFlags[FirefliesItemFlags::Spawncounter] = 0;
|
||||
item.ItemFlags[FirefliesItemFlags::LightIndex1] = NO_VALUE;
|
||||
item.ItemFlags[FirefliesItemFlags::LightIndex2] = NO_VALUE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
constexpr auto ALPHA_PAUSE_DURATION = 2.0f;
|
||||
static float frameCounter = 0.0f;
|
||||
|
||||
// Increment the counter variable in each frame.
|
||||
frameCounter += 1.0f;
|
||||
|
||||
if (item.HitPoints != NOT_TARGETABLE)
|
||||
{
|
||||
int fireflyCount = item.HitPoints - item.ItemFlags[FirefliesItemFlags::Spawncounter];
|
||||
|
||||
if (fireflyCount < 0)
|
||||
{
|
||||
int firefliesToTurnOff = -fireflyCount;
|
||||
for (auto& firefly : FireflySwarm)
|
||||
{
|
||||
if (firefly.TargetItemPtr == &item && firefly.Life > 0.0f)
|
||||
{
|
||||
firefly.Life = 0.0f;
|
||||
firefly.on = false;
|
||||
firefliesToTurnOff--;
|
||||
|
||||
if (firefliesToTurnOff == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fireflyCount > 0)
|
||||
{
|
||||
for (int i = 0; i < fireflyCount; i++)
|
||||
{
|
||||
SpawnFireflySwarm(item, item.TriggerFlags);
|
||||
}
|
||||
}
|
||||
|
||||
item.ItemFlags[FirefliesItemFlags::Spawncounter] = item.HitPoints;
|
||||
item.HitPoints = NOT_TARGETABLE;
|
||||
}
|
||||
|
||||
// Update color values for blinking effect.
|
||||
float alphaFactor;
|
||||
|
||||
for (auto& firefly : FireflySwarm)
|
||||
{
|
||||
auto targetItem = firefly.TargetItemPtr;
|
||||
|
||||
if (targetItem == &item)
|
||||
{
|
||||
// Choose one of the available firefly number that has the light.
|
||||
if (targetItem->ItemFlags[FirefliesItemFlags::LightIndex1] == NO_VALUE && targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] >= 0)
|
||||
{
|
||||
targetItem->ItemFlags[FirefliesItemFlags::LightIndex1] = Random::GenerateInt(0, targetItem->TriggerFlags);
|
||||
}
|
||||
// Two lights max for each cluster.
|
||||
if (targetItem->ItemFlags[FirefliesItemFlags::LightIndex2] == NO_VALUE && targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] >= 0)
|
||||
{
|
||||
targetItem->ItemFlags[FirefliesItemFlags::LightIndex2] = Random::GenerateInt(0, targetItem->TriggerFlags);
|
||||
}
|
||||
|
||||
auto posBase = firefly.Position;
|
||||
auto rotMatrix = firefly.Orientation.ToRotationMatrix();
|
||||
auto pos = posBase + Vector3::Transform(Vector3(0, 0, 30), rotMatrix);
|
||||
auto direction0 = Geometry::RotatePoint(posBase, EulerAngles::Identity);
|
||||
short orient2D = firefly.Orientation.z;
|
||||
|
||||
if (targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] >= 0)
|
||||
{
|
||||
StreamerEffect.Spawn(targetItem->Index, firefly.Number, pos, direction0, orient2D,
|
||||
Vector4(firefly.r / (float)UCHAR_MAX, firefly.g / (float)UCHAR_MAX, firefly.b / (float)UCHAR_MAX, 1.0f),
|
||||
Vector4::Zero,
|
||||
6.3f - (firefly.zVel / 12), ((firefly.Velocity / 8) + firefly.zVel * 3) / (float)UCHAR_MAX, 0.0f, -0.1f, 90.0f, StreamerFeatherMode::None, BlendMode::Additive);
|
||||
}
|
||||
else if (targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] < 0)
|
||||
{
|
||||
StreamerEffect.Spawn(targetItem->Index, firefly.Number, pos, direction0, orient2D,
|
||||
Vector4((firefly.r / 2) / (float)UCHAR_MAX, (firefly.g / 2) / (float)UCHAR_MAX, (firefly.b / 2) / (float)UCHAR_MAX, 0.2f),
|
||||
Vector4((firefly.r / 3) / (float)UCHAR_MAX, (firefly.g / 3) / (float)UCHAR_MAX, (firefly.b / 3) / (float)UCHAR_MAX, 0.2f),
|
||||
0.0f, 0.4f, 0.0f, 0.2f, 0.0f, StreamerFeatherMode::None, BlendMode::Subtractive);
|
||||
}
|
||||
|
||||
if ((targetItem->ItemFlags[FirefliesItemFlags::LightIndex1] == firefly.Number || targetItem->ItemFlags[FirefliesItemFlags::LightIndex2] == firefly.Number) &&
|
||||
targetItem->ItemFlags[FirefliesItemFlags::Light] == 1)
|
||||
{
|
||||
float totalCycleDuration = 2 * (LIGHT_ALPHA_CYCLE_DURATION + ALPHA_PAUSE_DURATION);
|
||||
float alphaTime = fmod(frameCounter, totalCycleDuration);
|
||||
|
||||
if (alphaTime < ALPHA_PAUSE_DURATION)
|
||||
{
|
||||
alphaFactor = 1.0f; // Pause on Alpha 1.
|
||||
}
|
||||
else if (alphaTime < ALPHA_PAUSE_DURATION + LIGHT_ALPHA_CYCLE_DURATION)
|
||||
{
|
||||
alphaFactor = 1.0f - ((alphaTime - ALPHA_PAUSE_DURATION) / LIGHT_ALPHA_CYCLE_DURATION);
|
||||
}
|
||||
else if (alphaTime < 2 * ALPHA_PAUSE_DURATION + LIGHT_ALPHA_CYCLE_DURATION)
|
||||
{
|
||||
alphaFactor = 0.0f; // Pause on Alpha 0.
|
||||
targetItem->ItemFlags[FirefliesItemFlags::LightIndex1] = NO_VALUE;
|
||||
targetItem->ItemFlags[FirefliesItemFlags::LightIndex2] = NO_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
alphaFactor = (alphaTime - 2 * ALPHA_PAUSE_DURATION - LIGHT_ALPHA_CYCLE_DURATION) / LIGHT_ALPHA_CYCLE_DURATION;
|
||||
}
|
||||
|
||||
SpawnDynamicLight(firefly.Position.x, firefly.Position.y, firefly.Position.z, 3,
|
||||
static_cast<unsigned char>(std::clamp(firefly.r * alphaFactor, 0.0f, (float)firefly.r)),
|
||||
static_cast<unsigned char>(std::clamp(firefly.g * alphaFactor, 0.0f, (float)firefly.g)),
|
||||
static_cast<unsigned char>(std::clamp(firefly.b * alphaFactor, 0.0f, (float)firefly.b)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateFireflySwarm()
|
||||
{
|
||||
constexpr auto FLEE_VEL = 1.5f;
|
||||
constexpr auto ALPHA_PAUSE_DURATION = 100.0f;
|
||||
|
||||
static const auto SPHERE = BoundingSphere(Vector3::Zero, BLOCK(1 / 8.0f));
|
||||
|
||||
if (FireflySwarm.empty())
|
||||
return;
|
||||
|
||||
const auto& playerItem = *LaraItem;
|
||||
static float frameCounter = 0.0f;
|
||||
|
||||
// Increment the counter variable in each frame.
|
||||
frameCounter += 1.0f;
|
||||
|
||||
for (auto& firefly : FireflySwarm)
|
||||
{
|
||||
if (firefly.Life <= 0.0f || !firefly.on)
|
||||
continue;
|
||||
|
||||
auto targetItem = firefly.TargetItemPtr;
|
||||
|
||||
if (targetItem->ItemFlags[FirefliesItemFlags::RemoveFliesEffect])
|
||||
{
|
||||
firefly.r = 0;
|
||||
firefly.g = 0;
|
||||
firefly.b = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
firefly.StoreInterpolationData();
|
||||
|
||||
firefly.PositionTarget = Random::GeneratePointInSphere(SPHERE);
|
||||
|
||||
int multiplierX = CLICK(targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] * 2);
|
||||
int multiplierY = CLICK(targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] * 4);
|
||||
int multiplierZ = CLICK(targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] * 2);
|
||||
|
||||
auto spheroidAxis = Vector3(multiplierX, multiplierY, multiplierZ);
|
||||
auto itemPos = Vector3i(targetItem->Pose.Position.x, targetItem->Pose.Position.y - FIREFLY_RISE_UP_FACTOR, targetItem->Pose.Position.z);
|
||||
|
||||
// Calculate desired position based on target object and random offsets.
|
||||
auto desiredPos = itemPos + Random::GeneratePointInSpheroid(firefly.PositionTarget, EulerAngles::Identity, spheroidAxis);
|
||||
auto dir = desiredPos - firefly.Position;
|
||||
|
||||
auto dirs = dir.ToVector3();
|
||||
dirs.Normalize();
|
||||
auto dirNorm = dirs;
|
||||
|
||||
// Define cohesion factor to keep fireflies close together.
|
||||
float distToTarget = dirs.Length();
|
||||
|
||||
float targetVel = (distToTarget * FIREFLY_COHESION_FACTOR) + Random::GenerateFloat(3.0f, 5.0f);
|
||||
firefly.Velocity = std::min(targetVel, targetItem->Animation.Velocity.z - 21.0f);
|
||||
|
||||
// If firefly is too far from target, increase velocity to catch up.
|
||||
if (distToTarget > FIREFLY_TARGET_DISTANCE_MAX)
|
||||
firefly.Velocity += FIREFLY_CATCH_UP_FACTOR;
|
||||
|
||||
// Translate.
|
||||
auto moveDir = firefly.Orientation.ToDirection();
|
||||
moveDir.Normalize();
|
||||
firefly.Position += (moveDir * firefly.Velocity) / 26.0f;
|
||||
firefly.Position += (moveDir * FIREFLY_SPACING_FACTOR) / 26.0f;
|
||||
|
||||
auto orientTo = Geometry::GetOrientToPoint(firefly.Position, desiredPos.ToVector3());
|
||||
firefly.Orientation.Lerp(orientTo, 0.1f);
|
||||
|
||||
// Update color values for blinking effect.
|
||||
float totalCycleDuration = 2 * (LIGHT_ALPHA_CYCLE_DURATION + ALPHA_PAUSE_DURATION);
|
||||
float alphaTime = fmod(frameCounter + firefly.Life, totalCycleDuration);
|
||||
float alphaFactor;
|
||||
|
||||
if (alphaTime < ALPHA_PAUSE_DURATION)
|
||||
{
|
||||
alphaFactor = 1.0f;
|
||||
}
|
||||
else if (alphaTime < ALPHA_PAUSE_DURATION + LIGHT_ALPHA_CYCLE_DURATION)
|
||||
{
|
||||
alphaFactor = 1.0f - ((alphaTime - ALPHA_PAUSE_DURATION) / LIGHT_ALPHA_CYCLE_DURATION);
|
||||
}
|
||||
else if (alphaTime < 2 * ALPHA_PAUSE_DURATION + LIGHT_ALPHA_CYCLE_DURATION)
|
||||
{
|
||||
alphaFactor = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
alphaFactor = (alphaTime - 2 * ALPHA_PAUSE_DURATION - LIGHT_ALPHA_CYCLE_DURATION) / LIGHT_ALPHA_CYCLE_DURATION;
|
||||
}
|
||||
|
||||
firefly.r = static_cast<unsigned char>(firefly.rB * alphaFactor);
|
||||
firefly.g = static_cast<unsigned char>(firefly.gB * alphaFactor);
|
||||
firefly.b = static_cast<unsigned char>(firefly.bB * alphaFactor);
|
||||
|
||||
for (const auto& otherFirefly : FireflySwarm)
|
||||
{
|
||||
if (&firefly == &otherFirefly)
|
||||
continue;
|
||||
|
||||
float distToOtherFirefly = Vector3i::Distance(firefly.Position, otherFirefly.Position);
|
||||
float distToPlayer = Vector3i::Distance(firefly.Position, playerItem.Pose.Position);
|
||||
|
||||
// If player is too close, flee.
|
||||
if (distToPlayer < FIREFLY_FLEE_DISTANCE && playerItem.Animation.ActiveState != 2)
|
||||
{
|
||||
auto separationDir = firefly.Position - playerItem.Pose.Position.ToVector3();
|
||||
separationDir.Normalize();
|
||||
|
||||
// Reduce the Y component of the escape direction.
|
||||
separationDir.y *= Random::GenerateFloat(0.0f, 0.4f);
|
||||
|
||||
// Normalize the direction again to get the length of the vector.
|
||||
separationDir.Normalize();
|
||||
|
||||
firefly.Position += separationDir * FLEE_VEL;
|
||||
|
||||
auto orientTo = Geometry::GetOrientToPoint(firefly.Position, separationDir);
|
||||
firefly.Orientation.Lerp(orientTo, 0.05f);
|
||||
|
||||
firefly.Velocity -= std::min(FLEE_VEL, firefly.TargetItemPtr->Animation.Velocity.z - 1.0f);
|
||||
|
||||
if (Random::TestProbability(1.0f / 700.0f) &&
|
||||
targetItem->ItemFlags[FirefliesItemFlags::Light] == 1 &&
|
||||
targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] >= 0)
|
||||
{
|
||||
if (firefly.zVel == 0.3f)
|
||||
{
|
||||
firefly.zVel = 50.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (firefly.zVel > 50.0f)
|
||||
firefly.zVel = 0.3f;
|
||||
}
|
||||
|
||||
if (distToOtherFirefly < FIREFLY_BASE_SEPARATION_DISTANCE)
|
||||
{
|
||||
auto separationDir = firefly.Position - otherFirefly.Position;
|
||||
separationDir.Normalize();
|
||||
|
||||
firefly.Position += separationDir * (FIREFLY_BASE_SEPARATION_DISTANCE - distToOtherFirefly);
|
||||
}
|
||||
}
|
||||
|
||||
auto pointColl = GetPointCollision(firefly.Position, firefly.RoomNumber);
|
||||
|
||||
// Update firefly room number.
|
||||
if (pointColl.GetRoomNumber() != firefly.RoomNumber &&
|
||||
pointColl.GetRoomNumber() != NO_VALUE)
|
||||
{
|
||||
firefly.RoomNumber = pointColl.GetRoomNumber();
|
||||
}
|
||||
|
||||
if (targetItem->ItemFlags[FirefliesItemFlags::Light] == 1 && targetItem->ItemFlags[FirefliesItemFlags::TriggerFlags] >= 0)
|
||||
{
|
||||
if (Random::TestProbability(1.0f / (700.0f - (float)(targetItem->ItemFlags[FirefliesItemFlags::Spawncounter] * 2))))
|
||||
firefly.zVel = 100.0f;
|
||||
|
||||
if (firefly.zVel > 1.0f)
|
||||
firefly.zVel -= 2.0f;
|
||||
if (firefly.zVel <= 1.0f)
|
||||
firefly.zVel = 0.3f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveFireflies(ItemInfo& item)
|
||||
{
|
||||
FireflySwarm.erase(std::remove_if(FireflySwarm.begin(), FireflySwarm.end(),
|
||||
[&item](FireflyData& firefly)
|
||||
{
|
||||
if (firefly.TargetItemPtr == &item)
|
||||
{
|
||||
firefly.Life = 0.0f;
|
||||
firefly.on = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}), FireflySwarm.end());
|
||||
nextFireflyNumberMap.erase(item.Index);
|
||||
}
|
||||
|
||||
void ClearFireflySwarm()
|
||||
{
|
||||
FireflySwarm.clear();
|
||||
nextFireflyNumberMap.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
76
TombEngine/Objects/Effects/Fireflies.h
Normal file
76
TombEngine/Objects/Effects/Fireflies.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
#pragma once
|
||||
#include "Game/items.h"
|
||||
#include "Math/Math.h"
|
||||
|
||||
using namespace TEN::Math;
|
||||
|
||||
namespace TEN::Effects::Fireflies
|
||||
{
|
||||
enum FirefliesItemFlags
|
||||
{
|
||||
TargetItemPtr,
|
||||
Light,
|
||||
TriggerFlags,
|
||||
Spawncounter,
|
||||
RemoveFliesEffect,
|
||||
LightIndex1,
|
||||
LightIndex2
|
||||
};
|
||||
|
||||
struct FireflyData
|
||||
{
|
||||
int SpriteSeqID = ID_DEFAULT_SPRITES;
|
||||
int SpriteID = SPR_UNDERWATERDUST;
|
||||
BlendMode blendMode;
|
||||
unsigned int scalar;
|
||||
|
||||
Vector3 Position = Vector3::Zero;
|
||||
int RoomNumber = 0;
|
||||
Vector3 PositionTarget = Vector3::Zero;
|
||||
EulerAngles Orientation = EulerAngles::Identity;
|
||||
float Velocity = 0.0f;
|
||||
|
||||
ItemInfo* TargetItemPtr = nullptr;
|
||||
|
||||
float zVel;
|
||||
float Life = 0.0f;
|
||||
int Number = 0;
|
||||
|
||||
unsigned char rB;
|
||||
unsigned char gB;
|
||||
unsigned char bB;
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
|
||||
bool on;
|
||||
float size;
|
||||
short rotAng;
|
||||
|
||||
int PrevX;
|
||||
int PrevY;
|
||||
int PrevZ;
|
||||
byte PrevR;
|
||||
byte PrevG;
|
||||
byte PrevB;
|
||||
|
||||
void StoreInterpolationData()
|
||||
{
|
||||
PrevX = Position.x;
|
||||
PrevY = Position.y;
|
||||
PrevZ = Position.z;
|
||||
PrevR = r;
|
||||
PrevG = g;
|
||||
PrevB = b;
|
||||
}
|
||||
};
|
||||
|
||||
extern std::vector<FireflyData> FireflySwarm;
|
||||
|
||||
void InitializeFireflySwarm(short itemNumber);
|
||||
void ControlFireflySwarm(short itemNumber);
|
||||
void UpdateFireflySwarm();
|
||||
void ClearFireflySwarm();
|
||||
void SpawnFireflySwarm(ItemInfo& item, int triggerFlags);
|
||||
void RemoveFireflies(ItemInfo& item);
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
#include "Game/Lara/lara_helpers.h"
|
||||
#include "Game/Setup.h"
|
||||
#include "Math/Math.h"
|
||||
#include "Objects/Effects/Fireflies.h"
|
||||
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
||||
#include "Sound/sound.h"
|
||||
#include "Specific/level.h"
|
||||
|
@ -25,9 +26,13 @@ using namespace TEN::Collision::Point;
|
|||
using namespace TEN::Effects::Ripple;
|
||||
using namespace TEN::Effects::Splash;
|
||||
using namespace TEN::Math;
|
||||
using namespace TEN::Effects::Fireflies;
|
||||
|
||||
namespace TEN::Entities::TR3
|
||||
{
|
||||
constexpr auto FLY_EFFECT_MAX_WIDTH = -1;
|
||||
constexpr auto FLY_AMOUNT = 16;
|
||||
|
||||
enum CorpseState
|
||||
{
|
||||
CORPSE_STATE_GROUNDED = 0,
|
||||
|
@ -51,19 +56,25 @@ namespace TEN::Entities::TR3
|
|||
|
||||
if (item.TriggerFlags == 1)
|
||||
{
|
||||
item.ItemFlags[1] = (int)CorpseFlag::Hang;
|
||||
item.ItemFlags[7] = (int)CorpseFlag::Hang;
|
||||
item.Animation.AnimNumber = object.animIndex + CORPSE_ANIM_HANG;
|
||||
item.Animation.ActiveState = CORPSE_STATE_HANG;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.ItemFlags[1] = (int)CorpseFlag::Grounded;
|
||||
item.ItemFlags[7] = (int)CorpseFlag::Grounded;
|
||||
item.Animation.AnimNumber = object.animIndex + CORPSE_ANIM_GROUNDED;
|
||||
item.Animation.ActiveState = CORPSE_STATE_GROUNDED;
|
||||
}
|
||||
|
||||
item.ItemFlags[FirefliesItemFlags::RemoveFliesEffect] = 0;
|
||||
|
||||
AddActiveItem(itemNumber);
|
||||
item.Status = ITEM_ACTIVE;
|
||||
|
||||
item.ItemFlags[FirefliesItemFlags::TargetItemPtr] = item.Index;
|
||||
item.ItemFlags[FirefliesItemFlags::TriggerFlags] = -1;
|
||||
item.HitPoints = FLY_AMOUNT;
|
||||
}
|
||||
|
||||
void ControlCorpse(short itemNumber)
|
||||
|
@ -71,9 +82,11 @@ namespace TEN::Entities::TR3
|
|||
auto& item = g_Level.Items[itemNumber];
|
||||
const auto& object = Objects[item.ObjectNumber];
|
||||
|
||||
if (item.ItemFlags[1] == (int)CorpseFlag::Fall)
|
||||
if (item.ItemFlags[7] == (int)CorpseFlag::Fall)
|
||||
{
|
||||
bool isWater = TestEnvironment(RoomEnvFlags::ENV_FLAG_WATER, item.RoomNumber);
|
||||
bool isSwamp = TestEnvironment(RoomEnvFlags::ENV_FLAG_SWAMP, item.RoomNumber);
|
||||
|
||||
float verticalVelCoeff = isWater ? 81.0f : 1.0f;
|
||||
|
||||
auto pointColl = GetPointCollision(item);
|
||||
|
@ -94,31 +107,37 @@ namespace TEN::Entities::TR3
|
|||
ItemNewRoom(itemNumber, pointColl.GetRoomNumber());
|
||||
}
|
||||
|
||||
pointColl = GetPointCollision(item);
|
||||
// Remove fly effect when in water.
|
||||
if (isWater || isSwamp)
|
||||
{
|
||||
item.ItemFlags[FirefliesItemFlags::RemoveFliesEffect] = 1;
|
||||
}
|
||||
|
||||
auto bounds = GameBoundingBox(&item);
|
||||
|
||||
item.Animation.IsAirborne = true;
|
||||
|
||||
if (pointColl.GetFloorHeight() < item.Pose.Position.y)
|
||||
if (pointColl.GetFloorHeight() <= item.Pose.Position.y - bounds.Y2)
|
||||
{
|
||||
if (!isWater)
|
||||
{
|
||||
item.Pose.Position.y = item.Pose.Position.y - item.Animation.Velocity.y;
|
||||
item.Pose.Position.y = pointColl.GetFloorHeight();
|
||||
SoundEffect(SFX_TR4_CROCGOD_LAND, &item.Pose);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
item.Pose.Position.y = item.Pose.Position.y;
|
||||
item.Pose.Position.y = pointColl.GetFloorHeight();
|
||||
}
|
||||
|
||||
item.Animation.IsAirborne = false;
|
||||
item.Animation.Velocity = Vector3::Zero;
|
||||
item.Animation.TargetState = CORPSE_STATE_LAND;
|
||||
item.Animation.AnimNumber = object.animIndex + CORPSE_ANIM_LAND;
|
||||
AlignEntityToSurface(&item, Vector2(object.radius));
|
||||
|
||||
item.ItemFlags[1] = (int)CorpseFlag::Grounded;
|
||||
item.ItemFlags[7] = (int)CorpseFlag::Grounded;
|
||||
return;
|
||||
}
|
||||
else
|
||||
else if (item.Animation.ActiveState == CORPSE_STATE_FALL)
|
||||
{
|
||||
if (isWater)
|
||||
{
|
||||
|
@ -133,17 +152,56 @@ namespace TEN::Entities::TR3
|
|||
|
||||
AnimateItem(&item);
|
||||
|
||||
if (!TriggerActive(&item))
|
||||
return;
|
||||
|
||||
int meshCount = object.nmeshes;
|
||||
for (int i = 0; i < meshCount; i++)
|
||||
if (!TriggerActive(&item) || item.ItemFlags[FirefliesItemFlags::RemoveFliesEffect] == 1)
|
||||
{
|
||||
if (Random::TestProbability(1 / 72.0f))
|
||||
// Remove all fireflies associated with this item.
|
||||
RemoveFireflies(item);
|
||||
|
||||
// Reset ItemFlags.
|
||||
if (item.HitPoints == NOT_TARGETABLE)
|
||||
item.HitPoints = FLY_AMOUNT;
|
||||
|
||||
item.ItemFlags[FirefliesItemFlags::Spawncounter] = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddActiveItem(itemNumber);
|
||||
item.Status = ITEM_ACTIVE;
|
||||
}
|
||||
|
||||
// Spawn fly effect.
|
||||
if (item.HitPoints != NOT_TARGETABLE)
|
||||
{
|
||||
int fireflyCount = item.HitPoints - item.ItemFlags[FirefliesItemFlags::Spawncounter];
|
||||
|
||||
if (fireflyCount < 0)
|
||||
{
|
||||
auto pos = GetJointPosition(&item, i).ToVector3();
|
||||
SpawnCorpseEffect(pos);
|
||||
int firefliesToTurnOff = -fireflyCount;
|
||||
for (auto& firefly : FireflySwarm)
|
||||
{
|
||||
if (firefly.TargetItemPtr == &item && firefly.Life > 0.0f)
|
||||
{
|
||||
firefly.Life = 0.0f;
|
||||
firefly.on = false;
|
||||
firefliesToTurnOff--;
|
||||
|
||||
if (firefliesToTurnOff == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fireflyCount > 0)
|
||||
{
|
||||
for (int i = 0; i < fireflyCount; i++)
|
||||
{
|
||||
SpawnFireflySwarm(item, FLY_EFFECT_MAX_WIDTH);
|
||||
}
|
||||
}
|
||||
|
||||
item.ItemFlags[FirefliesItemFlags::Spawncounter] = item.HitPoints;
|
||||
item.HitPoints = NOT_TARGETABLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,9 +218,9 @@ namespace TEN::Entities::TR3
|
|||
{
|
||||
DoBloodSplat(pos->x, pos->y, pos->z, Random::GenerateInt(4, 8), source.Pose.Orientation.y, pos->RoomNumber);
|
||||
|
||||
if (target.ItemFlags[1] == (int)CorpseFlag::Hang)
|
||||
if (target.ItemFlags[7] == (int)CorpseFlag::Hang)
|
||||
{
|
||||
target.ItemFlags[1] = (int)CorpseFlag::Fall;
|
||||
target.ItemFlags[7] = (int)CorpseFlag::Fall;
|
||||
target.Animation.AnimNumber = object.animIndex + CORPSE_ANIM_FALL;
|
||||
target.Animation.ActiveState = CORPSE_STATE_FALL;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "Objects/TR5/Emitter/tr5_spider_emitter.h"
|
||||
#include "Objects/TR5/Emitter/tr5_smoke_emitter.h"
|
||||
#include "Objects/TR5/Emitter/Waterfall.h"
|
||||
#include "Objects/Effects/Fireflies.h"
|
||||
|
||||
// Objects
|
||||
#include "Objects/TR5/Light/tr5_light.h"
|
||||
|
@ -81,6 +82,7 @@ using namespace TEN::Effects::WaterfallEmitter;
|
|||
using namespace TEN::Entities::Creatures::TR5;
|
||||
using namespace TEN::Entities::Switches;
|
||||
using namespace TEN::Entities::Traps;
|
||||
using namespace TEN::Effects::Fireflies;
|
||||
|
||||
static void StartEntity(ObjectInfo *obj)
|
||||
{
|
||||
|
@ -796,6 +798,14 @@ static void StartObject(ObjectInfo *obj)
|
|||
obj->control = ControlEmberEmitter;
|
||||
}
|
||||
|
||||
obj = &Objects[ID_FIREFLY_EMITTER];
|
||||
if (obj->loaded)
|
||||
{
|
||||
obj->Initialize = InitializeFireflySwarm;
|
||||
obj->control = ControlFireflySwarm;
|
||||
obj->drawRoutine = NULL;
|
||||
}
|
||||
|
||||
obj = &Objects[ID_GEN_SLOT1];
|
||||
if (obj->loaded)
|
||||
{
|
||||
|
|
|
@ -817,6 +817,7 @@ enum GAME_OBJECT_ID : short
|
|||
ID_CORPSE,
|
||||
ID_WRAITH_TRAP,
|
||||
ID_WATERFALL_EMITTER,
|
||||
ID_FIREFLY_EMITTER,
|
||||
|
||||
ID_MESHSWAP1 = 1100,
|
||||
ID_MESHSWAP2,
|
||||
|
@ -1006,8 +1007,8 @@ enum GAME_OBJECT_ID : short
|
|||
ID_DASH_BAR_TEXTURE,
|
||||
ID_SFX_BAR_TEXTURE,
|
||||
ID_WATERFALL_SPRITES,
|
||||
// 1379
|
||||
ID_CROSSHAIR_GRAPHICS = 1380,
|
||||
ID_FIREFLY_SPRITES,
|
||||
ID_CROSSHAIR_GRAPHICS,
|
||||
ID_SPEEDOMETER_GRAPHICS,
|
||||
ID_CUSTOM_BAR_GRAPHICS,
|
||||
ID_CUSTOM_AMMO_GRAPHICS,
|
||||
|
|
|
@ -409,6 +409,7 @@ namespace TEN::Renderer
|
|||
void PrepareFires(RenderView& view);
|
||||
void PrepareParticles(RenderView& view);
|
||||
void PrepareSmokes(RenderView& view);
|
||||
void PrepareFireflies(RenderView& view);
|
||||
void PrepareElectricity(RenderView& view);
|
||||
void PrepareHelicalLasers(RenderView& view);
|
||||
void PrepareBlood(RenderView& view);
|
||||
|
|
|
@ -1759,6 +1759,7 @@ namespace TEN::Renderer
|
|||
PrepareStreamers(view);
|
||||
PrepareLaserBarriers(view);
|
||||
PrepareSingleLaserBeam(view);
|
||||
PrepareFireflies(view);
|
||||
|
||||
// Sprites grouped in buckets for instancing. Non-commutative sprites are collected at a later stage.
|
||||
SortAndPrepareSprites(view);
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
||||
#include "Specific/level.h"
|
||||
#include "Structures/RendererSpriteBucket.h"
|
||||
#include "Objects/Effects/Fireflies.h"
|
||||
|
||||
using namespace TEN::Effects::Blood;
|
||||
using namespace TEN::Effects::Bubble;
|
||||
|
@ -48,6 +49,7 @@ using namespace TEN::Effects::Streamer;
|
|||
using namespace TEN::Entities::Creatures::TR5;
|
||||
using namespace TEN::Entities::Traps;
|
||||
using namespace TEN::Math;
|
||||
using namespace TEN::Effects::Fireflies;
|
||||
|
||||
extern BLOOD_STRUCT Blood[MAX_SPARKS_BLOOD];
|
||||
extern FIRE_SPARKS FireSparks[MAX_SPARKS_FIRE];
|
||||
|
@ -330,6 +332,49 @@ namespace TEN::Renderer
|
|||
}
|
||||
}
|
||||
|
||||
void Renderer::PrepareFireflies(RenderView& view)
|
||||
{
|
||||
if (!Objects[ID_FIREFLY_EMITTER].loaded)
|
||||
return;
|
||||
|
||||
for (auto& firefly : FireflySwarm)
|
||||
{
|
||||
if (!firefly.on)
|
||||
continue;
|
||||
|
||||
|
||||
if (!CheckIfSlotExists(ID_SPARK_SPRITE, "Particle rendering"))
|
||||
continue;
|
||||
|
||||
auto axis = Vector3(0,0,0);
|
||||
axis.Normalize();
|
||||
|
||||
|
||||
firefly.scalar = 3;
|
||||
firefly.size = 3;
|
||||
|
||||
auto pos = Vector3::Lerp(
|
||||
Vector3(firefly.PrevX, firefly.PrevY, firefly.PrevZ),
|
||||
Vector3(firefly.Position.x, firefly.Position.y, firefly.Position.z),
|
||||
GetInterpolationFactor());
|
||||
|
||||
pos = Vector3(firefly.Position.x, firefly.Position.y, firefly.Position.z);
|
||||
|
||||
// Disallow sprites out of bounds.
|
||||
int spriteIndex = Objects[firefly.SpriteSeqID].meshIndex + firefly.SpriteID;
|
||||
spriteIndex = std::clamp(spriteIndex, 0, (int)_sprites.size());
|
||||
|
||||
AddSpriteBillboard(
|
||||
&_sprites[spriteIndex],
|
||||
pos,
|
||||
Color(firefly.r / (float)UCHAR_MAX, firefly.g / (float)UCHAR_MAX, firefly.b / (float)UCHAR_MAX, 1.0f),
|
||||
TO_RAD(firefly.rotAng << 4), firefly.scalar,
|
||||
Vector2(firefly.size, firefly.size),
|
||||
firefly.blendMode, true, view);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::PrepareSmokes(RenderView& view)
|
||||
{
|
||||
for (const auto& smoke : SmokeSparks)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
// This file is generated automatically, do not edit it.
|
||||
// Last generated on 13/03/2025.
|
||||
// Last generated on 17/03/2025.
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
@ -815,6 +815,7 @@ The following constants are inside ObjID.
|
|||
CORPSE
|
||||
WRAITH_TRAP
|
||||
WATERFALL_EMITTER
|
||||
FIREFLY_EMITTER
|
||||
MESHSWAP1
|
||||
MESHSWAP2
|
||||
MESHSWAP3
|
||||
|
@ -995,6 +996,7 @@ The following constants are inside ObjID.
|
|||
DASH_BAR_TEXTURE
|
||||
SFX_BAR_TEXTURE
|
||||
WATERFALL_SPRITES
|
||||
FIREFLY_SPRITES
|
||||
CROSSHAIR_GRAPHICS
|
||||
SPEEDOMETER_GRAPHICS
|
||||
CUSTOM_BAR_GRAPHICS
|
||||
|
@ -1245,6 +1247,7 @@ The following ObjID members refer to sprites.
|
|||
DASH_BAR_TEXTURE
|
||||
SFX_BAR_TEXTURE
|
||||
WATERFALL_SPRITES
|
||||
FIREFLY_SPRITES
|
||||
CROSSHAIR_GRAPHICS
|
||||
SPEEDOMETER_GRAPHICS
|
||||
CUSTOM_BAR_GRAPHICS
|
||||
|
@ -2052,6 +2055,7 @@ static const std::unordered_map<std::string, GAME_OBJECT_ID> GAME_OBJECT_IDS {
|
|||
{ "CORPSE", ID_CORPSE },
|
||||
{ "WRAITH_TRAP", ID_WRAITH_TRAP },
|
||||
{ "WATERFALL_EMITTER", ID_WATERFALL_EMITTER },
|
||||
{ "FIREFLY_EMITTER", ID_FIREFLY_EMITTER },
|
||||
{ "MESHSWAP1", ID_MESHSWAP1 },
|
||||
{ "MESHSWAP2", ID_MESHSWAP2 },
|
||||
{ "MESHSWAP3", ID_MESHSWAP3 },
|
||||
|
@ -2232,6 +2236,7 @@ static const std::unordered_map<std::string, GAME_OBJECT_ID> GAME_OBJECT_IDS {
|
|||
{ "DASH_BAR_TEXTURE", ID_DASH_BAR_TEXTURE },
|
||||
{ "SFX_BAR_TEXTURE", ID_SFX_BAR_TEXTURE },
|
||||
{ "WATERFALL_SPRITES", ID_WATERFALL_SPRITES },
|
||||
{ "FIREFLY_SPRITES", ID_FIREFLY_SPRITES },
|
||||
{ "CROSSHAIR_GRAPHICS", ID_CROSSHAIR_GRAPHICS },
|
||||
{ "SPEEDOMETER_GRAPHICS", ID_SPEEDOMETER_GRAPHICS },
|
||||
{ "CUSTOM_BAR_GRAPHICS", ID_CUSTOM_BAR_GRAPHICS },
|
||||
|
|
|
@ -169,6 +169,10 @@ struct FishData;
|
|||
struct FishDataBuilder;
|
||||
struct FishDataT;
|
||||
|
||||
struct FireflyData;
|
||||
struct FireflyDataBuilder;
|
||||
struct FireflyDataT;
|
||||
|
||||
struct KeyValPair;
|
||||
|
||||
struct ScriptTable;
|
||||
|
@ -6861,6 +6865,295 @@ struct FishData::Traits {
|
|||
|
||||
flatbuffers::Offset<FishData> CreateFishData(flatbuffers::FlatBufferBuilder &_fbb, const FishDataT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
|
||||
struct FireflyDataT : public flatbuffers::NativeTable {
|
||||
typedef FireflyData TableType;
|
||||
int32_t sprite_index = 0;
|
||||
int32_t sprite_id = 0;
|
||||
int32_t blend_mode = 0;
|
||||
int32_t scalar = 0;
|
||||
std::unique_ptr<TEN::Save::Vector3> position{};
|
||||
int32_t room_number = 0;
|
||||
std::unique_ptr<TEN::Save::Vector3> position_target{};
|
||||
std::unique_ptr<TEN::Save::EulerAngles> orientation{};
|
||||
float velocity = 0.0f;
|
||||
int32_t target_item_number = 0;
|
||||
float z_vel = 0.0f;
|
||||
float life = 0.0f;
|
||||
int32_t number = 0;
|
||||
int32_t d_r = 0;
|
||||
int32_t d_g = 0;
|
||||
int32_t d_b = 0;
|
||||
int32_t r = 0;
|
||||
int32_t g = 0;
|
||||
int32_t b = 0;
|
||||
bool on = false;
|
||||
float size = 0.0f;
|
||||
int32_t rot_Ang = 0;
|
||||
};
|
||||
|
||||
struct FireflyData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef FireflyDataT NativeTableType;
|
||||
typedef FireflyDataBuilder Builder;
|
||||
struct Traits;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_SPRITE_INDEX = 4,
|
||||
VT_SPRITE_ID = 6,
|
||||
VT_BLEND_MODE = 8,
|
||||
VT_SCALAR = 10,
|
||||
VT_POSITION = 12,
|
||||
VT_ROOM_NUMBER = 14,
|
||||
VT_POSITION_TARGET = 16,
|
||||
VT_ORIENTATION = 18,
|
||||
VT_VELOCITY = 20,
|
||||
VT_TARGET_ITEM_NUMBER = 22,
|
||||
VT_Z_VEL = 24,
|
||||
VT_LIFE = 26,
|
||||
VT_NUMBER = 28,
|
||||
VT_D_R = 30,
|
||||
VT_D_G = 32,
|
||||
VT_D_B = 34,
|
||||
VT_R = 36,
|
||||
VT_G = 38,
|
||||
VT_B = 40,
|
||||
VT_ON = 42,
|
||||
VT_SIZE = 44,
|
||||
VT_ROT_ANG = 46
|
||||
};
|
||||
int32_t sprite_index() const {
|
||||
return GetField<int32_t>(VT_SPRITE_INDEX, 0);
|
||||
}
|
||||
int32_t sprite_id() const {
|
||||
return GetField<int32_t>(VT_SPRITE_ID, 0);
|
||||
}
|
||||
int32_t blend_mode() const {
|
||||
return GetField<int32_t>(VT_BLEND_MODE, 0);
|
||||
}
|
||||
int32_t scalar() const {
|
||||
return GetField<int32_t>(VT_SCALAR, 0);
|
||||
}
|
||||
const TEN::Save::Vector3 *position() const {
|
||||
return GetStruct<const TEN::Save::Vector3 *>(VT_POSITION);
|
||||
}
|
||||
int32_t room_number() const {
|
||||
return GetField<int32_t>(VT_ROOM_NUMBER, 0);
|
||||
}
|
||||
const TEN::Save::Vector3 *position_target() const {
|
||||
return GetStruct<const TEN::Save::Vector3 *>(VT_POSITION_TARGET);
|
||||
}
|
||||
const TEN::Save::EulerAngles *orientation() const {
|
||||
return GetStruct<const TEN::Save::EulerAngles *>(VT_ORIENTATION);
|
||||
}
|
||||
float velocity() const {
|
||||
return GetField<float>(VT_VELOCITY, 0.0f);
|
||||
}
|
||||
int32_t target_item_number() const {
|
||||
return GetField<int32_t>(VT_TARGET_ITEM_NUMBER, 0);
|
||||
}
|
||||
float z_vel() const {
|
||||
return GetField<float>(VT_Z_VEL, 0.0f);
|
||||
}
|
||||
float life() const {
|
||||
return GetField<float>(VT_LIFE, 0.0f);
|
||||
}
|
||||
int32_t number() const {
|
||||
return GetField<int32_t>(VT_NUMBER, 0);
|
||||
}
|
||||
int32_t d_r() const {
|
||||
return GetField<int32_t>(VT_D_R, 0);
|
||||
}
|
||||
int32_t d_g() const {
|
||||
return GetField<int32_t>(VT_D_G, 0);
|
||||
}
|
||||
int32_t d_b() const {
|
||||
return GetField<int32_t>(VT_D_B, 0);
|
||||
}
|
||||
int32_t r() const {
|
||||
return GetField<int32_t>(VT_R, 0);
|
||||
}
|
||||
int32_t g() const {
|
||||
return GetField<int32_t>(VT_G, 0);
|
||||
}
|
||||
int32_t b() const {
|
||||
return GetField<int32_t>(VT_B, 0);
|
||||
}
|
||||
bool on() const {
|
||||
return GetField<uint8_t>(VT_ON, 0) != 0;
|
||||
}
|
||||
float size() const {
|
||||
return GetField<float>(VT_SIZE, 0.0f);
|
||||
}
|
||||
int32_t rot_Ang() const {
|
||||
return GetField<int32_t>(VT_ROT_ANG, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<int32_t>(verifier, VT_SPRITE_INDEX) &&
|
||||
VerifyField<int32_t>(verifier, VT_SPRITE_ID) &&
|
||||
VerifyField<int32_t>(verifier, VT_BLEND_MODE) &&
|
||||
VerifyField<int32_t>(verifier, VT_SCALAR) &&
|
||||
VerifyField<TEN::Save::Vector3>(verifier, VT_POSITION) &&
|
||||
VerifyField<int32_t>(verifier, VT_ROOM_NUMBER) &&
|
||||
VerifyField<TEN::Save::Vector3>(verifier, VT_POSITION_TARGET) &&
|
||||
VerifyField<TEN::Save::EulerAngles>(verifier, VT_ORIENTATION) &&
|
||||
VerifyField<float>(verifier, VT_VELOCITY) &&
|
||||
VerifyField<int32_t>(verifier, VT_TARGET_ITEM_NUMBER) &&
|
||||
VerifyField<float>(verifier, VT_Z_VEL) &&
|
||||
VerifyField<float>(verifier, VT_LIFE) &&
|
||||
VerifyField<int32_t>(verifier, VT_NUMBER) &&
|
||||
VerifyField<int32_t>(verifier, VT_D_R) &&
|
||||
VerifyField<int32_t>(verifier, VT_D_G) &&
|
||||
VerifyField<int32_t>(verifier, VT_D_B) &&
|
||||
VerifyField<int32_t>(verifier, VT_R) &&
|
||||
VerifyField<int32_t>(verifier, VT_G) &&
|
||||
VerifyField<int32_t>(verifier, VT_B) &&
|
||||
VerifyField<uint8_t>(verifier, VT_ON) &&
|
||||
VerifyField<float>(verifier, VT_SIZE) &&
|
||||
VerifyField<int32_t>(verifier, VT_ROT_ANG) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
FireflyDataT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
void UnPackTo(FireflyDataT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
static flatbuffers::Offset<FireflyData> Pack(flatbuffers::FlatBufferBuilder &_fbb, const FireflyDataT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
};
|
||||
|
||||
struct FireflyDataBuilder {
|
||||
typedef FireflyData Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_sprite_index(int32_t sprite_index) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_SPRITE_INDEX, sprite_index, 0);
|
||||
}
|
||||
void add_sprite_id(int32_t sprite_id) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_SPRITE_ID, sprite_id, 0);
|
||||
}
|
||||
void add_blend_mode(int32_t blend_mode) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_BLEND_MODE, blend_mode, 0);
|
||||
}
|
||||
void add_scalar(int32_t scalar) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_SCALAR, scalar, 0);
|
||||
}
|
||||
void add_position(const TEN::Save::Vector3 *position) {
|
||||
fbb_.AddStruct(FireflyData::VT_POSITION, position);
|
||||
}
|
||||
void add_room_number(int32_t room_number) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_ROOM_NUMBER, room_number, 0);
|
||||
}
|
||||
void add_position_target(const TEN::Save::Vector3 *position_target) {
|
||||
fbb_.AddStruct(FireflyData::VT_POSITION_TARGET, position_target);
|
||||
}
|
||||
void add_orientation(const TEN::Save::EulerAngles *orientation) {
|
||||
fbb_.AddStruct(FireflyData::VT_ORIENTATION, orientation);
|
||||
}
|
||||
void add_velocity(float velocity) {
|
||||
fbb_.AddElement<float>(FireflyData::VT_VELOCITY, velocity, 0.0f);
|
||||
}
|
||||
void add_target_item_number(int32_t target_item_number) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_TARGET_ITEM_NUMBER, target_item_number, 0);
|
||||
}
|
||||
void add_z_vel(float z_vel) {
|
||||
fbb_.AddElement<float>(FireflyData::VT_Z_VEL, z_vel, 0.0f);
|
||||
}
|
||||
void add_life(float life) {
|
||||
fbb_.AddElement<float>(FireflyData::VT_LIFE, life, 0.0f);
|
||||
}
|
||||
void add_number(int32_t number) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_NUMBER, number, 0);
|
||||
}
|
||||
void add_d_r(int32_t d_r) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_D_R, d_r, 0);
|
||||
}
|
||||
void add_d_g(int32_t d_g) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_D_G, d_g, 0);
|
||||
}
|
||||
void add_d_b(int32_t d_b) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_D_B, d_b, 0);
|
||||
}
|
||||
void add_r(int32_t r) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_R, r, 0);
|
||||
}
|
||||
void add_g(int32_t g) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_G, g, 0);
|
||||
}
|
||||
void add_b(int32_t b) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_B, b, 0);
|
||||
}
|
||||
void add_on(bool on) {
|
||||
fbb_.AddElement<uint8_t>(FireflyData::VT_ON, static_cast<uint8_t>(on), 0);
|
||||
}
|
||||
void add_size(float size) {
|
||||
fbb_.AddElement<float>(FireflyData::VT_SIZE, size, 0.0f);
|
||||
}
|
||||
void add_rot_Ang(int32_t rot_Ang) {
|
||||
fbb_.AddElement<int32_t>(FireflyData::VT_ROT_ANG, rot_Ang, 0);
|
||||
}
|
||||
explicit FireflyDataBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
flatbuffers::Offset<FireflyData> Finish() {
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<FireflyData>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<FireflyData> CreateFireflyData(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
int32_t sprite_index = 0,
|
||||
int32_t sprite_id = 0,
|
||||
int32_t blend_mode = 0,
|
||||
int32_t scalar = 0,
|
||||
const TEN::Save::Vector3 *position = 0,
|
||||
int32_t room_number = 0,
|
||||
const TEN::Save::Vector3 *position_target = 0,
|
||||
const TEN::Save::EulerAngles *orientation = 0,
|
||||
float velocity = 0.0f,
|
||||
int32_t target_item_number = 0,
|
||||
float z_vel = 0.0f,
|
||||
float life = 0.0f,
|
||||
int32_t number = 0,
|
||||
int32_t d_r = 0,
|
||||
int32_t d_g = 0,
|
||||
int32_t d_b = 0,
|
||||
int32_t r = 0,
|
||||
int32_t g = 0,
|
||||
int32_t b = 0,
|
||||
bool on = false,
|
||||
float size = 0.0f,
|
||||
int32_t rot_Ang = 0) {
|
||||
FireflyDataBuilder builder_(_fbb);
|
||||
builder_.add_rot_Ang(rot_Ang);
|
||||
builder_.add_size(size);
|
||||
builder_.add_b(b);
|
||||
builder_.add_g(g);
|
||||
builder_.add_r(r);
|
||||
builder_.add_d_b(d_b);
|
||||
builder_.add_d_g(d_g);
|
||||
builder_.add_d_r(d_r);
|
||||
builder_.add_number(number);
|
||||
builder_.add_life(life);
|
||||
builder_.add_z_vel(z_vel);
|
||||
builder_.add_target_item_number(target_item_number);
|
||||
builder_.add_velocity(velocity);
|
||||
builder_.add_orientation(orientation);
|
||||
builder_.add_position_target(position_target);
|
||||
builder_.add_room_number(room_number);
|
||||
builder_.add_position(position);
|
||||
builder_.add_scalar(scalar);
|
||||
builder_.add_blend_mode(blend_mode);
|
||||
builder_.add_sprite_id(sprite_id);
|
||||
builder_.add_sprite_index(sprite_index);
|
||||
builder_.add_on(on);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct FireflyData::Traits {
|
||||
using type = FireflyData;
|
||||
static auto constexpr Create = CreateFireflyData;
|
||||
};
|
||||
|
||||
flatbuffers::Offset<FireflyData> CreateFireflyData(flatbuffers::FlatBufferBuilder &_fbb, const FireflyDataT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
|
||||
struct ScriptTableT : public flatbuffers::NativeTable {
|
||||
typedef ScriptTable TableType;
|
||||
std::vector<TEN::Save::KeyValPair> keys_vals{};
|
||||
|
@ -8000,6 +8293,7 @@ struct SaveGameT : public flatbuffers::NativeTable {
|
|||
int32_t next_item_active = 0;
|
||||
std::vector<int32_t> room_items{};
|
||||
std::vector<std::unique_ptr<TEN::Save::FishDataT>> fish_swarm{};
|
||||
std::vector<std::unique_ptr<TEN::Save::FireflyDataT>> firefly_swarm{};
|
||||
std::vector<std::unique_ptr<TEN::Save::FXInfoT>> fxinfos{};
|
||||
int32_t next_fx_free = 0;
|
||||
int32_t next_fx_active = 0;
|
||||
|
@ -8066,52 +8360,53 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||
VT_NEXT_ITEM_ACTIVE = 24,
|
||||
VT_ROOM_ITEMS = 26,
|
||||
VT_FISH_SWARM = 28,
|
||||
VT_FXINFOS = 30,
|
||||
VT_NEXT_FX_FREE = 32,
|
||||
VT_NEXT_FX_ACTIVE = 34,
|
||||
VT_FIXED_CAMERAS = 36,
|
||||
VT_SINKS = 38,
|
||||
VT_STATIC_MESHES = 40,
|
||||
VT_FLYBY_CAMERAS = 42,
|
||||
VT_PARTICLES = 44,
|
||||
VT_RATS = 46,
|
||||
VT_SPIDERS = 48,
|
||||
VT_SCARABS = 50,
|
||||
VT_BATS = 52,
|
||||
VT_FLIP_MAPS = 54,
|
||||
VT_FLIP_STATS = 56,
|
||||
VT_FLIP_EFFECT = 58,
|
||||
VT_FLIP_TIMER = 60,
|
||||
VT_FLIP_STATUS = 62,
|
||||
VT_CURRENT_FOV = 64,
|
||||
VT_LAST_INV_ITEM = 66,
|
||||
VT_ACTION_QUEUE = 68,
|
||||
VT_SOUNDTRACKS = 70,
|
||||
VT_CD_FLAGS = 72,
|
||||
VT_POSTPROCESS_MODE = 74,
|
||||
VT_POSTPROCESS_STRENGTH = 76,
|
||||
VT_POSTPROCESS_TINT = 78,
|
||||
VT_ROPE = 80,
|
||||
VT_PENDULUM = 82,
|
||||
VT_ALTERNATE_PENDULUM = 84,
|
||||
VT_VOLUMES = 86,
|
||||
VT_GLOBAL_EVENT_SETS = 88,
|
||||
VT_VOLUME_EVENT_SETS = 90,
|
||||
VT_SCRIPT_VARS = 92,
|
||||
VT_CALLBACKS_PRE_START = 94,
|
||||
VT_CALLBACKS_POST_START = 96,
|
||||
VT_CALLBACKS_PRE_END = 98,
|
||||
VT_CALLBACKS_POST_END = 100,
|
||||
VT_CALLBACKS_PRE_SAVE = 102,
|
||||
VT_CALLBACKS_POST_SAVE = 104,
|
||||
VT_CALLBACKS_PRE_LOAD = 106,
|
||||
VT_CALLBACKS_POST_LOAD = 108,
|
||||
VT_CALLBACKS_PRE_LOOP = 110,
|
||||
VT_CALLBACKS_POST_LOOP = 112,
|
||||
VT_CALLBACKS_PRE_USEITEM = 114,
|
||||
VT_CALLBACKS_POST_USEITEM = 116,
|
||||
VT_CALLBACKS_PRE_FREEZE = 118,
|
||||
VT_CALLBACKS_POST_FREEZE = 120
|
||||
VT_FIREFLY_SWARM = 30,
|
||||
VT_FXINFOS = 32,
|
||||
VT_NEXT_FX_FREE = 34,
|
||||
VT_NEXT_FX_ACTIVE = 36,
|
||||
VT_FIXED_CAMERAS = 38,
|
||||
VT_SINKS = 40,
|
||||
VT_STATIC_MESHES = 42,
|
||||
VT_FLYBY_CAMERAS = 44,
|
||||
VT_PARTICLES = 46,
|
||||
VT_RATS = 48,
|
||||
VT_SPIDERS = 50,
|
||||
VT_SCARABS = 52,
|
||||
VT_BATS = 54,
|
||||
VT_FLIP_MAPS = 56,
|
||||
VT_FLIP_STATS = 58,
|
||||
VT_FLIP_EFFECT = 60,
|
||||
VT_FLIP_TIMER = 62,
|
||||
VT_FLIP_STATUS = 64,
|
||||
VT_CURRENT_FOV = 66,
|
||||
VT_LAST_INV_ITEM = 68,
|
||||
VT_ACTION_QUEUE = 70,
|
||||
VT_SOUNDTRACKS = 72,
|
||||
VT_CD_FLAGS = 74,
|
||||
VT_POSTPROCESS_MODE = 76,
|
||||
VT_POSTPROCESS_STRENGTH = 78,
|
||||
VT_POSTPROCESS_TINT = 80,
|
||||
VT_ROPE = 82,
|
||||
VT_PENDULUM = 84,
|
||||
VT_ALTERNATE_PENDULUM = 86,
|
||||
VT_VOLUMES = 88,
|
||||
VT_GLOBAL_EVENT_SETS = 90,
|
||||
VT_VOLUME_EVENT_SETS = 92,
|
||||
VT_SCRIPT_VARS = 94,
|
||||
VT_CALLBACKS_PRE_START = 96,
|
||||
VT_CALLBACKS_POST_START = 98,
|
||||
VT_CALLBACKS_PRE_END = 100,
|
||||
VT_CALLBACKS_POST_END = 102,
|
||||
VT_CALLBACKS_PRE_SAVE = 104,
|
||||
VT_CALLBACKS_POST_SAVE = 106,
|
||||
VT_CALLBACKS_PRE_LOAD = 108,
|
||||
VT_CALLBACKS_POST_LOAD = 110,
|
||||
VT_CALLBACKS_PRE_LOOP = 112,
|
||||
VT_CALLBACKS_POST_LOOP = 114,
|
||||
VT_CALLBACKS_PRE_USEITEM = 116,
|
||||
VT_CALLBACKS_POST_USEITEM = 118,
|
||||
VT_CALLBACKS_PRE_FREEZE = 120,
|
||||
VT_CALLBACKS_POST_FREEZE = 122
|
||||
};
|
||||
const TEN::Save::SaveGameHeader *header() const {
|
||||
return GetPointer<const TEN::Save::SaveGameHeader *>(VT_HEADER);
|
||||
|
@ -8152,6 +8447,9 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||
const flatbuffers::Vector<flatbuffers::Offset<TEN::Save::FishData>> *fish_swarm() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<TEN::Save::FishData>> *>(VT_FISH_SWARM);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<TEN::Save::FireflyData>> *firefly_swarm() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<TEN::Save::FireflyData>> *>(VT_FIREFLY_SWARM);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<TEN::Save::FXInfo>> *fxinfos() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<TEN::Save::FXInfo>> *>(VT_FXINFOS);
|
||||
}
|
||||
|
@ -8318,6 +8616,9 @@ struct SaveGame FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||
VerifyOffset(verifier, VT_FISH_SWARM) &&
|
||||
verifier.VerifyVector(fish_swarm()) &&
|
||||
verifier.VerifyVectorOfTables(fish_swarm()) &&
|
||||
VerifyOffset(verifier, VT_FIREFLY_SWARM) &&
|
||||
verifier.VerifyVector(firefly_swarm()) &&
|
||||
verifier.VerifyVectorOfTables(firefly_swarm()) &&
|
||||
VerifyOffset(verifier, VT_FXINFOS) &&
|
||||
verifier.VerifyVector(fxinfos()) &&
|
||||
verifier.VerifyVectorOfTables(fxinfos()) &&
|
||||
|
@ -8478,6 +8779,9 @@ struct SaveGameBuilder {
|
|||
void add_fish_swarm(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<TEN::Save::FishData>>> fish_swarm) {
|
||||
fbb_.AddOffset(SaveGame::VT_FISH_SWARM, fish_swarm);
|
||||
}
|
||||
void add_firefly_swarm(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<TEN::Save::FireflyData>>> firefly_swarm) {
|
||||
fbb_.AddOffset(SaveGame::VT_FIREFLY_SWARM, firefly_swarm);
|
||||
}
|
||||
void add_fxinfos(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<TEN::Save::FXInfo>>> fxinfos) {
|
||||
fbb_.AddOffset(SaveGame::VT_FXINFOS, fxinfos);
|
||||
}
|
||||
|
@ -8642,6 +8946,7 @@ inline flatbuffers::Offset<SaveGame> CreateSaveGame(
|
|||
int32_t next_item_active = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<int32_t>> room_items = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<TEN::Save::FishData>>> fish_swarm = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<TEN::Save::FireflyData>>> firefly_swarm = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<TEN::Save::FXInfo>>> fxinfos = 0,
|
||||
int32_t next_fx_free = 0,
|
||||
int32_t next_fx_active = 0,
|
||||
|
@ -8734,6 +9039,7 @@ inline flatbuffers::Offset<SaveGame> CreateSaveGame(
|
|||
builder_.add_next_fx_active(next_fx_active);
|
||||
builder_.add_next_fx_free(next_fx_free);
|
||||
builder_.add_fxinfos(fxinfos);
|
||||
builder_.add_firefly_swarm(firefly_swarm);
|
||||
builder_.add_fish_swarm(fish_swarm);
|
||||
builder_.add_room_items(room_items);
|
||||
builder_.add_next_item_active(next_item_active);
|
||||
|
@ -8771,6 +9077,7 @@ inline flatbuffers::Offset<SaveGame> CreateSaveGameDirect(
|
|||
int32_t next_item_active = 0,
|
||||
const std::vector<int32_t> *room_items = nullptr,
|
||||
const std::vector<flatbuffers::Offset<TEN::Save::FishData>> *fish_swarm = nullptr,
|
||||
const std::vector<flatbuffers::Offset<TEN::Save::FireflyData>> *firefly_swarm = nullptr,
|
||||
const std::vector<flatbuffers::Offset<TEN::Save::FXInfo>> *fxinfos = nullptr,
|
||||
int32_t next_fx_free = 0,
|
||||
int32_t next_fx_active = 0,
|
||||
|
@ -8821,6 +9128,7 @@ inline flatbuffers::Offset<SaveGame> CreateSaveGameDirect(
|
|||
auto items__ = items ? _fbb.CreateVector<flatbuffers::Offset<TEN::Save::Item>>(*items) : 0;
|
||||
auto room_items__ = room_items ? _fbb.CreateVector<int32_t>(*room_items) : 0;
|
||||
auto fish_swarm__ = fish_swarm ? _fbb.CreateVector<flatbuffers::Offset<TEN::Save::FishData>>(*fish_swarm) : 0;
|
||||
auto firefly_swarm__ = firefly_swarm ? _fbb.CreateVector<flatbuffers::Offset<TEN::Save::FireflyData>>(*firefly_swarm) : 0;
|
||||
auto fxinfos__ = fxinfos ? _fbb.CreateVector<flatbuffers::Offset<TEN::Save::FXInfo>>(*fxinfos) : 0;
|
||||
auto fixed_cameras__ = fixed_cameras ? _fbb.CreateVector<flatbuffers::Offset<TEN::Save::FixedCamera>>(*fixed_cameras) : 0;
|
||||
auto sinks__ = sinks ? _fbb.CreateVector<flatbuffers::Offset<TEN::Save::Sink>>(*sinks) : 0;
|
||||
|
@ -8868,6 +9176,7 @@ inline flatbuffers::Offset<SaveGame> CreateSaveGameDirect(
|
|||
next_item_active,
|
||||
room_items__,
|
||||
fish_swarm__,
|
||||
firefly_swarm__,
|
||||
fxinfos__,
|
||||
next_fx_free,
|
||||
next_fx_active,
|
||||
|
@ -10889,6 +11198,95 @@ inline flatbuffers::Offset<FishData> CreateFishData(flatbuffers::FlatBufferBuild
|
|||
_velocity);
|
||||
}
|
||||
|
||||
inline FireflyDataT *FireflyData::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
|
||||
auto _o = std::make_unique<FireflyDataT>();
|
||||
UnPackTo(_o.get(), _resolver);
|
||||
return _o.release();
|
||||
}
|
||||
|
||||
inline void FireflyData::UnPackTo(FireflyDataT *_o, const flatbuffers::resolver_function_t *_resolver) const {
|
||||
(void)_o;
|
||||
(void)_resolver;
|
||||
{ auto _e = sprite_index(); _o->sprite_index = _e; }
|
||||
{ auto _e = sprite_id(); _o->sprite_id = _e; }
|
||||
{ auto _e = blend_mode(); _o->blend_mode = _e; }
|
||||
{ auto _e = scalar(); _o->scalar = _e; }
|
||||
{ auto _e = position(); if (_e) _o->position = std::unique_ptr<TEN::Save::Vector3>(new TEN::Save::Vector3(*_e)); }
|
||||
{ auto _e = room_number(); _o->room_number = _e; }
|
||||
{ auto _e = position_target(); if (_e) _o->position_target = std::unique_ptr<TEN::Save::Vector3>(new TEN::Save::Vector3(*_e)); }
|
||||
{ auto _e = orientation(); if (_e) _o->orientation = std::unique_ptr<TEN::Save::EulerAngles>(new TEN::Save::EulerAngles(*_e)); }
|
||||
{ auto _e = velocity(); _o->velocity = _e; }
|
||||
{ auto _e = target_item_number(); _o->target_item_number = _e; }
|
||||
{ auto _e = z_vel(); _o->z_vel = _e; }
|
||||
{ auto _e = life(); _o->life = _e; }
|
||||
{ auto _e = number(); _o->number = _e; }
|
||||
{ auto _e = d_r(); _o->d_r = _e; }
|
||||
{ auto _e = d_g(); _o->d_g = _e; }
|
||||
{ auto _e = d_b(); _o->d_b = _e; }
|
||||
{ auto _e = r(); _o->r = _e; }
|
||||
{ auto _e = g(); _o->g = _e; }
|
||||
{ auto _e = b(); _o->b = _e; }
|
||||
{ auto _e = on(); _o->on = _e; }
|
||||
{ auto _e = size(); _o->size = _e; }
|
||||
{ auto _e = rot_Ang(); _o->rot_Ang = _e; }
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<FireflyData> FireflyData::Pack(flatbuffers::FlatBufferBuilder &_fbb, const FireflyDataT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
|
||||
return CreateFireflyData(_fbb, _o, _rehasher);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<FireflyData> CreateFireflyData(flatbuffers::FlatBufferBuilder &_fbb, const FireflyDataT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
|
||||
(void)_rehasher;
|
||||
(void)_o;
|
||||
struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const FireflyDataT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
|
||||
auto _sprite_index = _o->sprite_index;
|
||||
auto _sprite_id = _o->sprite_id;
|
||||
auto _blend_mode = _o->blend_mode;
|
||||
auto _scalar = _o->scalar;
|
||||
auto _position = _o->position ? _o->position.get() : 0;
|
||||
auto _room_number = _o->room_number;
|
||||
auto _position_target = _o->position_target ? _o->position_target.get() : 0;
|
||||
auto _orientation = _o->orientation ? _o->orientation.get() : 0;
|
||||
auto _velocity = _o->velocity;
|
||||
auto _target_item_number = _o->target_item_number;
|
||||
auto _z_vel = _o->z_vel;
|
||||
auto _life = _o->life;
|
||||
auto _number = _o->number;
|
||||
auto _d_r = _o->d_r;
|
||||
auto _d_g = _o->d_g;
|
||||
auto _d_b = _o->d_b;
|
||||
auto _r = _o->r;
|
||||
auto _g = _o->g;
|
||||
auto _b = _o->b;
|
||||
auto _on = _o->on;
|
||||
auto _size = _o->size;
|
||||
auto _rot_Ang = _o->rot_Ang;
|
||||
return TEN::Save::CreateFireflyData(
|
||||
_fbb,
|
||||
_sprite_index,
|
||||
_sprite_id,
|
||||
_blend_mode,
|
||||
_scalar,
|
||||
_position,
|
||||
_room_number,
|
||||
_position_target,
|
||||
_orientation,
|
||||
_velocity,
|
||||
_target_item_number,
|
||||
_z_vel,
|
||||
_life,
|
||||
_number,
|
||||
_d_r,
|
||||
_d_g,
|
||||
_d_b,
|
||||
_r,
|
||||
_g,
|
||||
_b,
|
||||
_on,
|
||||
_size,
|
||||
_rot_Ang);
|
||||
}
|
||||
|
||||
inline ScriptTableT *ScriptTable::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
|
||||
auto _o = std::make_unique<ScriptTableT>();
|
||||
UnPackTo(_o.get(), _resolver);
|
||||
|
@ -11323,6 +11721,7 @@ inline void SaveGame::UnPackTo(SaveGameT *_o, const flatbuffers::resolver_functi
|
|||
{ auto _e = next_item_active(); _o->next_item_active = _e; }
|
||||
{ auto _e = room_items(); if (_e) { _o->room_items.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->room_items[_i] = _e->Get(_i); } } }
|
||||
{ auto _e = fish_swarm(); if (_e) { _o->fish_swarm.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->fish_swarm[_i] = std::unique_ptr<TEN::Save::FishDataT>(_e->Get(_i)->UnPack(_resolver)); } } }
|
||||
{ auto _e = firefly_swarm(); if (_e) { _o->firefly_swarm.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->firefly_swarm[_i] = std::unique_ptr<TEN::Save::FireflyDataT>(_e->Get(_i)->UnPack(_resolver)); } } }
|
||||
{ auto _e = fxinfos(); if (_e) { _o->fxinfos.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->fxinfos[_i] = std::unique_ptr<TEN::Save::FXInfoT>(_e->Get(_i)->UnPack(_resolver)); } } }
|
||||
{ auto _e = next_fx_free(); _o->next_fx_free = _e; }
|
||||
{ auto _e = next_fx_active(); _o->next_fx_active = _e; }
|
||||
|
@ -11392,6 +11791,7 @@ inline flatbuffers::Offset<SaveGame> CreateSaveGame(flatbuffers::FlatBufferBuild
|
|||
auto _next_item_active = _o->next_item_active;
|
||||
auto _room_items = _fbb.CreateVector(_o->room_items);
|
||||
auto _fish_swarm = _fbb.CreateVector<flatbuffers::Offset<TEN::Save::FishData>> (_o->fish_swarm.size(), [](size_t i, _VectorArgs *__va) { return CreateFishData(*__va->__fbb, __va->__o->fish_swarm[i].get(), __va->__rehasher); }, &_va );
|
||||
auto _firefly_swarm = _fbb.CreateVector<flatbuffers::Offset<TEN::Save::FireflyData>> (_o->firefly_swarm.size(), [](size_t i, _VectorArgs *__va) { return CreateFireflyData(*__va->__fbb, __va->__o->firefly_swarm[i].get(), __va->__rehasher); }, &_va );
|
||||
auto _fxinfos = _fbb.CreateVector<flatbuffers::Offset<TEN::Save::FXInfo>> (_o->fxinfos.size(), [](size_t i, _VectorArgs *__va) { return CreateFXInfo(*__va->__fbb, __va->__o->fxinfos[i].get(), __va->__rehasher); }, &_va );
|
||||
auto _next_fx_free = _o->next_fx_free;
|
||||
auto _next_fx_active = _o->next_fx_active;
|
||||
|
@ -11453,6 +11853,7 @@ inline flatbuffers::Offset<SaveGame> CreateSaveGame(flatbuffers::FlatBufferBuild
|
|||
_next_item_active,
|
||||
_room_items,
|
||||
_fish_swarm,
|
||||
_firefly_swarm,
|
||||
_fxinfos,
|
||||
_next_fx_free,
|
||||
_next_fx_active,
|
||||
|
|
|
@ -499,6 +499,31 @@ table FishData {
|
|||
velocity: float;
|
||||
}
|
||||
|
||||
table FireflyData {
|
||||
sprite_index: int32;
|
||||
sprite_id: int32;
|
||||
blend_mode: int32;
|
||||
scalar: int32;
|
||||
position: Vector3;
|
||||
room_number: int32;
|
||||
position_target: Vector3;
|
||||
orientation: EulerAngles;
|
||||
velocity: float;
|
||||
target_item_number: int32;
|
||||
z_vel: float;
|
||||
life: float;
|
||||
number: int32;
|
||||
d_r: int32;
|
||||
d_g: int32;
|
||||
d_b: int32;
|
||||
r: int32;
|
||||
g: int32;
|
||||
b: int32;
|
||||
on: bool;
|
||||
size: float;
|
||||
rot_Ang: int32;
|
||||
}
|
||||
|
||||
struct KeyValPair {
|
||||
key: uint32;
|
||||
val: uint32;
|
||||
|
@ -602,6 +627,7 @@ table SaveGame {
|
|||
next_item_active: int32;
|
||||
room_items: [int32];
|
||||
fish_swarm: [FishData];
|
||||
firefly_swarm: [FireflyData];
|
||||
fxinfos: [FXInfo];
|
||||
next_fx_free: int32;
|
||||
next_fx_active: int32;
|
||||
|
|
|
@ -506,6 +506,7 @@ if not exist "%ScriptsDir%\Strings.lua" xcopy /Y "$(SolutionDir)Scripts\Strings.
|
|||
<ClInclude Include="Objects\Effects\effect_objects.h" />
|
||||
<ClInclude Include="Objects\Effects\EmberEmitter.h" />
|
||||
<ClInclude Include="Objects\Effects\enemy_missile.h" />
|
||||
<ClInclude Include="Objects\Effects\Fireflies.h" />
|
||||
<ClInclude Include="Objects\Effects\flame_emitters.h" />
|
||||
<ClInclude Include="Objects\Effects\LensFlare.h" />
|
||||
<ClInclude Include="Objects\Effects\tr4_locusts.h" />
|
||||
|
@ -1044,6 +1045,7 @@ if not exist "%ScriptsDir%\Strings.lua" xcopy /Y "$(SolutionDir)Scripts\Strings.
|
|||
<ClCompile Include="Objects\Effects\effect_objects.cpp" />
|
||||
<ClCompile Include="Objects\Effects\EmberEmitter.cpp" />
|
||||
<ClCompile Include="Objects\Effects\enemy_missile.cpp" />
|
||||
<ClCompile Include="Objects\Effects\Fireflies.cpp" />
|
||||
<ClCompile Include="Objects\Effects\flame_emitters.cpp" />
|
||||
<ClCompile Include="Objects\Effects\LensFlare.cpp" />
|
||||
<ClCompile Include="Objects\Effects\tr4_locusts.cpp" />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue