/foundryvtt-forien-unidentified-items

This module aims to provides system agnostic solution to handle unidentified items and their identification for games via Foundry VTT.

Primary LanguageJavaScriptMIT LicenseMIT

FoundryVTT - Forien's Unidentified Items

GitHub release (latest SemVer)

GitHub Releases

GitHub All Releases

Latest Release Download Count

Forge Installs

Foundry Core Compatible Version

Latest Version

Foundry Hub Endorsements

This module aims to provides system agnostic solution to handle unidentified items and their identification for games via Foundry Virtual Tabletop.

Installation

It's always easiest to install modules from the in game add-on browser.

To install this module manually:

  1. Inside the Foundry "Configuration and Setup" screen, click "Add-on Modules"
  2. Click "Install Module"
  3. In the "Manifest URL" field, paste the following url: https://github.com/Forien/foundryvtt-forien-unidentified-items/releases/latest/download/module.json
  4. Click 'Install' and wait for installation to complete
  5. Don't forget to enable the module in game using the "Manage Module" button

libWrapper

This module uses the libWrapper library for wrapping core methods. It is a hard dependency and it is recommended for the best experience and compatibility with other modules.

Archon

This module uses the Archon library for wrapping core methods. It is a hard dependency and it is recommended for the best experience and compatibility with other modules.

System Integration

dnd5e pf2e wfrp4e sw5e swade
Settings
Logic

One of main principles of this module is being System Agnostic. There is however, way of integrating systems.

Basic settings initialization (like setting default persisting properties for dnd5e) I will allow to be built-in this module. These can, however, be defined from the System's side.

Usage

Right click on items in sidebar, or use buttons on Item Sheet's header to Mystify an item. It will create new apparently blank item.

