Add files via upload

This commit is contained in:
CK 2020-06-24 14:13:41 -04:00 committed by GitHub
parent 71fe2eb170
commit 11ad5fd923
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 2171 additions and 0 deletions

32
gulpfile.js Normal file
View file

@ -0,0 +1,32 @@
const gulp = require('gulp');
const less = require('gulp-less');
/* ----------------------------------------- */
/* Compile LESS
/* ----------------------------------------- */
const SW5E_LESS = ["less/*.less"];
function compileLESS() {
return gulp.src("less/sw5e.less")
.pipe(less())
.pipe(gulp.dest("./"))
}
const css = gulp.series(compileLESS);
/* ----------------------------------------- */
/* Watch Updates
/* ----------------------------------------- */
function watchUpdates() {
gulp.watch(SW5E_LESS, css);
}
/* ----------------------------------------- */
/* Export Tasks
/* ----------------------------------------- */
exports.default = gulp.series(
gulp.parallel(css),
watchUpdates
);
exports.css = css;

1369
sw5e.css Normal file

File diff suppressed because it is too large Load diff

206
sw5e.js Normal file
View file

@ -0,0 +1,206 @@
/**
* The Star Wars 5th Edition game system for Foundry Virtual Tabletop
* Author: Kakeman89
* Software License: GNU GPLv3
* Content License: https://media.wizards.com/2016/downloads/SW5ERD-OGL_V5.1.pdf
* Repository: https://gitlab.com/foundrynet/sw5e
* Issue Tracker: https://gitlab.com/foundrynet/sw5e/issues
*/
// Import Modules
import { SW5E } from "./module/config.js";
import { registerSystemSettings } from "./module/settings.js";
import { preloadHandlebarsTemplates } from "./module/templates.js";
import { _getInitiativeFormula } from "./module/combat.js";
import { measureDistance, getBarAttribute } from "./module/canvas.js";
import { Actor5e } from "./module/actor/entity.js";
import { ActorSheet5eCharacter } from "./module/actor/sheets/character.js";
import { Item5e } from "./module/item/entity.js";
import { ItemSheet5e } from "./module/item/sheet.js";
import { ActorSheet5eNPC } from "./module/actor/sheets/npc.js";
import { Dice5e } from "./module/dice.js";
import * as chat from "./module/chat.js";
import * as migrations from "./module/migration.js";
/* -------------------------------------------- */
/* Foundry VTT Initialization */
/* -------------------------------------------- */
Hooks.once("init", function() {
console.log(`SW5e | Initializing Star Wars 5th Edition System\n${SW5E.ASCII}`);
// Create a SW5E namespace within the game global
game.sw5e = {
Actor5e,
Dice5e,
Item5e,
migrations,
rollItemMacro
};
// Record Configuration Values
CONFIG.SW5E = SW5E;
CONFIG.Actor.entityClass = Actor5e;
CONFIG.Item.entityClass = Item5e;
// Register System Settings
registerSystemSettings();
// Patch Core Functions
Combat.prototype._getInitiativeFormula = _getInitiativeFormula;
// Register sheet application classes
Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("sw5e", ActorSheet5eCharacter, { types: ["character"], makeDefault: true });
Actors.registerSheet("sw5e", ActorSheet5eNPC, { types: ["npc"], makeDefault: true });
Items.unregisterSheet("core", ItemSheet);
Items.registerSheet("sw5e", ItemSheet5e, {makeDefault: true});
// Preload Handlebars Templates
preloadHandlebarsTemplates();
});
/* -------------------------------------------- */
/* Foundry VTT Setup */
/* -------------------------------------------- */
/**
* This function runs after game data has been requested and loaded from the servers, so entities exist
*/
Hooks.once("setup", function() {
// Localize CONFIG objects once up-front
const toLocalize = [
"abilities", "alignments", "conditionTypes", "consumableTypes", "currencies", "damageTypes", "distanceUnits", "equipmentTypes",
"healingTypes", "itemActionTypes", "limitedUsePeriods", "senses", "skills", "powerComponents", "powerLevels", "powerPreparationModes",
"powerSchools", "powerScalingModes", "targetTypes", "timePeriods", "weaponProperties", "weaponTypes", "languages", "polymorphSettings",
"armorProficiencies", "weaponProficiencies", "toolProficiencies", "abilityActivationTypes", "actorSizes", "proficiencyLevels"
];
for ( let o of toLocalize ) {
CONFIG.SW5E[o] = Object.entries(CONFIG.SW5E[o]).reduce((obj, e) => {
obj[e[0]] = game.i18n.localize(e[1]);
return obj;
}, {});
}
});
/* -------------------------------------------- */
/**
* Once the entire VTT framework is initialized, check to see if we should perform a data migration
*/
Hooks.once("ready", function() {
// Determine whether a system migration is required and feasible
const currentVersion = game.settings.get("sw5e", "systemMigrationVersion");
const NEEDS_MIGRATION_VERSION = 0.84;
const COMPATIBLE_MIGRATION_VERSION = 0.80;
let needMigration = (currentVersion < NEEDS_MIGRATION_VERSION) || (currentVersion === null);
const canMigrate = currentVersion >= COMPATIBLE_MIGRATION_VERSION;
// Perform the migration
if ( needMigration && game.user.isGM ) {
if ( currentVersion && (currentVersion < COMPATIBLE_MIGRATION_VERSION) ) {
ui.notifications.error(`Your SW5E system data is from too old a Foundry version and cannot be reliably migrated to the latest version. The process will be attempted, but errors may occur.`, {permanent: true});
}
migrations.migrateWorld();
}
// Wait to register hotbar drop hook on ready so that modules could register earlier if they want to
Hooks.on("hotbarDrop", (bar, data, slot) => create5eMacro(data, slot));
});
/* -------------------------------------------- */
/* Canvas Initialization */
/* -------------------------------------------- */
Hooks.on("canvasInit", function() {
// Extend Diagonal Measurement
canvas.grid.diagonalRule = game.settings.get("sw5e", "diagonalMovement");
SquareGrid.prototype.measureDistance = measureDistance;
// Extend Token Resource Bars
Token.prototype.getBarAttribute = getBarAttribute;
});
/* -------------------------------------------- */
/* Other Hooks */
/* -------------------------------------------- */
Hooks.on("renderChatMessage", (app, html, data) => {
// Display action buttons
chat.displayChatActionButtons(app, html, data);
// Highlight critical success or failure die
chat.highlightCriticalSuccessFailure(app, html, data);
// Optionally collapse the content
if (game.settings.get("sw5e", "autoCollapseItemCards")) html.find(".card-content").hide();
});
Hooks.on("getChatLogEntryContext", chat.addChatMessageContextOptions);
Hooks.on("renderChatLog", (app, html, data) => Item5e.chatListeners(html));
Hooks.on('getActorDirectoryEntryContext', Actor5e.addDirectoryContextOptions);
/* -------------------------------------------- */
/* Hotbar Macros */
/* -------------------------------------------- */
/**
* Create a Macro from an Item drop.
* Get an existing item macro if one exists, otherwise create a new one.
* @param {Object} data The dropped data
* @param {number} slot The hotbar slot to use
* @returns {Promise}
*/
async function create5eMacro(data, slot) {
if ( data.type !== "Item" ) return;
if (!( "data" in data ) ) return ui.notifications.warn("You can only create macro buttons for owned Items");
const item = data.data;
// Create the macro command
const command = `game.sw5e.rollItemMacro("${item.name}");`;
let macro = game.macros.entities.find(m => (m.name === item.name) && (m.command === command));
if ( !macro ) {
macro = await Macro.create({
name: item.name,
type: "script",
img: item.img,
command: command,
flags: {"sw5e.itemMacro": true}
});
}
game.user.assignHotbarMacro(macro, slot);
return false;
}
/* -------------------------------------------- */
/**
* Create a Macro from an Item drop.
* Get an existing item macro if one exists, otherwise create a new one.
* @param {string} itemName
* @return {Promise}
*/
function rollItemMacro(itemName) {
const speaker = ChatMessage.getSpeaker();
let actor;
if ( speaker.token ) actor = game.actors.tokens[speaker.token];
if ( !actor ) actor = game.actors.get(speaker.actor);
// Get matching items
const items = actor ? actor.items.filter(i => i.name === itemName) : [];
if ( items.length > 1 ) {
ui.notifications.warn(`Your controlled Actor ${actor.name} has more than one Item with name ${itemName}. The first matched item will be chosen.`);
} else if ( items.length === 0 ) {
return ui.notifications.warn(`Your controlled Actor does not have an item named ${itemName}`);
}
const item = items[0];
// Trigger the item roll
if ( item.data.type === "power" ) return actor.usePower(item);
return item.roll();
}

