Skip to content

Commit

Permalink
Merge pull request #8 from johnmartel/feature/show-token-alignment
Browse files Browse the repository at this point in the history
Feature/show token alignment
  • Loading branch information
johnmartel committed Dec 20, 2020
2 parents cdeff6b + 14a70c3 commit 468f52a
Show file tree
Hide file tree
Showing 13 changed files with 284 additions and 9 deletions.
6 changes: 6 additions & 0 deletions .codeclimate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ checks:
config:
threshold: # language-specific defaults. an override will affect all languages.
plugins:
duplication:
enabled: true
config:
languages:
javascript:
mass_threshold: 65
fixme:
enabled: true
exclude_patterns:
Expand Down
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"plugin:foundry-vtt/recommended"
],
"rules": {
"import/extensions": ["error", "always"],
"no-unused-vars": ["error", { "vars": "all", "args": "after-used", "ignoreRestSiblings": false, "argsIgnorePattern": "^_" }]
},
"overrides": [
Expand Down
37 changes: 37 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
on:
push:
tags:
- 'v*'

name: Release

jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Zip files
run: |
zip -r hover-align.zip module.json README.md CHANGELOG.md LICENSE modules lang
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Upload Release Asset
id: upload-release-asset
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./hover-align.zip
asset_name: hover-align.zip
asset_content_type: application/zip
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# v1.0.0

Initial release
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,24 @@

Simple FoundryVTT module that displays character (both PC/NPC) alignment on hovering a token.

It will display the alignment for all tokens to the GM and only for player-owned tokens to players.

This module uses the Core functionality used to display the token tooltip without interfering with it.

![sample](doc/sample.gif)

## Installation

TBD
You could either:

1. Navigate to the Foundry Setup screen and click on the Modules tab
1. Click Install Module and look for HoverAlign

or:

1. Start FVTT and browse to the Game Modules tab in the Configuration and Setup menu
1. Select the Install Module button and enter the following URL: https://raw.githubusercontent.com/johnmartel/hover-align/master/module.json
1. Click Install and wait for installation to complete

## Development

Expand Down
47 changes: 47 additions & 0 deletions __tests__/moduleLogger.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import ModuleLogger from '@modules/moduleLogger';

describe('moduleLogger', () => {
it('should inject module tag to console.debug', () => {
const spy = jest.spyOn(console, 'debug');

ModuleLogger.debug('test debug');

expect(spy).toHaveBeenCalledWith('[hover-align] test debug');
});

it('should inject module tag to console.error', () => {
const spy = jest.spyOn(console, 'error');

ModuleLogger.error('test error');

expect(spy).toHaveBeenCalledWith('[hover-align] test error');
});

it('should inject module tag to console.info', () => {
const spy = jest.spyOn(console, 'info');

ModuleLogger.info('test info');

expect(spy).toHaveBeenCalledWith('[hover-align] test info');
});

it('should inject module tag to console.log', () => {
const spy = jest.spyOn(console, 'log');

ModuleLogger.log('test log');

expect(spy).toHaveBeenCalledWith('[hover-align] test log');
});

it('should inject module tag to console.warn', () => {
const spy = jest.spyOn(console, 'warn');

ModuleLogger.warn('test warn');

expect(spy).toHaveBeenCalledWith('[hover-align] test warn');
});

afterEach(() => {
jest.restoreAllMocks();
});
});
95 changes: 95 additions & 0 deletions __tests__/showAlignment.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import showAlignment from '@modules/showAlignment';

const PLAYER_TOKEN = true;
const NPC_TOKEN = false;

function initializeToken(hasPlayerOwner, originalGetTooltipText) {
const token = {
actor: {
data: {
data: {
details: {
alignment: 'Chaotic Evil',
},
},
},
hasPlayerOwner: hasPlayerOwner,
},
drawTooltip: jest.fn(() => token._getTooltipText()),
refresh: jest.fn(),
tooltip: { text: '' },
uuid: 'test-token',
_getTooltipText: originalGetTooltipText,
};
return token;
}

describe('showAlignment', () => {
global.game = {
user: { isGM: false },
};

describe('when hovering over a token', () => {
it('should display alignment for GM', () => {
game.user.isGM = true;
const originalGetTooltipText = jest.fn(() => '');
const token = initializeToken(NPC_TOKEN, originalGetTooltipText);

showAlignment(token, true);

expect(token._getTooltipText()).toEqual('hover-align.alignment.title: Chaotic Evil');
expect(token.drawTooltip).toHaveBeenCalled();
expect(token.refresh).toHaveBeenCalled();
});

it('should append alignment to any tooltip set by the core', () => {
game.user.isGM = true;
const originalGetTooltipText = jest.fn(() => '+ 300ft');
const token = initializeToken(NPC_TOKEN, originalGetTooltipText);

showAlignment(token, true);

expect(token._getTooltipText()).toEqual('+ 300ft\nhover-align.alignment.title: Chaotic Evil');
expect(token.drawTooltip).toHaveBeenCalled();
expect(token.refresh).toHaveBeenCalled();
});

it('should display alignment for player when token is owned by a player', () => {
game.user.isGM = false;
const originalGetTooltipText = jest.fn(() => '');
const token = initializeToken(PLAYER_TOKEN, originalGetTooltipText);

showAlignment(token, true);

expect(token._getTooltipText()).toEqual('hover-align.alignment.title: Chaotic Evil');
expect(token.drawTooltip).toHaveBeenCalled();
expect(token.refresh).toHaveBeenCalled();
});

it('should not display alignment for player when token is not owned by a player', () => {
game.user.isGM = false;
const originalGetTooltipText = jest.fn(() => '');
const token = initializeToken(NPC_TOKEN, originalGetTooltipText);

showAlignment(token, true);

expect(token._getTooltipText()).toBeEmpty();
expect(token.drawTooltip).toHaveBeenCalled();
expect(token.refresh).toHaveBeenCalled();
});
});

describe('when hovering out of a token', () => {
it('should reset the tooltip to what is provided by the core', () => {
game.user.isGM = false;
const originalGetTooltipText = jest.fn(() => '+ 300ft');
const token = initializeToken(PLAYER_TOKEN, originalGetTooltipText);

showAlignment(token, false);

expect(token._getTooltipText()).toEqual('+ 300ft');
expect(token.drawTooltip).toHaveBeenCalled();
expect(token.refresh).toHaveBeenCalled();
});
});
});
Binary file added doc/sample.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion lang/en.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"hover-align.title": "HoverAlign"
"hover-align.alignment.title": "Alignment"
}
5 changes: 3 additions & 2 deletions module.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
],
"url": "https://github.com/johnmartel/hover-align",
"manifest": "https://raw.githubusercontent.com/johnmartel/hover-align/master/module.json",
"download": "https://github.com/johnmartel/hover-align/archive/master.zip",
"download": "https://github.com/johnmartel/hover-align/releases/latest/download/hover-align.zip",
"license": "https://github.com/johnmartel/hover-align/blob/master/LICENSE",
"readme": "https://github.com/johnmartel/hover-align/blob/master/README.md",
"bugs": "https://github.com/johnmartel/hover-align/issues"
"bugs": "https://github.com/johnmartel/hover-align/issues",
"changelog": "https://github.com/johnmartel/hover-align/blob/master/CHANGELOG.md"
}
13 changes: 8 additions & 5 deletions modules/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import * as I18nWrapper from './i18nWrapper';
import * as I18nWrapper from './i18nWrapper.js';
import ModuleLogger from './moduleLogger.js';
import showAlignment from './showAlignment.js';

function registerModule() {
console.info('[hover-align] Initializing module');
ModuleLogger.info('Initializing module');

I18nWrapper.setSource(game.i18n);
console.info(I18nWrapper.localize('hover-align.title'));

console.info('[hover-align] Done initializing');
Hooks.on('hoverToken', showAlignment);

ModuleLogger.info('Done initializing');
}

Hooks.on('ready', registerModule);
Hooks.once('ready', registerModule);
23 changes: 23 additions & 0 deletions modules/moduleLogger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const MODULE_TAG = '[hover-align]';

export default class ModuleLogger {
static debug(message) {
console.debug(`${MODULE_TAG} ${message}`);
}

static error(message) {
console.error(`${MODULE_TAG} ${message}`);
}

static info(message) {
console.info(`${MODULE_TAG} ${message}`);
}

static log(message) {
console.log(`${MODULE_TAG} ${message}`);
}

static warn(message) {
console.warn(`${MODULE_TAG} ${message}`);
}
}
44 changes: 44 additions & 0 deletions modules/showAlignment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import * as I18nWrapper from './i18nWrapper.js';
import ModuleLogger from './moduleLogger.js';

function getTooltipTextFromOtherStuffThanElevation() {
const elevationTooltip = this.originalGetTooltipText();
let tooltip = '';
if (elevationTooltip.length > 0) {
tooltip = `${elevationTooltip}\n`;
}
return `${tooltip}${I18nWrapper.localize('hover-align.alignment.title')}: ${this.actor.data.data.details.alignment}`;
}

function resetTokenTooltip(token) {
ModuleLogger.debug(`Reset token ${token.uuid} tooltip`);

token.tooltip.text = '';

// istanbul ignore next: this is a safety net in case `originalGetTooltipText` gets bumped by core
if (token.originalGetTooltipText) {
token._getTooltipText = token.originalGetTooltipText;
}
}

function displayTokenTooltipWithAlignment(token) {
ModuleLogger.debug(`Token ${token.uuid} tooltip can be displayed`);

token.originalGetTooltipText = token._getTooltipText;
token._getTooltipText = getTooltipTextFromOtherStuffThanElevation.bind(token);
}

export default function showAlignment(token, isHovering) {
if (!isHovering) {
resetTokenTooltip(token);
} else {
ModuleLogger.debug(`Check if token ${token.uuid} tooltip can be displayed`);

if (token.actor.hasPlayerOwner || game.user.isGM) {
displayTokenTooltipWithAlignment(token);
}
}

token.drawTooltip();
token.refresh();
}

0 comments on commit 468f52a

Please sign in to comment.