arx-convert
Version:
Converts various Arx Fatalis formats to JSON or YAML and back
156 lines • 6.73 kB
JavaScript
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 = {
pos: 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.pos);
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(0, Number.MAX_SAFE_INTEGER, light.exSpeed));
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