Skip to content

Instantly share code, notes, and snippets.

@mrowrpurr
Last active November 19, 2021 06:26
Show Gist options
  • Save mrowrpurr/2721d470ccc052a753d1bff53de8aaa6 to your computer and use it in GitHub Desktop.
Save mrowrpurr/2721d470ccc052a753d1bff53de8aaa6 to your computer and use it in GitHub Desktop.
Get mod name and relative ID for Skyrim mod (using Skyrim Platform)
import { printConsole, Game } from "skyrimPlatform"
import { getFormInfo } from "./FormInfo"
export default function StartRuntime() {
// ESPFE
const justDesserts = Game.getFormFromFile(0x801, "JustDesserts.esp")
const justDessertsInfo = getFormInfo(justDesserts!)
printConsole(JSON.stringify(justDessertsInfo))
// Prints out: {"modName":"JustDesserts.esp","relativeFormId":2049}
// ESP
const hailOfThorns = Game.getFormFromFile(0x800, "AdventurerLikeYou.esp")
const hailOfThornsInfo = getFormInfo(hailOfThorns!)
printConsole(JSON.stringify(hailOfThornsInfo))
// Prints out: {"modName":"AdventurerLikeYou.esp","relativeFormId":2048}
}
import { Game, Form } from "skyrimPlatform"
export interface FormInfo {
modName: string,
relativeFormId: number
}
export function getFormInfo(form: Form) {
return getFormInfoFromId(form.getFormID())
}
export function getFormInfoFromId(formId: number): FormInfo | undefined {
const hex = formId.toString(16)
if (hex.toLowerCase().startsWith('ff')) {
// FF are forms which were created at runtime (no source ESP/ESM/ESL)
return
} else if (hex.toLowerCase().startsWith('fe')) {
// FExxxYYY
const index = parseInt(hex.substr(2, 3), 16)
const relativeId = parseInt(hex.substr(5, 3), 16)
const modName = Game.getLightModName(index)
return {
modName: modName,
relativeFormId: relativeId
}
} else {
// xxYYYYYY
const index = parseInt(hex.substr(0, 2), 16)
const relativeId = parseInt(hex.substr(2, 6), 16)
const modName = Game.getModName(index)
return {
modName: modName,
relativeFormId: relativeId
}
}
}
// If you have LOTS and LOTS of forms and you want to make fewer native function invocations
// then you could cache the mod names for each mod index.
//
// I haven't tested this version, but it uses a cache so you'll only ever make a `Game.*` native
// invocation *ONCE* per each unique mod.
import { Game, Form } from "skyrimPlatform"
const lightMods = new Map<number, string>() // I forget whether the IDs can collide,
const fullMods = new Map<number, string>() // I don't actually know why Game has getLightModName
// There is no reason to have 2 separate maps but 🤷‍♀️
export interface FormInfo {
modName: string,
relativeFormId: number
}
export function getFormInfo(form: Form) {
return getFormInfoFromId(form.getFormID())
}
export function getFormInfoFromId(formId: number): FormInfo | undefined {
const hex = formId.toString(16)
if (hex.toLowerCase().startsWith('ff')) {
// FF are forms which were created at runtime (no source ESP/ESM/ESL)
return
} else if (hex.toLowerCase().startsWith('fe')) {
// FExxxYYY
const index = parseInt(hex.substr(2, 3), 16)
const relativeId = parseInt(hex.substr(5, 3), 16)
let modName = ""
if (lightMods.has(index)) {
modName = lightMods.get(index)
} else {
modName = Game.getLightModName(index)
lightMods.set(index, modName)
}
return {
modName: modName,
relativeFormId: relativeId
}
} else {
// xxYYYYYY
const index = parseInt(hex.substr(0, 2), 16)
const relativeId = parseInt(hex.substr(2, 6), 16)
let modName = ""
if (fullMods.has(index)) {
modName = fullMods.get(index)
} else {
modName = Game.getModName(index)
fullMods.set(index, modName)
}
return {
modName: modName,
relativeFormId: relativeId
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment