6 Commits

Author SHA1 Message Date
2578ea4dc1 Fix bio + initiative
All checks were successful
Release Creation / build (release) Successful in 1m2s
2025-10-05 18:09:02 +02:00
d80e3e4658 Fix roll options
All checks were successful
Release Creation / build (release) Successful in 1m8s
2025-08-26 22:14:45 +02:00
188501423a Add new roll options
All checks were successful
Release Creation / build (release) Successful in 1m24s
2025-08-25 22:41:42 +02:00
668da28d2c Fix various issues with rolls and compendiums
All checks were successful
Release Creation / build (release) Successful in 57s
2025-08-24 16:19:35 +02:00
8a5b402388 Fix v13 issue
All checks were successful
Release Creation / build (release) Successful in 2m15s
2025-08-20 18:43:53 +02:00
ebb3bd9fb3 Fix enc for equipments/weapons 2025-07-13 21:02:49 +02:00
36 changed files with 531 additions and 193 deletions

View File

@@ -8,45 +8,45 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner." - run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner."
#- uses: actions/checkout@v3 #- uses: actions/checkout@v3
- uses: RouxAntoine/checkout@v3.5.4 - uses: RouxAntoine/checkout@v3.5.4
# get part of the tag after the `v` # get part of the tag after the `v`
- name: Extract tag version number - name: Extract tag version number
id: get_version id: get_version
uses: battila7/get-version-action@v2 uses: battila7/get-version-action@v2
# Substitute the Manifest and Download URLs in the module.json # Substitute the Manifest and Download URLs in the module.json
- name: Substitute Manifest and Download Links For Versioned Ones - name: Substitute Manifest and Download Links For Versioned Ones
id: sub_manifest_link_version id: sub_manifest_link_version
uses: microsoft/variable-substitution@v1 uses: microsoft/variable-substitution@v1
with: with:
files: 'system.json' files: "system.json"
env: env:
version: ${{steps.get_version.outputs.version-without-v}} version: ${{steps.get_version.outputs.version-without-v}}
url: https://www.uberwald.me/gitea/${{gitea.repository}} url: https://www.uberwald.me/gitea/${{gitea.repository}}
manifest: https://www.uberwald.me/gitea/uberwald/${{gitea.repository}}/releases/download/latest/system.json manifest: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/latest/system.json
download: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-ftl-nomad-${{github.event.release.tag_name}}.zip download: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/fvtt-ftl-nomad-${{github.event.release.tag_name}}.zip
# Create a zip file with all files required by the module to add to the release # Create a zip file with all files required by the module to add to the release
- run: | - run: |
apt update -y apt update -y
apt install -y zip apt install -y zip
- run: zip -r ./fvtt-ftl-nomad-${{github.event.release.tag_name}}.zip system.json README.md LICENSE assets/ css/ lang/ module/ packs/ packs-system/ templates/ fvtt-ftl-nomad.mjs - run: zip -r ./fvtt-ftl-nomad-${{github.event.release.tag_name}}.zip system.json README.md LICENSE assets/ css/ lang/ module/ packs/ packs-system/ templates/ fvtt-ftl-nomad.mjs
- name: setup go - name: setup go
uses: https://github.com/actions/setup-go@v4 uses: https://github.com/actions/setup-go@v4
with: with:
go-version: '>=1.20.1' go-version: ">=1.20.1"
- name: Use Go Action - name: Use Go Action
id: use-go-action id: use-go-action
uses: https://gitea.com/actions/release-action@main uses: https://gitea.com/actions/release-action@main
with: with:
files: |- files: |-
./fvtt-ftl-nomad-${{github.event.release.tag_name}}.zip ./fvtt-ftl-nomad-${{github.event.release.tag_name}}.zip
system.json system.json
api_key: '${{secrets.ALLOW_PUSH_RELEASE}}' api_key: "${{secrets.ALLOW_PUSH_RELEASE}}"

View File

