UNPKG

@cruncheevos/core

Version:

Parse and generate achievements and leaderboards for RetroAchievements.org

182 lines (181 loc) 7.56 kB
import { ConditionBuilder } from './define.js'; import { DeepPartial } from './util.js'; export declare namespace Condition { type Hits = number; interface Value { /** Specifies if value is read from memory and the way it's read/interpreted, or if value is constant. Empty string is allowed for rvalue. */ type: ValueType; /** Specifies how to interpret the value at specified memory address. Not required for constant values. */ size: Size; /** If value type implies reading from memory - this specifies memory address, otherwise specifies constant value. */ value: number; } type ValueArray = [ValueType, Size, number]; type Array = [Flag, ValueType, Size, number, Operator?, ValueType?, Size?, number?, Hits?]; interface Data { /** * Affects condition logic or the way it reads memory. * * Individual documentation for each flag [can be seen here](https://docs.retroachievements.org/developer-docs/achievement-development-overview.html#flags). */ flag: Flag; /** * Condition's left value, it always exists. */ lvalue: Value; /** * An operator set between left and right value. Empty string is allowed for conditions that don't specify right value. */ cmp: Operator; /** * Condition's optional right value. If it's not set - rvalue properties are empty strings. */ rvalue: Value; /** * Amount of hits set (also known as Hit Count), additional explanation [can be seen here](https://docs.retroachievements.org/developer-docs/hit-counts.html). */ hits: number; } type PartialMergedData = DeepPartial<Data> | { lvalue?: Partial<ValueArray>; rvalue?: Partial<ValueArray>; }; type Input = Condition.Data | Condition.Array | string | Condition; type FlagForReading = '' | 'PauseIf' | 'ResetIf' | 'ResetNextIf' | 'AddHits' | 'SubHits' | 'AndNext' | 'OrNext' | 'Measured' | 'Measured%' | 'MeasuredIf' | 'Trigger'; type FlagForCalculation = 'AddSource' | 'SubSource' | 'AddAddress' | 'Remember'; type Flag = FlagForReading | FlagForCalculation; type OperatorComparison = '=' | '!=' | '<' | '<=' | '>' | '>='; type OperatorModifier = '+' | '-' | '*' | '/' | '%' | '&' | '^'; type Operator = '' | OperatorComparison | OperatorModifier; type SizeRegular = '' | 'Bit0' | 'Bit1' | 'Bit2' | 'Bit3' | 'Bit4' | 'Bit5' | 'Bit6' | 'Bit7' | 'Lower4' | 'Upper4' | '8bit' | '16bit' | '24bit' | '32bit' | '16bitBE' | '24bitBE' | '32bitBE' | 'BitCount'; type SizeExtended = 'Float' | 'FloatBE' | 'Double32' | 'Double32BE' | 'MBF32' | 'MBF32LE'; type Size = SizeRegular | SizeExtended; type ValueTypeSized = 'Mem' | 'Delta' | 'Prior' | 'BCD' | 'Invert'; type ValueTypeNoSize = 'Value' | 'Float' | 'Recall'; type ValueType = '' | ValueTypeSized | ValueTypeNoSize; type GroupNormalized = Condition[][]; type Group = (Condition.Input | ConditionBuilder)[] | string | ConditionBuilder; type GroupSetObject<G = Group> = { core: G; [x: `alt${bigint}`]: G; }; type GroupSet = Group | GroupSetObject; } interface GroupSetParseOptions { considerLegacyValueFormat?: boolean; } export declare function validateRegularMeasuredConditions(conditions: Condition.GroupNormalized): void; /** * This class represents a code piece that can be part of achievements, leaderboards or rich presence for RetroAchievements. * * Conditions are immutable, if you need to a make a new Condition instance based of existing one - use `with()` method. */ export declare class Condition implements Condition.Data { flag: Condition.Flag; lvalue: Condition.Value; cmp: Condition.Operator; rvalue: Condition.Value; hits: number; /** * Creates Condition using array representing it. * * @example * new Condition(['ResetIf', 'Mem', 'Bit0', 71, '>', 'Delta', 'Bit1', 71, 3]) */ constructor(def: Condition.Array); /** * Creates Condition using a string representing the condition. * * @example * new Condition('R:0xM47>d0xN47.3.') * // same as * new Condition(['ResetIf', 'Mem', 'Bit0', 71, '>', 'Delta', 'Bit1', 71, 3]) */ constructor(def: string); /** * Returns the same Condition instance passed, * which is due to Conditions being immutable. */ constructor(def: Condition); /** * Creates Condition using an object that directly represents the Condition data. * * @example * new Condition({ * flag: '', * lvalue: { * type: 'Mem', * size: '32bit', * value: 0xcafe, * }, * cmp: '=', * rvalue: { * type: 'Value', * size: '', * value: 47, * }, * hits: 0, * }) */ constructor(def: Condition.Data); /** * @ignore Stub definition to please TypeScript, this accepts all the previous types. */ constructor(def: Condition.Input); /** * Returns new Condition instance with different values merged. * * `lvalue` and `rvalue` can be specified as partial array, which can be less verbose * * @param {DeepPartial<Condition.Data>} data DeepPartial<Condition.Data> * * @example * new Condition('0=1') * .with({ cmp: '!=', rvalue: { value: 47 } }) * .toString() // 0!=47 * * new Condition('0xXcafe=0xXfeed') * .with({ rvalue: ['Delta', '16bit', 0xabcd] }) * .toString() // 0xXcafe=d0x abcd * * new Condition('0xXcafe=0xXfeed') * .with({ rvalue: ['Delta'] }) * .toString() // 0xXcafe=d0xXfeed */ with(data: Condition.PartialMergedData): Condition; /** * Returns string representation of Condition * suitable for RetroAchievements and local files. * @example * new Condition(['ResetIf', 'Mem', 'Bit0', 71, '>', 'Delta', 'Bit1', 71, 3]).toString() // 'R:0xM47>d0xN47.3.' */ toString(): string; /** * Returns direct Array representation of Condition, * values are exactly same as properties of Condition. * * @example * new Condition(['Measured', 'Mem', '8bit', 4]).toArray() * // [ "Measured", "Mem", "8bit", 4, "", "", "", 0, 0 ] */ toArray(): Condition.Array; /** * Returns prettier Array representation of Condition, which is more suitable for display: * * * Everything is a string * * Values are formatted as hexadecimal if they are greater or equal to 100000 * * Negative values are formatted as decimal if they are greater or equal to -4096, otherwise formatted as hexadecimal with underflow correction * * Hits are empty string if equal to zero * * @example * new cruncheevos.Condition(['ResetIf', 'Mem', '32bit', 0xfeedcafe, '>', 'Value', '', 71]).toArrayPretty() * // [ "ResetIf", "Mem", "32bit", "0xfeedcafe", ">", "Value", "", "71", "" ] * * new cruncheevos.Condition(['', 'Value', '', -4097, '>', 'Value', '', -1]).toArrayPretty() * // [ "", "Value", "", "0xffffefff", ">", "Value", "", "-1", "" ] */ toArrayPretty(): string[]; } export declare function normalizedConditionGroupSetFromString(str: string, options?: GroupSetParseOptions): Condition[][]; export declare function normalizedConditionGroupSet(def: Condition.GroupSet, options?: GroupSetParseOptions): Condition.GroupNormalized; export {};