76
system.json Normal file
View file

@ -0,0 +1,76 @@
{
"name": "sw5e",
"title": "Star Wars 5th Edition",
"description": "A comprehensive game system for running games of Star wars 5th Edition in the Foundry VTT environment.",
"version": 0.88,
"author": "Kakeman89",
"scripts": [],
"esmodules": ["sw5e.js"],
"styles": ["sw5e.css"],
"packs": [
{
"name": "heroes",
"label": "Starter Heroes",
"system": "dnd5e",
"path": "./packs/heroes.db",
"entity": "Actor"
},
{
"name": "beasts",
"label": "Beasts",
"system": "sw5e",
"path": "./packs/beasts.db",
"entity": "Actor"
},
{
"name": "items",
"label": "Items",
"system": "sw5e",
"path": "./packs/items.db",
"entity": "Item"
},
{
"name": "tradegoods",
"label": "Trade Goods (SRD)",
"system": "sw5e",
"path": "./packs/tradegoods.db",
"entity": "Item"
},
{
"name": "powers",
"label": "Casting",
"system": "sw5e",
"path": "./packs/powers.db",
"entity": "Item"
},
{
"name": "classes",
"label": "Classes",
"system": "sw5e",
"path": "./packs/classes.db",
"entity": "Item"
},
{
"name": "classfeatures",
"label": "Class Features (SRD)",
"system": "sw5e",
"path": "./packs/classfeatures.db",
"entity": "Item"
}
],
"languages": [
{
"lang": "en",
"name": "English",
"path": "lang/en.json"
}
],
"socket": true,
"initiative": "1d20 + @abilities.dex.mod + @attributes.init.value + (@abilities.dex.value / 100)",
"gridDistance": 5,
"gridUnits": "ft",
"primaryTokenAttribute": "attributes.hp",
"secondaryTokenAttribute": null,
"minimumCoreVersion": "0.5.2",
"compatibleCoreVersion": "0.6.4"
}

