UNPKG

arx-convert

Version:

Converts various Arx Fatalis formats to JSON or YAML and back

156 lines 6.74 kB
import { BinaryIO } from '../common/BinaryIO.js'; import { Color } from '../common/Color.js'; import { clamp, repeat } from '../common/helpers.js'; /** * @see https://github.com/arx/ArxLibertatis/blob/1.2.1/src/scene/Light.h#L80 */ export var ArxLightFlags; (function (ArxLightFlags) { ArxLightFlags[ArxLightFlags["None"] = 0] = "None"; /** * Makes the light source dynamic in a way that when combined with other flags it can * be manipulated real-time in-game. For example it can be made extinguishable. * * A non-dynamic light is one that has their effect hardcoded into the polygon's vertex * data as vertex lighting. */ ArxLightFlags[ArxLightFlags["SemiDynamic"] = 1] = "SemiDynamic"; /** * Makes the light source extinguishable with the douse spell (and probably to the arrows too). * Also makes it ignitable with the ignite spell. * * Only works if `SemiDynamic` is also set. * * @see https://www.youtube.com/watch?v=x8CGx19No4k on how to douse a light source with an arrow */ ArxLightFlags[ArxLightFlags["Extinguishable"] = 2] = "Extinguishable"; /** * When `SemiDynamic` is set it makes the light source start turned off. * If `Extinguishable` is also set then it can be ignited. */ ArxLightFlags[ArxLightFlags["StartExtinguished"] = 4] = "StartExtinguished"; /** * On its own it only makes the light source emit fire cracking sounds. * When `SemiDynamic` is also set it creates a flare/halo around the light source. * * The flare's/halo's properties can be controlled by the properties of `ArxLight.ex*` properties * * Fire only shows if `ArxLight.exFrequency` is > 0 */ ArxLightFlags[ArxLightFlags["SpawnFire"] = 8] = "SpawnFire"; /** * Similarly to `SpawnFire` this also makes fire cracking sounds on its own. * When `SemiDynamic` is set and `ArxLight.exFrequency` is > 0 then it periodically emits * smoke particles. */ ArxLightFlags[ArxLightFlags["SpawnSmoke"] = 16] = "SpawnSmoke"; /** * Unused * * Not used by any of the lights on the existing arx levels, nor is it used in Danae, AF or AL. */ ArxLightFlags[ArxLightFlags["Off"] = 32] = "Off"; /** * If set then the fire/smoke particles will take on the color from `ArxLight.color`, otherwise * they are white. * If `SpawnFire` is set, then the flames will take on the colors, but the smoke particles will * remain white. */ ArxLightFlags[ArxLightFlags["ColorLegacy"] = 64] = "ColorLegacy"; /** * Only used by DANAE. Arx Fatalis 1.21 and Arx Libertatis ignores it. * * It supposed to have been used to control whether a shadow casting should be taken into consideration * when calculating vertex lighting. * * @see https://github.com/arx/ArxLibertatis/blob/ArxFatalis-1.21/Sources/EERIE/EERIELight.cpp#L504 */ ArxLightFlags[ArxLightFlags["NoCasted"] = 128] = "NoCasted"; /** * Normally the flare will keep its size relative to the game's window. * This flag allows to break from that and have the flare size be tied to the world. */ ArxLightFlags[ArxLightFlags["FixFlareSize"] = 256] = "FixFlareSize"; /** * When the halo/flare size is automatically set then this flag makes it slightly larger. * * Unless `Flare` is explicitly set the halo's size is 80, but if `Fireplace` is also set, * then it becomes 95. * * @see https://github.com/arx/ArxLibertatis/blob/ArxFatalis-1.21/Sources/DANAE/DanaeSaveLoad.cpp#L1618 */ ArxLightFlags[ArxLightFlags["Fireplace"] = 512] = "Fireplace"; /** * Works together with `Extinguishable`. * Blocks reacting to the ignite spell cast by the player, the spellcast script command can * ignite it though. * * This doesn't block the light source from reacting to the douse spell. */ ArxLightFlags[ArxLightFlags["NoIgnit"] = 1024] = "NoIgnit"; /** * This makes that a light source has a halo around it. If `SpawnFire` is set, then this * flag automatically/implicitly gets set as you can't have fire without a flare. * * When this flag is explicitly set the size of the halo can be changed with `ArxLight.exFlareSize`. * Otherwise the halo's size is 80, but if `Fireplace` flag is set, then it's 95. * * @see https://github.com/arx/ArxLibertatis/blob/ArxFatalis-1.21/Sources/DANAE/DanaeSaveLoad.cpp#L1618 */ ArxLightFlags[ArxLightFlags["Flare"] = 2048] = "Flare"; })(ArxLightFlags || (ArxLightFlags = {})); export class Light { static readFrom(binary) { const dataBlock1 = { position: binary.readVector3(), color: Color.readFrom(binary, 'rgb'), fallStart: binary.readFloat32(), fallEnd: binary.readFloat32(), intensity: binary.readFloat32(), }; binary.readFloat32(); // i - always 0 const dataBlock2 = { exFlicker: Color.readFrom(binary, 'rgb'), exRadius: binary.readFloat32(), exFrequency: binary.readFloat32(), exSize: binary.readFloat32(), exSpeed: binary.readFloat32(), exFlareSize: binary.readFloat32(), }; binary.readFloat32Array(24); // fpad - ? const flags = binary.readInt32(); binary.readInt32Array(31); // lpad - ? return { ...dataBlock1, ...dataBlock2, flags, }; } static accumulateFrom(light) { const buffer = new ArrayBuffer(Light.sizeOf()); const binary = new BinaryIO(buffer); binary.writeVector3(light.position); binary.writeBuffer(Color.accumulateFrom(light.color, 'rgb')); binary.writeFloat32(light.fallStart); binary.writeFloat32(light.fallEnd); binary.writeFloat32(light.intensity); binary.writeFloat32(0); // i binary.writeBuffer(Color.accumulateFrom(light.exFlicker, 'rgb')); binary.writeFloat32(light.exRadius); binary.writeFloat32(light.exFrequency); binary.writeFloat32(light.exSize); binary.writeFloat32(clamp(light.exSpeed, 0, Number.MAX_SAFE_INTEGER)); binary.writeFloat32(light.exFlareSize); binary.writeFloat32Array(repeat(0, 24)); // fpad binary.writeInt32(light.flags); binary.writeInt32Array(repeat(0, 31)); // lpad return buffer; } static sizeOf() { return (BinaryIO.sizeOfVector3() + Color.sizeOf('rgb') * 2 + BinaryIO.sizeOfFloat32Array(9 + 24) + BinaryIO.sizeOfInt32Array(32)); } } //# sourceMappingURL=Light.js.map