Skip to content

Commit

Permalink
Merge pull request #54 from EvenTorset/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
EvenTorset authored Aug 28, 2024
2 parents f3cf456 + 8163eba commit 5c28cc8
Show file tree
Hide file tree
Showing 39 changed files with 7,800 additions and 7,184 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Changelog

## [15.0.0] - 2024-08-28

### Highlights
- Added `Game.Heuristic`, which can be used with `FXR.read` to let the library figure out what game an FXR file is for.
- This is now the default `game` value for the `FXR.read` function. (*Was `Game.EldenRing` previously.*)
- `FXR` objects now have a new `gameHint` property that stores what game the file was parsed as. It defaults to `Game.Generic`, and the only way to set it is using the `FXR.read` function. New effects created with `new FXR` or `FXR.fromJSON` will have the default value. The hint will be `Game.Heuristic` if the `FXR.read` function could not determine what game it was from.
- The `FXR.toArrayBuffer` and `FXR.saveAs` methods now use `Game.Heuristic` as the default game value too (*was also `Game.EldenRing` previously*), which will cause them to use the `gameHint` as the game, unless the hint is `Game.Heuristic`. If the hint is `Game.Heuristic`, they will look for some AC6-specific things, like action 800, and will use that as the game if anything is found. Otherwise, it will throw an error. I highly recommend still giving these methods a specific game, so the library doesn't need to guess.
- `FXR.read` can detect any DS3 or Sekiro effects perfectly, as long as they're not modified in ways that would make the effect invalid for the game.
- It has a pretty high chance of getting it right for ER and AC6, but it is not perfect, because there are a lot of ways to make AC6 effects that would be the same in ER. It will still read the effect correctly, as it doesn't matter if it's for ER or AC6 if they're both the same, but it affects the `gameHint` property, which can then affect `FXR.toArrayBuffer` and `FXR.saveAs`.
- Added a `Recolor.weightedAveragePalette` function, which takes a color palette with weights for each entry and returns a new palette that has the weighted average of all entries for each slot.
- Added a `randomSeed` function for generating random seeds to be used with randomization modifiers. The modifier classes already generated random seeds as default values, but this allows you to easily generate seeds that can be used in multiple properties, synchronizing their randomization.
- Added a `RandomFractionProperty` function. This was the only missing function to generate properties with randomization modifiers. The other two modifiers have had functions like this one for a while now.
- Added a `getValueType` function that returns the `ValueType` of a given value. This works with numbers, vector arrays, and properties. It's probably not super useful for most people, it's just a utility function used internally that I figured might as well be exported.
- All action fields/properties have been sorted in a way to make their order closer to their order in the actual files. It's not going to match exactly, because the actions in the library have all fields and properties from all four of the supported games, and some of the games have things moved around a bit. This order doesn't really affect much in the library or the documentation, but it causes the JSON structure to have the fields/properties in the new order, so it should hopefully make it easier to find and edit unknowns in the JSON.
- Named and documented the `bloom` field (previously `unk_ds3_f2_4`) in actions 600, 601, 602, 603, 604, 606, and 10012. This is simply a boolean field that toggles the extra bloom effect. (*Requires "Effects Quality" to be set to anything but "Low", and the `bloomColor` vector field to have a non-zero alpha.*)
- The behavior of the `unk_ds3_p2_0` property in `PointLight`s has been documented. The property is still unnamed.
- The `hex` template tag now also accepts strings starting with `#`, like `#ff0000`.
- Fixed the return type of the `hex` template tag. It was previously `number[]`, and is now `Vector4` like it should be.
- `BasicEffect` and `NodeEmitterEffect` can now be constructed without any arguments to make a default effect.

## [14.1.0] - 2024-08-14

### Highlights
Expand Down Expand Up @@ -151,6 +171,7 @@
- External values 2000 and 70200 for AC6 have been documented thanks to lugia19.
- Fixed action 301 (EqualDistanceEmitter) missing a type for one of its fields, potentially causing issues when writing to DS3's structure.