488
template.json Normal file
View file

@ -0,0 +1,488 @@
{
"Actor": {
"types": ["character", "npc"],
"templates": {
"common": {
"abilities": {
"str": {
"value": 10,
"proficient": 0
},
"dex": {
"value": 10,
"proficient": 0
},
"con": {
"value": 10,
"proficient": 0
},
"int": {
"value": 10,
"proficient": 0
},
"wis": {
"value": 10,
"proficient": 0
},
"cha": {
"value": 10,
"proficient": 0
}
},
"attributes": {
"ac": {
"min": 0
},
"hp": {
"value": 10,
"min": 0,
"max": 10,
"temp": 0,
"tempmax": 0
},
"init": {
"value": 0,
"bonus": 0
},
"speed": {
"value": "30 ft",
"special": ""
},
"powercasting": "int"
},
"details": {
"alignment": "",
"biography": {
"value": "",
"public": ""
},
"race": ""
},
"skills": {
"acr": {
"value": 0,
"ability": "dex"
},
"ani": {
"value": 0,
"ability": "wis"
},
"ath": {
"value": 0,
"ability": "str"
},
"dec": {
"value": 0,
"ability": "cha"
},
"ins": {
"value": 0,
"ability": "wis"
},
"itm": {
"value": 0,
"ability": "cha"
},
"inv": {
"value": 0,
"ability": "int"
},
"lor": {
"value": 0,
"ability": "int"
},
"med": {
"value": 0,
"ability": "wis"
},
"nat": {
"value": 0,
"ability": "int"
},
"pil": {
"value": 0,
"ability": "int"
},
"prc": {
"value": 0,
"ability": "wis"
},
"prf": {
"value": 0,
"ability": "cha"
},
"per": {
"value": 0,
"ability": "cha"
},
"slt": {
"value": 0,
"ability": "dex"
},
"ste": {
"value": 0,
"ability": "dex"
},
"sur": {
"value": 0,
"ability": "wis"
},
"tec": {
"value": 0,
"ability": "int"
}
},
"traits": {
"size": "med",
"senses": "",
"languages": {
"value": [],
"custom": ""
},
"di": {
"value": [],
"custom": ""
},
"dr": {
"value": [],
"custom": ""
},
"dv": {
"value": [],
"custom": ""
},
"ci": {
"value": [],
"custom": ""
}
},
"currency": {
"gc": 0
},
"powers": {
"power1": {
"value": 0,
"max": 0,
"override": null
},
"power2": {
"value": 0,
"max": 0,
"override": null
},
"power3": {
"value": 0,
"max": 0,
"override": null
},
"power4": {
"value": 0,
"max": 0,
"override": null
},
"power5": {
"value": 0,
"max": 0,
"override": null
},
"power6": {
"value": 0,
"max": 0,
"override": null
},
"power7": {
"value": 0,
"max": 0,
"override": null
},
"power8": {
"value": 0,
"max": 0,
"override": null
},
"power9": {
"value": 0,
"max": 0,
"override": null
},
"pact": {
"value": 0,
"max": 0,
"override": null
}
},
"bonuses": {
"mwak": {
"attack": "",
"damage": ""
},
"rwak": {
"attack": "",
"damage": ""
},
"mpak": {
"attack": "",
"damage": ""
},
"rpak": {
"attack": "",
"damage": ""
},
"abilities": {
"check": "",
"save": "",
"skill": ""
},
"power": {
"dc": ""
}
}
}
},
"character": {
"templates": ["common"],
"attributes": {
"death": {
"success": 0,
"failure": 0
},
"exhaustion": 0,
"inspiration": 0
},
"details": {
"background": "",
"xp": {
"value": 0,
"min": 0,
"max": 300
},
"trait": "",
"ideal": "",
"bond": "",
"flaw": ""
},
"resources": {
"primary": {
"value": 0,
"max": 0,
"sr": 0,
"lr": 0
},
"secondary": {
"value": 0,
"max": 0,
"sr": 0,
"lr": 0
},
"tertiary": {
"value": 0,
"max": 0,
"sr": 0,
"lr": 0
}
},
"traits": {
"weaponProf": {
"value": [],
"custom": ""
},
"armorProf": {
"value": [],
"custom": ""
},
"toolProf": {
"value": [],
"custom": ""
}
}
},
"npc": {
"templates": ["common"],
"details": {
"type": "",
"environment": "",
"cr": 1,
"powerLevel": 0,
"xp": {
"value": 10
},
"source": ""
},
"resources": {
"legact": {
"value": 0,
"max": 0
},
"legres": {
"value": 0,
"max": 0
},
"lair": {
"value": 0,
"initiative": 0
}
}
}
},
"Item": {
"types": ["weapon", "equipment", "consumable", "tool", "loot", "class", "power", "feat", "backpack"],
"templates": {
"itemDescription": {
"description": {
"value": "",
"chat": "",
"unidentified": ""
},
"source": ""
},
"physicalItem": {
"quantity": 1,
"weight": 0,
"price": 0,
"attuned": false,
"equipped": false,
"rarity": "",
"identified": true
},
"activatedEffect": {
"activation": {
"type": "",
"cost": 0,
"condition": ""
},
"duration": {
"value": null,
"units": ""
},
"target": {
"value": null,
"units": "",
"type": ""
},
"range": {
"value": null,
"long": null,
"units": ""
},
"uses": {
"value": 0,
"max": 0,
"per": null
}
},
"action": {
"ability": null,
"actionType": null,
"attackBonus": 0,
"chatFlavor": "",
"critical": null,
"damage": {
"parts": [],
"versatile": ""
},
"formula": "",
"save": {
"ability": "",
"dc": null,
"scaling": "power"
}
}
},
"backpack": {
"templates": ["itemDescription", "physicalItem"],
"capacity": {
"type": "weight",
"value": 0,
"weightless": false
},
"currency": {
"gc": 0
}
},
"class": {
"templates": ["itemDescription"],
"levels": 1,
"subclass": "",
"hitDice": "d6",
"hitDiceUsed": 0,
"skills": {
"number": 2,
"choices": [],
"value": []
},
"powercasting": "none"
},
"consumable": {
"templates": ["itemDescription", "physicalItem", "activatedEffect", "action"],
"consumableType": "potion",
"uses": {
"value": 0,
"max": 0,
"per": null,
"autoUse": true,
"autoDestroy": true
}
},
"equipment": {
"templates": ["itemDescription", "physicalItem", "activatedEffect", "action"],
"armor": {
"type": "light",
"value": 10,
"dex": null
},
"strength": 0,
"stealth": false,
"proficient": true
},
"feat": {
"templates": ["itemDescription", "activatedEffect", "action"],
"requirements": "",
"recharge": {
"value": null,
"charged": false
}
},
"loot": {
"templates": ["itemDescription", "physicalItem"]
},
"tool": {
"templates": ["itemDescription", "physicalItem"],
"ability": "int",
"chatFlavor": "",
"proficient": 0
},
"power": {
"templates": ["itemDescription", "activatedEffect", "action"],
"level": 1,
"school": "",
"components": {
"value": "",
"vocal": false,
"somatic": false,
"material": false,
"ritual": false,
"concentration": false
},
"materials": {
"value": "",
"consumed": false,
"cost": 0,
"supply": 0
},
"preparation": {
"mode": null,
"prepared": false
},
"scaling": {
"mode": null,
"formula": null
}
},
"weapon": {
"templates": ["itemDescription", "physicalItem" ,"activatedEffect", "action"],
"weaponType": "simpleM",
"properties": {},
"proficient": true
}
}
}