Mystified item can be fully edited and works just as a normal item in that system. However, GM can at any point peek at what the original item is (currently it's not possible to edit original data).

GM can also click on "Identify" button, which transforms entire Item into original, using embedded data. Data used during identification is decided upon at the time of mystification.

1. Context Menu Options

Right click on any entry in Item Directory (either Sidebar or Popup) to bring Context Menu for Items.

Mystify

Will duplicate the Item, with duplicate being mystified.

Replace with Mystified

Exactly as Mystify, but will replace Original Item, instead of duplicating it.

Mystify As…

This option will create new Dialog Popup:

Drag & Drop an item which will become new "face" of Original Item. This basically allows to use some other item as template for Mystified item, instead of using Default properties

Mystify

This option works like "Mystify" context menu option

Replace

This option works like "Replace with Mystified" context menu option

Mystify (advanced)…

This option will open a Dialog Popup:

This popup allows you to choose which properties of Original Item should be kept (checkboxes checked) and which should be set as default (unchecked)

Buttons work like buttons in Mystify As… Dialog

Peek

Opens sheet for Original Item allowing to "Peek" what the item really is, without identifying it.

Identify

Replaces Mystified Item with Original Item.

2. Item Sheet Header Buttons

Mystify

  1. If it's World Item or Compendium Item, it works like "Mystify" Context Menu option
  2. If it's Owned Item of an Actor, it works like "Replace with Mystified" Context Menu option

Peek

Works exactly like "Peek" Context Menu option

Identify

Works exactly like "Identify" Context Menu option

Definitions

Mystified Item

Mystified Item is normal item, that has all or most of it's properties reset to default ones (like when you create new Item), while saving Original Data of Source Item deep inside Item's flags. Original Data is normally inaccessible and item for the purpose of Foundry VTT and game system acts just as it would without Original Data.

Original Item

Item that went through, or is about to go through "mystification". All data of Original Item is serialized and hidden within Mystified Item.

Screenshots

Mystify As - Transmogrify

Advanced mystification


Mystified Acid Vial

Context Menu

Context Menu

API

This page is meant for System and Module developers that wish to integrate their systems & modules with Unidentified Items, although some information here might be useful for people wanting to write Macros as well.

This is the only public class exposed by this module:

async game.modules.get("forien-unidentified-items").api.mystify(itemUuid, options = {replace: false, mystifiedData: undefined})

  • itemUuidstring – UUID of Original Item to be mystified
  • optionsObject – object of options
  • options.replacebooleantrue means, Original Item should be replaced with Mystified one
  • options.mystifiedDataundefined | Object – if defined, it acts as a basis for setting data of Mystified Item. Properties not defined will be set to system's default.

This method handles the Mystification proccess. Fires the forien-unidentified-items:onMystifyItem Hook right before mystifying.

async game.modules.get("forien-unidentified-items").api.mystifyReplace(itemUuid)

  • itemUuidstring – UUID of Original Item to be mystified

Alias for mystify(itemUuid, {replace: true}).

async game.modules.get("forien-unidentified-items").api.mystifyAsDialog(itemUuid)

  • itemUuidstring – UUID of Original Item to be mystified

Opens "Mystify As…" Dialog. Callbacks for buttons fire the mystify() method with respective settings.

async game.modules.get("forien-unidentified-items").api.mystifyAdvancedDialog(itemUuid)

  • itemUuidstring – UUID of Original Item to be mystified

Opens "Mystify (advanced)…" Dialog. Callbacks for buttons fire the mystify() method with respective settings.

async game.modules.get("forien-unidentified-items").api.identify(item)

  • itemItem – instance of Item class to be identified

If item has OrigData flag, this method will replace Mystified Item with OrigData. Fires the forien-unidentified-items:onIdentifyItem hook. If Hook returns false, it will not proceed with full identification.

game.modules.get("forien-unidentified-items").api.isMystified(item)

  • itemItem – instance of Item class

Returns Boolean. True if item is mystified (has Original Data), false otherwise.

async game.modules.get("forien-unidentified-items").api.isUuidMystified(itemUuid)

  • itemUuidstring – UUID of Original Item to be mystified

Returns Boolean. True if item is mystified (has Original Data), false otherwise.

game.modules.get("forien-unidentified-items").api.getOrigData(item)

  • itemItem – instance of Item class

Returns Object of item's Original Data, or undefined if it isn't mystified.

Item

This module expands the prototype of registered Item entity class.

item.isMystified()

Returns true if item is Mystified (has Original Data), false otherwise

getter item.origData

Returns Object of item's Original Data, or undefined if it isn't mystified.

Hooks

General Hooks

Hooks.callAll forien-unidentified-items:afterInit

At this hook, context menu event listener and settings are already redistered

Hooks.callAllforien-unidentified-items:afterSetup

At this hook, the ForienIdentification API class is already available under global scope

Hooks.callAll forien-unidentified-items:afterReady

At this hook, settings are initialized (if first launch) and derived Item classes are generated and replaced the original Item classes in CONFIG.Item

Setting Initialization Hooks

There Hooks fire only once per world, they are used to initialize default state of Settings. GMs will be able to freely change settings afterwards

Hooks.call forien-unidentified-items:onInitializeDefaultIcons

  • iconsObject – a key-value pair object containing item types as keys and image paths as values

Example for dnd5e:

{
  "weapon": "modules/forien-unidentified-items/icons/inv-unidentified.png",
  "equipment": "modules/forien-unidentified-items/icons/inv-unidentified-armor.png",
  "consumable": "modules/forien-unidentified-items/icons/inv-unidentified-potion.png",
  "tool": "modules/forien-unidentified-items/icons/inv-unidentified-tool.png",
  "loot": "modules/forien-unidentified-items/icons/inv-unidentified-loot.png",
  "class": "modules/forien-unidentified-items/icons/inv-unidentified-book.png",
  "spell": "modules/forien-unidentified-items/icons/inv-unidentified-scroll.png",
  "feat": "modules/forien-unidentified-items/icons/inv-unidentified-book.png",
  "backpack": "modules/forien-unidentified-items/icons/inv-unidentified-knapsack.png"
}

You can replace any path by for example:

Hooks.on('forien-unidentified-items:onInitializeDefaultIcons', (icons) => {
  icons.weapon = "path/to/icon.png";
});

Important note: if you perform assignment on icons, you will remove it's reference and fail to override data.

Hooks.call forien-unidentified-items:onInitializeItemProperties

  • propertiesObject – a key-value pair object containing item types as keys and key-pair object as value

Property Paths set to true mean they will by default be kept when mystifying items.

Example for dnd5e:

{
  "weapon": {
    "ability": false,
    "actionType": false,
    "description.chat": false,
    "description.unidentified": false,
    "quantity": true,
    "weight": true,
    "...": "..."
  },
  "equipment": {
    "armor.dex": false,
    "armor.type": true,
    "armor.value": false,
    "...": "..."
  },
  "...": "...",
  "backpack": {
    "...": "..."
  }
}

You can replace any path by for example:

Hooks.on('forien-unidentified-items:onInitializeItemProperties', (properties) => {
  properties.equipment = {
    "armor.value": true,
    "armor.dex": true
  };
});

Not defined paths will be kept (so in above example, equipment.armor.type will remain true)

Important note: if you perform assignment on icons, you will remove it's reference and fail to override data.

Identification & Mystification Hooks

Hooks.call forien-unidentified-items:onMystifyItem

  • itemItem – an Item Entity instance of Original Item
  • origDataObject – result of duplicate(item), will be directly applied to OrigData flag and will represent Original Item data for purpose of Peek and Identify
  • mystifiedDataObject – data object directly destined to become Mystified Object data. Properties not defined will be set to default (as in create new Item)
  • optionsObject – options as passed to mystify() method.

If you perform changes on above parameters and keep object references, you can decide entire Mystification process.

Hooks.call forien-unidentified-items:onIdentifyItem

  • itemItem – an Item Entity instance of Mystified Item
  • origDataObject – directly taken from OrigData flag and represents Original Item data.

If you perform changes on above parameters and keep object references, you can influence Identification process. The OrigData flag is removed by default.

If your Hook returns false, the default Identification process will not happen. So you can perform partial identification. For example (in pseudo-code):

Hooks.on('forien-unidentified-items:onIdentifyItem', (item, data) => {
  // perform skill check if identification can happen
  let testResult = SomeClass.rollIdentification(data);

  // If result was only partial:
  switch (testResult.result) {
    case 'partial':
      // update description with new information
      item.update({"data.description": testResult.newDescription});
    case 'failed':
      return false; //and stop default full identification
    default:
      return true;
  }
});

Item Sheet Hooks

Hooks.call forien-unidentified-items:getItemPermissions

  • itemItem – an Item Entity instance of opened ItemSheet
  • permissionObject – object containing permissions. All permission default to game.user.isGM
let permissions = {
  canIdentify: game.user.isGM,
  canPeek: game.user.isGM,
  canMystify: game.user.isGM
}

canIdentify

If true, user can see and press Identify Header Button.

canPeek

If true, user can see and press Peek Header Button to open Original Item sheet.

canMystify

If true, user can see and press Mystify Header Button.

What about logic? Skill Checks for Identification?

According to this module's Primary Principle, there will never be any system-specific logic in module. Feel free to integrate logic into your System or your Module, using API and Hooks

How to integrate?

If you are System or Module developer, please read the Developers Wiki for API and Hooks references.

Also, do not hesitate to contact me with questions and for assistance.

Future plans

  • none currently

You can always check current and up-to-date planned and requested features here

If you have any suggestion or idea on new contents, hit me up on Discord!

Build

Install all packages

npm install

dev

dev will let you develop you own code with hot reloading on the browser

npm run dev

npm build scripts

build

build will build and set up a symlink between dist and your dataPath.

npm run build

build-watch

build-watch will build and watch for changes, rebuilding automatically.

npm run build-watch

prettier-format

prettier-format launch the prettier plugin based on the configuration here

npm run-script prettier-format

Issues

Any issues, bugs, or feature requests are always welcome to be reported directly to the Issue Tracker, or using the Bug Reporter Module.

License

This package is under an MIT license and the Foundry Virtual Tabletop Limited License Agreement for module development.

Acknowledgements

  • Thanks to Forien#2130 (discord contact)
  • Bootstrapped with League of Extraordinary FoundryVTT Developers foundry-vtt-types.
  • Icons were created by transforming assets made by Lorc and Willdabeast from game-icons.net
  • Thanks to unsoluble for the idea for this Module!
  • Thanks to KLO for providing Korean translation
  • Thanks to rinnocenti for providing Portuguese (Brazil) translation
  • Thanks to freyrrabbit for help with defining default properties for PF2e system
  • Thanks to SalieriC for help with defining default properties for Swade system