feat: read and keep a scene file's sounds and particles as the client does

Files from before chunks now read their sounds and particles after the
objects, and chunked files their particle chunk:
- sounds (SceneLoader::LoadSounds, version 5 on, only before chunks):
  position and config (before 35 a 260 character name, kept as
  soundName);
- particles (SceneLoader::LoadParticles, version 5 on): priority (43
  on), position, rotation, effect names and config (46 on; before, an
  unused u16); the client stops at one with no effect, and before 44 a
  file may end before them.

Every scene file of every client on disk reads each part to the next
part's start (up to the client's 16 byte padding): 5408 referenced by
zone files and 5125 on disk, versions 31-43 before chunks and 44-49
chunked. One client file, a LUP world, ends before its sounds; its
objects are kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-10-27 10:34:46 -05:00
committed by GitHub
parent e3370d7042
commit 066571ea28
3 changed files with 101 additions and 2 deletions

View File

@@ -50,6 +50,23 @@ struct LevelSkydome {
std::array<std::string, 5> extraFilenames;
};
// A sound placed in the scene (SceneLoader::LoadSounds, version 5 on). Only the level editor makes anything of them
struct LevelSound {
NiPoint3 position;
LwoNameValue config; // before version 35 only a 260 character soundName
};
// A particle effect placed in the scene (SceneLoader::LoadParticles, version 5 on)
struct LevelParticle {
int16_t priority{}; // version 43 on
NiPoint3 position;
NiQuaternion rotation = QuatUtils::IDENTITY;
std::string effectNames; // separated by ';'
uint16_t unknown{}; // before version 46
// Version 46 on. The client keeps the last one it read for a particle without one
std::string config;
};
// A scene file (.lvl), read as the client reads it (SceneLoader::LoadLvlFile)
class Level {
public:
@@ -108,6 +125,8 @@ public:
const LevelSkydome& GetSkydome() const { return m_Skydome; }
const std::vector<NiColor>& GetEditorColors() const { return m_EditorColors; }
const std::vector<SceneObject>& GetObjects() const { return m_Objects; }
const std::vector<LevelSound>& GetSounds() const { return m_Sounds; }
const std::vector<LevelParticle>& GetParticles() const { return m_Particles; }
std::map<uint32_t, Header> m_ChunkHeaders;
private:
@@ -125,6 +144,8 @@ private:
// Version 37 on: the editor's saved colours (the client keeps at most 32)
std::vector<NiColor> m_EditorColors;
std::vector<SceneObject> m_Objects;
std::vector<LevelSound> m_Sounds;
std::vector<LevelParticle> m_Particles;
//private functions:
void ReadChunks(std::istream& file);
@@ -134,5 +155,7 @@ private:
void ReadSkydomeInfo(std::istream& file);
void ReadEditorSettings(std::istream& file);
void ReadSceneObjectDataChunk(std::istream& file);
void ReadSounds(std::istream& file);
void ReadParticles(std::istream& file);
void LoadSceneObjects();
};