[15.0.0]: https://github.com/EvenTorset/fxr/compare/v14.1.0...v15.0.0
[14.1.0]: https://github.com/EvenTorset/fxr/compare/v14.0.1...v14.1.0
[14.0.1]: https://github.com/EvenTorset/fxr/compare/v14.0.0...v14.0.1
[14.0.0]: https://github.com/EvenTorset/fxr/compare/v13.0.0...v14.0.0
Expand Down
79 changes: 79 additions & 0 deletions build/sort_props.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'

import yaml from 'yaml'

const projectDir = path.dirname(path.dirname(fileURLToPath(import.meta.url)))
const srcDir = path.join(projectDir, 'src')
const actionsDir = path.join(srcDir, 'actions')

function getLineIndex(str, index) {
if (index < 0 || index > str.length) return -1
let lineNumber = 1
let lineIndex = 0
for (let i = 0; i < index; i++) {
if (str[i] === '\n') {
lineNumber++
lineIndex = i + 1
}
}
return lineIndex
}

const gamesSort = {
DS3: 4e5,
SDT: 3e5,
ER: 2e5,
AC6: 1e5,
}

for (const fn of fs.readdirSync(actionsDir)) {
const filePath = path.join(actionsDir, fn)
const yamlString = await fs.promises.readFile(filePath, 'utf-8')
const doc = yaml.parseDocument(yamlString)
if (!doc.get('properties')) continue;

const props = doc.get('properties').items.map(item => ({
key: item.key.value,
start: getLineIndex(yamlString, item.key.range[0]),
end: getLineIndex(yamlString, item.value.range[2]),
}))

const propsStart = props[0].start
const propsEnd = props.at(-1).end

const propIndices = {}
const games = doc.get('games').toJSON()
for (const { key } of props) {
let min = Infinity
for (const [n, game] of Object.entries(games)) {
if (typeof game !== 'object') continue;
if ('properties1' in game && Array.isArray(game.properties1) && game.properties1.includes(key)) {
min = Math.min(min, gamesSort[n] + 0e6 + game.properties1.indexOf(key))
}
if ('properties2' in game && Array.isArray(game.properties2) && game.properties2.includes(key)) {
min = Math.min(min, gamesSort[n] + 1e6 + game.properties2.indexOf(key))
}
if ('fields1' in game && Array.isArray(game.fields1) && game.fields1.includes(key)) {
min = Math.min(min, gamesSort[n] + 2e6 + game.fields1.indexOf(key))
}
if ('fields2' in game && Array.isArray(game.fields2) && game.fields2.includes(key)) {
min = Math.min(min, gamesSort[n] + 3e6 + game.fields2.indexOf(key))
}
if ('section10s' in game && Array.isArray(game.section10s) && game.section10s.includes(key)) {
min = Math.min(min, gamesSort[n] + 4e6 + game.section10s.indexOf(key))
}
}
propIndices[key] = min
}

props.sort((a, b) => propIndices[a.key] - propIndices[b.key])

const outputString =
yamlString.slice(0, propsStart) +
props.map(p => yamlString.slice(p.start, p.end)).join('') +
yamlString.slice(propsEnd)

await fs.promises.writeFile(filePath, outputString)
}
24 changes: 12 additions & 12 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cccode/fxr",
"version": "14.1.0",
"version": "15.0.0",
"description": "JavaScript library for creating and editing FXR files for Dark Souls 3, Sekiro, Elden Ring, and Armored Core 6.",
"author": "CCCode",
"type": "module",
Expand All @@ -13,6 +13,7 @@
"types": "./dist/esm/fxr.d.ts",
"scripts": {
"build:yaml": "node build/run.js",
"build:sort-props": "node build/sort_props.js",
"build:ts:esm": "npx tsc --p tsconfig-esm.json",
"build:ts:cjs": "npx tsc --p tsconfig-cjs.json && echo {\"type\":\"commonjs\"} > dist/cjs/package.json",
"build:ts": "npm-run-all --parallel build:ts:*",
Expand Down
Loading

0 comments on commit 5c28cc8

Please sign in to comment.