@@ -1,3 +1,14 @@
# fvtt-ftl-nomad Faster Than Light: Nomad (FTL: Nomad) for Foundry Virtual TableTop
Faster Than Light : Nomad system for FoundryVTT The official game system for playing Faster Than Light: Nomad on FoundryVTT. This framework covers all the fundemental aspects of Faster Than Light: Nomad and permits full FTL:N online gameplay.
This product's format, computer code, graphics, and presentation are copyrighted by Stellagama Publishing.
This system is used with permission granted as part of the partnership agreement between Foundry Gaming LLC and Stellagama Publishing. It uses the following copyright:
Faster Than Light: Nomad, © 2025 Stellagama Publishing. All rights reserved.
Stellagama Publishing's web page is available at https://stellagamapublishing.co/ and the company's owner, Omer Golan-Joel, may be contacted at golan2072@gmail.com.
Community
You are invited to join Stellagama Publishing's Discord server: https://discord.gg/MHpMDBpcZ6

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

@@ -413,10 +413,10 @@ i.fvtt-ftl-nomad {
background-color: var(--color-light-1); background-color: var(--color-light-1);
} }
.fvtt-ftl-nomad .character-biography prose-mirror.inactive { .fvtt-ftl-nomad .character-biography prose-mirror.inactive {
min-height: 40px; min-height: 16rem;
} }
.fvtt-ftl-nomad .character-biography prose-mirror.active { .fvtt-ftl-nomad .character-biography prose-mirror.active {
min-height: 150px; min-height: 16rem;
} }
.fvtt-ftl-nomad .character-biography .field-label { .fvtt-ftl-nomad .character-biography .field-label {
margin-left: 8px; margin-left: 8px;

View File

@@ -31,6 +31,13 @@ Hooks.once("init", function () {
utils: FTLNomadUtils, utils: FTLNomadUtils,
} }
/* -------------------------------------------- */
// Set an initiative formula for the system
CONFIG.Combat.initiative = {
formula: "2d6 + @skills.combat.value",
decimals: 1
};
CONFIG.Actor.documentClass = documents.FTLNomadActor CONFIG.Actor.documentClass = documents.FTLNomadActor
CONFIG.Actor.dataModels = { CONFIG.Actor.dataModels = {
character: models.FTLNomadCharacter, character: models.FTLNomadCharacter,

View File

@@ -351,6 +351,7 @@
} }
}, },
"Label": { "Label": {
"formula": "Formula",
"damages": "Damages", "damages": "Damages",
"modifications": "Modifications", "modifications": "Modifications",
"abilities": "Abilities", "abilities": "Abilities",
@@ -362,11 +363,17 @@
"cargo": "Cargo", "cargo": "Cargo",
"vehicle": "Vehicle", "vehicle": "Vehicle",
"starship": "Starship", "starship": "Starship",
"Easy4": "Easy (+4D)",
"Easy3": "Easy (+3D)",
"Easy2": "Easy (+2D)",
"Easy": "Easy (+1D)", "Easy": "Easy (+1D)",
"Moderate": "Moderate (+0D)", "Moderate": "Moderate (+0D)",
"Difficult": "Difficult (-1D)", "Difficult": "Difficult (-1D)",
"Formidable": "Formidable (-2D)", "Formidable": "Formidable (-2D)",
"Formidable3": "Formidable (-3D)",
"Impossible": "Impossible (-4D)", "Impossible": "Impossible (-4D)",
"Impossible5": "Impossible (-5D)",
"Impossible6": "Impossible (-6D)",
"combat": "Combat", "combat": "Combat",
"physical": "Physical", "physical": "Physical",
"social": "Social", "social": "Social",
@@ -648,6 +655,12 @@
}, },
"weaponType": { "weaponType": {
"label": "Type" "label": "Type"
},
"ammoCost": {
"label": "Ammo Cost"
},
"magazine": {
"label": "Mag"
} }
}, },
"Range": { "Range": {

View File

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

View File

@@ -2,15 +2,15 @@ export const SYSTEM_ID = "fvtt-ftl-nomad"
export const ASCII = ` export const ASCII = `
░▒▓████████▓▒░▒▓████████▓▒░▒▓█▓▒░ ░▒▓███████▓▒░ ░▒▓██████▓▒░░▒▓██████████████▓▒░ ░▒▓██████▓▒░░▒▓███████▓▒░ ░▒▓████████▓▒░▒▓████████▓▒░▒▓█▓▒░ ░▒▓███████▓▒░ ░▒▓██████▓▒░░▒▓██████████████▓▒░ ░▒▓██████▓▒░░▒▓███████▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓████████▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓████████▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓██▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░
░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░ ░▒▓█▓▒░░▒▓█▓▒░░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓███████▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓████████▓▒░ ░▒▓█▓▒░░▒▓█▓▒░░▒▓██████▓▒░░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓███████▓▒░
` `
@@ -52,12 +52,12 @@ export const WEAPON_TYPES = {
} }
export const WEAPON_RANGE = { export const WEAPON_RANGE = {
"handgun": { id: "handgun", label: "FTLNOMAD.Weapon.Range.Handgun", range: {close: 0, near:0, far:-2} }, "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} }, "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} }, "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} }, "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} }, "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} } "thrownweapon": { id: "thrownweapon", label: "FTLNOMAD.Weapon.Range.ThrownWeapon", range: { close: 0, near: -1 } }
} }
export const ATTACK_MODIFIERS = { export const ATTACK_MODIFIERS = {
@@ -73,35 +73,35 @@ export const ATTACK_MODIFIERS = {
} }
export const TRIAGE_RESULTS = { export const TRIAGE_RESULTS = {
"none": { id: "none", dice:0, label: "FTLNOMAD.TriageResults.None" }, "none": { id: "none", dice: 0, label: "FTLNOMAD.TriageResults.None" },
"death": { id: "death", dice:3, label: "FTLNOMAD.TriageResults.Death" }, "death": { id: "death", dice: 3, label: "FTLNOMAD.TriageResults.Death" },
"critical": { id: "critical", dice:4, label: "FTLNOMAD.TriageResults.Critical" }, "critical": { id: "critical", dice: 4, label: "FTLNOMAD.TriageResults.Critical" },
"severe": { id: "severe", dice:7, label: "FTLNOMAD.TriageResults.Severe" }, "severe": { id: "severe", dice: 7, label: "FTLNOMAD.TriageResults.Severe" },
"moderate": { id: "moderate", dice:10, label: "FTLNOMAD.TriageResults.Moderate" }, "moderate": { id: "moderate", dice: 10, label: "FTLNOMAD.TriageResults.Moderate" },
"fleshwound": { id: "fleshwound", dice:12, label: "FTLNOMAD.TriageResults.FleshWound" } "fleshwound": { id: "fleshwound", dice: 12, label: "FTLNOMAD.TriageResults.FleshWound" }
} }
export const CREATURE_TERRAIN_TYPES = { export const CREATURE_TERRAIN_TYPES = {
"cave": { id: "cave", label: "FTLNOMAD.Creature.Terrain.Cave", niche:0, size: 0 }, "cave": { id: "cave", label: "FTLNOMAD.Creature.Terrain.Cave", niche: 0, size: 0 },
"coast": { id: "coast", label: "FTLNOMAD.Creature.Terrain.Coast", niche:1, 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 }, "desert": { id: "desert", label: "FTLNOMAD.Creature.Terrain.Desert", niche: -1, size: -1 },
"forest": { id: "forest", label: "FTLNOMAD.Creature.Terrain.Forest", 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 }, "jungle": { id: "jungle", label: "FTLNOMAD.Creature.Terrain.Jungle", niche: 1, size: 1 },
"mixed": { id: "mixed", label: "FTLNOMAD.Creature.Terrain.Mixed", niche:0, size: 0 }, "mixed": { id: "mixed", label: "FTLNOMAD.Creature.Terrain.Mixed", niche: 0, size: 0 },
"mountain": { id: "mountain", label: "FTLNOMAD.Creature.Terrain.Mountain", niche:-1, size: -1 }, "mountain": { id: "mountain", label: "FTLNOMAD.Creature.Terrain.Mountain", niche: -1, size: -1 },
"ocean": { id: "ocean", label: "FTLNOMAD.Creature.Terrain.Ocean", 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 }, "river": { id: "river", label: "FTLNOMAD.Creature.Terrain.River", niche: 1, size: 0 },
"ruins": { id: "ruins", label: "FTLNOMAD.Creature.Terrain.Ruins", niche:0, size: 1 }, "ruins": { id: "ruins", label: "FTLNOMAD.Creature.Terrain.Ruins", niche: 0, size: 1 },
"savannah": { id: "savannah", label: "FTLNOMAD.Creature.Terrain.Savannah", 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 }, "shallows": { id: "shallows", label: "FTLNOMAD.Creature.Terrain.Shallows", niche: 1, size: 0 },
"swamp": { id: "swamp", label: "FTLNOMAD.Creature.Terrain.Swamp", niche:1, size: 1 } "swamp": { id: "swamp", label: "FTLNOMAD.Creature.Terrain.Swamp", niche: 1, size: 1 }
} }
export const CREATURE_NICHES = { export const CREATURE_NICHES = {
"prey": { id: "prey", label: "FTLNOMAD.Creature.Niche.Prey" }, "prey": { id: "prey", label: "FTLNOMAD.Creature.Niche.Prey" },
"opportunist": { id: "opportunist", label: "FTLNOMAD.Creature.Niche.Opportunist" }, "opportunist": { id: "opportunist", label: "FTLNOMAD.Creature.Niche.Opportunist" },
"herbivore": { id: "herbivore", label: "FTLNOMAD.Creature.Niche.Herbivore" }, "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 = { export const CREATURE_SIZES = {
@@ -114,11 +114,17 @@ export const CREATURE_SIZES = {
} }
export const MODIFIER_CHOICES = { export const MODIFIER_CHOICES = {
"easy": { id: "easy", label: "FTLNOMAD.Label.Easy", value :"1" }, "easy4": { id: "easy4", label: "FTLNOMAD.Label.Easy4", value: "4" },
"easy3": { id: "easy3", label: "FTLNOMAD.Label.Easy3", value: "3" },
"easy2": { id: "easy2", label: "FTLNOMAD.Label.Easy2", value: "2" },
"easy": { id: "easy", label: "FTLNOMAD.Label.Easy", value: "1" },
"moderate": { id: "moderate", label: "FTLNOMAD.Label.Moderate", value: "0" }, "moderate": { id: "moderate", label: "FTLNOMAD.Label.Moderate", value: "0" },
"difficult": { id: "difficult", label: "FTLNOMAD.Label.Difficult", value: "-1" }, "difficult": { id: "difficult", label: "FTLNOMAD.Label.Difficult", value: "-1" },
"formidable": { id: "formidable", label: "FTLNOMAD.Label.Formidable", value: "-2" }, "formidable": { id: "formidable", label: "FTLNOMAD.Label.Formidable", value: "-2" },
"impossible": { id: "impossible", label: "FTLNOMAD.Label.Impossible", value: "-4" } "formidable3": { id: "formidable3", label: "FTLNOMAD.Label.Formidable3", value: "-3" },
"impossible": { id: "impossible", label: "FTLNOMAD.Label.Impossible", value: "-4" },
"impossible5": { id: "impossible5", label: "FTLNOMAD.Label.Impossible5", value: "-5" },
"impossible6": { id: "impossible6", label: "FTLNOMAD.Label.Impossible6", value: "-6" }
} }
export const STARSHIP_HULL = { export const STARSHIP_HULL = {

View File

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

View File

@@ -35,8 +35,8 @@ export default class FTLNomadProtagonist extends foundry.abstract.TypeDataModel
schema.health = new fields.SchemaField({ schema.health = new fields.SchemaField({
staminaValue: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }), staminaValue: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }),
staminaMax: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }), staminaMax: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }),
wounds: new fields.NumberField({ ...requiredInteger, initial:0, min: 0 }), wounds: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
triageResults: new fields.StringField({ required: true, nullable: false, initial: "none", choices: SYSTEM.TRIAGE_RESULTS }) triageResults: new fields.StringField({ required: true, nullable: false, initial: "none", choices: SYSTEM.TRIAGE_RESULTS })
}) })
schema.enc = new fields.SchemaField({ schema.enc = new fields.SchemaField({
@@ -76,18 +76,18 @@ export default class FTLNomadProtagonist extends foundry.abstract.TypeDataModel
prepareDerivedData() { prepareDerivedData() {
super.prepareDerivedData(); super.prepareDerivedData();
let encMax = 10 + (2*this.skills.physical.value) let encMax = 10 + (2 * this.skills.physical.value)
if (encMax !== this.enc.max) { if (encMax !== this.enc.max) {
this.enc.max = encMax this.enc.max = encMax
} }
let enc = 0 let enc = 0
let armor = 0 let armor = 0
for (let i of this.parent.items) { for (let i of this.parent.items) {
if (i.system?.enc) { if (i.system?.enc) {
enc += i.system.enc enc += i.system.enc
} }
if ( i.system?.protection) { if (i.system?.protection) {
armor += i.system.protection armor += i.system.protection
} }
} }
@@ -97,12 +97,12 @@ export default class FTLNomadProtagonist extends foundry.abstract.TypeDataModel
if (armor !== this.armor.value) { if (armor !== this.armor.value) {
this.armor.value = armor this.armor.value = armor
} }
let staminaMax = 14 + (3*this.skills.physical.value) let staminaMax = 14 + (3 * this.skills.physical.value)
if (staminaMax !== this.health.staminaMax) { if (staminaMax !== this.health.staminaMax) {
this.health.staminaMax = staminaMax this.health.staminaMax = staminaMax
} }
} }
isEncumbered() { isEncumbered() {
return this.enc.value > this.enc.max return this.enc.value > this.enc.max
} }

View File

@@ -33,4 +33,24 @@ export default class FTLNomadStarship extends foundry.abstract.TypeDataModel {
return false 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 return false
} }
async roll(rollType, rollItem) { async roll(rollType, rollItem) {
let opponentTarget let opponentTarget
const hasTarget = opponentTarget !== undefined const hasTarget = opponentTarget !== undefined
let roll = await FTLNomadRoll.prompt({ let roll = await FTLNomadRoll.prompt({
rollType, rollType,
rollItem, rollItem,
actorId: this.parent.id, actorId: this.parent.id,
actorName: this.parent.name, actorName: this.parent.name,
actorImage: this.parent.img, actorImage: this.parent.img,
isEncumbered: this.isEncumbered(), isEncumbered: this.isEncumbered(),
hasTarget, hasTarget,
target: opponentTarget target: opponentTarget
}) })
if (!roll) return null 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 []; return [];
}); });
console.log("Melee Weapons Data", meleeWeaponsData); console.log("Melee Weapons Data", meleeWeaponsData);
// Import each melee weapon // Import each melee weapon
for (const weapon of meleeWeaponsData) { for (const weapon of meleeWeaponsData) {
// Check if the weapon already exists // 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.

View File

@@ -1 +1 @@
MANIFEST-000035 MANIFEST-000051

View File

@@ -1,15 +1,7 @@
2025/07/13-19:19:55.407043 7f3fa77fe6c0 Recovering log #33 2025/08/26-08:04:22.211637 7f99c9ffb6c0 Recovering log #48
2025/07/13-19:19:55.417622 7f3fa77fe6c0 Delete type=3 #31 2025/08/26-08:04:22.223370 7f99c9ffb6c0 Delete type=3 #46
2025/07/13-19:19:55.417740 7f3fa77fe6c0 Delete type=0 #33 2025/08/26-08:04:22.223498 7f99c9ffb6c0 Delete type=0 #48
2025/07/13-19:30:09.138052 7f3fa57fa6c0 Level-0 table #38: started 2025/08/26-08:13:33.915174 7f99c8ff96c0 Level-0 table #54: started
2025/07/13-19:30:09.142514 7f3fa57fa6c0 Level-0 table #38: 69052 bytes OK 2025/08/26-08:13:33.915296 7f99c8ff96c0 Level-0 table #54: 0 bytes OK
2025/07/13-19:30:09.149276 7f3fa57fa6c0 Delete type=0 #36 2025/08/26-08:13:33.948896 7f99c8ff96c0 Delete type=0 #52
2025/07/13-19:30:09.149522 7f3fa57fa6c0 Manual compaction at level-0 from '!folders!AuBtSOj1mJmh88qx' @ 72057594037927935 : 1 .. '!items!zv9dwgL3p7ThQn7j' @ 0 : 0; will stop at (end) 2025/08/26-08:13:33.949217 7f99c8ff96c0 Manual compaction at level-0 from '!folders!AuBtSOj1mJmh88qx' @ 72057594037927935 : 1 .. '!items!zv9dwgL3p7ThQn7j' @ 0 : 0; will stop at (end)
2025/07/13-19:30:09.149572 7f3fa57fa6c0 Manual compaction at level-1 from '!folders!AuBtSOj1mJmh88qx' @ 72057594037927935 : 1 .. '!items!zv9dwgL3p7ThQn7j' @ 0 : 0; will stop at '!items!zv9dwgL3p7ThQn7j' @ 347 : 0
2025/07/13-19:30:09.149581 7f3fa57fa6c0 Compacting 1@1 + 1@2 files
2025/07/13-19:30:09.155375 7f3fa57fa6c0 Generated table #39@1: 273 keys, 107280 bytes
2025/07/13-19:30:09.155393 7f3fa57fa6c0 Compacted 1@1 + 1@2 files => 107280 bytes
2025/07/13-19:30:09.161181 7f3fa57fa6c0 compacted to: files[ 0 0 1 0 0 0 0 ]
2025/07/13-19:30:09.161294 7f3fa57fa6c0 Delete type=2 #14
2025/07/13-19:30:09.161440 7f3fa57fa6c0 Delete type=2 #38
2025/07/13-19:30:09.181330 7f3fa57fa6c0 Manual compaction at level-1 from '!items!zv9dwgL3p7ThQn7j' @ 347 : 0 .. '!items!zv9dwgL3p7ThQn7j' @ 0 : 0; will stop at (end)

View File

@@ -1,8 +1,11 @@
2025/07/13-10:30:52.384204 7f3fa77fe6c0 Recovering log #29 2025/08/25-21:48:36.909732 7f99c9ffb6c0 Delete type=3 #1
2025/07/13-10:30:52.394989 7f3fa77fe6c0 Delete type=3 #27 2025/08/25-21:56:45.440471 7f99c8ff96c0 Level-0 table #49: started
2025/07/13-10:30:52.395058 7f3fa77fe6c0 Delete type=0 #29 2025/08/25-21:56:45.440527 7f99c8ff96c0 Level-0 table #49: 0 bytes OK
2025/07/13-10:33:26.219686 7f3fa57fa6c0 Level-0 table #34: started 2025/08/25-21:56:45.504826 7f99c8ff96c0 Delete type=0 #47
2025/07/13-10:33:26.219728 7f3fa57fa6c0 Level-0 table #34: 0 bytes OK 2025/08/25-21:56:45.558056 7f99c8ff96c0 Manual compaction at level-0 from '!folders!AuBtSOj1mJmh88qx' @ 72057594037927935 : 1 .. '!items!zv9dwgL3p7ThQn7j' @ 0 : 0; will stop at '!items!zv9dwgL3p7ThQn7j' @ 385 : 1
2025/07/13-10:33:26.225987 7f3fa57fa6c0 Delete type=0 #32 2025/08/25-21:56:45.558080 7f99c8ff96c0 Compacting 1@0 + 0@1 files
2025/07/13-10:33:26.233983 7f3fa57fa6c0 Manual compaction at level-0 from '!folders!AuBtSOj1mJmh88qx' @ 72057594037927935 : 1 .. '!items!zv9dwgL3p7ThQn7j' @ 0 : 0; will stop at (end) 2025/08/25-21:56:45.590210 7f99c8ff96c0 Generated table #50@0: 285 keys, 111653 bytes
2025/07/13-10:33:26.244796 7f3fa57fa6c0 Manual compaction at level-1 from '!folders!AuBtSOj1mJmh88qx' @ 72057594037927935 : 1 .. '!items!zv9dwgL3p7ThQn7j' @ 0 : 0; will stop at (end) 2025/08/25-21:56:45.590298 7f99c8ff96c0 Compacted 1@0 + 0@1 files => 111653 bytes
2025/08/25-21:56:45.648076 7f99c8ff96c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/08/25-21:56:45.648259 7f99c8ff96c0 Delete type=2 #44
2025/08/25-21:56:45.801444 7f99c8ff96c0 Manual compaction at level-0 from '!items!zv9dwgL3p7ThQn7j' @ 385 : 1 .. '!items!zv9dwgL3p7ThQn7j' @ 0 : 0; will stop at (end)

Binary file not shown.

Binary file not shown.

View File

View File

@@ -1 +1 @@
MANIFEST-000014 MANIFEST-000029

View File

@@ -1,8 +1,7 @@
2025/07/13-19:19:55.423004 7f3fa5ffb6c0 Recovering log #12 2025/08/26-08:04:22.229470 7f99caffd6c0 Recovering log #26
2025/07/13-19:19:55.432450 7f3fa5ffb6c0 Delete type=3 #10 2025/08/26-08:04:22.240597 7f99caffd6c0 Delete type=3 #24
2025/07/13-19:19:55.432507 7f3fa5ffb6c0 Delete type=0 #12 2025/08/26-08:04:22.240743 7f99caffd6c0 Delete type=0 #26
2025/07/13-19:30:09.131809 7f3fa57fa6c0 Level-0 table #17: started 2025/08/26-08:13:33.840012 7f99c8ff96c0 Level-0 table #32: started
2025/07/13-19:30:09.131855 7f3fa57fa6c0 Level-0 table #17: 0 bytes OK 2025/08/26-08:13:33.840112 7f99c8ff96c0 Level-0 table #32: 0 bytes OK
2025/07/13-19:30:09.137925 7f3fa57fa6c0 Delete type=0 #15 2025/08/26-08:13:33.862575 7f99c8ff96c0 Delete type=0 #30
2025/07/13-19:30:09.149491 7f3fa57fa6c0 Manual compaction at level-0 from '!actors!3pydTJsM73Z4o0V6' @ 72057594037927935 : 1 .. '!folders!vRnrOJqSMlxbSgyX' @ 0 : 0; will stop at (end) 2025/08/26-08:13:33.949166 7f99c8ff96c0 Manual compaction at level-0 from '!actors!3pydTJsM73Z4o0V6' @ 72057594037927935 : 1 .. '!folders!vRnrOJqSMlxbSgyX' @ 0 : 0; will stop at (end)
2025/07/13-19:30:09.149534 7f3fa57fa6c0 Manual compaction at level-1 from '!actors!3pydTJsM73Z4o0V6' @ 72057594037927935 : 1 .. '!folders!vRnrOJqSMlxbSgyX' @ 0 : 0; will stop at (end)

View File

@@ -1,8 +1,11 @@
2025/07/13-10:30:52.399161 7f3fa5ffb6c0 Recovering log #8 2025/08/25-21:48:36.994202 7f99ca7fc6c0 Delete type=3 #1
2025/07/13-10:30:52.409521 7f3fa5ffb6c0 Delete type=3 #6 2025/08/25-21:56:45.505125 7f99c8ff96c0 Level-0 table #27: started
2025/07/13-10:30:52.409646 7f3fa5ffb6c0 Delete type=0 #8 2025/08/25-21:56:45.505238 7f99c8ff96c0 Level-0 table #27: 0 bytes OK
2025/07/13-10:33:26.202414 7f3fa57fa6c0 Level-0 table #13: started 2025/08/25-21:56:45.557727 7f99c8ff96c0 Delete type=0 #25
2025/07/13-10:33:26.202485 7f3fa57fa6c0 Level-0 table #13: 0 bytes OK 2025/08/25-21:56:45.648499 7f99c8ff96c0 Manual compaction at level-0 from '!actors!3pydTJsM73Z4o0V6' @ 72057594037927935 : 1 .. '!folders!vRnrOJqSMlxbSgyX' @ 0 : 0; will stop at '!folders!vRnrOJqSMlxbSgyX' @ 92 : 1
2025/07/13-10:33:26.208789 7f3fa57fa6c0 Delete type=0 #11 2025/08/25-21:56:45.648514 7f99c8ff96c0 Compacting 1@0 + 0@1 files
2025/07/13-10:33:26.233915 7f3fa57fa6c0 Manual compaction at level-0 from '!actors!3pydTJsM73Z4o0V6' @ 72057594037927935 : 1 .. '!folders!vRnrOJqSMlxbSgyX' @ 0 : 0; will stop at (end) 2025/08/25-21:56:45.676577 7f99c8ff96c0 Generated table #28@0: 51 keys, 49087 bytes
2025/07/13-10:33:26.234020 7f3fa57fa6c0 Manual compaction at level-1 from '!actors!3pydTJsM73Z4o0V6' @ 72057594037927935 : 1 .. '!folders!vRnrOJqSMlxbSgyX' @ 0 : 0; will stop at (end) 2025/08/25-21:56:45.676616 7f99c8ff96c0 Compacted 1@0 + 0@1 files => 49087 bytes
2025/08/25-21:56:45.736809 7f99c8ff96c0 compacted to: files[ 0 1 0 0 0 0 0 ]
2025/08/25-21:56:45.736931 7f99c8ff96c0 Delete type=2 #22
2025/08/25-21:56:45.801488 7f99c8ff96c0 Manual compaction at level-0 from '!folders!vRnrOJqSMlxbSgyX' @ 92 : 1 .. '!folders!vRnrOJqSMlxbSgyX' @ 0 : 0; will stop at (end)

View File

View File

@@ -219,10 +219,10 @@
.character-biography { .character-biography {
background-color: var(--color-light-1); background-color: var(--color-light-1);
prose-mirror.inactive { prose-mirror.inactive {
min-height: 40px; min-height: 16rem;
} }
prose-mirror.active { prose-mirror.active {
min-height: 150px; min-height: 16rem;
} }
.field-label { .field-label {
margin-left: 8px; margin-left: 8px;

View File

@@ -23,12 +23,12 @@
<fieldset> <fieldset>
<legend>{{localize "FTLNOMAD.Label.description"}}</legend> <legend>{{localize "FTLNOMAD.Label.description"}}</legend>
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true}} {{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true class="character-description"}}
</fieldset> </fieldset>
<fieldset> <fieldset>
<legend>{{localize "FTLNOMAD.Label.notes"}}</legend> <legend>{{localize "FTLNOMAD.Label.notes"}}</legend>
{{formInput systemFields.notes enriched=enrichedNotes value=system.notes name="system.notes" toggled=true}} {{formInput systemFields.notes enriched=enrichedNotes value=system.notes name="system.notes" toggled=true class="character-notes"}}
</fieldset> </fieldset>
</div> </div>
</section> </section>

View File

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

View File

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