After setting up a deck of many things in one of my games, I found there wasn't great out-of-the-box way to simply view and share a card. Taking visual inspiration from a popular 5e toolset, I ported their card viewer UX over to the Foundry system. Now, I can view cards beautifully in a 3d-feel viewer, flip the cards over to view the card art or read the card stats, and even share this beautiful view with my players on the fly.
This was built on Foundry v11 and, based on initial user feedback, appears to be currently mostly compatible with v10 but may have some bugs. As for compatibility with other modules, none have been tested, but the functionality of this mod doesn't mess with the core card system and only serves to enhance the UI in exactly one way, so I doubt there will be many conflicts. If you come across any issues in v10 or with mother modules, please feel free to log in the github issues section.
A demo showing how to view a card from a deck, flip it, share it, dismiss it, and what output to expect in the DM chat:
A quick demo showcasing 2 macros that will draw a random card from a given deck and discard it, or peek at a card without drawing it:
You'll need to import all the macros from the compendium in this module and customize them.
'Deck of Many Things'
with name of a deck in your world.'My Discard Pile'
with the name of a pile in your world.share
to true, everyone logged in FVTT will see the card immediately when drawn.face
determines how the card is initially displayed. This var can be ommitted, or set to "UP", "DOWN", or "REVEAL" to flip the card face-up with animation.// Draws, views, and discards a card from a given deck name. Leave discardPile null to smart-match an existing discard pile name or auto-create a new one named "[your deck name] - Discard Pile".
let deckName = 'Deck of Many Things';
let discardPile = 'My Discard Pile';
let share = true;
let face = "REVEAL"; //either "UP", "DOWN", or "REVEAL" to flip up
OrcnogFancyCardDealer({
deckName: deckName ,
discardPileName: discardPile
}).draw(share, face);
'Deck of Many Things'
with name of a deck in your world.'Gem'
with the name of a card in the deck or the UID.// Peeks at a card, but does not draw and discard it.
let deckName = 'Deck of Many Things';
let card = 'Gem'; // card name or ID
let faceDown = true;
let whisper = false;
let share = false;
OrcnogFancyCardDealer({
deckName: deckName,
}).view(card, faceDown, whisper, share);
'modules/orcnog-card-viewer/assets/beefy-abraham-lincoln.webp'
with a path or URL to any image you want.'modules/orcnog-card-viewer/assets/orcnogback.webp'
with a path or URL to any card back image.borderColor
can change the border color.borderWidth
can change the colored border thickness.shareToAll
will show to everyone.// Requires Orcnog's Card Viewer
// This macro demonstrates the easiest way to view any image (URL or local path) as a flippable card. The card back image is automatically provided.
let img = 'modules/orcnog-card-viewer/assets/beefy-abraham-lincoln.webp';
let backImg = 'https://i.imgur.com/mStOCso.png'; // optional
let borderColor = '#543'; // optional
let borderWidth = '5px'; // optional
let shareToAll = true; // optional
OrcnogFancyDisplay({
front: img,
back: backImg,
border: borderColor,
borderWidth: borderWidth
}).render(shareToAll)
This module ships with several API methods that can be leveraged in code, and a couple of added global convenience functions.
Expose the FancyDisplay constructor globally for modules and macros and such.
front
- a string path to an image. Try to keep this image card-shaped.back
(optional) - a string path to a card back image. If not provided, it will use modules/orcnog-card-viewer/assets/orcnogback.webp
border
(optional) - a string (hex value) representing a custom border color. Ex: "#000"borderWidth
(optional) - a string (px value) representing a custom border width. Ex: "5px"faceDown
(optional) - boolean, whether the card will display face-down (default is true)const myFancyViewer = await game.modules.get('orcnog-card-viewer').api.FancyDisplay({
front: 'https://i.imgur.com/someAmazingCardFrontImage.jpg`,
back: 'https://i.imgur.com/someAmazingCardBackImage.jpg`,
border: '#990000',
borderWidth: '6px',
faceDown: false
});
// and later on...
let doShare = true;
myFancyViewer.render(doShare);
Expose the CardDealer constructor as a global function for modules and macros and such.
deckName
{String} - a string name of the deck to set up this CardDealer fordiscardPileName
{String} (optional) - a string name of a discard pile. If not provided, this module will attempt to smart-match a likely discard pile, or create a new one when needed.const myFancyDealer = await game.modules.get('orcnog-card-viewer').api.CardDealer({
deckName: 'My Deck',
discardPileName: 'My Discard Pile'
});
// and later on...
let doShare = true;
myFancyDealer.draw(doShare);
Draws a Card from a given deck. This is a convenience method that simply constructs the same object as api.CardDealer( options )
, and then automatically calls the .draw( args )
method on that instance.
Args:
deckName
{String} - see: api.CardDealer > deckNamediscardPileName
{String} (optional) - see api.CardDealer > discardPileNameshareToAll
{Boolean} (optional) - whether the drawn card will be shared to all players (default is true)Example:
game.modules.get('orcnog-card-viewer').api.draw(someDeckName, someDiscardPileName, true);
Peeks at Card from a given deck (but doesn't draw it). This is a convenience method that simply constructs the same object as api.CardDealer( options )
, and then automatically calls the .view( args )
method on that instance.
Args:
deckName
{String} - see: api.CardDealer > deckNamecard
{String} - the name or ID of the card to viewfaceDown
{Boolean} - whether the card should display face-down (true) or face-up (false)whisper
{Boolean} - whether the card description text should be whispered to the DMshare
{Boolean} (optional) - whether the card will be shared to all players on draw(default is true)Example:
game.modules.get('orcnog-card-viewer').api.view(deckName, cardNameOrID, true, true, true);
$${\color{red}Warning: Experimental!}$$ This functionality is experimental at best. It "works", but I'm having trouble with image sizing, webp/png transparency, and most non-card images tend to look bad with the glint/glare effect.
View any image with the FancyViewer. No border. Can't flip.
This is a (very experimental!) convenience method that simply constructs the same object as would api.FancyDisplay( options )
, and then automatically calls the .render( share )
method on it.
Args:
image
{String} - string path to an image. can be local, or a URL.share
{Boolean} (optional) - whether the image will be immediately shared to all players (default is true)Example:
game.modules.get('orcnog-card-viewer').api.viewImage(imgPath, true);
These functions shuold be accessible at the global level. Use them in macros or in other module code as needed. With the API methods exposed, I probably should just get rid of these... but they do clean up the macros' code.
An alias for the api.FancyDisplay
method. See: api.FancyDisplay above.
Example:
const myFancyViewer = await OrcnogFancyDisplay({
front: myFrontImg,
back: myBackImg,
border: myCstomBorderColor,
faceDown: false
});
// and later on...
myFancyViewer.render(true);
An alias for the api.CardDealer
method. See: api.CardDealer above.
Example:
const myFancyDealer = await OrcnogFancyCardDealer({
deckName: myDeckName,
discardPileName: myDiscardPileName
});
// and later on...
myFancyDealer.draw(true);
An alias for the api.viewImage
method. See: api.viewImage above. Warning: this is only experimental functionality!
testing this github release functionality.
Orcnog Card Viewer's world debut! (or so i thought!)
Release 0.1.1 - ready for package submission! (or so i thought!)
Release 0.1.2 - some quick changes for package approval. removed possibly-copyrighted sabaac image. ACTUAL WORLD DEBUT HERE. Hello world!
First round of bugfixes and me-aculpas. Added decent README (including this changelog section), and a demo video. Nerfed the compatibility to just v11, as user feedback indicates it's not compatible with v10 =/
Fixed Issue #10, 'Deck of Many Things' hardcoded. Also added a new GIF demo video.
Fixed a bug pointed out by @kristianserrano in this PR: https://github.com/orcnog/orcnog-card-viewer/pull/14/files
This release is for testing only! It's a carbon copy of the v0.1.5 release, but the compatibility is lowered to include v10.
Added game settings for default border color & width and cardback image. Made borderWidth configurable in macros and api calls. Fixed Issue #18.
Completes localization or all client-facing or language-functional strings. Attempts to fix .deal()
erroring out.
Handle for Pass and Draw (to a hand) actions, with new settings to handle whether those trigger card views. Module now depends on socketlib. Moevs several values to a new CONSTS file. Fixed an annoyance where it searched for a discard pile every time, even if just viewing a card.
Multiple cards are now grouped into a single display. "Dramatic reveal" (I know, corny name), is now implemented to show cards face-down at first, but then auto-flip them over after a small (dramatic?) delay. Several new settings added to add fine control over display behaviors based on specific card actions, e.g. on the Deal action, always show cards face-up, but on Draw action, show them face-down, while on Pass actions, show them with a dramatic reveal (flip from face-down to -up automagically). Settings menu has also been enhanced with collapsible groups of settings. The grouping of multiple cards into a single viewer was enough to merit a new minor version on its own, but with all the enhancements to settings, dramatic reveal, and a few other things crossed off the TODO list, I'm happy with calling this a new minor version. After a few weeks/months of beta testing, I may as well call this version 1.0, but cart/horse.
Quick bug fix: .viewImage and .viewImageAsCard api methods and global OrcnogFancyDisplay() and OrcnogFancyImage() functions broke in v0.3.0 after the image input for the fancyDisplay class was converted from singular fonr/back img params to an Array (to support multiple cards in one view). This fix ought to solve that before ppl start logging bugs.
Updated to Foundry v12 (verified in module.json). Also updated the TODOs a bit.