Fix various issues with rolls and compendiums
All checks were successful
Release Creation / build (release) Successful in 57s

This commit is contained in:
2025-08-24 16:19:35 +02:00
parent 8a5b402388
commit 668da28d2c
21 changed files with 392 additions and 101 deletions

View File

@@ -0,0 +1,112 @@
[
{
"name": "Autocannon, Light",
"tech_age": "Late Mechanical",
"cost": 10000,
"range": "heavy",
"damage": "5d6",
"mag": 100,
"ammo_cost": 1000,
"aspect": "Auto, AV 3d6+1.",
"description": "This weapon can fire bursts of shells at high rates of fire. It is common to find this mounted on aircraft as a dogfighting weapon, as well as on light armored vehicles as a support weapon for infantry."
},
{
"name": "Autocannon, Heavy",
"tech_age": "Late Mechanical",
"cost": 20000,
"range": "heavy",
"damage": "5d6",
"mag": 50,
"ammo_cost": 2000,
"aspect": "Auto, AV 3d6+2.",
"description": "A larger version of the light autocannon, often found on light armored vehicles, naval vessels, and ground attack aircraft."
},
{
"name": "Cannon, Light",
"tech_age": "Early Mechanical",
"cost": 15000,
"range": "heavy",
"damage": "5d6",
"mag": 40,
"ammo_cost": 2000,
"aspect": "AV 4d6+1.",
"description": "A multipurpose support weapon usually mounted on a vehicle or gun carriage."
},
{
"name": "Cannon, Heavy",
"tech_age": "Early Mechanical",
"cost": 30000,
"range": "heavy",
"damage": "6d6",
"mag": 20,
"ammo_cost": 3000,
"aspect": "AV 5d6.",
"description": "This cannon is a main battle tanks primary weapon. It is often used as field artillery as well."
},
{
"name": "Heavy Flamer",
"tech_age": "Late Mechanical",
"cost": 1000,
"range": "Rifle",
"damage": "3d6",
"mag": 5,
"ammo_cost": 25,
"aspect": "AV 2d6, Fire. ",
"description": "A brutal close-in anti-infantry weapon used to flush out fortifications and defend against infantry attack in built-up areas. Vehicles that carry flamethrowers are usually the first to be targeted by enemy infantry."
},
{
"name": "Grenade Launcher",
"tech_age": "Late Mechanical",
"cost": 400,
"range": "Rifle",
"damage": "According to grenade",
"mag": 50,
"ammo_cost": 0,
"aspect": "",
"description": "A light support weapon mounted on many vehicles. This version has a 50 round belt magazine. Many vehicles mount smoke grenade launchers as defensive weapons."
},
{
"name": "Guided Anti-Tank Missile",
"tech_age": "Early Atomic",
"cost": 4000,
"range": "heavy",
"damage": "5d6",
"mag": 4,
"ammo_cost": 200,
"aspect": "Blast, AV 5d6. ",
"description": "This vehicle mounted version of the portable anti-tank missile launcher has a magazine of four missiles. A system like this is often mounted on a light vehicle to give it significant anti-armor punch."
},
{
"name": "Laser Cannon",
"tech_age": "Early Space",
"cost": 10000,
"range": "heavy",
"damage": "5d6",
"mag": 100,
"ammo_cost": 100,
"aspect": "AV 4d6+2.",
"description": "The Early Space Ages replacement for all but the heaviest cannons, this vehicle weapon is highly efficient, and can be recharged from any power grid. This makes it the darling of logistics officers in any military where it is found."
},
{
"name": "Laser, Support",
"tech_age": "Early Space",
"cost": 5000,
"range": "heavy",
"damage": "5d6",
"mag": 100,
"ammo_cost": 100,
"aspect": "AV 3d6+1.",
"description": "This vehicle mounted version of the portable support laser lacks auto fire capabilities but has a nearly inexhaustible ammunition supply."
},
{
"name": "Rocket Launcher",
"tech_age": "Early Atomic",
"cost": 2000,
"range": "heavy",
"damage": "4d6",
"mag": 1,
"ammo_cost": 150,
"aspect": "Greater Blast, AV 3d6.",
"description": "A portable rocket launcher utilizing unguided munitions. Rocket payloads are considered high explosive and are not particularly effective against armored vehicles. Vehicle-mounted versions usually have 12 or 24 shots before requiring reloading."
}
]

