TYP: Improve Scripts/*-related type annotations

This commit is contained in:
bananarama92 2023-02-26 19:07:33 +01:00 committed by banarama92
parent 58e8af9bcb
commit 463c43db28
33 changed files with 401 additions and 341 deletions

View file

@ -13,7 +13,7 @@ interface AssetGroupDefinition {
/** @see {AssetDefinition.Random} */
Random?: boolean;
Color?: string[];
ParentSize?: string;
ParentSize?: AssetGroupName;
ParentColor?: AssetGroupName;
Clothing?: boolean;
Underwear?: boolean;
@ -206,7 +206,7 @@ interface AssetDefinition {
LoverOnly?: boolean;
/** A list of facial expression using the asset causes to the character */
ExpressionTrigger?: { Name: string, Group: AssetGroupName, Timer: number }[];
ExpressionTrigger?: { Name: string, Group: AssetGroupBodyName, Timer: number }[];
/** A list of assets to also remove when the asset is taken off. */
RemoveItemOnRemove?: { Name: string, Group: AssetGroupItemName, Type?: string }[];
@ -227,7 +227,7 @@ interface AssetDefinition {
Category?: string[];
Fetish?: string[];
ArousalZone?: string;
ArousalZone?: AssetGroupName;
IsRestraint?: boolean;
BodyCosplay?: boolean;
OverrideBlinking?: boolean;
@ -288,7 +288,7 @@ interface AssetDefinition {
/** The list of layers for the asset. */
Layer?: AssetLayerDefinition[];
Archetype?: string;
Archetype?: ExtendedArchetype;
FuturisticRecolor?: boolean;
FuturisticRecolorDisplay?: boolean;
@ -425,7 +425,7 @@ interface ExtendedItemAssetConfig<Archetype extends ExtendedArchetype, Config> {
/** The specific configuration for the item (type will vary based on the item's archetype) */
Config?: Config;
/** The group name and asset name of a configuration to copy - useful if multiple items share the same config */
CopyConfig?: { GroupName?: string, AssetName: string };
CopyConfig?: { GroupName?: AssetGroupName, AssetName: string };
}
/** Defines a single extended item option */
@ -779,9 +779,9 @@ interface ModularItemOptionBase {
/** A custom background for this option that overrides the default */
CustomBlindBackground?: string;
/** A list of groups that this option blocks - defaults to [] */
Block?: string[];
Block?: AssetGroupItemName[];
/** A list of groups that this option hides - defaults to [] */
Hide?: string[];
Hide?: AssetGroupName[];
/** A list of items that this option hides */
HideItem?: string[];
/** The Property object to be applied when this option is used */
@ -803,9 +803,9 @@ interface ModularItemOptionBase {
/** Whether that option moves the character up */
HeightModifier?: number;
/** Whether that option applies effects */
Effect?: string[];
Effect?: EffectName[];
/** Whether the option forces a given pose */
SetPose?: string;
SetPose?: AssetPoseName;
/** A list of activities enabled by that module */
AllowActivity?: string[];
/** A buy group to check for that module to be available */

View file

@ -19,6 +19,7 @@ var PlatformDrawUpArrow = [null, null];
var PlatformButtons = null;
var PlatformRunDirection = "";
var PlatformRunTime = 0;
/** @type {null | TouchList} */
var PlatformLastTouch = null;
var PlatformImmunityTime = 500;
var PlatformSaveMode = false;

View file

@ -81,8 +81,8 @@ function ActivityDictionaryText(KeyWord) {
/**
* Resolve a group name to the correct group for activities
* @param {string} family - The asset family for the named group
* @param {string} groupname - The name of the group to resolve
* @param {IAssetFamily} family - The asset family for the named group
* @param {AssetGroupName} groupname - The name of the group to resolve
* @returns {AssetGroup | null} - The resolved group
*/
function ActivityGetGroupOrMirror(family, groupname) {
@ -100,7 +100,7 @@ function ActivityGetGroupOrMirror(family, groupname) {
* Gets all groups that mirror or are mirrored by the given group name for activities. The returned array includes the
* named group.
* @param {string} family - The asset family for the named group
* @param {string} groupName - The name of the group to resolve
* @param {AssetGroupName} groupName - The name of the group to resolve
* @returns {AssetGroup[]} - The group and all groups from the same family that mirror or are mirrored by it
*/
function ActivityGetAllMirrorGroups(family, groupName) {
@ -110,7 +110,7 @@ function ActivityGetAllMirrorGroups(family, groupName) {
/**
* Check if any activities are possible for a character's given group.
* @param {Character} char - The character on which the check is done
* @param {string} groupname - The group to check access on
* @param {AssetGroupName} groupname - The group to check access on
* @returns {boolean} Whether any activity is possible
*/
function ActivityPossibleOnGroup(char, groupname) {
@ -212,7 +212,7 @@ function ActivityCheckPrerequisite(prereq, acting, acted, group) {
// FIXME: The original ZoneAccessible should have been prefixed with Target, which is why those are reversed
// TargetZoneAccessible is only used for ReverseSuckItem, which is marked as reverse, adding in to the confusion
const actor = prereq.startsWith("Target") ? acting : acted;
return ActivityGetAllMirrorGroups(actor.AssetFamily, group.Name).some((g) => !InventoryGroupIsBlocked(actor, g.Name, true));
return ActivityGetAllMirrorGroups(actor.AssetFamily, group.Name).some((g) => g.IsItem() ? !InventoryGroupIsBlocked(actor, g.Name, true) : true);
}
case "ZoneNaked":
case "TargetZoneNaked": {
@ -306,7 +306,7 @@ function ActivityGenerateItemActivitiesFromNeed(allowed, acting, acted, needsIte
blocked = "limited";
} else if (types.some((type) => InventoryBlockedOrLimited(acted, item, type))) {
blocked = "blocked";
} else if (InventoryGroupIsBlocked(acting, item.Asset.Group.Name)) {
} else if (InventoryGroupIsBlocked(acting, /** @type {AssetGroupItemName} */(item.Asset.Group.Name))) {
blocked = "unavail";
}
@ -330,7 +330,7 @@ function ActivityGenerateItemActivitiesFromNeed(allowed, acting, acted, needsIte
/**
* Builds the allowed activities on a group given the character's settings.
* @param {Character} character - The character for which to build the activity dialog options
* @param {string} groupname - The group to check
* @param {AssetGroupName} groupname - The group to check
* @return {ItemActivity[]} - The list of allowed activities
*/
function ActivityAllowedForGroup(character, groupname) {
@ -392,7 +392,7 @@ function ActivityAllowedForGroup(character, groupname) {
* Returns TRUE if an activity can be done
* @param {Character} C - The character to evaluate
* @param {string} Activity - The name of the activity
* @param {string} Group - The name of the group
* @param {AssetGroupName} Group - The name of the group
* @return {boolean} - TRUE if the activity can be done
*/
function ActivityCanBeDone(C, Activity, Group) {
@ -408,7 +408,7 @@ function ActivityCanBeDone(C, Activity, Group) {
* @param {Character} S - The character performing the activity
* @param {Character} C - The character on which the activity is performed
* @param {string|Activity} A - The activity performed
* @param {string} Z - The group/zone name where the activity was performed
* @param {AssetGroupName} Z - The group/zone name where the activity was performed
* @param {number} [Count=1] - If the activity is done repeatedly, this defines the number of times, the activity is done.
* If you don't want an activity to modify arousal, set this parameter to '0'
* @param {Asset} [Asset] - The asset used to perform the activity
@ -443,7 +443,7 @@ function ActivityEffect(S, C, A, Z, Count, Asset) {
* @param {Character} S - The character performing the activity
* @param {Character} C - The character on which the activity is performed
* @param {number} Amount - The base amount of arousal to add
* @param {string} Z - The group/zone name where the activity was performed
* @param {AssetGroupName} Z - The group/zone name where the activity was performed
* @param {number} [Count=1] - If the activity is done repeatedly, this defines the number of times, the activity is done.
* If you don't want an activity to modify arousal, set this parameter to '0'
* @param {Asset} [Asset] - The asset used to perform the activity
@ -495,8 +495,8 @@ function ActivitySetArousal(C, Progress) {
/**
* Sets an activity progress on a timer, activities are capped at MaxProgress
* @param {Character} C - The character for which to set the timer for
* @param {object} Activity - The activity for which the timer is for
* @param {string} Zone - The target zone of the activity
* @param {null | Activity} Activity - The activity for which the timer is for
* @param {AssetGroupName | "ActivityOnOther"} Zone - The target zone of the activity
* @param {number} Progress - Progress to set
* @param {Asset} [Asset] - The asset used to perform the activity
* @return {void} - Nothing
@ -928,7 +928,7 @@ function ActivityRun(C, ItemActivity) {
* Checks if a used asset should trigger an activity/arousal progress on the target character
* @param {Character} Source - The character who used the item
* @param {Character} Target - The character on which the item was used
* @param {object} Asset - Asset used
* @param {Asset} Asset - Asset used
* @return {void} - Nothing
*/
function ActivityArousalItem(Source, Target, Asset) {

View file

@ -2,7 +2,7 @@
/**
* Where animation data is stored. Animation data is only managed client side, nothing should be synced.
* @constant
* @type {object} - The animation data object.
* @type {Record<string, any>} - The animation data object.
*/
var AnimationPersistentStorage = {};

View file

@ -7,11 +7,11 @@ var Asset = [];
var AssetGroup = [];
/** @type {Map<string, Asset>} */
var AssetMap = new Map();
/** @type {Map<string, AssetGroup>} */
/** @type {Map<AssetGroupName, AssetGroup>} */
var AssetGroupMap = new Map();
/** @type {Pose[]} */
var Pose = [];
/** @type {Map<string, AssetGroup[]>} */
/** @type {Map<AssetGroupName, AssetGroup[]>} */
var AssetActivityMirrorGroups = new Map();
/**
@ -56,7 +56,7 @@ function AssetGroupAdd(Family, GroupDef) {
DrawingTop: (GroupDef.Top == null) ? 0 : GroupDef.Top,
DrawingFullAlpha: (GroupDef.FullAlpha == null) ? true : GroupDef.FullAlpha,
DrawingBlink: (GroupDef.Blink == null) ? false : GroupDef.Blink,
InheritColor: (typeof GroupDef.InheritColor === "string" ? GroupDef.InheritColor : undefined),
InheritColor: (typeof GroupDef.InheritColor === "string" ? GroupDef.InheritColor : null),
FreezeActivePose: Array.isArray(GroupDef.FreezeActivePose) ? GroupDef.FreezeActivePose : [],
PreviewZone: GroupDef.PreviewZone,
DynamicGroupName: GroupDef.DynamicGroupName || GroupDef.Group,
@ -229,6 +229,7 @@ function AssetAdd(Group, AssetDef, ExtendedConfig) {
AssetAssignColorIndices(A);
// Unwearable assets are not visible but can be overwritten
if (!A.Wear && AssetDef.Visible != true) A.Visible = false;
// @ts-ignore: ignore `readonly` while still building the group properties
Group.Asset.push(A);
AssetMap.set(Group.Name + "/" + A.Name, A);
Asset.push(A);
@ -286,7 +287,7 @@ function AssetBuildExtended(A, ExtendedConfig) {
/**
* Finds the extended item configuration for the provided group and asset name, if any exists
* @param {ExtendedItemConfig} ExtendedConfig - The full extended item configuration object
* @param {string} GroupName - The name of the asset group to find extended configuration for
* @param {AssetGroupName} GroupName - The name of the asset group to find extended configuration for
* @param {string} AssetName - The name of the asset to find extended configuration fo
* @returns {AssetArchetypeConfig | undefined} - The extended asset configuration object for the specified asset, if
* any exists, or undefined otherwise
@ -525,7 +526,7 @@ function AssetLoadDescription(Family) {
/**
* Loads a specific asset file
* @param {AssetGroupDefinition[]} Groups
* @param {readonly AssetGroupDefinition[]} Groups
* @param {IAssetFamily} Family
* @param {ExtendedItemConfig} ExtendedConfig
*/
@ -561,8 +562,8 @@ function AssetLoadAll() {
/**
* Gets a specific asset by family/group/name
* @param {string} Family - The family to search in (Ignored until other family is added)
* @param {string} Group - Name of the group of the searched asset
* @param {IAssetFamily} Family - The family to search in (Ignored until other family is added)
* @param {AssetGroupName} Group - Name of the group of the searched asset
* @param {string} Name - Name of the searched asset
* @returns {Asset|null}
*/
@ -572,7 +573,7 @@ function AssetGet(Family, Group, Name) {
/**
* Gets all activities on a family and name
* @param {string} family - The family to search in
* @param {IAssetFamily} family - The family to search in
* @returns {Activity[]}
*/
function AssetAllActivities(family) {
@ -583,7 +584,7 @@ function AssetAllActivities(family) {
/**
* Gets an activity asset by family and name
* @param {string} family - The family to search in
* @param {IAssetFamily} family - The family to search in
* @param {string} name - Name of activity to search for
* @returns {Activity|undefined}
*/
@ -597,8 +598,8 @@ function AssetGetActivity(family, name) {
* @description Note that this just returns activities as defined, no checks are
* actually done on whether the activity makes sense.
*
* @param {string} family
* @param {string} groupname
* @param {IAssetFamily} family
* @param {AssetGroupName} groupname
* @param {"self" | "other" | "any"} onSelf
* @returns {Activity[]}
*/
@ -627,8 +628,8 @@ function AssetActivitiesForGroup(family, groupname, onSelf = "other") {
/**
* Cleans the given array of assets of any items that no longer exists
* @param {ItemPermissions[]} AssetArray - The arrays of items to clean
* @returns The cleaned up array
* @param {readonly ItemPermissions[]} AssetArray - The arrays of items to clean
* @returns {ItemPermissions[]} - The cleaned up array
*/
function AssetCleanArray(AssetArray) {
return AssetArray.filter(({ Group, Name }) => AssetGet('Female3DCG', Group, Name) != null);
@ -636,8 +637,8 @@ function AssetCleanArray(AssetArray) {
/**
* Gets an asset group by the asset family name and group name
* @param {string} Family - The asset family that the group belongs to (Ignored until other family is added)
* @param {string} Group - The name of the asset group to find
* @param {IAssetFamily} Family - The asset family that the group belongs to (Ignored until other family is added)
* @param {AssetGroupName} Group - The name of the asset group to find
* @returns {AssetGroup|null} - The asset group matching the provided family and group name
*/
function AssetGroupGet(Family, Group) {

View file

@ -470,7 +470,7 @@ function AudioPlaySoundForAsset(character, asset) {
* Get the sound effect for a given asset.
*
* @param {Character} character
* @param {string} groupName
* @param {AssetGroupName} groupName
* @param {string} assetName
* @returns {AudioSoundEffect?}
*/

View file

@ -45,15 +45,15 @@ var CharacterType = {
/**
* Loads a character into the buffer, creates it if it does not exist
* @param {number} CharacterID - ID of the character
* @param {string} CharacterAssetFamily - Name of the asset family of the character
* @param {IAssetFamily} CharacterAssetFamily - Name of the asset family of the character
* @param {CharacterType} [Type=CharacterType.ONLINE] - The character type
* @returns {Character} - The newly loaded character
*/
function CharacterReset(CharacterID, CharacterAssetFamily, Type = CharacterType.ONLINE) {
// Prepares the character sheet
/** @type {Character} */
var NewCharacter = {
ActivePose: [],
ID: CharacterID,
Hooks: null,
Name: "",
@ -452,7 +452,7 @@ function CharacterRandomName(C) {
/**
* Builds the dialog objects from the character CSV file
* @param {Character} C - Character for which to build the dialog
* @param {string[][]} CSV - Content of the CSV file
* @param {readonly string[][]} CSV - Content of the CSV file
* @returns {void} - Nothing
*/
function CharacterBuildDialog(C, CSV) {
@ -542,7 +542,7 @@ function CharacterLoadCSVDialog(C, Override) {
/**
* Sets the clothes based on a character archetype
* @param {Character} C - Character to set the clothes for
* @param {string} Archetype - Archetype to determine the clothes to put on
* @param {"Maid" | "Mistress" | "Employee"} Archetype - Archetype to determine the clothes to put on
* @param {string} [ForceColor] - Color to use for the added clothes
* @returns {void} - Nothing
*/
@ -846,7 +846,7 @@ function CharacterDeleteAllOnline() {
/**
* Adds a pose to a character's pose list, does not add it if it's already there
* @param {Character} C - Character for which to add a pose to its list
* @param {AssetPoseName[]} NewPose - The name of the pose to add
* @param {readonly AssetPoseName[]} NewPose - The name of the pose to add
* @returns {void} - Nothing
*/
function CharacterAddPose(C, NewPose) {
@ -1017,7 +1017,7 @@ function CharacterLoadAttributes(C) {
/**
* Returns a list of effects for a character from some or all groups
* @param {Character} C - The character to check
* @param {AssetGroupName[]} [Groups=null] - Optional: The list of groups to consider. If none defined, check all groups
* @param {readonly AssetGroupName[]} [Groups=null] - Optional: The list of groups to consider. If none defined, check all groups
* @param {boolean} [AllowDuplicates=false] - Optional: If true, keep duplicates of the same effect provided they're taken from different groups
* @returns {EffectName[]} - A list of effects
*/
@ -1466,7 +1466,7 @@ function CharacterFullRandomRestrain(C, Ratio, Refresh) {
*/
function CharacterSetActivePose(C, NewPose, ForceChange = false) {
if (NewPose == null || ForceChange || C.ActivePose == null) {
C.ActivePose = NewPose;
C.ActivePose = [NewPose];
CharacterRefresh(C, false);
return;
}
@ -1499,7 +1499,7 @@ function CharacterSetActivePose(C, NewPose, ForceChange = false) {
* Be careful that "Eyes" for this function means both eyes. Use Eyes1/Eyes2 to target the left or right one only.
*
* @param {Character} C - Character for which to set the expression of
* @param {AssetGroupName | "Eyes1"} AssetGroup - Asset group for the expression
* @param {AssetGroupBodyName | "Eyes1"} AssetGroup - Asset group for the expression
* @param {string} Expression - Name of the expression to use
* @param {number} [Timer] - Optional: time the expression will last
* @param {string|string[]} [Color] - Optional: color of the expression to set
@ -1540,9 +1540,12 @@ function CharacterSetFacialExpression(C, AssetGroup, Expression, Timer, Color) {
* @returns {void} - Nothing
*/
function CharacterResetFacialExpression(C) {
for (let A = 0; A < C.Appearance.length; A++)
if (C.Appearance[A].Asset.Group.AllowExpression)
CharacterSetFacialExpression(C, C.Appearance[A].Asset.Group.Name, null);
for (const item of C.Appearance) {
const group = item.Asset.Group;
if (group.IsAppearance() && group.AllowExpression) {
CharacterSetFacialExpression(C, group.Name, null);
}
}
}
/**

View file

@ -23,7 +23,7 @@ var CommonPhotoMode = false;
var GameVersion = "R0";
const GameVersionFormat = /^R([0-9]+)(?:(Alpha|Beta)([0-9]+)?)?$/;
var CommonVersionUpdated = false;
/** @type {null | { pageX: number, pageY: number }} */
/** @type {null | TouchList} */
var CommonTouchList = null;
/**
@ -76,7 +76,7 @@ const CommonFontStacks = {
/**
* Checks if a variable is a number
* @param {*} n - Variable to check for
* @param {unknown} n - Variable to check for
* @returns {boolean} - Returns TRUE if the variable is a finite number
*/
function CommonIsNumeric(n) {
@ -273,7 +273,7 @@ function CommonClick(event) {
* @param {number} Y - The Y position
* @param {number} W - The width of the square
* @param {number} H - The height of the square
* @param {object} TL - Can give a specific touch event instead of the default one
* @param {TouchList} [TL] - Can give a specific touch event instead of the default one
* @returns {boolean}
*/
function CommonTouchActive(X, Y, W, H, TL) {
@ -376,7 +376,7 @@ function CommonDynamicFunctionParams(FunctionName) {
* passed directly into the function call, allowing for more complex JS objects to be passed in. This
* function will not log to console if the provided function name does not exist as a global function.
* @param {string} FunctionName - The name of the global function to call
* @param {any[]} [args] - zero or more arguments to be passed to the function (optional)
* @param {readonly any[]} [args] - zero or more arguments to be passed to the function (optional)
* @returns {any} - returns the result of the function call, or undefined if the function name isn't valid
*/
function CommonCallFunctionByName(FunctionName/*, ...args */) {
@ -390,7 +390,7 @@ function CommonCallFunctionByName(FunctionName/*, ...args */) {
/**
* Behaves exactly like CommonCallFunctionByName, but logs a warning if the function name is invalid.
* @param {string} FunctionName - The name of the global function to call
* @param {any[]} [args] - zero or more arguments to be passed to the function (optional)
* @param {readonly any[]} [args] - zero or more arguments to be passed to the function (optional)
* @returns {any} - returns the result of the function call, or undefined if the function name isn't valid
*/
function CommonCallFunctionByNameWarn(FunctionName/*, ...args */) {
@ -480,7 +480,7 @@ function CommonIsColor(Value) {
* Checks whether an item's color has a valid value that can be interpreted by the drawing
* functions. Valid values are null, undefined, strings, and an array containing any of the
* aforementioned types.
* @param {*} Color - The Color value to check
* @param {null | string | readonly (null | string)[]} [Color] - The Color value to check
* @returns {boolean} - Returns TRUE if the color is a valid item color
*/
function CommonColorIsValid(Color) {
@ -509,7 +509,7 @@ function CommonEmailIsValid(Email) {
* Get a random item from a list while making sure not to pick the previous one.
* @template T
* @param {T} ItemPrevious - Previously selected item from the given list
* @param {T[]} ItemList - List for which to pick a random item from
* @param {readonly T[]} ItemList - List for which to pick a random item from
* @returns {T} - The randomly selected item from the list
*/
function CommonRandomItemFromList(ItemPrevious, ItemList) {
@ -553,7 +553,7 @@ function CommonStringShuffle(string) {
/**
* Converts an array to a string separated by commas (equivalent of .join(","))
* @param {Array} Arr - Array to convert to a joined string
* @param {readonly any[]} Arr - Array to convert to a joined string
* @returns {string} - String of all the array items joined together
*/
function CommonConvertArrayToString(Arr) {
@ -567,8 +567,8 @@ function CommonConvertArrayToString(Arr) {
/**
* Checks whether two item colors are equal. An item color may either be a string or an array of strings.
* @param {string|string[]} C1 - The first color to check
* @param {string|string[]} C2 - The second color to check
* @param {string | readonly string[]} C1 - The first color to check
* @param {string | readonly string[]} C2 - The second color to check
* @returns {boolean} - TRUE if C1 and C2 represent the same item color, FALSE otherwise
*/
function CommonColorsEqual(C1, C2) {
@ -581,8 +581,8 @@ function CommonColorsEqual(C1, C2) {
/**
* Checks whether two arrays are equal. The arrays are considered equal if they have the same length and contain the same items in the same
* order, as determined by === comparison
* @param {*[]} a1 - The first array to compare
* @param {*[]} a2 - The second array to compare
* @param {readonly *[]} a1 - The first array to compare
* @param {readonly *[]} a2 - The second array to compare
* @param {boolean} [ignoreOrder] - Whether to ignore item order when considering equality
* @returns {boolean} - TRUE if both arrays have the same length and contain the same items in the same order, FALSE otherwise
*/
@ -656,7 +656,7 @@ function CommonThrottle(func) {
/**
* Creates a wrapper for a function to limit how often it can be called. The player-defined wait interval setting determines the
* allowed frequency. Below 100 ms the function will be throttled and above will be debounced.
* @template {() => void} FunctionType
* @template {(...args: any) => any} FunctionType
* @param {FunctionType} func - The function to limit calls of
* @param {number} [minWait=0] - A lower bound for how long the wait interval can be, 0 by default
* @param {number} [maxWait=1000] - An upper bound for how long the wait interval can be, 1 second by default
@ -893,7 +893,7 @@ function CommonDeepEqual(obj1, obj2) {
/**
* Adds all items from the source array to the destination array if they aren't already included
* @param {*[]} dest - The destination array
* @param {*[]} src - The source array
* @param {readonly *[]} src - The source array
* @returns {*[]} - The destination array
*/
function CommonArrayConcatDedupe(dest, src) {

View file

@ -359,7 +359,7 @@ function CommonDrawColorValid(Color, AssetGroup) {
/**
* Finds the correct pose to draw for drawable layer for the provided character from the provided list of allowed poses
* @param {Character} C - The character to check for poses against
* @param {AssetPoseName[]} AllowedPoses - The list of permitted poses for the current layer
* @param {readonly AssetPoseName[]} AllowedPoses - The list of permitted poses for the current layer
* @return {AssetPoseName} - The name of the pose to draw for the layer, or an empty string if no pose should be drawn
*/
function CommonDrawFindPose(C, AllowedPoses) {

View file

@ -47,8 +47,8 @@ function ClearButtons() {
}
/**
* adds a button to the lists
* @param {any} X X value of the button
* @param {any} Y Y value of the button
* @param {number} X X value of the button
* @param {number} Y Y value of the button
*/
function setButton(X, Y) {
if (ControllerIgnoreButton == false) {
@ -62,8 +62,9 @@ function setButton(X, Y) {
}
/**
* checks, whether a button is already in the lists (I realize now, that I could have used .includes but it works)
* @param {any} X X value of the button
* @param {any} Y Y value of the button
* @param {number} X X value of the button
* @param {number} Y Y value of the button
* @returns {boolean}
*/
function ButtonExists(X, Y) {
var g = 0;
@ -79,7 +80,7 @@ function ButtonExists(X, Y) {
/**
* handles the sitck input
* @param {any} axes the raw data of all axes of the controller
* @param {readonly number[]} axes the raw data of all axes of the controller
*/
function ControllerAxis(axes) {

View file

@ -212,7 +212,7 @@ function DialogChangeMoney(Amount) { CharacterChangeMoney(Player, parseInt(Amoun
/**
* Alters the current player's reputation by a given amount
* @param {string} RepType - The name of the reputation to change
* @param {ReputationType} RepType - The name of the reputation to change
* @param {number|string} Value - The value, the player's reputation should be altered by
* @returns {void} - Nothing
*/
@ -220,7 +220,7 @@ function DialogSetReputation(RepType, Value) { ReputationChange(RepType, (parseI
/**
* Change the player's reputation progressively through dialog options (a reputation is easier to break than to build)
* @param {string} RepType - The name of the reputation to change
* @param {ReputationType} RepType - The name of the reputation to change
* @param {number|string} Value - The value, the player's reputation should be altered by
* @returns {void} - Nothing
*/
@ -229,21 +229,21 @@ function DialogChangeReputation(RepType, Value) { ReputationProgress(RepType, Va
/**
* Equips a specific item on the player from dialog
* @param {string} AssetName - The name of the asset that should be equipped
* @param {string} AssetGroup - The name of the corresponding asset group
* @param {AssetGroupName} AssetGroup - The name of the corresponding asset group
* @returns {void} - Nothing
*/
function DialogWearItem(AssetName, AssetGroup) { InventoryWear(Player, AssetName, /** @type {AssetGroupName} */(AssetGroup)); }
/**
* Equips a random item from a given group to the player from dialog
* @param {string} AssetGroup - The name of the asset group to pick from
* @param {AssetGroupName} AssetGroup - The name of the asset group to pick from
* @returns {void} - Nothing
*/
function DialogWearRandomItem(AssetGroup) { InventoryWearRandom(Player, /** @type {AssetGroupName} */(AssetGroup)); }
/**
* Removes an item of a specific item group from the player
* @param {string} AssetGroup - The item to be removed belongs to this asset group
* @param {AssetGroupName} AssetGroup - The item to be removed belongs to this asset group
* @returns {void} - Nothing
*/
function DialogRemoveItem(AssetGroup) { InventoryRemove(Player, /** @type {AssetGroupName} */(AssetGroup)); }
@ -358,15 +358,15 @@ function DialogCanInteract(C) { return DialogGetCharacter(C).CanInteract(); }
* Sets a new pose for the given character
* @param {string} C - The character whose pose should be altered.
* Either the player (value: Player) or the current character (value: CurrentCharacter)
* @param {AssetPoseName} [NewPose=null] - The new pose, the character should take.
* @param {null | AssetPoseName} [NewPose=null] - The new pose, the character should take.
* Can be omitted to bring the character back to the standing position.
* @returns {void} - Nothing
*/
function DialogSetPose(C, NewPose) { CharacterSetActivePose((C.toUpperCase().trim() == "PLAYER") ? Player : CurrentCharacter, ((NewPose != null) && (NewPose != "")) ? NewPose : null, true); }
function DialogSetPose(C, NewPose) { CharacterSetActivePose((C.toUpperCase().trim() == "PLAYER") ? Player : CurrentCharacter, NewPose ?? null, true); }
/**
* Checks, whether a given skill of the player is greater or equal a given value
* @param {string} SkillType - Name of the skill to check
* @param {SkillType} SkillType - Name of the skill to check
* @param {string} Value - The value, the given skill must be compared to
* @returns {boolean} - Returns true if a specific skill is greater or equal than a given value
*/
@ -375,10 +375,10 @@ function DialogSkillGreater(SkillType, Value) { return (parseInt(SkillGetLevel(P
/**
* Checks, if a given item is available in the player's inventory
* @param {string} InventoryName
* @param {string} InventoryGroup
* @param {AssetGroupName} InventoryGroup
* @returns {boolean} - Returns true, if the item is available, false otherwise
*/
function DialogInventoryAvailable(InventoryName, InventoryGroup) { return InventoryAvailable(Player, InventoryName, /** @type {AssetGroupName} */(InventoryGroup)); }
function DialogInventoryAvailable(InventoryName, InventoryGroup) { return InventoryAvailable(Player, InventoryName, InventoryGroup); }
/**
* Checks, if the player is the administrator of the current chat room
@ -644,13 +644,13 @@ function DialogRemove() {
/**
* Generic dialog function to remove any dialog from a specific group
* @param {string} GroupName - All dialog options are removed from this group
* @param {AssetGroupName} GroupName - All dialog options are removed from this group
* @returns {void} - Nothing
*/
function DialogRemoveGroup(GroupName) {
GroupName = GroupName.trim().toUpperCase();
const GroupNameUpper = GroupName.trim().toUpperCase();
for (let D = CurrentCharacter.Dialog.length - 1; D >= 0; D--)
if ((CurrentCharacter.Dialog[D].Group != null) && (CurrentCharacter.Dialog[D].Group.trim().toUpperCase() == GroupName)) {
if ((CurrentCharacter.Dialog[D].Group != null) && (CurrentCharacter.Dialog[D].Group.trim().toUpperCase() == GroupNameUpper)) {
CurrentCharacter.Dialog.splice(D, 1);
}
}
@ -953,7 +953,7 @@ function DialogCanColor(C, Item) {
/**
* Checks whether a lock can be inspected while blind.
* @param {string} lockName - The lock type
* @param {AssetLockType} lockName - The lock type
* @returns {boolean}
*/
function DialogCanInspectLockWhileBlind(lockName) {
@ -1034,7 +1034,7 @@ function DialogMenuButtonBuild(C) {
break;
}
}
if (Lock && (!Player.IsBlind() || DialogCanInspectLockWhileBlind(Lock.Asset.Name))) {
if (Lock && (!Player.IsBlind() || DialogCanInspectLockWhileBlind(/** @type {AssetLockType} */(Lock.Asset.Name)))) {
DialogMenuButton.push(LockBlockedOrLimited ? "InspectLockDisabled" : "InspectLock");
}
@ -1064,8 +1064,8 @@ function DialogMenuButtonBuild(C) {
DialogMenuButton.push("Remove");
if (
IsItemLocked &&
(
IsItemLocked
&& (
(
!Player.IsBlind() ||
(Item.Property && DialogCanInspectLockWhileBlind(Item.Property.LockedBy))
@ -1080,10 +1080,8 @@ function DialogMenuButtonBuild(C) {
C.ID == 0 ||
(C.OnlineSharedSettings && !C.OnlineSharedSettings.DisablePickingLocksOnSelf)
)
) &&
(Item.Property != null) &&
(Item.Property.LockedBy != null) &&
(Item.Property.LockedBy != "")
)
&& Item.Property?.LockedBy
) {
DialogMenuButton.push("LockMenu");
}
@ -1218,7 +1216,7 @@ function DialogInventoryBuild(C, Offset, redrawPreviews = false) {
if ((CurItem == null) || (CurItem.Asset.Name != A.Name) || (CurItem.Asset.Group.Name != A.Group.Name))
DialogInventoryAdd(Player, { Asset: A }, false, DialogSortOrder.Enabled);
} else if (A.IsLock) {
const LockIsWorn = InventoryCharacterIsWearingLock(C, A.Name);
const LockIsWorn = InventoryCharacterIsWearingLock(C, /** @type {AssetLockType} */(A.Name));
DialogInventoryAdd(Player, { Asset: A }, LockIsWorn, DialogSortOrder.Enabled);
}
}
@ -1335,10 +1333,9 @@ function DialogFacialExpressionsSave(Slot) {
* @param {number} Slot - Index of saved expression (0 to 4)
*/
function DialogFacialExpressionsLoad(Slot) {
if (Player.SavedExpressions[Slot] != null) {
for (let x = 0; x < Player.SavedExpressions[Slot].length; x++) {
CharacterSetFacialExpression(Player, Player.SavedExpressions[Slot][x].Group, Player.SavedExpressions[Slot][x].CurrentExpression);
}
const expressions = Player.SavedExpressions && Player.SavedExpressions[Slot];
if (expressions != null) {
expressions.forEach(e => CharacterSetFacialExpression(Player, e.Group, e.CurrentExpression));
DialogFacialExpressionsBuild();
}
}
@ -1491,6 +1488,7 @@ function DialogMenuButtonClick() {
// Cycle through the layers of restraints for the mouth
else if (DialogMenuButton[I] == "ChangeLayersMouth") {
/** @type {AssetGroupName} */
var NewLayerName;
if (C.FocusGroup.Name == "ItemMouth") NewLayerName = "ItemMouth2";
if (C.FocusGroup.Name == "ItemMouth2") NewLayerName = "ItemMouth3";
@ -2016,7 +2014,7 @@ function DialogClick() {
/**
* Returns whether the clicked co-ordinates are inside the asset zone
* @param {Character} C - The character the click is on
* @param {Array} Zone - The 4 part array of the rectangular asset zone on the character's body: [X, Y, Width, Height]
* @param {readonly [number, number, number, number]} Zone - The 4 part array of the rectangular asset zone on the character's body: [X, Y, Width, Height]
* @param {number} Zoom - The amount the character has been zoomed
* @param {number} X - The X co-ordinate of the click
* @param {number} Y - The Y co-ordinate of the click
@ -2031,12 +2029,12 @@ function DialogClickedInZone(C, Zone, Zoom, X, Y, HeightRatio) {
/**
* Return the co-ordinates and dimensions of the asset group zone as it appears on screen
* @param {Character} C - The character the zone is calculated for
* @param {Array} Zone - The 4 part array of the rectangular asset zone: [X, Y, Width, Height]
* @param {readonly [number, number, number, number]} Zone - The 4 part array of the rectangular asset zone: [X, Y, Width, Height]
* @param {number} X - The starting X co-ordinate of the character's position
* @param {number} Y - The starting Y co-ordinate of the character's position
* @param {number} Zoom - The amount the character has been zoomed
* @param {number} HeightRatio - The displayed height ratio of the character
* @returns {Array} - The 4 part array of the displayed rectangular asset zone: [X, Y, Width, Height]
* @returns {[number, number, number, number]} - The 4 part array of the displayed rectangular asset zone: [X, Y, Width, Height]
*/
function DialogGetCharacterZone(C, Zone, X, Y, Zoom, HeightRatio) {
X += CharacterAppearanceXOffset(C, HeightRatio) * Zoom;
@ -2761,7 +2759,7 @@ function DialogDrawOwnerRulesMenu() {
/**
* Sets the skill ratio for the player, will be a % of effectiveness applied to the skill when using it.
* This way a player can use only a part of her bondage or evasion skill.
* @param {string} SkillType - The name of the skill to influence
* @param {SkillType} SkillType - The name of the skill to influence
* @param {string} NewRatio - The ration of this skill that should be used
* @returns {void} - Nothing
*/

View file

@ -234,7 +234,7 @@ class ConditionalDictionaryBuilder extends DictionaryBuilder {
}
/**
* @param {ChatMessageDictionaryEntry} entry
* @param {ChatMessageDictionaryEntry | TaggedDictionaryEntry} entry
* @returns {entry is TaggedDictionaryEntry}
*/
function IsTaggedDictionaryEntry(entry) {

View file

@ -375,13 +375,14 @@ function DrawCharacter(C, X, Y, Zoom, IsHeightResizeAllowed, DrawCanvas) {
if ((C.FocusGroup != null) && (C.FocusGroup.Zone != null) && (CurrentScreen != "Preference") && (DialogColor == null)) {
// Draw all the possible zones in transparent colors (gray if free, yellow if occupied, red if blocker)
for (let A = 0; A < AssetGroup.length; A++)
if (AssetGroup[A].Zone != null && AssetGroup[A].Name != C.FocusGroup.Name) {
for (const group of AssetGroup) {
if (group.Zone != null && group.Name != C.FocusGroup.Name) {
let Color = "#80808040";
if (InventoryGroupIsBlocked(C, AssetGroup[A].Name)) Color = "#88000580";
else if (InventoryGet(C, AssetGroup[A].Name) != null) Color = "#D5A30080";
DrawAssetGroupZone(C, AssetGroup[A].Zone, Zoom, X, Y, HeightRatio, Color, 5);
if (group.IsItem() && InventoryGroupIsBlocked(C, group.Name)) Color = "#88000580";
else if (InventoryGet(C, group.Name) != null) Color = "#D5A30080";
DrawAssetGroupZone(C, group.Zone, Zoom, X, Y, HeightRatio, Color, 5);
}
}
// Draw the focused zone in cyan
DrawAssetGroupZone(C, C.FocusGroup.Zone, Zoom, X, Y, HeightRatio, "cyan");
@ -402,7 +403,7 @@ function DrawCharacter(C, X, Y, Zoom, IsHeightResizeAllowed, DrawCanvas) {
/**
* Draws an asset group zone outline over the character
* @param {Character} C - Character for which to draw the zone
* @param {number[][]} Zone - Zone to be drawn
* @param {readonly [number, number, number, number][]} Zone - Zone to be drawn
* @param {number} Zoom - Height ratio of the character
* @param {number} X - Position of the character on the X axis
* @param {number} Y - Position of the character on the Y axis
@ -490,7 +491,7 @@ function DrawImageResize(Source, X, Y, Width, Height) {
* @param {CanvasRenderingContext2D} Canvas - Canvas on which to draw the image
* @param {number} X - Position of the image on the X axis
* @param {number} Y - Position of the image on the Y axis
* @param {RectTuple[]} [AlphaMasks] - A list of alpha masks to apply to the asset
* @param {readonly RectTuple[]} [AlphaMasks] - A list of alpha masks to apply to the asset
* @param {number} [Opacity=1] - The opacity at which to draw the image
* @param {boolean} [Rotate=false] - If the image should be rotated by 180 degrees
* @param {GlobalCompositeOperation} [BlendingMode="source-over"] - blending mode for drawing the image
@ -533,7 +534,7 @@ function DrawImageCanvas(Source, Canvas, X, Y, AlphaMasks, Opacity, Rotate, Blen
* @param {CanvasRenderingContext2D} Canvas - Canvas on which to draw the image
* @param {number} X - Position of the image on the X axis
* @param {number} Y - Position of the image on the Y axis
* @param {RectTuple[]} AlphaMasks - A list of alpha masks to apply to the asset
* @param {readonly RectTuple[]} AlphaMasks - A list of alpha masks to apply to the asset
* @returns {boolean} - whether the image was complete or not
*/
function DrawCanvas(Img, Canvas, X, Y, AlphaMasks) {
@ -598,7 +599,7 @@ function DrawImage(Source, X, Y, Invert) {
* @param {number} Zoom - Zoom factor
* @param {string} HexColor - Color of the image to draw
* @param {boolean} FullAlpha - Whether or not it is drawn in full alpha mode
* @param {RectTuple[]} [AlphaMasks] - A list of alpha masks to apply to the asset
* @param {readonly RectTuple[]} [AlphaMasks] - A list of alpha masks to apply to the asset
* @param {number} [Opacity=1] - The opacity at which to draw the image
* @param {boolean} [Rotate=false] - If the image should be rotated by 180 degrees
* @param {GlobalCompositeOperation} [BlendingMode="source-over"] - blending mode for drawing the image
@ -705,7 +706,7 @@ function DrawImageInvert(Img) {
* @param {object} [options] - any extra options, optional
* @param {CanvasRenderingContext2D} [options.Canvas] - Canvas on which to draw the image, defaults to `MainCanvas`
* @param {number} [options.Alpha] - transparency between 0-1
* @param {[number, number, number, number]} [options.SourcePos] - Area in original image to draw in format `[left, top, width, height]`
* @param {readonly [number, number, number, number]} [options.SourcePos] - Area in original image to draw in format `[left, top, width, height]`
* @param {number} [options.Width] - Width of the drawn image, defaults to width of original image
* @param {number} [options.Height] - Height of the drawn image, defaults to height of original image
* @param {boolean} [options.Invert=false] - If image should be flipped vertically
@ -1455,7 +1456,7 @@ function DrawProcessHoverElements() {
* @param {boolean} [Options.Hover] - Whether or not the button should enable hover behavior (background color change)
* @param {string} [Options.HoverBackground] - The background color that should be used on mouse hover, if any
* @param {boolean} [Options.Disabled] - Whether or not the element is disabled (prevents hover functionality)
* @param {InventoryIcon[]} [Options.Icons] - A list of small icons to display in the top-left corner
* @param {readonly InventoryIcon[]} [Options.Icons] - A list of small icons to display in the top-left corner
* @param {object} [Options.Craft] - The crafted properties of the item
* @returns {void} - Nothing
*/
@ -1483,7 +1484,7 @@ function DrawAssetPreview(X, Y, A, Options) {
* @param {boolean} [Options.Hover] - Whether or not the button should enable hover behavior (background color change)
* @param {string} [Options.HoverBackground] - The background color that should be used on mouse hover, if any
* @param {boolean} [Options.Disabled] - Whether or not the element is disabled (prevents hover functionality)
* @param {InventoryIcon[]} [Options.Icons] - A list of images to draw in the top-left of the preview box
* @param {readonly InventoryIcon[]} [Options.Icons] - A list of images to draw in the top-left of the preview box
* @returns {void} - Nothing
*/
function DrawPreviewBox(X, Y, Path, Description, Options) {
@ -1505,7 +1506,7 @@ function DrawPreviewBox(X, Y, Path, Description, Options) {
/**
* Draws a list of small icons over a preview box
* @param {InventoryIcon[]} icons - An array of icon names
* @param {readonly InventoryIcon[]} icons - An array of icon names
* @param {number} X - The X co-ordinate to start drawing from
* @param {number} Y - The Y co-ordinate to start drawing from
* @returns {void} - Nothing

View file

@ -117,7 +117,7 @@ const DynamicDrawTextCurve = {
/**
* An enum encapsulating the available drawing effects that can be applied to dynamic text.
* @enum {string}
* @type {{ BURN: "burn" }}
*/
const DynamicDrawTextEffect = {
BURN: "burn",
@ -221,8 +221,8 @@ function DynamicDrawText(text, ctx, x, y, options) {
* contained in the rectangle defined by the from and to positions.
* @param {string} text - The text to draw
* @param {CanvasRenderingContext2D} ctx - The rendering context to draw the text to
* @param {number[]} from - The [x, y] coordinates to start drawing the text at
* @param {number[]} to - The [x, y] coordinates to end drawing the text at
* @param {readonly number[]} from - The [x, y] coordinates to start drawing the text at
* @param {readonly number[]} to - The [x, y] coordinates to end drawing the text at
* @param {DynamicDrawOptions} options - Additional drawing options
* @returns {void} - Nothing
*/

View file

@ -136,7 +136,7 @@ function ElementCreateRangeInput(id, value, min, max, step, thumbIcon, vertical)
* - Multiple selects are impossible
* @param {string} ID - The name of the select item. The outer div will get this name, for positioning. The select
* tag will get the name ID+"-select"
* @param {string[]} Options - The list of options for the current select statement
* @param {readonly string[]} Options - The list of options for the current select statement
* @param {EventListenerOrEventListenerObject} [ClickEventListener=null] - An event listener to be called, when the value of the drop down box changes
* @returns {void} - Nothing
*/

View file

@ -93,7 +93,7 @@ function ExtendedItemGetXY(Asset, ShowImages=true) {
/**
* Loads the item extension properties
* @param {ExtendedItemOption[]} Options - An Array of type definitions for each allowed extended type. The first item
* @param {readonly ExtendedItemOption[]} Options - An Array of type definitions for each allowed extended type. The first item
* in the array should be the default option.
* @param {string} DialogKey - The dialog key for the message to display prompting the player to select an extended
* type
@ -140,13 +140,13 @@ function ExtendedItemLoad(Options, DialogKey, BaselineProperty=null) {
/**
* Draws the extended item type selection screen
* @param {ExtendedItemOption[]} Options - An Array of type definitions for each allowed extended type. The first item
* @param {readonly ExtendedItemOption[]} Options - An Array of type definitions for each allowed extended type. The first item
* in the array should be the default option.
* @param {string} DialogPrefix - The prefix to the dialog keys for the display strings describing each extended type.
* The full dialog key will be <Prefix><Option.Name>
* @param {number} [OptionsPerPage] - The number of options displayed on each page
* @param {boolean} [ShowImages=true] - Denotes whether images should be shown for the specific item
* @param {[number, number][]} [XYPositions] - An array with custom X & Y coordinates of the buttons
* @param {readonly [number, number][]} [XYPositions] - An array with custom X & Y coordinates of the buttons
* @returns {void} Nothing
*/
function ExtendedItemDraw(Options, DialogPrefix, OptionsPerPage, ShowImages=true, XYPositions=null) {
@ -332,7 +332,7 @@ function ExtendedItemGetButtonColor(C, Option, CurrentOption, Hover, IsSelected,
/**
* Handles clicks on the extended item type selection screen
* @param {ExtendedItemOption[]} Options - An Array of type definitions for each allowed extended type. The first item
* @param {readonly ExtendedItemOption[]} Options - An Array of type definitions for each allowed extended type. The first item
* in the array should be the default option.
* @param {number} [OptionsPerPage] - The number of options displayed on each page
* @param {boolean} [ShowImages=true] - Denotes whether images are shown for the specific item
@ -432,7 +432,7 @@ function ExtendedItemExit() {
/**
* Handler function for setting the type of an extended item
* @param {Character} C - The character wearing the item
* @param {ExtendedItemOption[]} Options - An Array of type definitions for each allowed extended type. The first item
* @param {readonly ExtendedItemOption[]} Options - An Array of type definitions for each allowed extended type. The first item
* in the array should be the default option.
* @param {ExtendedItemOption} Option - The selected type definition
* @returns {void} Nothing
@ -513,7 +513,7 @@ function ExtendedItemSetOption(C, item, previousProperty, newProperty, push=fals
/**
* Handler function called when an option on the type selection screen is clicked
* @param {Character} C - The character wearing the item
* @param {ExtendedItemOption[]} Options - An Array of type definitions for each allowed extended type. The first item
* @param {readonly ExtendedItemOption[]} Options - An Array of type definitions for each allowed extended type. The first item
* in the array should be the default option.
* @param {ExtendedItemOption} Option - The selected type definition
* @returns {void} Nothing
@ -703,7 +703,7 @@ function ExtendedItemMapChatTagToDictionaryEntry(C, asset, tag) {
* @param {Character} C - The target character
* @param {Asset} Asset - The asset for the typed item
* @param {string | null} Type - The type of the asse
* @param {EffectName[]} [Effects]
* @param {readonly EffectName[]} [Effects]
* @returns {InventoryIcon[]} - The inventory icons
*/
function ExtendItemGetIcons(C, Asset, Type=null, Effects=null) {

View file

@ -66,9 +66,8 @@ function LogDelete(DelLogName, DelLogGroup, Push) {
/**
* Deletes all log entries to starts with the name.
* @template {LogGroupType} T
* @param {LogNameType[T]} DelLogName - The name of the log
* @param {T} DelLogGroup - The name of the log's group
* @param {string} DelLogName - The name of the log
* @param {LogGroupType} DelLogGroup - The name of the log's group
* @param {boolean} [Push=true] - TRUE if we must push the log to the server
* @returns {void} - Nothing
*/
@ -144,7 +143,7 @@ function LogValue(QueryLogName, QueryLogGroup) {
/**
* Loads the account log.
* @param {LogRecord[]} NewLog - Existing logs received by the server
* @param {readonly LogRecord[]} NewLog - Existing logs received by the server
* @returns {void} - Nothing
*/
function LogLoad(NewLog) {

View file

@ -31,7 +31,7 @@ function InventoryAdd(C, NewItemName, NewItemGroup, Push) {
/**
* Adds multiple new items by group & name to the character inventory
* @param {Character} C - The character that gets the new items added to her inventory
* @param {Array.<{ Name: string, Group: AssetGroupName }>} NewItems - The new items to add
* @param {readonly { Name: string, Group: AssetGroupName }[]} NewItems - The new items to add
* @param {Boolean} [Push=true] - Set to TRUE to push to the server, pushed by default
*/
function InventoryAddMany(C, NewItems, Push) {
@ -133,7 +133,7 @@ function InventoryDeleteGroup(C, group, push) {
* Loads the current inventory for a character, can be loaded from an object of Name/Group or a compressed array using
* LZString
* @param {Character} C - The character on which we should load the inventory
* @param {Array|Record<AssetGroupName, string[]>} Inventory - An array of Name / Group of items to load
* @param {string | readonly ItemBundle[] | Partial<Record<AssetGroupName, readonly string[]>>} Inventory - An array of Name / Group of items to load
*/
function InventoryLoad(C, Inventory) {
if (Inventory == null) return;
@ -298,7 +298,7 @@ function InventoryPrerequisiteMessage(C, Prerequisite) {
* whose name matches one of the names in the provided list.
* @param {Character} C - The character for whom to check equipped items
* @param {AssetGroupName} ItemGroup - The name of the item group to check
* @param {String[]} ItemList - A list of item names to check against
* @param {readonly string[]} ItemList - A list of item names to check against
* @returns {boolean} - TRUE if the character has an item from the item list equipped in the named slot, FALSE
* otherwise
*/
@ -326,7 +326,7 @@ function InventoryDoesItemHavePrerequisite(C, ItemGroup, Prerequisite) {
* given groups to check.
* @param {Character} C - The character whose items should be checked
* @param {AssetGroupItemName} TargetGroup - The name of the group that should be checked for being blocked
* @param {AssetGroupName[]} GroupsToCheck - The name(s) of the groups whose items should be checked
* @param {readonly AssetGroupName[]} GroupsToCheck - The name(s) of the groups whose items should be checked
* @returns {boolean} - TRUE if the character has an item equipped in any of the given groups to check which blocks the
* target group, FALSE otherwise.
*/
@ -341,8 +341,8 @@ function InventoryDoItemsBlockGroup(C, TargetGroup, GroupsToCheck) {
* Prerequisite utility function to check whether the target group for the given character is exposed by all of the
* given groups to check.
* @param {Character} C - The character whose items should be checked
* @param {AssetGroupName} TargetGroup - The name of the group that should be checked for being exposed
* @param {AssetGroupName[]} GroupsToCheck - The name(s) of the groups whose items should be checked
* @param {AssetGroupItemName} TargetGroup - The name of the group that should be checked for being exposed
* @param {readonly AssetGroupName[]} GroupsToCheck - The name(s) of the groups whose items should be checked
* @returns {boolean} - FALSE if the character has an item equipped in ANY of the given groups to check that does not
* expose the target group. Returns TRUE otherwise.
*/
@ -357,7 +357,7 @@ function InventoryDoItemsExposeGroup(C, TargetGroup, GroupsToCheck) {
* Prerequisite utility function that returns TRUE if the given character has an item equipped in any of the named group
* slots.
* @param {Character} C - The character whose items should be checked
* @param {AssetGroupName[]} GroupList - The list of groups to check for items in
* @param {readonly AssetGroupName[]} GroupList - The list of groups to check for items in
* @returns {boolean} - TRUE if the character has any item equipped in any of the named groups, FALSE otherwise.
*/
function InventoryHasItemInAnyGroup(C, GroupList) {
@ -367,7 +367,7 @@ function InventoryHasItemInAnyGroup(C, GroupList) {
/**
* Check if there are any gags with prerequisites that block the new gag from being applied
* @param {Character} C - The character on which we check for prerequisites
* @param {string[]} BlockingPrereqs - The prerequisites we check for on lower gags
* @param {readonly string[]} BlockingPrereqs - The prerequisites we check for on lower gags
* @returns {string} - Returns the prerequisite message if the gag is blocked, or an empty string if not
*/
function InventoryPrerequisiteConflictingGags(C, BlockingPrereqs) {
@ -405,7 +405,7 @@ function InventoryPrerequisiteConflictingGags(C, BlockingPrereqs) {
* @param {Character} C - The character on which we check for prerequisites
* @param {Asset} asset - The asset for which prerequisites should be checked. Any item equipped in the asset's group
* will be ignored for the purposes of the prerequisite check.
* @param {string|string[]} [prerequisites=asset.Prerequisite] - An array of prerequisites or a string for a single
* @param {string | readonly string[]} [prerequisites=asset.Prerequisite] - An array of prerequisites or a string for a single
* prerequisite. If nothing is provided, the asset's default prerequisites will be used
* @param {boolean} [setDialog=true] - If TRUE, set the screen dialog message at the same time
* @returns {boolean} - TRUE if the item can be added to the character
@ -538,7 +538,7 @@ function InventoryCraft(Source, Target, GroupName, Craft, Refresh, ApplyColor=tr
/**
* Returns the number of items on a character with a specific property
* @param {Character} C - The character to validate
* @param {String} Property - The property to count
* @param {CraftingPropertyType} Property - The property to count
* @returns {Number} - The number of times the property is found
*/
function InventoryCraftCount(C, Property) {
@ -553,7 +553,7 @@ function InventoryCraftCount(C, Property) {
/**
* Returns TRUE if an item as the specified crafted property
* @param {Item} Item - The item to validate
* @param {String} Property - The property to check
* @param {CraftingPropertyType} Property - The property to check
* @returns {boolean} - TRUE if the property matches
*/
function InventoryCraftPropertyIs(Item, Property) {
@ -700,7 +700,7 @@ function InventoryWearCraft(Item, Craft) {
* @param {Character} C - The character that must wear the item
* @param {string} AssetName - The name of the asset to wear
* @param {AssetGroupName} AssetGroup - The name of the asset group to wear
* @param {string | string[]} [ItemColor] - The hex color of the item, can be undefined or "Default"
* @param {string | readonly string[]} [ItemColor] - The hex color of the item, can be undefined or "Default"
* @param {number} [Difficulty] - The difficulty, on top of the base asset difficulty, to assign to the item
* @param {number} [MemberNumber] - The member number of the character putting the item on - defaults to -1
* @param {CraftingItem} [Craft] - The crafting properties of the item
@ -760,7 +760,7 @@ function InventoryLocked(C, AssetGroup, CheckProperties) {
* be used
* @param {boolean} [Extend=true] - Whether or not to randomly extend the item (i.e. set the item type), provided it has
* an archetype that supports random extension
* @param {string[]} [AllowedAssets=null] - A list of assets from which one must be selected
* @param {readonly string[]} [AllowedAssets=null] - A list of assets from which one must be selected
* @param {boolean} [IgnoreRequirements=false] - If True, the group being blocked and prerequisites will not prevent the item being added.
* NOTE: Long-term this should be replaced with better checks before calling this function.
* @returns {void} - Nothing
@ -835,8 +835,8 @@ function InventoryRandomExtend(C, GroupName) {
* Select a random asset from a group, narrowed to the most preferable available options (i.e
* unblocked/visible/unlimited) based on their binary "rank"
* @param {Character} C - The character to pick the asset for
* @param {string} GroupName - The asset group to pick the asset from. Set to an empty string to not filter by group.
* @param {Asset[]} [AllowedAssets] - Optional parameter: A list of assets from which one can be selected. If not provided,
* @param {AssetGroupName} GroupName - The asset group to pick the asset from. Set to an empty string to not filter by group.
* @param {readonly Asset[]} [AllowedAssets] - Optional parameter: A list of assets from which one can be selected. If not provided,
* the full list of all assets is used.
* @param {boolean} [IgnorePrerequisites=false] - If True, skip the step to check whether prerequisites are met
* NOTE: Long-term this should be replaced with better checks before calling this function.
@ -942,12 +942,11 @@ function InventoryRemove(C, AssetGroup, Refresh) {
/**
* Returns TRUE if the body area (Asset Group) for a character is blocked and cannot be used
* @param {Character} C - The character on which we validate the group
* @param {AssetGroupName} [G] - The name of the asset group (body area), defaults to `C.FocusGroup`
* @param {AssetGroupItemName} [GroupName] - The name of the asset group (body area), defaults to `C.FocusGroup`
* @param {boolean} [Activity=false] - if TRUE check if activity is allowed on the asset group
* @returns {boolean} - TRUE if the group is blocked
*/
function InventoryGroupIsBlockedForCharacter(C, G, Activity) {
let GroupName = /** @type {AssetGroupItemName} */(G);
function InventoryGroupIsBlockedForCharacter(C, GroupName, Activity) {
if (Activity == null) Activity = false;
// Default to characters focused group
@ -1032,7 +1031,7 @@ function InventoryGroupIsBlockedByOwnerRule(C, GroupName) {
* Returns TRUE if the body area (Asset Group) for a character is blocked and cannot be used
* Similar to InventoryGroupIsBlockedForCharacter but also blocks groups on all characters if the player is enclosed.
* @param {Character} C - The character on which we validate the group
* @param {AssetGroupName} [GroupName] - The name of the asset group (body area)
* @param {AssetGroupItemName} [GroupName] - The name of the asset group (body area)
* @param {boolean} [Activity] - if TRUE check if activity is allowed on the asset group
* @returns {boolean} - TRUE if the group is blocked
*/
@ -1089,7 +1088,7 @@ function InventoryItemIsPickable(Item) {
/**
* Returns the value of a given property of an appearance item, prioritizes the Property object.
* @param {Item} Item - The appearance item to scan
* @param {string} PropertyName - The property name to get.
* @param {keyof ItemProperties | keyof Asset | keyof AssetGroup} PropertyName - The property name to get.
* @param {boolean} [CheckGroup=false] - Whether or not to fall back to the item's group if the property is not found on
* Property or Asset.
* @returns {any} - The value of the requested property for the given item. Returns undefined if the property or the
@ -1106,7 +1105,7 @@ function InventoryGetItemProperty(Item, PropertyName, CheckGroup=false) {
/**
* Apply an item's expression trigger to a character if able
* @param {Character} C - The character to update
* @param {ExpressionTrigger[]} expressions - The expression change to apply to each group
* @param {readonly ExpressionTrigger[]} expressions - The expression change to apply to each group
*/
function InventoryExpressionTriggerApply(C, expressions) {
const expressionsAllowed = C.ID === 0 || C.AccountName.startsWith("Online-") ? C.OnlineSharedSettings.ItemsAffectExpressions : true;
@ -1179,7 +1178,7 @@ function InventoryCharacterHasLockedRestraint(C) {
/**
*
* @param {Character} C - The character to scan
* @param {String} LockName - The type of lock to check for
* @param {AssetLockType} LockName - The type of lock to check for
* @returns {Boolean} - Returns TRUE if any item has the specified lock locked onto it
*/
function InventoryCharacterIsWearingLock(C, LockName) {
@ -1249,9 +1248,9 @@ function InventoryDoesItemAllowLock(item) {
/**
* Applies a lock to an appearance item of a character
* @param {Character} C - The character on which the lock must be applied
* @param {Item|AssetGroupName} Item - The item from appearance to lock, or the group
* @param {Item|string} Lock - The asset of the lock or the name of the lock asset
* @param {number|string} [MemberNumber] - The member number to put on the lock, or message to show
* @param {Item|AssetGroupName} Item - The item from appearance to lock
* @param {Item|AssetLockType} Lock - The asset of the lock or the name of the lock asset
* @param {null|number|string} [MemberNumber] - The member number to put on the lock, or message to show
* @param {boolean} [Update=true] - Whether or not to update the character
*/
function InventoryLock(C, Item, Lock, MemberNumber, Update = true) {
@ -1274,7 +1273,7 @@ function InventoryLock(C, Item, Lock, MemberNumber, Update = true) {
/**
* Unlocks an item and removes all related properties
* @param {Character} C - The character on which the item must be unlocked
* @param {Item|AssetGroupName} Item - The item from appearance to unlock
* @param {Item|AssetGroupItemName} Item - The item from appearance to unlock
*/
function InventoryUnlock(C, Item) {
if (typeof Item === 'string') Item = InventoryGet(C, Item);
@ -1317,7 +1316,7 @@ function InventoryFullLockRandom(C, FromOwner) {
/**
* Applies a specific lock on each character items that can be locked
* @param {Character} C - The character on which the items must be locked
* @param {String} LockType - The lock type to apply
* @param {AssetLockType} LockType - The lock type to apply
*/
function InventoryFullLock(C, LockType) {
if ((C != null) && (LockType != null))
@ -1351,7 +1350,7 @@ function InventoryConfiscateRemote() {
* Returns TRUE if the item is worn by the character
* @param {Character} C - The character to scan
* @param {String} AssetName - The asset / item name to scan
* @param {String} AssetGroup - The asset group name to scan
* @param {AssetGroupName} AssetGroup - The asset group name to scan
* @returns {Boolean} - TRUE if item is worn
*/
function InventoryIsWorn(C, AssetName, AssetGroup) {
@ -1372,7 +1371,7 @@ function InventoryIsWorn(C, AssetName, AssetGroup) {
function InventoryTogglePermission(Item, Type, Worn) {
const onExtreme = Player.GetDifficulty() >= 3;
const blockAllowed = !Worn && !onExtreme;
const limitedAllowed = !Worn && (!onExtreme || MainHallStrongLocks.includes(Item.Asset.Name));
const limitedAllowed = !Worn && (!onExtreme || MainHallStrongLocks.includes(/** @type {AssetLockType} */(Item.Asset.Name)));
const removeFromPermissions = (B) => B.Name != Item.Asset.Name || B.Group != Item.Asset.Group.Name || B.Type != Type;
const permissionItem = { Name: Item.Asset.Name, Group: Item.Asset.Group.Name, Type: Type };
@ -1397,7 +1396,7 @@ function InventoryTogglePermission(Item, Type, Worn) {
* Returns TRUE if a specific item / asset is blocked by the character item permissions
* @param {Character} C - The character on which we check the permissions
* @param {string} AssetName - The asset / item name to scan
* @param {string} AssetGroup - The asset group name to scan
* @param {AssetGroupName} AssetGroup - The asset group name to scan
* @param {string} [AssetType] - The asset type to scan
* @returns {boolean} - TRUE if asset / item is blocked
*/
@ -1414,7 +1413,7 @@ function InventoryIsPermissionBlocked(C, AssetName, AssetGroup, AssetType) {
* Returns TRUE if a specific item / asset is favorited by the character item permissions
* @param {Character} C - The character on which we check the permissions
* @param {string} AssetName - The asset / item name to scan
* @param {string} AssetGroup - The asset group name to scan
* @param {AssetGroupName} AssetGroup - The asset group name to scan
* @param {string} [AssetType] - The asset type to scan
* @returns {boolean} - TRUE if asset / item is a favorite
*/
@ -1430,7 +1429,7 @@ function InventoryIsFavorite(C, AssetName, AssetGroup, AssetType) {
* Returns TRUE if a specific item / asset is limited by the character item permissions
* @param {Character} C - The character on which we check the permissions
* @param {string} AssetName - The asset / item name to scan
* @param {string} AssetGroup - The asset group name to scan
* @param {AssetGroupName} AssetGroup - The asset group name to scan
* @param {string} [AssetType] - The asset type to scan
* @returns {boolean} - TRUE if asset / item is limited
*/
@ -1460,7 +1459,7 @@ function InventoryCheckLimitedPermission(C, Item, ItemType) {
* Returns TRUE if a specific item / asset is blocked or limited for the player by the character item permissions
* @param {Character} C - The character on which we check the permissions
* @param {Item} Item - The item being interacted with
* @param {String} [ItemType] - The asset type to scan
* @param {string | null} [ItemType] - The asset type to scan
* @returns {Boolean} - Returns TRUE if the item cannot be used
*/
function InventoryBlockedOrLimited(C, Item, ItemType) {
@ -1508,7 +1507,7 @@ function InventoryStringify(C) {
/**
* Returns TRUE if the inventory category is blocked in the current chat room
* @param {array} Category - An array of string containing all the categories to validate
* @param {readonly string[]} Category - An array of string containing all the categories to validate
* @return {boolean} - TRUE if it's blocked
*/
function InventoryChatRoomAllow(Category) {

View file

@ -165,7 +165,7 @@ function ModularItemCreateExitFunction(data) {
/**
* Parse and convert the passed item modules inplace. Returns the originally passed object.
* @param {ModularItemModuleBase[]} Modules - An object describing a single module for a modular item.
* @param {readonly ModularItemModuleBase[]} Modules - An object describing a single module for a modular item.
* @returns {ModularItemModule[]} - The updated modules; same object as `Modules`.
*/
function ModularItemUpdateModules(Modules) {
@ -309,7 +309,7 @@ function ModularItemMapOptionToButtonDefinition(option, module, { dialogOptionPr
/**
* Draws a module screen from the provided button definitions and modular item data.
* @param {string} moduleName - The name of the module whose page is being drawn
* @param {ModularItemButtonDefinition[]} buttonDefinitions - A list of button definitions to draw
* @param {readonly ModularItemButtonDefinition[]} buttonDefinitions - A list of button definitions to draw
* @param {ModularItemData} data - The modular item's data
* @returns {void} - Nothing
*/
@ -516,7 +516,7 @@ function ModularItemParseCurrent({ asset, modules }, type=null) {
/**
* Merges all of the selected module options for a modular item into a single Property object to set on the item
* @param {ModularItemData} data - The modular item's data
* @param {number[]} moduleValues - The numeric values representing the current options for each module
* @param {readonly number[]} moduleValues - The numeric values representing the current options for each module
* @param {ItemProperties|null} BaselineProperty - Initial properties
* @returns {ItemProperties} - A property object created from combining each module of the modular item
*/
@ -603,7 +603,7 @@ function ModularItemMergeOverrideHeight(currentValue, newValue) {
/**
* Generates the type string for a modular item from its modules and their current values.
* @param {ModularItemModule[]} modules - The modules array for the modular item
* @param {number[]} [values] - The numeric values representing the current options for each module
* @param {readonly number[]} [values] - The numeric values representing the current options for each module
* @returns {string} - A string type generated from the selected option values for each module
*/
function ModularItemConstructType(modules, values) {
@ -699,8 +699,8 @@ function ModularItemSetType(module, index, data) {
* Sets a modular item's type and properties to the option provided.
* @param {Character} C - The character on whom the item is equipped
* @param {Item} Item - The item whose type to set
* @param {number[]} previousModuleValues - The previous module values
* @param {number[]} newModuleValues - The new module values
* @param {readonly number[]} previousModuleValues - The previous module values
* @param {readonly number[]} newModuleValues - The new module values
* @param {ModularItemData} data - The modular item data
* @param {boolean} [push] - Whether or not appearance updates should be persisted (only applies if the character is the
* player) - defaults to false.
@ -846,6 +846,7 @@ function ModularItemGenerateLayerAllowTypes(layer, data) {
// When option 0 is an allowed module, it means the undefined/null type is allowed.
if (allowedModuleCombinations.find(arr => arr.find(combo => combo[1] === 0))) {
// @ts-ignore: ignore `readonly` while still building the asset
layer.AllowTypes.push("");
}
}
@ -862,6 +863,7 @@ function ModularItemGenerateValidationProperties(data) {
asset.Extended = true;
asset.AllowType = ModularItemGenerateTypeList(data);
asset.AllowEffect = Array.isArray(asset.AllowEffect) ? asset.AllowEffect.slice() : [];
// @ts-ignore: ignore `readonly` while still building the asset
CommonArrayConcatDedupe(asset.AllowEffect, asset.Effect);
asset.AllowBlock = Array.isArray(asset.Block) ? asset.Block.slice() : [];
asset.AllowHide = Array.isArray(asset.Hide) ? asset.Hide.slice() : [];
@ -869,9 +871,13 @@ function ModularItemGenerateValidationProperties(data) {
for (const module of modules) {
for (const {Property} of module.Options) {
if (Property) {
// @ts-ignore: ignore `readonly` while still building the asset
if (Property.Effect) CommonArrayConcatDedupe(asset.AllowEffect, Property.Effect);
// @ts-ignore: ignore `readonly` while still building the asset
if (Property.Block) CommonArrayConcatDedupe(asset.AllowBlock, Property.Block);
// @ts-ignore: ignore `readonly` while still building the asset
if (Property.Hide) CommonArrayConcatDedupe(asset.AllowHide, Property.Hide);
// @ts-ignore: ignore `readonly` while still building the asset
if (Property.HideItem) CommonArrayConcatDedupe(asset.AllowHideItem, Property.HideItem);
if (Property.Tint && Array.isArray(Property.Tint) && Property.Tint.length > 0) asset.AllowTint = true;
}

View file

@ -2,7 +2,7 @@
/**
* List for all possible pairs of NPC traits. A pair defines opposites.
* @constant
* @type {string[][]}
* @type {[string, string][]}
*/
var NPCTrait = [
["Dominant", "Submissive"],
@ -65,7 +65,7 @@ function NPCTraitReverse(Trait) {
/**
* Returns the weight value of the specified option (The higher the value, the higher the chances the option will be picked, an opposite trait will always result as an option that's not picked)
* @param {string} Dialog - Specified dialog line with the affecting traits.
* @param {NPCTrait[]} NPCTrait - List of traits of the NPC.
* @param {readonly NPCTrait[]} NPCTrait - List of traits of the NPC.
* @returns {number} - Weight of the dialog option
*/
function NPCTraitGetOptionValue(Dialog, NPCTrait) {

View file

@ -2,7 +2,7 @@
/**
* An enum for the events in the game that notifications can be raised for
* @enum {string}
* @type {{ CHATMESSAGE: "ChatMessage", CHATJOIN: "ChatJoin", BEEP: "Beep", DISCONNECT: "Disconnect", TEST: "Test", LARP: "Larp" }}
*/
const NotificationEventType = {
CHATMESSAGE: "ChatMessage",
@ -34,13 +34,6 @@ const NotificationAudioType = {
REPEAT: 2,
};
/**
* An object defining the components of the player's settings for a particular notification event
* @typedef {object} NotificationSetting
* @property {NotificationAlertType} AlertType - The selected type of notification alert to use
* @property {NotificationAudioType} Audio - The selected audio setting to apply
*/
/**
* A class to track the state of each notification event type and handle actions based on the player's settings
*/
@ -59,7 +52,7 @@ class NotificationEventHandler {
/**
* Raise a notification
* @param {object} data - Data relating to the event that can be passed into a popup
* @param {NotificationData} data - Data relating to the event that can be passed into a popup
* @returns {void} - Nothing
*/
raise(data) {
@ -88,7 +81,7 @@ class NotificationEventHandler {
/**
* Raise a popup notification
* @param {any} data - Data relating to the event passed into the popup
* @param {NotificationData} data - Data relating to the event passed into the popup
* @returns {void} - Nothing
*/
raisePopup(data) {
@ -169,8 +162,11 @@ class NotificationEventHandler {
}
}
/** @type {Record<NotificationEventType, NotificationEventHandler>} */
let NotificationEventHandlers;
/** @type {NotificationAlertType[]} */
var NotificationAlertTypeList = [];
/** @type {NotificationAudioType[]} */
var NotificationAudioTypeList = [];
/**
@ -179,6 +175,7 @@ var NotificationAudioTypeList = [];
*/
function NotificationLoad() {
// Create the list of event handlers
// @ts-ignore: record values are initialized in subsequent `NotificationEventHandlerSetup` ca;;s
NotificationEventHandlers = {};
NotificationEventHandlerSetup(NotificationEventType.CHATMESSAGE, Player.NotificationSettings.ChatMessage);
NotificationEventHandlerSetup(NotificationEventType.CHATJOIN, Player.NotificationSettings.ChatJoin);
@ -208,7 +205,7 @@ function NotificationEventHandlerSetup(eventType, setting) {
/**
* Create a new notification
* @param {NotificationEventType} eventType - The type of event that occurred
* @param {object} [data={}] - Data relating to the event that can be passed into a popup
* @param {NotificationData} [data={}] - Data relating to the event that can be passed into a popup
* @returns {void} - Nothing
*/
function NotificationRaise(eventType, data = {}) {
@ -239,7 +236,7 @@ function NotificationResetAll() {
/**
* Returns whether popup notifications are permitted
* @param {NotificationEventType} eventType - The type of event that occurred
* @param {object} [data={}] - Data relating to the event that can be passed into a popup
* @param {NotificationData} [data={}] - Data relating to the event that can be passed into a popup
* @returns {boolean} - Whether popups can appear
*/
function NotificationPopupsEnabled(eventType, data) {

View file

@ -1,10 +1,11 @@
"use strict";
/** @type {ReputationType[]} */
var ReputationValidReputations = ["Dominant", "Kidnap", "ABDL", "Gaming", "Maid", "LARP", "Asylum", "Gambling", "HouseMaiestas", "HouseVincula", "HouseAmplector", "HouseCorporis"];
/**
* Alters a given reputation value for the player
* @param {string} RepType - The name/type of the reputation to alter
* @param {ReputationType} RepType - The name/type of the reputation to alter
* @param {number} RepValue - Reputation to add/subtract to the current reputation value.
* @param {boolean} [Push=true] - Pushes the reputation to the server if TRUE
* @returns {void} - Nothing
@ -47,7 +48,7 @@ function ReputationChange(RepType, RepValue, Push) {
/**
* Loads the reputation data from the server
* @param {Array.<{Type: string, Value: number}>} NewRep - The array of reputation-value pairs to load for the current player
* @param {readonly Reputation[]} NewRep - The array of reputation-value pairs to load for the current player
* @returns {void} - Nothing
*/
function ReputationLoad(NewRep) {
@ -77,7 +78,7 @@ function ReputationGet(RepType) {
/**
* Returns a specific reputation value for a given character
* @param {Character} C - Character to get the reputation for.
* @param {string} RepType - Type/name of the reputation to get the value of.
* @param {ReputationType} RepType - Type/name of the reputation to get the value of.
* @returns {number} - Returns the value of the reputation. It can range from 100 to -100, and it defaults to 0 if the given character never earned this type of reputation before.
*/
function ReputationCharacterGet(C, RepType) {
@ -90,7 +91,7 @@ function ReputationCharacterGet(C, RepType) {
/**
* Alter the reputation progress by a factor. The higher the rep, the slower it gets, a reputation is easier to break than to build. Takes the cheater version factor into account.
* @param {string} RepType - Type/name of the reputation
* @param {ReputationType} RepType - Type/name of the reputation
* @param {number|string} Value - Value of the reputation change before the factor is applied
* @return {void} - Nothing
*/

View file

@ -2,7 +2,7 @@
* A map containing appearance item diffs, keyed according to the item group. Used to compare and validate before/after
* for appearance items.
* @typedef AppearanceDiffMap
* @type {Record.<string, Item[]>}
* @type {Partial<Record<AssetGroupName, Item[]>>}
*/
"use strict";
@ -347,7 +347,7 @@ function ServerPlayerRelationsSync() {
/**
* Prepares an appearance bundle so we can push it to the server. It minimizes it by keeping only the necessary
* information. (Asset name, group name, color, properties and difficulty)
* @param {Item[]} Appearance - The appearance array to bundle
* @param {readonly Item[]} Appearance - The appearance array to bundle
* @returns {AppearanceBundle} - The appearance bundle created from the given appearance array
*/
function ServerAppearanceBundle(Appearance) {
@ -370,7 +370,7 @@ function ServerAppearanceBundle(Appearance) {
* Loads the appearance assets from a server bundle that only contains the main info (no asset) and validates their
* properties to prevent griefing and respecting permissions in multiplayer
* @param {Character} C - Character for which to load the appearance
* @param {string} AssetFamily - Family of assets used for the appearance array
* @param {IAssetFamily} AssetFamily - Family of assets used for the appearance array
* @param {AppearanceBundle} Bundle - Bundled appearance
* @param {number} [SourceMemberNumber] - Member number of the user who triggered the change
* @param {boolean} [AppearanceFull=false] - Whether or not the appearance should be assigned to an NPC's AppearanceFull
@ -417,8 +417,8 @@ function ServerAppearanceLoadFromBundle(C, AssetFamily, Bundle, SourceMemberNumb
/**
* Builds a diff map for comparing changes to a character's appearance, keyed by asset group name
* @param {string} assetFamily - The asset family of the appearance
* @param {Item[]} appearance - The current appearance to compare against
* @param {IAssetFamily} assetFamily - The asset family of the appearance
* @param {readonly Item[]} appearance - The current appearance to compare against
* @param {AppearanceBundle} bundle - The new appearance bundle
* @returns {AppearanceDiffMap} - An appearance diff map representing the changes that have been made to the character's
* appearance
@ -442,7 +442,7 @@ function ServerBuildAppearanceDiff(assetFamily, appearance, bundle) {
/**
* Maps a bundled appearance item, as stored on the server and used for appearance update messages, into a full
* appearance item, as used by the game client
* @param {string} assetFamily - The asset family of the appearance item
* @param {IAssetFamily} assetFamily - The asset family of the appearance item
* @param {ItemBundle} item - The bundled appearance item
* @returns {Item} - A full appearance item representation of the provided bundled appearance item
*/
@ -464,8 +464,8 @@ function ServerBundledItemToAppearanceItem(assetFamily, item) {
/**
* Parses an item color, based on the allowed colorable layers on an asset, and the asset's color schema
* @param {Asset} asset - The asset on which the color is set
* @param {string|string[]} color - The color value to parse
* @param {string[]} schema - The color schema to validate against
* @param {string | readonly string[]} color - The color value to parse
* @param {readonly string[]} schema - The color schema to validate against
* @returns {string|string[]} - A parsed valid item color
*/
function ServerParseColor(asset, color, schema) {
@ -480,7 +480,7 @@ function ServerParseColor(asset, color, schema) {
/**
* Populates an appearance diff map with any required items, to ensure that all asset groups are present that need to
* be.
* @param {string} assetFamily - The asset family for the appearance
* @param {IAssetFamily} assetFamily - The asset family for the appearance
* @param {AppearanceDiffMap} diffMap - The appearance diff map to populate
* @returns {void} - Nothing
*/
@ -513,7 +513,7 @@ function ServerAddRequiredAppearance(assetFamily, diffMap) {
/**
* Validates and returns a color against a color schema
* @param {string} Color - The color to validate
* @param {string[]} Schema - The color schema to validate against (a list of accepted Color values)
* @param {readonly string[]} Schema - The color schema to validate against (a list of accepted Color values)
* @returns {string} - The color if it is a valid hex color string or part of the color schema, or the default color
* from the color schema otherwise
*/

View file

@ -5,11 +5,13 @@ var SkillModifierMin = -10;
var SkillLevelMaximum = 10;
var SkillLevelMinimum = 0;
var SkillBondageRatio = 1;
/** @type {SkillType[]} */
var SkillValidSkills = ["Bondage", "SelfBondage", "LockPicking", "Evasion", "Willpower", "Infiltration", "Dressage"];
/**
* When the player progresses in a skill. Also validates the values to make sure they are within the proper ranges once changed. (level 0-10, progress 0-100)
* @param {string} SkillType - Name of the skill to set the value for
* @param {SkillType} SkillType - Name of the skill to set the value for
* @param {number} SkillLevel - Level to set for the given skill
* @param {number} SkillProgress - Progress to set for the given skill
* @param {boolean} [Push=true] - Pushes the skills to the server if TRUE
@ -52,7 +54,7 @@ function SkillChange(SkillType, SkillLevel, SkillProgress, Push) {
/**
* Loads the skill data from the server on login
* @param {Skill[]} NewSkill - The player skills array sent by the server
* @param {readonly Skill[]} NewSkill - The player skills array sent by the server
* @returns {void} - Nothing
*/
function SkillLoad(NewSkill) {
@ -73,7 +75,7 @@ function SkillLoad(NewSkill) {
/**
* Get a specific skill level from a character WITH the current modifier applied
* @param {Character} C - Character for which we want to query a skill
* @param {string} SkillType - Name of the skill to get the value of
* @param {SkillType} SkillType - Name of the skill to get the value of
* @returns {number} - Current level for the given skill.
*/
function SkillGetLevel(C, SkillType) {
@ -108,7 +110,7 @@ function SkillGetLevel(C, SkillType) {
/**
* Get a specific skill level from a character WITHOUT the modifier applied
* @param {Character} C - Character for which we want to query a skill
* @param {string} SkillType - Name of the skill to get the value of
* @param {SkillType} SkillType - Name of the skill to get the value of
* @returns {number} - Current real level for the given skill.
*/
function SkillGetLevelReal(C, SkillType) {
@ -121,7 +123,7 @@ function SkillGetLevelReal(C, SkillType) {
/**
* Get a specific skill progress from a character
* @param {Character} C - Character for which we want to query a skill
* @param {string} SkillType - Name of the skill to get the progress of
* @param {SkillType} SkillType - Name of the skill to get the progress of
* @returns {number} - Current progress for the given skill.
*/
function SkillGetProgress(C, SkillType) {
@ -133,7 +135,7 @@ function SkillGetProgress(C, SkillType) {
/**
* Add progress to a skill, the skill progresses slower for each level, takes into account cheaters version.
* @param {string} SkillType - Name of the skill to add progress to
* @param {SkillType} SkillType - Name of the skill to add progress to
* @param {number} SkillProgress - Progress to be made before the ratios are applied
* @returns {void} - Nothing
*/
@ -161,7 +163,7 @@ function SkillProgress(SkillType, SkillProgress) {
/**
* Sets the ratio % of a skill that's going to be used by the player
* @param {string} SkillType - Name of the skill to get the value of
* @param {SkillType} SkillType - Name of the skill to get the value of
* @param {number} Ratio - The ratio to set for a given skill (0 to 1)
* @param {boolean} [Push=true] - Pushes the skills to the server if TRUE
*/
@ -178,7 +180,7 @@ function SkillSetRatio(SkillType, Ratio, Push) {
/**
* Gets the ratio % of effectiveness of a skill for the player
* @param {string} SkillType - Name of the skill to get the value of
* @param {SkillType} SkillType - Name of the skill to get the value of
* @returns {number} - The current active ratio for the given skill
*/
function SkillGetRatio(SkillType) {
@ -193,7 +195,7 @@ function SkillGetRatio(SkillType) {
/**
* Gets a skill level with the current ratio applied to it, if the current skill has a % modifier.
* @param {string} SkillType - Name of the skill to get the value of
* @param {SkillType} SkillType - Name of the skill to get the value of
* @returns {number} - The skill level with the ratio % applied
*/
function SkillGetWithRatio(SkillType) {

View file

@ -5,7 +5,7 @@ const chineseRandomGarbledSound = ['啊', '恩', '咕', '唔', '哈', '嗷', '
/**
* A lookup mapping the gag effect names to their corresponding gag level numbers.
* @type {Object.<string,number>}
* @type {Partial<Record<EffectName, number>>}
* @constant
*/
var SpeechGagLevelLookup = {
@ -33,7 +33,7 @@ function SpeechFullEmote(D) {
/**
* Returns the gag level corresponding to the given effect array, or 0 if the effect array contains no gag effects
* @param {string[]} Effect - The effect to lookup the gag level for
* @param {EffectName[]} Effect - The effect to lookup the gag level for
* @return {number} - The gag level corresponding to the given effects
*/
function SpeechGetEffectGagLevel(Effect) {
@ -47,7 +47,7 @@ function SpeechGetEffectGagLevel(Effect) {
* - Item.Asset.Effect
* - Item.Asset.Group.Effect
* @param {Character} C - The character, whose assets are used for the check
* @param {AssetGroupName[]} AssetGroups - The name of the asset groups to look through
* @param {readonly AssetGroupItemName[]} AssetGroups - The name of the asset groups to look through
* @returns {number} - Returns the total gag effect of the character's assets
*/
function SpeechGetGagLevel(C, AssetGroups) {
@ -107,7 +107,7 @@ function SpeechGarble(C, CD, NoDeaf=false) {
* @param {number} b - seed 2
* @param {number} c - seed 3
* @param {number} d - seed 4
* @returns {function} - The function where it could be used to do PRNG magic.
* @returns {() => number} - The function where it could be used to do PRNG magic.
*/
function sfc32(a, b, c, d) {
return function() {
@ -129,8 +129,8 @@ function sfc32(a, b, c, d) {
* (This implementation is needed because dialog refreshes every frame, we have to generate garbled text that are the same.)
* (Otherwise it will just keep flashing and changing the text.)
*
* @param {*} seed - The seed to generate random numbers.
* @returns {function} - The function where it could be used to do PRNG magic.
* @param {string} seed - The seed to generate random numbers.
* @returns {() => number} - The function where it could be used to do PRNG magic.
*/
function randomSeeding(seed) {
for (var i = 0, h = 1779033703 ^ seed.length; i < seed.length; i++) {
@ -290,9 +290,10 @@ function isAccentedOrLatinCharacter(character) {
* The core of the speech garble function, usable without being tied to a specific character
* @param {number} GagEffect - The gag level of the speech
* @param {string} CD - The character's dialog to alter
* @param {boolean} IgnoreOOC
* @return {string} - Garbled text
*/
function SpeechGarbleByGagLevel(GagEffect, CD, IgnoreOOC) {
function SpeechGarbleByGagLevel(GagEffect, CD, IgnoreOOC=false) {
// Variables to build the new string and check if we are in a parentheses
var NS = "";
@ -649,7 +650,7 @@ function SpeechBabyTalk(C, CD) {
* Used as part of sensory-deprivation processing.
*
* @param {string} msg
* @param {Character[]} characters
* @param {readonly Character[]} characters
*/
function SpeechAnonymize(msg, characters) {
const names = [];

View file

@ -59,7 +59,9 @@ class TextCache {
this.path = path;
this.warn = warn;
this.language = TranslationLanguage;
/** @type {Record<string, string>} */
this.cache = {};
/** @type {((cache?: TextCache) => void)[]} */
this.rebuildListeners = [];
this.loaded = false;
this.buildCache();
@ -85,7 +87,7 @@ class TextCache {
* Adds a callback function as a rebuild listener. Rebuild listeners will
* be called whenever the cache has completed a rebuild (either after
* initial construction, or after a language change).
* @param {Function} callback - The callback to register
* @param {(cache?: TextCache) => void} callback - The callback to register
* @param {boolean} [immediate] - Whether or not the callback should be called on registration
* @returns {Function} - A callback function which can be used to unsubscribe the added listener
*/

View file

@ -52,20 +52,21 @@ function TimerInventoryRemove() {
// Cycles through all items items for all offline characters (player + NPC)
for (let C = 0; C < Character.length; C++)
if (Character[C].IsPlayer() || Character[C].IsNpc())
for (let A = 0; A < Character[C].Appearance.length; A++)
if ((Character[C].Appearance[A].Property != null) && (Character[C].Appearance[A].Property.RemoveTimer != null))
if ((typeof Character[C].Appearance[A].Property.RemoveTimer == "number") && (Character[C].Appearance[A].Property.RemoveTimer <= CurrentTime)) {
const Lock = InventoryGetLock(Character[C].Appearance[A]);
const ShouldRemoveItem = Character[C].Appearance[A].Property.RemoveItem;
for (let A = 0; A < Character[C].Appearance.length; A++) {
const item = Character[C].Appearance[A];
if ((item.Property != null) && (item.Property.RemoveTimer != null))
if ((typeof item.Property.RemoveTimer == "number") && (item.Property.RemoveTimer <= CurrentTime)) {
const Lock = InventoryGetLock(item);
const ShouldRemoveItem = item.Property.RemoveItem;
// Remove any lock or timer
ValidationDeleteLock(Character[C].Appearance[A].Property, false);
ValidationDeleteLock(item.Property, false);
// If we're removing a lock and we're in a chatroom, send a chatroom message
if (Lock && ServerPlayerIsInChatRoom()) {
const Dictionary = new DictionaryBuilder()
.destinationCharacterName(C)
.destinationCharacterName(Character[C])
.focusGroup(Character[C].Appearance[1].Asset.Group.Name)
.asset(Lock.Asset, "LockName")
.build();
@ -73,10 +74,11 @@ function TimerInventoryRemove() {
}
// If we must remove the linked item from the character or the facial expression
if (ShouldRemoveItem && Character[C].Appearance[A].Asset.Group.Category === "Item")
InventoryRemove(Character[C], Character[C].Appearance[A].Asset.Group.Name);
else if (Character[C].Appearance[A].Asset.Group.AllowExpression != null)
CharacterSetFacialExpression(Character[C], Character[C].Appearance[A].Asset.Group.Name, null);
const group = item.Asset.Group;
if (ShouldRemoveItem && group.IsItem())
InventoryRemove(Character[C], group.Name);
else if (group.IsAppearance() && group.AllowExpression != null)
CharacterSetFacialExpression(Character[C], group.Name, null);
else
CharacterRefresh(Character[C]);
@ -86,13 +88,14 @@ function TimerInventoryRemove() {
return;
}
}
}
/**
* Sets a remove timer in seconds for a specific item part / body part
* @param {Character} C - Character for which we are removing an item
* @param {string} AssetGroup - Group targeted by the removal
* @param {AssetGroupName} AssetGroup - Group targeted by the removal
* @param {number} Timer - Seconds it takes to remove the item
* @returns {void} - Nothing
*/
@ -253,7 +256,7 @@ function TimerProcess(Timestamp) {
/**
* Returns a string of the time remaining on a given timer (Hours, minutes, seconds)
* @param {number} s - Time to convert to a string in ms
* @Returns - The time string in the HH:MM:SS format
* @returns {string} - The time string in the HH:MM:SS format
*/
function TimermsToTime(s) {

View file

@ -783,7 +783,7 @@ function TranslationParseTXT(str) {
/**
* Translates a string to another language from the array, the translation is always the one right after the english line
* @param {string} S - The original english string to translate
* @param {string[]} T - The active translation dictionary
* @param {readonly string[]} T - The active translation dictionary
* @param {string} CharacterName - Name of the character if it is required to replace it within the string.
* @returns {string} - The translated string
*/
@ -800,7 +800,7 @@ function TranslationString(S, T, CharacterName) {
/**
* Translates a character dialog from the specified array
* @param {Character} C - The character for which we need to translate the dialog array.
* @param {string[]} T - The active translation dictionary
* @param {readonly string[]} T - The active translation dictionary
* @returns {void} - Nothing
*/
function TranslationDialogArray(C, T) {
@ -812,8 +812,8 @@ function TranslationDialogArray(C, T) {
/**
* Translates a set of tags. Rerenders the login message when on the login page.
* @param {Array.<{Tag: string, Value: string}>} S - Array of current tag-value pairs
* @param {string[]} T - The active translation dictionary
* @param {readonly { Tag: string, Value: string }[]} S - Array of current tag-value pairs
* @param {readonly string[]} T - The active translation dictionary
* @returns {void} - Nothing
*/
function TranslationTextArray(S, T) {
@ -857,7 +857,7 @@ function TranslationDialog(C) {
/**
* Translate an array of tags in the current selected language
* @param {Array.<{Tag: string, Value: string}>} Text - Array of current tag-value pairs
* @param {readonly {Tag: string, Value: string}[]} Text - Array of current tag-value pairs
* @returns {void} - Nothing
*/
function TranslationText(Text) {
@ -900,7 +900,7 @@ function TranslationAssetProcess(T) {
/**
* Translates the description of the assets and groups of an asset family
* @param {string} Family - Name of the asset family to translate
* @param {IAssetFamily} Family - Name of the asset family to translate
* @returns {void} - Nothing
*/
function TranslationAsset(Family) {

View file

@ -254,6 +254,7 @@ function TypedItemGenerateAllowType({ asset, options }) {
function TypedItemGenerateAllowEffect({asset, options}) {
asset.AllowEffect = Array.isArray(asset.Effect) ? asset.Effect.slice() : [];
for (const option of options) {
// @ts-ignore: ignore `readonly` while still building the asset
CommonArrayConcatDedupe(asset.AllowEffect, option.Property.Effect);
}
}
@ -266,6 +267,7 @@ function TypedItemGenerateAllowEffect({asset, options}) {
function TypedItemGenerateAllowBlock({asset, options}) {
asset.AllowBlock = Array.isArray(asset.Block) ? asset.Block.slice() : [];
for (const option of options) {
// @ts-ignore: ignore `readonly` while still building the asset
CommonArrayConcatDedupe(asset.AllowBlock, option.Property.Block);
}
}
@ -279,7 +281,9 @@ function TypedItemGenerateAllowHide({asset, options}) {
asset.AllowHide = Array.isArray(asset.Hide) ? asset.Hide.slice() : [];
asset.AllowHideItem = Array.isArray(asset.HideItem) ? asset.HideItem.slice() : [];
for (const option of options) {
// @ts-ignore: ignore `readonly` while still building the asset
CommonArrayConcatDedupe(asset.AllowHide, option.Property.Hide);
// @ts-ignore: ignore `readonly` while still building the asset
CommonArrayConcatDedupe(asset.AllowHideItem, option.Property.HideItem);
}
}
@ -323,7 +327,7 @@ function TypedItemGenerateAllowLockType({asset, options}) {
* Sets the AllowLock and AllowLockType properties on an asset based on an AllowLockType array and the total number of
* possible types.
* @param {Asset} asset - The asset to set properties on
* @param {string[]} allowLockType - The AllowLockType array indicating which of the asset's types permit locks
* @param {readonly string[]} allowLockType - The AllowLockType array indicating which of the asset's types permit locks
* @param {number} typeCount - The total number of types available on the asset
* @returns {void} - Nothing
*/
@ -376,7 +380,7 @@ function TypedItemBuildChatMessageDictionary(ChatData, { asset, chatTags, dictio
/**
* Returns the options configuration array for a typed item
* @param {string} groupName - The name of the asset group
* @param {AssetGroupName} groupName - The name of the asset group
* @param {string} assetName - The name of the asset
* @returns {ExtendedItemOption[]|null} - The options array for the item, or null if no typed item data was found
*/
@ -387,7 +391,7 @@ function TypedItemGetOptions(groupName, assetName) {
/**
* Returns a list of typed item option names available for the given asset, or an empty array if the asset is not typed
* @param {string} groupName - The name of the asset group
* @param {AssetGroupName} groupName - The name of the asset group
* @param {string} assetName - The name of the asset
* @returns {string[]} - The option names available for the asset, or an empty array if the asset is not typed or no
* typed item data was found
@ -399,7 +403,7 @@ function TypedItemGetOptionNames(groupName, assetName) {
/**
* Returns the named option configuration object for a typed item
* @param {string} groupName - The name of the asset group
* @param {AssetGroupName} groupName - The name of the asset group
* @param {string} assetName - The name of the asset
* @param {string} optionName - The name of the option
* @returns {ExtendedItemOption|null} - The named option configuration object, or null if none was found
@ -446,7 +450,7 @@ function TypedItemValidateOption(C, item, option, previousOption) {
/**
* Sets a typed item's type and properties to the option whose name matches the provided option name parameter.
* @param {Character} C - The character on whom the item is equipped
* @param {Item|string} itemOrGroupName - The item whose type to set, or the group name for the item
* @param {Item | AssetGroupName} itemOrGroupName - The item whose type to set, or the group name for the item
* @param {string} optionName - The name of the option to set
* @param {boolean} [push] - Whether or not appearance updates should be persisted (only applies if the character is the
* player) - defaults to false.
@ -484,7 +488,7 @@ function TypedItemSetOptionByName(C, itemOrGroupName, optionName, push = false)
* Sets a typed item's type and properties to the option provided.
* @param {Character} C - The character on whom the item is equipped
* @param {Item} item - The item whose type to set
* @param {ExtendedItemOption[]} options - The typed item options for the item
* @param {readonly ExtendedItemOption[]} options - The typed item options for the item
* @param {ExtendedItemOption} option - The option to set
* @param {boolean} [push] - Whether or not appearance updates should be persisted (only applies if the character is the
* player) - defaults to false.
@ -508,7 +512,7 @@ function TypedItemSetOption(C, item, options, option, push = false) {
/**
* Finds the currently set option on the given typed item
* @param {Item} item - The equipped item
* @param {ExtendedItemOption[]} options - The list of available options for the item
* @param {readonly ExtendedItemOption[]} options - The list of available options for the item
* @returns {ExtendedItemOption} - The option which is currently applied to the item, or the first item in the options
* array if no type is set.
*/
@ -521,7 +525,7 @@ function TypedItemFindPreviousOption(item, options) {
/**
* Sets a typed item's type to a random option, respecting prerequisites and option validation.
* @param {Character} C - The character on whom the item is equipped
* @param {Item|string} itemOrGroupName - The item whose type to set, or the group name for the item
* @param {Item | AssetGroupName} itemOrGroupName - The item whose type to set, or the group name for the item
* @param {boolean} [push] - Whether or not appearance updates should be persisted (only applies if the character is the
* player) - defaults to false.
* @returns {string|undefined} - undefined or an empty string if the type was set correctly. Otherwise, returns a string

View file

@ -48,7 +48,7 @@ interface HTMLImageElement {
}
interface HTMLElement {
setAttribute(qualifiedName: string, value: string | number): void;
setAttribute(qualifiedName: string, value: any): void;
}
interface RGBColor {
@ -70,9 +70,6 @@ type CommonSubtituteSubstitution = [tag: string, substitution: string, replacer?
//#region Enums
type NotificationAudioType = 0 | 1 | 2;
type NotificationAlertType = 0 | 1 | 3 | 2;
type DialogSortOrder = | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
type DialogStruggleActionType = "ActionUse" | "ActionSwap" | "ActionRemove" | "ActionUnlock" | "ActionUnlockAndRemove" | "ActionStruggle" | "ActionEscape" | "ActionDismount";
@ -232,11 +229,13 @@ type AssetGroupItemName =
'ItemMouth3' | 'ItemNeck' | 'ItemNeckAccessories' | 'ItemNeckRestraints' |
'ItemNipples' | 'ItemNipplesPiercings' | 'ItemNose' | 'ItemPelvis' |
'ItemTorso' | 'ItemTorso2'| 'ItemVulva' | 'ItemVulvaPiercings' |
'ItemHandheld' | 'ItemScript' |
'ItemHandheld' |
'ItemHidden' /* TODO: investigate, not a real group */
;
type AssetGroupScriptName = 'ItemScript';
type AssetGroupBodyName =
'Blush' | 'BodyLower' | 'BodyUpper' | 'Bra' | 'Bracelet' | 'Cloth' |
'ClothAccessory' | 'ClothLower' | 'Corset' | 'Emoticon' | 'Eyebrows' |
@ -247,7 +246,7 @@ type AssetGroupBodyName =
'Shoes' | 'Socks' | 'SocksLeft' | 'SocksRight' | 'Suit' | 'SuitLower' | 'TailStraps' | 'Wings'
;
type AssetGroupName = AssetGroupBodyName | AssetGroupItemName;
type AssetGroupName = AssetGroupBodyName | AssetGroupItemName | AssetGroupScriptName;
type AssetPoseCategory = 'BodyUpper' | 'BodyLower' | 'BodyFull';
@ -256,10 +255,10 @@ type AssetPoseName =
/* BodyLower */ 'BaseLower' | 'Kneel' | 'KneelingSpread' | 'LegsClosed' | 'LegsOpen' | 'Spread' |
/* BodyFull */ 'Hogtied' | 'AllFours' |
/* BodyAddon */ 'Suspension'
/* BodyAddon */ 'Suspension' | 'SuspensionHogtied'
;
type AssetPoseMapping = { [index: string]: AssetPoseName | "" };
type AssetPoseMapping = Partial<Record<AssetPoseName, AssetPoseName | "">>;
type AssetLockType =
"CombinationPadlock" | "ExclusivePadlock" | "HighSecurityPadlock" |
@ -679,7 +678,7 @@ interface IChatRoomMessageMetadata {
/** The assets referenced in the message */
Assets?: Record<string, Asset>;
/** The groups referenced in the message */
Groups?: Record<string, AssetGroup>;
Groups?: Partial<Record<AssetGroupName, AssetGroup>>;
/** How intense the shock should be */
ShockIntensity?: number;
ActivityCounter?: number;
@ -796,7 +795,7 @@ interface AssetGroup {
Family: IAssetFamily;
Name: AssetGroupName;
Description: string;
Asset: Asset[];
Asset: readonly Asset[];
ParentGroupName: AssetGroupName | "";
Category: 'Appearance' | 'Item' | 'Script';
IsDefault: boolean;
@ -805,28 +804,28 @@ interface AssetGroup {
AllowColorize: boolean;
AllowCustomize: boolean;
Random?: boolean;
ColorSchema: string[];
ParentSize: string;
ColorSchema: readonly string[];
ParentSize: AssetGroupName | "";
ParentColor: AssetGroupName | "";
Clothing: boolean;
Underwear: boolean;
BodyCosplay: boolean;
Hide?: AssetGroupName[];
Block?: AssetGroupItemName[];
Zone?: [number, number, number, number][];
SetPose?: AssetPoseName[];
AllowPose: AssetPoseName[];
AllowExpression?: string[];
Effect?: EffectName[];
Hide?: readonly AssetGroupName[];
Block?: readonly AssetGroupItemName[];
Zone?: readonly [number, number, number, number][];
SetPose?: readonly AssetPoseName[];
AllowPose: readonly AssetPoseName[];
AllowExpression?: readonly string[];
Effect?: readonly EffectName[];
MirrorGroup: AssetGroupName | "";
RemoveItemOnRemove: { Group: AssetGroupItemName; Name: string; Type?: string }[];
RemoveItemOnRemove: readonly { Group: AssetGroupItemName; Name: string; Type?: string }[];
DrawingPriority: number;
DrawingLeft: number;
DrawingTop: number;
DrawingFullAlpha: boolean;
DrawingBlink: boolean;
InheritColor?: AssetGroupName;
FreezeActivePose: AssetPoseCategory[];
InheritColor: AssetGroupName | null;
FreezeActivePose: readonly AssetPoseCategory[];
PreviewZone?: RectTuple;
DynamicGroupName: AssetGroupName;
MirrorActivitiesFrom?: AssetGroupItemName;
@ -834,7 +833,7 @@ interface AssetGroup {
/** A dict mapping colors to custom filename suffices.
The "HEX_COLOR" key is special-cased to apply to all color hex codes. */
ColorSuffix?: Record<string, string>;
ExpressionPrerequisite?: string[];
ExpressionPrerequisite?: readonly string[];
HasPreviewImages: boolean;
/** Return whether this group belongs to the `Appearance` {@link AssetGroup.Category} */
IsAppearance(): this is AssetAppearanceGroup;
@ -849,6 +848,7 @@ interface AssetAppearanceGroup extends AssetGroup {
Category: "Appearance";
Name: AssetGroupBodyName;
IsRestraint: false;
AllowExpression?: readonly string[];
}
/** An AssetGroup subtype for the `Item` {@link AssetGroup.Category} */
@ -859,6 +859,7 @@ interface AssetItemGroup extends AssetGroup {
BodyCosplay: false;
Clothing: false;
IsDefault: false;
AllowExpression?: undefined;
}
/** An AssetGroup subtype for the `Script` {@link AssetGroup.Category} */
@ -870,6 +871,7 @@ interface AssetScriptGroup extends AssetGroup {
Underwear: false;
Clothing: false;
IsDefault: false;
AllowExpression?: undefined;
}
/** An object defining a drawable layer of an asset */
@ -886,7 +888,7 @@ interface AssetLayer {
HideColoring: boolean;
/** A list of allowed extended item types that this layer permits - the layer will only be drawn if
the item type matches one of these types. If null, the layer is considered to permit all extended types. */
AllowTypes: string[] | null;
AllowTypes: readonly string[] | null;
/** whether or not the layer has separate assets per type. If not, the extended type will not be included in
the URL when fetching the layer's image */
HasType: boolean;
@ -895,16 +897,16 @@ interface AssetLayer {
ParentGroupName?: AssetGroupName | "" | null;
/** An array of poses that this layer permits. If set, it will override the poses permitted
by the parent asset/group. */
AllowPose: AssetPoseName[] | null;
AllowPose: readonly AssetPoseName[] | null;
/** An array of poses that this layer should be hidden for. */
HideForPose: (AssetPoseName | "")[];
HideForPose: readonly (AssetPoseName | "")[];
/** An array of objects mapping poses to other poses to determine their draw folder */
PoseMapping?: AssetPoseMapping;
/** The drawing priority of this layer. Inherited from the parent asset/group if not specified in the layer
definition. */
Priority: number;
InheritColor: AssetGroupName | null;
Alpha: AlphaDefinition[];
Alpha: readonly AlphaDefinition[];
/** The asset that this layer belongs to */
Asset: Asset;
DrawingLeft?: number;
@ -919,25 +921,25 @@ interface AssetLayer {
BlendingMode: GlobalCompositeOperation;
LockLayer: boolean;
MirrorExpression?: AssetGroupName;
AllowModuleTypes?: string[];
AllowModuleTypes?: readonly string[];
/** The coloring index for this layer */
ColorIndex: number;
/** Any group-specific alpha masks that should be applied when drawing the layer. Only available on layers that have
been created prior to drawing */
GroupAlpha?: AlphaDefinition[];
/** A module for which the layer can have types. */
ModuleType: string[] | null;
ModuleType: readonly string[] | null;
/* Specifies that this layer should not be drawn if the character is wearing any item with the given attributes */
HideForAttribute: AssetAttribute[] | null;
HideForAttribute: readonly AssetAttribute[] | null;
/* Specifies that this layer should not be drawn unless the character is wearing an item with one of the given attributes */
ShowForAttribute: AssetAttribute[] | null;
ShowForAttribute: readonly AssetAttribute[] | null;
}
/** An object defining a group of alpha masks to be applied when drawing an asset layer */
interface AlphaDefinition {
/** A list of the group names that the given alpha masks should be applied to. If empty or not present, the
alpha masks will be applied to every layer underneath the present one. */
Group?: string[];
Group?: AssetGroupName[];
/** A list of the poses that the given alpha masks should be applied to. If empty or not present, the alpha
masks will be applied regardless of character pose. */
Pose?: AssetPoseName[];
@ -960,7 +962,7 @@ interface ResolvedTintDefinition extends TintDefinition {
}
interface ExpressionTrigger {
Group: AssetGroupName;
Group: AssetGroupBodyName;
Name: string;
Timer: number;
}
@ -978,30 +980,30 @@ interface Asset {
ParentGroupName?: AssetGroupName | null;
Enable: boolean;
Visible: boolean;
NotVisibleOnScreen?: string[];
NotVisibleOnScreen?: readonly string[];
Wear: boolean;
Activity: string | null;
AllowActivity?: string[];
ActivityAudio?: string[];
ActivityExpression: Record<string, ExpressionTrigger[]>;
AllowActivity?: readonly string[];
ActivityAudio?: readonly string[];
ActivityExpression: Record<string, readonly ExpressionTrigger[]>;
AllowActivityOn?: AssetGroupItemName[];
BuyGroup?: string;
PrerequisiteBuyGroups?: string[];
Effect?: EffectName[];
PrerequisiteBuyGroups?: readonly string[];
Effect?: readonly EffectName[];
Bonus?: AssetBonusName;
Block?: AssetGroupItemName[];
Expose: string[];
Hide?: AssetGroupName[];
HideItem?: string[];
HideItemExclude: string[];
Block?: readonly AssetGroupItemName[];
Expose: readonly AssetGroupItemName[];
Hide?: readonly AssetGroupName[];
HideItem?: readonly string[];
HideItemExclude: readonly string[];
HideItemAttribute: AssetAttribute[];
Require: string[];
SetPose?: AssetPoseName[];
AllowPose: AssetPoseName[];
HideForPose: (AssetPoseName | "")[];
Require: readonly AssetGroupBodyName[];
SetPose?: readonly AssetPoseName[];
AllowPose: readonly AssetPoseName[] | null;
HideForPose: readonly (AssetPoseName | "")[];
PoseMapping?: AssetPoseMapping;
AllowActivePose?: AssetPoseName[];
WhitelistActivePose?: AssetPoseName[];
AllowActivePose?: readonly AssetPoseName[];
WhitelistActivePose?: readonly AssetPoseName[];
Value: number;
Difficulty: number;
SelfBondage: number;
@ -1018,8 +1020,8 @@ interface Asset {
DrawingTop?: number;
HeightModifier: number;
ZoomModifier: number;
Alpha?: AlphaDefinition[];
Prerequisite: string[];
Alpha?: readonly AlphaDefinition[];
Prerequisite: readonly string[];
Extended: boolean;
AlwaysExtend: boolean;
AlwaysInteract: boolean;
@ -1029,23 +1031,23 @@ interface Asset {
PickDifficulty: number;
OwnerOnly: boolean;
LoverOnly: boolean;
ExpressionTrigger?: ExpressionTrigger[];
RemoveItemOnRemove: { Name: string; Group: AssetGroupItemName; Type?: string; }[];
AllowEffect?: EffectName[];
AllowBlock?: AssetGroupItemName[];
AllowHide?: AssetGroupItemName[];
AllowHideItem?: string[];
AllowType?: string[];
ExpressionTrigger?: readonly ExpressionTrigger[];
RemoveItemOnRemove: readonly { Name: string; Group: AssetGroupName; Type?: string; }[];
AllowEffect?: readonly EffectName[];
AllowBlock?: readonly AssetGroupItemName[];
AllowHide?: readonly AssetGroupName[];
AllowHideItem?: readonly string[];
AllowType?: readonly string[];
AllowTighten?: boolean;
DefaultColor?: ItemColor;
Opacity: number;
MinOpacity: number;
MaxOpacity: number;
Audio?: string;
Category?: string[];
Fetish?: string[];
Category?: readonly string[];
Fetish?: readonly string[];
CustomBlindBackground?: string;
ArousalZone: string;
ArousalZone: AssetGroupName;
IsRestraint: boolean;
BodyCosplay: boolean;
OverrideBlinking: boolean;
@ -1064,27 +1066,27 @@ interface Asset {
DynamicAfterDraw: boolean;
DynamicScriptDraw: boolean;
HasType: boolean;
AllowLockType?: string[];
AllowLockType?: readonly string[];
AllowColorizeAll: boolean;
AvailableLocations: string[];
AvailableLocations: readonly string[];
OverrideHeight?: AssetOverrideHeight;
FreezeActivePose: AssetPoseCategory[];
FreezeActivePose: readonly AssetPoseCategory[];
DrawLocks: boolean;
AllowExpression?: string[];
MirrorExpression?: string;
AllowExpression?: readonly string[];
MirrorExpression?: AssetGroupName;
FixedPosition: boolean;
Layer: AssetLayer[];
Layer: readonly AssetLayer[];
ColorableLayerCount: number;
Archetype?: string;
Archetype?: ExtendedArchetype;
Attribute: AssetAttribute[];
PreviewIcons: InventoryIcon[];
Tint: TintDefinition[];
PreviewIcons: readonly InventoryIcon[];
Tint: readonly TintDefinition[];
AllowTint: boolean;
DefaultTint?: string;
Gender?: 'F' | 'M';
CraftGroup: string;
ColorSuffix: Record<string, string>;
ExpressionPrerequisite?: string[];
ExpressionPrerequisite?: readonly string[];
TextMaxLength: null | Partial<Record<PropertyTextNames, number>>;
TextFont: null | string;
@ -1096,7 +1098,7 @@ interface Asset {
/** An ItemBundle is a minified version of the normal Item */
interface ItemBundle {
Group: string;
Group: AssetGroupName;
Name: string;
Difficulty?: number;
Color?: ItemColor;
@ -1114,8 +1116,8 @@ interface Pose {
/** Only show in menu if an asset supports it */
AllowMenuTransient?: true;
OverrideHeight?: AssetOverrideHeight;
Hide?: string[];
MovePosition?: { Group: string; X: number; Y: number; }[];
Hide?: AssetGroupName[];
MovePosition?: { Group: AssetGroupName; X: number; Y: number; }[];
}
interface Activity {
@ -1162,20 +1164,26 @@ type ItemEffectIcon = "BlindLight" | "BlindNormal" | "BlindHeavy" | "DeafLight"
type InventoryIcon = FavoriteIcon | ItemEffectIcon | "AllowedLimited" | "Handheld" | "Locked" | "LoverOnly" | "OwnerOnly" | "Unlocked";
interface InventoryItem {
Group: string;
Group: AssetGroupName;
Name: string;
Asset: Asset;
}
type SkillType = "Bondage" | "SelfBondage" | "LockPicking" | "Evasion" | "Willpower" | "Infiltration" | "Dressage";
interface Skill {
Type: string;
Type: SkillType;
Level: number;
Progress: number;
Ratio?: number;
}
type ReputationType =
"Dominant" | "Kidnap" | "ABDL" | "Gaming" | "Maid" | "LARP" | "Asylum" | "Gambling" |
"HouseMaiestas" | "HouseVincula" | "HouseAmplector" | "HouseCorporis";
interface Reputation {
Type: string;
Type: ReputationType;
Value: number;
}
@ -1272,7 +1280,7 @@ interface Character {
Type: CharacterType;
Name: string;
Nickname?: string;
AssetFamily: IAssetFamily | string;
AssetFamily: IAssetFamily;
AccountName: string;
Owner: string;
Lover: string;
@ -1287,10 +1295,10 @@ interface Character {
Pose: AssetPoseName[];
ActivePose: AssetPoseName[];
AllowedActivePose: AssetPoseName[];
Effect: string[];
Effect: EffectName[];
Tints: ResolvedTintDefinition[];
Attribute: AssetAttribute[];
FocusGroup: AssetGroup | null;
FocusGroup: AssetItemGroup | null;
Canvas: HTMLCanvasElement | null;
CanvasBlink: HTMLCanvasElement | null;
MustDraw: boolean;
@ -1376,7 +1384,7 @@ interface Character {
IsInverted: () => boolean;
CanChangeToPose: (Pose: AssetPoseName) => boolean;
GetClumsiness: () => number;
HasEffect: (Effect: string) => boolean;
HasEffect: (Effect: EffectName) => boolean;
HasTints: () => boolean;
GetTints: () => RGBAColor[];
HasAttribute: (attribute: AssetAttribute) => boolean;
@ -1439,7 +1447,8 @@ interface Character {
Rule?: LogRecord[];
Status?: string | null;
StatusTimer?: number;
Crafting?: CraftingItem[];
Crafting?: (null | CraftingItem)[];
}
/**
* The characters online shared settings.
@ -1708,7 +1717,7 @@ interface PlayerCharacter extends Character {
GhostList?: number[];
Wardrobe?: any[][];
WardrobeCharacterNames?: string[];
SavedExpressions?: ({ Group: AssetGroupName, CurrentExpression?: string }[] | null)[];
SavedExpressions?: ({ Group: AssetGroupBodyName, CurrentExpression?: string }[] | null)[];
SavedColors: HSVColor[];
FriendList?: number[];
FriendNames?: Map<number, string>;
@ -1896,7 +1905,8 @@ interface AssetDefinitionProperties {
SelfUnlock?: boolean;
/**
* The timer for after how long until a lock should be removed
* The timer for after how long until a lock should be removed.
* Also used for timed emoticons.
* @see {@link Asset.RemoveTimer}
*/
RemoveTimer?: number;
@ -2612,7 +2622,7 @@ type DrawImageCallback = (
alphasMasks: RectTuple[],
opacity?: number,
rotate?: boolean,
blendingMode?: GlobalCompositeOperation
blendingMode?: GlobalCompositeOperation,
) => void;
/**
@ -2714,6 +2724,8 @@ interface DynamicBeforeDrawOverrides {
Pose?: AssetPoseName;
}
type DynamicDrawTextEffect = "burn";
/**
* A dynamic BeforeDraw callback
*/
@ -3052,3 +3064,25 @@ interface DialogSelfMenuOptionType {
}
// #end region
// #region Notification
type NotificationAudioType = 0 | 1 | 2;
type NotificationAlertType = 0 | 1 | 3 | 2;
type NotificationEventType = "ChatMessage" | "ChatJoin" | "Beep" | "Disconnect" | "Test" | "Larp";
interface NotificationSetting {
AlertType: NotificationAlertType,
Audio: NotificationAudioType,
}
interface NotificationData {
body?: string,
character?: Character,
useCharAsIcon?: boolean,
memberNumber?: number,
characterName?: string,
chatRoomName?: string,
}
// #end region

View file

@ -98,9 +98,10 @@ function ValidationResolveAppearanceDiff(groupName, previousItem, newItem, param
/**
* Check whether newArray is different from oldArray.
* @param {any[]} oldArray
* @param {any[]} newArray
* @returns
* @template T
* @param {T[]} oldArray
* @param {T[]} newArray
* @returns {boolean}
*/
function ValidationHasArrayPropertyBeenModified(oldArray, newArray) {
if (!oldArray && !newArray) {
@ -130,6 +131,7 @@ function ValidationResolveScriptDiff(previousItem, newItem, {C, permissions, sou
const previousProperty = (previousItem && previousItem.Property) || {};
const newProperty = (newItem && newItem.Property) || {};
/** @type {ItemProperties} */
const sanitizedProperty = {};
/** @type {(keyof ItemProperties)[]} */
@ -540,7 +542,7 @@ function ValidationCanAddItem(newItem, params) {
* against the target character's limited and blocked item lists, not their global item permissions.
* @param {Character} C - The target character
* @param {number} sourceMemberNumber - The member number of the source character
* @param {string} groupName - The name of the asset group for the intended item
* @param {AssetGroupName} groupName - The name of the asset group for the intended item
* @param {string} assetName - The asset name of the intended item
* @param {string|null} [type] - The type of the intended item
* @returns {boolean} - TRUE if the character with the provided source member number is _not_ allowed to equip the
@ -1135,7 +1137,7 @@ function ValidationFindBlockCycles(appearance) {
/**
* Finds the groups, from a provided list of groups, that are blocked by a given item.
* @param {Item} item - The item to check
* @param {AssetGroupName[]} groupNames - A list of group names that should be used to filter the final block list
* @param {readonly AssetGroupName[]} groupNames - A list of group names that should be used to filter the final block list
* @returns {AssetGroupName[]} - A subset of the provided group names representing the groups that are blocked by the given
* item.
*/
@ -1212,7 +1214,7 @@ function ValidationHasScriptPermission(character, property, permissionLevel) {
* Checks whether a character permits any of the given permission levels to modify the given item property.
* @param {Character} character - The character to check
* @param {ScriptPermissionProperty} property - The name of the property to check
* @param {ScriptPermissionLevel[]} permissionLevels - The permission levels to check
* @param {readonly ScriptPermissionLevel[]} permissionLevels - The permission levels to check
* @returns {boolean} TRUE if the character permits modifications to the provided property
*/
function ValidationHasSomeScriptPermission(character, property, permissionLevels) {

View file

@ -47,6 +47,8 @@ function VariableHeightRegister(asset, config, property, parentOptions = null) {
* Generates an asset's variable height data
* @param {Asset} asset - The asset to generate modular item data for
* @param {VariableHeightConfig} config - The variable height configuration
* @param {ItemProperties} property
* @param {ExtendedItemOption[]} parentOptions
* @returns {VariableHeightData} - The generated variable height data for the asset
*/
function VariableHeightCreateData(asset,
@ -261,7 +263,7 @@ function VariableHeightExit() {
* Publishes a custom action to the chat for the height change
* @param {Object} dialog - The keywords for the dialog entries to look up
* @param {Asset} asset - The asset for the variable height item
* @param {CommonChatTags[]} chatTags - The tags to map to a dictionary entry
* @param {readonly CommonChatTags[]} chatTags - The tags to map to a dictionary entry
* @param {Function} getHeight - Function to find the current setting from a property
* @returns {void} - Nothing
*/

View file

@ -294,8 +294,10 @@ function VibratorModeSetAssetProperties(data) {
*/
function VibratorModeSetAllowEffect({asset, options}) {
asset.AllowEffect = Array.isArray(asset.AllowEffect) ? [...asset.AllowEffect] : [];
// @ts-ignore: ignore `readonly` while still building the asset
CommonArrayConcatDedupe(asset.AllowEffect, ["Egged", "Vibrating"]);
if (options.includes(VibratorModeSet.ADVANCED)) {
// @ts-ignore: ignore `readonly` while still building the asset
CommonArrayConcatDedupe(asset.AllowEffect, ["Edged"]);
}
}
@ -307,12 +309,13 @@ function VibratorModeSetAllowEffect({asset, options}) {
*/
function VibratorModeSetEffect({asset}) {
asset.Effect = Array.isArray(asset.Effect) ? [...asset.Effect] : [];
// @ts-ignore: ignore `readonly` while still building the asset
CommonArrayConcatDedupe(asset.Effect, ["Egged"]);
}
/**
* Common load function for vibrators
* @param {VibratorModeSet[]} [Options] - The vibrator mode sets to load the item with
* @param {readonly VibratorModeSet[]} [Options] - The vibrator mode sets to load the item with
* @returns {void} - Nothing
*/
function VibratorModeLoad(Options) {
@ -331,7 +334,7 @@ function VibratorModeLoad(Options) {
/**
* Common draw function for vibrators
* @param {VibratorModeSet[]} Options - The vibrator mode sets to draw for the item
* @param {readonly VibratorModeSet[]} Options - The vibrator mode sets to draw for the item
* @param {number} [Y] - The y-coordinate at which to start drawing the controls
* @returns {void} - Nothing
*/
@ -342,7 +345,7 @@ function VibratorModeDraw(Options, Y=450) {
/**
* Common draw function for drawing the control sets of the extended item menu screen for a vibrator
* @param {VibratorModeSet[]} Options - The vibrator mode sets to draw for the item
* @param {readonly VibratorModeSet[]} Options - The vibrator mode sets to draw for the item
* @param {number} [Y] - The y-coordinate at which to start drawing the controls
* @returns {void} - Nothing
*/
@ -368,7 +371,7 @@ function VibratorModeDrawControls(Options, Y=450) {
/**
* Common click function for vibrators
* @param {VibratorModeSet[]} Options - The vibrator mode sets for the item
* @param {readonly VibratorModeSet[]} Options - The vibrator mode sets for the item
* @param {number} [Y] - The y-coordinate at which the extended item controls were drawn
* @returns {void} - Nothing
*/
@ -594,7 +597,7 @@ function VibratorModeUpdateEdge(Item, C, PersistentData) {
* @param {Item} Item - The item that is being updated
* @param {Character} C - The character that the item is equipped on
* @param {object} PersistentData - Persistent animation data for the item
* @param {VibratorModeState[]} TransitionsFromDefault - The possible vibrator states that may be transitioned to from
* @param {readonly VibratorModeState[]} TransitionsFromDefault - The possible vibrator states that may be transitioned to from
* the default state
* @returns {void} - Nothing
*/
@ -637,7 +640,7 @@ function VibratorModeUpdateStateBased(Item, C, PersistentData, TransitionsFromDe
* @param {number} Arousal - The current arousal of the character
* @param {number} TimeSinceLastChange - The time in milliseconds since the vibrator intensity was last changed
* @param {VibratorIntensity} OldIntensity - The current intensity of the vibrating item
* @param {VibratorModeState[]} TransitionsFromDefault - The possible vibrator states that may be transitioned to from
* @param {readonly VibratorModeState[]} TransitionsFromDefault - The possible vibrator states that may be transitioned to from
* the default state
* @returns {StateAndIntensity} - The updated state and intensity of the vibrator
*/