View File

@@ -351,6 +351,7 @@
}
},
"Label": {
"formula": "Formula",
"damages": "Damages",
"modifications": "Modifications",
"abilities": "Abilities",
@@ -648,6 +649,12 @@
},
"weaponType": {
"label": "Type"
},
"ammoCost": {
"label": "Ammo Cost"
},
"magazine": {
"label": "Mag"
}
},
"Range": {

View File

@@ -12,6 +12,8 @@ export default class FTLNomadStarshipSheet extends FTLNomadActorSheet {
contentClasses: ["starship-content"],
},
actions: {
createEquipment: FTLNomadStarshipSheet.#onCreateEquipment,
createWeapon: FTLNomadStarshipSheet.#onCreateWeapon,
},
}
@@ -23,14 +25,17 @@ export default class FTLNomadStarshipSheet extends FTLNomadActorSheet {
tabs: {
template: "templates/generic/tab-navigation.hbs",
},
equipment: {
template: "systems/fvtt-ftl-nomad/templates/starship-equipment.hbs",
},
description: {
template: "systems/fvtt-ftl-nomad/templates/starship-description.hbs",
},
}
/** @override */
tabGroups = {
sheet: "description",
/** @override */
tabGroups = {
sheet: "equipment",
}
/**
@@ -39,6 +44,7 @@ export default class FTLNomadStarshipSheet extends FTLNomadActorSheet {
*/
#getTabs() {
const tabs = {
equipment: { id: "equipment", group: "sheet", icon: "fa-solid fa-shapes", label: "FTLNOMAD.Label.equipment" },
description: { id: "description", group: "sheet", icon: "fa-solid fa-book", label: "FTLNOMAD.Label.description" },
}
for (const v of Object.values(tabs)) {
@@ -69,6 +75,13 @@ export default class FTLNomadStarshipSheet extends FTLNomadActorSheet {
switch (partId) {
case "main":
break
case "equipment":
context.tab = context.tabs.equipment
context.weapons = doc.itemTypes.weapon
context.weapons.sort((a, b) => a.name.localeCompare(b.name))
context.equipments = doc.itemTypes.equipment
context.equipments.sort((a, b) => a.name.localeCompare(b.name))
break
case "description":
context.tab = context.tabs.description
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.description, { async: true })
@@ -78,22 +91,31 @@ export default class FTLNomadStarshipSheet extends FTLNomadActorSheet {
return context
}
static #onCreateEquipment(event, target) {
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newEquipment"), type: "equipment" }])
}
static #onCreateWeapon(event, target) {
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newWeapon"), type: "weapon" }])
}
async _onRoll(event, target) {
const rollType = $(event.currentTarget).data("roll-type")
let rollType = $(event.currentTarget).data("roll-type")
let item
let formula
let roll
console.log("rollType", rollType)
switch (rollType) {
case "damage":
let li = $(event.currentTarget).parents(".item");
item = this.actor.items.get(li.data("item-id"));
break
case "starship-guns":
formula = this.actor.system.guns
// Rolll the damage
roll = new Roll(formula)
await roll.evaluate()
roll.toMessage( { flavor: `Starship ${this.actor.name} : Guns Damage` })
item = { name: "Starship Guns", type: "weapon", system: { damage: this.actor.system.guns, rangeType: "heavyweapon" } }
rollType = "damage"
break
default:
throw new Error(`Unknown roll type ${rollType}`)
}
await this.document.system.roll(rollType, item)
}

View File

@@ -33,8 +33,8 @@ export default class FTLNomadVehicleSheet extends FTLNomadActorSheet {
},
}
/** @override */
tabGroups = {
/** @override */
tabGroups = {
sheet: "equipment",
}

View File

@@ -2,15 +2,15 @@ export const SYSTEM_ID = "fvtt-ftl-nomad"
export const ASCII = `
░▒▓████████▓▒░▒▓████████▓▒░▒▓█▓▒░ ░▒▓███████▓▒░ ░▒▓██████▓▒░░▒▓██████████████▓▒░ ░▒▓██████▓▒░░▒▓███████▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓████████▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░ ░▒▓█▓▒░░▒▓█▓▒░░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓███████▓▒░
░▒▓████████▓▒░▒▓████████▓▒░▒▓█▓▒░ ░▒▓███████▓▒░ ░▒▓██████▓▒░░▒▓██████████████▓▒░ ░▒▓██████▓▒░░▒▓███████▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓████████▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░ ░▒▓█▓▒░░▒▓█▓▒░░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓███████▓▒░
`
@@ -52,12 +52,12 @@ export const WEAPON_TYPES = {
}
export const WEAPON_RANGE = {
"handgun": { id: "handgun", label: "FTLNOMAD.Weapon.Range.Handgun", range: {close: 0, near:0, far:-2} },
"assault": { id: "assault", label: "FTLNOMAD.Weapon.Range.Assault", range: {close: -2, near:0, far:-1, distant: -2} },
"rifle": { id: "rifle", label: "FTLNOMAD.Weapon.Range.Rifle", range: {close: -3, near:0, far:0, distant: -1} },
"melee": { id: "melee", label: "FTLNOMAD.Weapon.Range.Melee", range: {close: 0} },
"heavyweapon": { id: "heavyweapon", label: "FTLNOMAD.Weapon.Range.HeavyWeapon", range: {near:-1, far:0, distant: 0} },
"thrownweapon": { id: "thrownweapon", label: "FTLNOMAD.Weapon.Range.ThrownWeapon", range: {close: 0, near:-1} }
"handgun": { id: "handgun", label: "FTLNOMAD.Weapon.Range.Handgun", range: { close: 0, near: 0, far: -2 } },
"assault": { id: "assault", label: "FTLNOMAD.Weapon.Range.Assault", range: { close: -2, near: 0, far: -1, distant: -2 } },
"rifle": { id: "rifle", label: "FTLNOMAD.Weapon.Range.Rifle", range: { close: -3, near: 0, far: 0, distant: -1 } },
"melee": { id: "melee", label: "FTLNOMAD.Weapon.Range.Melee", range: { close: 0 } },
"heavyweapon": { id: "heavyweapon", label: "FTLNOMAD.Weapon.Range.HeavyWeapon", range: { near: -1, far: 0, distant: 0 } },
"thrownweapon": { id: "thrownweapon", label: "FTLNOMAD.Weapon.Range.ThrownWeapon", range: { close: 0, near: -1 } }
}
export const ATTACK_MODIFIERS = {
@@ -73,35 +73,35 @@ export const ATTACK_MODIFIERS = {
}
export const TRIAGE_RESULTS = {
"none": { id: "none", dice:0, label: "FTLNOMAD.TriageResults.None" },
"death": { id: "death", dice:3, label: "FTLNOMAD.TriageResults.Death" },
"critical": { id: "critical", dice:4, label: "FTLNOMAD.TriageResults.Critical" },
"severe": { id: "severe", dice:7, label: "FTLNOMAD.TriageResults.Severe" },
"moderate": { id: "moderate", dice:10, label: "FTLNOMAD.TriageResults.Moderate" },
"fleshwound": { id: "fleshwound", dice:12, label: "FTLNOMAD.TriageResults.FleshWound" }
"none": { id: "none", dice: 0, label: "FTLNOMAD.TriageResults.None" },
"death": { id: "death", dice: 3, label: "FTLNOMAD.TriageResults.Death" },
"critical": { id: "critical", dice: 4, label: "FTLNOMAD.TriageResults.Critical" },
"severe": { id: "severe", dice: 7, label: "FTLNOMAD.TriageResults.Severe" },
"moderate": { id: "moderate", dice: 10, label: "FTLNOMAD.TriageResults.Moderate" },
"fleshwound": { id: "fleshwound", dice: 12, label: "FTLNOMAD.TriageResults.FleshWound" }
}
export const CREATURE_TERRAIN_TYPES = {
"cave": { id: "cave", label: "FTLNOMAD.Creature.Terrain.Cave", niche:0, size: 0 },
"coast": { id: "coast", label: "FTLNOMAD.Creature.Terrain.Coast", niche:1, size: 0 },
"desert": { id: "desert", label: "FTLNOMAD.Creature.Terrain.Desert", niche:-1, size: -1 },
"forest": { id: "forest", label: "FTLNOMAD.Creature.Terrain.Forest", niche:1, size: 1 },
"jungle": { id: "jungle", label: "FTLNOMAD.Creature.Terrain.Jungle", niche:1, size: 1 },
"mixed": { id: "mixed", label: "FTLNOMAD.Creature.Terrain.Mixed", niche:0, size: 0 },
"mountain": { id: "mountain", label: "FTLNOMAD.Creature.Terrain.Mountain", niche:-1, size: -1 },
"ocean": { id: "ocean", label: "FTLNOMAD.Creature.Terrain.Ocean", niche:-1, size: 1 },
"river": { id: "river", label: "FTLNOMAD.Creature.Terrain.River", niche:1, size: 0 },
"ruins": { id: "ruins", label: "FTLNOMAD.Creature.Terrain.Ruins", niche:0, size: 1 },
"savannah": { id: "savannah", label: "FTLNOMAD.Creature.Terrain.Savannah", niche:0, size: 1 },
"shallows": { id: "shallows", label: "FTLNOMAD.Creature.Terrain.Shallows", niche:1, size: 0 },
"swamp": { id: "swamp", label: "FTLNOMAD.Creature.Terrain.Swamp", niche:1, size: 1 }
"cave": { id: "cave", label: "FTLNOMAD.Creature.Terrain.Cave", niche: 0, size: 0 },
"coast": { id: "coast", label: "FTLNOMAD.Creature.Terrain.Coast", niche: 1, size: 0 },
"desert": { id: "desert", label: "FTLNOMAD.Creature.Terrain.Desert", niche: -1, size: -1 },
"forest": { id: "forest", label: "FTLNOMAD.Creature.Terrain.Forest", niche: 1, size: 1 },
"jungle": { id: "jungle", label: "FTLNOMAD.Creature.Terrain.Jungle", niche: 1, size: 1 },
"mixed": { id: "mixed", label: "FTLNOMAD.Creature.Terrain.Mixed", niche: 0, size: 0 },
"mountain": { id: "mountain", label: "FTLNOMAD.Creature.Terrain.Mountain", niche: -1, size: -1 },
"ocean": { id: "ocean", label: "FTLNOMAD.Creature.Terrain.Ocean", niche: -1, size: 1 },
"river": { id: "river", label: "FTLNOMAD.Creature.Terrain.River", niche: 1, size: 0 },
"ruins": { id: "ruins", label: "FTLNOMAD.Creature.Terrain.Ruins", niche: 0, size: 1 },
"savannah": { id: "savannah", label: "FTLNOMAD.Creature.Terrain.Savannah", niche: 0, size: 1 },
"shallows": { id: "shallows", label: "FTLNOMAD.Creature.Terrain.Shallows", niche: 1, size: 0 },
"swamp": { id: "swamp", label: "FTLNOMAD.Creature.Terrain.Swamp", niche: 1, size: 1 }
}
export const CREATURE_NICHES = {
"prey": { id: "prey", label: "FTLNOMAD.Creature.Niche.Prey" },
"opportunist": { id: "opportunist", label: "FTLNOMAD.Creature.Niche.Opportunist" },
"herbivore": { id: "herbivore", label: "FTLNOMAD.Creature.Niche.Herbivore" },
"predator": { id: "predator", label: "FTLNOMAD.Creature.Niche.Predator" }
"predator": { id: "predator", label: "FTLNOMAD.Creature.Niche.Predator" }
}
export const CREATURE_SIZES = {
@@ -114,11 +114,11 @@ export const CREATURE_SIZES = {
}
export const MODIFIER_CHOICES = {
"easy": { id: "easy", label: "FTLNOMAD.Label.Easy", value :"1" },
"easy": { id: "easy", label: "FTLNOMAD.Label.Easy", value: "1" },
"moderate": { id: "moderate", label: "FTLNOMAD.Label.Moderate", value: "0" },
"difficult": { id: "difficult", label: "FTLNOMAD.Label.Difficult", value: "-1" },
"formidable": { id: "formidable", label: "FTLNOMAD.Label.Formidable", value: "-2" },
"impossible": { id: "impossible", label: "FTLNOMAD.Label.Impossible", value: "-4" }
"impossible": { id: "impossible", label: "FTLNOMAD.Label.Impossible", value: "-4" }
}
export const STARSHIP_HULL = {

View File

@@ -62,7 +62,8 @@ export default class FTLNomadRoll extends Roll {
static updateFullFormula(options) {
let fullFormula
fullFormula = `${options.formula} + ${options.rollItem.value} + ${options.skillModifier}D + ${options.rangeModifier}D + ${options.numericModifier}D`
let mod = options.rollItem?.value || 0
fullFormula = `${options.formula} + ${options.skillModifier}D + ${mod} + ${options.rangeModifier}D + ${options.numericModifier}D`
// Replace all the "+ -" with "-"
fullFormula = fullFormula.replace(/\+\s*-/g, "- ")
$('#roll-dialog-full-formula').text(fullFormula)
@@ -85,20 +86,15 @@ export default class FTLNomadRoll extends Roll {
*/
static async prompt(options = {}) {
let formula = "2d6"
let actor = game.actors.get(options.actorId)
switch (options.rollType) {
case "skill":
break
case "damage":
let formula = options.rollItem.system.damage
let damageRoll = new Roll(formula)
await damageRoll.evaluate()
await damageRoll.toMessage({
flavor: `${options.rollItem.name} - Damage Roll`
});
return
options.weapon = foundry.utils.duplicate(options.rollItem)
break
case "weapon":
let actor = game.actors.get(options.actorId)
options.weapon = foundry.utils.duplicate(options.rollItem)
options.rollItem = actor.system.skills.combat
break
@@ -106,6 +102,7 @@ export default class FTLNomadRoll extends Roll {
break
}
options.actor = actor
const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes)
const fieldRollMode = new foundry.data.fields.StringField({
choices: rollModes,
@@ -116,7 +113,7 @@ export default class FTLNomadRoll extends Roll {
const choiceModifier = SYSTEM.MODIFIER_CHOICES
let choiceRangeModifier = {}
let rangeModifier = 0
if ( options.weapon) {
if (options.weapon) {
// Build the range modifiers
let range = SYSTEM.WEAPON_RANGE[options.weapon.system.rangeType]
for (let [key, value] of Object.entries(range.range)) {
@@ -192,7 +189,7 @@ export default class FTLNomadRoll extends Roll {
$(".select-combat-option").change(event => {
let field = $(event.target).data("field")
let modifier = SYSTEM.ATTACK_MODIFIERS[field]
if ( event.target.checked) {
if (event.target.checked) {
options.numericModifier += modifier
} else {
options.numericModifier -= modifier
@@ -212,13 +209,20 @@ export default class FTLNomadRoll extends Roll {
if (Hooks.call("fvtt-ftl-nomad.preRoll", options, rollData) === false) return
let diceFormula = `${2+Math.abs(options.numericModifier)}D6`
if ( options.numericModifier > 0 ) {
diceFormula += `kh2 + ${options.rollItem.value}`
options.numericModifier = Number(rollData.numericModifier) || 0
options.skillModifier = Number(rollData.skillModifier) || 0
options.rangeModifier = Number(rollData.rangeModifier) || 0
let mod = options.rollItem?.value || 0
// Build the dice formula
let diceFormula = `${2 + Math.abs(options.skillModifier)}D6`
if (options.skillModifier > 0) {
diceFormula += `kh2 + ${mod}`
} else {
diceFormula += `kl2 + ${options.rollItem.value}`
diceFormula += `kl2 + ${mod}`
}
console.log("FTLNomadRoll | Rolling ", diceFormula, options, rollData)
const roll = new this(diceFormula, options.data, rollData)
await roll.evaluate()
@@ -254,6 +258,8 @@ export default class FTLNomadRoll extends Roll {
*/
static createTitle(type, target) {
switch (type) {
case "damage":
return `${game.i18n.localize("FTLNOMAD.Label.titleDamage")}`
case "skill":
return `${game.i18n.localize("FTLNOMAD.Label.titleSkill")}`
case "weapon":

View File

@@ -33,4 +33,24 @@ export default class FTLNomadStarship extends foundry.abstract.TypeDataModel {
return false
}
async roll(rollType, rollItem) {
let opponentTarget
const hasTarget = opponentTarget !== undefined
let roll = await FTLNomadRoll.prompt({
rollType,
rollItem,
actorId: this.parent.id,
actorName: this.parent.name,
actorImage: this.parent.img,
isEncumbered: false,
hasTarget,
target: opponentTarget
})
if (!roll) return null
await roll.toMessage({}, { rollMode: roll.options.rollMode })
}
}

View File

@@ -33,23 +33,23 @@ export default class FTLNomadVehicle extends foundry.abstract.TypeDataModel {
return false
}
async roll(rollType, rollItem) {
let opponentTarget
const hasTarget = opponentTarget !== undefined
async roll(rollType, rollItem) {
let opponentTarget
const hasTarget = opponentTarget !== undefined
let roll = await FTLNomadRoll.prompt({
rollType,
rollItem,
actorId: this.parent.id,
actorName: this.parent.name,
actorImage: this.parent.img,
isEncumbered: this.isEncumbered(),
hasTarget,
target: opponentTarget
})
if (!roll) return null
let roll = await FTLNomadRoll.prompt({
rollType,
rollItem,
actorId: this.parent.id,
actorName: this.parent.name,
actorImage: this.parent.img,
isEncumbered: this.isEncumbered(),
hasTarget,
target: opponentTarget
})
if (!roll) return null
await roll.toMessage({}, { rollMode: roll.options.rollMode })
}
await roll.toMessage({}, { rollMode: roll.options.rollMode })
}
}

View File

@@ -675,7 +675,7 @@ export default class FTLNomadUtils {
return [];
});
console.log("Melee Weapons Data", meleeWeaponsData);
console.log("Melee Weapons Data", meleeWeaponsData);
// Import each melee weapon
for (const weapon of meleeWeaponsData) {
// Check if the weapon already exists
@@ -705,4 +705,51 @@ export default class FTLNomadUtils {
}
}
static async importVehicleWeapons() {
// Create a melee weapons folder if it doesn't exist
const meleeWeaponsFolder = game.folders.getName("Vehicle Weapons") || await Folder.create({
name: "Vehicle Weapons", type: "Item"
})
if (!meleeWeaponsFolder) {
console.error("Failed to create Vehicle Weapons folder");
return;
}
// Load the melee weapons JSON file
const meleeWeaponsData = await fetch("systems/fvtt-ftl-nomad/assets/json_data/vehicleweapons.json")
.then(response => response.json())
.catch(error => {
console.error("Failed to load vehicle weapons data:", error);
return [];
});
console.log("vehicle Weapons Data", meleeWeaponsData);
// Import each melee weapon
for (const weapon of meleeWeaponsData) {
// Check if the weapon already exists
const existingWeapon = game.items.find(i => i.name === weapon.name && i.type === "weapon");
if (existingWeapon) {
console.warn(`Weapon ${weapon.name} already exists, skipping import.`);
}
// Create the weapon item
await Item.create({
name: weapon.name,
type: "weapon",
img: "systems/fvtt-ftl-nomad/assets/icons/icon_weapon.svg",
system: {
description: weapon.description,
damage: weapon.damage,
techAge: this.getTechAgeKeyFromLabel(weapon.tech_age),
weaponType: "vehicle", //SYSTEM.WEAPON_TYPES.melee.id,
rangeType: SYSTEM.WEAPON_RANGE.melee.id,
enc: 0,
aspect: weapon.aspects,
cost: weapon.cost || 0,
ammoCost: weapon.ammo_cost || 0,
magazine: weapon.mag || 1,
},
folder: meleeWeaponsFolder.id
});
}
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -12,18 +12,28 @@
{{/if}}
{{#if (eq rollType "damage")}}
<li class="result-success">Weapon Damage</li>
<li><strong>{{weapon.name}}</strong></li>
{{else}}
{{#if weapon}}
<li><strong>Weapon : {{weapon.name}}</strong></li>
{{/if}}
{{/if}}
<li><strong>{{localize rollItem.label}} : {{fullFormula}}</strong></li>
{{#if (eq rollType "damage")}}
{{else}}
{{#if isEncumbered}}
<li class="red-warning">Encumbered : -1D</li>
{{/if}}
<li>{{localize "FTLNOMAD.Label.modifier"}} : {{skillModifier}}D {{rangeModifier}}D {{numericModifier}}D</li>
{{/if}}
{{#if (eq rollType "damage")}}
{{else}}
{{#if isSuccess}}
<li class="result-success">
{{localize "FTLNOMAD.Label.success"}}
@@ -35,6 +45,8 @@
{{localize "FTLNOMAD.Label.failure"}}
</li>
{{/if}}
{{/if}}
</ul>
</div>
</div>

View File

@@ -6,9 +6,14 @@
<legend>{{localize "FTLNOMAD.Label.skill"}}</legend>
{{/if}}
{{#if (eq rollType "damage")}}
<div class="dialog-skill">Damage : {{weapon.system.damage}}</div>
<div class="dialog-skill">Weapon : {{weapon.name}}</div>
{{else}}
<div class="dialog-skill">{{localize rollItem.label}} : 2d6+{{rollItem.value}}</div>
{{/if}}
{{#if weapon}}
{{#if (eq rollType "weapon")}}
<div class="dialog-skill">Weapon : {{weapon.name}}</div>
{{/if}}
@@ -25,28 +30,29 @@
{{selectOptions choiceModifier selected=modifier localize=true}}
</select>
{{#if weapon}}
<select name="range-modifier" class="roll-skill-range-modifier">
{{selectOptions choiceRangeModifier selected=rangeModifier}}
</select>
<ul>
<li>Two Attacks : <input type="checkbox" name="isAiming" data-field="two-attacks" class="select-combat-option"></li>
<li>Aiming : <input type="checkbox" data-field="aiming" class="select-combat-option"></li>
<li>Dim Lightning : <input type="checkbox" data-field="dim" class="select-combat-option"></li>
<li>Darkness : <input type="checkbox" data-field="darkness" class="select-combat-option"></li>
<li>Target Prone/Obscured : <input type="checkbox" data-field="prone" class="select-combat-option"></li>
<li>Target Cover : <input type="checkbox" data-field="cover" class="select-combat-option"></li>
<li>1/2 Auto Fire Recoil : <input type="checkbox" data-field="recoil-first" class="select-combat-option"></li>
<li>2+ Auto Fire Recoil : <input type="checkbox" data-field="recoil-third" class="select-combat-option"></li>
<li>Target Aware : <input type="checkbox" data-field="aware" class="select-combat-option"></li>
</ul>
{{#if (eq rollType "weapon")}}
<select name="range-modifier" class="roll-skill-range-modifier">
{{selectOptions choiceRangeModifier selected=rangeModifier}}
</select>
<ul>
<li>Two Attacks : <input type="checkbox" name="isAiming" data-field="two-attacks" class="select-combat-option">
</li>
<li>Aiming : <input type="checkbox" data-field="aiming" class="select-combat-option"></li>
<li>Dim Lightning : <input type="checkbox" data-field="dim" class="select-combat-option"></li>
<li>Darkness : <input type="checkbox" data-field="darkness" class="select-combat-option"></li>
<li>Target Prone/Obscured : <input type="checkbox" data-field="prone" class="select-combat-option"></li>
<li>Target Cover : <input type="checkbox" data-field="cover" class="select-combat-option"></li>
<li>1/2 Auto Fire Recoil : <input type="checkbox" data-field="recoil-first" class="select-combat-option"></li>
<li>2+ Auto Fire Recoil : <input type="checkbox" data-field="recoil-third" class="select-combat-option"></li>
<li>Target Aware : <input type="checkbox" data-field="aware" class="select-combat-option"></li>
</ul>
{{/if}}
</fieldSet>
<fieldSet class="dialog-formula">
<legend>{{localize "FTLNOMAD.Label.formula"}}</legend>
<label name="fullFormula" id="roll-dialog-full-formula" >{{fullFormula}}</label>
<label name="fullFormula" id="roll-dialog-full-formula">{{fullFormula}}</label>
</fieldSet>
<fieldSet>

View File

@@ -0,0 +1,54 @@
<section class="tab vehicle-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
<div class="main-div">
<fieldset>
<legend>{{localize "FTLNOMAD.Label.weapons"}}{{#if isEditMode}}
<a class="action" data-tooltip="{{localize " FTLNOMAD.Tooltip.addWeapon"}}" data-tooltip-direction="UP"><i
class="fas fa-plus" data-action="createWeapon"></i></a>{{/if}}
</legend>
<div class="weapons">
{{#each weapons as |item|}}
{{!log 'weapon' this}}
<div class="weapon item" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<div class="name rollable" data-roll-type="weapon" data-tooltip="{{{item.system.description}}}">
{{item.name}}
</div>
<a class="damage rollable" data-item-id="{{item.id}}" data-action="roll" data-roll-type="damage"
data-roll-value="{{item.system.damage}}">{{localize "FTLNOMAD.Label.damageShort"}} :
{{item.system.damage}}</a>
<div class="controls">
<a data-tooltip="{{localize 'FTLNOMAD.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'FTLNOMAD.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div>
{{/each}}
</div>
</fieldset>
<fieldset>
<legend>{{localize "FTLNOMAD.Label.equipment"}}{{#if isEditMode}}
<a class="action" data-tooltip="{{localize " FTLNOMAD.Tooltip.addEquipment"}}" data-tooltip-direction="UP"><i
class="fas fa-plus" data-action="createEquipment"></i></a>{{/if}}
</legend>
<div class="equipments">
{{#each equipments as |item|}}
{{!log 'armor' this}}
<div class="equipment" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}">
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
<div class="name" data-tooltip="{{{item.system.description}}}">
{{item.name}}
</div>
<div class="controls">
<a data-tooltip="{{localize 'FTLNOMAD.Edit'}}" data-action="edit" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-edit"></i></a>
<a data-tooltip="{{localize 'FTLNOMAD.Delete'}}" data-action="delete" data-item-id="{{item.id}}"
data-item-uuid="{{item.uuid}}"><i class="fas fa-trash"></i></a>
</div>
</div>
{{/each}}
</div>
</fieldset>
</div>
</section>

View File

@@ -13,7 +13,12 @@
{{formField systemFields.damage value=system.damage}}
{{formField systemFields.enc value=system.enc}}
{{formField systemFields.cost value=system.cost}}
{{formField cost value=system.cost}}
{{#if (eq system.weaponType "vehicle")}}
{{formField systemFields.ammoCost value=system.ammoCost}}
{{formField systemFields.magazine value=system.magazine}}
{{/if}}
</fieldset>
<fieldset>