From add497156b367c23aaf473730fa1875b17629dc6 Mon Sep 17 00:00:00 2001 From: Leratier Bretonnien Date: Mon, 22 Feb 2021 19:17:38 +0000 Subject: [PATCH 01/47] Add .gitlab-ci.yml --- .gitlab-ci.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..30a73a2 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,29 @@ +image: python:3-alpine + +before_script: + - apk update + - apk add zip + +stages: + - test + - build + +test: + stage: test + script: + - python -mjson.tool 'system.json' > /dev/null + - python -mjson.tool 'template.json' > /dev/null + +build: + stage: build + script: + - zip foundryvtt-shadows-over-sol.zip -r *.js *.json *.md fonts img lang module packs styles templates -x ".*" + artifacts: + name: foundryvtt-shadows-over-sol + when: on_success + paths: + - foundryvtt-shadows-over-sol.zip + when: on_success + only: + - tags + - master -- 2.35.3 From 9ea19a55095cab4c0db1fe9c61aa9cb6de1cb403 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Mon, 22 Feb 2021 20:32:12 +0100 Subject: [PATCH 02/47] #1 Fix item deletion --- module/actor-sheet.js | 2 +- module/sos-utility.js | 30 ++++++++++++++++++++++++++++++ system.json | 2 +- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index f692c25..2ad579b 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -92,7 +92,7 @@ export class SoSActorSheet extends ActorSheet { // Delete Inventory Item html.find('.item-delete').click(ev => { const li = $(ev.currentTarget).parents(".item"); - RdDUtility.confirmerSuppression(this, li); + SoSUtility.confirmDelete(this, li); }); html.find('.stat-label a').click((event) => { diff --git a/module/sos-utility.js b/module/sos-utility.js index 4e1c302..ba99a25 100644 --- a/module/sos-utility.js +++ b/module/sos-utility.js @@ -219,6 +219,36 @@ export class SoSUtility extends Entity { return 0; } + /* -------------------------------------------- */ + static async confirmDelete(actorSheet, li) { + let itemId = li.data("item-id"); + let objet = actorSheet.actor.items.find(item => item._id == itemId); + let msgTxt = "

Are you sure to delete this item ?"; + let buttons = { + delete: { + icon: '', + label: "Yes, delete it", + callback: () => { + console.log("Delete : ", itemId); + actorSheet.actor.deleteOwnedItem(itemId); + li.slideUp(200, () => actorSheet.render(false)); + } + }, + cancel: { + icon: '', + label: "Cancel" + } + } + msgTxt += "

"; + let d = new Dialog({ + title: "Confirm deletion", + content: msgTxt, + buttons: buttons, + default: "cancel" + }); + d.render(true); + } + /* -------------------------------------------- */ static async applyDamage( flipData ) { if (!this.registry) this.registry = {}; diff --git a/system.json b/system.json index ef9820b..785e64a 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "name": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", - "version": "0.1.1", + "version": "0.1.2", "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", -- 2.35.3 From a8578c3aa14dc797e366cc28c2b3aa630496fa90 Mon Sep 17 00:00:00 2001 From: tmtabor Date: Thu, 25 Feb 2021 21:16:46 -0800 Subject: [PATCH 03/47] Prevent the combat script from crashing when there's a token without an assigned actor --- module/sos-combat.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/module/sos-combat.js b/module/sos-combat.js index 51ec277..6dc6842 100644 --- a/module/sos-combat.js +++ b/module/sos-combat.js @@ -15,13 +15,14 @@ export class SoSCombat extends Combat { for( let combatant of this.combatants) { this.setInitiative(combatant._id, -1 ); // Reset init let uniq = randomID(16); + const name = combatant.actor ? combatant.actor.data.name : combatant.name; if ( combatant.players[0]) { // A player controls this combatant -> message ! - ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${combatant.actor.data.name} for round ${this.round} !
+ ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${name} for round ${this.round} !
Declare actions`, whisper: [ combatant.players[0].data._id] } ); } else { - ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${combatant.actor.data.name} for round ${this.round} !
+ ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${name} for round ${this.round} !
Declare actions`, whisper: [ ChatMessage.getWhisperRecipients("GM") ] } ); } @@ -57,11 +58,12 @@ export class SoSCombat extends Combat { let actionData = this.phaseSetup[combatantId]; if ( actionData.phaseArray[phaseIndex].name != 'No Action' ) { let combatant = this.combatants.find( comb => comb._id == actionData.combatantId); + const name = combatant.actor ? combatant.actor.data.name : combatant.name; actionList.push( { combatant: combatant, action: actionData.phaseArray[phaseIndex], isDone: false }); - actionMsg += `
${combatant.actor.name} is going to : ${actionData.phaseArray[phaseIndex].name}`; + actionMsg += `
${name} is going to : ${actionData.phaseArray[phaseIndex].name}`; } } if ( actionList.length == 0) { @@ -75,14 +77,15 @@ export class SoSCombat extends Combat { for ( let action of actionList) { let uniq = randomID(16); action.uniqId = uniq; // Easy tracking with chat messages + const name = action.combatant.actor ? action.combatant.actor.data.name : action.combatant.name; if ( action.combatant.players[0]) { // A player controls this combatant -> message ! - ChatMessage.create( { content: `Phase ${this.phaseNumber} ! ${action.combatant.actor.data.name} must perform a ${action.action.name} action. + ChatMessage.create( { content: `Phase ${this.phaseNumber} ! ${name} must perform a ${action.action.name} action. When done, click on the button below to close the action. Action is done !`, whisper: [ action.combatant.players[0].data._id] } ); } else { - ChatMessage.create( { content: `Phase ${this.phaseNumber} ! ${action.combatant.actor.data.name} must perform a ${action.action.name} action.
+ ChatMessage.create( { content: `Phase ${this.phaseNumber} ! ${name} must perform a ${action.action.name} action.
When done, click on the button below to close the action. Action is done !`, whisper: [ ChatMessage.getWhisperRecipients("GM") ] } ); @@ -96,6 +99,7 @@ export class SoSCombat extends Combat { applyConsequences( ) { if (game.user.isGM ) { for( let combatant of this.combatants) { + if (!combatant.actor) continue; // Can't check tokens without assigned actors, Maybe print chat message about bleeding happening so that the GM can manually track this? let bleeding = combatant.actor.data.items.find( item => item.type == 'consequence' && item.name == 'Bleeding'); combatant.actor.applyConsequenceWound( bleeding.data.severity, "bleeding" ); } -- 2.35.3 From 10fbcec5fb5ee9b3cdab1acc9d6952c1ed9e8faa Mon Sep 17 00:00:00 2001 From: sladecraven Date: Fri, 26 Feb 2021 17:35:11 +0100 Subject: [PATCH 04/47] Sync --- packs/gears.db | 52 +++++++++++++++++++++++++------------------------- scecd | 0 2 files changed, 26 insertions(+), 26 deletions(-) create mode 100644 scecd diff --git a/packs/gears.db b/packs/gears.db index 7ad8238..48f8883 100644 --- a/packs/gears.db +++ b/packs/gears.db @@ -5,32 +5,32 @@ {"name":"Ladar Scanner","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Ladar! Ladar! Ladar! Ladar scanners emit low-energy laser beams to detect and identify nearby objects. Although they are of limited use in detecting unknown objects due to the narrowness of their beams, they have remarkable resolution in identifying objects once they are known. This includes facial recognition and chemical recognition technologies! Just compare to a facial database, or to a database of chemicals based on which wavelengths of the laser light the materials absorb. Signal is good up to a dozen kilometers in atmosphere or a thousand kilometers in a vacuum.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"5AMS4LoD2ccjSOoR"} {"name":"Disposable Cuffs","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"These disposable cuffs are little more than metal-meshed tape that can automatically tighten over the limbs of their target once applied. Further struggles against the cuffs cause them to tighten further. Each length is good for one use. Comes with 10 uses.","quantity":0,"costrating":3,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"5aVUx3LL0sgKDX5c"} {"name":"Encryption System (Ultimate)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":9,"worn":false,"description":"Keep your private life private. Encryption is necessary for any sort of secure transaction using broadcast communication, such as on the net or through radio comms. Most computers come with basic built-in encryption methods, but for those who want real security, bolstered encryption software is a no-brainer. Difficulty of breaking encryption scales with processing requirements. Encryption systems come in a variety of different qualities, with differing processing requirements (see page XXX).","quantity":0,"costrating":10,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"5h4IMmt4GE1XWHLf"} -{"name":"USD-720 “Widowmaker” Heavy Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The ultimate man-stopper, the USD-720 “Windowmaker” Heavy Pistol is sure to leave you standing and your enemies taking a dirt nap. A long-time favorite of bounty hunters and security forces the Sol system over, this sleek .50 caliber handgun is now available on the open market! Order yours today!","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"2M","damage_hearts":"10M","damage_spade":"15M","damage_diamond":"5M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"5v8G1u0BqBCYDbuc"} +{"name":"USD-720 “Widowmaker” Heavy Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The ultimate man-stopper, the USD-720 “Windowmaker” Heavy Pistol is sure to leave you standing and your enemies taking a dirt nap. A long-time favorite of bounty hunters and security forces the Sol system over, this sleek .50 caliber handgun is now available on the open market! Order yours today!","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"2M","damage_hearth":"10M","damage_spade":"15M","damage_diamond":"5M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"5v8G1u0BqBCYDbuc"} {"name":"Encryption System (Basic)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":3,"worn":false,"description":"Keep your private life private. Encryption is necessary for any sort of secure transaction using broadcast communication, such as on the net or through radio comms. Most computers come with basic built-in encryption methods, but for those who want real security, bolstered encryption software is a no-brainer. Difficulty of breaking encryption scales with processing requirements. Encryption systems come in a variety of different qualities, with differing processing requirements (see page XXX).","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"77LBpjdxXYae9Xpv"} {"name":"Torpestat","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Be the boss of pain. Don't let pain be the boss of you. Torpestat is a powerful pain-killer. Once injected, it lasts for 8 hours. During this time, the recipient does not take penalties from the Wound consequence. Additionally, she gains a +2 bonus to her Shock threshold. The downside is that the drug also leaves her numb, giving her a -2 penalty to all Dexterity and Speed actions, as well as to any Perception action relying on her sense of touch. Pack of 10 doses.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"7bcyIelcEDzRQVZx"} {"name":"Disguise Kit (Superior)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Be who you want to be with this disguise kit! This complete kit contains makeup, chemicals for mimicking muscle twitches and tightness, prosthetic attachments, instant hair coloring and colored contacts. This counts as sufficient tools for disguise. Also consider our superior quality version, which counts as superior tools (+2) for the purposes of disguise! Each kit contains enough materials for 10 uses.","quantity":0,"costrating":9,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"7mMMx0cXlag4ivNv"} {"name":"AR Implant","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":1,"neg":false,"mil":false,"software":0,"worn":false,"description":"Tired of bulky AR glasses? Internalize your augmented reality! This state-of-the-art AR implant intercepts signals between the host's eyes and brain, injecting AR tags and other data into the visual signal. Operated through either voice or programmed eye movements, the AR implant comes complete with encrypted wireless interface and hard-wired off switch. For AR rules, see page XXX.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"7qbtPn0nGYsuslSj"} {"name":"Somnitol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Prescribed for even the toughest insomnia, Somnitol will put you to sleep. If injected, Somnitol will put the recipient into a deep sleep in a number of rounds equal to her Endurance. Once asleep, she will be unconscious for the next 8 hours unless awoken through a stimulant or by other chemical means. Pack of 10 doses.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"At2vZV5LuNy6B0An"} -{"name":"Power Tool","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Some repair and constructions tasks require more than a simple toolkit. For those, try a dedicated power tool! Power tools come in a variety of shapes and sizes from chainsaws to magnetic drills. In a pinch, they can even serve as an improvised hand-to-hand weapon! (See the damage listing above.). Count as an improvised weapon.","quantity":0,"costrating":4,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str×½M","damage_hearts":"Str×2M","damage_spade":"Str×3M","damage_diamond":"StrM","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"B8WtZN572O0Bh2aK"} +{"name":"Power Tool","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Some repair and constructions tasks require more than a simple toolkit. For those, try a dedicated power tool! Power tools come in a variety of shapes and sizes from chainsaws to magnetic drills. In a pinch, they can even serve as an improvised hand-to-hand weapon! (See the damage listing above.). Count as an improvised weapon.","quantity":0,"costrating":4,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str×½M","damage_hearth":"Str×2M","damage_spade":"Str×3M","damage_diamond":"StrM","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"B8WtZN572O0Bh2aK"} {"name":"Verazine","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":true,"software":0,"worn":false,"description":"When the perp won't talk, try Verazine! Verazine is a psychoactive drug used in interrogations and for even less savory purposes. It causes the recipient to enter a hazy, dream-like state, becoming talkative and losing her internal filters. Injected directly into the bloodstream, Verazine takes about a minute to set in. Then, for the next 10 minutes, the recipient is at a -4 penalty to all actions to deceive or avoid simple mental trickery. Pack of 10 doses.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"BRfji7Q0B6ziSKFZ"} -{"name":"Gun Arm Implant","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":4,"container":0,"implant":1,"neg":false,"mil":false,"software":0,"worn":false,"description":"Have your safety well in hand, or at least in arm, with this gun arm implant! Included is a concealed ballistic gun barrel and trigger mechanism, which embeds beneath the skin into the flesh of the forearm. The gun can be programmed to fire with a simple flick of the arm, giving the element of surprise. It holds three shots. Reloading requires opening a compartment in the arm and loading each bullet individually.","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearts":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":2,"shots":3,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"BXO08S48bEirevNW"} -{"name":"USD-720 Widowmaker Heavy Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"

The ultimate man-stopper, the USD-720 “Windowmaker” Heavy Pistol is sure to leave you standing and your enemies taking a dirt nap. A long-time favorite of bounty hunters and security forces the Sol system over, this sleek .50 caliber handgun is now available on the open market! Order yours today!

\n

 

","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"2M","damage_hearts":"10M","damage_spade":"15M","damage_diamond":"5M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/usd-720.svg","effects":[],"_id":"CgOBdHEwfFMUbEYk"} +{"name":"Gun Arm Implant","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":4,"container":0,"implant":1,"neg":false,"mil":false,"software":0,"worn":false,"description":"Have your safety well in hand, or at least in arm, with this gun arm implant! Included is a concealed ballistic gun barrel and trigger mechanism, which embeds beneath the skin into the flesh of the forearm. The gun can be programmed to fire with a simple flick of the arm, giving the element of surprise. It holds three shots. Reloading requires opening a compartment in the arm and loading each bullet individually.","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearth":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":2,"shots":3,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"BXO08S48bEirevNW"} +{"name":"USD-720 Widowmaker Heavy Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"

The ultimate man-stopper, the USD-720 “Windowmaker” Heavy Pistol is sure to leave you standing and your enemies taking a dirt nap. A long-time favorite of bounty hunters and security forces the Sol system over, this sleek .50 caliber handgun is now available on the open market! Order yours today!

\n

 

","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"2M","damage_hearth":"10M","damage_spade":"15M","damage_diamond":"5M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/usd-720.svg","effects":[],"_id":"CgOBdHEwfFMUbEYk"} {"name":"USD-38n “Knight” Tactical Suit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":5,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Utakar's latest design in heavy civilian armor, the USD-38n “Knight” Tactical Suit employs advanced safety measures to keep the wearer up and fighting. Built from the ground up for reliable protection, the Knight Tactical Suit is a must-have for any urban warrior. Straps and pockets carry extra magazines. Comes in a variety of patterns and colors. Available in both matte and gloss.","quantity":0,"costrating":8,"defensive":0,"containerid":"","bulky":1,"dr":5,"gel":0,"reflect":0,"str":0,"vac":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/generic_armor.svg","effects":[],"_id":"DIT9UQ5ygV04DLDq"} {"name":"Rope","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"You never know when you'll need some good, old-fashioned rope! This rope is made of light, but durable synthetic fabrics and coils into an easy-to-transport bundle. Contained is 50 m of rope, capable of safely holding up to 200 kg. If trying to load the rope with more than this, have the GM flip a card. If it's a clubs the rope breaks. Flip an additional card for every increment of 200 kg. Rope counts as a sufficient tool for many purposes, such as climbing heights or tying someone up.","quantity":0,"costrating":1,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"EOEHdeBTN1sTehdB"} -{"name":"Xenocom L8 Machine Lasrifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"When in combat, it's best to remember: don't let up. That's why you need the Xenocom L8 Machine Lasrifle. With this high quality military-grade laser rifle, you can keep the pressure on, pinning your enemies down with its automatic fire and keeping your allies out of the line of fire.","quantity":0,"costrating":12,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"4M","damage_hearts":"16M","damage_spade":"24M","damage_diamond":"8M","hands":2,"pierce":0,"range":20,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"EWFG5rLe5vzAbelR"} +{"name":"Xenocom L8 Machine Lasrifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"When in combat, it's best to remember: don't let up. That's why you need the Xenocom L8 Machine Lasrifle. With this high quality military-grade laser rifle, you can keep the pressure on, pinning your enemies down with its automatic fire and keeping your allies out of the line of fire.","quantity":0,"costrating":12,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"4M","damage_hearth":"16M","damage_spade":"24M","damage_diamond":"8M","hands":2,"pierce":0,"range":20,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"EWFG5rLe5vzAbelR"} {"name":"ToolKit (Superior)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"After using our toolkits, you'll feel naked without one! A variety of toolkits are available, each geared towards a specific kind of task and each containing tools useful in that task. When purchasing a toolkit, think about what the toolkit is geared for as a specific skill experience. For example, “electrician” might be a toolkit used with the mechanic skill. Tool kits count as sufficient equipment for that specialty and count as improvised equipment for other uses of the same skill. Also, consider our top of the line superior toolkits for the best tools that money can buy. These superior toolkits count as superior tools (+2) for the specialty in question and sufficient tools for any other application of the skill.","quantity":0,"costrating":9,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"EXlYN1hS2xFtOoC8"} -{"name":"USD-2280L “Zeus” Light Lasrifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Perfect for use on spaceships or stations across the system, the USD-2280L “Zeus” Light Lasrifle is jam-packed with all the essentials needed for successful space security. From its sleek, curved barrel to its finger-molded grip, the Zeus is a miracle for the professional security worker.","quantity":0,"costrating":8,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"3M","damage_hearts":"12M","damage_spade":"18M","damage_diamond":"6M","hands":2,"pierce":0,"range":20,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"EpfGa44ZASM6RxvM"} +{"name":"USD-2280L “Zeus” Light Lasrifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Perfect for use on spaceships or stations across the system, the USD-2280L “Zeus” Light Lasrifle is jam-packed with all the essentials needed for successful space security. From its sleek, curved barrel to its finger-molded grip, the Zeus is a miracle for the professional security worker.","quantity":0,"costrating":8,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"3M","damage_hearth":"12M","damage_spade":"18M","damage_diamond":"6M","hands":2,"pierce":0,"range":20,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"EpfGa44ZASM6RxvM"} {"name":"AR Glasses","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Join the AR revolution. Join the twenty-third century. AR glasses look a lot like typical glasses, except they project augmented reality (AR) information before the wearer's eyes. This allows the wearer to read AR tags, access AR data and overlay projections on the world around her. Doing this, however, requires wirelessly interfacing the AR glasses with a computer—typically a hand terminal. This connection is typically a radio or infrared (IR) connection.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"GGnTiYuoZmtfW1cu"} {"name":"Expert System (Deluxe)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":7,"worn":false,"description":"Know your knowns and your known unknowns! An expert system is software that provides a database of knowledge and useful advice on a given topic. This is often designed to hook in to AR software, projecting useful tags and other information right before the user's eyes, aiding in a variety of tasks. Every expert software is designed to support one skill, or sometimes a specific experience in a skill. By taking a moment (an interact action in combat) the user can query the expert system for help on this skill. Mechanically this works as if the expert system is making a group effort action supporting the user, with a total based on the quality of the software (see page XXX). An action may only benefit from one expert system at a time. Expert software comes in four qualities: basic (total 10), pro (total 12), deluxe (total 14) and ultimate (total 16). Example: Stan is using a pro expert system to help him with ship repairs. He makes the required Dex/mechanic flip and gets a total of 9, not yet taking into account the expert system. Since expert systems work exactly like secondary characters in a group effort action, and since the expert system's total—12 for pro quality—is higher than Stan's total, he gets a +2 bonus to his action. This gives him a final total of 11.","quantity":0,"costrating":8,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"GJ38ece2gUCLzqNb"} {"name":"Translation Software","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":3,"worn":false,"description":"Don't let the language barrier be an issue. Translation software provides real time on-the-fly translation between two languages. Every language pairing is its own software. Most translation software is capable of outputting the translation in both speech and text, and often includes the ability to manually enter new vocabulary and idioms. No translation software is perfect, and most still has problems translating less common subculture slang or figures of speech.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"GeoammxYJ3lVSOnH"} {"name":"Backpack","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"container","data":{"big":0,"computer":0,"conceal":0,"container":5,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Strap things to your back so that you don't have to carry them in your hands! This designer backpack comes in a variety of colors and styles—perfect for any occasion. The backpack features one large pocket and a variety of smaller pockets for your carrying convenience. Retrieving an item from a backpack requires an interact action to open the backpack and fish around in addition to the usual interact action to retrieve the item.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"H8mMpHD0idwFSEsQ"} {"name":"Mainframe","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":10,"computer":7,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Do you have the need for not just sufficient, but vigorous computing? Order a mainframe today! Mainframes are designed to go beyond personal computing needs. They host popular net nodes, serve as the main computers for spaceships, administrate corp sites and sit on academic campuses. Mainframes are generally large machines meant to remain wired in place and communicated with through individual workstations or hand terminals. Many have wireless capabilities, but this is often left turned off to take advantage of the superior bandwidth offered by wired connections.","quantity":0,"costrating":9,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_computer.svg","effects":[],"_id":"Hsnyxz7KKBuu0lp8"} {"name":"Personal Assistant","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":5,"worn":false,"description":"When you need a little bit of help, get a personal assistant! Personal assistant software uses adaptive algorithms to learn the wants, needs, schedule and habits of a particular user, looking up information and making suggestions without prompting. All personal assistant software requires several weeks to adapt to a new user, and most is given a customizable anthropomorphic avatar, or at least a name. This avatar can be projected into the surrounding environment when viewed through AR. Many personal assistants have adjustable personalities as well.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"I89e6zkA3IU2j0rc"} -{"name":"USD-490L “Indra” Light Laspistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"In zero-G the professional soldier knows not to be caught with only a ballistic gun at hand, because dead is what she will be. Don't let this happen to you. Take the USD-490L “Indra” Light Laspistol into your zero-G battles and you will never want to use another lasgun again!","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearts":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"ILzHxSck1VV5Qvl2"} +{"name":"USD-490L “Indra” Light Laspistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"In zero-G the professional soldier knows not to be caught with only a ballistic gun at hand, because dead is what she will be. Don't let this happen to you. Take the USD-490L “Indra” Light Laspistol into your zero-G battles and you will never want to use another lasgun again!","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearth":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"ILzHxSck1VV5Qvl2"} {"name":"Regrowth Therapy","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Need a new arm, leg or bodily organ? Look no further! Lost limbs, digits, eyes and many other organs can be regrown, but this is expensive, takes time and requires frequent visits to the doctor to apply the next stage of the therapy. Limbs in the process of regrowth typically are tender and itch fiercely. For full rules on surgery and regrowth therapy, see page XXX.","quantity":0,"costrating":8,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"IMhke5iishvcwjws"} {"name":"USD-IIh Bulwak Ballistic Suite","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"

Simply the best in light but durable ballistic protection, the USD-11h “Bulwark” Ballistic Suit stops bullets in their tracks. Utilizing Utakar’s proprietary Shell-StopperTM gel technology, the Bulwark hardens upon impact, distributing the kinetic force of the impact throughout the body. Self-sealing gel closes in seconds. Designer pockets fit most common magazines. It is available in black, charcoal, rosewood and navy.

\n

 

","quantity":0,"costrating":5,"defensive":0,"containerid":"","bulky":0,"dr":2,"gel":3,"reflect":0,"str":0,"vac":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/bulwak_armor.svg","effects":[],"_id":"IzyB0If465nUk2Ws"} -{"name":"USD-07 “Firefly” Shockstick","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Critical Effect: When this critical effect is chosen, increase the target's Stun consequence a severity. Incapacitate your opponents with a nonlethal electric charge, using this USD-07 “Firefly” Shockstick. The Firefly is a telescoping baton that has a rubberized grip on one end. This insulates the wielder from the electric charge, which can be switched on or off using a button on the grip. If struck, the electrolyzed end discharges, delivering a shock to the opponent intended to stun or incapacitate.","quantity":0,"costrating":4,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str+3L","damage_hearts":"Str+12L","damage_spade":"Str+18L","damage_diamond":"Str+6L","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":true,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"JZghdsLCHaAIAhCH"} -{"name":"Unarmed","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"It doesn't get much more primal than old-school fisticuffs. Despite all the technological ways to go for blood, fistfights remain the most common form of violence in the Sol system. This listing represents the human capacity to attack with fists, feet or teeth.","quantity":0,"costrating":"—","defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"½StrL","damage_hearts":"Str×2L","damage_spade":"Str×3L","damage_diamond":"StrL","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"K05lfEHRogl3m4Df"} +{"name":"USD-07 “Firefly” Shockstick","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Critical Effect: When this critical effect is chosen, increase the target's Stun consequence a severity. Incapacitate your opponents with a nonlethal electric charge, using this USD-07 “Firefly” Shockstick. The Firefly is a telescoping baton that has a rubberized grip on one end. This insulates the wielder from the electric charge, which can be switched on or off using a button on the grip. If struck, the electrolyzed end discharges, delivering a shock to the opponent intended to stun or incapacitate.","quantity":0,"costrating":4,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str+3L","damage_hearth":"Str+12L","damage_spade":"Str+18L","damage_diamond":"Str+6L","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":true,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"JZghdsLCHaAIAhCH"} +{"name":"Unarmed","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"It doesn't get much more primal than old-school fisticuffs. Despite all the technological ways to go for blood, fistfights remain the most common form of violence in the Sol system. This listing represents the human capacity to attack with fists, feet or teeth.","quantity":0,"costrating":"—","defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"½StrL","damage_hearth":"Str×2L","damage_spade":"Str×3L","damage_diamond":"StrL","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"K05lfEHRogl3m4Df"} {"name":"USD-24k Aegis Reflect Suit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"

Do lasers threaten to give you health problems by burning holes into your flesh? Then look no further! The USD-24k “Aegis” Reflect Suit scatters lasers before they can scatter you. Constructed of bleeding-edge materials, the Aegis refracts laser light, leaving the wearer unharmed. This comes with either a frosted or glossy finish.

\n

 

","quantity":0,"costrating":6,"defensive":0,"containerid":"","bulky":0,"dr":2,"gel":0,"reflect":3,"str":0,"vac":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/bulwak_armor.svg","effects":[],"_id":"K6pBGZRiBzPzHHPZ"} {"name":"Biometric Reader","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"For all your secure needs, you can rely on a biometric reader. A biometric reader is typically used as a secure input device to authenticate the identity of the computer user. Most biometric readers scan fingerprints or retinas, although DNA biometric readers exist as well. A biometric reader is typically connected to a host computer, which then takes input from the device.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"KFF8f1849H6BTjk3"} {"name":"ToolKit (Basic)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"After using our toolkits, you'll feel naked without one! A variety of toolkits are available, each geared towards a specific kind of task and each containing tools useful in that task. When purchasing a toolkit, think about what the toolkit is geared for as a specific skill experience. For example, “electrician” might be a toolkit used with the mechanic skill. Tool kits count as sufficient equipment for that specialty and count as improvised equipment for other uses of the same skill. Also, consider our top of the line superior toolkits for the best tools that money can buy. These superior toolkits count as superior tools (+2) for the specialty in question and sufficient tools for any other application of the skill.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"KjHfCiJaHaPwHxEH"} @@ -38,29 +38,29 @@ {"name":"Surgery Kit (Basic)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":1,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Not all injuries happen within easy reach of a hospital or medical bay. For unexpected injuries in the remote reaches of space, there's the portable surgery kit. With a portable pack of surgeon's tools, diagnostic gear, cheap anesthetics and antibiotics, this kit counts as sufficient equipment for minor surgery, or improvised equipment (-2) for major surgery. Also consider our superior quality surgery kits, which count as superior tools (+2) for minor surgery or sufficient tools for major surgery! Contains materials for 10 surgeries. Performing surgery using one of these kits does not incur the expense of paying for a full surgery treatment (see page XXX).","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_computer.svg","effects":[],"_id":"LjALXCUxnMtqMynq"} {"name":"Encryption System (Pro)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":5,"worn":false,"description":"Keep your private life private. Encryption is necessary for any sort of secure transaction using broadcast communication, such as on the net or through radio comms. Most computers come with basic built-in encryption methods, but for those who want real security, bolstered encryption software is a no-brainer. Difficulty of breaking encryption scales with processing requirements. Encryption systems come in a variety of different qualities, with differing processing requirements (see page XXX).","quantity":0,"costrating":6,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"MB9mtcTOiuDTNMzK"} {"name":"Medikit (Superior)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Treat nagging injuries on the go! The medikit contains basic medical tools, useful for treating all major or simple injuries, including adhesive spray, antibiotics, a variety of ointments, an oxygen mask and sutures. This counts as sufficient tools for first aid or improvised equipment (-2) for minor surgery. Also, consider our superior quality medikits, which count as superior tools (+2) to first aid! Contains 10 uses.","quantity":0,"costrating":"","defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"MkgxXeeQniToOcPi"} -{"name":"USD-383 “Wasp” Light Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"A personal protection favorite, the USD-383 “Wasp” Light Pistol is ready to lock and load! Take aim at your favorite shooting range or when your life is in danger. The gun is small enough to fit most holsters or to slip into a purse! It comes with patent-pending rubberized grip and is available in gun barrel gray, matte black, racing stripe red or powder pink.","quantity":0,"costrating":5,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearts":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"Mkv9Q7x9IaGJ5uvn"} -{"name":"USD-1200 Amazon Light Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"

The rifle you need when you’re on the go, the USD-1200 “Amazon” Light Rifle has beendesigned from the ground up for easy transportation and assembly. With  balancing range, magazine capacity and ease of maintenance, the Amazon gets the job done. Satisfaction guaranteed. Some assembly required.

\n

 

","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearts":"12M","damage_spade":"18M","damage_diamond":"6M","hands":2,"pierce":0,"range":20,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/usd-1200.svg","effects":[],"_id":"NN9iWxPKU9djFfA9"} -{"name":"USD-3200 Valkyrie Heavy Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"

The USD-3200 “Valkyrie” Heavy Rifle is a masterpiece of twenty-third century engi-neering, combined with sleek twenty-second century ascetics. Own the best-designed and best-looking heavy rifle on the market! It comes with two autofire settings and a designer gun case. Remember, Valkyrie means quality.

\n

 

","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearts":"14M","damage_spade":"21M","damage_diamond":"7M","hands":2,"pierce":0,"range":20,"reload":1,"shots":20,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/usd-3200.svg","effects":[],"_id":"O4B0meZMhDgxDXcC"} +{"name":"USD-383 “Wasp” Light Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"A personal protection favorite, the USD-383 “Wasp” Light Pistol is ready to lock and load! Take aim at your favorite shooting range or when your life is in danger. The gun is small enough to fit most holsters or to slip into a purse! It comes with patent-pending rubberized grip and is available in gun barrel gray, matte black, racing stripe red or powder pink.","quantity":0,"costrating":5,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearth":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"Mkv9Q7x9IaGJ5uvn"} +{"name":"USD-1200 Amazon Light Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"

The rifle you need when you’re on the go, the USD-1200 “Amazon” Light Rifle has beendesigned from the ground up for easy transportation and assembly. With  balancing range, magazine capacity and ease of maintenance, the Amazon gets the job done. Satisfaction guaranteed. Some assembly required.

\n

 

","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearth":"12M","damage_spade":"18M","damage_diamond":"6M","hands":2,"pierce":0,"range":20,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/usd-1200.svg","effects":[],"_id":"NN9iWxPKU9djFfA9"} +{"name":"USD-3200 Valkyrie Heavy Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"

The USD-3200 “Valkyrie” Heavy Rifle is a masterpiece of twenty-third century engi-neering, combined with sleek twenty-second century ascetics. Own the best-designed and best-looking heavy rifle on the market! It comes with two autofire settings and a designer gun case. Remember, Valkyrie means quality.

\n

 

","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearth":"14M","damage_spade":"21M","damage_diamond":"7M","hands":2,"pierce":0,"range":20,"reload":1,"shots":20,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/usd-3200.svg","effects":[],"_id":"O4B0meZMhDgxDXcC"} {"name":"GPS Tracker","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Always know your way around with this GPS tracker! Useful on any planetary body with GPS satellites, this simple GPS tracker has a small display for its coordinates and also can transmit wirelessly to any close computer or other wireless device. It is best used with an Expert System for planetary navigation!","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"Phq7WiW0byei3CcO"} {"name":"Night Vision Glasses","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Don't be caught in the dark without them. They look like regular sunglasses, meeting all your style requirements! These night vision glasses can detect infrared, projecting a false-color image right before the wearer's eyes. Good for seeing objects in the dark but less useful for reading or color detection.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"Pm47QnZSb5o5Ooqq"} {"name":"Disposable Test Kit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Have a specific condition that needs testing? That calls for a disposable test kit. This kit tests for a specific disease, toxin, drug or medical condition, such as sleep deprivation or pregnancy. It is typically administered through either drawing blood or through a urine sample. Results usually take a minute or two. Contains 10 disposable tests.","quantity":0,"costrating":3,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"PzAPqa0QH8WY5MO8"} {"name":"Major Surgery","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Minor surgery not enough for your wounds? Major surgery may be just what the doctor ordered! Major surgery is capable of removing even more potent lasting consequences, including many of the worst lingering injuries (see page XXX). For full rules on surgery, see page XXX.","quantity":0,"costrating":7,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"QTfWF9guaWTefAvS"} {"name":"Laser Comm","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Direct your communication with a laser comm. Laser comms use lasers to transmit and receive data at a directed target. This limits the ability to intercept the data because it is not broadcast to the world but rather directed at a specific target. Naturally, the ability to use a laser comm relies on having a direct line of communication unobscured by walls, the curve of planetary bodies or atmospheric interference. This personal laser comm is good for a dozen kilometers on a clear day in atmospheric conditions or several thousand kilometers in the vacuum of space.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"QvBZml9C4OxCvSOR"} {"name":"IR Cloak","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Do your enemies have the means of IR detection? Foil even that with this IR cloak! An IR cloak appears to be a thick poncho or tarp, which is usually matte black in color. It self-adjusts to the ambient temperature to fool infrared detection methods. This is usually coupled by cutting the lights or otherwise moving around in the dark to foil visible spectrum detection as well.","quantity":0,"costrating":7,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"Rs8osdikMhPYixjf"} -{"name":"USD-383 Wasp Light Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"

A personal protection favorite, the USD-383 “Wasp” Light Pistol is ready to lock and load! Take aim at your favorite shooting  range or when your life is in danger. The gun is small enough to fit most holsters or to slip into a purse! It comes with patent-pending rubberized grip and is available in gun barrel gray, matte black, racing stripe red or powder pink. 

\n

 

","quantity":0,"costrating":5,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearts":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/usd-383.svg","effects":[],"_id":"U55o7zC4bKnqpXug"} +{"name":"USD-383 Wasp Light Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"

A personal protection favorite, the USD-383 “Wasp” Light Pistol is ready to lock and load! Take aim at your favorite shooting  range or when your life is in danger. The gun is small enough to fit most holsters or to slip into a purse! It comes with patent-pending rubberized grip and is available in gun barrel gray, matte black, racing stripe red or powder pink. 

\n

 

","quantity":0,"costrating":5,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearth":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/usd-383.svg","effects":[],"_id":"U55o7zC4bKnqpXug"} {"name":"Expert System (Basic)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":3,"worn":false,"description":"Know your knowns and your known unknowns! An expert system is software that provides a database of knowledge and useful advice on a given topic. This is often designed to hook in to AR software, projecting useful tags and other information right before the user's eyes, aiding in a variety of tasks. Every expert software is designed to support one skill, or sometimes a specific experience in a skill. By taking a moment (an interact action in combat) the user can query the expert system for help on this skill. Mechanically this works as if the expert system is making a group effort action supporting the user, with a total based on the quality of the software (see page XXX). An action may only benefit from one expert system at a time. Expert software comes in four qualities: basic (total 10), pro (total 12), deluxe (total 14) and ultimate (total 16). Example: Stan is using a pro expert system to help him with ship repairs. He makes the required Dex/mechanic flip and gets a total of 9, not yet taking into account the expert system. Since expert systems work exactly like secondary characters in a group effort action, and since the expert system's total—12 for pro quality—is higher than Stan's total, he gets a +2 bonus to his action. This gives him a final total of 11.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"VD52Z8KMWtSACXYp"} {"name":"USD-11h “Bulwark” Ballistic Suit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Simply the best in light but durable ballistic protection, the USD-11h “Bulwark” Ballistic Suit stops bullets in their tracks. Utilizing Utakar's proprietary Shell-Stopper™ gel technology, the Bulwark hardens upon impact, distributing the kinetic force of the impact throughout the body. Self-sealing gel closes in seconds. Designer pockets fit most common magazines. It is available in black, charcoal, rosewood and navy.","quantity":0,"costrating":5,"defensive":0,"containerid":"","bulky":0,"dr":2,"gel":3,"reflect":0,"str":0,"vac":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/generic_armor.svg","effects":[],"_id":"VDP99ZYhwXxMH2ll"} {"name":"Microcomputer","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Are you tracking an object, calculating basic numbers or broadcasting a message on loop? Do you need only very basic computing and wireless ability? Then a microcomputer is what you're looking for! This dime-sized computer is capable of basic computations and processing. It has inbuilt wireless access using either IR or radio comms (see page XXX). Unlike other computers and due to its size, it has no display or other input or output features, requiring peripherals or wireless communication with another device.","quantity":0,"costrating":1,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"VW7edurHNZF9039v"} -{"name":"Combat Utility Knife","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"It's a weapon. It's a tool. It's both! Combat utility knives are a versatile weapon and tool, balanced for both hand-to-hand use as well as sudden throws. Combat utility knives can be used to cut rope, pry open simple doors or butter toast. Never leave home without one! The handle comes in a variety of custom styles.","quantity":0,"costrating":1,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str×½M","damage_hearts":"Str×2M","damage_spade":"Str×3M","damage_diamond":"StrM","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":true,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"VoOZYzdC0F1TIF8B"} -{"name":"Xenocom X4 Machine Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"The Xenocom X4 Machine Pistol is a military favorite. Coming with the best fully automatic capability of any pistol on the market, the X4 outdoes the competition. Pick yours up and feel the ballistic power in your hand. Place an order for the entire unit. Outfit our squad with the best!","quantity":0,"costrating":9,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"3M","damage_hearts":"12M","damage_spade":"18M","damage_diamond":"6M","hands":1,"pierce":0,"range":10,"reload":1,"shots":15,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"W2L04UuUZ15VXsH7"} +{"name":"Combat Utility Knife","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"It's a weapon. It's a tool. It's both! Combat utility knives are a versatile weapon and tool, balanced for both hand-to-hand use as well as sudden throws. Combat utility knives can be used to cut rope, pry open simple doors or butter toast. Never leave home without one! The handle comes in a variety of custom styles.","quantity":0,"costrating":1,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str×½M","damage_hearth":"Str×2M","damage_spade":"Str×3M","damage_diamond":"StrM","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":true,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"VoOZYzdC0F1TIF8B"} +{"name":"Xenocom X4 Machine Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"The Xenocom X4 Machine Pistol is a military favorite. Coming with the best fully automatic capability of any pistol on the market, the X4 outdoes the competition. Pick yours up and feel the ballistic power in your hand. Place an order for the entire unit. Outfit our squad with the best!","quantity":0,"costrating":9,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"3M","damage_hearth":"12M","damage_spade":"18M","damage_diamond":"6M","hands":1,"pierce":0,"range":10,"reload":1,"shots":15,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"W2L04UuUZ15VXsH7"} {"name":"Biomonitor","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"This biomonitor is a small, barely-invasive implant that periodically records simple medical data, such as blood pressure, pulse, heart rate and blood sugar. It comes complete with a small external switch that turns on the capability to communicate wirelessly with medical equipment. This aids in diagnosis and first aid on the host, granting a +2 bonus to such endeavors.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"WzZjCTfa518Rsybn"} {"name":"Minor Surgery","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Suffering from a simple bone fracture, minor organ damage or moderate tissue damage? A variety of minor surgeries may be able to help you! They are capable of removing a variety of lasting consequences, including many on the Lingering Injury tables (see page XXX). For full rules on surgery, see page XXX.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"XW9zucts77QdfayO"} {"name":"Ballistic Clips","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":null,"software":0,"worn":false,"description":"What are guns without clips of ammunition? Poorly-designed clubs! Don't bring a club to a gun fight. Ammunition is sold in clips fitting the gun in question. Most guns have their own standard for ammunition in terms of both caliber and cartridge design. The type of gun the ammo is designed for must be specified when the clip is purchased.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"YrnLXsHuVlmt1yO8"} {"name":"Workstation","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":5,"computer":5,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"For serious computing needs, a workstation computer will excel! These computers are designed to be set on a desk or hung on a wall. They have the serious processing power needed for the most resource intensive games, extended scientific calculations and encryption. They can also serve as a makeshift server if needed. Workstation computers typically come with touchscreen and voice controls, as well as key inputs and sometimes simple biometric input.","quantity":0,"costrating":6,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_computer.svg","effects":[],"_id":"ZSu4Yt7TYSKIGtNw"} {"name":"IR Comm","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Does your device not speak infrared? Get a dedicated IR comm! IR comms use infrared to transmit and receive data. This is useful only at very short ranges—usually no more than a few dozen meters. It is of particular use in short distance, secured transmissions because IR does not penetrate walls and its short distance limits eavesdropping. IR communication comes built in to most hand terminals and other short-range wireless devices. A dedicated IR comm, such as this one, can be attached to other devices to give IR communication capabilities.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"aEtzovx5IkSSaMhO"} -{"name":"USD-4700L “Thor” Heavy Lasrifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Don't be out-gunned: carry the USD-4700L “Thor” Heavy Lasrifle. The best in range, accuracy and automatic fire capacity, every Thor heavy lasrifle is constructed from the finest materials and tested by the weapons experts at Utakar System Dynamics. So don't be out-gunned. Choose the best!","quantity":0,"costrating":9,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearts":"14M","damage_spade":"21M","damage_diamond":"7M","hands":2,"pierce":0,"range":20,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"aKC117PiIlTgqhr2"} +{"name":"USD-4700L “Thor” Heavy Lasrifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Don't be out-gunned: carry the USD-4700L “Thor” Heavy Lasrifle. The best in range, accuracy and automatic fire capacity, every Thor heavy lasrifle is constructed from the finest materials and tested by the weapons experts at Utakar System Dynamics. So don't be out-gunned. Choose the best!","quantity":0,"costrating":9,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearth":"14M","damage_spade":"21M","damage_diamond":"7M","hands":2,"pierce":0,"range":20,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"aKC117PiIlTgqhr2"} {"name":"Gecko-Climbers","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Have a surface you need to scale? Try some Gecko-Climbers! These gloves and boots strap firmly to the limbs, allowing the climber to stick to most surfaces in a manner similar to a gecko. Only capable of supporting up to 100 kg, a wearer of Gecko-Climbers should travel light. Gecko-Climbers count as sufficient tools for climbing and furthermore provide a +2 bonus on actions to climb surfaces to which they stick.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"aTeyx97Uo04c6OoT"} -{"name":"USD-9700 Stun Grenade","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Perfect for crowd control, the USD-9700 Stun Grenade is a wonder to behold. Just set the grenade to burst on timer or upon impact and let it go. The USD-9700 is guaranteed to stun or incapacitate with nonlethal precision. Order yours today!","quantity":0,"costrating":3,"defensive":0,"containerid":"","area":5,"autofire":0,"damage_club":"4L","damage_hearts":"16L","damage_spade":"24L","damage_diamond":"8L","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":true,"thrown":true,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"b0CoCTzsIszkmEZD"} +{"name":"USD-9700 Stun Grenade","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Perfect for crowd control, the USD-9700 Stun Grenade is a wonder to behold. Just set the grenade to burst on timer or upon impact and let it go. The USD-9700 is guaranteed to stun or incapacitate with nonlethal precision. Order yours today!","quantity":0,"costrating":3,"defensive":0,"containerid":"","area":5,"autofire":0,"damage_club":"4L","damage_hearth":"16L","damage_spade":"24L","damage_diamond":"8L","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":true,"thrown":true,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"b0CoCTzsIszkmEZD"} {"name":"Laser Batt-Packs","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":null,"software":0,"worn":false,"description":"Keep your lasers powered up and ready! Laser weapons are powered by high-density batt-packs, capable of releasing the tremendous charge necessary to power weaponized lasers in a small amount of time. The downside of these high-density batt-packs is that it takes serious industrial equipment to recharge them, meaning that batt-packs are typically bought as one-use items and the expended packs simply sold back to the manufacturer for pocket change. Each batt-pack holds the weapon's listed “shots” in charges. Like clips, batt-packs are typically manufactured for a single model of firearm.","quantity":0,"costrating":3,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"b3GPnPnHrh9muSAi"} {"name":"Flashlight","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"While most hand terminals have basic flashlight functionality, they don't have the power of illumination possessed by this durable, high-output survival flashlight! Useful for exploration when the power has gone out, the visible light beam illuminates at 3000 lumens and up to 500 m away!","quantity":0,"costrating":1,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"bI4q9Fx5DBRYMtcD"} {"name":"E-Lockpick","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Never be sealed out of electronic doors again! This small device cycles rapidly through possible electronic lock combinations and patterns, gaining access to electronically-sealed doors or hatches. This counts as sufficient tools for actions to open electronic locks and typically opens them within a few seconds. Attempts to access the locks may still be logged by locks capable of doing so.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"cb8z7SKsUAeWUkhM"} @@ -73,26 +73,26 @@ {"name":"Cybernetic Replacement Limb","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":1,"neg":false,"mil":false,"software":0,"worn":false,"description":"Can't afford the cost of a regrowth treatment? This cybernetic limb has you covered! Just have the nerve interface installed on the arm or leg's stump and let the machinery do the rest. A week's training is required to regain full limb capability. Cybernetic arms and legs typically come complete with faux-skin, making them look slightly less unnatural. A cybernetic limb will never have tactile input like a natural arm or leg, but in all other regards, cybernetic limbs function like the real thing.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"iy3isMKVetZnBD8L"} {"name":"Hand Terminal","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":3,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"The ubiquitous hand terminal is a must-have for anyone! These handheld computers work as video and audio comms; are capable of IR and wireless connections; have an inbuilt camera, microphone and GPS; play games; do basic calculations; connect to the net; and interface with most common AR implants and glasses. Most come with both voice and touchscreen controls.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_computer.svg","effects":[],"_id":"juPjuak0WiII3VOY"} {"name":"Adrenaline Booster Gland","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":2,"neg":false,"mil":true,"software":0,"worn":false,"description":"A boost when you need it, the adrenaline booster gland is an artificial organ implanted near the kidneys. Typically triggered through a pre-programmed biological input such as saying a specific word, a tongue pattern or a series of finger taps, the implant gives a +2 bonus to Strength, Dexterity, Speed and Endurance actions for a number of rounds equal to the target's Endurance. This bonus also applies to Strength-based damage, Defense and action order. Activating the gland is an interact action. After its primary effects wear off, the user increases her Fatigue consequence a severity, because the after-effects of the gland leave her shaking and weakened. The gland cannot be used for another 24 hours because it has to remanufacture its artificial adrenaline.","quantity":0,"costrating":9,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"kEvGZ3xMy2Xtscud"} -{"name":"Baton","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Barons are a tried-and-true classic when it comes to dealing out blows with a minimum of lethal force. Favored as a control weapon by light security forces the world over, it never hurts to have a baton at your side. Baton telescopes for easy pocket storage. It is available in both solid colors and faux-wood.","quantity":0,"costrating":1,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"½Str+1L","damage_hearts":"Str×2+4L","damage_spade":"Str×3+6L","damage_diamond":"Str+2L","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"l3LUBCnICPAknvnr"} +{"name":"Baton","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Barons are a tried-and-true classic when it comes to dealing out blows with a minimum of lethal force. Favored as a control weapon by light security forces the world over, it never hurts to have a baton at your side. Baton telescopes for easy pocket storage. It is available in both solid colors and faux-wood.","quantity":0,"costrating":1,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"½Str+1L","damage_hearth":"Str×2+4L","damage_spade":"Str×3+6L","damage_diamond":"Str+2L","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"l3LUBCnICPAknvnr"} {"name":"Unitech “Sunspot” C3 Vac Suit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":5,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"The Unitech “Sunspot” C3 Vac Suit is the spacer's best friend. Capable of operating for up to six hours in complete vacuum and in a variety of pressure, radiation and atmospheric conditions, this space suit is truly the first in its class. Compressed air canisters connect at both hips, providing redundancy and allowing changes in the field. AR link included.","quantity":0,"costrating":5,"defensive":0,"containerid":"","bulky":1,"dr":3,"gel":0,"reflect":0,"str":0,"vac":true},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/generic_armor.svg","effects":[],"_id":"lEzknag9lK4IYoki"} {"name":"Xenocom “Infinity” PowerShell Armor","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":15,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":true,"description":"Go beyond the usual limits with Xenocom “Infinity” Powershell Armor. The go-to choice of security professions for more than three decades, Infinity power armor is rugged and reliable. Tailor-made for field maintenance and repair, the Infinity comes with HUD, AR link, a six-hour air supply, left and right arm weapon mounts and internal power cell. Holster points optional. Comes in a variety of colors.","quantity":0,"costrating":14,"defensive":0,"containerid":"","bulky":3,"dr":20,"gel":0,"reflect":0,"str":5,"vac":true},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/generic_armor.svg","effects":[],"_id":"lGIITGW9DqxsjvBd"} {"name":"P&W Wide-Trim Designer Coverjack","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":0,"computer":0,"conceal":2,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Just because you need to wear armor doesn't mean you have to sacrifice style. With the Pfeiffer & Wu Wide-Trim Designer Coverjack you can have your cake and eat it, too! Designed for maximum comfort and discrete protection, all P&W coverjacks can pass as normal suits upon both visual and infrared inspection. This comes in a variety of designer colors! Power tie optional.","quantity":0,"costrating":4,"defensive":0,"containerid":"","bulky":0,"dr":3,"gel":0,"reflect":0,"str":0,"vac":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/generic_armor.svg","effects":[],"_id":"laY2NPjRpuJ4N3ud"} {"name":"Chameleon Suit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"You'll blend right in with this chameleon suit! This tight-fitting suit changes color as the wearer moves, similar to a chameleon. This aids the wearer's attempts at stealth, but it does not fool infrared detection. It counts as a superior tool (+2) for stealth against simple, unaided observation.","quantity":0,"costrating":7,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"lpLONx41Dmd7wKzr"} {"name":"Voice Mask","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Studies show that the largest cause of disguise failure is identification by voice. Change your voice today! This device attaches to the wearer's throat, usually sitting on the shoulder or neck, beneath the collar. Once attached and turned on, it will distort the wearer's voice so as to be unrecognizable. Other people's voices can be mimicked, but this requires both a sample audio recording of the speaker to be mimicked, and calibration with the wearer's voice—an Int/programming-10 flip. (Improvised)","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"lpPYNxyV3jH22nbk"} -{"name":"USD-1200 “Amazon” Light Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The rifle you need when you're on the go, the USD-1200 “Amazon” Light Rifle has been designed from the ground up for easy transportation and assembly. With balancing range, magazine capacity and ease of maintenance, the Amazon gets the job done. Satisfaction guaranteed. Some assembly required.","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"3M","damage_hearts":"12M","damage_spade":"18M","damage_diamond":"6M","hands":2,"pierce":0,"range":20,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"lsIbTfdKK0e19vfO"} -{"name":"USD-9300 Frag Grenade","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"The USD-9300 is the ultimate in frag grenade flexibility and reliability. It comes with two modes of operation: impact or timer. Simply arm the grenade and fling it at foes, or let it count down. The choice is yours!","quantity":0,"costrating":4,"defensive":0,"containerid":"","area":5,"autofire":0,"damage_club":"4M","damage_hearts":"16M","damage_spade":"24M","damage_diamond":"8M","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":true,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"m9YpVR3nCrLIfLQN"} +{"name":"USD-1200 “Amazon” Light Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The rifle you need when you're on the go, the USD-1200 “Amazon” Light Rifle has been designed from the ground up for easy transportation and assembly. With balancing range, magazine capacity and ease of maintenance, the Amazon gets the job done. Satisfaction guaranteed. Some assembly required.","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"3M","damage_hearth":"12M","damage_spade":"18M","damage_diamond":"6M","hands":2,"pierce":0,"range":20,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"lsIbTfdKK0e19vfO"} +{"name":"USD-9300 Frag Grenade","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"The USD-9300 is the ultimate in frag grenade flexibility and reliability. It comes with two modes of operation: impact or timer. Simply arm the grenade and fling it at foes, or let it count down. The choice is yours!","quantity":0,"costrating":4,"defensive":0,"containerid":"","area":5,"autofire":0,"damage_club":"4M","damage_hearth":"16M","damage_spade":"24M","damage_diamond":"8M","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":true,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"m9YpVR3nCrLIfLQN"} {"name":"Data Chip","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Data chips: for when the net just won't cut it! Data chips are small silicate chips intended to transfer data physically between computers. They are often used when transferal over the net would be deemed insecure or where no local net is available. All data chips have a software rating. While data chips cannot run software as can a computer, they can store software up to the same rating. So, for example, a Data Chip 5 could store a Software 5 program or two Software 4 programs, etc. A data chip has a cost rating equal to the software rating.","quantity":0,"costrating":-1,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"mD6ucBx7dzEJe9hj"} -{"name":"Sinoex Monowhip XT","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"Critical Effect: When this critical effect is chosen, the monowhip does not break upon impact, as is normal. Crafted by the exotic materials experts at Sinoex, the Sinoex Monowhip XT is a coiled strand of near-monomolecular wire with a weight on the end held in a magnetized handle. Upon pressing a button, a power source in the handle causes the wire to uncoil and extend outward, providing the ideal cutting tool. Monowhips tear through armor like cardboard, but their limited tensile strength means they are typically one-use weapons, breaking after they successfully strike a target.","quantity":0,"costrating":5,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str×¼S","damage_hearts":"Str×¾S","damage_spade":"StrS","damage_diamond":"Str×½S","hands":1,"pierce":10,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"mQLJjG8uWn31Oyy6"} -{"name":"Xenocom L3 Machine Laspistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"The L3 Machine Laspistol is the latest military-grade laspistol from Xenocom. It's heavy-duty ionized battery contains enough charge for sustained fire, and its state of the art heat-sinks support the highest rates if automatic fire. Pick yours up and make the best decision you've ever made today!","quantity":0,"costrating":11,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"3M","damage_hearts":"12M","damage_spade":"18M","damage_diamond":"6M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"o56uRwUqBo9Cde5Z"} +{"name":"Sinoex Monowhip XT","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"Critical Effect: When this critical effect is chosen, the monowhip does not break upon impact, as is normal. Crafted by the exotic materials experts at Sinoex, the Sinoex Monowhip XT is a coiled strand of near-monomolecular wire with a weight on the end held in a magnetized handle. Upon pressing a button, a power source in the handle causes the wire to uncoil and extend outward, providing the ideal cutting tool. Monowhips tear through armor like cardboard, but their limited tensile strength means they are typically one-use weapons, breaking after they successfully strike a target.","quantity":0,"costrating":5,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str×¼S","damage_hearth":"Str×¾S","damage_spade":"StrS","damage_diamond":"Str×½S","hands":1,"pierce":10,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"mQLJjG8uWn31Oyy6"} +{"name":"Xenocom L3 Machine Laspistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"The L3 Machine Laspistol is the latest military-grade laspistol from Xenocom. It's heavy-duty ionized battery contains enough charge for sustained fire, and its state of the art heat-sinks support the highest rates if automatic fire. Pick yours up and make the best decision you've ever made today!","quantity":0,"costrating":11,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"3M","damage_hearth":"12M","damage_spade":"18M","damage_diamond":"6M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"o56uRwUqBo9Cde5Z"} {"name":"Geiger-Counter","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"A trusted method of detecting radiation, this clip-on geiger-counter will also determine the intensity of the radiation exposure and keep a count of absorbed rads. It can be set to alert the wearer either visually through its integrated display or audibly with a series of clicking noises.","quantity":0,"costrating":3,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"q1Aeerg8EkEiPLRM"} {"name":"Chem-Sniff","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Sniff out trouble with this chem-sniff. This olfactory sensor is able to detect and recognize substances by smell, comparing them against a database of commonly known scents. While it is not useful in a vacuum, underwater or against anything in a sealed environment, most everything otherwise leaves an olfactory signature that can be recorded and recognized again.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"qwYIVJSr2CcAwof7"} -{"name":"USD-3200 “Valkyrie” Heavy Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The USD-3200 “Valkyrie” Heavy Rifle is a masterpiece of twenty-third century engineering, combined with sleek twenty-second century ascetics. Own the best-designed and best-looking heavy rifle on the market! It comes with two autofire settings and a designer gun case. Remember, Valkyrie means quality.","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearts":"14M","damage_spade":"21M","damage_diamond":"7M","hands":2,"pierce":0,"range":20,"reload":1,"shots":20,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"rY5kH9T9h2PzxHXa"} +{"name":"USD-3200 “Valkyrie” Heavy Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The USD-3200 “Valkyrie” Heavy Rifle is a masterpiece of twenty-third century engineering, combined with sleek twenty-second century ascetics. Own the best-designed and best-looking heavy rifle on the market! It comes with two autofire settings and a designer gun case. Remember, Valkyrie means quality.","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearth":"14M","damage_spade":"21M","damage_diamond":"7M","hands":2,"pierce":0,"range":20,"reload":1,"shots":20,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"rY5kH9T9h2PzxHXa"} {"name":"Binoculars","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Don't let your enemies get close; spot them from afar with these binoculars! Binoculars are a tried and true method of seeing things at large distances. These binoculars are good for ×4 magnification, giving a +2 bonus to see objects at great distances.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"rqamf48CZsH7KfzW"} {"name":"Biometric Cracker","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"This device quickly cycles through biometric input used to open locks or secure areas. It is capable of imitating the input for fingerprints, irises, DNA and other common biometric methods. Wiring this device first into the biometric reader is required because it only fakes biometric data in digital form. It does not fake actual physical fingers or irises. This device counts as sufficient tools when surpassing such a device and is typically capable of bypassing compatible devices in a matter of seconds.","quantity":0,"costrating":7,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"sA4J47BrzPlhMnOR"} -{"name":"USD-840L “Horus” Heavy Laspistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The USD-840L “Horus” Heavy Laspistol is simply best heavy laspistol on the market. Designed from heavy-duty metal alloys and with anti-heat ceramic plating, the Horus outshoots the competition. Plus, the Horus' state of the art battery packs are guaranteed to hold the charges for months without unwanted discharge.","quantity":0,"costrating":8,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"2M","damage_hearts":"10M","damage_spade":"15M","damage_diamond":"5M","hands":1,"pierce":0,"range":10,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"tAizFnum5ufMQfvi"} +{"name":"USD-840L “Horus” Heavy Laspistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The USD-840L “Horus” Heavy Laspistol is simply best heavy laspistol on the market. Designed from heavy-duty metal alloys and with anti-heat ceramic plating, the Horus outshoots the competition. Plus, the Horus' state of the art battery packs are guaranteed to hold the charges for months without unwanted discharge.","quantity":0,"costrating":8,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"2M","damage_hearth":"10M","damage_spade":"15M","damage_diamond":"5M","hands":1,"pierce":0,"range":10,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"tAizFnum5ufMQfvi"} {"name":"Expert System (Ultimate)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":9,"worn":false,"description":"Know your knowns and your known unknowns! An expert system is software that provides a database of knowledge and useful advice on a given topic. This is often designed to hook in to AR software, projecting useful tags and other information right before the user's eyes, aiding in a variety of tasks. Every expert software is designed to support one skill, or sometimes a specific experience in a skill. By taking a moment (an interact action in combat) the user can query the expert system for help on this skill. Mechanically this works as if the expert system is making a group effort action supporting the user, with a total based on the quality of the software (see page XXX). An action may only benefit from one expert system at a time. Expert software comes in four qualities: basic (total 10), pro (total 12), deluxe (total 14) and ultimate (total 16). Example: Stan is using a pro expert system to help him with ship repairs. He makes the required Dex/mechanic flip and gets a total of 9, not yet taking into account the expert system. Since expert systems work exactly like secondary characters in a group effort action, and since the expert system's total—12 for pro quality—is higher than Stan's total, he gets a +2 bonus to his action. This gives him a final total of 11.","quantity":0,"costrating":10,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"uCGmNGm6JaBDrW3M"} -{"name":"Plasma Cutter","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"A favorite in heavy duty construction work, ship repair and emergency boarding actions, this plasma cutter cuts right through even the toughest metals and ceramics. The airlock busted? Just cut right through the hull! A plasma cutter can also be used as an improvised weapon in a pinch (see the damage listing above). Count as an improvised weapon.","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"1M","damage_hearts":"6M","damage_spade":"9M","damage_diamond":"3M","hands":1,"pierce":3,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"v51T7RAbTQ7Xu2Ka"} -{"name":"Xenocom X8 Machine Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"When you want maximum staying power, you want the Xenocom X8 Machine Rifle. Combining the best in range and magazine capacity with the best in full-auto heat suppression technology, the Xenocom X8 is second to none. Pair with our range finder or tracer round extras for the ultimate military battlefield kit.","quantity":0,"costrating":10,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"4M","damage_hearts":"16M","damage_spade":"24M","damage_diamond":"8M","hands":2,"pierce":0,"range":20,"reload":1,"shots":30,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"vItuyxzQjpXpeLcf"} +{"name":"Plasma Cutter","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"A favorite in heavy duty construction work, ship repair and emergency boarding actions, this plasma cutter cuts right through even the toughest metals and ceramics. The airlock busted? Just cut right through the hull! A plasma cutter can also be used as an improvised weapon in a pinch (see the damage listing above). Count as an improvised weapon.","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"1M","damage_hearth":"6M","damage_spade":"9M","damage_diamond":"3M","hands":1,"pierce":3,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"v51T7RAbTQ7Xu2Ka"} +{"name":"Xenocom X8 Machine Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"When you want maximum staying power, you want the Xenocom X8 Machine Rifle. Combining the best in range and magazine capacity with the best in full-auto heat suppression technology, the Xenocom X8 is second to none. Pair with our range finder or tracer round extras for the ultimate military battlefield kit.","quantity":0,"costrating":10,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"4M","damage_hearth":"16M","damage_spade":"24M","damage_diamond":"8M","hands":2,"pierce":0,"range":20,"reload":1,"shots":30,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"vItuyxzQjpXpeLcf"} {"name":"Expert System (Pro)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":5,"worn":false,"description":"Know your knowns and your known unknowns! An expert system is software that provides a database of knowledge and useful advice on a given topic. This is often designed to hook in to AR software, projecting useful tags and other information right before the user's eyes, aiding in a variety of tasks. Every expert software is designed to support one skill, or sometimes a specific experience in a skill. By taking a moment (an interact action in combat) the user can query the expert system for help on this skill. Mechanically this works as if the expert system is making a group effort action supporting the user, with a total based on the quality of the software (see page XXX). An action may only benefit from one expert system at a time. Expert software comes in four qualities: basic (total 10), pro (total 12), deluxe (total 14) and ultimate (total 16). Example: Stan is using a pro expert system to help him with ship repairs. He makes the required Dex/mechanic flip and gets a total of 9, not yet taking into account the expert system. Since expert systems work exactly like secondary characters in a group effort action, and since the expert system's total—12 for pro quality—is higher than Stan's total, he gets a +2 bonus to his action. This gives him a final total of 11.","quantity":0,"costrating":6,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"vJTVVLZ48JtFXPsE"} {"name":"Encryption System (Deluxe)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":7,"worn":false,"description":"Keep your private life private. Encryption is necessary for any sort of secure transaction using broadcast communication, such as on the net or through radio comms. Most computers come with basic built-in encryption methods, but for those who want real security, bolstered encryption software is a no-brainer. Difficulty of breaking encryption scales with processing requirements. Encryption systems come in a variety of different qualities, with differing processing requirements (see page XXX).","quantity":0,"costrating":8,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"vLoahjL5ZprVNg4M"} {"name":"Regenasone","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Get better faster with Regenasone. A potent healing aid, Regenasone speeds cellular regeneration within the body. If administered once a day, a dose of Regenasone reduces the time it takes to heal wounds from one week down to one day. This, however, leaves the recipient feeling hazy and lethargic. After Regenasone is administered and for the day afterward, the recipient increases her Fatigue consequence a severity. Pack of 10 doses.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"voJMdG5rlzSG9ggs"} diff --git a/scecd b/scecd new file mode 100644 index 0000000..e69de29 -- 2.35.3 From 1cd0506d3e25a31eabab51e66ce23b0fd4386916 Mon Sep 17 00:00:00 2001 From: tmtabor Date: Fri, 26 Feb 2021 13:43:13 -0800 Subject: [PATCH 05/47] Fixed a bug where if shock is erroneously set to 0, incSeverity is set to infinity and the script loops forever on line 260. --- module/sos-utility.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/sos-utility.js b/module/sos-utility.js index eb90a51..b5ebb70 100644 --- a/module/sos-utility.js +++ b/module/sos-utility.js @@ -233,7 +233,7 @@ export class SoSUtility extends Entity { } let dr = flipData.target.actor.data.data.scores.dr.value; - let shock = flipData.target.actor.data.data.scores.shock.value; + let shock = flipData.target.actor.data.data.scores.shock.value || 1; let defenseCritical = flipData.target.actor.data.data.scores.defense.critical; flipData.damageStatus = 'apply_damage'; -- 2.35.3 From c2c837b7789f86078204dbfc4298e02719e1bf8d Mon Sep 17 00:00:00 2001 From: sladecraven Date: Mon, 8 Mar 2021 22:46:33 +0100 Subject: [PATCH 06/47] Manage GM cards --- img/cards/hearth.webp | Bin 0 -> 3556 bytes img/icons/injury_generic.svg | 1 + module/actor.js | 20 ++++-- module/sos-flip-dialog.js | 24 +++---- module/sos-gm-deck.js | 124 +++++++++++++++++++++++++++++++++++ module/sos-main.js | 17 ++++- system.json | 4 +- template.json | 5 +- templates/chat-card.html | 2 + templates/gm-deck.html | 21 ++++++ 10 files changed, 193 insertions(+), 25 deletions(-) create mode 100644 img/cards/hearth.webp create mode 100644 img/icons/injury_generic.svg create mode 100644 module/sos-gm-deck.js create mode 100644 templates/chat-card.html create mode 100644 templates/gm-deck.html diff --git a/img/cards/hearth.webp b/img/cards/hearth.webp new file mode 100644 index 0000000000000000000000000000000000000000..46ece2d40707f9b29d97243db2fe6907d81c36fa GIT binary patch literal 3556 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 literal 0 HcmV?d00001 diff --git a/img/icons/injury_generic.svg b/img/icons/injury_generic.svg new file mode 100644 index 0000000..2225ed8 --- /dev/null +++ b/img/icons/injury_generic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/module/actor.js b/module/actor.js index ab284c5..1623188 100644 --- a/module/actor.js +++ b/module/actor.js @@ -54,8 +54,12 @@ export class SoSActor extends Actor { super.prepareData(); if ( !this.cardDeck ) { - this.cardDeck = new SoSCardDeck(); - this.cardDeck.initCardDeck( this, this.data.data.internals.deck ); + if ( this.hasPlayerOwner) { + this.cardDeck = new SoSCardDeck(); + this.cardDeck.initCardDeck( this, this.data.data.internals.deck ); + } else { + this.cardDeck = game.system.sos.gmDeck; + } } this.controlScores(); } @@ -100,10 +104,14 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ saveDeck( ) { let deck = { deck: duplicate(this.cardDeck.data.deck), - discard: duplicate(this.cardDeck.data.discard), - cardEdge: duplicate(this.cardDeck.data.cardEdge) - } - this.update( { 'data.internals.deck': deck }); + discard: duplicate(this.cardDeck.data.discard), + cardEdge: duplicate(this.cardDeck.data.cardEdge) + } + if ( this.hasPlayerOwner ) { + this.update( { 'data.internals.deck': deck }); + } else { + game.settings.set("foundryvtt-shadows-over-sol", "gmDeck", deck ); + } } /* -------------------------------------------- */ diff --git a/module/sos-flip-dialog.js b/module/sos-flip-dialog.js index 16a7daf..77ad360 100644 --- a/module/sos-flip-dialog.js +++ b/module/sos-flip-dialog.js @@ -89,19 +89,19 @@ export class SoSFlipDialog extends Dialog { this.updateScoreBase(); } - /* -------------------------------------------- */ - updateConsequenceBonus(event) { - this.flipData.consequencesSelected = $('#consequenceSelectBonus').val(); - let bonusConsequence = 0; - for (let consequenceId of this.flipData.consequencesSelected) { - let consequence = this.flipData.consequencesList.find( item => item._id == consequenceId); - console.log(consequence, consequenceId); - bonusConsequence += SoSUtility.getConsequenceBonus( consequence.data.severity ); - } - $('#consequence-bonus').text(bonusConsequence); - this.flipData.bonusConsequence = bonusConsequence; - this.updateScoreBase(); + /* -------------------------------------------- */ + updateConsequenceBonus(event) { + this.flipData.consequencesSelected = $('#consequenceSelectBonus').val(); + let bonusConsequence = 0; + for (let consequenceId of this.flipData.consequencesSelected) { + let consequence = this.flipData.consequencesList.find( item => item._id == consequenceId); + console.log(consequence, consequenceId); + bonusConsequence += SoSUtility.getConsequenceBonus( consequence.data.severity ); } + $('#consequence-bonus').text(bonusConsequence); + this.flipData.bonusConsequence = bonusConsequence; + this.updateScoreBase(); + } /* -------------------------------------------- */ activateListeners(html) { diff --git a/module/sos-gm-deck.js b/module/sos-gm-deck.js new file mode 100644 index 0000000..8831e87 --- /dev/null +++ b/module/sos-gm-deck.js @@ -0,0 +1,124 @@ +/* -------------------------------------------- */ +import { SoSUtility } from "./sos-utility.js"; +import { SoSCardDeck } from "./sos-card-deck.js"; + +/* -------------------------------------------- */ +export class SoSGMDeck extends Dialog { + + /* -------------------------------------------- */ + constructor(html) { + let conf = { + title: 'GM Deck Dialog', + content: html, + buttons: { + 'flip-close': { label: 'Cancel and Close', callback: html => this.onFlipClose() } + }, + default: 'flip' + }; + super(conf, { classes: ["sosdialog"], width: 640 }); + + let deckData = game.settings.get("foundryvtt-shadows-over-sol", "gmDeck" ); + if ( deckData == undefined || deckData.deck == undefined) { + deckData = {deck:[], discard: [], cardEdge:[] }; + } + + this.name = "GM Deck"; + this.GMdeck = new SoSCardDeck(); + this.GMdeck.initCardDeck( this, deckData ); + } + + /* -------------------------------------------- */ + onFlipClose() { + this.close(); + } + + /* -------------------------------------------- */ + saveDeck( ) { + let deck = { + deck: duplicate(this.GMdeck.data.deck), + discard: duplicate(this.GMdeck.data.discard), + cardEdge: duplicate(this.GMdeck.data.cardEdge) + } + game.settings.set("foundryvtt-shadows-over-sol", "gmDeck", deck ); + } + + /* -------------------------------------------- */ + async updateFlip( deckData) { + $('.view-deck').remove(); + $("#view-gm-deck").append(await this.GMdeck.getDeckHTML()); + + $('.view-edge').remove(); + $("#view-gm-edge").append(await this.GMdeck.getEdgeHTMLForFlip()); + + //this.flipData.GMdeck.drawFromDeck(); + + } + + /* -------------------------------------------- */ + async drawCard() { + let card = this.GMdeck.drawFromDeck(); + let cardPath = `systems/foundryvtt-shadows-over-sol/img/cards/${card.cardName}.webp`; + let cardData = { card: card, cardPath: cardPath }; + let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-card.html', cardData ); + ChatMessage.create( { content: html, whisper: [ ChatMessage.getWhisperRecipients("GM") ] }); + //dialog.onFlipClose(); + } + + /* -------------------------------------------- */ + resetDeckFull( ) { + this.GMdeck.shuffleDeck(); + this.GMdeck.drawEdge( 3 ); + this.saveDeck(); + } + /* -------------------------------------------- */ + drawNewEdge( ) { + this.GMdeck.drawEdge( 1 ); + this.saveDeck(); + } + + /* -------------------------------------------- */ + discardEdge( cardName ) { + this.GMdeck.discardEdge( cardName ); + this.saveDeck(); + } + + /* -------------------------------------------- */ + resetDeck( ) { + this.GMdeck.resetDeck(); + this.saveDeck(); + } + + /* -------------------------------------------- */ + activateListeners(html) { + super.activateListeners(html); + + this.bringToTop(); + + var dialog = this; + + function onLoad() { + dialog.updateFlip(); + } + + // Setup everything onload + $(function () { onLoad(); }); + + html.find('.class-view-deck').click((event) => { + this.drawCard(); + }); + html.find('.reset-deck-full').click((event) => { + this.resetDeckFull(); + this.render(true); + }); + html.find('.draw-new-edge').click((event) => { + this.drawNewEdge(); + this.render(true); + }); + html.find('.reset-deck').click((event) => { + this.resetDeck(); + this.render(true); + }); + + } + +} \ No newline at end of file diff --git a/module/sos-main.js b/module/sos-main.js index 91f77ca..d882870 100644 --- a/module/sos-main.js +++ b/module/sos-main.js @@ -14,6 +14,7 @@ import { SoSActorSheet } from "./actor-sheet.js"; import { SoSUtility } from "./sos-utility.js"; import { SoSCombat } from "./sos-combat.js"; import { gearConverter } from "./gears_convert.js"; +import { SoSGMDeck } from "./sos-gm-deck.js"; /* -------------------------------------------- */ /* Foundry VTT Initialization */ @@ -23,10 +24,24 @@ import { gearConverter } from "./gears_convert.js"; Hooks.once("init", async function () { console.log(`Initializing Shadows Over Sol System`); + /* -------------------------------------------- */ + game.settings.register("foundryvtt-shadows-over-sol", "gmDeck", { + name: "gmDeck", + scope: "world", + config: false, + type: Object + }); + + /* -------------------------------------------- */ // preload handlebars templates SoSUtility.preloadHandlebarsTemplates(); // Create useful storage space - game.system.sos = { } + let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/gm-deck.html', {} ); + let gmDeck = new SoSGMDeck(html); + gmDeck.render(true); + game.system.sos = { + gmDeck: gmDeck, + } /* -------------------------------------------- */ // Set an initiative formula for the system diff --git a/system.json b/system.json index 785e64a..b782801 100644 --- a/system.json +++ b/system.json @@ -2,11 +2,11 @@ "name": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", - "version": "0.1.2", + "version": "0.1.4", "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", - "templateVersion": 17, + "templateVersion": 18, "author": "LeRatierBretonnien", "esmodules": [ "module/sos-main.js" ], "styles": ["styles/simple.css"], diff --git a/template.json b/template.json index f602ce4..81f75b3 100644 --- a/template.json +++ b/template.json @@ -1,6 +1,6 @@ { "Actor": { - "types": ["character", "npc"], + "types": ["character"], "templates": { "subactors": { "subactors": { @@ -133,9 +133,6 @@ }, "character": { "templates": [ "background", "common", "subactors" ] - }, - "npc": { - "templates": [ "background", "common" ] } }, "Item": { diff --git a/templates/chat-card.html b/templates/chat-card.html new file mode 100644 index 0000000..17acdbb --- /dev/null +++ b/templates/chat-card.html @@ -0,0 +1,2 @@ +

GM draws a card from its deck !

+ diff --git a/templates/gm-deck.html b/templates/gm-deck.html new file mode 100644 index 0000000..b904fec --- /dev/null +++ b/templates/gm-deck.html @@ -0,0 +1,21 @@ +
+ +
+
+ +
+ +
+ + +
+
+ +
+
+ +
\ No newline at end of file -- 2.35.3 From a824a826782e269c30b944b61323dd5fbac2597b Mon Sep 17 00:00:00 2001 From: sladecraven Date: Mon, 8 Mar 2021 23:10:03 +0100 Subject: [PATCH 07/47] Manage GM cards --- packs/injuries.db | 53 +++++++++++++++++++++++++++++++++++++++++++++++ system.json | 11 +++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 packs/injuries.db diff --git a/packs/injuries.db b/packs/injuries.db new file mode 100644 index 0000000..e91496a --- /dev/null +++ b/packs/injuries.db @@ -0,0 +1,53 @@ +{"_id":"2ZUnK7mjIeizobUM","name":"Stunning","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"h06","description":"

Stunning: There was something about that attack the character wasn’t expecting, and it's left her stunned and reevaluating the situation. This increases the target's Stun consequence two severities.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"name":"Debilitated","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c09","description":"

Debilitated: Every wound makes it harder to go on, sapping the character’s strength and vigor. This increases the target's Fatigue consequence two severities.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"5mH7KTHX3PTgyf0K"} +{"_id":"6VVhw27n93JauM51","name":"Dazing Strike","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"h04","description":"

Dazing Strike: The sudden attack leaves the character hit and a bit dazed from the pain. This increases the target's Dazed consequence a severity.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"7S0f1aAU3edBJ7qR","name":"Jolt of Pain","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"h02","description":"

Jolt of Pain: The attack sends a jolt of pain throughout the character’s body, stunning her momentarily and leaving her unable to act. This increases the target's Stun consequence a severity.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"name":"Shattered Leg","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c13","description":"

Shattered Leg: The attack shatters the character’s leg, snapping it in several locations and rendering it useless until haled. This prevents her from walking, rending most move actions ineffective Severity: Critical. Duration: Until major surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"84bdeqdlDvtJZ2aS"} +{"_id":"8uHSZ69e0tQcpaOO","name":"Stumble Backward","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s04","description":"

Stumble Backward: The shock of the blast sends the character stumbling backward a couple meters. This increases the target’s Spin consequence a severity.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"Abn2WpLIuQAxF7Ti","name":"Black Joker","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"jb","description":"

Draw two cards and the attacker takes her choice of the two results.

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"BbbI7e52tz31HRaP","name":"Broken Nose","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s09","description":"

Broken Nose: The blow slams into the character’s face, snapping her nose and smearing blood down her front. She takes a -2 penalty to Charisma actions. Severity: Severe. Duration: Until minor surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"name":"Makeshift Phlebotomy","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c10","description":"

Makeshift Phlebotomy: The wound leaves the character losing blood—a lot of it. It's so very red, and there's so very much of it. This increases the target's Bleeding consequence two severities.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"CIK9W5jd6AXVGXt0"} +{"name":"Popped Eye","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c11","description":"

Popped Eye: The attack splatters one of the character’s eyes, which is smeared down her face like some sort of jam. Additionally, the attack does quite a number on the rest of her head as well. This gives a -2 penalty to all mental actions. Severity: CriticalDuration: Until replacement or regrowth therapy.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"CWPlZ4zgvshlp9Oq"} +{"name":"Vital Hit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d05","description":"

Vital Hit: The hit has struck some particularly vital part of the character’s anatomy. Double the damage rating dealt by the attack, just as with the Vital Hit critical effect (see page 130).

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"D8QoB97lR45hwsyJ"} +{"name":"Bloody Face","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d03","description":"

Bloody Face: The force of the blow causes the character’s face to be struck, leaving a bloody smear across her nose and mouth. She takes a -1 penalty to all Charisma actions. Severity: Light. Duration: Until the end of next round.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"D8vIxrcheDOiFHm5"} +{"_id":"DqG35qxxI6AKVm1i","name":"Concussion","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"h12","description":"

Concussion: The attack tears through the character, sending waves and shock and pain throughout her body, as your head reels, trying to cope with the wounds. This increases the target's the Stun (critical) consequence.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"HaOqMkLXCYpSYdEb","name":"Winded","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s01","description":"

Winded: The blow knocks the wind out of the character. She gains 1 fewer AP next round. Severity: Light. Duration: Until the end of the next round.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"name":"Overwhelmed","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c08","description":"

Overwhelmed: The violence around the character and pain in her system overwhelms her mental faculties. This increases the target's Stun consequence three severities.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"HiHGTf5odQfAUHLp"} +{"_id":"IEHRrXwqFZUkKblM","name":"Broken Toes","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"h07","description":"

Broken Toes: The attack blows into the character’s foot, crushing her toes and snapping bones with sickening pops. She has a -1 penalty to Speed actions and halher movement. Severity: Moderate. Duration: Until minor surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"name":"Thunderstruck","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d08","description":"

Thunderstruck: The blow lands on the character’s head, sending her vision spinning and her ears ringing. She takes a -2 penalty to all Perception actions. Severity: Severe. Duration: Until minor surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"IPV3FLsZBcq1rBhl"} +{"_id":"Ii0FLfbiDKwZSeld","name":"Numb Arm","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s02","description":"

Numb Arm: The attack glances off one of the character’s arms, leaving it numb andtingly. Actions made with that arm next round are at a -2 penalty.

\n

Severity: Light.

\n

Duration: Until the end of the next round.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"OdypZ29JC7IHaAPx","name":"Broken Rib","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s08","description":"

Broken Rib: The attack slams into the character’s ribs with a sickening crunching sound. At least one of her ribs snaps, leaving her in nauseating pain. She takes a -2 penalty to all Strength actions. Severity: Severe. Duration: Until minor surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"OjYxHD6HI1bZfWZP","name":"Herniating Entrails","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s10","description":"

Herniating Entrails: The attack tears open the target’s abdomen, allowing her entrails to bulge out. Needless to say, the pain is considerable. She takes a -2 penalty to all Endurance actions. Severity: Severe. Duration: Until minor surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"P6VcDOHmNLigPOCX","name":"Makeshift Lobotomy","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s13","description":"

Makeshift Lobotomy: The attack rips the character’s skull asunder, tearing away gaping chunks of bone and some precious brain-meats. At least one of her eyes is dangling by a thread from the bleeding mass of flesh that was once her face. This gives it a -4 penalty on all social actions, as well as a -4 penalty on all sensory actions. Short of major surgery, your face will forever be a monstrous ruin. Severity: Critical. Duration: Until major surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"PQE5atcEtpueRmzb","name":"Red Joker","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"jr","description":"

Draw two cards and the attacker takes her choice of the two results.

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"name":"Snapped Arm","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c12","description":"

Snapped Arm: The attack snaps the character’s arm like a twig and now it hangs lifeless at her side. No actions can be performed with the arm until it heals, and all two-handed actions are at -4. Severity: Critical. Duration: Until major surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"QrPOPbJqgYHHFZgw"} +{"_id":"RTkY0Yfi90gv5HEz","name":"Momentarily Blinded","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s03","description":"

Momentarily Blinded: Light from the attack or a blow to the head leaves the character blinded next round. Severity: Light. Duration: Until the end of the next round.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"RqL6LsglGIXb2O4Z","name":"Split Skull","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"h09","description":"

Split Skull: The blow cracks the character’s skull, causing bleeding, swelling and a terrible headache. She takes a -2 penalty to all Intelligence actions. Severity: Severe. Duration: Until minor surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"SqUQ118myvq0Zg8I","name":"Distraction","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d06","description":"

Distraction: The pain of attack causes the character to lose focus. Any wait reaction she has active is immediately lost.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"T7uVvIfrXmQKcuNh","name":"Exhausted","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s07","description":"

Exhausted: The attack has left the character pained and exhausted, unable to carry on with the vigor she was able to muster before. This increases the target’s Fatigue consequence a severity.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"V6gYpmP6IOPer9FL","name":"Wobbly Leg","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"h01","description":"

Wobbly Leg: The attack glances off one of the character’s knees, leaving the leg wobbly and numb. Actions made with that leg next round are at a -2 penalty, and the distance of movement is halved. Severity: Light. Duration: Until the end of the next round.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"name":"Lost Opportunity","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c07","description":"

Lost Opportunity: The pain hinders the character’s ability to perform. If she has an unspent AP, she immediately loses one. Otherwise, if the player has an action declared, she must cancel one of her choice.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"VcHrC9a3qkdclPP5"} +{"name":"Crushed Hand","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d12","description":"

Crushed Hand: The attack crushes the character’s hand, twisting it in ways it was not meant to bend. Bones are broken and it's left a bloody mess. She cannot use that hand until it is healed. Severity: Critical. Duration: Until major surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"WFwAbxcjOBQ7WoTI"} +{"_id":"ZW02wolEOyn0njV6","name":"Mortal Wound","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"h13","description":"

Mortal Wound: The attack ripped through the character’s guts, rending vital organs and major arteries into useless bloody giblets. While the target is not dead yet, saving her is beyond the ability of modern medicine. Starting next round and every round thereafter, the character should, draw a card at the end of her turn. If it's a joker, she has finally bled out. Severity: Critical. Duration: Until death.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"ZxP1X4AuiPqtTMtm","name":"One-armed","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s11","description":"

One-armed: The blow tears away the target’s arm like pulled pork from the bone, leaving the limb twisted, ruined and several meters away. You will never enjoy your natural arm again—at least not in a functional state. Severity: Critical. Duration: Until arm replacement or regrowth treatment.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"a4qOgh3iX927mMK7","name":"One-legged","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s12","description":"

One-legged: The attack literally twists the character’s leg away from her body, cracking bone and ripping sinew. She falls down, her ruined leg trapped beneath her. She will never walk on it again, although with major surgery she may still gain a new one. Severity: Critical. Duration: Until leg replacement or regrowth treatment.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"name":"Seeing Stars","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c03","description":"

Seeing Stars: The force of the attack whips your head backward, leaving your senses reeling. She takes a -1 penalty to all Perception actions. Severity: Light. Duration: Until the end of the next round.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"an1J1HgdsgBuPbAw"} +{"_id":"bsUsBhTW2y5u2XIh","name":"Bloody Gash","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s05","description":"

Bloody Gash: The attack has opened up a bloody gash in the character’s body, ripping away skin and exposing the flesh underneath. It bleeds profusely. This increases the target’s Bleeding consequence a severity.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"cKwsGa5rthCdQ1Du","name":"Face Down","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"h05","description":"

Face Down: The force of the blow sends the character reeling, slamming her face- first into the ground. This increases the target's Spin consequence two severities.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"_id":"dLYH7jy1dPLfSX7R","name":"Twisted Back","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"h08","description":"

Twisted Back: The character twists with the blow, spraining her back with a worrying crunching sound as the attack rips into her. She takes a -2 penalty to all Dexterity actions. Severity: Severe. Duration: Until minor surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"name":"Guard Down","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c04","description":"

Guard Down: The will to survive momentarily saps the character’s willpower in other areas. She takes a -1 penalty to all Determination actions. Severity: Light. Duration: Until the end of the next round.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"fCf5wSpI5fBHXyXN"} +{"_id":"gCw6BIXbK8xVqmfQ","name":"Trauma Response","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"h11","description":"

Trauma Response: The character’s mental response to the attack leaves her with the sense that she is trapped in a dream. This increases the target's Dazed (critical) consequence.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"name":"Broken Fingers","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d10","description":"

Broken Fingers: The attack squarely strikes the character’s hand and she feels one or more of her fingers break. She drops anything she is holding in that hand, and her mangled fingers are at unnatural angles. She has a -2 penalty on actions involving that hand. Severity: Severe. Duration: Until minor surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"gLs37vyBY6S2trc3"} +{"_id":"hKfZuQAAwjZMupsp","name":"Broken Foot","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"h10","description":"

Broken Foot: The blow crumples the character’s foot like wet paper, leaving it a broken lump. She has a -2 penalty to Speed actions and half her movement. Severity: Severe. Duration: Until major surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"name":"Shell-shocked","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d09","description":"

Shell-shocked: The attack connects with the character’s head, leaving her in a vulner- able state of shock. She takes a -2 penalty to all Determination actions. Severity: Severe. Duration: Until minor surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"kgesIoCPuKEeMfgG"} +{"name":"Headache","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d02","description":"

Headache: Blood loss, exhaustion or damage to the character’s nerves leaves her with a momentary splitting headache. She takes a -1 penalty to all Intelligence actions. Severity: Light. Duration: Until the end of next round.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"khJcBCEYADTrnC6e"} +{"name":"Gushing Blood","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d11","description":"

Gushing Blood: The character’s body is ripped asunder as her bodily fluids pour out like a wave. This increases the target's Bleeding consequence three severities.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"m50Lq8OmBCHWZhQS"} +{"_id":"n2FgyVDQsbGNHAdJ","name":"Concussive Blow","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"s06","description":"

Concussive Blow: The blow just glances off the target’s head, cutting a nasty wound and leaving her dazed. This increases the target’s Dazed consequence two severities.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[]} +{"name":"Sluggish","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c02","description":"

Sluggish: The shock of the attack ripples throughout the character’s nervous system, momentarily affecting her reaction time. She takes a -1 penalty to all Speed actions. Severity: Light. Duration: Until the end of next round.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"o6NuCCSMIJd8QCM2"} +{"name":"Shock","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d04","description":"

Shock: Dealing with bodily injury has left her system in a state of shock. She takes a -1 penalty to all Endurance actions. Severity: Light. Duration: Until the end of next round.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"pqmZYfJODCgNr7CS"} +{"name":"Disarmed","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c05","description":"

Disarmed: The attack hits the arm holding the weapon, causing the character to drop it, just as with the Disarm critical effect (see pages 128 and 130).

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"r5zVdlYvxMUGea0o"} +{"name":"Spasm","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c01","description":"

Spasm: The pain of the target’s wounds sends spasms throughout her body. She takes a -1 penalty to all Dexterity actions. Severity: Light. Duration: Until the end of the next round.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"sGSH8XGyEWWPcckI"} +{"name":"Faint","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d01","description":"

Faint: There is a wave of pain and nausea from the wound, leaving the character feeling faint. She takes a -1 penalty to all Strength actions. Severity: Light. Duration: Until the end of next round.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"uN1czNhbnrhlCOCH"} +{"name":"Accidental Discharge","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"c06","description":"

Accidental Discharge: The blow forces the player character’s hand to twitch and causes her weapon to discharge. If it's a melee weapon, the player draws a card and deals herself damage based on its suit. If it's a ranged weapon, it hits the nearest ally.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"vXg3iDo3hja73DKu"} +{"name":"Secondary Wound","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d07","description":"

Secondary Wound: The attack lands upon the character’s body twice, leaving a secondary wound in her flesh. The target gains a Wound (light) consequence in addition to the normal wound.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"ww8AV6bbWy8VHXGI"} +{"name":"Spinal Break","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"injury","data":{"card":"d13","description":"

Spinal Break: The character’s spine cracks and slightly fractures, causing her to fall prone. She may not stand up or take move actions until the injury heals. Severity: Critical. Duration: Until major surgery to fix.

\n

 

"},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/injury_generic.svg","effects":[],"_id":"xZL7aO0xOOZvB2cs"} diff --git a/system.json b/system.json index b782801..8e676af 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "name": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", - "version": "0.1.4", + "version": "0.1.5", "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", @@ -40,6 +40,15 @@ "path": "./packs/gears.db", "entity": "Item", "tags" : [ "gear", "weapon", "armor" ] + }, + { + "name": "injuries", + "label": "Injuries", + "system": "foundryvtt-shadows-over-sol", + "module": "foundryvtt-shadows-over-sol", + "path": "./packs/injuries.db", + "entity": "Item", + "tags" : [ "injury" ] }, { "name": "combat-actions", -- 2.35.3 From d7131d467589b71a0c44ce83f2db141b1d76fe2e Mon Sep 17 00:00:00 2001 From: sladecraven Date: Mon, 8 Mar 2021 23:26:56 +0100 Subject: [PATCH 08/47] Manage GM cards --- module/sos-gm-deck.js | 2 +- module/sos-main.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/module/sos-gm-deck.js b/module/sos-gm-deck.js index 8831e87..323323b 100644 --- a/module/sos-gm-deck.js +++ b/module/sos-gm-deck.js @@ -11,7 +11,7 @@ export class SoSGMDeck extends Dialog { title: 'GM Deck Dialog', content: html, buttons: { - 'flip-close': { label: 'Cancel and Close', callback: html => this.onFlipClose() } + 'flip-close': { label: 'Close', callback: html => this.onFlipClose() } }, default: 'flip' }; diff --git a/module/sos-main.js b/module/sos-main.js index d882870..bea3a48 100644 --- a/module/sos-main.js +++ b/module/sos-main.js @@ -38,7 +38,7 @@ Hooks.once("init", async function () { // Create useful storage space let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/gm-deck.html', {} ); let gmDeck = new SoSGMDeck(html); - gmDeck.render(true); + //gmDeck.render(true); game.system.sos = { gmDeck: gmDeck, } @@ -117,13 +117,16 @@ Hooks.on("chatMessage", (html, content, msg) => { if (content[0] == '/') { let regExp = /(\S+)/g; let commands = content.toLowerCase().match(regExp); - if (game.system.sos.commands.processChatCommand(commands, content, msg)) { + console.log(commands); + if ( commands[0] == '/gmdeck') { + game.system.sos.gmDeck.render(true); return false; } } return true; }); + /* -------------------------------------------- */ Hooks.on("getCombatTrackerEntryContext", (html, options) => { //SoS.pushInitiativeOptions(html, options); -- 2.35.3 From 56eb2aeef1d8273e0cbfbd0c05dedc03ea5023da Mon Sep 17 00:00:00 2001 From: sladecraven Date: Mon, 8 Mar 2021 23:42:38 +0100 Subject: [PATCH 09/47] Manage GM cards --- module/sos-gm-deck.js | 2 +- module/sos-main.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/module/sos-gm-deck.js b/module/sos-gm-deck.js index 323323b..5320885 100644 --- a/module/sos-gm-deck.js +++ b/module/sos-gm-deck.js @@ -29,7 +29,7 @@ export class SoSGMDeck extends Dialog { /* -------------------------------------------- */ onFlipClose() { - this.close(); + this.minimize(); } /* -------------------------------------------- */ diff --git a/module/sos-main.js b/module/sos-main.js index bea3a48..35fd287 100644 --- a/module/sos-main.js +++ b/module/sos-main.js @@ -38,7 +38,6 @@ Hooks.once("init", async function () { // Create useful storage space let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/gm-deck.html', {} ); let gmDeck = new SoSGMDeck(html); - //gmDeck.render(true); game.system.sos = { gmDeck: gmDeck, } @@ -119,7 +118,7 @@ Hooks.on("chatMessage", (html, content, msg) => { let commands = content.toLowerCase().match(regExp); console.log(commands); if ( commands[0] == '/gmdeck') { - game.system.sos.gmDeck.render(true); + game.system.sos.gmDeck.render( true ); return false; } } -- 2.35.3 From 5795c42808944cf4b33e3089381d8304e00b5602 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Fri, 12 Mar 2021 15:03:35 +0100 Subject: [PATCH 10/47] #5 Languages/Subcultures management --- module/actor-sheet.js | 10 ++++--- styles/simple.css | 3 +- templates/actor-sheet.html | 48 ++++++++++++++++++++++++++++-- templates/item-language-sheet.html | 22 ++++++++++++++ 4 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 templates/item-language-sheet.html diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 2ad579b..0f75153 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -47,12 +47,14 @@ export class SoSActorSheet extends ActorSheet { data.data.currentWounds = this.actor.computeCurrentWounds(); data.data.totalWounds = this.actor.data.data.scores.wound.value; - data.data.subculture = this.actor.data.items.find( item => item.type == 'subculture'); - data.data.geneline = this.actor.data.items.find( item => item.type == 'geneline'); + data.data.subcultureList = this.actor.data.items.filter( item => item.type == 'subculture'); + if ( data.data.subculture != "" ) { // background.subculture contains the main subculture ID + data.data.mainSubculture = data.data.subcultureList.find( subc => subc._id == data.data.subculture); + } + data.data.languageList = this.actor.data.items.filter( item => item.type == 'language'); + data.data.geneline = this.actor.data.items.find( item => item.type == 'geneline'); data.data.editStatSkill = this.options.editStatSkill; console.log("stats", data); - //data.stats = duplicate(this.actor.stats); - //data.scores = duplicate(this.actor.scores); return data; } diff --git a/styles/simple.css b/styles/simple.css index ca51d61..c619063 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -618,6 +618,7 @@ ul, li { flex-grow: 0; margin-right: 0.25rem; } +.genelang-column, .skill-column { flex-direction: column; align-content: flex-start; @@ -631,7 +632,7 @@ ul, li { font-weight: bold; flex-grow: 0; } - +.genelang-label, .skill-label, .conseq-label, .generic-label { diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 1905dd5..a583569 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -274,8 +274,14 @@
  • - - + +
  • @@ -305,6 +311,44 @@
  • +
    +
    +
    + +
    + Familiar Subcultures +
      + {{#each data.subcultureList as |subculture key|}} +
    • + + {{subculture.name}} +
      + + +
      +
    • + {{/each}} +
    +
    +
    + Known Languages +
      + {{#each data.languageList as |language key|}} +
    • + + {{language.name}} +
      + + +
      +
    • + {{/each}} +
    +
    +
    +
    + +

    diff --git a/templates/item-language-sheet.html b/templates/item-language-sheet.html new file mode 100644 index 0000000..2049b1e --- /dev/null +++ b/templates/item-language-sheet.html @@ -0,0 +1,22 @@ +
    +
    + +
    +

    +
    +
    + + {{!-- Sheet Body --}} +
    + +
    +
    + +
    + {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} +
    +
    +
    + +
    +
    -- 2.35.3 From 96991516b6eb237138ad5f0a2996faf6b998f19e Mon Sep 17 00:00:00 2001 From: sladecraven Date: Fri, 12 Mar 2021 15:43:53 +0100 Subject: [PATCH 11/47] #2 add Naturaist skill --- img/icons/.directory | 4 +--- img/icons/forest-camp.svg | 1 + img/icons/language_generic.svg | 1 + module/actor-sheet.js | 1 + packs/languages.db | 15 +++++++++++++++ packs/skills.db | 1 + system.json | 11 ++++++++++- 7 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 img/icons/forest-camp.svg create mode 100644 img/icons/language_generic.svg create mode 100644 packs/languages.db diff --git a/img/icons/.directory b/img/icons/.directory index de7028d..8a192c3 100644 --- a/img/icons/.directory +++ b/img/icons/.directory @@ -1,7 +1,5 @@ [Dolphin] -SortOrder=1 -SortRole=modificationtime -Timestamp=2021,1,19,23,13,52 +Timestamp=2021,3,12,15,41,28.086 Version=4 ViewMode=1 VisibleRoles=Details_text,Details_size,Details_modificationtime,Details_creationtime,CustomizedDetails diff --git a/img/icons/forest-camp.svg b/img/icons/forest-camp.svg new file mode 100644 index 0000000..8aba9e3 --- /dev/null +++ b/img/icons/forest-camp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/icons/language_generic.svg b/img/icons/language_generic.svg new file mode 100644 index 0000000..a5d1661 --- /dev/null +++ b/img/icons/language_generic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 0f75153..826c689 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -52,6 +52,7 @@ export class SoSActorSheet extends ActorSheet { data.data.mainSubculture = data.data.subcultureList.find( subc => subc._id == data.data.subculture); } data.data.languageList = this.actor.data.items.filter( item => item.type == 'language'); + data.data.weaknessList = this.actor.data.items.filter( item => item.type == 'weakness'); data.data.geneline = this.actor.data.items.find( item => item.type == 'geneline'); data.data.editStatSkill = this.options.editStatSkill; console.log("stats", data); diff --git a/packs/languages.db b/packs/languages.db new file mode 100644 index 0000000..9103e04 --- /dev/null +++ b/packs/languages.db @@ -0,0 +1,15 @@ +{"name":"Punjabi","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"0OaXJm1iih3gYI6P"} +{"name":"Hindi","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"6SrEUZyVWEotG1r5"} +{"name":"Javanese","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"IqOylpRQpYFh6LNO"} +{"name":"Bengali","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"JfRw5mPVhHxRoImL"} +{"name":"Portuguese","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"PBIkRjiWvjZga5Sh"} +{"name":"Malay","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"Twrh1paNKmVYfwiX"} +{"name":"Spanish","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"VIDgP7Tac11z11Ue"} +{"name":"English","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"Z8r1Lr6tZpI1UFZf"} +{"name":"Mandarin","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"bsUeqWPcT8KO4oEg"} +{"name":"Wu","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"empozpJ5aDBOVQo8"} +{"name":"Arabic","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"fpaTetKF4Y1UgBKg"} +{"name":"Japanese","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":"

    French language

    "},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"fzJ505qsIwl3CIFZ"} +{"name":"French","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":"

    French language

    "},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"mp47bUSdiBX7GgBQ"} +{"name":"German","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"weG6nxdHeH4efiSh"} +{"name":"Russian","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"language","data":{"description":null},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/language_generic.svg","effects":[],"_id":"xbpEhhdqx4o5KUJA"} diff --git a/packs/skills.db b/packs/skills.db index 0ed3859..0a5800d 100644 --- a/packs/skills.db +++ b/packs/skills.db @@ -14,6 +14,7 @@ {"name":"Conspiracy","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"skill","data":{"value":0,"xp":0,"description":"

    Conspiracy is the skill of knowing information others want suppressed or at least knowing where to look to find such information. It also includes the ability to sift through the resulting conspiracy theories, separating the dross from the kernels of truth. Conspiracy is the skill of finding things that don’t want to be found.

    \n

     

    "},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/conspiracy.svg","effects":[],"_id":"XCoRrznhqaUHiiPI"} {"name":"Melee","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"skill","data":{"value":0,"xp":0,"description":"

    Melee is the skill used for hand-to-hand combat, street fighting, wrestling, fencing, boxing and any other activity mimicking close combat. Despite the prevalence of guns and other advanced weaponry, simple fistfights remain the most common type of violence in the solar system.

    \n

     

    "},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/melee.svg","effects":[],"_id":"XqmSwOdflpM8ocfz"} {"name":"Medic","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"skill","data":{"value":0,"xp":0,"description":"

    This is the skill of applied medical knowledge. It’s used to treat injuries and other medical conditions, take practical diagnoses, treat poisons, perform surgery, apply first aid and dress wounds. It does not cover the academic or research aspects of biological knowledge; for those, use Bio-Sci.

    \n

     

    "},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/medic.svg","effects":[],"_id":"Yx5D41bOiWdSYqJg"} +{"name":"Naturalist","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"skill","data":{"value":0,"xp":0,"description":"

    The naturalist skill covers the ability to survive outside the bounds of civilization as well as the applied knowledge of the local flora and fauna. It covers working with and training animals as well as the practical knowledge of both what’s edible and what’s dangerous. It covers tracking and reading animal signs and makeshift ways to gauge atmospheric pressure, composition and radiation. It covers foraging for food, firewood or other basic natural resources. The Naturalist skill also includes skill in riding an animal or using an animal as manual labor.

    \n

     

    "},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/naturalist.svg","effects":[],"_id":"aT8X7QFkXD0Oiwdd"} {"name":"Persuade","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"skill","data":{"value":0,"xp":0,"description":"

    The persuade skill covers a variety of tactics to get other people to see things your way or to otherwise comply with your requests. It covers sweet-talking, formal diplomacy, browbeating, fast-talking and intimidation. It covers knowing useful techniques in argument, as well as knowing the right social approach to use— from solid reasoning to subtle psychological tricks to seem more commanding. It does not include haggling and deal-making, nor does it include seduction and putting people at ease; for those, use Broker or Socialize, respectively.

    \n

     

    "},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/persuade.svg","effects":[],"_id":"b43edlbX4VprPk5p"} {"name":"Mechanic","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"skill","data":{"value":0,"xp":0,"description":"

    Mechanic is an applied skill covering the upkeep, repair and assembly of pretty much any mechanical system. Use it for repairing vehicular damage after a battle, maintenance to a ship’s systems or assembling a new piece of cyberware. It does not include designing, repurposing or giving new functionality to mechanical systems; for those, use engineer.

    \n

     

    "},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/mechanic.svg","effects":[],"_id":"dJ7ZdimLGygBcC0M"} {"name":"Deception","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"skill","data":{"value":0,"xp":0,"description":"

    The deception skill includes telling convincing lies, giving off inaccurate body language, pulling the wool over the eyes of others and disguising oneself as someone else. Additionally, deception is useful in gambling, acting and other activities that require making oneself difficult to read or which involve deceiving others.

    \n

     

    "},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/deception.svg","effects":[],"_id":"fBA0UG5lh8jlTbih"} diff --git a/system.json b/system.json index 8e676af..141d826 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "name": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", - "version": "0.1.5", + "version": "0.1.6", "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", @@ -49,6 +49,15 @@ "path": "./packs/injuries.db", "entity": "Item", "tags" : [ "injury" ] + }, + { + "name": "languages", + "label": "Languages", + "system": "foundryvtt-shadows-over-sol", + "module": "foundryvtt-shadows-over-sol", + "path": "./packs/languages.db", + "entity": "Item", + "tags" : [ "language" ] }, { "name": "combat-actions", -- 2.35.3 From 87ca3febd354abc0e30f28ec6ba857a6f602b86f Mon Sep 17 00:00:00 2001 From: sladecraven Date: Fri, 12 Mar 2021 17:12:14 +0100 Subject: [PATCH 12/47] #4 : Weakness management, including bonus/malus field for scores and reminder in the flip dialog --- img/icons/weakness_generic1.svg | 1 + ...{forest-camp.svg => weakness_generic2.svg} | 0 lang/en.json | 1 + module/actor-sheet.js | 2 + module/actor.js | 38 ++++++++++++------- packs/weaknesses.db | 4 ++ system.json | 13 ++++++- template.json | 27 ++++++++----- templates/actor-sheet.html | 34 ++++++++++++++--- templates/dialog-flip.html | 7 ++++ templates/item-weakness-sheet.html | 35 +++++++++++++++++ 11 files changed, 132 insertions(+), 30 deletions(-) create mode 100644 img/icons/weakness_generic1.svg rename img/icons/{forest-camp.svg => weakness_generic2.svg} (100%) create mode 100644 packs/weaknesses.db create mode 100644 templates/item-weakness-sheet.html diff --git a/img/icons/weakness_generic1.svg b/img/icons/weakness_generic1.svg new file mode 100644 index 0000000..601f08e --- /dev/null +++ b/img/icons/weakness_generic1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/icons/forest-camp.svg b/img/icons/weakness_generic2.svg similarity index 100% rename from img/icons/forest-camp.svg rename to img/icons/weakness_generic2.svg diff --git a/lang/en.json b/lang/en.json index 969232c..2cf8490 100644 --- a/lang/en.json +++ b/lang/en.json @@ -13,6 +13,7 @@ "SCORES.Currentwounds": "Current Wounds", "SCORES.Shock": "Shock", "SCORES.Wounds": "Wounds", + "SCORES.Totalwounds": "Max. Wounds", "SCORES.Encumbrance": "Encumbrance", "STATS.physical": "physical", diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 826c689..ff1819e 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -25,6 +25,8 @@ export class SoSActorSheet extends ActorSheet { getData() { let data = super.getData(); + this.actor.checkDeck(); + data.data.edgecard = this.actor.getEdgesCard(); data.data.deckSize = this.actor.getDeckSize(); diff --git a/module/actor.js b/module/actor.js index 1623188..35e98d5 100644 --- a/module/actor.js +++ b/module/actor.js @@ -53,17 +53,22 @@ export class SoSActor extends Actor { async prepareData() { super.prepareData(); - if ( !this.cardDeck ) { - if ( this.hasPlayerOwner) { - this.cardDeck = new SoSCardDeck(); - this.cardDeck.initCardDeck( this, this.data.data.internals.deck ); - } else { - this.cardDeck = game.system.sos.gmDeck; - } - } + this.checkDeck(); this.controlScores(); } + /* -------------------------------------------- */ + checkDeck() { + if ( !this.cardDeck && this.hasPlayerOwner ) { + this.cardDeck = new SoSCardDeck(); + this.cardDeck.initCardDeck( this, this.data.data.internals.deck ); + } + if ( !this.hasPlayerOwner ) { + this.cardDeck = game.system.sos.gmDeck.GMdeck; + console.log("DECK : ", this.cardDeck); + } + } + /* -------------------------------------------- */ getDeckSize() { return this.cardDeck.getDeckSize(); @@ -120,8 +125,8 @@ export class SoSActor extends Actor { } /* -------------------------------------------- */ computeDefense() { - return { value: Math.ceil((this.data.data.stats.speed.value + this.data.data.stats.perception.value + this.data.data.stats.dexterity.value) / 2), - critical: this.data.data.stats.speed.value + this.data.data.stats.perception.value + this.data.data.stats.dexterity.value + return { value: Math.ceil((this.data.data.stats.speed.value + this.data.data.stats.perception.value + this.data.data.stats.dexterity.value) / 2) + this.data.data.scores.defense.bonusmalus, + critical: this.data.data.stats.speed.value + this.data.data.stats.perception.value + this.data.data.stats.dexterity.value + this.data.data.scores.defense.bonusmalus } } /* -------------------------------------------- */ @@ -132,23 +137,27 @@ export class SoSActor extends Actor { getEncumbrance( ) { return this.data.data.scores.encumbrance.value; } + computeEncumbrance( ) { + return this.data.data.stats.strength.value + this.data.data.scores.encumbrance.bonusmalus; + } + /* -------------------------------------------- */ computeEdge( ) { - return Math.ceil( (this.data.data.stats.intelligence.value + this.data.data.stats.charisma.value) / 2) + this.data.data.scores.edge.bonus; + return Math.ceil( (this.data.data.stats.intelligence.value + this.data.data.stats.charisma.value) / 2) + this.data.data.scores.edge.bonusmalus; } /* -------------------------------------------- */ getShock( ) { return this.data.data.scores.shock.value; } computeShock() { - return Math.ceil( this.data.data.stats.endurance.value + this.data.data.stats.determination.value + this.data.data.scores.dr.value); + return Math.ceil( this.data.data.stats.endurance.value + this.data.data.stats.determination.value + this.data.data.scores.dr.value) + this.data.data.scores.shock.bonusmalus; } /* -------------------------------------------- */ getWound( ) { return this.data.data.scores.wound.value; } computeWound() { - return Math.ceil( (this.data.data.stats.strength.value + this.data.data.stats.endurance.value) / 2); + return Math.ceil( (this.data.data.stats.strength.value + this.data.data.stats.endurance.value) / 2) + this.data.data.scores.wounds.bonusmalus; } /* -------------------------------------------- */ @@ -183,7 +192,7 @@ export class SoSActor extends Actor { } // Encumbrance if ( this.getEncumbrance() != this.data.data.stats.strength.value ) { - await this.update( {'data.scores.encumbrance.value': this.data.data.stats.strength.value }); + await this.update( {'data.scores.encumbrance.value': this.computeEncumbrance() }); } // Shock if ( this.getShock() != this.computeShock() ) { @@ -235,6 +244,7 @@ export class SoSActor extends Actor { modifierList: SoSUtility.fillRange(-10, +10), tnList: SoSUtility.fillRange(6, 20), consequencesList: duplicate( this.getApplicableConsequences() ), + weaknessList: this.data.items.filter( item => item.type == 'weakness' ), wounds: duplicate( this.data.data.wounds), malusConsequence: 0, bonusConsequence: 0, diff --git a/packs/weaknesses.db b/packs/weaknesses.db new file mode 100644 index 0000000..d74a9e5 --- /dev/null +++ b/packs/weaknesses.db @@ -0,0 +1,4 @@ +{"name":"Complication (Wanted)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weakness","data":{"subtitle":"","category":"complication","description":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weakness_generic1.svg","effects":[],"_id":"FxCIbJm3T44kC0sG"} +{"name":"Impairment (Limp)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weakness","data":{"subtitle":"","category":"impairment","description":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weakness_generic1.svg","effects":[],"_id":"HxPweZ03At9tw6GH"} +{"name":"Shortcoming (Low Pain Treshold)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weakness","data":{"subtitle":"","category":"shortcoming","description":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weakness_generic1.svg","effects":[],"_id":"UEHEoNKHUe2hJryO"} +{"name":"Disability (Blind)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weakness","data":{"subtitle":"","category":"disability","description":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weakness_generic1.svg","effects":[],"_id":"VDYXsT8AZ6krv93p"} diff --git a/system.json b/system.json index 141d826..72f3527 100644 --- a/system.json +++ b/system.json @@ -2,11 +2,11 @@ "name": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", - "version": "0.1.6", + "version": "0.1.11", "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", - "templateVersion": 18, + "templateVersion": 22, "author": "LeRatierBretonnien", "esmodules": [ "module/sos-main.js" ], "styles": ["styles/simple.css"], @@ -49,6 +49,15 @@ "path": "./packs/injuries.db", "entity": "Item", "tags" : [ "injury" ] + }, + { + "name": "weaknesses", + "label": "Weaknesses", + "system": "foundryvtt-shadows-over-sol", + "module": "foundryvtt-shadows-over-sol", + "path": "./packs/weaknesses.db", + "entity": "Item", + "tags" : [ "weakness" ] }, { "name": "languages", diff --git a/template.json b/template.json index 81f75b3..1d46f73 100644 --- a/template.json +++ b/template.json @@ -81,40 +81,48 @@ "edge": { "label": "SCORES.Edge", "value": 0, - "bonus": 0 + "bonusmalus": 0 }, "wealth": { "label": "SCORES.Wealth", - "value": 0 + "value": 0, + "bonusmalus": 0 }, "lifestyle": { "label": "SCORES.Lifestyle", - "value": 0 + "value": 0, + "bonusmalus": 0 }, "defense": { "label": "SCORES.Defense", "value": 0, - "critical": 0 + "critical": 0, + "bonusmalus": 0 }, "dr": { "label": "SCORES.DR", - "value": 0 + "value": 0, + "bonusmalus": 0 }, "shock": { "label": "SCORES.Shock", - "value": 0 + "value": 0, + "bonusmalus": 0 }, "currentwounds": { "label": "SCORES.Currentwounds", - "value": 0 + "value": 0, + "bonusmalus": 0 }, "wound": { "label": "SCORES.Wounds", - "value": 0 + "value": 0, + "bonusmalus": 0 }, "encumbrance": { "label": "SCORES.Encumbrance", - "value": 0 + "value": 0, + "bonusmalus": 0 } } }, @@ -165,6 +173,7 @@ }, "weakness": { "subtitle": "", + "category": "", "description": "" }, "geneline": { diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index a583569..6708958 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -31,7 +31,13 @@ src="systems/foundryvtt-shadows-over-sol/img/icons/{{#if data.editStatSkill}}unlocked.svg{{else}}locked.svg{{/if}}" alt="lock/unlock" >{{#if data.editStatSkill}}Lock{{else}}Unlock{{/if}}
      - {{#each data.stats as |stat key|}} +
    • + Stat name + Value + XP +
    • + + {{#each data.stats as |stat key|}} {{#if stat.isLevelUp}}
    • @@ -55,6 +61,11 @@
        +
      • + Score name + Value + Bonus/Malus +
      • {{#each data.scores as |score key|}}
      • {{localize score.label}} @@ -62,9 +73,7 @@ {{#if (eq key 'defense')}} {{/if}} - {{#if (eq key 'edge')}} - - {{/if}} +
      • {{/each}}
      @@ -313,7 +322,7 @@

    -
    +
    Familiar Subcultures @@ -345,6 +354,21 @@ {{/each}}
    +
    + Weaknesses +
      + {{#each data.weaknessList as |weakness key|}} +
    • + + {{weakness.name}} +
      + + +
      +
    • + {{/each}} +
    +
    diff --git a/templates/dialog-flip.html b/templates/dialog-flip.html index 2141a11..f430505 100644 --- a/templates/dialog-flip.html +++ b/templates/dialog-flip.html @@ -51,6 +51,13 @@

    Consequences Bonus : 0

    +
    +
    + {{#each weaknessList as |weakness key|}} + {{localize weakness.name}} - {{weakness.data.category}} + {{/each}} +
    +
    {{#if (gt wounds.light 0)}} diff --git a/templates/item-weakness-sheet.html b/templates/item-weakness-sheet.html new file mode 100644 index 0000000..f555679 --- /dev/null +++ b/templates/item-weakness-sheet.html @@ -0,0 +1,35 @@ +
    +
    + +
    +

    +
    +
    + + {{!-- Sheet Body --}} +
    + +
    +
    + +
    + +
    +
    +
    + +
    + {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} +
    +
    +
    + +
    +
    -- 2.35.3 From 3285bd416eeeb0b8ebabad13e80f4306321df715 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Fri, 12 Mar 2021 17:41:13 +0100 Subject: [PATCH 13/47] SYnc --- img/icons/weapons/baton.svg | 1 + img/icons/weapons/bowie-knife.svg | 1 + img/icons/weapons/grenade.svg | 1 + img/icons/weapons/plasma-cutter.svg | 1 + img/icons/weapons/power-tool.svg | 1 + img/icons/weapons/unarmed.svg | 1 + img/icons/weapons/whiplash.svg | 1 + module/actor-sheet.js | 4 +-- module/actor.js | 2 +- packs/gears.db | 48 +++++++++++++---------------- system.json | 2 +- 11 files changed, 33 insertions(+), 30 deletions(-) create mode 100644 img/icons/weapons/baton.svg create mode 100644 img/icons/weapons/bowie-knife.svg create mode 100644 img/icons/weapons/grenade.svg create mode 100644 img/icons/weapons/plasma-cutter.svg create mode 100644 img/icons/weapons/power-tool.svg create mode 100644 img/icons/weapons/unarmed.svg create mode 100644 img/icons/weapons/whiplash.svg diff --git a/img/icons/weapons/baton.svg b/img/icons/weapons/baton.svg new file mode 100644 index 0000000..006f3a9 --- /dev/null +++ b/img/icons/weapons/baton.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/icons/weapons/bowie-knife.svg b/img/icons/weapons/bowie-knife.svg new file mode 100644 index 0000000..1d4d7af --- /dev/null +++ b/img/icons/weapons/bowie-knife.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/icons/weapons/grenade.svg b/img/icons/weapons/grenade.svg new file mode 100644 index 0000000..026c06c --- /dev/null +++ b/img/icons/weapons/grenade.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/icons/weapons/plasma-cutter.svg b/img/icons/weapons/plasma-cutter.svg new file mode 100644 index 0000000..8bdf698 --- /dev/null +++ b/img/icons/weapons/plasma-cutter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/icons/weapons/power-tool.svg b/img/icons/weapons/power-tool.svg new file mode 100644 index 0000000..4466467 --- /dev/null +++ b/img/icons/weapons/power-tool.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/icons/weapons/unarmed.svg b/img/icons/weapons/unarmed.svg new file mode 100644 index 0000000..9e662b8 --- /dev/null +++ b/img/icons/weapons/unarmed.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/icons/weapons/whiplash.svg b/img/icons/weapons/whiplash.svg new file mode 100644 index 0000000..4e05450 --- /dev/null +++ b/img/icons/weapons/whiplash.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/module/actor-sheet.js b/module/actor-sheet.js index ff1819e..18e1bc8 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -26,7 +26,7 @@ export class SoSActorSheet extends ActorSheet { let data = super.getData(); this.actor.checkDeck(); - + data.data.edgecard = this.actor.getEdgesCard(); data.data.deckSize = this.actor.getDeckSize(); @@ -40,7 +40,7 @@ export class SoSActorSheet extends ActorSheet { if ( a.name > b.name ) return 1; return -1; }); - data.data.gears = this.actor.data.items.filter( item => item.type == 'gear'); + data.data.gears = this.actor.data.items.filter( item => item.type == 'gear').concat( this.actor.data.items.filter( item => item.type == 'container') ); data.data.weapons = this.actor.data.items.filter( item => item.type == 'weapon'); data.data.armors = this.actor.data.items.filter( item => item.type == 'armor'); data.data.totalEncumbrance = SoSUtility.computeEncumbrance(this.actor.data.items); diff --git a/module/actor.js b/module/actor.js index 35e98d5..9db2a28 100644 --- a/module/actor.js +++ b/module/actor.js @@ -157,7 +157,7 @@ export class SoSActor extends Actor { return this.data.data.scores.wound.value; } computeWound() { - return Math.ceil( (this.data.data.stats.strength.value + this.data.data.stats.endurance.value) / 2) + this.data.data.scores.wounds.bonusmalus; + return Math.ceil( (this.data.data.stats.strength.value + this.data.data.stats.endurance.value) / 2) + this.data.data.scores.wound.bonusmalus; } /* -------------------------------------------- */ diff --git a/packs/gears.db b/packs/gears.db index 48f8883..dce6763 100644 --- a/packs/gears.db +++ b/packs/gears.db @@ -1,36 +1,35 @@ +{"name":"Xenocom X4 Machine Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"The Xenocom X4 Machine Pistol is a military favorite. Coming with the best fully automatic capability of any pistol on the market, the X4 outdoes the competition. Pick yours up and feel the ballistic power in your hand. Place an order for the entire unit. Outfit our squad with the best!","quantity":0,"costrating":9,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"3M","damage_hearts":"12M","damage_spade":"18M","damage_diamond":"6M","hands":1,"pierce":0,"range":10,"reload":1,"shots":15,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"1Gj3ATIVykyAQ5fD"} {"name":"Survival Kit (Superior)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Never get caught in the great outdoors without one! This robust kit contains water purification tablets, a set of disposable tests for food safety, a variety of ointments, food tablets, a small knife, a lighter, a signal flare and other useful odds and ends. It counts as sufficient tools for surviving in the wild, provided the user already has an air supply. Also consider our superior quality survival kits, which count as superior tools (+2). Contains 10 uses. Each use is good for one person for one day.","quantity":0,"costrating":9,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"1ll4eIuaJApCGrML"} +{"name":"Xenocom L8 Machine Lasrifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"When in combat, it's best to remember: don't let up. That's why you need the Xenocom L8 Machine Lasrifle. With this high quality military-grade laser rifle, you can keep the pressure on, pinning your enemies down with its automatic fire and keeping your allies out of the line of fire.","quantity":0,"costrating":12,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"4M","damage_hearts":"16M","damage_spade":"24M","damage_diamond":"8M","hands":2,"pierce":0,"range":20,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"1vtg2WBSSmvJxS4f"} {"name":"Radasil","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Don't let radiation get the best of you. Treat it preventatively with Radasil. If taken before radiation exposure, Radasil gives a +4 bonus to resist the effects of radiation. Its protection lasts for 8 hours. This potent medication still takes its toll on the body, however. Upon administration, the recipient gains the Fatigue consequence. Pack of 10 doses.","quantity":0,"costrating":3,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"2CXNwJC5OkaV8t1R"} {"name":"Microbug","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Never miss a hidden event: use a microbug! A microbug is a flea-sized recording device that captures both audio and video input. It can store up to 10 minutes of input on the device itself, but typically transmits its recording wirelessly to a remote computer. Transmission can be to occur in short bursts, in a constant stream or at a specified time.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"4ShEb618Jq2Pqk9a"} {"name":"USD-24k “Aegis” Reflect Suit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Do lasers threaten to give you health problems by burning holes into your flesh? Then look no further! The USD-24k “Aegis” Reflect Suit scatters lasers before they can scatter you. Constructed of bleeding-edge materials, the Aegis refracts laser light, leaving the wearer unharmed. This comes with either a frosted or glossy finish.","quantity":0,"costrating":6,"defensive":0,"containerid":"","bulky":0,"dr":2,"gel":0,"reflect":3,"str":0,"vac":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/generic_armor.svg","effects":[],"_id":"4forWg1Pt9MZ5hZ6"} +{"name":"USD-07 “Firefly” Shockstick","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Critical Effect: When this critical effect is chosen, increase the target's Stun consequence a severity. Incapacitate your opponents with a nonlethal electric charge, using this USD-07 “Firefly” Shockstick. The Firefly is a telescoping baton that has a rubberized grip on one end. This insulates the wielder from the electric charge, which can be switched on or off using a button on the grip. If struck, the electrolyzed end discharges, delivering a shock to the opponent intended to stun or incapacitate.","quantity":0,"costrating":4,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str+3L","damage_hearts":"Str+12L","damage_spade":"Str+18L","damage_diamond":"Str+6L","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":true,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"melee","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/baton.svg","effects":[],"_id":"4t0hCOUBt8KMIl7U"} {"name":"Ladar Scanner","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Ladar! Ladar! Ladar! Ladar scanners emit low-energy laser beams to detect and identify nearby objects. Although they are of limited use in detecting unknown objects due to the narrowness of their beams, they have remarkable resolution in identifying objects once they are known. This includes facial recognition and chemical recognition technologies! Just compare to a facial database, or to a database of chemicals based on which wavelengths of the laser light the materials absorb. Signal is good up to a dozen kilometers in atmosphere or a thousand kilometers in a vacuum.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"5AMS4LoD2ccjSOoR"} +{"name":"Combat Utility Knife","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"It's a weapon. It's a tool. It's both! Combat utility knives are a versatile weapon and tool, balanced for both hand-to-hand use as well as sudden throws. Combat utility knives can be used to cut rope, pry open simple doors or butter toast. Never leave home without one! The handle comes in a variety of custom styles.","quantity":0,"costrating":1,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str0.5M","damage_hearts":"Str2M","damage_spade":"Str3M","damage_diamond":"StrM","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":true,"reach":false,"shallow":false,"spread":false,"category":"melee","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/bowie-knife.svg","effects":[],"_id":"5QgIyzoaOU13GdJg"} {"name":"Disposable Cuffs","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"These disposable cuffs are little more than metal-meshed tape that can automatically tighten over the limbs of their target once applied. Further struggles against the cuffs cause them to tighten further. Each length is good for one use. Comes with 10 uses.","quantity":0,"costrating":3,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"5aVUx3LL0sgKDX5c"} {"name":"Encryption System (Ultimate)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":9,"worn":false,"description":"Keep your private life private. Encryption is necessary for any sort of secure transaction using broadcast communication, such as on the net or through radio comms. Most computers come with basic built-in encryption methods, but for those who want real security, bolstered encryption software is a no-brainer. Difficulty of breaking encryption scales with processing requirements. Encryption systems come in a variety of different qualities, with differing processing requirements (see page XXX).","quantity":0,"costrating":10,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"5h4IMmt4GE1XWHLf"} -{"name":"USD-720 “Widowmaker” Heavy Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The ultimate man-stopper, the USD-720 “Windowmaker” Heavy Pistol is sure to leave you standing and your enemies taking a dirt nap. A long-time favorite of bounty hunters and security forces the Sol system over, this sleek .50 caliber handgun is now available on the open market! Order yours today!","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"2M","damage_hearth":"10M","damage_spade":"15M","damage_diamond":"5M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"5v8G1u0BqBCYDbuc"} +{"name":"Xenocom L3 Machine Laspistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"The L3 Machine Laspistol is the latest military-grade laspistol from Xenocom. It's heavy-duty ionized battery contains enough charge for sustained fire, and its state of the art heat-sinks support the highest rates if automatic fire. Pick yours up and make the best decision you've ever made today!","quantity":0,"costrating":11,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"3M","damage_hearts":"12M","damage_spade":"18M","damage_diamond":"6M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"69yKqu677umscF5A"} {"name":"Encryption System (Basic)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":3,"worn":false,"description":"Keep your private life private. Encryption is necessary for any sort of secure transaction using broadcast communication, such as on the net or through radio comms. Most computers come with basic built-in encryption methods, but for those who want real security, bolstered encryption software is a no-brainer. Difficulty of breaking encryption scales with processing requirements. Encryption systems come in a variety of different qualities, with differing processing requirements (see page XXX).","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"77LBpjdxXYae9Xpv"} {"name":"Torpestat","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Be the boss of pain. Don't let pain be the boss of you. Torpestat is a powerful pain-killer. Once injected, it lasts for 8 hours. During this time, the recipient does not take penalties from the Wound consequence. Additionally, she gains a +2 bonus to her Shock threshold. The downside is that the drug also leaves her numb, giving her a -2 penalty to all Dexterity and Speed actions, as well as to any Perception action relying on her sense of touch. Pack of 10 doses.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"7bcyIelcEDzRQVZx"} {"name":"Disguise Kit (Superior)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Be who you want to be with this disguise kit! This complete kit contains makeup, chemicals for mimicking muscle twitches and tightness, prosthetic attachments, instant hair coloring and colored contacts. This counts as sufficient tools for disguise. Also consider our superior quality version, which counts as superior tools (+2) for the purposes of disguise! Each kit contains enough materials for 10 uses.","quantity":0,"costrating":9,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"7mMMx0cXlag4ivNv"} {"name":"AR Implant","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":1,"neg":false,"mil":false,"software":0,"worn":false,"description":"Tired of bulky AR glasses? Internalize your augmented reality! This state-of-the-art AR implant intercepts signals between the host's eyes and brain, injecting AR tags and other data into the visual signal. Operated through either voice or programmed eye movements, the AR implant comes complete with encrypted wireless interface and hard-wired off switch. For AR rules, see page XXX.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"7qbtPn0nGYsuslSj"} +{"name":"USD-383 “Wasp” Light Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"A personal protection favorite, the USD-383 “Wasp” Light Pistol is ready to lock and load! Take aim at your favorite shooting range or when your life is in danger. The gun is small enough to fit most holsters or to slip into a purse! It comes with patent-pending rubberized grip and is available in gun barrel gray, matte black, racing stripe red or powder pink.","quantity":0,"costrating":5,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearts":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"9hfSPPcykZalyToU"} {"name":"Somnitol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Prescribed for even the toughest insomnia, Somnitol will put you to sleep. If injected, Somnitol will put the recipient into a deep sleep in a number of rounds equal to her Endurance. Once asleep, she will be unconscious for the next 8 hours unless awoken through a stimulant or by other chemical means. Pack of 10 doses.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"At2vZV5LuNy6B0An"} -{"name":"Power Tool","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Some repair and constructions tasks require more than a simple toolkit. For those, try a dedicated power tool! Power tools come in a variety of shapes and sizes from chainsaws to magnetic drills. In a pinch, they can even serve as an improvised hand-to-hand weapon! (See the damage listing above.). Count as an improvised weapon.","quantity":0,"costrating":4,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str×½M","damage_hearth":"Str×2M","damage_spade":"Str×3M","damage_diamond":"StrM","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"B8WtZN572O0Bh2aK"} {"name":"Verazine","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":true,"software":0,"worn":false,"description":"When the perp won't talk, try Verazine! Verazine is a psychoactive drug used in interrogations and for even less savory purposes. It causes the recipient to enter a hazy, dream-like state, becoming talkative and losing her internal filters. Injected directly into the bloodstream, Verazine takes about a minute to set in. Then, for the next 10 minutes, the recipient is at a -4 penalty to all actions to deceive or avoid simple mental trickery. Pack of 10 doses.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"BRfji7Q0B6ziSKFZ"} -{"name":"Gun Arm Implant","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":4,"container":0,"implant":1,"neg":false,"mil":false,"software":0,"worn":false,"description":"Have your safety well in hand, or at least in arm, with this gun arm implant! Included is a concealed ballistic gun barrel and trigger mechanism, which embeds beneath the skin into the flesh of the forearm. The gun can be programmed to fire with a simple flick of the arm, giving the element of surprise. It holds three shots. Reloading requires opening a compartment in the arm and loading each bullet individually.","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearth":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":2,"shots":3,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"BXO08S48bEirevNW"} -{"name":"USD-720 Widowmaker Heavy Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"

    The ultimate man-stopper, the USD-720 “Windowmaker” Heavy Pistol is sure to leave you standing and your enemies taking a dirt nap. A long-time favorite of bounty hunters and security forces the Sol system over, this sleek .50 caliber handgun is now available on the open market! Order yours today!

    \n

     

    ","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"2M","damage_hearth":"10M","damage_spade":"15M","damage_diamond":"5M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/usd-720.svg","effects":[],"_id":"CgOBdHEwfFMUbEYk"} {"name":"USD-38n “Knight” Tactical Suit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":5,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Utakar's latest design in heavy civilian armor, the USD-38n “Knight” Tactical Suit employs advanced safety measures to keep the wearer up and fighting. Built from the ground up for reliable protection, the Knight Tactical Suit is a must-have for any urban warrior. Straps and pockets carry extra magazines. Comes in a variety of patterns and colors. Available in both matte and gloss.","quantity":0,"costrating":8,"defensive":0,"containerid":"","bulky":1,"dr":5,"gel":0,"reflect":0,"str":0,"vac":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/generic_armor.svg","effects":[],"_id":"DIT9UQ5ygV04DLDq"} {"name":"Rope","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"You never know when you'll need some good, old-fashioned rope! This rope is made of light, but durable synthetic fabrics and coils into an easy-to-transport bundle. Contained is 50 m of rope, capable of safely holding up to 200 kg. If trying to load the rope with more than this, have the GM flip a card. If it's a clubs the rope breaks. Flip an additional card for every increment of 200 kg. Rope counts as a sufficient tool for many purposes, such as climbing heights or tying someone up.","quantity":0,"costrating":1,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"EOEHdeBTN1sTehdB"} -{"name":"Xenocom L8 Machine Lasrifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"When in combat, it's best to remember: don't let up. That's why you need the Xenocom L8 Machine Lasrifle. With this high quality military-grade laser rifle, you can keep the pressure on, pinning your enemies down with its automatic fire and keeping your allies out of the line of fire.","quantity":0,"costrating":12,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"4M","damage_hearth":"16M","damage_spade":"24M","damage_diamond":"8M","hands":2,"pierce":0,"range":20,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"EWFG5rLe5vzAbelR"} {"name":"ToolKit (Superior)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"After using our toolkits, you'll feel naked without one! A variety of toolkits are available, each geared towards a specific kind of task and each containing tools useful in that task. When purchasing a toolkit, think about what the toolkit is geared for as a specific skill experience. For example, “electrician” might be a toolkit used with the mechanic skill. Tool kits count as sufficient equipment for that specialty and count as improvised equipment for other uses of the same skill. Also, consider our top of the line superior toolkits for the best tools that money can buy. These superior toolkits count as superior tools (+2) for the specialty in question and sufficient tools for any other application of the skill.","quantity":0,"costrating":9,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"EXlYN1hS2xFtOoC8"} -{"name":"USD-2280L “Zeus” Light Lasrifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Perfect for use on spaceships or stations across the system, the USD-2280L “Zeus” Light Lasrifle is jam-packed with all the essentials needed for successful space security. From its sleek, curved barrel to its finger-molded grip, the Zeus is a miracle for the professional security worker.","quantity":0,"costrating":8,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"3M","damage_hearth":"12M","damage_spade":"18M","damage_diamond":"6M","hands":2,"pierce":0,"range":20,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"EpfGa44ZASM6RxvM"} {"name":"AR Glasses","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Join the AR revolution. Join the twenty-third century. AR glasses look a lot like typical glasses, except they project augmented reality (AR) information before the wearer's eyes. This allows the wearer to read AR tags, access AR data and overlay projections on the world around her. Doing this, however, requires wirelessly interfacing the AR glasses with a computer—typically a hand terminal. This connection is typically a radio or infrared (IR) connection.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"GGnTiYuoZmtfW1cu"} {"name":"Expert System (Deluxe)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":7,"worn":false,"description":"Know your knowns and your known unknowns! An expert system is software that provides a database of knowledge and useful advice on a given topic. This is often designed to hook in to AR software, projecting useful tags and other information right before the user's eyes, aiding in a variety of tasks. Every expert software is designed to support one skill, or sometimes a specific experience in a skill. By taking a moment (an interact action in combat) the user can query the expert system for help on this skill. Mechanically this works as if the expert system is making a group effort action supporting the user, with a total based on the quality of the software (see page XXX). An action may only benefit from one expert system at a time. Expert software comes in four qualities: basic (total 10), pro (total 12), deluxe (total 14) and ultimate (total 16). Example: Stan is using a pro expert system to help him with ship repairs. He makes the required Dex/mechanic flip and gets a total of 9, not yet taking into account the expert system. Since expert systems work exactly like secondary characters in a group effort action, and since the expert system's total—12 for pro quality—is higher than Stan's total, he gets a +2 bonus to his action. This gives him a final total of 11.","quantity":0,"costrating":8,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"GJ38ece2gUCLzqNb"} {"name":"Translation Software","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":3,"worn":false,"description":"Don't let the language barrier be an issue. Translation software provides real time on-the-fly translation between two languages. Every language pairing is its own software. Most translation software is capable of outputting the translation in both speech and text, and often includes the ability to manually enter new vocabulary and idioms. No translation software is perfect, and most still has problems translating less common subculture slang or figures of speech.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"GeoammxYJ3lVSOnH"} {"name":"Backpack","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"container","data":{"big":0,"computer":0,"conceal":0,"container":5,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Strap things to your back so that you don't have to carry them in your hands! This designer backpack comes in a variety of colors and styles—perfect for any occasion. The backpack features one large pocket and a variety of smaller pockets for your carrying convenience. Retrieving an item from a backpack requires an interact action to open the backpack and fish around in addition to the usual interact action to retrieve the item.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"H8mMpHD0idwFSEsQ"} {"name":"Mainframe","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":10,"computer":7,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Do you have the need for not just sufficient, but vigorous computing? Order a mainframe today! Mainframes are designed to go beyond personal computing needs. They host popular net nodes, serve as the main computers for spaceships, administrate corp sites and sit on academic campuses. Mainframes are generally large machines meant to remain wired in place and communicated with through individual workstations or hand terminals. Many have wireless capabilities, but this is often left turned off to take advantage of the superior bandwidth offered by wired connections.","quantity":0,"costrating":9,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_computer.svg","effects":[],"_id":"Hsnyxz7KKBuu0lp8"} {"name":"Personal Assistant","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":5,"worn":false,"description":"When you need a little bit of help, get a personal assistant! Personal assistant software uses adaptive algorithms to learn the wants, needs, schedule and habits of a particular user, looking up information and making suggestions without prompting. All personal assistant software requires several weeks to adapt to a new user, and most is given a customizable anthropomorphic avatar, or at least a name. This avatar can be projected into the surrounding environment when viewed through AR. Many personal assistants have adjustable personalities as well.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"I89e6zkA3IU2j0rc"} -{"name":"USD-490L “Indra” Light Laspistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"In zero-G the professional soldier knows not to be caught with only a ballistic gun at hand, because dead is what she will be. Don't let this happen to you. Take the USD-490L “Indra” Light Laspistol into your zero-G battles and you will never want to use another lasgun again!","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearth":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"ILzHxSck1VV5Qvl2"} {"name":"Regrowth Therapy","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Need a new arm, leg or bodily organ? Look no further! Lost limbs, digits, eyes and many other organs can be regrown, but this is expensive, takes time and requires frequent visits to the doctor to apply the next stage of the therapy. Limbs in the process of regrowth typically are tender and itch fiercely. For full rules on surgery and regrowth therapy, see page XXX.","quantity":0,"costrating":8,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"IMhke5iishvcwjws"} +{"name":"USD-1200 “Amazon” Light Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The rifle you need when you're on the go, the USD-1200 “Amazon” Light Rifle has been designed from the ground up for easy transportation and assembly. With balancing range, magazine capacity and ease of maintenance, the Amazon gets the job done. Satisfaction guaranteed. Some assembly required.","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"3M","damage_hearts":"12M","damage_spade":"18M","damage_diamond":"6M","hands":2,"pierce":0,"range":20,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"IOu795LMQE85eVsF"} +{"name":"Xenocom X8 Machine Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"When you want maximum staying power, you want the Xenocom X8 Machine Rifle. Combining the best in range and magazine capacity with the best in full-auto heat suppression technology, the Xenocom X8 is second to none. Pair with our range finder or tracer round extras for the ultimate military battlefield kit.","quantity":0,"costrating":10,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"4M","damage_hearts":"16M","damage_spade":"24M","damage_diamond":"8M","hands":2,"pierce":0,"range":20,"reload":1,"shots":30,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"Iq9hnHSCinNaEztJ"} {"name":"USD-IIh Bulwak Ballistic Suite","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"

    Simply the best in light but durable ballistic protection, the USD-11h “Bulwark” Ballistic Suit stops bullets in their tracks. Utilizing Utakar’s proprietary Shell-StopperTM gel technology, the Bulwark hardens upon impact, distributing the kinetic force of the impact throughout the body. Self-sealing gel closes in seconds. Designer pockets fit most common magazines. It is available in black, charcoal, rosewood and navy.

    \n

     

    ","quantity":0,"costrating":5,"defensive":0,"containerid":"","bulky":0,"dr":2,"gel":3,"reflect":0,"str":0,"vac":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/bulwak_armor.svg","effects":[],"_id":"IzyB0If465nUk2Ws"} -{"name":"USD-07 “Firefly” Shockstick","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Critical Effect: When this critical effect is chosen, increase the target's Stun consequence a severity. Incapacitate your opponents with a nonlethal electric charge, using this USD-07 “Firefly” Shockstick. The Firefly is a telescoping baton that has a rubberized grip on one end. This insulates the wielder from the electric charge, which can be switched on or off using a button on the grip. If struck, the electrolyzed end discharges, delivering a shock to the opponent intended to stun or incapacitate.","quantity":0,"costrating":4,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str+3L","damage_hearth":"Str+12L","damage_spade":"Str+18L","damage_diamond":"Str+6L","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":true,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"JZghdsLCHaAIAhCH"} -{"name":"Unarmed","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"It doesn't get much more primal than old-school fisticuffs. Despite all the technological ways to go for blood, fistfights remain the most common form of violence in the Sol system. This listing represents the human capacity to attack with fists, feet or teeth.","quantity":0,"costrating":"—","defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"½StrL","damage_hearth":"Str×2L","damage_spade":"Str×3L","damage_diamond":"StrL","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"K05lfEHRogl3m4Df"} {"name":"USD-24k Aegis Reflect Suit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"

    Do lasers threaten to give you health problems by burning holes into your flesh? Then look no further! The USD-24k “Aegis” Reflect Suit scatters lasers before they can scatter you. Constructed of bleeding-edge materials, the Aegis refracts laser light, leaving the wearer unharmed. This comes with either a frosted or glossy finish.

    \n

     

    ","quantity":0,"costrating":6,"defensive":0,"containerid":"","bulky":0,"dr":2,"gel":0,"reflect":3,"str":0,"vac":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/bulwak_armor.svg","effects":[],"_id":"K6pBGZRiBzPzHHPZ"} {"name":"Biometric Reader","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"For all your secure needs, you can rely on a biometric reader. A biometric reader is typically used as a secure input device to authenticate the identity of the computer user. Most biometric readers scan fingerprints or retinas, although DNA biometric readers exist as well. A biometric reader is typically connected to a host computer, which then takes input from the device.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"KFF8f1849H6BTjk3"} {"name":"ToolKit (Basic)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"After using our toolkits, you'll feel naked without one! A variety of toolkits are available, each geared towards a specific kind of task and each containing tools useful in that task. When purchasing a toolkit, think about what the toolkit is geared for as a specific skill experience. For example, “electrician” might be a toolkit used with the mechanic skill. Tool kits count as sufficient equipment for that specialty and count as improvised equipment for other uses of the same skill. Also, consider our top of the line superior toolkits for the best tools that money can buy. These superior toolkits count as superior tools (+2) for the specialty in question and sufficient tools for any other application of the skill.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"KjHfCiJaHaPwHxEH"} @@ -38,61 +37,57 @@ {"name":"Surgery Kit (Basic)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":1,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Not all injuries happen within easy reach of a hospital or medical bay. For unexpected injuries in the remote reaches of space, there's the portable surgery kit. With a portable pack of surgeon's tools, diagnostic gear, cheap anesthetics and antibiotics, this kit counts as sufficient equipment for minor surgery, or improvised equipment (-2) for major surgery. Also consider our superior quality surgery kits, which count as superior tools (+2) for minor surgery or sufficient tools for major surgery! Contains materials for 10 surgeries. Performing surgery using one of these kits does not incur the expense of paying for a full surgery treatment (see page XXX).","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_computer.svg","effects":[],"_id":"LjALXCUxnMtqMynq"} {"name":"Encryption System (Pro)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":5,"worn":false,"description":"Keep your private life private. Encryption is necessary for any sort of secure transaction using broadcast communication, such as on the net or through radio comms. Most computers come with basic built-in encryption methods, but for those who want real security, bolstered encryption software is a no-brainer. Difficulty of breaking encryption scales with processing requirements. Encryption systems come in a variety of different qualities, with differing processing requirements (see page XXX).","quantity":0,"costrating":6,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"MB9mtcTOiuDTNMzK"} {"name":"Medikit (Superior)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Treat nagging injuries on the go! The medikit contains basic medical tools, useful for treating all major or simple injuries, including adhesive spray, antibiotics, a variety of ointments, an oxygen mask and sutures. This counts as sufficient tools for first aid or improvised equipment (-2) for minor surgery. Also, consider our superior quality medikits, which count as superior tools (+2) to first aid! Contains 10 uses.","quantity":0,"costrating":"","defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"MkgxXeeQniToOcPi"} -{"name":"USD-383 “Wasp” Light Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"A personal protection favorite, the USD-383 “Wasp” Light Pistol is ready to lock and load! Take aim at your favorite shooting range or when your life is in danger. The gun is small enough to fit most holsters or to slip into a purse! It comes with patent-pending rubberized grip and is available in gun barrel gray, matte black, racing stripe red or powder pink.","quantity":0,"costrating":5,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearth":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"Mkv9Q7x9IaGJ5uvn"} -{"name":"USD-1200 Amazon Light Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"

    The rifle you need when you’re on the go, the USD-1200 “Amazon” Light Rifle has beendesigned from the ground up for easy transportation and assembly. With  balancing range, magazine capacity and ease of maintenance, the Amazon gets the job done. Satisfaction guaranteed. Some assembly required.

    \n

     

    ","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearth":"12M","damage_spade":"18M","damage_diamond":"6M","hands":2,"pierce":0,"range":20,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/usd-1200.svg","effects":[],"_id":"NN9iWxPKU9djFfA9"} -{"name":"USD-3200 Valkyrie Heavy Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"

    The USD-3200 “Valkyrie” Heavy Rifle is a masterpiece of twenty-third century engi-neering, combined with sleek twenty-second century ascetics. Own the best-designed and best-looking heavy rifle on the market! It comes with two autofire settings and a designer gun case. Remember, Valkyrie means quality.

    \n

     

    ","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearth":"14M","damage_spade":"21M","damage_diamond":"7M","hands":2,"pierce":0,"range":20,"reload":1,"shots":20,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/usd-3200.svg","effects":[],"_id":"O4B0meZMhDgxDXcC"} {"name":"GPS Tracker","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Always know your way around with this GPS tracker! Useful on any planetary body with GPS satellites, this simple GPS tracker has a small display for its coordinates and also can transmit wirelessly to any close computer or other wireless device. It is best used with an Expert System for planetary navigation!","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"Phq7WiW0byei3CcO"} {"name":"Night Vision Glasses","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Don't be caught in the dark without them. They look like regular sunglasses, meeting all your style requirements! These night vision glasses can detect infrared, projecting a false-color image right before the wearer's eyes. Good for seeing objects in the dark but less useful for reading or color detection.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"Pm47QnZSb5o5Ooqq"} {"name":"Disposable Test Kit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Have a specific condition that needs testing? That calls for a disposable test kit. This kit tests for a specific disease, toxin, drug or medical condition, such as sleep deprivation or pregnancy. It is typically administered through either drawing blood or through a urine sample. Results usually take a minute or two. Contains 10 disposable tests.","quantity":0,"costrating":3,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"PzAPqa0QH8WY5MO8"} {"name":"Major Surgery","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Minor surgery not enough for your wounds? Major surgery may be just what the doctor ordered! Major surgery is capable of removing even more potent lasting consequences, including many of the worst lingering injuries (see page XXX). For full rules on surgery, see page XXX.","quantity":0,"costrating":7,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"QTfWF9guaWTefAvS"} +{"name":"Plasma Cutter","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"A favorite in heavy duty construction work, ship repair and emergency boarding actions, this plasma cutter cuts right through even the toughest metals and ceramics. The airlock busted? Just cut right through the hull! A plasma cutter can also be used as an improvised weapon in a pinch (see the damage listing above). Count as an improvised weapon.","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"1M","damage_hearts":"6M","damage_spade":"9M","damage_diamond":"3M","hands":1,"pierce":3,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"melee","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/plasma-cutter.svg","effects":[],"_id":"QrLfGgq5GS0AwVA2"} {"name":"Laser Comm","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Direct your communication with a laser comm. Laser comms use lasers to transmit and receive data at a directed target. This limits the ability to intercept the data because it is not broadcast to the world but rather directed at a specific target. Naturally, the ability to use a laser comm relies on having a direct line of communication unobscured by walls, the curve of planetary bodies or atmospheric interference. This personal laser comm is good for a dozen kilometers on a clear day in atmospheric conditions or several thousand kilometers in the vacuum of space.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"QvBZml9C4OxCvSOR"} {"name":"IR Cloak","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Do your enemies have the means of IR detection? Foil even that with this IR cloak! An IR cloak appears to be a thick poncho or tarp, which is usually matte black in color. It self-adjusts to the ambient temperature to fool infrared detection methods. This is usually coupled by cutting the lights or otherwise moving around in the dark to foil visible spectrum detection as well.","quantity":0,"costrating":7,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"Rs8osdikMhPYixjf"} -{"name":"USD-383 Wasp Light Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"

    A personal protection favorite, the USD-383 “Wasp” Light Pistol is ready to lock and load! Take aim at your favorite shooting  range or when your life is in danger. The gun is small enough to fit most holsters or to slip into a purse! It comes with patent-pending rubberized grip and is available in gun barrel gray, matte black, racing stripe red or powder pink. 

    \n

     

    ","quantity":0,"costrating":5,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearth":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/usd-383.svg","effects":[],"_id":"U55o7zC4bKnqpXug"} {"name":"Expert System (Basic)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":3,"worn":false,"description":"Know your knowns and your known unknowns! An expert system is software that provides a database of knowledge and useful advice on a given topic. This is often designed to hook in to AR software, projecting useful tags and other information right before the user's eyes, aiding in a variety of tasks. Every expert software is designed to support one skill, or sometimes a specific experience in a skill. By taking a moment (an interact action in combat) the user can query the expert system for help on this skill. Mechanically this works as if the expert system is making a group effort action supporting the user, with a total based on the quality of the software (see page XXX). An action may only benefit from one expert system at a time. Expert software comes in four qualities: basic (total 10), pro (total 12), deluxe (total 14) and ultimate (total 16). Example: Stan is using a pro expert system to help him with ship repairs. He makes the required Dex/mechanic flip and gets a total of 9, not yet taking into account the expert system. Since expert systems work exactly like secondary characters in a group effort action, and since the expert system's total—12 for pro quality—is higher than Stan's total, he gets a +2 bonus to his action. This gives him a final total of 11.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"VD52Z8KMWtSACXYp"} {"name":"USD-11h “Bulwark” Ballistic Suit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Simply the best in light but durable ballistic protection, the USD-11h “Bulwark” Ballistic Suit stops bullets in their tracks. Utilizing Utakar's proprietary Shell-Stopper™ gel technology, the Bulwark hardens upon impact, distributing the kinetic force of the impact throughout the body. Self-sealing gel closes in seconds. Designer pockets fit most common magazines. It is available in black, charcoal, rosewood and navy.","quantity":0,"costrating":5,"defensive":0,"containerid":"","bulky":0,"dr":2,"gel":3,"reflect":0,"str":0,"vac":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/generic_armor.svg","effects":[],"_id":"VDP99ZYhwXxMH2ll"} {"name":"Microcomputer","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Are you tracking an object, calculating basic numbers or broadcasting a message on loop? Do you need only very basic computing and wireless ability? Then a microcomputer is what you're looking for! This dime-sized computer is capable of basic computations and processing. It has inbuilt wireless access using either IR or radio comms (see page XXX). Unlike other computers and due to its size, it has no display or other input or output features, requiring peripherals or wireless communication with another device.","quantity":0,"costrating":1,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"VW7edurHNZF9039v"} -{"name":"Combat Utility Knife","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"It's a weapon. It's a tool. It's both! Combat utility knives are a versatile weapon and tool, balanced for both hand-to-hand use as well as sudden throws. Combat utility knives can be used to cut rope, pry open simple doors or butter toast. Never leave home without one! The handle comes in a variety of custom styles.","quantity":0,"costrating":1,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str×½M","damage_hearth":"Str×2M","damage_spade":"Str×3M","damage_diamond":"StrM","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":true,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"VoOZYzdC0F1TIF8B"} -{"name":"Xenocom X4 Machine Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"The Xenocom X4 Machine Pistol is a military favorite. Coming with the best fully automatic capability of any pistol on the market, the X4 outdoes the competition. Pick yours up and feel the ballistic power in your hand. Place an order for the entire unit. Outfit our squad with the best!","quantity":0,"costrating":9,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"3M","damage_hearth":"12M","damage_spade":"18M","damage_diamond":"6M","hands":1,"pierce":0,"range":10,"reload":1,"shots":15,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"W2L04UuUZ15VXsH7"} +{"name":"Sinoex Monowhip XT","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"Critical Effect: When this critical effect is chosen, the monowhip does not break upon impact, as is normal. Crafted by the exotic materials experts at Sinoex, the Sinoex Monowhip XT is a coiled strand of near-monomolecular wire with a weight on the end held in a magnetized handle. Upon pressing a button, a power source in the handle causes the wire to uncoil and extend outward, providing the ideal cutting tool. Monowhips tear through armor like cardboard, but their limited tensile strength means they are typically one-use weapons, breaking after they successfully strike a target.","quantity":0,"costrating":5,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str0.5S","damage_hearts":"Str0.75","damage_spade":"StrS","damage_diamond":"Str0.5S","hands":1,"pierce":10,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"melee","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/whiplash.svg","effects":[],"_id":"WgMteHIHwSNIdeYU"} {"name":"Biomonitor","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"This biomonitor is a small, barely-invasive implant that periodically records simple medical data, such as blood pressure, pulse, heart rate and blood sugar. It comes complete with a small external switch that turns on the capability to communicate wirelessly with medical equipment. This aids in diagnosis and first aid on the host, granting a +2 bonus to such endeavors.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"WzZjCTfa518Rsybn"} {"name":"Minor Surgery","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Suffering from a simple bone fracture, minor organ damage or moderate tissue damage? A variety of minor surgeries may be able to help you! They are capable of removing a variety of lasting consequences, including many on the Lingering Injury tables (see page XXX). For full rules on surgery, see page XXX.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"XW9zucts77QdfayO"} +{"name":"USD-840L “Horus” Heavy Laspistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The USD-840L “Horus” Heavy Laspistol is simply best heavy laspistol on the market. Designed from heavy-duty metal alloys and with anti-heat ceramic plating, the Horus outshoots the competition. Plus, the Horus' state of the art battery packs are guaranteed to hold the charges for months without unwanted discharge.","quantity":0,"costrating":8,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"2M","damage_hearts":"10M","damage_spade":"15M","damage_diamond":"5M","hands":1,"pierce":0,"range":10,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"Y2PKUrKdUoeZj4YR"} +{"name":"USD-720 “Widowmaker” Heavy Pistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The ultimate man-stopper, the USD-720 “Windowmaker” Heavy Pistol is sure to leave you standing and your enemies taking a dirt nap. A long-time favorite of bounty hunters and security forces the Sol system over, this sleek .50 caliber handgun is now available on the open market! Order yours today!","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"2M","damage_hearts":"10M","damage_spade":"15M","damage_diamond":"5M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"YaIR4x1yisBoFVWT"} {"name":"Ballistic Clips","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":null,"software":0,"worn":false,"description":"What are guns without clips of ammunition? Poorly-designed clubs! Don't bring a club to a gun fight. Ammunition is sold in clips fitting the gun in question. Most guns have their own standard for ammunition in terms of both caliber and cartridge design. The type of gun the ammo is designed for must be specified when the clip is purchased.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"YrnLXsHuVlmt1yO8"} {"name":"Workstation","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":5,"computer":5,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"For serious computing needs, a workstation computer will excel! These computers are designed to be set on a desk or hung on a wall. They have the serious processing power needed for the most resource intensive games, extended scientific calculations and encryption. They can also serve as a makeshift server if needed. Workstation computers typically come with touchscreen and voice controls, as well as key inputs and sometimes simple biometric input.","quantity":0,"costrating":6,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_computer.svg","effects":[],"_id":"ZSu4Yt7TYSKIGtNw"} {"name":"IR Comm","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Does your device not speak infrared? Get a dedicated IR comm! IR comms use infrared to transmit and receive data. This is useful only at very short ranges—usually no more than a few dozen meters. It is of particular use in short distance, secured transmissions because IR does not penetrate walls and its short distance limits eavesdropping. IR communication comes built in to most hand terminals and other short-range wireless devices. A dedicated IR comm, such as this one, can be attached to other devices to give IR communication capabilities.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"aEtzovx5IkSSaMhO"} -{"name":"USD-4700L “Thor” Heavy Lasrifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Don't be out-gunned: carry the USD-4700L “Thor” Heavy Lasrifle. The best in range, accuracy and automatic fire capacity, every Thor heavy lasrifle is constructed from the finest materials and tested by the weapons experts at Utakar System Dynamics. So don't be out-gunned. Choose the best!","quantity":0,"costrating":9,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearth":"14M","damage_spade":"21M","damage_diamond":"7M","hands":2,"pierce":0,"range":20,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"aKC117PiIlTgqhr2"} +{"name":"USD-4700L “Thor” Heavy Lasrifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Don't be out-gunned: carry the USD-4700L “Thor” Heavy Lasrifle. The best in range, accuracy and automatic fire capacity, every Thor heavy lasrifle is constructed from the finest materials and tested by the weapons experts at Utakar System Dynamics. So don't be out-gunned. Choose the best!","quantity":0,"costrating":9,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearts":"14","damage_spade":"21M","damage_diamond":"7M","hands":2,"pierce":0,"range":20,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"aTGyQDeozsStCaig"} {"name":"Gecko-Climbers","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Have a surface you need to scale? Try some Gecko-Climbers! These gloves and boots strap firmly to the limbs, allowing the climber to stick to most surfaces in a manner similar to a gecko. Only capable of supporting up to 100 kg, a wearer of Gecko-Climbers should travel light. Gecko-Climbers count as sufficient tools for climbing and furthermore provide a +2 bonus on actions to climb surfaces to which they stick.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"aTeyx97Uo04c6OoT"} -{"name":"USD-9700 Stun Grenade","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Perfect for crowd control, the USD-9700 Stun Grenade is a wonder to behold. Just set the grenade to burst on timer or upon impact and let it go. The USD-9700 is guaranteed to stun or incapacitate with nonlethal precision. Order yours today!","quantity":0,"costrating":3,"defensive":0,"containerid":"","area":5,"autofire":0,"damage_club":"4L","damage_hearth":"16L","damage_spade":"24L","damage_diamond":"8L","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":true,"thrown":true,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"b0CoCTzsIszkmEZD"} {"name":"Laser Batt-Packs","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":null,"software":0,"worn":false,"description":"Keep your lasers powered up and ready! Laser weapons are powered by high-density batt-packs, capable of releasing the tremendous charge necessary to power weaponized lasers in a small amount of time. The downside of these high-density batt-packs is that it takes serious industrial equipment to recharge them, meaning that batt-packs are typically bought as one-use items and the expended packs simply sold back to the manufacturer for pocket change. Each batt-pack holds the weapon's listed “shots” in charges. Like clips, batt-packs are typically manufactured for a single model of firearm.","quantity":0,"costrating":3,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"b3GPnPnHrh9muSAi"} {"name":"Flashlight","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"While most hand terminals have basic flashlight functionality, they don't have the power of illumination possessed by this durable, high-output survival flashlight! Useful for exploration when the power has gone out, the visible light beam illuminates at 3000 lumens and up to 500 m away!","quantity":0,"costrating":1,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"bI4q9Fx5DBRYMtcD"} {"name":"E-Lockpick","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Never be sealed out of electronic doors again! This small device cycles rapidly through possible electronic lock combinations and patterns, gaining access to electronically-sealed doors or hatches. This counts as sufficient tools for actions to open electronic locks and typically opens them within a few seconds. Attempts to access the locks may still be logged by locks capable of doing so.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"cb8z7SKsUAeWUkhM"} {"name":"Radio Comm","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Radio comms are the most common type of comms in the solar system. They broadcast out radio waves in all directions, carrying data outward. Some wavelengths even have the ability to bounce off walls and atmospheric conditions, spreading or directing their signal in different ways. This maximizes the distance of communication at the expense of being easy to intercept. This personal dedicated radio comm can transmit up to a range of several thousand kilometers.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"dEW5fYf0UuBDjgxR"} {"name":"Surgery Kit (Superior)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":1,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Not all injuries happen within easy reach of a hospital or medical bay. For unexpected injuries in the remote reaches of space, there's the portable surgery kit. With a portable pack of surgeon's tools, diagnostic gear, cheap anesthetics and antibiotics, this kit counts as sufficient equipment for minor surgery, or improvised equipment (-2) for major surgery. Also consider our superior quality surgery kits, which count as superior tools (+2) for minor surgery or sufficient tools for major surgery! Contains materials for 10 surgeries. Performing surgery using one of these kits does not incur the expense of paying for a full surgery treatment (see page XXX).","quantity":0,"costrating":9,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_computer.svg","effects":[],"_id":"dGyTevmWGHWM1kan"} +{"name":"Unarmed","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"It doesn't get much more primal than old-school fisticuffs. Despite all the technological ways to go for blood, fistfights remain the most common form of violence in the Sol system. This listing represents the human capacity to attack with fists, feet or teeth.","quantity":0,"costrating":null,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str0.5L","damage_hearts":"Str2L","damage_spade":"Str3L","damage_diamond":"StrL","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"melee","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/unarmed.svg","effects":[],"_id":"dZShIVfuOgPsm6kW"} {"name":"Injector Unit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":1,"neg":false,"mil":false,"software":0,"worn":false,"description":"Always have your drugs on hand when you need them with this injector unit! The implant is typically embedded in the thigh, and can be programmed to deliver a dose of a contained drug intravenously, all with the flip of a switch or a pre-programmed voice command. Holds three doses. Activating the injector unit is a reaction which costs no AP. The character must be capable of taking reactions.","quantity":0,"costrating":3,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"dchIBN8Hce4weLLH"} +{"_id":"e5iATtC3DCSpE9UO","name":"USD-490L “Indra” Light Laspistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"In zero-G the professional soldier knows not to be caught with only a ballistic gun at hand, because dead is what she will be. Don't let this happen to you. Take the USD-490L “Indra” Light Laspistol into your zero-G battles and you will never want to use another lasgun again!","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearts":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[]} +{"name":"USD-9700 Stun Grenade","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Perfect for crowd control, the USD-9700 Stun Grenade is a wonder to behold. Just set the grenade to burst on timer or upon impact and let it go. The USD-9700 is guaranteed to stun or incapacitate with nonlethal precision. Order yours today!","quantity":0,"costrating":3,"defensive":0,"containerid":"","area":5,"autofire":0,"damage_club":"4L","damage_hearts":"16L","damage_spade":"24L","damage_diamond":"8L","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":true,"thrown":true,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/grenade.svg","effects":[],"_id":"eP3AP4kVQuou4xBs"} +{"name":"Baton","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Barons are a tried-and-true classic when it comes to dealing out blows with a minimum of lethal force. Favored as a control weapon by light security forces the world over, it never hurts to have a baton at your side. Baton telescopes for easy pocket storage. It is available in both solid colors and faux-wood.","quantity":0,"costrating":1,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str0.5+1L","damage_hearts":"Str2+4L","damage_spade":"Str3+6L","damage_diamond":"Str+2L","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"melee","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/baton.svg","effects":[],"_id":"eieqBfY3N4zHdRSk"} {"name":"Camera","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Be a pro photographer! Although most hand terminals come complete with a camera, this dedicated camera far surpasses the typical hand terminal camera in both speed, resolution and assorted options. Good for both still shots and video recording! Net-capable for immediate uploading. Apply a variety of filters on the go.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"f9Oe4FewPC1WF8Jr"} +{"name":"USD-9300 Frag Grenade","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"The USD-9300 is the ultimate in frag grenade flexibility and reliability. It comes with two modes of operation: impact or timer. Simply arm the grenade and fling it at foes, or let it count down. The choice is yours!","quantity":0,"costrating":4,"defensive":0,"containerid":"","area":5,"autofire":0,"damage_club":"4M","damage_hearts":"16M","damage_spade":"24M","damage_diamond":"8M","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":true,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/grenade.svg","effects":[],"_id":"fun9XkbPsOcWICQo"} {"name":"Stimulox","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Stimulox is recommended by doctors system-wide! Use of this drug instantly awakens an unconscious individual, granting a +1 bonus to all Strength, Dexterity and Speed actions for the next 10 minutes, as well as a +1 bonus to Strength-based damage, Defense and Shock threshold. After this effect wears off, the recipient increases her Fatigue consequence a severity. Pack of 10 doses.","quantity":0,"costrating":3,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"iAYXLTEWutlckYeS"} {"name":"Disguise Kit (Basic)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Be who you want to be with this disguise kit! This complete kit contains makeup, chemicals for mimicking muscle twitches and tightness, prosthetic attachments, instant hair coloring and colored contacts. This counts as sufficient tools for disguise. Also consider our superior quality version, which counts as superior tools (+2) for the purposes of disguise! Each kit contains enough materials for 10 uses.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"iZCfjKYg8zSNCO1r"} {"name":"Cybernetic Replacement Limb","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":1,"neg":false,"mil":false,"software":0,"worn":false,"description":"Can't afford the cost of a regrowth treatment? This cybernetic limb has you covered! Just have the nerve interface installed on the arm or leg's stump and let the machinery do the rest. A week's training is required to regain full limb capability. Cybernetic arms and legs typically come complete with faux-skin, making them look slightly less unnatural. A cybernetic limb will never have tactile input like a natural arm or leg, but in all other regards, cybernetic limbs function like the real thing.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"iy3isMKVetZnBD8L"} {"name":"Hand Terminal","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":3,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"The ubiquitous hand terminal is a must-have for anyone! These handheld computers work as video and audio comms; are capable of IR and wireless connections; have an inbuilt camera, microphone and GPS; play games; do basic calculations; connect to the net; and interface with most common AR implants and glasses. Most come with both voice and touchscreen controls.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_computer.svg","effects":[],"_id":"juPjuak0WiII3VOY"} {"name":"Adrenaline Booster Gland","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":2,"neg":false,"mil":true,"software":0,"worn":false,"description":"A boost when you need it, the adrenaline booster gland is an artificial organ implanted near the kidneys. Typically triggered through a pre-programmed biological input such as saying a specific word, a tongue pattern or a series of finger taps, the implant gives a +2 bonus to Strength, Dexterity, Speed and Endurance actions for a number of rounds equal to the target's Endurance. This bonus also applies to Strength-based damage, Defense and action order. Activating the gland is an interact action. After its primary effects wear off, the user increases her Fatigue consequence a severity, because the after-effects of the gland leave her shaking and weakened. The gland cannot be used for another 24 hours because it has to remanufacture its artificial adrenaline.","quantity":0,"costrating":9,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"kEvGZ3xMy2Xtscud"} -{"name":"Baton","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Barons are a tried-and-true classic when it comes to dealing out blows with a minimum of lethal force. Favored as a control weapon by light security forces the world over, it never hurts to have a baton at your side. Baton telescopes for easy pocket storage. It is available in both solid colors and faux-wood.","quantity":0,"costrating":1,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"½Str+1L","damage_hearth":"Str×2+4L","damage_spade":"Str×3+6L","damage_diamond":"Str+2L","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"l3LUBCnICPAknvnr"} {"name":"Unitech “Sunspot” C3 Vac Suit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":5,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"The Unitech “Sunspot” C3 Vac Suit is the spacer's best friend. Capable of operating for up to six hours in complete vacuum and in a variety of pressure, radiation and atmospheric conditions, this space suit is truly the first in its class. Compressed air canisters connect at both hips, providing redundancy and allowing changes in the field. AR link included.","quantity":0,"costrating":5,"defensive":0,"containerid":"","bulky":1,"dr":3,"gel":0,"reflect":0,"str":0,"vac":true},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/generic_armor.svg","effects":[],"_id":"lEzknag9lK4IYoki"} {"name":"Xenocom “Infinity” PowerShell Armor","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":15,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":true,"description":"Go beyond the usual limits with Xenocom “Infinity” Powershell Armor. The go-to choice of security professions for more than three decades, Infinity power armor is rugged and reliable. Tailor-made for field maintenance and repair, the Infinity comes with HUD, AR link, a six-hour air supply, left and right arm weapon mounts and internal power cell. Holster points optional. Comes in a variety of colors.","quantity":0,"costrating":14,"defensive":0,"containerid":"","bulky":3,"dr":20,"gel":0,"reflect":0,"str":5,"vac":true},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/generic_armor.svg","effects":[],"_id":"lGIITGW9DqxsjvBd"} {"name":"P&W Wide-Trim Designer Coverjack","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"armor","data":{"big":0,"computer":0,"conceal":2,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"Just because you need to wear armor doesn't mean you have to sacrifice style. With the Pfeiffer & Wu Wide-Trim Designer Coverjack you can have your cake and eat it, too! Designed for maximum comfort and discrete protection, all P&W coverjacks can pass as normal suits upon both visual and infrared inspection. This comes in a variety of designer colors! Power tie optional.","quantity":0,"costrating":4,"defensive":0,"containerid":"","bulky":0,"dr":3,"gel":0,"reflect":0,"str":0,"vac":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/armors/generic_armor.svg","effects":[],"_id":"laY2NPjRpuJ4N3ud"} {"name":"Chameleon Suit","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"You'll blend right in with this chameleon suit! This tight-fitting suit changes color as the wearer moves, similar to a chameleon. This aids the wearer's attempts at stealth, but it does not fool infrared detection. It counts as a superior tool (+2) for stealth against simple, unaided observation.","quantity":0,"costrating":7,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"lpLONx41Dmd7wKzr"} {"name":"Voice Mask","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Studies show that the largest cause of disguise failure is identification by voice. Change your voice today! This device attaches to the wearer's throat, usually sitting on the shoulder or neck, beneath the collar. Once attached and turned on, it will distort the wearer's voice so as to be unrecognizable. Other people's voices can be mimicked, but this requires both a sample audio recording of the speaker to be mimicked, and calibration with the wearer's voice—an Int/programming-10 flip. (Improvised)","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"lpPYNxyV3jH22nbk"} -{"name":"USD-1200 “Amazon” Light Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The rifle you need when you're on the go, the USD-1200 “Amazon” Light Rifle has been designed from the ground up for easy transportation and assembly. With balancing range, magazine capacity and ease of maintenance, the Amazon gets the job done. Satisfaction guaranteed. Some assembly required.","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"3M","damage_hearth":"12M","damage_spade":"18M","damage_diamond":"6M","hands":2,"pierce":0,"range":20,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"lsIbTfdKK0e19vfO"} -{"name":"USD-9300 Frag Grenade","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"The USD-9300 is the ultimate in frag grenade flexibility and reliability. It comes with two modes of operation: impact or timer. Simply arm the grenade and fling it at foes, or let it count down. The choice is yours!","quantity":0,"costrating":4,"defensive":0,"containerid":"","area":5,"autofire":0,"damage_club":"4M","damage_hearth":"16M","damage_spade":"24M","damage_diamond":"8M","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":true,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"m9YpVR3nCrLIfLQN"} {"name":"Data Chip","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Data chips: for when the net just won't cut it! Data chips are small silicate chips intended to transfer data physically between computers. They are often used when transferal over the net would be deemed insecure or where no local net is available. All data chips have a software rating. While data chips cannot run software as can a computer, they can store software up to the same rating. So, for example, a Data Chip 5 could store a Software 5 program or two Software 4 programs, etc. A data chip has a cost rating equal to the software rating.","quantity":0,"costrating":-1,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"mD6ucBx7dzEJe9hj"} -{"name":"Sinoex Monowhip XT","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"Critical Effect: When this critical effect is chosen, the monowhip does not break upon impact, as is normal. Crafted by the exotic materials experts at Sinoex, the Sinoex Monowhip XT is a coiled strand of near-monomolecular wire with a weight on the end held in a magnetized handle. Upon pressing a button, a power source in the handle causes the wire to uncoil and extend outward, providing the ideal cutting tool. Monowhips tear through armor like cardboard, but their limited tensile strength means they are typically one-use weapons, breaking after they successfully strike a target.","quantity":0,"costrating":5,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str×¼S","damage_hearth":"Str×¾S","damage_spade":"StrS","damage_diamond":"Str×½S","hands":1,"pierce":10,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"mQLJjG8uWn31Oyy6"} -{"name":"Xenocom L3 Machine Laspistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"The L3 Machine Laspistol is the latest military-grade laspistol from Xenocom. It's heavy-duty ionized battery contains enough charge for sustained fire, and its state of the art heat-sinks support the highest rates if automatic fire. Pick yours up and make the best decision you've ever made today!","quantity":0,"costrating":11,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"3M","damage_hearth":"12M","damage_spade":"18M","damage_diamond":"6M","hands":1,"pierce":0,"range":10,"reload":1,"shots":10,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"o56uRwUqBo9Cde5Z"} +{"_id":"nvrtcC4kl0oHb0LR","name":"USD-3200 “Valkyrie” Heavy Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The USD-3200 “Valkyrie” Heavy Rifle is a masterpiece of twenty-third century engineering, combined with sleek twenty-second century ascetics. Own the best-designed and best-looking heavy rifle on the market! It comes with two autofire settings and a designer gun case. Remember, Valkyrie means quality.","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearts":"14M","damage_spade":"21M","damage_diamond":"7M","hands":2,"pierce":0,"range":20,"reload":1,"shots":20,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[]} {"name":"Geiger-Counter","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":true,"description":"A trusted method of detecting radiation, this clip-on geiger-counter will also determine the intensity of the radiation exposure and keep a count of absorbed rads. It can be set to alert the wearer either visually through its integrated display or audibly with a series of clicking noises.","quantity":0,"costrating":3,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"q1Aeerg8EkEiPLRM"} {"name":"Chem-Sniff","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Sniff out trouble with this chem-sniff. This olfactory sensor is able to detect and recognize substances by smell, comparing them against a database of commonly known scents. While it is not useful in a vacuum, underwater or against anything in a sealed environment, most everything otherwise leaves an olfactory signature that can be recorded and recognized again.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"qwYIVJSr2CcAwof7"} -{"name":"USD-3200 “Valkyrie” Heavy Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The USD-3200 “Valkyrie” Heavy Rifle is a masterpiece of twenty-third century engineering, combined with sleek twenty-second century ascetics. Own the best-designed and best-looking heavy rifle on the market! It comes with two autofire settings and a designer gun case. Remember, Valkyrie means quality.","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"3M","damage_hearth":"14M","damage_spade":"21M","damage_diamond":"7M","hands":2,"pierce":0,"range":20,"reload":1,"shots":20,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"rY5kH9T9h2PzxHXa"} +{"name":"Gun Arm Implant","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":4,"container":0,"implant":1,"neg":false,"mil":false,"software":0,"worn":false,"description":"Have your safety well in hand, or at least in arm, with this gun arm implant! Included is a concealed ballistic gun barrel and trigger mechanism, which embeds beneath the skin into the flesh of the forearm. The gun can be programmed to fire with a simple flick of the arm, giving the element of surprise. It holds three shots. Reloading requires opening a compartment in the arm and loading each bullet individually.","quantity":0,"costrating":7,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"2M","damage_hearts":"8M","damage_spade":"12M","damage_diamond":"4M","hands":1,"pierce":0,"range":10,"reload":2,"shots":3,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"rjamPY5gfyjxpzf6"} {"name":"Binoculars","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Don't let your enemies get close; spot them from afar with these binoculars! Binoculars are a tried and true method of seeing things at large distances. These binoculars are good for ×4 magnification, giving a +2 bonus to see objects at great distances.","quantity":0,"costrating":2,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"rqamf48CZsH7KfzW"} {"name":"Biometric Cracker","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"This device quickly cycles through biometric input used to open locks or secure areas. It is capable of imitating the input for fingerprints, irises, DNA and other common biometric methods. Wiring this device first into the biometric reader is required because it only fakes biometric data in digital form. It does not fake actual physical fingers or irises. This device counts as sufficient tools when surpassing such a device and is typically capable of bypassing compatible devices in a matter of seconds.","quantity":0,"costrating":7,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"sA4J47BrzPlhMnOR"} -{"name":"USD-840L “Horus” Heavy Laspistol","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"The USD-840L “Horus” Heavy Laspistol is simply best heavy laspistol on the market. Designed from heavy-duty metal alloys and with anti-heat ceramic plating, the Horus outshoots the competition. Plus, the Horus' state of the art battery packs are guaranteed to hold the charges for months without unwanted discharge.","quantity":0,"costrating":8,"defensive":0,"containerid":"","area":0,"autofire":2,"damage_club":"2M","damage_hearth":"10M","damage_spade":"15M","damage_diamond":"5M","hands":1,"pierce":0,"range":10,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"tAizFnum5ufMQfvi"} +{"name":"Power Tool","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Some repair and constructions tasks require more than a simple toolkit. For those, try a dedicated power tool! Power tools come in a variety of shapes and sizes from chainsaws to magnetic drills. In a pinch, they can even serve as an improvised hand-to-hand weapon! (See the damage listing above.). Count as an improvised weapon.","quantity":0,"costrating":4,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"Str0.5M","damage_hearts":"Str2M","damage_spade":"Str3M","damage_diamond":"StrM","hands":1,"pierce":0,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"melee","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/power-tool.svg","effects":[],"_id":"t35TlVvh13UJbk7m"} {"name":"Expert System (Ultimate)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":9,"worn":false,"description":"Know your knowns and your known unknowns! An expert system is software that provides a database of knowledge and useful advice on a given topic. This is often designed to hook in to AR software, projecting useful tags and other information right before the user's eyes, aiding in a variety of tasks. Every expert software is designed to support one skill, or sometimes a specific experience in a skill. By taking a moment (an interact action in combat) the user can query the expert system for help on this skill. Mechanically this works as if the expert system is making a group effort action supporting the user, with a total based on the quality of the software (see page XXX). An action may only benefit from one expert system at a time. Expert software comes in four qualities: basic (total 10), pro (total 12), deluxe (total 14) and ultimate (total 16). Example: Stan is using a pro expert system to help him with ship repairs. He makes the required Dex/mechanic flip and gets a total of 9, not yet taking into account the expert system. Since expert systems work exactly like secondary characters in a group effort action, and since the expert system's total—12 for pro quality—is higher than Stan's total, he gets a +2 bonus to his action. This gives him a final total of 11.","quantity":0,"costrating":10,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"uCGmNGm6JaBDrW3M"} -{"name":"Plasma Cutter","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"A favorite in heavy duty construction work, ship repair and emergency boarding actions, this plasma cutter cuts right through even the toughest metals and ceramics. The airlock busted? Just cut right through the hull! A plasma cutter can also be used as an improvised weapon in a pinch (see the damage listing above). Count as an improvised weapon.","quantity":0,"costrating":6,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"1M","damage_hearth":"6M","damage_spade":"9M","damage_diamond":"3M","hands":1,"pierce":3,"range":0,"reload":1,"shots":0,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"v51T7RAbTQ7Xu2Ka"} -{"name":"Xenocom X8 Machine Rifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":true,"software":0,"worn":false,"description":"When you want maximum staying power, you want the Xenocom X8 Machine Rifle. Combining the best in range and magazine capacity with the best in full-auto heat suppression technology, the Xenocom X8 is second to none. Pair with our range finder or tracer round extras for the ultimate military battlefield kit.","quantity":0,"costrating":10,"defensive":0,"containerid":"","area":0,"autofire":3,"damage_club":"4M","damage_hearth":"16M","damage_spade":"24M","damage_diamond":"8M","hands":2,"pierce":0,"range":20,"reload":1,"shots":30,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"vItuyxzQjpXpeLcf"} {"name":"Expert System (Pro)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":5,"worn":false,"description":"Know your knowns and your known unknowns! An expert system is software that provides a database of knowledge and useful advice on a given topic. This is often designed to hook in to AR software, projecting useful tags and other information right before the user's eyes, aiding in a variety of tasks. Every expert software is designed to support one skill, or sometimes a specific experience in a skill. By taking a moment (an interact action in combat) the user can query the expert system for help on this skill. Mechanically this works as if the expert system is making a group effort action supporting the user, with a total based on the quality of the software (see page XXX). An action may only benefit from one expert system at a time. Expert software comes in four qualities: basic (total 10), pro (total 12), deluxe (total 14) and ultimate (total 16). Example: Stan is using a pro expert system to help him with ship repairs. He makes the required Dex/mechanic flip and gets a total of 9, not yet taking into account the expert system. Since expert systems work exactly like secondary characters in a group effort action, and since the expert system's total—12 for pro quality—is higher than Stan's total, he gets a +2 bonus to his action. This gives him a final total of 11.","quantity":0,"costrating":6,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"vJTVVLZ48JtFXPsE"} {"name":"Encryption System (Deluxe)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":7,"worn":false,"description":"Keep your private life private. Encryption is necessary for any sort of secure transaction using broadcast communication, such as on the net or through radio comms. Most computers come with basic built-in encryption methods, but for those who want real security, bolstered encryption software is a no-brainer. Difficulty of breaking encryption scales with processing requirements. Encryption systems come in a variety of different qualities, with differing processing requirements (see page XXX).","quantity":0,"costrating":8,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_software.svg","effects":[],"_id":"vLoahjL5ZprVNg4M"} {"name":"Regenasone","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":true,"mil":false,"software":0,"worn":false,"description":"Get better faster with Regenasone. A potent healing aid, Regenasone speeds cellular regeneration within the body. If administered once a day, a dose of Regenasone reduces the time it takes to heal wounds from one week down to one day. This, however, leaves the recipient feeling hazy and lethargic. After Regenasone is administered and for the day afterward, the recipient increases her Fatigue consequence a severity. Pack of 10 doses.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"voJMdG5rlzSG9ggs"} @@ -101,3 +96,4 @@ {"name":"Magnetic Grapnel","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Get to unreached heights fast. Try a magnetic grapnel today! This coiled grapnel gun can almost silently fire a magnetic grapnel, with a cord up to 30 meters. It can then be set to recoil itself, pulling the user towards its target at the rate of 5 meters per round. Hitting the target is a Dex/guns flip. The cord can safely hold up to 200 kg. If trying to load the cord with more than this, have the GM flip a card. If it’s a club, the cord breaks. Flip an additional card for every increment of 200 kg.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"xSkUZRdZbOdS2hsL"} {"name":"Medikit (Basic)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Treat nagging injuries on the go! The medikit contains basic medical tools, useful for treating all major or simple injuries, including adhesive spray, antibiotics, a variety of ointments, an oxygen mask and sutures. This counts as sufficient tools for first aid or improvised equipment (-2) for minor surgery. Also, consider our superior quality medikits, which count as superior tools (+2) to first aid! Contains 10 uses.","quantity":0,"costrating":4,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"ym7LLW7f7XaG7Msv"} {"name":"Survival Kit (Basic)","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"gear","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Never get caught in the great outdoors without one! This robust kit contains water purification tablets, a set of disposable tests for food safety, a variety of ointments, food tablets, a small knife, a lighter, a signal flare and other useful odds and ends. It counts as sufficient tools for surviving in the wild, provided the user already has an air supply. Also consider our superior quality survival kits, which count as superior tools (+2). Contains 10 uses. Each use is good for one person for one day.","quantity":0,"costrating":5,"defensive":0,"containerid":""},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/gears/generic_gear.svg","effects":[],"_id":"yrG3Zcmct7DX4OwN"} +{"name":"USD-2280L “Zeus” Light Lasrifle","permission":{"default":0,"pJLHbu8WlBVyfXG4":3},"type":"weapon","data":{"big":0,"computer":0,"conceal":0,"container":0,"implant":0,"neg":false,"mil":false,"software":0,"worn":false,"description":"Perfect for use on spaceships or stations across the system, the USD-2280L “Zeus” Light Lasrifle is jam-packed with all the essentials needed for successful space security. From its sleek, curved barrel to its finger-molded grip, the Zeus is a miracle for the professional security worker.","quantity":0,"costrating":8,"defensive":0,"containerid":"","area":0,"autofire":0,"damage_club":"3M","damage_hearts":"12M","damage_spade":"18M","damage_diamond":"6M","hands":2,"pierce":0,"range":20,"reload":1,"shots":5,"stun":false,"thrown":false,"reach":false,"shallow":false,"spread":false,"category":"ballistic","equiped":false},"flags":{},"img":"systems/foundryvtt-shadows-over-sol/img/icons/weapons/generic_weapon.svg","effects":[],"_id":"zMiaz2HLsddO22H3"} diff --git a/system.json b/system.json index 72f3527..813e155 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "name": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", - "version": "0.1.11", + "version": "0.1.12", "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", -- 2.35.3 From 9d610215d4dedcd9a53885b604d212cff9ec43f6 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Fri, 12 Mar 2021 20:57:41 +0100 Subject: [PATCH 14/47] #6 : Skill experience management --- README.md | 3 -- img/icons/.directory | 3 +- img/icons/skill_xp.svg | 1 + module/actor.js | 13 +++++++-- module/item-sheet.js | 20 ++++++++++++- module/sos-flip-dialog.js | 18 ++++++++++-- module/sos-utility.js | 2 +- system.json | 4 +-- template.json | 2 +- templates/dialog-flip.html | 12 ++++++++ templates/item-skill-sheet.html | 16 +++++++++-- templates/item-skillexperience-sheet.html | 34 +++++++++++++++++++++++ 12 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 img/icons/skill_xp.svg create mode 100644 templates/item-skillexperience-sheet.html diff --git a/README.md b/README.md index 65cf797..d8efa95 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,7 @@ # FoundryVTT - Shadows Over Sol -**STILL IN ALPHA, DO NOT USE IT !!** - Shadows Over Sol ( https://www.tabcreations.com/shadows-over-sol/ ) implementation for FoundryVTT . This system is developed under authorization of Tab Creations. Shadows Over Sol is Property of Tab Creations, all related copyright belongs to Tab Creations. -**STILL IN ALPHA, DO NOT USE IT !!** diff --git a/img/icons/.directory b/img/icons/.directory index 8a192c3..86db330 100644 --- a/img/icons/.directory +++ b/img/icons/.directory @@ -1,5 +1,6 @@ [Dolphin] -Timestamp=2021,3,12,15,41,28.086 +SortRole=creationtime +Timestamp=2021,3,12,18,53,49.303 Version=4 ViewMode=1 VisibleRoles=Details_text,Details_size,Details_modificationtime,Details_creationtime,CustomizedDetails diff --git a/img/icons/skill_xp.svg b/img/icons/skill_xp.svg new file mode 100644 index 0000000..9e985d1 --- /dev/null +++ b/img/icons/skill_xp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/module/actor.js b/module/actor.js index 9db2a28..ef4d45f 100644 --- a/module/actor.js +++ b/module/actor.js @@ -160,6 +160,11 @@ export class SoSActor extends Actor { return Math.ceil( (this.data.data.stats.strength.value + this.data.data.stats.endurance.value) / 2) + this.data.data.scores.wound.bonusmalus; } + /* -------------------------------------------- */ + getSkillExperience( skillName ) { + return this.data.items.filter( item => item.type == 'skillexperience' && item.data.skill == skillName); + } + /* -------------------------------------------- */ async wornObject( itemID) { let item = this.getOwnedItem(itemID); @@ -262,13 +267,15 @@ export class SoSActor extends Actor { selectedStat: 'strength', consequencesList: duplicate( this.getApplicableConsequences() ), wounds: duplicate( this.data.data.wounds), + skillExperienceList: this.getSkillExperience( skill.name), skill: duplicate(skill), actor: this, modifierList: SoSUtility.fillRange(-10, +10), tnList: SoSUtility.fillRange(6, 20), malusConsequence: 0, bonusConsequence: 0, - woundMalus: 0 + woundMalus: 0, + bonusSkillXP: 0 } flipData.statList['nostat'] = { label: "No stat (ie defaulting skills)", value: 0, cardsuit: "none" } let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/dialog-flip.html', flipData); @@ -297,6 +304,7 @@ export class SoSActor extends Actor { target: target, selectedStat: selectedStatName, consequencesList: duplicate( this.getApplicableConsequences() ), + skillExperienceList: this.getSkillExperience( skill.name), wounds: duplicate( this.data.data.wounds), skill: duplicate(skill), actor: this, @@ -304,7 +312,8 @@ export class SoSActor extends Actor { tnList: SoSUtility.fillRange(6, 20), malusConsequence: 0, bonusConsequence: 0, - woundMalus: 0 + woundMalus: 0, + bonusSkillXP: 0 } console.log(flipData); diff --git a/module/item-sheet.js b/module/item-sheet.js index c480b1a..cfb5067 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -45,7 +45,12 @@ export class SoSItemSheet extends ItemSheet { async getData() { let data = super.getData(); data.isGM = game.user.isGM; - + if ( data.item.type == 'skillexperience') { + data.skillList = await SoSUtility.loadCompendiumNames("foundryvtt-shadows-over-sol.skills"); + } + if ( data.item.type == 'skill' && this.object.options?.actor) { + data.skillExperienceList = this.object.options.actor.getSkillExperience( data.item.name ); + } return data; } @@ -57,6 +62,19 @@ export class SoSItemSheet extends ItemSheet { // Everything below here is only needed if the sheet is editable if (!this.options.editable) return; + // Update Inventory Item + html.find('.item-edit').click(ev => { + const li = $(ev.currentTarget).parents(".item"); + const item = this.object.options.actor.getOwnedItem(li.data("item-id")); + console.log("ITEM", item, li.data("item-id"), li); + item.sheet.render(true); + }); + // Update Inventory Item + html.find('.item-delete').click(ev => { + const li = $(ev.currentTarget).parents(".item"); + this.object.options.actor.deleteOwnedItem( li.data("item-id") ).then( this.render(true)); + //this.render(true); + }); } diff --git a/module/sos-flip-dialog.js b/module/sos-flip-dialog.js index 77ad360..e13e2b2 100644 --- a/module/sos-flip-dialog.js +++ b/module/sos-flip-dialog.js @@ -43,6 +43,7 @@ export class SoSFlipDialog extends Dialog { scoreBase += this.flipData.malusConsequence; scoreBase += this.flipData.bonusConsequence; scoreBase += this.flipData.woundMalus; + scoreBase += this.flipData.bonusSkillXP; $('#wound-malus').text(this.flipData.woundMalus); $('#score-base').text( scoreBase); } @@ -74,7 +75,18 @@ export class SoSFlipDialog extends Dialog { }); } - + /* -------------------------------------------- */ + updateSkillXPBonus(event) { + this.flipData.skillXPSelected = $('#skillXPBonus').val(); + let bonusSkillXP = 0; + for (let skillXPId of this.flipData.skillXPSelected) { + bonusSkillXP += 1; + } + $('#skillxp-bonus').text(bonusSkillXP); + this.flipData.bonusSkillXP = bonusSkillXP; + this.updateScoreBase(); + } + /* -------------------------------------------- */ updateConsequenceMalus(event) { this.flipData.consequencesSelected = $('#consequenceSelectMalus').val(); @@ -122,7 +134,9 @@ export class SoSFlipDialog extends Dialog { html.find('#statSelect').change((event) => { this.updateFlip(dialog.flipData ); } ); - + html.find('#skillXPBonus').change((event) => { + this.updateSkillXPBonus( event ); + } ); html.find('#consequenceSelectMalus').change((event) => { this.updateConsequenceMalus( event ); } ); diff --git a/module/sos-utility.js b/module/sos-utility.js index ea96998..c855925 100644 --- a/module/sos-utility.js +++ b/module/sos-utility.js @@ -34,7 +34,7 @@ export class SoSUtility extends Entity { static fillRange (start, end) { return Array(end - start + 1).fill().map((item, index) => start + index); } - + /* -------------------------------------------- */ static onSocketMesssage( msg ) { if( !game.user.isGM ) return; // Only GM diff --git a/system.json b/system.json index 813e155..0145d50 100644 --- a/system.json +++ b/system.json @@ -2,11 +2,11 @@ "name": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", - "version": "0.1.12", + "version": "0.1.13", "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", - "templateVersion": 22, + "templateVersion": 23, "author": "LeRatierBretonnien", "esmodules": [ "module/sos-main.js" ], "styles": ["styles/simple.css"], diff --git a/template.json b/template.json index 1d46f73..ef19d57 100644 --- a/template.json +++ b/template.json @@ -145,7 +145,7 @@ }, "Item": { "types": ["gear", "weapon", "armor", "container", "skill", "language", "weakness", "geneline", - "subculture", "consequence", "action", "injury", "malady", "vehicle" ], + "subculture", "consequence", "action", "injury", "malady", "vehicle", "skillexperience"], "templates": { "commongear": { "big": 0, diff --git a/templates/dialog-flip.html b/templates/dialog-flip.html index f430505..957bd91 100644 --- a/templates/dialog-flip.html +++ b/templates/dialog-flip.html @@ -27,6 +27,18 @@ {{/if}}
    +
    +
    + +

    Skill XP Bonus : 0

    +
    +
    -
  • - +
      +
    • + Experiences list : +
    • + {{#each skillExperienceList as |skillXP key|}} +
    • + {{skillXP.name}} +
      + + +
      +
    • + {{/each}} +
    {{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
    diff --git a/templates/item-skillexperience-sheet.html b/templates/item-skillexperience-sheet.html new file mode 100644 index 0000000..8d8562d --- /dev/null +++ b/templates/item-skillexperience-sheet.html @@ -0,0 +1,34 @@ +
    +
    + +
    +

    +
    +
    + + {{!-- Sheet Body --}} +
    + +
    +
    + +
    + +
    +
    +
    + +
    + {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} +
    +
    +
    + +
    +
    -- 2.35.3 From 2353ba5ff9c57fe676a0553a3e1cfdc382a10db2 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sat, 13 Mar 2021 22:33:24 +0100 Subject: [PATCH 15/47] #8 - Weapn/armor management --- module/actor.js | 18 ++++++++++++- module/item-sheet.js | 2 -- module/sos-card-deck.js | 14 +++++++--- module/sos-utility.js | 42 +++++++++++++++++++++++------- templates/chat-damage-taken.html | 3 +++ templates/chat-nodamage-taken.html | 1 + 6 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 templates/chat-nodamage-taken.html diff --git a/module/actor.js b/module/actor.js index ef4d45f..06cb815 100644 --- a/module/actor.js +++ b/module/actor.js @@ -374,13 +374,19 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ async applyWounds( flipData ) { + if ( flipData.damageStatus == 'no_damage') { + let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-nodamage-taken.html', flipData ); + ChatMessage.create( { content: html, whisper: [ChatMessage.getWhisperRecipients(this.name), ChatMessage.getWhisperRecipients("GM") ] } ); + return; + } + let wounds = duplicate(this.data.data.wounds); for (let wound of flipData.woundsList ) { if (wound == 'L' ) wounds.light += 1; if (wound == 'M' ) wounds.moderate += 1; if (wound == 'S' ) wounds.severe += 1; if (wound == 'C' ) wounds.critical += 1; - } + } // Compute total let sumWound = wounds.light + (wounds.moderate*2) + (wounds.severe*3) + (wounds.critical*4); let currentWounds = duplicate(this.data.data.scores.currentwounds); @@ -391,6 +397,16 @@ export class SoSActor extends Actor { await this.updateOwnedItem( { _id: bleeding._id, 'data.severity': newSeverity}); flipData.isBleeding = newSeverity; } + // Stun consequence + if ( flipData.nbStun > 0) { + let stun = this.data.items.find( item => item.type == 'consequence' && item.name == 'Sun'); + let newSeverity = stun.severity; + for(i=0; i { const li = $(ev.currentTarget).parents(".item"); const item = this.object.options.actor.getOwnedItem(li.data("item-id")); - console.log("ITEM", item, li.data("item-id"), li); item.sheet.render(true); }); // Update Inventory Item html.find('.item-delete').click(ev => { const li = $(ev.currentTarget).parents(".item"); this.object.options.actor.deleteOwnedItem( li.data("item-id") ).then( this.render(true)); - //this.render(true); }); } diff --git a/module/sos-card-deck.js b/module/sos-card-deck.js index 91c460f..3fef1ba 100644 --- a/module/sos-card-deck.js +++ b/module/sos-card-deck.js @@ -272,10 +272,16 @@ export class SoSCardDeck { flipData.damageCardsuit = flipData.cardSlot[flipData.cardSlotIndex].cardsuit; let damageKey = 'damage_'+ flipData.damageCardsuit; flipData.damageString = flipData.weapon.data[damageKey]; - let damageRegexp = flipData.damageString.match( /(\d*)([LMSC])/i ); - flipData.damageValue = damageRegexp[1]; - flipData.damageSeverity = damageRegexp[2]; - + if (flipData.damageString.includes('Str') ) { + let damageRegexp = flipData.damageString.match( /Str([\d])?\+?([\d])?([LMSC])/i ); + flipData.damageValue = (flipData.actor.data.data.stats.strength.value * Number(damageRegexp[1]?damageRegexp[1]:1)) + Number(damageRegexp[2]?damageRegexp[2]:0); + flipData.damageSeverity = damageRegexp[3]; + } else { + let damageRegexp = flipData.damageString.match( /(\d*)([LMSC])/i ); + flipData.damageValue = damageRegexp[1]; + flipData.damageSeverity = damageRegexp[2]; + } + // Now process damage if ( flipData.target) { if ( game.user.isGM ) { // Direct access diff --git a/module/sos-utility.js b/module/sos-utility.js index c855925..137972c 100644 --- a/module/sos-utility.js +++ b/module/sos-utility.js @@ -261,8 +261,20 @@ export class SoSUtility extends Entity { return; } } + + // DR management + let armor = flipData.target.actor.data.items.find( item => item.type == 'armor' && item.data.worn); + flipData.armorDR = armor ? armor.data.dr : 0; + flipData.armorGel = armor ?armor.data.gel : 0; + flipData.armorReflect = armor ? armor.data.reflect : 0; + let dr = flipData.target.actor.data.data.scores.dr.value + flipData.armorDR; + if (flipData.weapon.data.category == 'ballistic') { + dr += flipData.armorGel; + } + if (flipData.weapon.data.category == 'laser') { + dr += flipData.armorReflect; + } - let dr = flipData.target.actor.data.data.scores.dr.value; let shock = flipData.target.actor.data.data.scores.shock.value || 1; let defenseCritical = flipData.target.actor.data.data.scores.defense.critical; flipData.damageStatus = 'apply_damage'; @@ -274,25 +286,35 @@ export class SoSUtility extends Entity { if ( flipData.damageValue < dr) { if (flipData.damageValue < dr / 2) { flipData.damageStatus = "no_damage"; - // TODO : No damage ! + flipData.damageReason = "Damage are lesser than DR/2"; } else { flipData.damageSeverity = this.decreaseSeverity(flipData.damageSeverity ); if ( flipData.damageSeverity == 'N') { flipData.damageStatus = "no_damage"; + flipData.damageReason = "Severity decreased to nothing"; } } } // Shock management flipData.woundsList = []; - if ( flipData.damageValue >= shock) { - let incSeverity = Math.floor(flipData.damageValue / shock); - for (let i=0; i= shock ) { + flipData.nbStun = Math.floor(flipData.damageValue / shock); + } + } else { + if ( flipData.damageValue >= shock ) { + let incSeverity = Math.floor(flipData.damageValue / shock); + for (let i=0; i{{defenderName}} is bleeding with severity {{isBleeding}}. He will have a new {{isBleeding}} wound at the end of the round ! {{/if}} + {{#if isStun}} + + {{/if}}
    diff --git a/templates/chat-nodamage-taken.html b/templates/chat-nodamage-taken.html new file mode 100644 index 0000000..ecd19db --- /dev/null +++ b/templates/chat-nodamage-taken.html @@ -0,0 +1 @@ +

    {{defenderName}}: no damages received !

    -- 2.35.3 From baf84bee356f1a05ec355330ed2e596c17e14ad5 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Mon, 22 Mar 2021 21:02:56 +0100 Subject: [PATCH 16/47] #7 - Manage container --- module/actor-sheet.js | 42 +++++++++++++++++++++++++++++--------- module/actor.js | 20 ++++++++++++++++++ module/sos-utility.js | 12 +++++++++++ styles/simple.css | 3 +++ system.json | 2 +- templates/actor-sheet.html | 14 ++++++++++++- 6 files changed, 81 insertions(+), 12 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 18e1bc8..a47920e 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -31,16 +31,35 @@ export class SoSActorSheet extends ActorSheet { data.data.deckSize = this.actor.getDeckSize(); data.data.skills = this.actor.data.items.filter( item => item.type == 'skill').sort( (a, b) => { - if ( a.name > b.name ) return 1; - return -1; - }); + if ( a.name > b.name ) return 1; + return -1; + }); + data.data.skill1 = data.data.skills.slice(0, Math.ceil(data.data.skills.length/2) ) data.data.skill2 = data.data.skills.slice(Math.ceil(data.data.skills.length/2), data.data.skills.length ) data.data.consequences = this.actor.data.items.filter( item => item.type == 'consequence').sort( (a, b) => { if ( a.name > b.name ) return 1; return -1; }); - data.data.gears = this.actor.data.items.filter( item => item.type == 'gear').concat( this.actor.data.items.filter( item => item.type == 'container') ); + data.data.gears = this.actor.data.items.filter( item => item.type == 'gear').concat( this.actor.data.items.filter( item => item.type == 'container') ); + + // Build the gear tree + data.data.gearsRoot = data.data.gears.filter(item => item.data.containerid == ""); + for ( let container of data.data.gearsRoot) { + if ( container.type == 'container') { + container.data.contains = [] + container.data.containerEnc = 0; + for (let gear of data.data.gears) { + if ( gear.data.containerid == container._id) { + container.data.contains.push( gear ); + if ( !gear.data.neg && !gear.data.software ) { + container.data.containerEnc += (gear.big > 0) ? gear.big : 1; + } + } + } + } + } + data.data.weapons = this.actor.data.items.filter( item => item.type == 'weapon'); data.data.armors = this.actor.data.items.filter( item => item.type == 'armor'); data.data.totalEncumbrance = SoSUtility.computeEncumbrance(this.actor.data.items); @@ -57,16 +76,11 @@ export class SoSActorSheet extends ActorSheet { data.data.weaknessList = this.actor.data.items.filter( item => item.type == 'weakness'); data.data.geneline = this.actor.data.items.find( item => item.type == 'geneline'); data.data.editStatSkill = this.options.editStatSkill; - console.log("stats", data); + //console.log("stats", data); return data; } - /* -------------------------------------------- */ - async _onDrop(event) { - super._onDrop(event); - } - /* -------------------------------------------- */ /** @override */ activateListeners(html) { @@ -164,6 +178,14 @@ export class SoSActorSheet extends ActorSheet { } + /* -------------------------------------------- */ + async _onDrop(event) { + let toSuper = await SoSUtility.processItemDropEvent(this, event); + if ( toSuper) { + super._onDrop(event); + } + } + /* -------------------------------------------- */ /** @override */ setPosition(options = {}) { diff --git a/module/actor.js b/module/actor.js index 06cb815..f0ffc54 100644 --- a/module/actor.js +++ b/module/actor.js @@ -372,6 +372,26 @@ export class SoSActor extends Actor { this.checkDeath(); } + /* -------------------------------------------- */ + async addObjectToContainer( itemId, containerId ) { + let container = this.data.items.find( item => item._id == containerId && item.type == 'container'); + let object = this.data.items.find( item => item._id == itemId ); + if ( container ) { + if ( object.type == 'container') { + ui.notifications.warn("Only 1 level of container... sorry"); + return + } + let alreadyInside = this.data.items.filter( item => item.data.containerid && item.data.containerid == containerId); + if ( alreadyInside.length >= container.data.container ) { + ui.notifications.warn("Container is already full !"); + } else { + await this.updateOwnedItem( { _id: object._id, 'data.containerid':containerId }); + } + } else if ( object && object.data.containerid) { // remove from container + await this.updateOwnedItem( { _id: object._id, 'data.containerid':"" }); + } + } + /* -------------------------------------------- */ async applyWounds( flipData ) { if ( flipData.damageStatus == 'no_damage') { diff --git a/module/sos-utility.js b/module/sos-utility.js index 137972c..e5841d4 100644 --- a/module/sos-utility.js +++ b/module/sos-utility.js @@ -382,4 +382,16 @@ export class SoSUtility extends Entity { defender.applyWounds( flipData ); } + /* -------------------------------------------- */ + static async processItemDropEvent(actorSheet, event) { + let dragData = JSON.parse(event.dataTransfer.getData("text/plain")); + let dropID = $(event.target).parents(".item").attr("data-item-id"); // Only relevant if container drop + let objectID = dragData.id || dragData.data._id; + //console.log("drag/drop", dragData, actorSheet.actor._id, dropID, objectID); + if (dragData.type == 'Item' && dropID) { + actorSheet.actor.addObjectToContainer(objectID, dropID ); + } + return true; + } + } \ No newline at end of file diff --git a/styles/simple.css b/styles/simple.css index c619063..5da1a63 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -550,6 +550,9 @@ ul, li { .alternate-list > .list-item:nth-child(odd) { background: rgb(160, 130, 100, 0.05); } +.list-item-margin1 { + margin-left: 1rem; +} .xp-level-up { margin: 0.125rem; box-shadow: inset 0px 0px 1px #00000096; diff --git a/system.json b/system.json index 0145d50..2729358 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "name": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", - "version": "0.1.13", + "version": "0.1.14", "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 6708958..63126aa 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -259,7 +259,7 @@

    Equipment/Gears

      - {{#each data.gears as |gear key|}} + {{#each data.gearsRoot as |gear key|}}
    • {{gear.name}} @@ -269,6 +269,18 @@
    • + {{/each}}
    -- 2.35.3 From e33c18a4b540d745af18a4dfb2725b2cca36f34d Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sat, 27 Mar 2021 15:15:40 +0100 Subject: [PATCH 17/47] Shadows over Sol --- system.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system.json b/system.json index 2729358..1e58e62 100644 --- a/system.json +++ b/system.json @@ -2,7 +2,7 @@ "name": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", - "version": "0.1.14", + "version": "1.0.0", "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", -- 2.35.3 From 8ab4c68924f45568d2575dc39b217400791a4c59 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sat, 22 May 2021 22:01:05 +0200 Subject: [PATCH 18/47] 0.8 branch --- system.json | 195 +++++++++++++++++++++++++--------------------------- 1 file changed, 94 insertions(+), 101 deletions(-) diff --git a/system.json b/system.json index 1e58e62..c213547 100644 --- a/system.json +++ b/system.json @@ -2,101 +2,21 @@ "name": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", - "version": "1.0.0", - "manifestPlusVersion": "1.0.0", - "minimumCoreVersion": "0.7.5", - "compatibleCoreVersion": "0.7.9", - "templateVersion": 23, "author": "LeRatierBretonnien", - "esmodules": [ "module/sos-main.js" ], - "styles": ["styles/simple.css"], - "background" : "img/ui/background01.webp", - "media": [ + "authors": [], + "url": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/", + "license": "LICENSE.txt", + "flags": {}, + "version": "2.0.0", + "minimumCoreVersion": "0.8.0", + "compatibleCoreVersion": "0.8.5", + "scripts": [], + "esmodules": [ + "module/sos-main.js" ], - "packs": [ - { - "name": "skills", - "label": "Skills", - "system": "foundryvtt-shadows-over-sol", - "module": "foundryvtt-shadows-over-sol", - "path": "./packs/skills.db", - "entity": "Item", - "tags" : [ "skill", "skills" ] - }, - { - "name": "consequences", - "label": "Consequences", - "system": "foundryvtt-shadows-over-sol", - "module": "foundryvtt-shadows-over-sol", - "path": "./packs/consequences.db", - "entity": "Item", - "tags" : [ "consequence", "Consequences" ] - }, - { - "name": "gears", - "label": "Gears", - "system": "foundryvtt-shadows-over-sol", - "module": "foundryvtt-shadows-over-sol", - "path": "./packs/gears.db", - "entity": "Item", - "tags" : [ "gear", "weapon", "armor" ] - }, - { - "name": "injuries", - "label": "Injuries", - "system": "foundryvtt-shadows-over-sol", - "module": "foundryvtt-shadows-over-sol", - "path": "./packs/injuries.db", - "entity": "Item", - "tags" : [ "injury" ] - }, - { - "name": "weaknesses", - "label": "Weaknesses", - "system": "foundryvtt-shadows-over-sol", - "module": "foundryvtt-shadows-over-sol", - "path": "./packs/weaknesses.db", - "entity": "Item", - "tags" : [ "weakness" ] - }, - { - "name": "languages", - "label": "Languages", - "system": "foundryvtt-shadows-over-sol", - "module": "foundryvtt-shadows-over-sol", - "path": "./packs/languages.db", - "entity": "Item", - "tags" : [ "language" ] - }, - { - "name": "combat-actions", - "label": "Combat Actions", - "system": "foundryvtt-shadows-over-sol", - "module": "foundryvtt-shadows-over-sol", - "path": "./packs/combat-actions.db", - "entity": "Item", - "tags" : [ "actions", "combat", "attack" ] - }, - { - "name": "genelines", - "label": "Genelines", - "system": "foundryvtt-shadows-over-sol", - "module": "foundryvtt-shadows-over-sol", - "path": "./packs/genelines.db", - "entity": "Item", - "tags" : [ "genelines", "genetic" ] - }, - { - "name": "subcultures", - "label": "Subcultures", - "system": "foundryvtt-shadows-over-sol", - "module": "foundryvtt-shadows-over-sol", - "path": "./packs/subcultures.db", - "entity": "Item", - "tags" : [ "subcultures", "cultures" ] - } + "styles": [ + "styles/simple.css" ], - "library": false, "languages": [ { "lang": "en", @@ -104,13 +24,86 @@ "path": "lang/en.json" } ], - "gridDistance": 5, - "gridUnits": "ft", - "primaryTokenAttribute": "", - "secondaryTokenAttribute": "", + "packs": [ + { + "name": "skills", + "label": "Skills", + "path": "./packs/skills.db", + "entity": "Item", + "system": "foundryvtt-shadows-over-sol", + "private": false + }, + { + "name": "consequences", + "label": "Consequences", + "path": "./packs/consequences.db", + "entity": "Item", + "system": "foundryvtt-shadows-over-sol", + "private": false + }, + { + "name": "gears", + "label": "Gears", + "path": "./packs/gears.db", + "entity": "Item", + "system": "foundryvtt-shadows-over-sol", + "private": false + }, + { + "name": "injuries", + "label": "Injuries", + "path": "./packs/injuries.db", + "entity": "Item", + "system": "foundryvtt-shadows-over-sol", + "private": false + }, + { + "name": "weaknesses", + "label": "Weaknesses", + "path": "./packs/weaknesses.db", + "entity": "Item", + "system": "foundryvtt-shadows-over-sol", + "private": false + }, + { + "name": "languages", + "label": "Languages", + "path": "./packs/languages.db", + "entity": "Item", + "system": "foundryvtt-shadows-over-sol", + "private": false + }, + { + "name": "combat-actions", + "label": "Combat Actions", + "path": "./packs/combat-actions.db", + "entity": "Item", + "system": "foundryvtt-shadows-over-sol", + "private": false + }, + { + "name": "genelines", + "label": "Genelines", + "path": "./packs/genelines.db", + "entity": "Item", + "system": "foundryvtt-shadows-over-sol", + "private": false + }, + { + "name": "subcultures", + "label": "Subcultures", + "path": "./packs/subcultures.db", + "entity": "Item", + "system": "foundryvtt-shadows-over-sol", + "private": false + } + ], + "system": [], + "dependencies": [], "socket": true, - "url": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/", - "manifest": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/-/raw/master/system.json", - "download": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/-/archive/master/foundryvtt-shadows-over-sol.zip", - "license": "LICENSE.txt" -} + "manifest": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/-/raw/dev_0.8/system.json", + "download": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/-/archive/dev_0.8/foundryvtt-shadows-over-sol.zip", + "protected": false, + "gridDistance": 5, + "gridUnits": "ft" +} \ No newline at end of file -- 2.35.3 From 6ebc11c51855b8539c1a22f873c7a1f57f96109b Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sat, 22 May 2021 23:20:23 +0200 Subject: [PATCH 19/47] Start 0.8 support --- module/actor-sheet.js | 76 ++++++++++++++++++------------- module/actor.js | 8 ++-- module/sos-main.js | 8 ++-- module/sos-utility.js | 34 ++++++++++++-- templates/actor-sheet.html | 92 +++++++++++++++++++------------------- 5 files changed, 130 insertions(+), 88 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index a47920e..d3f261e 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -23,34 +23,48 @@ export class SoSActorSheet extends ActorSheet { /* -------------------------------------------- */ getData() { - let data = super.getData(); - + const objectData = SoSUtility.data(this.object); + let formData = { + title: this.title, + id: objectData.id, + type: objectData.type, + img: objectData.img, + name: objectData.name, + editable: this.isEditable, + cssClass: this.isEditable ? "editable" : "locked", + data: foundry.utils.deepClone(this.object.data), + effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)), + limited: this.object.limited, + options: this.options, + owner: this.document.isOwner + }; + this.actor.checkDeck(); - data.data.edgecard = this.actor.getEdgesCard(); - data.data.deckSize = this.actor.getDeckSize(); + formData.edgecard = this.actor.getEdgesCard(); + formData.deckSize = this.actor.getDeckSize(); - data.data.skills = this.actor.data.items.filter( item => item.type == 'skill').sort( (a, b) => { + formData.skills = this.actor.data.items.filter( item => item.type == 'skill').sort( (a, b) => { if ( a.name > b.name ) return 1; return -1; }); - - data.data.skill1 = data.data.skills.slice(0, Math.ceil(data.data.skills.length/2) ) - data.data.skill2 = data.data.skills.slice(Math.ceil(data.data.skills.length/2), data.data.skills.length ) - data.data.consequences = this.actor.data.items.filter( item => item.type == 'consequence').sort( (a, b) => { + + formData.skill1 = formData.skills.slice(0, Math.ceil(formData.skills.length/2) ) + formData.skill2 = formData.skills.slice(Math.ceil(formData.skills.length/2), formData.skills.length ) + formData.consequences = this.actor.data.items.filter( item => item.type == 'consequence').sort( (a, b) => { if ( a.name > b.name ) return 1; return -1; }); - data.data.gears = this.actor.data.items.filter( item => item.type == 'gear').concat( this.actor.data.items.filter( item => item.type == 'container') ); + formData.gears = this.actor.data.items.filter( item => item.type == 'gear').concat( this.actor.data.items.filter( item => item.type == 'container') ); // Build the gear tree - data.data.gearsRoot = data.data.gears.filter(item => item.data.containerid == ""); - for ( let container of data.data.gearsRoot) { + formData.gearsRoot = formData.gears.filter(item => item.data.containerid == ""); + for ( let container of formData.gearsRoot) { if ( container.type == 'container') { container.data.contains = [] container.data.containerEnc = 0; for (let gear of data.data.gears) { - if ( gear.data.containerid == container._id) { + if ( gear.data.containerid == container.id) { container.data.contains.push( gear ); if ( !gear.data.neg && !gear.data.software ) { container.data.containerEnc += (gear.big > 0) ? gear.big : 1; @@ -60,25 +74,25 @@ export class SoSActorSheet extends ActorSheet { } } - data.data.weapons = this.actor.data.items.filter( item => item.type == 'weapon'); - data.data.armors = this.actor.data.items.filter( item => item.type == 'armor'); - data.data.totalEncumbrance = SoSUtility.computeEncumbrance(this.actor.data.items); - data.data.wounds = duplicate(this.actor.data.data.wounds); - data.data.isGM = game.user.isGM; - data.data.currentWounds = this.actor.computeCurrentWounds(); - data.data.totalWounds = this.actor.data.data.scores.wound.value; + formData.weapons = this.actor.data.items.filter( item => item.type == 'weapon'); + formData.armors = this.actor.data.items.filter( item => item.type == 'armor'); + formData.totalEncumbrance = SoSUtility.computeEncumbrance(this.actor.data.items); + formData.wounds = duplicate(this.actor.data.data.wounds); + formData.isGM = game.user.isGM; + formData.currentWounds = this.actor.computeCurrentWounds(); + formData.totalWounds = this.actor.data.data.scores.wound.value; - data.data.subcultureList = this.actor.data.items.filter( item => item.type == 'subculture'); - if ( data.data.subculture != "" ) { // background.subculture contains the main subculture ID - data.data.mainSubculture = data.data.subcultureList.find( subc => subc._id == data.data.subculture); + formData.subcultureList = this.actor.data.items.filter( item => item.type == 'subculture'); + if ( formData.subculture != "" ) { // background.subculture contains the main subculture ID + formData.mainSubculture = formData.subcultureList.find( subc => subc._id == data.data.subculture); } - data.data.languageList = this.actor.data.items.filter( item => item.type == 'language'); - data.data.weaknessList = this.actor.data.items.filter( item => item.type == 'weakness'); - data.data.geneline = this.actor.data.items.find( item => item.type == 'geneline'); - data.data.editStatSkill = this.options.editStatSkill; - //console.log("stats", data); + formData.languageList = this.actor.data.items.filter( item => item.type == 'language'); + formData.weaknessList = this.actor.data.items.filter( item => item.type == 'weakness'); + formData.geneline = this.actor.data.items.find( item => item.type == 'geneline'); + formData.editStatSkill = this.options.editStatSkill; - return data; + console.log("stats", formData); + return formData; } /* -------------------------------------------- */ @@ -94,7 +108,7 @@ export class SoSActorSheet extends ActorSheet { // Update Inventory Item html.find('.item-edit').click(ev => { const li = $(ev.currentTarget).parents(".item"); - const item = this.actor.getOwnedItem(li.data("item-id")); + const item = this.actor.items.get(li.data("item-id")); item.sheet.render(true); }); html.find('.item-equip').click(ev => { @@ -163,7 +177,7 @@ export class SoSActorSheet extends ActorSheet { const li = $(event.currentTarget).parents(".item"); const item = this.actor.getOwnedItem(li.data("item-id")); let severity = $(event.currentTarget).val(); - this.actor.updateOwnedItem( { _id: item._id, 'data.severity': severity}); + this.actor.updateOwnedItem( { id: item.id, 'data.severity': severity}); this.render(true); }); html.find('.lock-unlock-sheet').click((event) => { diff --git a/module/actor.js b/module/actor.js index f0ffc54..ce86f31 100644 --- a/module/actor.js +++ b/module/actor.js @@ -34,17 +34,19 @@ export class SoSActor extends Actor { return actor; } - data.items = []; + let items = []; let compendiumName = "foundryvtt-shadows-over-sol.skills"; if ( compendiumName ) { let skills = await SoSUtility.loadCompendium(compendiumName); - data.items = data.items.concat( skills ); + items = skills.map(i => i.toObject()); } compendiumName = "foundryvtt-shadows-over-sol.consequences"; if ( compendiumName ) { let consequences = await SoSUtility.loadCompendium(compendiumName) - data.items = data.items.concat(consequences); + items = items.concat( consequences.map(i => i.toObject()) ); } + data.items = items; + console.log(data); return super.create(data, options); } diff --git a/module/sos-main.js b/module/sos-main.js index 35fd287..d33610a 100644 --- a/module/sos-main.js +++ b/module/sos-main.js @@ -56,8 +56,8 @@ Hooks.once("init", async function () { /* -------------------------------------------- */ // Define custom Entity classes - CONFIG.Actor.entityClass = SoSActor; - CONFIG.Combat.entityClass = SoSCombat; + CONFIG.Actor.documentClass = SoSActor; + CONFIG.Combat.documentClass = SoSCombat; CONFIG.SoS = { } @@ -83,8 +83,8 @@ Hooks.once("init", async function () { function welcomeMessage() { //ChatUtility.removeMyChatMessageContaining('
    '); ChatMessage.create({ - user: game.user._id, - whisper: [game.user._id], + user: game.user.id, + whisper: [game.user.id], content: `
    Welcome !
    ` }); } diff --git a/module/sos-utility.js b/module/sos-utility.js index e5841d4..d1ccefb 100644 --- a/module/sos-utility.js +++ b/module/sos-utility.js @@ -8,7 +8,7 @@ const severity2malus = { "none": 0, "light": -1, "moderate": -2, "severe": -3, " const severity2bonus = { "none": 0, "light": 1, "moderate": 2, "severe": 3, "critical": 4}; /* -------------------------------------------- */ -export class SoSUtility extends Entity { +export class SoSUtility { /* -------------------------------------------- */ static async preloadHandlebarsTemplates() { @@ -55,6 +55,32 @@ export class SoSUtility extends Entity { } } + /* -------------------------------------------- */ + static data(it) { + if (it instanceof Actor || it instanceof Item || it instanceof Combatant) { + return it.data; + } + return it; + } + + + /* -------------------------------------------- */ + static templateData(it) { + return SoSUtility.data(it)?.data ?? {} + } + + /* -------------------------------------------- */ + static async loadCompendiumData(compendium) { + const pack = game.packs.get(compendium); + return await pack?.getDocuments() ?? []; + } + + /* -------------------------------------------- */ + static async loadCompendium(compendium, filter = item => true) { + let compendiumData = await SoSUtility.loadCompendiumData(compendium); + return compendiumData.filter(filter); + } + /* -------------------------------------------- */ static async loadCompendiumNames(compendium) { const pack = game.packs.get(compendium); @@ -64,13 +90,13 @@ export class SoSUtility extends Entity { } /* -------------------------------------------- */ - static async loadCompendium(compendium, filter = item => true) { + /*static async loadCompendium(compendium, filter = item => true) { let compendiumItems = await SoSUtility.loadCompendiumNames(compendium); const pack = game.packs.get(compendium); let list = []; for (let compendiumItem of compendiumItems) { - await pack.getEntity(compendiumItem._id).then(it => { + await pack.getEntity(compendiumItem.id).then(it => { const item = it.data; if (filter(item)) { list.push(item); @@ -78,7 +104,7 @@ export class SoSUtility extends Entity { }); }; return list; - } + }*/ /* -------------------------------------------- */ static updateCombat(combat, round, diff, id) { diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 63126aa..1b441f9 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -5,8 +5,8 @@
    - -

    + +

    @@ -28,8 +28,8 @@
    lock/unlock{{#if data.editStatSkill}}Lock{{else}}Unlock{{/if}} + src="systems/foundryvtt-shadows-over-sol/img/icons/{{#if editStatSkill}}unlocked.svg{{else}}locked.svg{{/if}}" alt="lock/unlock" + >{{#if editStatSkill}}Lock{{else}}Unlock{{/if}}
    • Stat name @@ -37,7 +37,7 @@ XP
    • - {{#each data.stats as |stat key|}} + {{#each data.data.stats as |stat key|}} {{#if stat.isLevelUp}}
    • @@ -48,12 +48,12 @@
    • {{/if}} {{localize stat.label}} - {{#select stat.value}} {{>"systems/foundryvtt-shadows-over-sol/templates/stat-option-list.html"}} {{/select}} - +
    • {{/each}} @@ -66,14 +66,14 @@ Value Bonus/Malus - {{#each data.scores as |score key|}} + {{#each data.data.scores as |score key|}}
    • {{localize score.label}} - + {{#if (eq key 'defense')}} - + {{/if}} - +
    • {{/each}}
    @@ -81,7 +81,7 @@
    -

    Current deck size : {{data.deckSize}} cards

    +

    Current deck size : {{deckSize}} cards

    Reset full deck and edges Draw a new Edge card @@ -90,7 +90,7 @@

    Edge cards :

    - {{#each data.edgecard as |card key|}} + {{#each edgecard as |card key|}}
    Discard @@ -106,8 +106,8 @@
    lock/unlock{{#if data.editStatSkill}}Lock{{else}}Unlock{{/if}} + src="systems/foundryvtt-shadows-over-sol/img/icons/{{#if editStatSkill}}unlocked.svg{{else}}locked.svg{{/if}}" alt="lock/unlock" + >{{#if editStatSkill}}Lock{{else}}Unlock{{/if}}
    Skills @@ -115,11 +115,11 @@
      - {{#each data.skill1 as |skill key|}} + {{#each skill1 as |skill key|}} {{#if skill.data.isLevelUp}} -
    • +
    • {{else}} -
    • +
    • {{/if}} {{#if skill.data.isLevelUp}} @@ -143,11 +143,11 @@
        - {{#each data.skill2 as |skill key|}} + {{#each skill2 as |skill key|}} {{#if skill.data.isLevelUp}} -
      • +
      • {{else}} -
      • +
      • {{/if}} {{#if skill.data.isLevelUp}} @@ -174,24 +174,24 @@ {{!-- Consequences Tab --}}
        lock/unlock{{#if data.editStatSkill}}Lock{{else}}Unlock{{/if}} + src="systems/foundryvtt-shadows-over-sol/img/icons/{{#if editStatSkill}}unlocked.svg{{else}}locked.svg{{/if}}" alt="lock/unlock" + >{{#if editStatSkill}}Lock{{else}}Unlock{{/if}}

        Wounds & Conséquences

        • Wounds :

        • Light : - +
        • Moderate : - +
        • Severe : - +
        • Critical : - +
        • Total : {{data.currentWounds}} / {{data.totalWounds}} @@ -200,8 +200,8 @@
          - {{#each data.consequences as |conseq key|}} -
        • + {{#each consequences as |conseq key|}} +
        • {{conseq.name}} - {{#select data.subculture}} - {{#each data.subcultureList as |subculture key|}} + {{#select subculture}} + {{#each subcultureList as |subculture key|}} {{/each}} {{/select}} @@ -339,8 +339,8 @@
          Familiar Subcultures
            - {{#each data.subcultureList as |subculture key|}} -
          • + {{#each subcultureList as |subculture key|}} +
          • {{subculture.name}}
            @@ -354,8 +354,8 @@
            Known Languages
              - {{#each data.languageList as |language key|}} -
            • + {{#each languageList as |language key|}} +
            • {{language.name}}
              @@ -369,8 +369,8 @@
              Weaknesses
                - {{#each data.weaknessList as |weakness key|}} -
              • + {{#each weaknessList as |weakness key|}} +
              • {{weakness.name}}
                -- 2.35.3 From 3d23807820d182a5a92fa34bc7329065d36e472d Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sat, 22 May 2021 23:42:53 +0200 Subject: [PATCH 20/47] Start 0.8 support --- module/actor-sheet.js | 4 ++-- module/actor.js | 24 +++++++++++----------- module/item-sheet.js | 29 ++++++++++++++++++++------- templates/actor-sheet.html | 24 +++++++++++----------- templates/item-consequence-sheet.html | 10 ++++----- templates/item-skill-sheet.html | 8 ++++---- 6 files changed, 57 insertions(+), 42 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index d3f261e..e69b79d 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -175,9 +175,9 @@ export class SoSActorSheet extends ActorSheet { }); html.find('.consequence-severity').click((event) => { const li = $(event.currentTarget).parents(".item"); - const item = this.actor.getOwnedItem(li.data("item-id")); + const item = this.actor.items.get(li.data("item-id")); let severity = $(event.currentTarget).val(); - this.actor.updateOwnedItem( { id: item.id, 'data.severity': severity}); + this.actor.updateEmbeddedDocuments( "Item", [ { _id: item.id, 'data.severity': severity} ] ); this.render(true); }); html.find('.lock-unlock-sheet').click((event) => { diff --git a/module/actor.js b/module/actor.js index ce86f31..e648d41 100644 --- a/module/actor.js +++ b/module/actor.js @@ -171,8 +171,8 @@ export class SoSActor extends Actor { async wornObject( itemID) { let item = this.getOwnedItem(itemID); if (item && item.data.data) { - let update = { _id: item._id, "data.worn": !item.data.data.worn }; - await this.updateEmbeddedEntity("OwnedItem", update); + let update = { _id: item.id, "data.worn": !item.data.data.worn }; + await this.updateEmbeddedDocuments("Item", [update]); } } @@ -180,8 +180,8 @@ export class SoSActor extends Actor { async equipObject(itemID) { let item = this.getOwnedItem(itemID); if (item && item.data.data) { - let update = { _id: item._id, "data.equiped": !item.data.data.equiped }; - await this.updateEmbeddedEntity("OwnedItem", update); + let update = { _id: item.id, "data.equiped": !item.data.data.equiped }; + await this.updateEmbeddedDocuments("Item", [update]); } } @@ -222,16 +222,16 @@ export class SoSActor extends Actor { async updateSkill(skillName, value) { let skill = this.data.items.find( item => item.name == skillName); if (skill) { - const update = { _id: skill._id, 'data.value': value }; - const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity + const update = { _id: skill.id, 'data.value': value }; + const updated = await this.updateEmbeddedDocuments("Item", [ update] ); // Updates one EmbeddedEntity } } /* -------------------------------------------- */ async updateSkillExperience(skillName, value) { let skill = this.data.items.find( item => item.name == skillName); if (skill) { - const update = { _id: skill._id, 'data.xp': value }; - const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity + const update = { _id: skill.id, 'data.xp': value }; + const updated = await this.updateEmbeddedDocuments("Item", [update]); // Updates one EmbeddedEntity } } @@ -387,10 +387,10 @@ export class SoSActor extends Actor { if ( alreadyInside.length >= container.data.container ) { ui.notifications.warn("Container is already full !"); } else { - await this.updateOwnedItem( { _id: object._id, 'data.containerid':containerId }); + await this.updateOwnedItem( { _id: object.id, 'data.containerid':containerId }); } } else if ( object && object.data.containerid) { // remove from container - await this.updateOwnedItem( { _id: object._id, 'data.containerid':"" }); + await this.updateOwnedItem( { _id: object.id, 'data.containerid':"" }); } } @@ -416,7 +416,7 @@ export class SoSActor extends Actor { if ( sumWound >= this.data.data.scores.wound.value) { let bleeding = this.data.items.find( item => item.type == 'consequence' && item.name == 'Bleeding'); let newSeverity = SoSUtility.increaseConsequenceSeverity( bleeding.severity ); - await this.updateOwnedItem( { _id: bleeding._id, 'data.severity': newSeverity}); + await this.updateOwnedItem( { _id: bleeding.id, 'data.severity': newSeverity}); flipData.isBleeding = newSeverity; } // Stun consequence @@ -426,7 +426,7 @@ export class SoSActor extends Actor { for(i=0; i foundry.utils.deepClone(e.data)), + limited: this.object.limited, + options: this.options, + owner: this.document.isOwner + }; + + formData.isGM = game.user.isGM; + if ( objectData.type == 'skillexperience') { + formData.skillList = await SoSUtility.loadCompendiumNames("foundryvtt-shadows-over-sol.skills"); } - if ( data.item.type == 'skill' && this.object.options?.actor) { - data.skillExperienceList = this.object.options.actor.getSkillExperience( data.item.name ); + if ( objectData.type == 'skill' && this.object.options?.actor) { + formData.skillExperienceList = this.object.options.actor.getSkillExperience( data.item.name ); } - return data; + return formData; } /* -------------------------------------------- */ diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 1b441f9..b2d1ea9 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -130,8 +130,8 @@ {{else}} {{skill.name}} {{/if}} - - + +
                @@ -158,8 +158,8 @@ {{else}} {{skill.name}} {{/if}} - - + +
                @@ -182,16 +182,16 @@
                • Wounds :

                • Light : - +
                • Moderate : - +
                • Severe : - +
                • Critical : - +
                • Total : {{data.currentWounds}} / {{data.totalWounds}} @@ -204,8 +204,8 @@
                • {{conseq.name}} - + {{#select conseq.data.data.severity}} @@ -390,12 +390,12 @@

                  Biography :

                  - {{editor content=data.history target="data.history" button=true owner=owner editable=editable}} + {{editor content=data.data.history target="data.history" button=true owner=owner editable=editable}}

                  Notes :

                  - {{editor content=data.notes target="data.notes" button=true owner=owner editable=editable}} + {{editor content=data.data.notes target="data.notes" button=true owner=owner editable=editable}}

                  {{>"systems/foundryvtt-shadows-over-sol/templates/editor-notes-gm.html"}} diff --git a/templates/item-consequence-sheet.html b/templates/item-consequence-sheet.html index 774bb95..d6cae1d 100644 --- a/templates/item-consequence-sheet.html +++ b/templates/item-consequence-sheet.html @@ -1,8 +1,8 @@
                  - +
                  -

                  +

                  @@ -13,8 +13,8 @@
                  - + {{#select data.data.severity}} @@ -27,7 +27,7 @@
                  - {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} + {{editor content=data.data.description target="data.description" button=true owner=owner editable=editable}}
                  diff --git a/templates/item-skill-sheet.html b/templates/item-skill-sheet.html index 5061aa5..5e5f07e 100644 --- a/templates/item-skill-sheet.html +++ b/templates/item-skill-sheet.html @@ -1,8 +1,8 @@
                  - +
                  -

                  +

                  @@ -11,7 +11,7 @@
                    -
                  • +
                    • Experiences list : @@ -27,7 +27,7 @@ {{/each}}
                    - {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} + {{editor content=data.data.description target="data.description" button=true owner=owner editable=editable}}
                  -- 2.35.3 From b93a29f7fc336772e2d9cd8f646810f1ab07323a Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sun, 23 May 2021 00:03:37 +0200 Subject: [PATCH 21/47] Start 0.8 support --- module/actor-sheet.js | 8 ++++---- module/sos-card-deck.js | 2 +- templates/actor-sheet.html | 18 +++++++++--------- templates/item-armor-sheet.html | 7 +++++-- templates/item-commongear-sheet.html | 3 ++- templates/item-container-sheet.html | 6 +++--- templates/item-gear-sheet.html | 4 ++-- templates/item-geneline-sheet.html | 6 ++++-- templates/item-injury-sheet.html | 6 ++++-- templates/item-language-sheet.html | 6 +++--- templates/item-malady-sheet.html | 8 ++++---- templates/item-skillexperience-sheet.html | 7 ++++--- templates/item-subculture-sheet.html | 6 ++++-- templates/item-vehicle-sheet.html | 8 +++++--- templates/item-weakness-sheet.html | 6 ++++-- templates/item-weapon-sheet.html | 8 +++++--- 16 files changed, 63 insertions(+), 46 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index e69b79d..0537ef1 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -55,10 +55,10 @@ export class SoSActorSheet extends ActorSheet { if ( a.name > b.name ) return 1; return -1; }); - formData.gears = this.actor.data.items.filter( item => item.type == 'gear').concat( this.actor.data.items.filter( item => item.type == 'container') ); + formData.gears = this.actor.data.items.filter( item => item.type == 'gear').concat( this.actor.data.items.filter( item => item.type == 'container') ); // Build the gear tree - formData.gearsRoot = formData.gears.filter(item => item.data.containerid == ""); + formData.gearsRoot = formData.gears.filter(item => item.data.data.containerid == ""); for ( let container of formData.gearsRoot) { if ( container.type == 'container') { container.data.contains = [] @@ -134,12 +134,12 @@ export class SoSActorSheet extends ActorSheet { }); html.find('.skill-label a').click((event) => { const li = $(event.currentTarget).parents(".item"); - const skill = this.actor.getOwnedItem(li.data("item-id")); + const skill = this.actor.get.items(li.data("item-id")); this.actor.rollSkill(skill); }); html.find('.weapon-label a').click((event) => { const li = $(event.currentTarget).parents(".item"); - const weapon = this.actor.getOwnedItem(li.data("item-id")); + const weapon = this.actor.get.items(li.data("item-id")); this.actor.rollWeapon(weapon); }); html.find('.skill-value').change((event) => { diff --git a/module/sos-card-deck.js b/module/sos-card-deck.js index 3fef1ba..3f1f3a6 100644 --- a/module/sos-card-deck.js +++ b/module/sos-card-deck.js @@ -38,7 +38,7 @@ export class SoSCardDeck { this.cleanCardList(); // Randomize deck while (this.data.deck.length != NB_POKER_CARD) { - let idx = new Roll("1d54").roll().total; + let idx = new Roll("1d54").roll( {async:false} ).total; if (!this.data.cardState[idx - 1]) { if (idx == 53) { // Red Joker this.data.deck.push( { cardName: 'jr' } ); diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index b2d1ea9..326846b 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -227,7 +227,7 @@ {{!-- Gears Tab --}}
                  -

                  Total Encumbrance : {{totalEncumbrance}} / {{stats.strength.value}}

                  +

                  Total Encumbrance : {{totalEncumbrance}} / {{data.data.stats.strength.value}}

                  Weapons

                  Equipment/Gears

                    {{#each gearsRoot as |gear key|}}
                  • - {{gear.name}} + {{gear.data.name}}
                    • - {{#each data.contains as |subgear key|}} + {{#each data.data.contains as |subgear key|}}
                    • - {{subgear.name}} + {{subgear.data.name}} diff --git a/templates/item-armor-sheet.html b/templates/item-armor-sheet.html index 3d26f84..556c6c0 100644 --- a/templates/item-armor-sheet.html +++ b/templates/item-armor-sheet.html @@ -1,14 +1,15 @@
                      - +
                      -

                      +

                      {{!-- Sheet Body --}}
                      + {{#with data}}
                      @@ -35,6 +36,8 @@
                      + {{/with}} + {{>"systems/foundryvtt-shadows-over-sol/templates/item-commongear-sheet.html"}}
                      diff --git a/templates/item-commongear-sheet.html b/templates/item-commongear-sheet.html index cc763b7..d122999 100644 --- a/templates/item-commongear-sheet.html +++ b/templates/item-commongear-sheet.html @@ -1,3 +1,4 @@ + {{#with data}}
                      @@ -48,4 +49,4 @@ {{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
                  - +{{/with}} diff --git a/templates/item-container-sheet.html b/templates/item-container-sheet.html index fd50779..9b7a727 100644 --- a/templates/item-container-sheet.html +++ b/templates/item-container-sheet.html @@ -1,8 +1,8 @@
                  - +
                  -

                  +

                  @@ -13,7 +13,7 @@
                  - +
                  {{>"systems/foundryvtt-shadows-over-sol/templates/item-commongear-sheet.html"}}
                  diff --git a/templates/item-gear-sheet.html b/templates/item-gear-sheet.html index 8dd71f5..181a526 100644 --- a/templates/item-gear-sheet.html +++ b/templates/item-gear-sheet.html @@ -1,8 +1,8 @@
                  - +
                  -

                  +

                  diff --git a/templates/item-geneline-sheet.html b/templates/item-geneline-sheet.html index 900649c..22154cc 100644 --- a/templates/item-geneline-sheet.html +++ b/templates/item-geneline-sheet.html @@ -1,13 +1,14 @@
                  - +
                  -

                  +

                  {{!-- Sheet Body --}}
                  + {{#with data}}
                  @@ -35,6 +36,7 @@
                + {{/with}} diff --git a/templates/item-injury-sheet.html b/templates/item-injury-sheet.html index 4795cba..76ea621 100644 --- a/templates/item-injury-sheet.html +++ b/templates/item-injury-sheet.html @@ -1,13 +1,14 @@
                - +
                -

                +

                {{!-- Sheet Body --}}
                + {{#with data}}
                @@ -20,6 +21,7 @@
                + {{/with}} diff --git a/templates/item-language-sheet.html b/templates/item-language-sheet.html index 2049b1e..5bfc7b2 100644 --- a/templates/item-language-sheet.html +++ b/templates/item-language-sheet.html @@ -1,8 +1,8 @@
                - +
                -

                +

                @@ -13,7 +13,7 @@
                - {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} + {{editor content=data.ata.description target="data.description" button=true owner=owner editable=editable}}
              diff --git a/templates/item-malady-sheet.html b/templates/item-malady-sheet.html index 0ba4655..b826474 100644 --- a/templates/item-malady-sheet.html +++ b/templates/item-malady-sheet.html @@ -1,14 +1,14 @@
              - +
              -

              +

              {{!-- Sheet Body --}}
              - + {{#with data}}
              @@ -28,6 +28,6 @@
            - + {{/with}} diff --git a/templates/item-skillexperience-sheet.html b/templates/item-skillexperience-sheet.html index 8d8562d..fe3f1c2 100644 --- a/templates/item-skillexperience-sheet.html +++ b/templates/item-skillexperience-sheet.html @@ -1,14 +1,14 @@
            - +
            -

            +

            {{!-- Sheet Body --}}
            - + {{#with data}}
            @@ -29,6 +29,7 @@
            + {{/with}} diff --git a/templates/item-subculture-sheet.html b/templates/item-subculture-sheet.html index cbf062a..5b3b9fa 100644 --- a/templates/item-subculture-sheet.html +++ b/templates/item-subculture-sheet.html @@ -1,13 +1,14 @@
            - +
            -

            +

            {{!-- Sheet Body --}}
            + {{#with data}}
            @@ -23,6 +24,7 @@
          + {{/with}} diff --git a/templates/item-vehicle-sheet.html b/templates/item-vehicle-sheet.html index 24a6c7a..f0204d4 100644 --- a/templates/item-vehicle-sheet.html +++ b/templates/item-vehicle-sheet.html @@ -1,8 +1,8 @@
          - +
          -

          +

          @@ -10,7 +10,7 @@
          - + {{#with data}}
          @@ -35,6 +35,8 @@
          + {{/with}} + {{>"systems/foundryvtt-shadows-over-sol/templates/item-commongear-sheet.html"}}
          diff --git a/templates/item-weakness-sheet.html b/templates/item-weakness-sheet.html index f555679..53d6c61 100644 --- a/templates/item-weakness-sheet.html +++ b/templates/item-weakness-sheet.html @@ -1,13 +1,14 @@
          - +
          -

          +

          {{!-- Sheet Body --}}
          + {{#with data}}
          @@ -30,6 +31,7 @@
        + {{/with}} diff --git a/templates/item-weapon-sheet.html b/templates/item-weapon-sheet.html index 7fe7c14..408a90d 100644 --- a/templates/item-weapon-sheet.html +++ b/templates/item-weapon-sheet.html @@ -1,13 +1,14 @@
        - +
        -

        +

        {{!-- Sheet Body --}}
        + {{#with data}}
        @@ -82,7 +83,8 @@
        - + {{/with}} + {{>"systems/foundryvtt-shadows-over-sol/templates/item-commongear-sheet.html"}}
        -- 2.35.3 From 5ceeefb52255e4a3a03ac97878c23338156b96b6 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sun, 23 May 2021 11:45:50 +0200 Subject: [PATCH 22/47] Fix gears management" --- module/actor-sheet.js | 4 ++-- templates/actor-sheet.html | 2 +- templates/item-armor-sheet.html | 4 ++-- templates/item-commongear-sheet.html | 5 +++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 0537ef1..cefbf9a 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -134,12 +134,12 @@ export class SoSActorSheet extends ActorSheet { }); html.find('.skill-label a').click((event) => { const li = $(event.currentTarget).parents(".item"); - const skill = this.actor.get.items(li.data("item-id")); + const skill = this.actor.items.get(li.data("item-id")); this.actor.rollSkill(skill); }); html.find('.weapon-label a').click((event) => { const li = $(event.currentTarget).parents(".item"); - const weapon = this.actor.get.items(li.data("item-id")); + const weapon = this.actor.items.get(li.data("item-id")); this.actor.rollWeapon(weapon); }); html.find('.skill-value').change((event) => { diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 326846b..290a7d1 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -236,7 +236,7 @@ {{weapon.name}} diff --git a/templates/item-armor-sheet.html b/templates/item-armor-sheet.html index 556c6c0..49b68c2 100644 --- a/templates/item-armor-sheet.html +++ b/templates/item-armor-sheet.html @@ -1,8 +1,8 @@
        - +
        -

        +

        diff --git a/templates/item-commongear-sheet.html b/templates/item-commongear-sheet.html index d122999..09167c7 100644 --- a/templates/item-commongear-sheet.html +++ b/templates/item-commongear-sheet.html @@ -43,10 +43,11 @@
        + {{/with}} +
        - {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} + {{editor content=data.data.description target="data.description" button=true owner=owner editable=editable}}
        -{{/with}} -- 2.35.3 From 6845e803a5d35ad8a72b10ad445819b2da021a6d Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sun, 23 May 2021 12:00:34 +0200 Subject: [PATCH 23/47] FixStun consequence --- module/actor.js | 4 ++-- system.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/module/actor.js b/module/actor.js index f0ffc54..a13054c 100644 --- a/module/actor.js +++ b/module/actor.js @@ -419,9 +419,9 @@ export class SoSActor extends Actor { } // Stun consequence if ( flipData.nbStun > 0) { - let stun = this.data.items.find( item => item.type == 'consequence' && item.name == 'Sun'); + let stun = this.data.items.find( item => item.type == 'consequence' && item.name == 'Stun'); let newSeverity = stun.severity; - for(i=0; i Date: Mon, 24 May 2021 09:11:57 +0200 Subject: [PATCH 24/47] Syn for 0.8.0 --- module/actor.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/module/actor.js b/module/actor.js index e648d41..0c9a287 100644 --- a/module/actor.js +++ b/module/actor.js @@ -415,18 +415,18 @@ export class SoSActor extends Actor { currentWounds.value = sumWound; if ( sumWound >= this.data.data.scores.wound.value) { let bleeding = this.data.items.find( item => item.type == 'consequence' && item.name == 'Bleeding'); - let newSeverity = SoSUtility.increaseConsequenceSeverity( bleeding.severity ); - await this.updateOwnedItem( { _id: bleeding.id, 'data.severity': newSeverity}); + let newSeverity = SoSUtility.increaseConsequenceSeverity( bleeding.data.severity ); + await this.updateEmbeddedDocuments( "Item", [ { _id: bleeding.id, 'data.severity': newSeverity} ] ); flipData.isBleeding = newSeverity; } // Stun consequence if ( flipData.nbStun > 0) { - let stun = this.data.items.find( item => item.type == 'consequence' && item.name == 'Sun'); - let newSeverity = stun.severity; - for(i=0; i item.type == 'consequence' && item.name == 'Stun'); + let newSeverity = stun.data.severity; + for(let i=0; i Date: Sat, 18 Dec 2021 09:49:29 +0100 Subject: [PATCH 25/47] v9 support --- styles/simple.css | 1 + system.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/styles/simple.css b/styles/simple.css index 5da1a63..fcedc08 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -812,6 +812,7 @@ ul, li { /* Sidebar CSS */ #sidebar { font-size: 1rem; + width: min-content; background: rgb(105,85,65) url("../img/ui/sidebar-bg.webp") no-repeat right bottom; background-position: 100%; color: rgba(19, 15, 15, 0.75); diff --git a/system.json b/system.json index c213547..a6bd771 100644 --- a/system.json +++ b/system.json @@ -7,9 +7,9 @@ "url": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", "flags": {}, - "version": "2.0.0", + "version": "2.0.1", "minimumCoreVersion": "0.8.0", - "compatibleCoreVersion": "0.8.5", + "compatibleCoreVersion": "0.8.9", "scripts": [], "esmodules": [ "module/sos-main.js" -- 2.35.3 From 6df412b1b30235ef85de21cd040b78275023d46e Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sat, 18 Dec 2021 09:54:39 +0100 Subject: [PATCH 26/47] Sync --- system.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system.json b/system.json index a6bd771..32869fc 100644 --- a/system.json +++ b/system.json @@ -7,9 +7,9 @@ "url": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", "flags": {}, - "version": "2.0.1", + "version": "2.0.2", "minimumCoreVersion": "0.8.0", - "compatibleCoreVersion": "0.8.9", + "compatibleCoreVersion": "9", "scripts": [], "esmodules": [ "module/sos-main.js" -- 2.35.3 From 07ea4477cdc50345f2957120b4ffa04fd5e502bb Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sat, 29 Jan 2022 16:45:09 +0100 Subject: [PATCH 27/47] SoS : Minor v9 update --- module/sos-main.js | 25 +++++++++++++++++++++++-- system.json | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/module/sos-main.js b/module/sos-main.js index d33610a..bfb7df6 100644 --- a/module/sos-main.js +++ b/module/sos-main.js @@ -89,6 +89,28 @@ function welcomeMessage() { ` }); } +/* -------------------------------------------- */ +// Register world usage statistics +function registerUsageCount( registerKey ) { + if ( game.user.isGM ) { + game.settings.register(registerKey, "world-key", { + name: "Unique world key", + scope: "world", + config: false, + type: String + }); + + let worldKey = game.settings.get(registerKey, "world-key") + if ( worldKey == undefined || worldKey == "" ) { + worldKey = randomID(32) + game.settings.set(registerKey, "world-key", worldKey ) + } + // Simple API counter + $.ajax(`https://jdr.lahiette.com/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.data.version}"`) + /* -------------------------------------------- */ + } +} + /* -------------------------------------------- */ /* Foundry VTT Initialization */ /* -------------------------------------------- */ @@ -102,9 +124,8 @@ Hooks.once("ready", function () { user: game.user._id }); } + registerUsageCount("foundryvtt-shadows-over-sol") - //gearConverter.importgear(); - welcomeMessage(); }); diff --git a/system.json b/system.json index 32869fc..3369b00 100644 --- a/system.json +++ b/system.json @@ -7,7 +7,7 @@ "url": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", "flags": {}, - "version": "2.0.2", + "version": "2.0.3", "minimumCoreVersion": "0.8.0", "compatibleCoreVersion": "9", "scripts": [], -- 2.35.3 From e6089451338a9601ddb18704a447029cc8385014 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sat, 19 Feb 2022 09:30:44 +0100 Subject: [PATCH 28/47] Use another server for measures --- module/sos-main.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/module/sos-main.js b/module/sos-main.js index bfb7df6..b52a6bc 100644 --- a/module/sos-main.js +++ b/module/sos-main.js @@ -106,7 +106,8 @@ function registerUsageCount( registerKey ) { game.settings.set(registerKey, "world-key", worldKey ) } // Simple API counter - $.ajax(`https://jdr.lahiette.com/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.data.version}"`) + let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.data.version}"` + $.ajax(regURL) /* -------------------------------------------- */ } } -- 2.35.3 From ae2d926324791cf92368948065d49855ed112978 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sat, 5 Mar 2022 23:39:35 +0100 Subject: [PATCH 29/47] Fix gears and containers --- module/actor-sheet.js | 11 ++++++----- module/actor.js | 19 ++++++++++--------- module/sos-utility.js | 2 +- system.json | 2 +- templates/actor-sheet.html | 2 +- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index cefbf9a..98c8ad6 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -63,11 +63,12 @@ export class SoSActorSheet extends ActorSheet { if ( container.type == 'container') { container.data.contains = [] container.data.containerEnc = 0; - for (let gear of data.data.gears) { - if ( gear.data.containerid == container.id) { - container.data.contains.push( gear ); - if ( !gear.data.neg && !gear.data.software ) { - container.data.containerEnc += (gear.big > 0) ? gear.big : 1; + for (let gear of formData.gears) { + console.log("GEAR", gear, container) + if ( gear.data.data.containerid == container.id) { + container.data.contains.push( gear ) + if ( !gear.data.data.neg && !gear.data.data.software ) { + container.data.containerEnc += (gear.data.data.big > 0) ? gear.data.data.big : 1; } } } diff --git a/module/actor.js b/module/actor.js index 0c9a287..d1a0d5e 100644 --- a/module/actor.js +++ b/module/actor.js @@ -169,7 +169,7 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ async wornObject( itemID) { - let item = this.getOwnedItem(itemID); + let item = this.items.get(itemID); if (item && item.data.data) { let update = { _id: item.id, "data.worn": !item.data.data.worn }; await this.updateEmbeddedDocuments("Item", [update]); @@ -178,7 +178,7 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ async equipObject(itemID) { - let item = this.getOwnedItem(itemID); + let item = this.items.get(itemID) if (item && item.data.data) { let update = { _id: item.id, "data.equiped": !item.data.data.equiped }; await this.updateEmbeddedDocuments("Item", [update]); @@ -376,21 +376,22 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ async addObjectToContainer( itemId, containerId ) { - let container = this.data.items.find( item => item._id == containerId && item.type == 'container'); - let object = this.data.items.find( item => item._id == itemId ); + let container = this.data.items.find( item => item.id == containerId && item.type == 'container') + let object = this.data.items.find( item => item.id == itemId ) + //console.log("Found", container, object) if ( container ) { if ( object.type == 'container') { ui.notifications.warn("Only 1 level of container... sorry"); return } - let alreadyInside = this.data.items.filter( item => item.data.containerid && item.data.containerid == containerId); - if ( alreadyInside.length >= container.data.container ) { + let alreadyInside = this.data.items.filter( item => item.data.data.containerid && item.data.data.containerid == containerId); + if ( alreadyInside.length >= container.data.data.container ) { ui.notifications.warn("Container is already full !"); } else { - await this.updateOwnedItem( { _id: object.id, 'data.containerid':containerId }); + await this.updateEmbeddedDocuments( "Item", [{ _id: object.id, 'data.containerid':containerId }]); } - } else if ( object && object.data.containerid) { // remove from container - await this.updateOwnedItem( { _id: object.id, 'data.containerid':"" }); + } else if ( object && object.data.data.containerid) { // remove from container + await this.updateEmbeddedDocuments( "Item", [{ _id: object.id, 'data.containerid':"" }]); } } diff --git a/module/sos-utility.js b/module/sos-utility.js index d1ccefb..89eadb9 100644 --- a/module/sos-utility.js +++ b/module/sos-utility.js @@ -256,7 +256,7 @@ export class SoSUtility { label: "Yes, delete it", callback: () => { console.log("Delete : ", itemId); - actorSheet.actor.deleteOwnedItem(itemId); + actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]); li.slideUp(200, () => actorSheet.render(false)); } }, diff --git a/system.json b/system.json index 3369b00..c683147 100644 --- a/system.json +++ b/system.json @@ -7,7 +7,7 @@ "url": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", "flags": {}, - "version": "2.0.3", + "version": "2.0.4", "minimumCoreVersion": "0.8.0", "compatibleCoreVersion": "9", "scripts": [], diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 290a7d1..8099bcd 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -270,7 +270,7 @@
      • - {{#each data.data.contains as |subgear key|}} + {{#each data.contains as |subgear key|}}
      • {{subgear.data.name}} -- 2.35.3 From 633525a9e56be1fb2f8270c6902b822dde1e61bd Mon Sep 17 00:00:00 2001 From: sladecraven Date: Fri, 18 Mar 2022 19:30:18 +0100 Subject: [PATCH 30/47] Fix reset deck in Foundry v9 #9 --- module/actor.js | 2 +- module/sos-card-deck.js | 23 ++++++++++++----------- system.json | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/module/actor.js b/module/actor.js index d1a0d5e..fc3e5d1 100644 --- a/module/actor.js +++ b/module/actor.js @@ -378,7 +378,7 @@ export class SoSActor extends Actor { async addObjectToContainer( itemId, containerId ) { let container = this.data.items.find( item => item.id == containerId && item.type == 'container') let object = this.data.items.find( item => item.id == itemId ) - //console.log("Found", container, object) + console.log("Found", container, object) if ( container ) { if ( object.type == 'container') { ui.notifications.warn("Only 1 level of container... sorry"); diff --git a/module/sos-card-deck.js b/module/sos-card-deck.js index 3f1f3a6..756979f 100644 --- a/module/sos-card-deck.js +++ b/module/sos-card-deck.js @@ -58,21 +58,22 @@ export class SoSCardDeck { /* -------------------------------------------- */ resetDeck() { - let newdeck = duplicate(this.data.deck).concat( duplicate (this.data.discard)); - this.data.discard = []; // Reinit discard pile - this.data.deck = []; - let decklen = newdeck.length; - let cardState = []; + let newdeck = duplicate(this.data.deck).concat( duplicate (this.data.discard) ) + this.data.discard = [] // Reinit discard pile + this.data.deck = [] + let decklen = newdeck.length + let cardState = [] for (let i = 0; i Date: Sat, 21 May 2022 12:46:46 +0200 Subject: [PATCH 31/47] Migrate repo --- system.json | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/system.json b/system.json index 090051e..8d80e04 100644 --- a/system.json +++ b/system.json @@ -4,10 +4,10 @@ "description": "Shadows over Sol for FoundryVTT", "author": "LeRatierBretonnien", "authors": [], - "url": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/", + "url": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", "flags": {}, - "version": "2.0.5", + "version": "2.0.6", "minimumCoreVersion": "0.8.0", "compatibleCoreVersion": "9", "scripts": [], @@ -29,7 +29,7 @@ "name": "skills", "label": "Skills", "path": "./packs/skills.db", - "entity": "Item", + "type": "Item", "system": "foundryvtt-shadows-over-sol", "private": false }, @@ -37,7 +37,7 @@ "name": "consequences", "label": "Consequences", "path": "./packs/consequences.db", - "entity": "Item", + "type": "Item", "system": "foundryvtt-shadows-over-sol", "private": false }, @@ -45,7 +45,7 @@ "name": "gears", "label": "Gears", "path": "./packs/gears.db", - "entity": "Item", + "type": "Item", "system": "foundryvtt-shadows-over-sol", "private": false }, @@ -53,7 +53,7 @@ "name": "injuries", "label": "Injuries", "path": "./packs/injuries.db", - "entity": "Item", + "type": "Item", "system": "foundryvtt-shadows-over-sol", "private": false }, @@ -61,7 +61,7 @@ "name": "weaknesses", "label": "Weaknesses", "path": "./packs/weaknesses.db", - "entity": "Item", + "type": "Item", "system": "foundryvtt-shadows-over-sol", "private": false }, @@ -69,7 +69,7 @@ "name": "languages", "label": "Languages", "path": "./packs/languages.db", - "entity": "Item", + "type": "Item", "system": "foundryvtt-shadows-over-sol", "private": false }, @@ -77,7 +77,7 @@ "name": "combat-actions", "label": "Combat Actions", "path": "./packs/combat-actions.db", - "entity": "Item", + "type": "Item", "system": "foundryvtt-shadows-over-sol", "private": false }, @@ -85,7 +85,7 @@ "name": "genelines", "label": "Genelines", "path": "./packs/genelines.db", - "entity": "Item", + "type": "Item", "system": "foundryvtt-shadows-over-sol", "private": false }, @@ -93,7 +93,7 @@ "name": "subcultures", "label": "Subcultures", "path": "./packs/subcultures.db", - "entity": "Item", + "type": "Item", "system": "foundryvtt-shadows-over-sol", "private": false } @@ -101,8 +101,8 @@ "system": [], "dependencies": [], "socket": true, - "manifest": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/-/raw/dev_0.8/system.json", - "download": "https://gitlab.com/LeRatierBretonnien/foundryvtt-shadows-over-sol/-/archive/dev_0.8/foundryvtt-shadows-over-sol.zip", + "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/master/system.json", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-2.0.6.zip", "protected": false, "gridDistance": 5, "gridUnits": "ft" -- 2.35.3 From 9551b2a0506e27ed64fe924ab0df3e34acf94196 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Wed, 13 Jul 2022 08:11:00 +0200 Subject: [PATCH 32/47] v10 branch - Update manifest --- module/actor-sheet.js | 40 +++---- module/actor.js | 132 +++++++++++----------- module/item-sheet.js | 10 +- module/sos-combat.js | 2 +- module/sos-flip-dialog.js | 10 +- module/sos-main.js | 3 +- module/sos-utility.js | 27 ++--- system.json | 17 +-- templates/actor-sheet.html | 86 +++++++------- templates/dialog-combat-actions.html | 4 +- templates/dialog-flip.html | 12 +- templates/editor-notes-gm.html | 2 +- templates/item-action-sheet.html | 12 +- templates/item-armor-sheet.html | 18 ++- templates/item-commongear-sheet.html | 26 ++--- templates/item-consequence-sheet.html | 10 +- templates/item-container-sheet.html | 6 +- templates/item-gear-sheet.html | 4 +- templates/item-geneline-sheet.html | 14 +-- templates/item-injury-sheet.html | 11 +- templates/item-language-sheet.html | 6 +- templates/item-malady-sheet.html | 17 ++- templates/item-skill-sheet.html | 8 +- templates/item-skillexperience-sheet.html | 13 +-- templates/item-subculture-sheet.html | 10 +- templates/item-vehicle-sheet.html | 18 ++- templates/item-weakness-sheet.html | 10 +- templates/item-weapon-sheet.html | 40 ++++--- 28 files changed, 271 insertions(+), 297 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 98c8ad6..a68338c 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -23,7 +23,7 @@ export class SoSActorSheet extends ActorSheet { /* -------------------------------------------- */ getData() { - const objectData = SoSUtility.data(this.object); + const objectData = this.object let formData = { title: this.title, id: objectData.id, @@ -32,7 +32,7 @@ export class SoSActorSheet extends ActorSheet { name: objectData.name, editable: this.isEditable, cssClass: this.isEditable ? "editable" : "locked", - data: foundry.utils.deepClone(this.object.data), + data: foundry.utils.deepClone(this.object.system), effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)), limited: this.object.limited, options: this.options, @@ -44,52 +44,52 @@ export class SoSActorSheet extends ActorSheet { formData.edgecard = this.actor.getEdgesCard(); formData.deckSize = this.actor.getDeckSize(); - formData.skills = this.actor.data.items.filter( item => item.type == 'skill').sort( (a, b) => { + formData.skills = this.actor.items.filter( item => item.type == 'skill').sort( (a, b) => { if ( a.name > b.name ) return 1; return -1; }); formData.skill1 = formData.skills.slice(0, Math.ceil(formData.skills.length/2) ) formData.skill2 = formData.skills.slice(Math.ceil(formData.skills.length/2), formData.skills.length ) - formData.consequences = this.actor.data.items.filter( item => item.type == 'consequence').sort( (a, b) => { + formData.consequences = this.actor.items.filter( item => item.type == 'consequence').sort( (a, b) => { if ( a.name > b.name ) return 1; return -1; }); - formData.gears = this.actor.data.items.filter( item => item.type == 'gear').concat( this.actor.data.items.filter( item => item.type == 'container') ); + formData.gears = this.actor.items.filter( item => item.type == 'gear').concat( this.actor.items.filter( item => item.type == 'container') ); // Build the gear tree - formData.gearsRoot = formData.gears.filter(item => item.data.data.containerid == ""); + formData.gearsRoot = formData.gears.filter(item => item.system.containerid == ""); for ( let container of formData.gearsRoot) { if ( container.type == 'container') { container.data.contains = [] container.data.containerEnc = 0; for (let gear of formData.gears) { console.log("GEAR", gear, container) - if ( gear.data.data.containerid == container.id) { + if ( gear.system.containerid == container.id) { container.data.contains.push( gear ) - if ( !gear.data.data.neg && !gear.data.data.software ) { - container.data.containerEnc += (gear.data.data.big > 0) ? gear.data.data.big : 1; + if ( !gear.system.neg && !gear.system.software ) { + container.system.containerEnc += (gear.system.big > 0) ? gear.system.big : 1; } } } } } - formData.weapons = this.actor.data.items.filter( item => item.type == 'weapon'); - formData.armors = this.actor.data.items.filter( item => item.type == 'armor'); - formData.totalEncumbrance = SoSUtility.computeEncumbrance(this.actor.data.items); - formData.wounds = duplicate(this.actor.data.data.wounds); + formData.weapons = this.actor.items.filter( item => item.type == 'weapon'); + formData.armors = this.actor.items.filter( item => item.type == 'armor'); + formData.totalEncumbrance = SoSUtility.computeEncumbrance(this.actor.items); + formData.wounds = duplicate(this.actor.system.wounds); formData.isGM = game.user.isGM; formData.currentWounds = this.actor.computeCurrentWounds(); - formData.totalWounds = this.actor.data.data.scores.wound.value; + formData.totalWounds = this.actor.system.scores.wound.value; - formData.subcultureList = this.actor.data.items.filter( item => item.type == 'subculture'); + formData.subcultureList = this.actor.items.filter( item => item.type == 'subculture'); if ( formData.subculture != "" ) { // background.subculture contains the main subculture ID - formData.mainSubculture = formData.subcultureList.find( subc => subc._id == data.data.subculture); + formData.mainSubculture = formData.subcultureList.find( subc => subc._id == this.actor.system.subculture); } - formData.languageList = this.actor.data.items.filter( item => item.type == 'language'); - formData.weaknessList = this.actor.data.items.filter( item => item.type == 'weakness'); - formData.geneline = this.actor.data.items.find( item => item.type == 'geneline'); + formData.languageList = this.actor.items.filter( item => item.type == 'language'); + formData.weaknessList = this.actor.items.filter( item => item.type == 'weakness'); + formData.geneline = this.actor.items.find( item => item.type == 'geneline'); formData.editStatSkill = this.options.editStatSkill; console.log("stats", formData); @@ -178,7 +178,7 @@ export class SoSActorSheet extends ActorSheet { const li = $(event.currentTarget).parents(".item"); const item = this.actor.items.get(li.data("item-id")); let severity = $(event.currentTarget).val(); - this.actor.updateEmbeddedDocuments( "Item", [ { _id: item.id, 'data.severity': severity} ] ); + this.actor.updateEmbeddedDocuments( "Item", [ { _id: item.id, 'system.severity': severity} ] ); this.render(true); }); html.find('.lock-unlock-sheet').click((event) => { diff --git a/module/actor.js b/module/actor.js index fc3e5d1..2cfc82f 100644 --- a/module/actor.js +++ b/module/actor.js @@ -63,7 +63,7 @@ export class SoSActor extends Actor { checkDeck() { if ( !this.cardDeck && this.hasPlayerOwner ) { this.cardDeck = new SoSCardDeck(); - this.cardDeck.initCardDeck( this, this.data.data.internals.deck ); + this.cardDeck.initCardDeck( this, this.system.internals.deck ); } if ( !this.hasPlayerOwner ) { this.cardDeck = game.system.sos.gmDeck.GMdeck; @@ -87,7 +87,7 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ resetDeckFull( ) { this.cardDeck.shuffleDeck(); - this.cardDeck.drawEdge( this.data.data.scores.edge.value ); + this.cardDeck.drawEdge( this.system.scores.edge.value ); this.saveDeck(); } /* -------------------------------------------- */ @@ -123,55 +123,55 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ getDefense( ) { - return this.data.data.scores.defense; + return this.system.scores.defense; } /* -------------------------------------------- */ computeDefense() { - return { value: Math.ceil((this.data.data.stats.speed.value + this.data.data.stats.perception.value + this.data.data.stats.dexterity.value) / 2) + this.data.data.scores.defense.bonusmalus, - critical: this.data.data.stats.speed.value + this.data.data.stats.perception.value + this.data.data.stats.dexterity.value + this.data.data.scores.defense.bonusmalus + return { value: Math.ceil((this.system.stats.speed.value + this.system.stats.perception.value + this.system.stats.dexterity.value) / 2) + this.system.scores.defense.bonusmalus, + critical: this.system.stats.speed.value + this.system.stats.perception.value + this.system.stats.dexterity.value + this.system.scores.defense.bonusmalus } } /* -------------------------------------------- */ getEdge( ) { - return this.data.data.scores.edge.value; + return this.system.scores.edge.value; } /* -------------------------------------------- */ getEncumbrance( ) { - return this.data.data.scores.encumbrance.value; + return this.system.scores.encumbrance.value; } computeEncumbrance( ) { - return this.data.data.stats.strength.value + this.data.data.scores.encumbrance.bonusmalus; + return this.system.stats.strength.value + this.system.scores.encumbrance.bonusmalus; } /* -------------------------------------------- */ computeEdge( ) { - return Math.ceil( (this.data.data.stats.intelligence.value + this.data.data.stats.charisma.value) / 2) + this.data.data.scores.edge.bonusmalus; + return Math.ceil( (this.system.stats.intelligence.value + this.system.stats.charisma.value) / 2) + this.system.scores.edge.bonusmalus; } /* -------------------------------------------- */ getShock( ) { - return this.data.data.scores.shock.value; + return this.system.scores.shock.value; } computeShock() { - return Math.ceil( this.data.data.stats.endurance.value + this.data.data.stats.determination.value + this.data.data.scores.dr.value) + this.data.data.scores.shock.bonusmalus; + return Math.ceil( this.system.stats.endurance.value + this.system.stats.determination.value + this.system.scores.dr.value) + this.system.scores.shock.bonusmalus; } /* -------------------------------------------- */ getWound( ) { - return this.data.data.scores.wound.value; + return this.system.scores.wound.value; } computeWound() { - return Math.ceil( (this.data.data.stats.strength.value + this.data.data.stats.endurance.value) / 2) + this.data.data.scores.wound.bonusmalus; + return Math.ceil( (this.system.stats.strength.value + this.system.stats.endurance.value) / 2) + this.system.scores.wound.bonusmalus; } /* -------------------------------------------- */ getSkillExperience( skillName ) { - return this.data.items.filter( item => item.type == 'skillexperience' && item.data.skill == skillName); + return this.items.filter( item => item.type == 'skillexperience' && item.system.skill == skillName); } /* -------------------------------------------- */ async wornObject( itemID) { let item = this.items.get(itemID); - if (item && item.data.data) { - let update = { _id: item.id, "data.worn": !item.data.data.worn }; + if (item && item.system) { + let update = { _id: item.id, "system.worn": !item.system.worn }; await this.updateEmbeddedDocuments("Item", [update]); } } @@ -179,8 +179,8 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ async equipObject(itemID) { let item = this.items.get(itemID) - if (item && item.data.data) { - let update = { _id: item.id, "data.equiped": !item.data.data.equiped }; + if (item && item.system) { + let update = { _id: item.id, "system.equiped": !item.system.equiped }; await this.updateEmbeddedDocuments("Item", [update]); } } @@ -198,7 +198,7 @@ export class SoSActor extends Actor { await this.update( {'data.scores.edge.value': this.computeEdge()}); } // Encumbrance - if ( this.getEncumbrance() != this.data.data.stats.strength.value ) { + if ( this.getEncumbrance() != this.system.stats.strength.value ) { await this.update( {'data.scores.encumbrance.value': this.computeEncumbrance() }); } // Shock @@ -213,31 +213,31 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ async updateWound(woundName, value) { - let wounds = duplicate(this.data.data.wounds) + let wounds = duplicate(this.system.wounds) wounds[woundName] = value; - await this.update( { 'data.wounds': wounds } ); + await this.update( { 'system.wounds': wounds } ); } /* -------------------------------------------- */ async updateSkill(skillName, value) { - let skill = this.data.items.find( item => item.name == skillName); + let skill = this.items.find( item => item.name == skillName); if (skill) { - const update = { _id: skill.id, 'data.value': value }; + const update = { _id: skill.id, 'system.value': value }; const updated = await this.updateEmbeddedDocuments("Item", [ update] ); // Updates one EmbeddedEntity } } /* -------------------------------------------- */ async updateSkillExperience(skillName, value) { - let skill = this.data.items.find( item => item.name == skillName); + let skill = this.items.find( item => item.name == skillName); if (skill) { - const update = { _id: skill.id, 'data.xp': value }; + const update = { _id: skill.id, 'system.xp': value }; const updated = await this.updateEmbeddedDocuments("Item", [update]); // Updates one EmbeddedEntity } } /* -------------------------------------------- */ getApplicableConsequences( ) { - let consequences = this.data.items.filter( item => item.type == 'consequence' && item.data.severity != 'none'); + let consequences = this.items.filter( item => item.type == 'consequence' && item.system.severity != 'none'); return consequences; } @@ -246,13 +246,13 @@ export class SoSActor extends Actor { let flipData = { mode: 'stat', - stat: duplicate(this.data.data.stats[statKey]), + stat: duplicate(this.system.stats[statKey]), actor: this, modifierList: SoSUtility.fillRange(-10, +10), tnList: SoSUtility.fillRange(6, 20), consequencesList: duplicate( this.getApplicableConsequences() ), - weaknessList: this.data.items.filter( item => item.type == 'weakness' ), - wounds: duplicate( this.data.data.wounds), + weaknessList: this.items.filter( item => item.type == 'weakness' ), + wounds: duplicate( this.system.wounds), malusConsequence: 0, bonusConsequence: 0, woundMalus: 0 @@ -265,10 +265,10 @@ export class SoSActor extends Actor { async rollSkill( skill ) { let flipData = { mode: 'skill', - statList: duplicate(this.data.data.stats), + statList: duplicate(this.system.stats), selectedStat: 'strength', consequencesList: duplicate( this.getApplicableConsequences() ), - wounds: duplicate( this.data.data.wounds), + wounds: duplicate( this.system.wounds), skillExperienceList: this.getSkillExperience( skill.name), skill: duplicate(skill), actor: this, @@ -288,26 +288,26 @@ export class SoSActor extends Actor { async rollWeapon( weapon ) { let target = SoSUtility.getTarget(); let skill, selectedStatName; - if ( weapon.data.data.category == 'ballistic' || weapon.data.data.category == 'laser' ) { - skill = this.data.items.find( item => item.name == 'Guns'); + if ( weapon.system.category == 'ballistic' || weapon.system.category == 'laser' ) { + skill = this.items.find( item => item.name == 'Guns'); selectedStatName = 'dexterity'; - } else if ( weapon.data.data.category == 'melee' ) { - skill = this.data.items.find( item => item.name == 'Melee'); + } else if ( weapon.system.category == 'melee' ) { + skill = this.items.find( item => item.name == 'Melee'); selectedStatName = 'dexterity'; - } else if ( weapon.data.data.category == 'grenade' ) { - skill = this.data.items.find( item => item.name == 'Athletics'); + } else if ( weapon.system.category == 'grenade' ) { + skill = this.items.find( item => item.name == 'Athletics'); selectedStatName = 'dexterity'; } let flipData = { mode: 'weapon', - weapon: duplicate(weapon.data), - statList: duplicate(this.data.data.stats), + weapon: duplicate(weapon), + statList: duplicate(this.system.stats), target: target, selectedStat: selectedStatName, consequencesList: duplicate( this.getApplicableConsequences() ), skillExperienceList: this.getSkillExperience( skill.name), - wounds: duplicate( this.data.data.wounds), + wounds: duplicate( this.system.wounds), skill: duplicate(skill), actor: this, modifierList: SoSUtility.fillRange(-10, +10), @@ -327,12 +327,12 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ async checkDeath( ) { - if ( this.data.data.scores.currentwounds.value >= this.data.data.scores.wound.value*2) { + if ( this.system.scores.currentwounds.value >= this.system.scores.wound.value*2) { let woundData = { name: this.name, - wounds: this.data.data.wounds, - currentWounds: this.data.data.scores.currentwounds.value, - totalWounds: this.data.data.scores.wound.value + wounds: this.system.wounds, + currentWounds: this.system.scores.currentwounds.value, + totalWounds: this.system.scores.wound.value } let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-character-death.html', woundData ); ChatMessage.create( { content: html, whisper: [ChatMessage.getWhisperRecipients(this.name), ChatMessage.getWhisperRecipients("GM") ] } ); @@ -341,7 +341,7 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ computeCurrentWounds( ) { - let wounds = this.data.data.wounds; + let wounds = this.system.wounds; return wounds.light + (wounds.moderate*2) + (wounds.severe*3) + (wounds.critical*4); } @@ -349,14 +349,14 @@ export class SoSActor extends Actor { async applyConsequenceWound( severity, consequenceName) { if ( severity == 'none') return; // Nothing ! - let wounds = duplicate(this.data.data.wounds); + let wounds = duplicate(this.system.wounds); if (severity == 'light' ) wounds.light += 1; if (severity == 'moderate' ) wounds.moderate += 1; if (severity == 'severe' ) wounds.severe += 1; if (severity == 'critical' ) wounds.critical += 1; let sumWound = wounds.light + (wounds.moderate*2) + (wounds.severe*3) + (wounds.critical*4); - let currentWounds = duplicate(this.data.data.scores.currentwounds); + let currentWounds = duplicate(this.system.scores.currentwounds); currentWounds.value = sumWound; await this.update( { 'data.scores.currentwounds': currentWounds, 'data.wounds': wounds } ); @@ -366,7 +366,7 @@ export class SoSActor extends Actor { severity: severity, wounds: wounds, currentWounds: sumWound, - totalWounds: this.data.data.scores.wound.value + totalWounds: this.system.scores.wound.value } let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-damage-consequence.html', woundData ); ChatMessage.create( { content: html, whisper: ChatMessage.getWhisperRecipients(this.name).concat(ChatMessage.getWhisperRecipients("GM")) } ); @@ -376,22 +376,22 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ async addObjectToContainer( itemId, containerId ) { - let container = this.data.items.find( item => item.id == containerId && item.type == 'container') - let object = this.data.items.find( item => item.id == itemId ) + let container = this.items.find( item => item.id == containerId && item.type == 'container') + let object = this.items.find( item => item.id == itemId ) console.log("Found", container, object) if ( container ) { if ( object.type == 'container') { ui.notifications.warn("Only 1 level of container... sorry"); return } - let alreadyInside = this.data.items.filter( item => item.data.data.containerid && item.data.data.containerid == containerId); - if ( alreadyInside.length >= container.data.data.container ) { + let alreadyInside = this.items.filter( item => item.system.containerid && item.system.containerid == containerId); + if ( alreadyInside.length >= container.system.container ) { ui.notifications.warn("Container is already full !"); } else { - await this.updateEmbeddedDocuments( "Item", [{ _id: object.id, 'data.containerid':containerId }]); + await this.updateEmbeddedDocuments( "Item", [{ _id: object.id, 'system.containerid':containerId }]); } - } else if ( object && object.data.data.containerid) { // remove from container - await this.updateEmbeddedDocuments( "Item", [{ _id: object.id, 'data.containerid':"" }]); + } else if ( object && object.system.containerid) { // remove from container + await this.updateEmbeddedDocuments( "Item", [{ _id: object.id, 'system.containerid':"" }]); } } @@ -403,7 +403,7 @@ export class SoSActor extends Actor { return; } - let wounds = duplicate(this.data.data.wounds); + let wounds = duplicate(this.system.wounds); for (let wound of flipData.woundsList ) { if (wound == 'L' ) wounds.light += 1; if (wound == 'M' ) wounds.moderate += 1; @@ -412,30 +412,30 @@ export class SoSActor extends Actor { } // Compute total let sumWound = wounds.light + (wounds.moderate*2) + (wounds.severe*3) + (wounds.critical*4); - let currentWounds = duplicate(this.data.data.scores.currentwounds); + let currentWounds = duplicate(this.system.scores.currentwounds); currentWounds.value = sumWound; - if ( sumWound >= this.data.data.scores.wound.value) { - let bleeding = this.data.items.find( item => item.type == 'consequence' && item.name == 'Bleeding'); - let newSeverity = SoSUtility.increaseConsequenceSeverity( bleeding.data.severity ); - await this.updateEmbeddedDocuments( "Item", [ { _id: bleeding.id, 'data.severity': newSeverity} ] ); + if ( sumWound >= this.system.scores.wound.value) { + let bleeding = this.items.find( item => item.type == 'consequence' && item.name == 'Bleeding'); + let newSeverity = SoSUtility.increaseConsequenceSeverity( bleeding.system.severity ); + await this.updateEmbeddedDocuments( "Item", [ { _id: bleeding.id, 'system.severity': newSeverity} ] ); flipData.isBleeding = newSeverity; } // Stun consequence if ( flipData.nbStun > 0) { - let stun = this.data.items.find( item => item.type == 'consequence' && item.name == 'Stun'); - let newSeverity = stun.data.severity; + let stun = this.items.find( item => item.type == 'consequence' && item.name == 'Stun'); + let newSeverity = stun.system.severity; for(let i=0; i foundry.utils.deepClone(e.data)), + data: foundry.utils.deepClone(this.object.system), + effects: this.object.effects.map(e => foundry.utils.deepClone(e.system)), limited: this.object.limited, options: this.options, owner: this.document.isOwner @@ -61,10 +61,10 @@ export class SoSItemSheet extends ItemSheet { formData.isGM = game.user.isGM; if ( objectData.type == 'skillexperience') { - formData.skillList = await SoSUtility.loadCompendiumNames("foundryvtt-shadows-over-sol.skills"); + formData.skillList = await SoSUtility.loadCompendiumNames("foundryvtt-shadows-over-sol.skills") } if ( objectData.type == 'skill' && this.object.options?.actor) { - formData.skillExperienceList = this.object.options.actor.getSkillExperience( data.item.name ); + formData.skillExperienceList = this.object.options.actor.getSkillExperience( objectData.name ) } return formData; } diff --git a/module/sos-combat.js b/module/sos-combat.js index 6dc6842..f35d452 100644 --- a/module/sos-combat.js +++ b/module/sos-combat.js @@ -15,7 +15,7 @@ export class SoSCombat extends Combat { for( let combatant of this.combatants) { this.setInitiative(combatant._id, -1 ); // Reset init let uniq = randomID(16); - const name = combatant.actor ? combatant.actor.data.name : combatant.name; + const name = combatant.actor ? combatant.actor.name : combatant.name; if ( combatant.players[0]) { // A player controls this combatant -> message ! ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${name} for round ${this.round} !
        diff --git a/module/sos-flip-dialog.js b/module/sos-flip-dialog.js index e13e2b2..ef6515b 100644 --- a/module/sos-flip-dialog.js +++ b/module/sos-flip-dialog.js @@ -30,7 +30,7 @@ export class SoSFlipDialog extends Dialog { if ( this.flipData.mode == 'skill' || this.flipData.mode == 'weapon' ) { let statKey = $('#statSelect').val(); this.flipData.stat = duplicate( this.flipData.statList[ statKey ] ); - scoreBase = Math.floor(this.flipData.statList[ statKey ].value / 2) + this.flipData.skill.data.value; + scoreBase = Math.floor(this.flipData.statList[ statKey ].value / 2) + this.flipData.skill.system.value } else { //Stat mode let statKey = $('#statSelect').val(); scoreBase = this.flipData.stat.value; @@ -62,7 +62,7 @@ export class SoSFlipDialog extends Dialog { $('.edge-card').click((event) => { let flipData = this.flipData; flipData.modifier = $('#modifier').val(); - flipData.tn = (flipData.target) ? flipData.target.actor.data.data.scores.defense.value : $('#tn').val(); + flipData.tn = (flipData.target) ? flipData.target.actor.system.scores.defense.value : $('#tn').val(); flipData.edgeName = event.currentTarget.attributes['data-edge-card'].value; flipData.edgeLuck = $('#edge-luck').is(":checked"); flipData.cardOrigin = "Edge"; @@ -94,7 +94,7 @@ export class SoSFlipDialog extends Dialog { for (let consequenceId of this.flipData.consequencesSelected) { let consequence = this.flipData.consequencesList.find( item => item._id == consequenceId); console.log(consequence, consequenceId); - malusConsequence += SoSUtility.getConsequenceMalus( consequence.data.severity ); + malusConsequence += SoSUtility.getConsequenceMalus( consequence.system.severity ); } $('#consequence-malus').text(malusConsequence); this.flipData.malusConsequence = malusConsequence; @@ -108,7 +108,7 @@ export class SoSFlipDialog extends Dialog { for (let consequenceId of this.flipData.consequencesSelected) { let consequence = this.flipData.consequencesList.find( item => item._id == consequenceId); console.log(consequence, consequenceId); - bonusConsequence += SoSUtility.getConsequenceBonus( consequence.data.severity ); + bonusConsequence += SoSUtility.getConsequenceBonus( consequence.system.severity ); } $('#consequence-bonus').text(bonusConsequence); this.flipData.bonusConsequence = bonusConsequence; @@ -164,7 +164,7 @@ export class SoSFlipDialog extends Dialog { flipData.stat = duplicate( flipData.statList[ statKey ] ); } flipData.cardOrigin = "Deck"; - flipData.tn = (flipData.target) ? flipData.target.actor.data.data.scores.defense.value : $('#tn').val(); + flipData.tn = (flipData.target) ? flipData.target.actor.system.scores.defense.value : $('#tn').val(); dialog.flipData.actor.cardDeck.doFlipFromDeckOrEdge(flipData); dialog.onFlipClose(); }); diff --git a/module/sos-main.js b/module/sos-main.js index b52a6bc..d4f5f99 100644 --- a/module/sos-main.js +++ b/module/sos-main.js @@ -97,6 +97,7 @@ function registerUsageCount( registerKey ) { name: "Unique world key", scope: "world", config: false, + default: "XXX", type: String }); @@ -106,7 +107,7 @@ function registerUsageCount( registerKey ) { game.settings.set(registerKey, "world-key", worldKey ) } // Simple API counter - let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.data.version}"` + let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.version}"` $.ajax(regURL) /* -------------------------------------------- */ } diff --git a/module/sos-utility.js b/module/sos-utility.js index 89eadb9..0809f09 100644 --- a/module/sos-utility.js +++ b/module/sos-utility.js @@ -55,20 +55,6 @@ export class SoSUtility { } } - /* -------------------------------------------- */ - static data(it) { - if (it instanceof Actor || it instanceof Item || it instanceof Combatant) { - return it.data; - } - return it; - } - - - /* -------------------------------------------- */ - static templateData(it) { - return SoSUtility.data(it)?.data ?? {} - } - /* -------------------------------------------- */ static async loadCompendiumData(compendium) { const pack = game.packs.get(compendium); @@ -411,13 +397,14 @@ export class SoSUtility { /* -------------------------------------------- */ static async processItemDropEvent(actorSheet, event) { let dragData = JSON.parse(event.dataTransfer.getData("text/plain")); - let dropID = $(event.target).parents(".item").attr("data-item-id"); // Only relevant if container drop - let objectID = dragData.id || dragData.data._id; - //console.log("drag/drop", dragData, actorSheet.actor._id, dropID, objectID); - if (dragData.type == 'Item' && dropID) { - actorSheet.actor.addObjectToContainer(objectID, dropID ); + const item = fromUuidSync(dragData.uuid) + let dropId = $(event.target).parents(".item").attr("data-item-id"); // Only relevant if container drop + let objectId = item.id + console.log("ID", dragData, dropId, objectId) + if (dragData.type == 'Item' && dropId) { + actorSheet.actor.addObjectToContainer(objectId, dropId ); } - return true; + return true } } \ No newline at end of file diff --git a/system.json b/system.json index 8d80e04..a763db9 100644 --- a/system.json +++ b/system.json @@ -1,5 +1,5 @@ { - "name": "foundryvtt-shadows-over-sol", + "id": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", "author": "LeRatierBretonnien", @@ -7,9 +7,13 @@ "url": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", "flags": {}, - "version": "2.0.6", - "minimumCoreVersion": "0.8.0", - "compatibleCoreVersion": "9", + "version": "10.0.0", + "compatibility": { + "minimum": 10, + "verified": 10, + "maximum": 10 + }, + "templateVersion": 50, "scripts": [], "esmodules": [ "module/sos-main.js" @@ -98,11 +102,10 @@ "private": false } ], - "system": [], - "dependencies": [], + "relationships": { }, "socket": true, "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/master/system.json", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-2.0.6.zip", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.0.zip", "protected": false, "gridDistance": 5, "gridUnits": "ft" diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 8099bcd..98cc4d3 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -5,8 +5,8 @@
        - -

        + +

        @@ -37,23 +37,23 @@ XP
      • - {{#each data.data.stats as |stat key|}} + {{#each data.stats as |stat key|}} {{#if stat.isLevelUp}}
      • - + {{localize 'STAT.levelUp'}} {{else}}
      • {{/if}} - {{localize stat.label}} - {{#select stat.value}} {{>"systems/foundryvtt-shadows-over-sol/templates/stat-option-list.html"}} {{/select}} - +
      • {{/each}} @@ -66,14 +66,14 @@ Value Bonus/Malus - {{#each data.data.scores as |score key|}} + {{#each data.scores as |score key|}}
      • - {{localize score.label}} - + {{localize score.label}} + {{#if (eq key 'defense')}} - + {{/if}} - +
      • {{/each}}
      @@ -116,13 +116,13 @@
        {{#each skill1 as |skill key|}} - {{#if skill.data.isLevelUp}} + {{#if skill.system.isLevelUp}}
      • {{else}}
      • {{/if}} - {{#if skill.data.isLevelUp}} + {{#if skill.system.isLevelUp}} @@ -130,8 +130,8 @@ {{else}} {{skill.name}} {{/if}} - - + +
        @@ -144,13 +144,13 @@
          {{#each skill2 as |skill key|}} - {{#if skill.data.isLevelUp}} + {{#if skill.system.isLevelUp}}
        • {{else}}
        • {{/if}} - {{#if skill.data.isLevelUp}} + {{#if skill.system.isLevelUp}} @@ -158,8 +158,8 @@ {{else}} {{skill.name}} {{/if}} - - + +
          @@ -182,16 +182,16 @@
          • Wounds :

          • Light : - +
          • Moderate : - +
          • Severe : - +
          • Critical : - +
          • Total : {{data.currentWounds}} / {{data.totalWounds}} @@ -204,8 +204,8 @@
          • {{conseq.name}} - + {{#select conseq.system.severity}} @@ -236,7 +236,7 @@ {{weapon.name}} @@ -248,9 +248,9 @@ {{#each armors as |armor key|}}
          • - {{armor.data.name}} + {{armor.name}} @@ -262,9 +262,9 @@ {{#each gearsRoot as |gear key|}}
          • - {{gear.data.name}} + {{gear.name}} @@ -273,9 +273,9 @@ {{#each data.contains as |subgear key|}}
          • - {{subgear.data.name}} + {{subgear.name}} @@ -292,11 +292,11 @@
            • - +
            • - {{#select subculture}} {{#each subcultureList as |subculture key|}} @@ -306,29 +306,29 @@
            • - +
            • - +
            • - +
            • - +
            • - +
            • - +
            @@ -390,12 +390,12 @@

            Biography :

            - {{editor content=data.data.history target="data.history" button=true owner=owner editable=editable}} + {{editor data.history target="system.history" button=true owner=owner editable=editable}}

            Notes :

            - {{editor content=data.data.notes target="data.notes" button=true owner=owner editable=editable}} + {{editor data.notes target="system.notes" button=true owner=owner editable=editable}}

            {{>"systems/foundryvtt-shadows-over-sol/templates/editor-notes-gm.html"}} diff --git a/templates/dialog-combat-actions.html b/templates/dialog-combat-actions.html index 2b2c65d..3d143eb 100644 --- a/templates/dialog-combat-actions.html +++ b/templates/dialog-combat-actions.html @@ -53,7 +53,7 @@ @@ -74,7 +74,7 @@ diff --git a/templates/dialog-flip.html b/templates/dialog-flip.html index 957bd91..b4cd5b9 100644 --- a/templates/dialog-flip.html +++ b/templates/dialog-flip.html @@ -22,7 +22,7 @@ {{/select}} -

            Skill Flip : {{skill.name}} ({{skill.data.value}})

            +

            Skill Flip : {{skill.name}} ({{skill.system.value}})

            Final Score : 0

            {{/if}} @@ -44,7 +44,7 @@ @@ -56,7 +56,7 @@ @@ -66,7 +66,7 @@
            {{#each weaknessList as |weakness key|}} - {{localize weakness.name}} - {{weakness.data.category}} + {{localize weakness.name}} - {{weakness.system.category}} {{/each}}
            @@ -90,7 +90,7 @@
            {{#if target}}
            -

            Target : {{target.actor.name}} - Defense : {{target.actor.data.data.scores.defense.value}}/{{target.actor.data.data.scores.defense.critical}}

            +

            Target : {{target.actor.name}} - Defense : {{target.actor.system.scores.defense.value}}/{{target.actor.system.scores.defense.critical}}

            {{/if}} @@ -99,7 +99,7 @@
            {{#if target}} - + {{else}} +

            @@ -13,7 +13,7 @@
            - {{#select data.type}} @@ -27,16 +27,16 @@
            - +
            - +
            - {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} + {{editor data.description target="system.description" button=true owner=owner editable=editable}}
            diff --git a/templates/item-armor-sheet.html b/templates/item-armor-sheet.html index 49b68c2..c6437d1 100644 --- a/templates/item-armor-sheet.html +++ b/templates/item-armor-sheet.html @@ -1,42 +1,40 @@
            - +
            -

            +

            {{!-- Sheet Body --}}
            - {{#with data}}
            - +
            - +
            - +
            - +
            - +
            - +
            - {{/with}} {{>"systems/foundryvtt-shadows-over-sol/templates/item-commongear-sheet.html"}}
            diff --git a/templates/item-commongear-sheet.html b/templates/item-commongear-sheet.html index 09167c7..ea91518 100644 --- a/templates/item-commongear-sheet.html +++ b/templates/item-commongear-sheet.html @@ -1,53 +1,51 @@ - {{#with data}}
            - +
            - +
            - +
            - +
            - +
            - +
            - +
            - +
            - +
            - +
            - +
            - {{/with}}
            - {{editor content=data.data.description target="data.description" button=true owner=owner editable=editable}} + {{editor data.description target="system.description" button=true owner=owner editable=editable}}
            diff --git a/templates/item-consequence-sheet.html b/templates/item-consequence-sheet.html index d6cae1d..ead2e39 100644 --- a/templates/item-consequence-sheet.html +++ b/templates/item-consequence-sheet.html @@ -1,8 +1,8 @@
            - +
            -

            +

            @@ -13,8 +13,8 @@
            - + {{#select data.severity}} @@ -27,7 +27,7 @@
            - {{editor content=data.data.description target="data.description" button=true owner=owner editable=editable}} + {{editor data.description target="system.description" button=true owner=owner editable=editable}}
            diff --git a/templates/item-container-sheet.html b/templates/item-container-sheet.html index 9b7a727..5c50ae3 100644 --- a/templates/item-container-sheet.html +++ b/templates/item-container-sheet.html @@ -1,8 +1,8 @@
            - +
            -

            +

            @@ -13,7 +13,7 @@
            - +
            {{>"systems/foundryvtt-shadows-over-sol/templates/item-commongear-sheet.html"}}
            diff --git a/templates/item-gear-sheet.html b/templates/item-gear-sheet.html index 181a526..8cc50e4 100644 --- a/templates/item-gear-sheet.html +++ b/templates/item-gear-sheet.html @@ -1,8 +1,8 @@
            - +
            -

            +

            diff --git a/templates/item-geneline-sheet.html b/templates/item-geneline-sheet.html index 22154cc..ab52044 100644 --- a/templates/item-geneline-sheet.html +++ b/templates/item-geneline-sheet.html @@ -1,42 +1,40 @@
            - +
            -

            +

            {{!-- Sheet Body --}}
            - {{#with data}}
            - {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} + {{editor data.description target="system.description" button=true owner=owner editable=editable}}
            - +
            - +
            - {{editor content=data.weakness target="data.weakness" button=true owner=owner editable=editable}} + {{editor data.weakness target="system.weakness" button=true owner=owner editable=editable}}
            - {{/with}}
            diff --git a/templates/item-injury-sheet.html b/templates/item-injury-sheet.html index 76ea621..433d531 100644 --- a/templates/item-injury-sheet.html +++ b/templates/item-injury-sheet.html @@ -1,27 +1,26 @@
            - +
            -

            +

            {{!-- Sheet Body --}}
            - {{#with data}} +
            - +
            - {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} + {{editor data.description target="system.description" button=true owner=owner editable=editable}}
          - {{/with}} diff --git a/templates/item-language-sheet.html b/templates/item-language-sheet.html index 5bfc7b2..216ebc0 100644 --- a/templates/item-language-sheet.html +++ b/templates/item-language-sheet.html @@ -1,8 +1,8 @@
          - +
          -

          +

          @@ -13,7 +13,7 @@
          - {{editor content=data.ata.description target="data.description" button=true owner=owner editable=editable}} + {{editor data.description target="system.description" button=true owner=owner editable=editable}}
        diff --git a/templates/item-malady-sheet.html b/templates/item-malady-sheet.html index b826474..67daede 100644 --- a/templates/item-malady-sheet.html +++ b/templates/item-malady-sheet.html @@ -1,33 +1,32 @@
        - +
        -

        +

        {{!-- Sheet Body --}}
        - {{#with data}} -
        + +
        - +
        - +
        - +
        - {{editor content=data.notes target="data.notes" button=true owner=owner editable=editable}} + {{editor data.notes target="system.notes" button=true owner=owner editable=editable}}
        - {{/with}}
        diff --git a/templates/item-skill-sheet.html b/templates/item-skill-sheet.html index 5e5f07e..3c65779 100644 --- a/templates/item-skill-sheet.html +++ b/templates/item-skill-sheet.html @@ -1,8 +1,8 @@
        - +
        -

        +

        @@ -11,7 +11,7 @@
          -
        • +
          • Experiences list : @@ -27,7 +27,7 @@ {{/each}}
          - {{editor content=data.data.description target="data.description" button=true owner=owner editable=editable}} + {{editor data.description target="system.description" button=true owner=owner editable=editable}}
        diff --git a/templates/item-skillexperience-sheet.html b/templates/item-skillexperience-sheet.html index fe3f1c2..b37462a 100644 --- a/templates/item-skillexperience-sheet.html +++ b/templates/item-skillexperience-sheet.html @@ -1,19 +1,19 @@
        - +
        -

        +

        {{!-- Sheet Body --}}
        - {{#with data}} -
        + +
        - {{#select data.skill}} {{#each skillList as |skill key|}} @@ -25,11 +25,10 @@
        - {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} + {{editor data.description target="system.description" button=true owner=owner editable=editable}}
        - {{/with}}
        diff --git a/templates/item-subculture-sheet.html b/templates/item-subculture-sheet.html index 5b3b9fa..e40926c 100644 --- a/templates/item-subculture-sheet.html +++ b/templates/item-subculture-sheet.html @@ -1,30 +1,28 @@
        - +
        -

        +

        {{!-- Sheet Body --}}
        - {{#with data}}
        - {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} + {{editor data.description target="system.description" button=true owner=owner editable=editable}}
        - +
        - {{/with}}
        diff --git a/templates/item-vehicle-sheet.html b/templates/item-vehicle-sheet.html index f0204d4..e2aaaef 100644 --- a/templates/item-vehicle-sheet.html +++ b/templates/item-vehicle-sheet.html @@ -1,8 +1,8 @@
        - +
        -

        +

        @@ -10,32 +10,30 @@
        - {{#with data}}
        - +
        - +
        - +
        - +
        - +
        - +
        - {{/with}} {{>"systems/foundryvtt-shadows-over-sol/templates/item-commongear-sheet.html"}}
        diff --git a/templates/item-weakness-sheet.html b/templates/item-weakness-sheet.html index 53d6c61..4706f9f 100644 --- a/templates/item-weakness-sheet.html +++ b/templates/item-weakness-sheet.html @@ -1,20 +1,19 @@
        - +
        -

        +

        {{!-- Sheet Body --}}
        - {{#with data}}
        - {{#select data.category}} @@ -27,11 +26,10 @@
        - {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} + {{editor data.description target="system.description" button=true owner=owner editable=editable}}
        - {{/with}}
        diff --git a/templates/item-weapon-sheet.html b/templates/item-weapon-sheet.html index 408a90d..6ed4bf9 100644 --- a/templates/item-weapon-sheet.html +++ b/templates/item-weapon-sheet.html @@ -1,20 +1,19 @@
        - +
        -

        +

        {{!-- Sheet Body --}}
        - {{#with data}}
        - {{#select data.category}} @@ -27,63 +26,62 @@
        - + - + - + - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - +
        - {{/with}} {{>"systems/foundryvtt-shadows-over-sol/templates/item-commongear-sheet.html"}}
        -- 2.35.3 From e52b62a314fab4bb6f125f70cc02bd47567b8ffb Mon Sep 17 00:00:00 2001 From: sladecraven Date: Wed, 13 Jul 2022 08:12:58 +0200 Subject: [PATCH 33/47] v10 branch - Update manifest --- system.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system.json b/system.json index a763db9..ddff9c5 100644 --- a/system.json +++ b/system.json @@ -104,7 +104,7 @@ ], "relationships": { }, "socket": true, - "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/master/system.json", + "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/v10/system.json", "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.0.zip", "protected": false, "gridDistance": 5, -- 2.35.3 From 1f0506f5c27abc49e7895e4f6ae22181301ca4c8 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sun, 17 Jul 2022 20:53:25 +0200 Subject: [PATCH 34/47] v10 compatibility --- module/actor.js | 8 +- module/sos-combat.js | 150 +++++++++++++++------------- module/sos-dialog-combat-actions.js | 2 +- module/sos-gm-deck.js | 2 +- 4 files changed, 86 insertions(+), 76 deletions(-) diff --git a/module/actor.js b/module/actor.js index 2cfc82f..6978a34 100644 --- a/module/actor.js +++ b/module/actor.js @@ -335,7 +335,7 @@ export class SoSActor extends Actor { totalWounds: this.system.scores.wound.value } let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-character-death.html', woundData ); - ChatMessage.create( { content: html, whisper: [ChatMessage.getWhisperRecipients(this.name), ChatMessage.getWhisperRecipients("GM") ] } ); + ChatMessage.create( { content: html, whisper: ChatMessage.getWhisperRecipients(this.name).concat(ChatMessage.getWhisperRecipients("GM") ) } ) } } @@ -369,7 +369,7 @@ export class SoSActor extends Actor { totalWounds: this.system.scores.wound.value } let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-damage-consequence.html', woundData ); - ChatMessage.create( { content: html, whisper: ChatMessage.getWhisperRecipients(this.name).concat(ChatMessage.getWhisperRecipients("GM")) } ); + ChatMessage.create( { content: html, whisper: ChatMessage.getWhisperRecipients(this.name).concat(ChatMessage.getWhisperRecipients("GM")) } ) this.checkDeath(); } @@ -399,7 +399,7 @@ export class SoSActor extends Actor { async applyWounds( flipData ) { if ( flipData.damageStatus == 'no_damage') { let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-nodamage-taken.html', flipData ); - ChatMessage.create( { content: html, whisper: [ChatMessage.getWhisperRecipients(this.name), ChatMessage.getWhisperRecipients("GM") ] } ); + ChatMessage.create( { content: html, whisper: ChatMessage.getWhisperRecipients(this.name).concat(ChatMessage.getWhisperRecipients("GM")) } ); return; } @@ -437,7 +437,7 @@ export class SoSActor extends Actor { flipData.currentWounds = sumWound; flipData.totalWounds = this.system.scores.wound.value; let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-damage-taken.html', flipData ); - ChatMessage.create( { content: html, whisper: [ChatMessage.getWhisperRecipients(this.name), ChatMessage.getWhisperRecipients("GM") ] } ); + ChatMessage.create( { content: html, whisper: ChatMessage.getWhisperRecipients(this.name).concat(ChatMessage.getWhisperRecipients("GM")) } ); this.checkDeath(); } diff --git a/module/sos-combat.js b/module/sos-combat.js index f35d452..24c5db7 100644 --- a/module/sos-combat.js +++ b/module/sos-combat.js @@ -5,26 +5,30 @@ import { SoSDialogCombatActions } from "./sos-dialog-combat-actions.js"; /* -------------------------------------------- */ export class SoSCombat extends Combat { - + /* -------------------------------------------- */ requestActions() { - if ( game.user.isGM && !this.actionsRequested) { - console.log("REQUEST ACTIONS !!!"); + if (game.user.isGM && !this.actionsRequested) { + console.log("REQUEST ACTIONS !!!") this.actionsRequested = true; this.phaseSetup = {}; // Reset each new round/update - for( let combatant of this.combatants) { - this.setInitiative(combatant._id, -1 ); // Reset init - let uniq = randomID(16); + for (let combatant of this.combatants) { + this.setInitiative(combatant.id, -1); // Reset init + let uniq = randomID(16) const name = combatant.actor ? combatant.actor.name : combatant.name; - if ( combatant.players[0]) { + if (combatant.players && combatant.players[0]) { // A player controls this combatant -> message ! - ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${name} for round ${this.round} !
        - Declare actions`, - whisper: [ combatant.players[0].data._id] } ); + ChatMessage.create({ + content: `New round ! Click on the button below to declare the actions of ${name} for round ${this.round} !
        + Declare actions`, + whisper: [combatant.players[0].id] + }); } else { - ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${name} for round ${this.round} !
        - Declare actions`, - whisper: [ ChatMessage.getWhisperRecipients("GM") ] } ); + ChatMessage.create({ + content: `New round ! Click on the button below to declare the actions of ${name} for round ${this.round} !
        + Declare actions`, + whisper: ChatMessage.getWhisperRecipients("GM"), + }); } } } @@ -39,56 +43,61 @@ export class SoSCombat extends Combat { /* -------------------------------------------- */ gotoNextTurn() { this.phaseNumber -= 1; - if ( this.phaseNumber <= 0) { + if (this.phaseNumber <= 0) { this.applyConsequences(); this.nextRound(); // Auto-switch to next round - } else { + } else { this.nextTurn(); } } /* -------------------------------------------- */ async nextTurn() { - console.log("Going to phase !", this.phaseNumber ); + console.log("Going to phase !", this.phaseNumber); // Get all actions for this phase let phaseIndex = this.phaseNumber - 1; let actionList = []; let actionMsg = `

        Actions for phase ${this.phaseNumber}

        `; - for (let combatantId in this.phaseSetup ) { + for (let combatantId in this.phaseSetup) { let actionData = this.phaseSetup[combatantId]; - if ( actionData.phaseArray[phaseIndex].name != 'No Action' ) { - let combatant = this.combatants.find( comb => comb._id == actionData.combatantId); - const name = combatant.actor ? combatant.actor.data.name : combatant.name; - actionList.push( { combatant: combatant, - action: actionData.phaseArray[phaseIndex], - isDone: false - }); + if (actionData.phaseArray[phaseIndex].name != 'No Action') { + let combatant = this.combatants.find(comb => comb._id == actionData.combatantId); + const name = combatant.actor ? combatant.actor.name : combatant.name; + actionList.push({ + combatant: combatant, + action: actionData.phaseArray[phaseIndex], + isDone: false + }); actionMsg += `
        ${name} is going to : ${actionData.phaseArray[phaseIndex].name}`; } } - if ( actionList.length == 0) { + if (actionList.length == 0) { actionMsg += "
        No actions for the phase !"; this.gotoNextTurn(); } // Display a nice message - ChatMessage.create( { content: actionMsg }); + ChatMessage.create({ content: actionMsg }); // Now push specific messages - for ( let action of actionList) { + for (let action of actionList) { let uniq = randomID(16); action.uniqId = uniq; // Easy tracking with chat messages - const name = action.combatant.actor ? action.combatant.actor.data.name : action.combatant.name; - if ( action.combatant.players[0]) { + const name = action.combatant.actor ? action.combatant.actor.name : action.combatant.name; + if (action.combatant.players[0]) { // A player controls this combatant -> message ! - ChatMessage.create( { content: `Phase ${this.phaseNumber} ! ${name} must perform a ${action.action.name} action. + ChatMessage.create({ + content: `Phase ${this.phaseNumber} ! ${name} must perform a ${action.action.name} action. When done, click on the button below to close the action. - Action is done !`, - whisper: [ action.combatant.players[0].data._id] } ); + Action is done !`, + whisper: [action.combatant.players[0].id] + }); } else { - ChatMessage.create( { content: `Phase ${this.phaseNumber} ! ${name} must perform a ${action.action.name} action.
        + ChatMessage.create({ + content: `Phase ${this.phaseNumber} ! ${name} must perform a ${action.action.name} action.
        When done, click on the button below to close the action. - Action is done !`, - whisper: [ ChatMessage.getWhisperRecipients("GM") ] } ); + Action is done !`, + whisper: ChatMessage.getWhisperRecipients("GM") + }); } } // Save for easy access @@ -96,28 +105,28 @@ export class SoSCombat extends Combat { } /* -------------------------------------------- */ - applyConsequences( ) { - if (game.user.isGM ) { - for( let combatant of this.combatants) { + applyConsequences() { + if (game.user.isGM) { + for (let combatant of this.combatants) { if (!combatant.actor) continue; // Can't check tokens without assigned actors, Maybe print chat message about bleeding happening so that the GM can manually track this? - let bleeding = combatant.actor.data.items.find( item => item.type == 'consequence' && item.name == 'Bleeding'); - combatant.actor.applyConsequenceWound( bleeding.data.severity, "bleeding" ); + let bleeding = combatant.actor.items.find(item => item.type == 'consequence' && item.name == 'Bleeding'); + combatant.actor.applyConsequenceWound(bleeding.system.severity, "bleeding"); } } } /* -------------------------------------------- */ - closeAction( uniqId) { + closeAction(uniqId) { // Delete message ! - const toDelete = game.messages.filter(it => it.data.content.includes( uniqId )); - toDelete.forEach(it => it.delete()); + const toDelete = game.messages.filter(it => it.content.includes(uniqId)); + toDelete.forEach(it => it.delete()) - let action = this.currentActions.find( _action => _action.uniqId == uniqId ); + let action = this.currentActions.find(_action => _action.uniqId == uniqId); if (action) { action.isDone = true; - let filtered = this.currentActions.filter( _action => action.isDone ); - if ( filtered.length == this.currentActions.length) { // All actions closed ! + let filtered = this.currentActions.filter(_action => action.isDone); + if (filtered.length == this.currentActions.length) { // All actions closed ! console.log("Going next turn !!!"); this.gotoNextTurn(); } @@ -125,22 +134,22 @@ export class SoSCombat extends Combat { } /* -------------------------------------------- */ - getPhaseRank( actionConf) { - for (let i=2; i>=0; i--) { + getPhaseRank(actionConf) { + for (let i = 2; i >= 0; i--) { let action = actionConf.phaseArray[i]; if (action.name != "No Action") { - return i+1; + return i + 1; } } return 0; } /* -------------------------------------------- */ - getAPFromActor( actorId ) { - for( let combatant of this.combatants) { + getAPFromActor(actorId) { + for (let combatant of this.combatants) { //console.log(combatant); - if ( combatant.actor.data._id == actorId ) { - let phase = this.phaseSetup[combatant._id]; + if (combatant.actor.id == actorId) { + let phase = this.phaseSetup[combatant.id]; return phase.remainingAP; } } @@ -148,42 +157,43 @@ export class SoSCombat extends Combat { } /* -------------------------------------------- */ - decreaseAPFromActor( actorId ) { - for( let combatant of this.combatants) { + decreaseAPFromActor(actorId) { + for (let combatant of this.combatants) { //console.log(combatant); - if ( combatant.actor.data._id == actorId ) { - let phase = this.phaseSetup[combatant._id]; + if (combatant.actor.id == actorId) { + let phase = this.phaseSetup[combatant.id]; phase.remainingAP -= 1; - if ( phase.remainingAP < 0 ) phase.remainingAP = 0; + if (phase.remainingAP < 0) phase.remainingAP = 0; } } } - + /* -------------------------------------------- */ async setupActorActions(actionConf) { console.log("Setting combat for phase : ", actionConf, actionConf.uniqId); // Delete message ! - const toDelete = game.messages.filter(it => it.data.content.includes( actionConf.uniqId )); - console.log("MESSAGE : ", toDelete); + const toDelete = game.messages.filter(it => it.content.includes(actionConf.uniqId)); toDelete.forEach(it => it.delete()); - if ( !this.phaseSetup) this.phaseSetup = {}; // Opportunistic init - + if (!this.phaseSetup) this.phaseSetup = {}; // Opportunistic init + // Keep track this.phaseSetup[actionConf.combatantId] = actionConf; - console.log( this.combatants ); + console.log(this.combatants); //let combatant = this.combatants.find( comb => comb._id == actionConf.combatantId); - await this.setInitiative( actionConf.combatantId, this.getPhaseRank( actionConf ) ); + await this.setInitiative(actionConf.combatantId, this.getPhaseRank(actionConf)); let actionsDone = true - for( let combatant of this.combatants) { - if ( combatant.initiative == -1 ) actionsDone = false; + for (let combatant of this.combatants) { + if (combatant.initiative == -1) actionsDone = false; } - if ( actionsDone ) { + if (actionsDone) { this.actionsRequested = false; - ChatMessage.create( { content: `Action declaration has been completed ! Now proceeding with actions.`, - whisper: [ ChatMessage.getWhisperRecipients("GM") ] } ); + ChatMessage.create({ + content: `Action declaration has been completed ! Now proceeding with actions.`, + whisper: ChatMessage.getWhisperRecipients("GM") + }) this.phaseNumber = 3; this.nextTurn(); } diff --git a/module/sos-dialog-combat-actions.js b/module/sos-dialog-combat-actions.js index 3fba332..823e539 100644 --- a/module/sos-dialog-combat-actions.js +++ b/module/sos-dialog-combat-actions.js @@ -12,7 +12,7 @@ export class SoSDialogCombatActions extends Dialog { actionPoints: SoSUtility.fillRange(0, 6), combatId: combatId, combatantId: combatantId, - combatantsList: combat.data.combatants, + combatantsList: combat.combatants, uniqId: uniqId, round: round } diff --git a/module/sos-gm-deck.js b/module/sos-gm-deck.js index 5320885..915a210 100644 --- a/module/sos-gm-deck.js +++ b/module/sos-gm-deck.js @@ -60,7 +60,7 @@ export class SoSGMDeck extends Dialog { let cardPath = `systems/foundryvtt-shadows-over-sol/img/cards/${card.cardName}.webp`; let cardData = { card: card, cardPath: cardPath }; let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-card.html', cardData ); - ChatMessage.create( { content: html, whisper: [ ChatMessage.getWhisperRecipients("GM") ] }); + ChatMessage.create( { content: html, whisper: ChatMessage.getWhisperRecipients("GM") } ); //dialog.onFlipClose(); } -- 2.35.3 From bef1750231c52c4db6e3f6598ceb08af77257589 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Sun, 17 Jul 2022 20:54:13 +0200 Subject: [PATCH 35/47] v10 compatibility --- system.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system.json b/system.json index ddff9c5..6252c6b 100644 --- a/system.json +++ b/system.json @@ -7,7 +7,7 @@ "url": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", "flags": {}, - "version": "10.0.0", + "version": "10.0.1", "compatibility": { "minimum": 10, "verified": 10, @@ -105,7 +105,7 @@ "relationships": { }, "socket": true, "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/v10/system.json", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.0.zip", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.1.zip", "protected": false, "gridDistance": 5, "gridUnits": "ft" -- 2.35.3 From d94c1a4dcec35f797a4b5d71b5254fb5fc7881ab Mon Sep 17 00:00:00 2001 From: sladecraven Date: Mon, 19 Sep 2022 09:26:57 +0200 Subject: [PATCH 36/47] v10 compat --- system.json | 65 ++++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 31 deletions(-) diff --git a/system.json b/system.json index 6252c6b..cb3adc6 100644 --- a/system.json +++ b/system.json @@ -2,19 +2,14 @@ "id": "foundryvtt-shadows-over-sol", "title": "Shadows over Sol", "description": "Shadows over Sol for FoundryVTT", - "author": "LeRatierBretonnien", - "authors": [], "url": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", - "flags": {}, - "version": "10.0.1", + "version": "10.0.6", "compatibility": { - "minimum": 10, - "verified": 10, - "maximum": 10 + "minimum": "10", + "verified": "10.285", + "maximum": "10" }, - "templateVersion": 50, - "scripts": [], "esmodules": [ "module/sos-main.js" ], @@ -25,88 +20,96 @@ { "lang": "en", "name": "English", - "path": "lang/en.json" + "path": "lang/en.json", + "flags": {} } ], "packs": [ { "name": "skills", "label": "Skills", - "path": "./packs/skills.db", + "path": "packs/skills.db", "type": "Item", "system": "foundryvtt-shadows-over-sol", - "private": false + "private": false, + "flags": {} }, { "name": "consequences", "label": "Consequences", - "path": "./packs/consequences.db", + "path": "packs/consequences.db", "type": "Item", "system": "foundryvtt-shadows-over-sol", - "private": false + "private": false, + "flags": {} }, { "name": "gears", "label": "Gears", - "path": "./packs/gears.db", + "path": "packs/gears.db", "type": "Item", "system": "foundryvtt-shadows-over-sol", - "private": false + "private": false, + "flags": {} }, { "name": "injuries", "label": "Injuries", - "path": "./packs/injuries.db", + "path": "packs/injuries.db", "type": "Item", "system": "foundryvtt-shadows-over-sol", - "private": false + "private": false, + "flags": {} }, { "name": "weaknesses", "label": "Weaknesses", - "path": "./packs/weaknesses.db", + "path": "packs/weaknesses.db", "type": "Item", "system": "foundryvtt-shadows-over-sol", - "private": false + "private": false, + "flags": {} }, { "name": "languages", "label": "Languages", - "path": "./packs/languages.db", + "path": "packs/languages.db", "type": "Item", "system": "foundryvtt-shadows-over-sol", - "private": false + "private": false, + "flags": {} }, { "name": "combat-actions", "label": "Combat Actions", - "path": "./packs/combat-actions.db", + "path": "packs/combat-actions.db", "type": "Item", "system": "foundryvtt-shadows-over-sol", - "private": false + "private": false, + "flags": {} }, { "name": "genelines", "label": "Genelines", - "path": "./packs/genelines.db", + "path": "packs/genelines.db", "type": "Item", "system": "foundryvtt-shadows-over-sol", - "private": false + "private": false, + "flags": {} }, { "name": "subcultures", "label": "Subcultures", - "path": "./packs/subcultures.db", + "path": "packs/subcultures.db", "type": "Item", "system": "foundryvtt-shadows-over-sol", - "private": false + "private": false, + "flags": {} } ], - "relationships": { }, "socket": true, "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/v10/system.json", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.1.zip", - "protected": false, + "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.6.zip", "gridDistance": 5, "gridUnits": "ft" } \ No newline at end of file -- 2.35.3 From 4b9af6a383358729d6352a42e4349ae2803fbb20 Mon Sep 17 00:00:00 2001 From: sladecraven Date: Wed, 28 Sep 2022 15:53:50 +0200 Subject: [PATCH 37/47] Allow items links in editors --- module/actor-sheet.js | 5 ++++- module/item-sheet.js | 9 ++++++++- system.json | 4 ++-- templates/actor-sheet.html | 4 ++-- templates/editor-notes-gm.html | 2 +- templates/item-action-sheet.html | 2 +- templates/item-commongear-sheet.html | 2 +- templates/item-consequence-sheet.html | 2 +- templates/item-geneline-sheet.html | 4 ++-- templates/item-injury-sheet.html | 2 +- templates/item-language-sheet.html | 2 +- templates/item-malady-sheet.html | 2 +- templates/item-skill-sheet.html | 2 +- templates/item-skillexperience-sheet.html | 2 +- templates/item-subculture-sheet.html | 2 +- templates/item-weakness-sheet.html | 2 +- 16 files changed, 29 insertions(+), 19 deletions(-) diff --git a/module/actor-sheet.js b/module/actor-sheet.js index a68338c..1be1bf4 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -22,7 +22,7 @@ export class SoSActorSheet extends ActorSheet { } /* -------------------------------------------- */ - getData() { + async getData() { const objectData = this.object let formData = { title: this.title, @@ -34,6 +34,9 @@ export class SoSActorSheet extends ActorSheet { cssClass: this.isEditable ? "editable" : "locked", data: foundry.utils.deepClone(this.object.system), effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)), + history: await TextEditor.enrichHTML(this.object.system.history, {async: true}), + notes: await TextEditor.enrichHTML(this.object.system.notes, {async: true}), + gmnotes: await TextEditor.enrichHTML(this.object.system.gmnotes, {async: true}), limited: this.object.limited, options: this.options, owner: this.document.isOwner diff --git a/module/item-sheet.js b/module/item-sheet.js index 6daa504..841563e 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -56,7 +56,8 @@ export class SoSItemSheet extends ItemSheet { effects: this.object.effects.map(e => foundry.utils.deepClone(e.system)), limited: this.object.limited, options: this.options, - owner: this.document.isOwner + owner: this.document.isOwner, + description: await TextEditor.enrichHTML(this.object.system.description, {async: true}), }; formData.isGM = game.user.isGM; @@ -66,6 +67,12 @@ export class SoSItemSheet extends ItemSheet { if ( objectData.type == 'skill' && this.object.options?.actor) { formData.skillExperienceList = this.object.options.actor.getSkillExperience( objectData.name ) } + if ( objectData.type == 'geneline') { + formData.weakness = await TextEditor.enrichHTML(this.object.system.weakness, {async: true}) + } + if ( objectData.type == 'malady') { + formData.notes = await TextEditor.enrichHTML(this.object.system.notes, {async: true}) + } return formData; } diff --git a/system.json b/system.json index cb3adc6..21f241d 100644 --- a/system.json +++ b/system.json @@ -4,7 +4,7 @@ "description": "Shadows over Sol for FoundryVTT", "url": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", - "version": "10.0.6", + "version": "10.0.7", "compatibility": { "minimum": "10", "verified": "10.285", @@ -109,7 +109,7 @@ ], "socket": true, "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/v10/system.json", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.6.zip", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.7.zip", "gridDistance": 5, "gridUnits": "ft" } \ No newline at end of file diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 98cc4d3..f2de1c8 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -390,12 +390,12 @@

        Biography :

        - {{editor data.history target="system.history" button=true owner=owner editable=editable}} + {{editor history target="system.history" button=true owner=owner editable=editable}}

        Notes :

        - {{editor data.notes target="system.notes" button=true owner=owner editable=editable}} + {{editor notes target="system.notes" button=true owner=owner editable=editable}}

        {{>"systems/foundryvtt-shadows-over-sol/templates/editor-notes-gm.html"}} diff --git a/templates/editor-notes-gm.html b/templates/editor-notes-gm.html index 4c17392..efc203c 100644 --- a/templates/editor-notes-gm.html +++ b/templates/editor-notes-gm.html @@ -1,6 +1,6 @@ {{#if data.isGM}}

        GM Notes :

        - {{editor data.gmnotes target="system.gmnotes" button=true owner=owner editable=editable}} + {{editor gmnotes target="system.gmnotes" button=true owner=owner editable=editable}}
        {{/if}} diff --git a/templates/item-action-sheet.html b/templates/item-action-sheet.html index 5ff5d6b..d3b75a1 100644 --- a/templates/item-action-sheet.html +++ b/templates/item-action-sheet.html @@ -36,7 +36,7 @@
        - {{editor data.description target="system.description" button=true owner=owner editable=editable}} + {{editor description target="system.description" button=true owner=owner editable=editable}}
        diff --git a/templates/item-commongear-sheet.html b/templates/item-commongear-sheet.html index ea91518..8f9b6e5 100644 --- a/templates/item-commongear-sheet.html +++ b/templates/item-commongear-sheet.html @@ -46,6 +46,6 @@
        - {{editor data.description target="system.description" button=true owner=owner editable=editable}} + {{editor description target="system.description" button=true owner=owner editable=editable}}
        diff --git a/templates/item-consequence-sheet.html b/templates/item-consequence-sheet.html index ead2e39..0e04353 100644 --- a/templates/item-consequence-sheet.html +++ b/templates/item-consequence-sheet.html @@ -27,7 +27,7 @@
        - {{editor data.description target="system.description" button=true owner=owner editable=editable}} + {{editor description target="system.description" button=true owner=owner editable=editable}}
        diff --git a/templates/item-geneline-sheet.html b/templates/item-geneline-sheet.html index ab52044..e6299c6 100644 --- a/templates/item-geneline-sheet.html +++ b/templates/item-geneline-sheet.html @@ -13,7 +13,7 @@
        - {{editor data.description target="system.description" button=true owner=owner editable=editable}} + {{editor description target="system.description" button=true owner=owner editable=editable}}
        @@ -31,7 +31,7 @@
        - {{editor data.weakness target="system.weakness" button=true owner=owner editable=editable}} + {{editor weakness target="system.weakness" button=true owner=owner editable=editable}}
        diff --git a/templates/item-injury-sheet.html b/templates/item-injury-sheet.html index 433d531..8e8bd52 100644 --- a/templates/item-injury-sheet.html +++ b/templates/item-injury-sheet.html @@ -17,7 +17,7 @@
        - {{editor data.description target="system.description" button=true owner=owner editable=editable}} + {{editor description target="system.description" button=true owner=owner editable=editable}}
      diff --git a/templates/item-language-sheet.html b/templates/item-language-sheet.html index 216ebc0..c6941da 100644 --- a/templates/item-language-sheet.html +++ b/templates/item-language-sheet.html @@ -13,7 +13,7 @@
      - {{editor data.description target="system.description" button=true owner=owner editable=editable}} + {{editor description target="system.description" button=true owner=owner editable=editable}}
    diff --git a/templates/item-malady-sheet.html b/templates/item-malady-sheet.html index 67daede..51eac36 100644 --- a/templates/item-malady-sheet.html +++ b/templates/item-malady-sheet.html @@ -24,7 +24,7 @@
    - {{editor data.notes target="system.notes" button=true owner=owner editable=editable}} + {{editor notes target="system.notes" button=true owner=owner editable=editable}}
    diff --git a/templates/item-skill-sheet.html b/templates/item-skill-sheet.html index 3c65779..a1c7794 100644 --- a/templates/item-skill-sheet.html +++ b/templates/item-skill-sheet.html @@ -27,7 +27,7 @@ {{/each}} - {{editor data.description target="system.description" button=true owner=owner editable=editable}} + {{editor description target="system.description" button=true owner=owner editable=editable}}
    diff --git a/templates/item-skillexperience-sheet.html b/templates/item-skillexperience-sheet.html index b37462a..3a1e3dd 100644 --- a/templates/item-skillexperience-sheet.html +++ b/templates/item-skillexperience-sheet.html @@ -25,7 +25,7 @@
    - {{editor data.description target="system.description" button=true owner=owner editable=editable}} + {{editor description target="system.description" button=true owner=owner editable=editable}}
    diff --git a/templates/item-subculture-sheet.html b/templates/item-subculture-sheet.html index e40926c..7c02e2a 100644 --- a/templates/item-subculture-sheet.html +++ b/templates/item-subculture-sheet.html @@ -13,7 +13,7 @@
    - {{editor data.description target="system.description" button=true owner=owner editable=editable}} + {{editor description target="system.description" button=true owner=owner editable=editable}}
    diff --git a/templates/item-weakness-sheet.html b/templates/item-weakness-sheet.html index 4706f9f..f122046 100644 --- a/templates/item-weakness-sheet.html +++ b/templates/item-weakness-sheet.html @@ -26,7 +26,7 @@
    - {{editor data.description target="system.description" button=true owner=owner editable=editable}} + {{editor description target="system.description" button=true owner=owner editable=editable}}
    -- 2.35.3 From f0c5e7b95db9d9571c8afcbb93854639c9ed6a21 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Thu, 2 Feb 2023 18:24:58 +0100 Subject: [PATCH 38/47] Sync --- module/actor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/actor.js b/module/actor.js index 6978a34..770da99 100644 --- a/module/actor.js +++ b/module/actor.js @@ -388,10 +388,10 @@ export class SoSActor extends Actor { if ( alreadyInside.length >= container.system.container ) { ui.notifications.warn("Container is already full !"); } else { - await this.updateEmbeddedDocuments( "Item", [{ _id: object.id, 'system.containerid':containerId }]); + setTimeout(function() { this.updateEmbeddedDocuments( "Item", [{ _id: object.id, 'system.containerid':containerId }])}, 800 ) } } else if ( object && object.system.containerid) { // remove from container - await this.updateEmbeddedDocuments( "Item", [{ _id: object.id, 'system.containerid':"" }]); + setTimeout(function() { this.updateEmbeddedDocuments( "Item", [{ _id: object.id, 'system.containerid':"" }])}, 800 ) } } -- 2.35.3 From 23b6a41eacb5bef0ef83d1e72abfdeec4dea3e1e Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Thu, 2 Feb 2023 18:25:16 +0100 Subject: [PATCH 39/47] Sync --- system.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system.json b/system.json index 21f241d..8030923 100644 --- a/system.json +++ b/system.json @@ -4,7 +4,7 @@ "description": "Shadows over Sol for FoundryVTT", "url": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", - "version": "10.0.7", + "version": "10.0.8", "compatibility": { "minimum": "10", "verified": "10.285", @@ -109,7 +109,7 @@ ], "socket": true, "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/v10/system.json", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.7.zip", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.8.zip", "gridDistance": 5, "gridUnits": "ft" } \ No newline at end of file -- 2.35.3 From f6104e533c34f5200452ec4800f6501fa809b539 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Thu, 2 Feb 2023 18:28:24 +0100 Subject: [PATCH 40/47] Sync --- system.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system.json b/system.json index 8030923..9b5886d 100644 --- a/system.json +++ b/system.json @@ -4,7 +4,7 @@ "description": "Shadows over Sol for FoundryVTT", "url": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", - "version": "10.0.8", + "version": "10.0.9", "compatibility": { "minimum": "10", "verified": "10.285", @@ -109,7 +109,7 @@ ], "socket": true, "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/v10/system.json", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.8.zip", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/releases/tag/foundryvtt-shadows-over-sol-10.0.9.zip", "gridDistance": 5, "gridUnits": "ft" } \ No newline at end of file -- 2.35.3 From c6c8622552f9be92bee4f7011387cb78681375b0 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Thu, 2 Feb 2023 18:32:25 +0100 Subject: [PATCH 41/47] Sync --- system.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system.json b/system.json index 9b5886d..4d1fd47 100644 --- a/system.json +++ b/system.json @@ -7,7 +7,7 @@ "version": "10.0.9", "compatibility": { "minimum": "10", - "verified": "10.285", + "verified": "10", "maximum": "10" }, "esmodules": [ -- 2.35.3 From c061b67bb3a0693a4332db18a51e789afe512919 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Thu, 2 Feb 2023 18:32:47 +0100 Subject: [PATCH 42/47] Sync --- system.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system.json b/system.json index 4d1fd47..352b8d1 100644 --- a/system.json +++ b/system.json @@ -4,7 +4,7 @@ "description": "Shadows over Sol for FoundryVTT", "url": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", - "version": "10.0.9", + "version": "10.0.10", "compatibility": { "minimum": "10", "verified": "10", @@ -109,7 +109,7 @@ ], "socket": true, "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/v10/system.json", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/releases/tag/foundryvtt-shadows-over-sol-10.0.9.zip", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/releases/tag/foundryvtt-shadows-over-sol-10.0.10.zip", "gridDistance": 5, "gridUnits": "ft" } \ No newline at end of file -- 2.35.3 From aa243a7b80587b41a558f4d5c959afb9d95b6942 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Thu, 2 Feb 2023 18:35:15 +0100 Subject: [PATCH 43/47] Sync --- system.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system.json b/system.json index 352b8d1..8616124 100644 --- a/system.json +++ b/system.json @@ -4,7 +4,7 @@ "description": "Shadows over Sol for FoundryVTT", "url": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", - "version": "10.0.10", + "version": "10.0.11", "compatibility": { "minimum": "10", "verified": "10", @@ -109,7 +109,7 @@ ], "socket": true, "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/v10/system.json", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/releases/tag/foundryvtt-shadows-over-sol-10.0.10.zip", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.11.zip", "gridDistance": 5, "gridUnits": "ft" } \ No newline at end of file -- 2.35.3 From 29ff86f4bdbd5672d28a264f5df21733a47d7602 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Thu, 25 May 2023 16:10:09 +0200 Subject: [PATCH 44/47] v10/v11 compat --- system.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system.json b/system.json index 8616124..4b38e28 100644 --- a/system.json +++ b/system.json @@ -4,11 +4,11 @@ "description": "Shadows over Sol for FoundryVTT", "url": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", - "version": "10.0.11", + "version": "11.0.0", "compatibility": { "minimum": "10", "verified": "10", - "maximum": "10" + "maximum": "11" }, "esmodules": [ "module/sos-main.js" @@ -109,7 +109,7 @@ ], "socket": true, "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/v10/system.json", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-10.0.11.zip", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-11.0.0.zip", "gridDistance": 5, "gridUnits": "ft" } \ No newline at end of file -- 2.35.3 From 6e5bb5da3263bc4de379ca28d6fe0005890aa34d Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Thu, 25 May 2023 16:22:02 +0200 Subject: [PATCH 45/47] v10/v11 compat --- module/actor-sheet.js | 6 +++--- module/sample-code.js | 24 ------------------------ module/sos-card-deck.js | 6 +++--- module/sos-combat.js | 2 +- module/sos-utility.js | 36 ++++++++++++++++++------------------ system.json | 4 ++-- 6 files changed, 27 insertions(+), 51 deletions(-) delete mode 100644 module/sample-code.js diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 1be1bf4..92958ef 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -64,12 +64,12 @@ export class SoSActorSheet extends ActorSheet { formData.gearsRoot = formData.gears.filter(item => item.system.containerid == ""); for ( let container of formData.gearsRoot) { if ( container.type == 'container') { - container.data.contains = [] - container.data.containerEnc = 0; + container.system.contains = [] + container.system.containerEnc = 0; for (let gear of formData.gears) { console.log("GEAR", gear, container) if ( gear.system.containerid == container.id) { - container.data.contains.push( gear ) + container.system.contains.push( gear ) if ( !gear.system.neg && !gear.system.software ) { container.system.containerEnc += (gear.system.big > 0) ? gear.system.big : 1; } diff --git a/module/sample-code.js b/module/sample-code.js deleted file mode 100644 index 29980c7..0000000 --- a/module/sample-code.js +++ /dev/null @@ -1,24 +0,0 @@ - html.find('.item .item-name h4').click(event => this._onItemSummary(event)); - - /** - * Handle toggling of an item from the Actor sheet - * @private - */ - _onItemSummary(event) { - event.preventDefault(); - let li = $(event.currentTarget).parents(".item"), - item = this.actor.getOwnedItem(li.data("item-id")); - - // Toggle summary - if (item.data.data.description !== undefined && item.data.data.description !== null){ - if ( li.hasClass("expanded") ) { - let summary = li.children(".item-summary"); - summary.slideUp(200, () => summary.remove()); - } else { - let div = $(`
    ${item.data.data.description}
    `); - li.append(div.hide()); - div.slideDown(200); - } - li.toggleClass("expanded"); - } - } \ No newline at end of file diff --git a/module/sos-card-deck.js b/module/sos-card-deck.js index 756979f..1bd8fea 100644 --- a/module/sos-card-deck.js +++ b/module/sos-card-deck.js @@ -247,7 +247,7 @@ export class SoSCardDeck { if ( flipData.mode == 'stat' || flipData.mode == 'weapon' ) { flipData.baseScore = flipData.stat.value + flipData.malusConsequence + flipData.bonusConsequence + flipData.woundMalus; } else if (flipData.mode == 'skill') { - flipData.baseScore = Math.floor(flipData.stat.value/2) + flipData.skill.data.value + flipData.malusConsequence + flipData.bonusConsequence + flipData.woundMalus; + flipData.baseScore = Math.floor(flipData.stat.value/2) + flipData.skill.system.value + flipData.malusConsequence + flipData.bonusConsequence + flipData.woundMalus; } flipData.finalScore = flipData.baseScore + flipData.cardTotal + Number(flipData.modifier); flipData.magnitude = flipData.finalScore - flipData.tn; @@ -272,10 +272,10 @@ export class SoSCardDeck { async processWeapon( flipData ) { flipData.damageCardsuit = flipData.cardSlot[flipData.cardSlotIndex].cardsuit; let damageKey = 'damage_'+ flipData.damageCardsuit; - flipData.damageString = flipData.weapon.data[damageKey]; + flipData.damageString = flipData.weapon.system[damageKey]; if (flipData.damageString.includes('Str') ) { let damageRegexp = flipData.damageString.match( /Str([\d])?\+?([\d])?([LMSC])/i ); - flipData.damageValue = (flipData.actor.data.data.stats.strength.value * Number(damageRegexp[1]?damageRegexp[1]:1)) + Number(damageRegexp[2]?damageRegexp[2]:0); + flipData.damageValue = (flipData.actor.system.stats.strength.value * Number(damageRegexp[1]?damageRegexp[1]:1)) + Number(damageRegexp[2]?damageRegexp[2]:0); flipData.damageSeverity = damageRegexp[3]; } else { let damageRegexp = flipData.damageString.match( /(\d*)([LMSC])/i ); diff --git a/module/sos-combat.js b/module/sos-combat.js index 24c5db7..47ae6e6 100644 --- a/module/sos-combat.js +++ b/module/sos-combat.js @@ -16,7 +16,7 @@ export class SoSCombat extends Combat { this.setInitiative(combatant.id, -1); // Reset init let uniq = randomID(16) const name = combatant.actor ? combatant.actor.name : combatant.name; - if (combatant.players && combatant.players[0]) { + if (combatant.players && combatant.players[0] ) { // A player controls this combatant -> message ! ChatMessage.create({ content: `New round ! Click on the button below to declare the actions of ${name} for round ${this.round} !
    diff --git a/module/sos-utility.js b/module/sos-utility.js index 0809f09..243c8bb 100644 --- a/module/sos-utility.js +++ b/module/sos-utility.js @@ -122,7 +122,7 @@ export class SoSUtility { let trappings = items.filter( item => item.type == 'gear' || item.type == 'armor' || item.type == 'weapon' ); let sumEnc = 0; for (let object of trappings) { - if ( (!object.data.worn) && (!object.data.neg) && (!object.data.software) && (!object.data.implant) && (!object.data.containerid || object.data.containerid == "") ) { + if ( (!object.system.worn) && (!object.system.neg) && (!object.system.software) && (!object.system.implant) && (!object.system.containerid || object.system.containerid == "") ) { sumEnc += (object.big > 0) ? object.big : 1; } } @@ -275,20 +275,20 @@ export class SoSUtility { } // DR management - let armor = flipData.target.actor.data.items.find( item => item.type == 'armor' && item.data.worn); - flipData.armorDR = armor ? armor.data.dr : 0; - flipData.armorGel = armor ?armor.data.gel : 0; - flipData.armorReflect = armor ? armor.data.reflect : 0; - let dr = flipData.target.actor.data.data.scores.dr.value + flipData.armorDR; - if (flipData.weapon.data.category == 'ballistic') { + let armor = flipData.target.actor.system.items.find( item => item.type == 'armor' && item.system.worn); + flipData.armorDR = armor ? armor.system.dr : 0; + flipData.armorGel = armor ?armor.system.gel : 0; + flipData.armorReflect = armor ? armor.system.reflect : 0; + let dr = flipData.target.actor.system.scores.dr.value + flipData.armorDR; + if (flipData.weapon.system.category == 'ballistic') { dr += flipData.armorGel; } - if (flipData.weapon.data.category == 'laser') { + if (flipData.weapon.system.category == 'laser') { dr += flipData.armorReflect; } - let shock = flipData.target.actor.data.data.scores.shock.value || 1; - let defenseCritical = flipData.target.actor.data.data.scores.defense.critical; + let shock = flipData.target.actor.system.scores.shock.value || 1; + let defenseCritical = flipData.target.actor.system.scores.defense.critical; flipData.damageStatus = 'apply_damage'; flipData.targetShock = shock; @@ -341,17 +341,17 @@ export class SoSUtility { // Is target able to dodge ?? let defender = game.actors.get( flipData.target.actor._id); - flipData.coverConsequence = defender.data.items.find( item => item.type == 'consequence' && item.name == 'Cover'); - flipData.APavailable = game.combat.getAPFromActor( defender.data._id ); + flipData.coverConsequence = defender.items.find( item => item.type == 'consequence' && item.name == 'Cover'); + flipData.APavailable = game.combat.getAPFromActor( defender._id ); console.log("FLIPDATE : ", flipData); if ( !flipData.isReaction && flipData.APavailable > 0) { - if ( (flipData.weapon.data.category == 'melee' ) || ( (flipData.weapon.data.category == 'laser' || flipData.weapon.data.category == 'ballistic') && - flipData.coverConsequence.data.severity != 'none') ) { - flipData.coverSeverityLevel = this.getConsequenceSeverityLevel( flipData.coverConsequence.data.severity ) * 2; + if ( (flipData.weapon.system.category == 'melee' ) || ( (flipData.weapon.system.category == 'laser' || flipData.weapon.system.category == 'ballistic') && + flipData.coverConsequence.system.severity != 'none') ) { + flipData.coverSeverityLevel = this.getConsequenceSeverityLevel( flipData.coverConsequence.system.severity ) * 2; flipData.coverSeverityFlag = (flipData.coverSeverityLevel > 0); - flipData.isMelee = (flipData.weapon.data.category == 'melee' ); - let melee = defender.data.items.find( item => item.type == 'skill' && item.name == 'Melee'); - flipData.defenderMelee = melee.data.value; + flipData.isMelee = (flipData.weapon.system.category == 'melee' ); + let melee = defender.items.find( item => item.type == 'skill' && item.name == 'Melee'); + flipData.defenderMelee = melee.system.value; flipData.uniqId = randomID(16); this.registry[flipData.uniqId] = flipData; let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-damage-request-dodge.html', flipData ); diff --git a/system.json b/system.json index 4b38e28..3f38e1b 100644 --- a/system.json +++ b/system.json @@ -4,7 +4,7 @@ "description": "Shadows over Sol for FoundryVTT", "url": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", - "version": "11.0.0", + "version": "11.0.1", "compatibility": { "minimum": "10", "verified": "10", @@ -109,7 +109,7 @@ ], "socket": true, "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/v10/system.json", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-11.0.0.zip", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-11.0.1.zip", "gridDistance": 5, "gridUnits": "ft" } \ No newline at end of file -- 2.35.3 From a3b6908a170339d976143edde372082dd6d844da Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Thu, 8 Feb 2024 12:53:15 +0100 Subject: [PATCH 46/47] Enhance stats --- module/sos-main.js | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/module/sos-main.js b/module/sos-main.js index d4f5f99..309efab 100644 --- a/module/sos-main.js +++ b/module/sos-main.js @@ -15,6 +15,7 @@ import { SoSUtility } from "./sos-utility.js"; import { SoSCombat } from "./sos-combat.js"; import { gearConverter } from "./gears_convert.js"; import { SoSGMDeck } from "./sos-gm-deck.js"; +import { ClassCounter} from "https://www.uberwald.me/fvtt_appcount/count-class-ready.js" /* -------------------------------------------- */ /* Foundry VTT Initialization */ @@ -89,30 +90,6 @@ function welcomeMessage() { ` }); } -/* -------------------------------------------- */ -// Register world usage statistics -function registerUsageCount( registerKey ) { - if ( game.user.isGM ) { - game.settings.register(registerKey, "world-key", { - name: "Unique world key", - scope: "world", - config: false, - default: "XXX", - type: String - }); - - let worldKey = game.settings.get(registerKey, "world-key") - if ( worldKey == undefined || worldKey == "" ) { - worldKey = randomID(32) - game.settings.set(registerKey, "world-key", worldKey ) - } - // Simple API counter - let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.version}"` - $.ajax(regURL) - /* -------------------------------------------- */ - } -} - /* -------------------------------------------- */ /* Foundry VTT Initialization */ /* -------------------------------------------- */ @@ -126,7 +103,7 @@ Hooks.once("ready", function () { user: game.user._id }); } - registerUsageCount("foundryvtt-shadows-over-sol") + ClassCounter.registerUsageCount() welcomeMessage(); -- 2.35.3 From 15e249e41e9845240e47b47492bb5c2922d4075e Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Fri, 7 Jun 2024 11:26:46 +0200 Subject: [PATCH 47/47] v12 support --- module/actor-sheet.js | 4 +- module/actor.js | 66 +++--- module/item-sheet.js | 2 +- module/sos-card-deck.js | 24 +- module/sos-combat.js | 4 +- module/sos-dialog-combat-actions.js | 6 +- module/sos-flip-dialog.js | 14 +- module/sos-gm-deck.js | 6 +- module/sos-main.js | 1 + module/sos-utility.js | 338 +++++++++++++-------------- packs/combat-actions/000009.log | 0 packs/combat-actions/000011.ldb | Bin 0 -> 15155 bytes packs/combat-actions/CURRENT | 1 + packs/combat-actions/LOCK | 0 packs/combat-actions/LOG | 13 ++ packs/combat-actions/LOG.old | 5 + packs/combat-actions/MANIFEST-000007 | Bin 0 -> 256 bytes packs/consequences/000009.log | 0 packs/consequences/000011.ldb | Bin 0 -> 7666 bytes packs/consequences/CURRENT | 1 + packs/consequences/LOCK | 0 packs/consequences/LOG | 13 ++ packs/consequences/LOG.old | 5 + packs/consequences/MANIFEST-000007 | Bin 0 -> 255 bytes packs/gears/000009.log | 0 packs/gears/000011.ldb | Bin 0 -> 58930 bytes packs/gears/CURRENT | 1 + packs/gears/LOCK | 0 packs/gears/LOG | 13 ++ packs/gears/LOG.old | 5 + packs/gears/MANIFEST-000007 | Bin 0 -> 260 bytes packs/genelines/000009.log | 0 packs/genelines/000011.ldb | Bin 0 -> 7865 bytes packs/genelines/CURRENT | 1 + packs/genelines/LOCK | 0 packs/genelines/LOG | 13 ++ packs/genelines/LOG.old | 5 + packs/genelines/MANIFEST-000007 | Bin 0 -> 255 bytes packs/injuries/000009.log | 0 packs/injuries/000011.ldb | Bin 0 -> 14817 bytes packs/injuries/CURRENT | 1 + packs/injuries/LOCK | 0 packs/injuries/LOG | 13 ++ packs/injuries/LOG.old | 5 + packs/injuries/MANIFEST-000007 | Bin 0 -> 256 bytes packs/languages/000009.log | 0 packs/languages/000011.ldb | Bin 0 -> 1725 bytes packs/languages/CURRENT | 1 + packs/languages/LOCK | 0 packs/languages/LOG | 13 ++ packs/languages/LOG.old | 5 + packs/languages/MANIFEST-000007 | Bin 0 -> 255 bytes packs/skills/000009.log | 0 packs/skills/000011.ldb | Bin 0 -> 11402 bytes packs/skills/CURRENT | 1 + packs/skills/LOCK | 0 packs/skills/LOG | 13 ++ packs/skills/LOG.old | 5 + packs/skills/MANIFEST-000007 | Bin 0 -> 255 bytes packs/subcultures/000009.log | 0 packs/subcultures/000011.ldb | Bin 0 -> 4158 bytes packs/subcultures/CURRENT | 1 + packs/subcultures/LOCK | 0 packs/subcultures/LOG | 13 ++ packs/subcultures/LOG.old | 5 + packs/subcultures/MANIFEST-000007 | Bin 0 -> 255 bytes packs/weaknesses/000009.log | 0 packs/weaknesses/000011.ldb | Bin 0 -> 837 bytes packs/weaknesses/CURRENT | 1 + packs/weaknesses/LOCK | 0 packs/weaknesses/LOG | 13 ++ packs/weaknesses/LOG.old | 5 + packs/weaknesses/MANIFEST-000007 | Bin 0 -> 255 bytes system.json | 15 +- 74 files changed, 410 insertions(+), 241 deletions(-) create mode 100644 packs/combat-actions/000009.log create mode 100644 packs/combat-actions/000011.ldb create mode 100644 packs/combat-actions/CURRENT create mode 100644 packs/combat-actions/LOCK create mode 100644 packs/combat-actions/LOG create mode 100644 packs/combat-actions/LOG.old create mode 100644 packs/combat-actions/MANIFEST-000007 create mode 100644 packs/consequences/000009.log create mode 100644 packs/consequences/000011.ldb create mode 100644 packs/consequences/CURRENT create mode 100644 packs/consequences/LOCK create mode 100644 packs/consequences/LOG create mode 100644 packs/consequences/LOG.old create mode 100644 packs/consequences/MANIFEST-000007 create mode 100644 packs/gears/000009.log create mode 100644 packs/gears/000011.ldb create mode 100644 packs/gears/CURRENT create mode 100644 packs/gears/LOCK create mode 100644 packs/gears/LOG create mode 100644 packs/gears/LOG.old create mode 100644 packs/gears/MANIFEST-000007 create mode 100644 packs/genelines/000009.log create mode 100644 packs/genelines/000011.ldb create mode 100644 packs/genelines/CURRENT create mode 100644 packs/genelines/LOCK create mode 100644 packs/genelines/LOG create mode 100644 packs/genelines/LOG.old create mode 100644 packs/genelines/MANIFEST-000007 create mode 100644 packs/injuries/000009.log create mode 100644 packs/injuries/000011.ldb create mode 100644 packs/injuries/CURRENT create mode 100644 packs/injuries/LOCK create mode 100644 packs/injuries/LOG create mode 100644 packs/injuries/LOG.old create mode 100644 packs/injuries/MANIFEST-000007 create mode 100644 packs/languages/000009.log create mode 100644 packs/languages/000011.ldb create mode 100644 packs/languages/CURRENT create mode 100644 packs/languages/LOCK create mode 100644 packs/languages/LOG create mode 100644 packs/languages/LOG.old create mode 100644 packs/languages/MANIFEST-000007 create mode 100644 packs/skills/000009.log create mode 100644 packs/skills/000011.ldb create mode 100644 packs/skills/CURRENT create mode 100644 packs/skills/LOCK create mode 100644 packs/skills/LOG create mode 100644 packs/skills/LOG.old create mode 100644 packs/skills/MANIFEST-000007 create mode 100644 packs/subcultures/000009.log create mode 100644 packs/subcultures/000011.ldb create mode 100644 packs/subcultures/CURRENT create mode 100644 packs/subcultures/LOCK create mode 100644 packs/subcultures/LOG create mode 100644 packs/subcultures/LOG.old create mode 100644 packs/subcultures/MANIFEST-000007 create mode 100644 packs/weaknesses/000009.log create mode 100644 packs/weaknesses/000011.ldb create mode 100644 packs/weaknesses/CURRENT create mode 100644 packs/weaknesses/LOCK create mode 100644 packs/weaknesses/LOG create mode 100644 packs/weaknesses/LOG.old create mode 100644 packs/weaknesses/MANIFEST-000007 diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 92958ef..a5162e2 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -10,7 +10,7 @@ export class SoSActorSheet extends ActorSheet { /** @override */ static get defaultOptions() { - return mergeObject(super.defaultOptions, { + return foundry.utils.mergeObject(super.defaultOptions, { classes: ["sos", "sheet", "actor"], template: "systems/foundryvtt-shadows-over-sol/templates/actor-sheet.html", width: 640, @@ -81,7 +81,7 @@ export class SoSActorSheet extends ActorSheet { formData.weapons = this.actor.items.filter( item => item.type == 'weapon'); formData.armors = this.actor.items.filter( item => item.type == 'armor'); formData.totalEncumbrance = SoSUtility.computeEncumbrance(this.actor.items); - formData.wounds = duplicate(this.actor.system.wounds); + formData.wounds = foundry.utils.duplicate(this.actor.system.wounds); formData.isGM = game.user.isGM; formData.currentWounds = this.actor.computeCurrentWounds(); formData.totalWounds = this.actor.system.scores.wound.value; diff --git a/module/actor.js b/module/actor.js index 770da99..4b379aa 100644 --- a/module/actor.js +++ b/module/actor.js @@ -61,24 +61,24 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ checkDeck() { - if ( !this.cardDeck && this.hasPlayerOwner ) { - this.cardDeck = new SoSCardDeck(); - this.cardDeck.initCardDeck( this, this.system.internals.deck ); + if ( !this.system.cardDeck && this.hasPlayerOwner ) { + this.system.cardDeck = new SoSCardDeck(); + this.system.cardDeck.initCardDeck( this, this.system.internals.deck ); } if ( !this.hasPlayerOwner ) { - this.cardDeck = game.system.sos.gmDeck.GMdeck; - console.log("DECK : ", this.cardDeck); + this.system.cardDeck = game.system.sos.gmDeck.GMdeck; + console.log("DECK : ", this.system.cardDeck); } } /* -------------------------------------------- */ getDeckSize() { - return this.cardDeck.getDeckSize(); + return this.system.cardDeck.getDeckSize(); } /* -------------------------------------------- */ getEdgesCard( ) { - let edgesCard = duplicate(this.cardDeck.data.cardEdge); + let edgesCard = foundry.utils.duplicate(this.system.cardDeck.data.cardEdge); for (let edge of edgesCard) { edge.path = `systems/foundryvtt-shadows-over-sol/img/cards/${edge.cardName}.webp` } @@ -86,36 +86,36 @@ export class SoSActor extends Actor { } /* -------------------------------------------- */ resetDeckFull( ) { - this.cardDeck.shuffleDeck(); - this.cardDeck.drawEdge( this.system.scores.edge.value ); + this.system.cardDeck.shuffleDeck(); + this.system.cardDeck.drawEdge( this.system.scores.edge.value ); this.saveDeck(); } /* -------------------------------------------- */ drawNewEdge( ) { - this.cardDeck.drawEdge( 1 ); + this.system.cardDeck.drawEdge( 1 ); this.saveDeck(); } /* -------------------------------------------- */ discardEdge( cardName ) { - this.cardDeck.discardEdge( cardName ); + this.system.cardDeck.discardEdge( cardName ); this.saveDeck(); } /* -------------------------------------------- */ resetDeck( ) { - this.cardDeck.resetDeck(); + this.system.cardDeck.resetDeck(); this.saveDeck(); } /* -------------------------------------------- */ saveDeck( ) { - let deck = { deck: duplicate(this.cardDeck.data.deck), - discard: duplicate(this.cardDeck.data.discard), - cardEdge: duplicate(this.cardDeck.data.cardEdge) + let deck = { deck: foundry.utils.duplicate(this.system.cardDeck.data.deck), + discard: foundry.utils.duplicate(this.system.cardDeck.data.discard), + cardEdge: foundry.utils.duplicate(this.system.cardDeck.data.cardEdge) } if ( this.hasPlayerOwner ) { - this.update( { 'data.internals.deck': deck }); + this.update( { 'system.internals.deck': deck }); } else { game.settings.set("foundryvtt-shadows-over-sol", "gmDeck", deck ); } @@ -213,7 +213,7 @@ export class SoSActor extends Actor { /* -------------------------------------------- */ async updateWound(woundName, value) { - let wounds = duplicate(this.system.wounds) + let wounds = foundry.utils.duplicate(this.system.wounds) wounds[woundName] = value; await this.update( { 'system.wounds': wounds } ); } @@ -246,13 +246,13 @@ export class SoSActor extends Actor { let flipData = { mode: 'stat', - stat: duplicate(this.system.stats[statKey]), + stat: foundry.utils.duplicate(this.system.stats[statKey]), actor: this, modifierList: SoSUtility.fillRange(-10, +10), tnList: SoSUtility.fillRange(6, 20), - consequencesList: duplicate( this.getApplicableConsequences() ), + consequencesList: foundry.utils.duplicate( this.getApplicableConsequences() ), weaknessList: this.items.filter( item => item.type == 'weakness' ), - wounds: duplicate( this.system.wounds), + wounds: foundry.utils.duplicate( this.system.wounds), malusConsequence: 0, bonusConsequence: 0, woundMalus: 0 @@ -265,12 +265,12 @@ export class SoSActor extends Actor { async rollSkill( skill ) { let flipData = { mode: 'skill', - statList: duplicate(this.system.stats), + statList: foundry.utils.duplicate(this.system.stats), selectedStat: 'strength', - consequencesList: duplicate( this.getApplicableConsequences() ), - wounds: duplicate( this.system.wounds), + consequencesList: foundry.utils.duplicate( this.getApplicableConsequences() ), + wounds: foundry.utils.duplicate( this.system.wounds), skillExperienceList: this.getSkillExperience( skill.name), - skill: duplicate(skill), + skill: foundry.utils.duplicate(skill), actor: this, modifierList: SoSUtility.fillRange(-10, +10), tnList: SoSUtility.fillRange(6, 20), @@ -301,14 +301,14 @@ export class SoSActor extends Actor { let flipData = { mode: 'weapon', - weapon: duplicate(weapon), - statList: duplicate(this.system.stats), + weapon: foundry.utils.duplicate(weapon), + statList: foundry.utils.duplicate(this.system.stats), target: target, selectedStat: selectedStatName, - consequencesList: duplicate( this.getApplicableConsequences() ), + consequencesList: foundry.utils.duplicate( this.getApplicableConsequences() ), skillExperienceList: this.getSkillExperience( skill.name), - wounds: duplicate( this.system.wounds), - skill: duplicate(skill), + wounds: foundry.utils.duplicate( this.system.wounds), + skill: foundry.utils.duplicate(skill), actor: this, modifierList: SoSUtility.fillRange(-10, +10), tnList: SoSUtility.fillRange(6, 20), @@ -349,14 +349,14 @@ export class SoSActor extends Actor { async applyConsequenceWound( severity, consequenceName) { if ( severity == 'none') return; // Nothing ! - let wounds = duplicate(this.system.wounds); + let wounds = foundry.utils.duplicate(this.system.wounds); if (severity == 'light' ) wounds.light += 1; if (severity == 'moderate' ) wounds.moderate += 1; if (severity == 'severe' ) wounds.severe += 1; if (severity == 'critical' ) wounds.critical += 1; let sumWound = wounds.light + (wounds.moderate*2) + (wounds.severe*3) + (wounds.critical*4); - let currentWounds = duplicate(this.system.scores.currentwounds); + let currentWounds = foundry.utils.duplicate(this.system.scores.currentwounds); currentWounds.value = sumWound; await this.update( { 'data.scores.currentwounds': currentWounds, 'data.wounds': wounds } ); @@ -403,7 +403,7 @@ export class SoSActor extends Actor { return; } - let wounds = duplicate(this.system.wounds); + let wounds = foundry.utils.duplicate(this.system.wounds); for (let wound of flipData.woundsList ) { if (wound == 'L' ) wounds.light += 1; if (wound == 'M' ) wounds.moderate += 1; @@ -412,7 +412,7 @@ export class SoSActor extends Actor { } // Compute total let sumWound = wounds.light + (wounds.moderate*2) + (wounds.severe*3) + (wounds.critical*4); - let currentWounds = duplicate(this.system.scores.currentwounds); + let currentWounds = foundry.utils.duplicate(this.system.scores.currentwounds); currentWounds.value = sumWound; if ( sumWound >= this.system.scores.wound.value) { let bleeding = this.items.find( item => item.type == 'consequence' && item.name == 'Bleeding'); diff --git a/module/item-sheet.js b/module/item-sheet.js index 841563e..c70f5ac 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -8,7 +8,7 @@ export class SoSItemSheet extends ItemSheet { /** @override */ static get defaultOptions() { - return mergeObject(super.defaultOptions, { + return foundry.utils.mergeObject(super.defaultOptions, { classes: ["foundryvtt-shadows-over-sol", "sheet", "item"], template: "systems/foundryvtt-shadows-over-sol/templates/item-sheet.html", width: 550, diff --git a/module/sos-card-deck.js b/module/sos-card-deck.js index 1bd8fea..833d378 100644 --- a/module/sos-card-deck.js +++ b/module/sos-card-deck.js @@ -8,7 +8,7 @@ const IDX2CARDFAMILY = ['c', 'd', 'h', 's']; export class SoSCardDeck { /* -------------------------------------------- */ - initCardDeck(actor, savedDeck = undefined ) { + async initCardDeck(actor, savedDeck = undefined ) { this.data = {}; @@ -18,27 +18,28 @@ export class SoSCardDeck { this.data.cardEdge = []; if ( savedDeck.deck && savedDeck.deck.length > 0 ) { - this.data.deck = duplicate(savedDeck.deck); + this.data.deck = foundry.utils.duplicate(savedDeck.deck); } if ( savedDeck.discard && savedDeck.discard.length > 0 ) { - this.data.discard = duplicate(savedDeck.discard); + this.data.discard = foundry.utils.duplicate(savedDeck.discard); } if ( savedDeck.cardEdge && savedDeck.cardEdge.length > 0 ) { - this.data.cardEdge = duplicate(savedDeck.cardEdge); + this.data.cardEdge = foundry.utils.duplicate(savedDeck.cardEdge); } this.data.actor = actor; if ( this.data.deck.length == 0 && this.data.discard.length == 0) { - this.shuffleDeck(); + await this.shuffleDeck(); } } /* -------------------------------------------- */ - shuffleDeck() { + async shuffleDeck() { this.cleanCardList(); // Randomize deck while (this.data.deck.length != NB_POKER_CARD) { - let idx = new Roll("1d54").roll( {async:false} ).total; + let roll = await new Roll("1d54").roll(); + let idx = roll.total; if (!this.data.cardState[idx - 1]) { if (idx == 53) { // Red Joker this.data.deck.push( { cardName: 'jr' } ); @@ -57,8 +58,8 @@ export class SoSCardDeck { } /* -------------------------------------------- */ - resetDeck() { - let newdeck = duplicate(this.data.deck).concat( duplicate (this.data.discard) ) + async resetDeck() { + let newdeck = foundry.utils.duplicate(this.data.deck).concat( foundry.utils.duplicate (this.data.discard) ) this.data.discard = [] // Reinit discard pile this.data.deck = [] let decklen = newdeck.length @@ -68,7 +69,8 @@ export class SoSCardDeck { } // Randomize deck while (this.data.deck.length != decklen) { - let idx = new Roll("1d"+decklen).roll({async : false}).total + let roll = await new Roll("1d"+decklen).roll() + let idx = roll.total //console.log("Deck stuff", this.data.deck.length, decklen, idx) if (!cardState[idx-1]) { this.data.deck.push( newdeck[idx-1] ) @@ -104,7 +106,7 @@ export class SoSCardDeck { /* -------------------------------------------- */ getDeckSize() { - return this.data.deck.length; + return this.data.deck.length; } /* -------------------------------------------- */ diff --git a/module/sos-combat.js b/module/sos-combat.js index 47ae6e6..f657486 100644 --- a/module/sos-combat.js +++ b/module/sos-combat.js @@ -14,7 +14,7 @@ export class SoSCombat extends Combat { this.phaseSetup = {}; // Reset each new round/update for (let combatant of this.combatants) { this.setInitiative(combatant.id, -1); // Reset init - let uniq = randomID(16) + let uniq = foundry.utils.randomID(16) const name = combatant.actor ? combatant.actor.name : combatant.name; if (combatant.players && combatant.players[0] ) { // A player controls this combatant -> message ! @@ -80,7 +80,7 @@ export class SoSCombat extends Combat { // Now push specific messages for (let action of actionList) { - let uniq = randomID(16); + let uniq = foundry.utils.randomID(16); action.uniqId = uniq; // Easy tracking with chat messages const name = action.combatant.actor ? action.combatant.actor.name : action.combatant.name; if (action.combatant.players[0]) { diff --git a/module/sos-dialog-combat-actions.js b/module/sos-dialog-combat-actions.js index 823e539..e39e49e 100644 --- a/module/sos-dialog-combat-actions.js +++ b/module/sos-dialog-combat-actions.js @@ -53,11 +53,11 @@ export class SoSDialogCombatActions extends Dialog { super.close(); let action3Index = $('#action3').val(); - let action3 = duplicate(this.combatActions.actionsList[action3Index]); + let action3 = foundry.utils.duplicate(this.combatActions.actionsList[action3Index]); let action2Index = $('#action2').val(); - let action2 = duplicate(this.combatActions.actionsList[action2Index]); + let action2 = foundry.utils.duplicate(this.combatActions.actionsList[action2Index]); let action1Index = $('#action1').val(); - let action1 = duplicate(this.combatActions.actionsList[action1Index]); + let action1 = foundry.utils.duplicate(this.combatActions.actionsList[action1Index]); let combatant3Id = $('#combatant3').val(); let combatant2Id = $('#combatant2').val(); diff --git a/module/sos-flip-dialog.js b/module/sos-flip-dialog.js index ef6515b..19d2951 100644 --- a/module/sos-flip-dialog.js +++ b/module/sos-flip-dialog.js @@ -29,7 +29,7 @@ export class SoSFlipDialog extends Dialog { let scoreBase = 0; if ( this.flipData.mode == 'skill' || this.flipData.mode == 'weapon' ) { let statKey = $('#statSelect').val(); - this.flipData.stat = duplicate( this.flipData.statList[ statKey ] ); + this.flipData.stat = foundry.utils.duplicate( this.flipData.statList[ statKey ] ); scoreBase = Math.floor(this.flipData.statList[ statKey ].value / 2) + this.flipData.skill.system.value } else { //Stat mode let statKey = $('#statSelect').val(); @@ -52,10 +52,10 @@ export class SoSFlipDialog extends Dialog { async updateFlip( flipData ) { //console.log("UPDATE !!!", flipData); $('.view-deck').remove(); - $("#view-deck").append(await flipData.actor.cardDeck.getDeckHTML()); + $("#view-deck").append(await flipData.actor.system.cardDeck.getDeckHTML()); $('.view-edge').remove(); - $("#view-edge").append(await flipData.actor.cardDeck.getEdgeHTMLForFlip()); + $("#view-edge").append(await flipData.actor.system.cardDeck.getEdgeHTMLForFlip()); this.updateScoreBase(); @@ -67,10 +67,10 @@ export class SoSFlipDialog extends Dialog { flipData.edgeLuck = $('#edge-luck').is(":checked"); flipData.cardOrigin = "Edge"; if ( flipData.mode == 'skill' || flipData.mode == 'weapon') { - flipData.stat = duplicate( flipData.statList[ $('#statSelect').val() ] ); + flipData.stat = foundry.utils.duplicate( flipData.statList[ $('#statSelect').val() ] ); } console.log("CLICK:", flipData); - this.flipData.actor.cardDeck.doFlipFromDeckOrEdge(flipData); + this.flipData.actor.system.cardDeck.doFlipFromDeckOrEdge(flipData); this.onFlipClose(); }); @@ -161,11 +161,11 @@ export class SoSFlipDialog extends Dialog { flipData.modifier = html.find('#modifier').val(); if ( flipData.mode == 'skill' || flipData.mode == 'weapon') { let statKey = $('#statSelect').val(); - flipData.stat = duplicate( flipData.statList[ statKey ] ); + flipData.stat = foundry.utils.duplicate( flipData.statList[ statKey ] ); } flipData.cardOrigin = "Deck"; flipData.tn = (flipData.target) ? flipData.target.actor.system.scores.defense.value : $('#tn').val(); - dialog.flipData.actor.cardDeck.doFlipFromDeckOrEdge(flipData); + dialog.flipData.actor.system.cardDeck.doFlipFromDeckOrEdge(flipData); dialog.onFlipClose(); }); diff --git a/module/sos-gm-deck.js b/module/sos-gm-deck.js index 915a210..3f472fd 100644 --- a/module/sos-gm-deck.js +++ b/module/sos-gm-deck.js @@ -35,9 +35,9 @@ export class SoSGMDeck extends Dialog { /* -------------------------------------------- */ saveDeck( ) { let deck = { - deck: duplicate(this.GMdeck.data.deck), - discard: duplicate(this.GMdeck.data.discard), - cardEdge: duplicate(this.GMdeck.data.cardEdge) + deck: foundry.utils.duplicate(this.GMdeck.data.deck), + discard: foundry.utils.duplicate(this.GMdeck.data.discard), + cardEdge: foundry.utils.duplicate(this.GMdeck.data.cardEdge) } game.settings.set("foundryvtt-shadows-over-sol", "gmDeck", deck ); } diff --git a/module/sos-main.js b/module/sos-main.js index 309efab..8b46c48 100644 --- a/module/sos-main.js +++ b/module/sos-main.js @@ -104,6 +104,7 @@ Hooks.once("ready", function () { }); } ClassCounter.registerUsageCount() + SoSUtility.ready() welcomeMessage(); diff --git a/module/sos-utility.js b/module/sos-utility.js index 243c8bb..22d2a98 100644 --- a/module/sos-utility.js +++ b/module/sos-utility.js @@ -1,18 +1,18 @@ -/* -------------------------------------------- */ +/* -------------------------------------------- */ import { SoSCombat } from "./sos-combat.js"; import { SoSDialogCombatActions } from "./sos-dialog-combat-actions.js"; -/* -------------------------------------------- */ -const severity2malus = { "none": 0, "light": -1, "moderate": -2, "severe": -3, "critical": -4}; -/* -------------------------------------------- */ -const severity2bonus = { "none": 0, "light": 1, "moderate": 2, "severe": 3, "critical": 4}; +/* -------------------------------------------- */ +const severity2malus = { "none": 0, "light": -1, "moderate": -2, "severe": -3, "critical": -4 }; +/* -------------------------------------------- */ +const severity2bonus = { "none": 0, "light": 1, "moderate": 2, "severe": 3, "critical": 4 }; -/* -------------------------------------------- */ -export class SoSUtility { - - /* -------------------------------------------- */ +/* -------------------------------------------- */ +export class SoSUtility { + + /* -------------------------------------------- */ static async preloadHandlebarsTemplates() { - + const templatePaths = [ 'systems/foundryvtt-shadows-over-sol/templates/actor-sheet.html', 'systems/foundryvtt-shadows-over-sol/templates/editor-notes-gm.html', @@ -27,31 +27,41 @@ export class SoSUtility { 'systems/foundryvtt-shadows-over-sol/templates/dialog-flip.html' ] - return loadTemplates(templatePaths); + return loadTemplates(templatePaths); } /* -------------------------------------------- */ - static fillRange (start, end) { + static ready() { + Handlebars.registerHelper('select', function (selected, options) { + const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected)); + const rgx = new RegExp(' value=[\"\']' + escapedValue + '[\"\']'); + const html = options.fn(this); + return html.replace(rgx, "$& selected"); + }); + } + + /* -------------------------------------------- */ + static fillRange(start, end) { return Array(end - start + 1).fill().map((item, index) => start + index); } - - /* -------------------------------------------- */ - static onSocketMesssage( msg ) { - if( !game.user.isGM ) return; // Only GM - if (msg.name == 'msg_declare_actions' ) { - let combat = game.combats.get( msg.data.combatId); // Get the associated combat - combat.setupActorActions( msg.data ); + /* -------------------------------------------- */ + static onSocketMesssage(msg) { + if (!game.user.isGM) return; // Only GM + + if (msg.name == 'msg_declare_actions') { + let combat = game.combats.get(msg.data.combatId); // Get the associated combat + combat.setupActorActions(msg.data); } else if (msg.name == 'msg_close_action') { - game.combat.closeAction( msg.data.uniqId ); + game.combat.closeAction(msg.data.uniqId); } else if (msg.name == 'msg_request_defense') { - SoSUtility.applyDamage( msg.data ); + SoSUtility.applyDamage(msg.data); } else if (msg.name == 'msg_reaction_cover') { - SoSUtility.reactionCover( msg.data.uniqId ); + SoSUtility.reactionCover(msg.data.uniqId); } else if (msg.name == 'msg_reaction_melee') { - SoSUtility.reactionMelee( msg.data.uniqId ); + SoSUtility.reactionMelee(msg.data.uniqId); } else if (msg.name == 'msg_reaction_hit') { - SoSUtility.reactionHit( msg.data.uniqId ); + SoSUtility.reactionHit(msg.data.uniqId); } } @@ -60,13 +70,13 @@ export class SoSUtility { const pack = game.packs.get(compendium); return await pack?.getDocuments() ?? []; } - + /* -------------------------------------------- */ static async loadCompendium(compendium, filter = item => true) { let compendiumData = await SoSUtility.loadCompendiumData(compendium); return compendiumData.filter(filter); } - + /* -------------------------------------------- */ static async loadCompendiumNames(compendium) { const pack = game.packs.get(compendium); @@ -74,38 +84,21 @@ export class SoSUtility { await pack.getIndex().then(index => competences = index); return competences; } - - /* -------------------------------------------- */ - /*static async loadCompendium(compendium, filter = item => true) { - let compendiumItems = await SoSUtility.loadCompendiumNames(compendium); - const pack = game.packs.get(compendium); - let list = []; - for (let compendiumItem of compendiumItems) { - await pack.getEntity(compendiumItem.id).then(it => { - const item = it.data; - if (filter(item)) { - list.push(item); - } - }); - }; - return list; - }*/ - /* -------------------------------------------- */ static updateCombat(combat, round, diff, id) { combat.requestActions(); } /* -------------------------------------------- */ - static async openDeclareActions( event) { + static async openDeclareActions(event) { event.preventDefault(); let round = event.currentTarget.attributes['data-round'].value; let combatantId = event.currentTarget.attributes['data-combatant-id'].value; let combatId = event.currentTarget.attributes['data-combat-id'].value; let uniqId = event.currentTarget.attributes['data-uniq-id'].value; - let d = await SoSDialogCombatActions.create( combatId, combatantId, round, uniqId ); - d.render(true); + let d = await SoSDialogCombatActions.create(combatId, combatantId, round, uniqId); + d.render(true); } /* -------------------------------------------- */ @@ -116,13 +109,13 @@ export class SoSUtility { static getConsequenceBonus(severity) { return severity2bonus[severity] ?? 0; } - + /* -------------------------------------------- */ - static computeEncumbrance( items) { - let trappings = items.filter( item => item.type == 'gear' || item.type == 'armor' || item.type == 'weapon' ); + static computeEncumbrance(items) { + let trappings = items.filter(item => item.type == 'gear' || item.type == 'armor' || item.type == 'weapon'); let sumEnc = 0; for (let object of trappings) { - if ( (!object.system.worn) && (!object.system.neg) && (!object.system.software) && (!object.system.implant) && (!object.system.containerid || object.system.containerid == "") ) { + if ((!object.system.worn) && (!object.system.neg) && (!object.system.software) && (!object.system.implant) && (!object.system.containerid || object.system.containerid == "")) { sumEnc += (object.big > 0) ? object.big : 1; } } @@ -133,48 +126,49 @@ export class SoSUtility { static closeAction(event) { let uniqId = event.currentTarget.attributes['data-uniq-id'].value; - if ( game.user.isGM ) { - game.combat.closeAction( uniqId ); + if (game.user.isGM) { + game.combat.closeAction(uniqId); } else { game.socket.emit("system.foundryvtt-shadows-over-sol", { - name: "msg_close_action", data: { uniqId: uniqId} } ); + name: "msg_close_action", data: { uniqId: uniqId } + }); } } /* -------------------------------------------- */ static async registerChatCallbacks(html) { html.on("click", '#button-declare-actions', event => { - SoSUtility.openDeclareActions( event ); + SoSUtility.openDeclareActions(event); }); html.on("click", '#button-end-action', event => { - SoSUtility.closeAction( event ); - }); + SoSUtility.closeAction(event); + }); html.on("click", '#button-reaction-cover', event => { let uniqId = event.currentTarget.attributes['data-uniq-id'].value; - if ( game.user.isGM ) { - SoSUtility.reactionCover( uniqId ); + if (game.user.isGM) { + SoSUtility.reactionCover(uniqId); } else { - game.socket.emit("system.foundryvtt-shadows-over-sol", { name: "msg_reaction_cover", data: { uniqId: uniqId} } ); + game.socket.emit("system.foundryvtt-shadows-over-sol", { name: "msg_reaction_cover", data: { uniqId: uniqId } }); } - }); + }); html.on("click", '#button-reaction-melee', event => { let uniqId = event.currentTarget.attributes['data-uniq-id'].value; - if ( game.user.isGM ) { - SoSUtility.reactionMelee( uniqId ); + if (game.user.isGM) { + SoSUtility.reactionMelee(uniqId); } else { - game.socket.emit("system.foundryvtt-shadows-over-sol", { name: "msg_reaction_melee", data: { uniqId: uniqId} } ); + game.socket.emit("system.foundryvtt-shadows-over-sol", { name: "msg_reaction_melee", data: { uniqId: uniqId } }); } - }); + }); html.on("click", '#button-reaction-hit', event => { let uniqId = event.currentTarget.attributes['data-uniq-id'].value; - if ( game.user.isGM ) { - SoSUtility.reactionHit( uniqId ); + if (game.user.isGM) { + SoSUtility.reactionHit(uniqId); } else { - game.socket.emit("system.foundryvtt-shadows-over-sol", { name: "msg_reaction_hit", data: { uniqId: uniqId} } ); + game.socket.emit("system.foundryvtt-shadows-over-sol", { name: "msg_reaction_hit", data: { uniqId: uniqId } }); } - }); + }); } /* -------------------------------------------- */ @@ -188,46 +182,46 @@ export class SoSUtility { } /* -------------------------------------------- */ - static increaseConsequenceSeverity( severity ) { - if ( severity == 'none') return 'light'; - if ( severity == 'light') return 'moderate'; - if ( severity == 'moderate') return 'severe'; - if ( severity == 'severe') return 'critical'; + static increaseConsequenceSeverity(severity) { + if (severity == 'none') return 'light'; + if (severity == 'light') return 'moderate'; + if (severity == 'moderate') return 'severe'; + if (severity == 'severe') return 'critical'; return 'critical'; } /* -------------------------------------------- */ - static getConsequenceSeverityLevel( severity) { - if ( severity == 'none') return 0; - if ( severity == 'light') return 1; - if ( severity == 'moderate') return 2; - if ( severity == 'severe') return 3; - if ( severity == 'critical') return 4; + static getConsequenceSeverityLevel(severity) { + if (severity == 'none') return 0; + if (severity == 'light') return 1; + if (severity == 'moderate') return 2; + if (severity == 'severe') return 3; + if (severity == 'critical') return 4; return 0; } - + /* -------------------------------------------- */ - static increaseSeverity( severity ) { - if ( severity == 'L') return 'M'; - if ( severity == 'M') return 'S'; - if ( severity == 'S') return 'C'; - if ( severity == 'C') return 'F'; + static increaseSeverity(severity) { + if (severity == 'L') return 'M'; + if (severity == 'M') return 'S'; + if (severity == 'S') return 'C'; + if (severity == 'C') return 'F'; } /* -------------------------------------------- */ - static decreaseSeverity( severity ) { - if ( severity == 'C') return 'S'; - if ( severity == 'S') return 'M'; - if ( severity == 'M') return 'L'; - if ( severity == 'L') return 'N'; + static decreaseSeverity(severity) { + if (severity == 'C') return 'S'; + if (severity == 'S') return 'M'; + if (severity == 'M') return 'L'; + if (severity == 'L') return 'N'; } /* -------------------------------------------- */ - static getSeverityLevel( severity) { - if ( severity == 'C') return 4; - if ( severity == 'S') return 3; - if ( severity == 'M') return 2; - if ( severity == 'L') return 1; + static getSeverityLevel(severity) { + if (severity == 'C') return 4; + if (severity == 'S') return 3; + if (severity == 'M') return 2; + if (severity == 'L') return 1; return 0; } @@ -238,53 +232,53 @@ export class SoSUtility { let msgTxt = "

    Are you sure to delete this item ?"; let buttons = { delete: { - icon: '', - label: "Yes, delete it", - callback: () => { - console.log("Delete : ", itemId); - actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]); - li.slideUp(200, () => actorSheet.render(false)); - } - }, - cancel: { - icon: '', - label: "Cancel" + icon: '', + label: "Yes, delete it", + callback: () => { + console.log("Delete : ", itemId); + actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]); + li.slideUp(200, () => actorSheet.render(false)); } + }, + cancel: { + icon: '', + label: "Cancel" } - msgTxt += "

    "; - let d = new Dialog({ - title: "Confirm deletion", - content: msgTxt, - buttons: buttons, - default: "cancel" - }); - d.render(true); } - + msgTxt += "

    "; + let d = new Dialog({ + title: "Confirm deletion", + content: msgTxt, + buttons: buttons, + default: "cancel" + }); + d.render(true); + } + /* -------------------------------------------- */ - static async applyDamage( flipData ) { + static async applyDamage(flipData) { if (!this.registry) this.registry = {}; - if ( flipData.isReaction) { // Check again resut in case of reaction ! + if (flipData.isReaction) { // Check again resut in case of reaction ! flipData.magnitude = flipData.finalScore - flipData.tn; // Update magnitude - if ( flipData.magnitude < 0 ) { - let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-reaction-result.html', flipData ); - ChatMessage.create( { content: html }); + if (flipData.magnitude < 0) { + let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-reaction-result.html', flipData); + ChatMessage.create({ content: html }); return; } } - + // DR management - let armor = flipData.target.actor.system.items.find( item => item.type == 'armor' && item.system.worn); + let armor = flipData.target.actor.system.items.find(item => item.type == 'armor' && item.system.worn); flipData.armorDR = armor ? armor.system.dr : 0; - flipData.armorGel = armor ?armor.system.gel : 0; + flipData.armorGel = armor ? armor.system.gel : 0; flipData.armorReflect = armor ? armor.system.reflect : 0; let dr = flipData.target.actor.system.scores.dr.value + flipData.armorDR; if (flipData.weapon.system.category == 'ballistic') { - dr += flipData.armorGel; + dr += flipData.armorGel; } if (flipData.weapon.system.category == 'laser') { - dr += flipData.armorReflect; + dr += flipData.armorReflect; } let shock = flipData.target.actor.system.scores.shock.value || 1; @@ -292,106 +286,106 @@ export class SoSUtility { flipData.damageStatus = 'apply_damage'; flipData.targetShock = shock; - flipData.targetDR = dr; + flipData.targetDR = dr; flipData.targetCritical = defenseCritical; // DR management - if ( flipData.damageValue < dr) { + if (flipData.damageValue < dr) { if (flipData.damageValue < dr / 2) { flipData.damageStatus = "no_damage"; flipData.damageReason = "Damage are lesser than DR/2"; } else { - flipData.damageSeverity = this.decreaseSeverity(flipData.damageSeverity ); - if ( flipData.damageSeverity == 'N') { + flipData.damageSeverity = this.decreaseSeverity(flipData.damageSeverity); + if (flipData.damageSeverity == 'N') { flipData.damageStatus = "no_damage"; flipData.damageReason = "Severity decreased to nothing"; - } + } } } - + // Shock management flipData.woundsList = []; flipData.nbStun = 0; - if ( flipData.weapon.stun ) { // Stun weapon case - if ( flipData.damageValue >= shock ) { + if (flipData.weapon.stun) { // Stun weapon case + if (flipData.damageValue >= shock) { flipData.nbStun = Math.floor(flipData.damageValue / shock); } } else { - if ( flipData.damageValue >= shock ) { + if (flipData.damageValue >= shock) { let incSeverity = Math.floor(flipData.damageValue / shock); - for (let i=0; i= defenseCritical); + flipData.isCritical = (flipData.cardTotal >= defenseCritical); - let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-damage-target.html', flipData ); - ChatMessage.create( { content: html }); + let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-damage-target.html', flipData); + ChatMessage.create({ content: html }); // Is target able to dodge ?? - let defender = game.actors.get( flipData.target.actor._id); - flipData.coverConsequence = defender.items.find( item => item.type == 'consequence' && item.name == 'Cover'); - flipData.APavailable = game.combat.getAPFromActor( defender._id ); + let defender = game.actors.get(flipData.target.actor._id); + flipData.coverConsequence = defender.items.find(item => item.type == 'consequence' && item.name == 'Cover'); + flipData.APavailable = game.combat.getAPFromActor(defender._id); console.log("FLIPDATE : ", flipData); - if ( !flipData.isReaction && flipData.APavailable > 0) { - if ( (flipData.weapon.system.category == 'melee' ) || ( (flipData.weapon.system.category == 'laser' || flipData.weapon.system.category == 'ballistic') && - flipData.coverConsequence.system.severity != 'none') ) { - flipData.coverSeverityLevel = this.getConsequenceSeverityLevel( flipData.coverConsequence.system.severity ) * 2; - flipData.coverSeverityFlag = (flipData.coverSeverityLevel > 0); - flipData.isMelee = (flipData.weapon.system.category == 'melee' ); - let melee = defender.items.find( item => item.type == 'skill' && item.name == 'Melee'); + if (!flipData.isReaction && flipData.APavailable > 0) { + if ((flipData.weapon.system.category == 'melee') || ((flipData.weapon.system.category == 'laser' || flipData.weapon.system.category == 'ballistic') && + flipData.coverConsequence.system.severity != 'none')) { + flipData.coverSeverityLevel = this.getConsequenceSeverityLevel(flipData.coverConsequence.system.severity) * 2; + flipData.coverSeverityFlag = (flipData.coverSeverityLevel > 0); + flipData.isMelee = (flipData.weapon.system.category == 'melee'); + let melee = defender.items.find(item => item.type == 'skill' && item.name == 'Melee'); flipData.defenderMelee = melee.system.value; - flipData.uniqId = randomID(16); + flipData.uniqId = foundry.utils.randomID(16); this.registry[flipData.uniqId] = flipData; - let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-damage-request-dodge.html', flipData ); - ChatMessage.create( { content: html, whisper: ChatMessage.getWhisperRecipients(flipData.target.actor.name).concat(ChatMessage.getWhisperRecipients("GM")) } ); + let html = await renderTemplate('systems/foundryvtt-shadows-over-sol/templates/chat-damage-request-dodge.html', flipData); + ChatMessage.create({ content: html, whisper: ChatMessage.getWhisperRecipients(flipData.target.actor.name).concat(ChatMessage.getWhisperRecipients("GM")) }); return; // Wait message response } } flipData.isReaction = false; - this.takeWounds( flipData); + this.takeWounds(flipData); } - /* -------------------------------------------- */ - static reactionCover( uniqId) { + /* -------------------------------------------- */ + static reactionCover(uniqId) { let flipData = this.registry[uniqId]; flipData.tn += flipData.coverSeverityLevel; flipData.isReaction = true; - game.combat.decreaseAPFromActor( flipData.target.actor._id ); - SoSUtility.applyDamage( flipData); - } + game.combat.decreaseAPFromActor(flipData.target.actor._id); + SoSUtility.applyDamage(flipData); + } /* -------------------------------------------- */ - static reactionMelee( uniqId) { + static reactionMelee(uniqId) { let flipData = this.registry[uniqId]; flipData.tn += flipData.defenderMelee; flipData.isReaction = true; - game.combat.decreaseAPFromActor( flipData.target.actor._id ); - SoSUtility.applyDamage( flipData); + game.combat.decreaseAPFromActor(flipData.target.actor._id); + SoSUtility.applyDamage(flipData); } /* -------------------------------------------- */ - static reactionHit( uniqId) { + static reactionHit(uniqId) { let flipData = this.registry[uniqId]; flipData.isReaction = true; - SoSUtility.takeWounds( flipData); + SoSUtility.takeWounds(flipData); } - - /* -------------------------------------------- */ - static takeWounds( flipData ) { - let defender = game.actors.get( flipData.target.actor._id); - defender.applyWounds( flipData ); + + /* -------------------------------------------- */ + static takeWounds(flipData) { + let defender = game.actors.get(flipData.target.actor._id); + defender.applyWounds(flipData); } /* -------------------------------------------- */ @@ -402,7 +396,7 @@ export class SoSUtility { let objectId = item.id console.log("ID", dragData, dropId, objectId) if (dragData.type == 'Item' && dropId) { - actorSheet.actor.addObjectToContainer(objectId, dropId ); + actorSheet.actor.addObjectToContainer(objectId, dropId); } return true } diff --git a/packs/combat-actions/000009.log b/packs/combat-actions/000009.log new file mode 100644 index 0000000..e69de29 diff --git a/packs/combat-actions/000011.ldb b/packs/combat-actions/000011.ldb new file mode 100644 index 0000000000000000000000000000000000000000..922ad1687e75b33e5f67cdbc28df9d619342487d GIT binary patch literal 15155 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 literal 0 HcmV?d00001 diff --git a/packs/combat-actions/CURRENT b/packs/combat-actions/CURRENT new file mode 100644 index 0000000..875cf23 --- /dev/null +++ b/packs/combat-actions/CURRENT @@ -0,0 +1 @@ +MANIFEST-000007 diff --git a/packs/combat-actions/LOCK b/packs/combat-actions/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/packs/combat-actions/LOG b/packs/combat-actions/LOG new file mode 100644 index 0000000..57ff2ac --- /dev/null +++ b/packs/combat-actions/LOG @@ -0,0 +1,13 @@ +2024/05/31-12:37:50.244518 7f20a6a006c0 Recovering log #6 +2024/05/31-12:37:50.292179 7f20a6a006c0 Delete type=0 #6 +2024/05/31-12:37:50.292229 7f20a6a006c0 Delete type=3 #4 +2024/05/31-12:57:42.325821 7f20a5a006c0 Level-0 table #10: started +2024/05/31-12:57:42.325873 7f20a5a006c0 Level-0 table #10: 0 bytes OK +2024/05/31-12:57:42.332227 7f20a5a006c0 Delete type=0 #8 +2024/05/31-12:57:42.355930 7f20a5a006c0 Manual compaction at level-0 from '!items!06L0cwm4CIuCFetU' @ 72057594037927935 : 1 .. '!items!uSQw858IiBrWkeSj' @ 0 : 0; will stop at '!items!uSQw858IiBrWkeSj' @ 20 : 1 +2024/05/31-12:57:42.355939 7f20a5a006c0 Compacting 1@0 + 0@1 files +2024/05/31-12:57:42.359540 7f20a5a006c0 Generated table #11@0: 20 keys, 15155 bytes +2024/05/31-12:57:42.359578 7f20a5a006c0 Compacted 1@0 + 0@1 files => 15155 bytes +2024/05/31-12:57:42.365779 7f20a5a006c0 compacted to: files[ 0 1 0 0 0 0 0 ] +2024/05/31-12:57:42.365873 7f20a5a006c0 Delete type=2 #5 +2024/05/31-12:57:42.386374 7f20a5a006c0 Manual compaction at level-0 from '!items!uSQw858IiBrWkeSj' @ 20 : 1 .. '!items!uSQw858IiBrWkeSj' @ 0 : 0; will stop at (end) diff --git a/packs/combat-actions/LOG.old b/packs/combat-actions/LOG.old new file mode 100644 index 0000000..b6e583a --- /dev/null +++ b/packs/combat-actions/LOG.old @@ -0,0 +1,5 @@ +2024/05/31-12:37:00.345049 7f04c4c006c0 Recovering log #3 +2024/05/31-12:37:00.345498 7f04c4c006c0 Level-0 table #5: started +2024/05/31-12:37:00.358604 7f04c4c006c0 Level-0 table #5: 22912 bytes OK +2024/05/31-12:37:00.406080 7f04c4c006c0 Delete type=0 #3 +2024/05/31-12:37:00.406202 7f04c4c006c0 Delete type=3 #2 diff --git a/packs/combat-actions/MANIFEST-000007 b/packs/combat-actions/MANIFEST-000007 new file mode 100644 index 0000000000000000000000000000000000000000..a86c839bc1f6a7cdc71dbb3a83dd5db392ca41b3 GIT binary patch literal 256 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 7666 bytes +2024/05/31-12:57:42.288596 7f20a5a006c0 compacted to: files[ 0 1 0 0 0 0 0 ] +2024/05/31-12:57:42.288688 7f20a5a006c0 Delete type=2 #5 +2024/05/31-12:57:42.318921 7f20a5a006c0 Manual compaction at level-0 from '!items!vHcRT3kQVWPHSz38' @ 13 : 1 .. '!items!vHcRT3kQVWPHSz38' @ 0 : 0; will stop at (end) diff --git a/packs/consequences/LOG.old b/packs/consequences/LOG.old new file mode 100644 index 0000000..1d5a478 --- /dev/null +++ b/packs/consequences/LOG.old @@ -0,0 +1,5 @@ +2024/05/31-12:36:59.630199 7f04bf4006c0 Recovering log #3 +2024/05/31-12:36:59.631365 7f04bf4006c0 Level-0 table #5: started +2024/05/31-12:36:59.641960 7f04bf4006c0 Level-0 table #5: 10948 bytes OK +2024/05/31-12:36:59.690838 7f04bf4006c0 Delete type=0 #3 +2024/05/31-12:36:59.690928 7f04bf4006c0 Delete type=3 #2 diff --git a/packs/consequences/MANIFEST-000007 b/packs/consequences/MANIFEST-000007 new file mode 100644 index 0000000000000000000000000000000000000000..728c476547037604780e52e0583e57afaa9711a5 GIT binary patch literal 255 zcmY$Dd9gH+fss)vC$%g!CnZVGsj?)sJhM2}IX|}`u_&=5zlfcI^+>3^VrEHdZn2`V zyOV*RV`@pHW0;3$RcSu2_$?aKtL2HyR*BK?CvZx zvk4okvTCfTsA#F8R!!SjsioFdsoGk_YOQUx*3Y9o)y9^#(n{6V2+wlwWWHegnESe`2$pJ%EEH&7zd8Y}dx?_4!3u%pR#u-&i ztJC3Om!}FhF2>tVsPUkdjCJWrBcK*~eHCV@iz5AoT?eo5_s2TK{cc# zqgGjSjjt@Rx}&W(*|a6Pd~+()v#P$VdBMd##}VS=d$llENp^}!OEnx0XFQ-P(LzzQ z6fN#3aci+eREZ1c?TV|ofFUJns=l(A7AzVehDr=^!$oMtQQjC-wQU-Jbx4T+ip~tj%SRT}@h-}fHR!vI|;ku+` zC28p~#nJ+DKuIXQ^mkLT9+H)KN>12!T-M|EFU1t2U$uNP@t0#&=t(Q6t0s54m*-VW zBVXQLjTI8;ms7ZCrkqUR6@qd|Rij*GORo}*;ylPTv+x%U+1!~_f{iaRJ}+)CKE{t(sfyM00o}9= zyo)%l-Xfp(*G@HVY6J7aY(TFXWiwq)rjZnr_hc-}THJ9>ZT)H` zZoQ$z!`K$Jq`;|0btTAoc{8Gupr^J0_s>dh^*F7Fp%2cS;lz0aBAXgK*c8zyzT)H) zhDz3VrWDZ=){PWSrQxP>oUytysU_5)qtSy!7t*6a|C8Dt-qa2Mlie5dr~QtPM(fq~ zq_WzdSh33J>>%p!cMg1adsosJ&<2#Kyat!8vMZUuzS50(W&0m-hVkagjz7c>KSWj@ zI7}qA+U$LRZGM0me}J7hjy=G3uDatvcJW#j+f@#$78XY`9I=%DPOoIbBk$~K=XJwW ze|#ZU0hWjAmAfNYdxqYd#KP*wUyU8AG37z*7(-4Z4J|bCQWV=$wv^teYMDMPQxmU> zbr#gjgl>}4+_Hs5X%2T*hIBnBn@UKvQsiv+fMRH>HT;f8*Wy-8jgu8z1!IwBBGuqE zVz_{Ee_RWxq`?!_aEhuy3Mx%49LL*7U^3E&JA$%~MQ_MSQ^lH>^;*%|1j|z7%rdl`h6;_K^%&s5QqCuaWF!TW}s0O)HJ$N}o zR-(#J#1xh?QI^Syh83DjB%-Nm*&j7^?^&#=jrd0^Vnd>g)jIlfABV|&@denH$4QR7N)4I*H#f}O5eb4}Uh6f8@Z4K=35dR3!Y z4(jo_mW7_;Os0-Ov}9##hT*isOO@Ya)W1l1$IOQ;@5|h7wfe zsG_{o`gz93onIQjuJ2dXg!cKROs6ZDwUH zeSX<y&Wpk5N zyOD&OzsI^aA|ROBS-*Ekzu?Dfg~PSNk}oskUuGwcN50JNxrK>Izji!QBQP!dFLvU6 zYl`dFytG76zA=0+&N0p55_P-$0;^f+O5XsM9HQ5Nih%5T+tImv85U*;yQN=^BUmFQ zsaK*I-of|^tDJHeKP=;wJhvzLd zz}+i-VMg&wJl`ZoBwiZvyK!R@x+VRI=VNMc_QQe`!8sb`zQCBnkBP|g(b>9$7Y?R; zazr1L&dsl>mNy~W%SsTLL@R#LG2$XOA&>>MgsVdk!$@PrH%Ok9co*TM>M9Uw5W7@l zIRtnm&`%yNt*yaLG*#0$&PxC7V3F9Xq~2TkQU?Dc^#A7$jQ;8uYa7#clIw*5PCV%Gl5Y$wE&Gc6ea+Y5Ld(wZXb_FNY^c&5{{6S

    )Xi4chg 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 i2A>i 58930 bytes +2024/05/31-12:57:42.318551 7f20a5a006c0 compacted to: files[ 0 1 0 0 0 0 0 ] +2024/05/31-12:57:42.318708 7f20a5a006c0 Delete type=2 #5 +2024/05/31-12:57:42.318989 7f20a5a006c0 Manual compaction at level-0 from '!items!zMiaz2HLsddO22H3' @ 99 : 1 .. '!items!zMiaz2HLsddO22H3' @ 0 : 0; will stop at (end) diff --git a/packs/gears/LOG.old b/packs/gears/LOG.old new file mode 100644 index 0000000..3524d9e --- /dev/null +++ b/packs/gears/LOG.old @@ -0,0 +1,5 @@ +2024/05/31-12:36:59.694104 7f04c4c006c0 Recovering log #3 +2024/05/31-12:36:59.695341 7f04c4c006c0 Level-0 table #5: started +2024/05/31-12:37:00.103755 7f04c4c006c0 Level-0 table #5: 87512 bytes OK +2024/05/31-12:37:00.158532 7f04c4c006c0 Delete type=0 #3 +2024/05/31-12:37:00.158786 7f04c4c006c0 Delete type=3 #2 diff --git a/packs/gears/MANIFEST-000007 b/packs/gears/MANIFEST-000007 new file mode 100644 index 0000000000000000000000000000000000000000..84f52d159cfae3f20bb8cbd657efc0e78b0a327f GIT binary patch literal 260 zcmX>o_y6c{@`{-yskz09 zhVEI$jv=05mD!b!fu?CLj42FY0F$rs%}lH^^6)86N%1!_@-SvhhRFXfTp`HGz{teG z$-vCXa*Q!E>~#r<&k5vn1NqsG3vQM``8+^AD+3`D*%(;a8M!x|VTLIr*=ffhP6Gh8 C=tBnp literal 0 HcmV?d00001 diff --git a/packs/genelines/000009.log b/packs/genelines/000009.log new file mode 100644 index 0000000..e69de29 diff --git a/packs/genelines/000011.ldb b/packs/genelines/000011.ldb new file mode 100644 index 0000000000000000000000000000000000000000..dac98bf004ba4773755be135ec1339eb8f6aaf70 GIT binary patch literal 7865 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 literal 0 HcmV?d00001 diff --git a/packs/genelines/CURRENT b/packs/genelines/CURRENT new file mode 100644 index 0000000..875cf23 --- /dev/null +++ b/packs/genelines/CURRENT @@ -0,0 +1 @@ +MANIFEST-000007 diff --git a/packs/genelines/LOCK b/packs/genelines/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/packs/genelines/LOG b/packs/genelines/LOG new file mode 100644 index 0000000..7e7e752 --- /dev/null +++ b/packs/genelines/LOG @@ -0,0 +1,13 @@ +2024/05/31-12:37:50.295525 7f20a7e006c0 Recovering log #6 +2024/05/31-12:37:50.344755 7f20a7e006c0 Delete type=0 #6 +2024/05/31-12:37:50.344847 7f20a7e006c0 Delete type=3 #4 +2024/05/31-12:57:42.332388 7f20a5a006c0 Level-0 table #10: started +2024/05/31-12:57:42.332415 7f20a5a006c0 Level-0 table #10: 0 bytes OK +2024/05/31-12:57:42.338850 7f20a5a006c0 Delete type=0 #8 +2024/05/31-12:57:42.365997 7f20a5a006c0 Manual compaction at level-0 from '!items!3o49zG4Xtc1I29j2' @ 72057594037927935 : 1 .. '!items!vDOAmovqE53dQzlh' @ 0 : 0; will stop at '!items!vDOAmovqE53dQzlh' @ 8 : 1 +2024/05/31-12:57:42.366005 7f20a5a006c0 Compacting 1@0 + 0@1 files +2024/05/31-12:57:42.369253 7f20a5a006c0 Generated table #11@0: 8 keys, 7865 bytes +2024/05/31-12:57:42.369293 7f20a5a006c0 Compacted 1@0 + 0@1 files => 7865 bytes +2024/05/31-12:57:42.376725 7f20a5a006c0 compacted to: files[ 0 1 0 0 0 0 0 ] +2024/05/31-12:57:42.376841 7f20a5a006c0 Delete type=2 #5 +2024/05/31-12:57:42.386385 7f20a5a006c0 Manual compaction at level-0 from '!items!vDOAmovqE53dQzlh' @ 8 : 1 .. '!items!vDOAmovqE53dQzlh' @ 0 : 0; will stop at (end) diff --git a/packs/genelines/LOG.old b/packs/genelines/LOG.old new file mode 100644 index 0000000..3f57dfe --- /dev/null +++ b/packs/genelines/LOG.old @@ -0,0 +1,5 @@ +2024/05/31-12:37:00.409789 7f04bfe006c0 Recovering log #3 +2024/05/31-12:37:00.410672 7f04bfe006c0 Level-0 table #5: started +2024/05/31-12:37:00.432255 7f04bfe006c0 Level-0 table #5: 11820 bytes OK +2024/05/31-12:37:00.469946 7f04bfe006c0 Delete type=0 #3 +2024/05/31-12:37:00.470035 7f04bfe006c0 Delete type=3 #2 diff --git a/packs/genelines/MANIFEST-000007 b/packs/genelines/MANIFEST-000007 new file mode 100644 index 0000000000000000000000000000000000000000..fac1d0631dbf5fb8121d259cd6206eb9b6fe9970 GIT binary patch literal 255 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 14817 bytes +2024/05/31-12:57:42.298878 7f20a5a006c0 compacted to: files[ 0 1 0 0 0 0 0 ] +2024/05/31-12:57:42.298975 7f20a5a006c0 Delete type=2 #5 +2024/05/31-12:57:42.318947 7f20a5a006c0 Manual compaction at level-0 from '!items!xZL7aO0xOOZvB2cs' @ 53 : 1 .. '!items!xZL7aO0xOOZvB2cs' @ 0 : 0; will stop at (end) diff --git a/packs/injuries/LOG.old b/packs/injuries/LOG.old new file mode 100644 index 0000000..7f14182 --- /dev/null +++ b/packs/injuries/LOG.old @@ -0,0 +1,5 @@ +2024/05/31-12:37:00.162792 7f04c56006c0 Recovering log #3 +2024/05/31-12:37:00.163468 7f04c56006c0 Level-0 table #5: started +2024/05/31-12:37:00.172845 7f04c56006c0 Level-0 table #5: 21537 bytes OK +2024/05/31-12:37:00.220464 7f04c56006c0 Delete type=0 #3 +2024/05/31-12:37:00.220541 7f04c56006c0 Delete type=3 #2 diff --git a/packs/injuries/MANIFEST-000007 b/packs/injuries/MANIFEST-000007 new file mode 100644 index 0000000000000000000000000000000000000000..f14b50ce9438eeee58cacd004b180ff2d344ed9c GIT binary patch literal 256 zcmd0w)XSU1z{n_-lUkOVlai$8R9TW*o>`pgoS$2eSd>_jU&PM9x^M-fykcfaYHqQj zQB-K2w|Q=sXKH3uep09}qZtDjz~n2Ue9RO54J!Qoqsp9&l8YHlA@T~AIeZ)pj7%Jy z49uJ?SsAaNT7bBmKrS~+mT$Avry?kqhb4=Zfsk=*46N*o+z*Rk>PU807Q|TqBEdie literal 0 HcmV?d00001 diff --git a/packs/languages/000009.log b/packs/languages/000009.log new file mode 100644 index 0000000..e69de29 diff --git a/packs/languages/000011.ldb b/packs/languages/000011.ldb new file mode 100644 index 0000000000000000000000000000000000000000..164ac4c0407b2d7855a317e1a420762451d4bd66 GIT binary patch literal 1725 zcmd6nO-y4|6oB9L4Z}18N$V7-!U*$}M3eGUpujw_kqZ51D5WjX(ctZS_r2cw{&+u> zLP%T~W1<`5X12ruf~(Pl0cNEOHxp+PC?O_p)EG1qW#NLwjOlngNKJ^*g)Y1~CpqWc zb572AIp2NMW>T$N^c8F(*|^d@4yPls2jg6?I1}!V13Og%l1q#NWyG*d+*0x|iy1d# z7B%2lkf0)3P(Q%wnEY>}J;}7rB}>ObFUvUt%~_ zM`@%RSXIcir>C>G$IH0uKWGV)aK(}&hrQt?TSFVCBWNN%iNVjdOHNtkv4H!XlwE>` zIacpF=Px=EL!2sWNa3+1PpX#AA&0Atw=@ZJB(<}N`kV}=7D$Ii4r^pihDQRlB$Hvg z-HaBAg|gP*l;lqrh3Q})!}cz_>%XwMod&04&8+zzthJE>f-3PycNiB8RR_`OOxrI%e&y=F7Vx?h*6dNE{JW@;kogmq$MV_nLw^T zc5NIy&F%tM1kOVR8Sta>D*a%U_N`OpeNdJBK8S765g}3V%JFnAw2)B4atvHz_kq)o z6cI}0b^75t?OUVDB~X=o3B>Nuaew%&L>^Dg=QASoPUe7Zk}@B&}r(Dm>J&QeLb%UaUFuH?#Yog(3%3^p(={ zft5x=(r2e6Az4!wwTKsv_{Y-|>L7TAko0Pmq$%qUi0b|kqKW?$BE+uzTZn%Azd>}H z7BrYdW;D<@<4KABs0f~IzjyV%Ygi|*6~~nKz^{A2w@MMCD%m{{ztHp*y%_O!d*_UB zLF#=i9LRv?6OhQF{Rt8!umq)3CdeAS$P8(|fQ}R{*Y@F|eW*+GG5H-jc9)j5zJY9N zlE?n(fuQK004?lKz?LZQ(8oJ;rG-OKl{<$ZcAGAsV861!hft^w37C*|nLPx~Akt;1 zkkI49C!L?B9UX$Y%F~wLrU}doS#30zd%&Ks34-0i*|efeWr4W6$AIEh}QHk(7=Q4B3$$wYdmgyxaNXFL5C z@v-8UR8eFwxn<@J#2OM~Oa;PuQQ?_%=seAYQt(r 1725 bytes +2024/05/31-12:57:42.386148 7f20a5a006c0 compacted to: files[ 0 1 0 0 0 0 0 ] +2024/05/31-12:57:42.386245 7f20a5a006c0 Delete type=2 #5 +2024/05/31-12:57:42.386396 7f20a5a006c0 Manual compaction at level-0 from '!items!xbpEhhdqx4o5KUJA' @ 15 : 1 .. '!items!xbpEhhdqx4o5KUJA' @ 0 : 0; will stop at (end) diff --git a/packs/languages/LOG.old b/packs/languages/LOG.old new file mode 100644 index 0000000..dc1eed3 --- /dev/null +++ b/packs/languages/LOG.old @@ -0,0 +1,5 @@ +2024/05/31-12:37:00.283664 7f04bf4006c0 Recovering log #3 +2024/05/31-12:37:00.285227 7f04bf4006c0 Level-0 table #5: started +2024/05/31-12:37:00.295941 7f04bf4006c0 Level-0 table #5: 2524 bytes OK +2024/05/31-12:37:00.342228 7f04bf4006c0 Delete type=0 #3 +2024/05/31-12:37:00.342291 7f04bf4006c0 Delete type=3 #2 diff --git a/packs/languages/MANIFEST-000007 b/packs/languages/MANIFEST-000007 new file mode 100644 index 0000000000000000000000000000000000000000..0e13b15896fd840f7841867e55940578cf944ec6 GIT binary patch literal 255 zcmb=~U3e#vfss)vC$%g!CnZVGsj?)sJhM2}IX|}`u_&=5zlfcI^^UN-VrEHdZn2_) ze`17Ju3=_ohH-kNr&$1_00S7nGw<0&zKkTy7S*NusP%i=bQ{7CBZ1LdLN%u(C69@8yN5BiUJU5N81ZY27_< literal 0 HcmV?d00001 diff --git a/packs/skills/000009.log b/packs/skills/000009.log new file mode 100644 index 0000000..e69de29 diff --git a/packs/skills/000011.ldb b/packs/skills/000011.ldb new file mode 100644 index 0000000000000000000000000000000000000000..315e21b1cd28adda55a02261d6a1ed8a9d321dab GIT binary patch literal 11402 zcmd6Ndwd(!o$nk*6Y8u-BPG~ zzejcqeD(vEzwW30jGS1H(abr&^L_o!y)jp~dl<}$;HH678n?&&XX@7=Rw-$1gz znXD2dGW`A;lNzk1qh=siY#2&wHSrp^m?t6K8Pjwfe`R!` z@2yhOHlr?6hc)su?}cH*Qnie>F)Rdi>bU*>h$mSL4Q@$WMxL3fRxpOFf}Lieh@uwq zx|YUA8&?R=;hwBX6W^B8^0>tsm1Sr_cWXMD;x+jleLbl{`#wE6Qp}8QZ>{OL;`+FM zmc)Y-R4*`To##kiS{7BAleV?I>;1jFCEpo45yagp>DZwjM;SA%Nu8-#rdS!p%`qiL z58|tJ1#e+ynmKC>l{&f28QU`a7v~&>nyQk{F++1)yBJqoOUW`zx3WcPRoGxIvur6C zZB+I;Own9&X$0esYj??(oMopp7iTtDI!8?{?cmeQaTSwIdPm7rY(pa4gXhxJPFbd+ z;`SA4r*o1a)xBsl42Yvxwqmoil{K}aOu=Yon9WRA!KF}_@;k7t^jM?P>nf_n9L2QU zdeW|>sH3G7gW~q^%fHjZ($bf=bSN2|&dpg4iz@|()hUraE!B{)UCEJ?nw5A-P`X~& z;xukqpYN=}EMzPlx6=Fz*|F@{mqxE&7WsHtGwn5x?&}}0yZiO7-Kp*5BDS&E7P@A> zT}-x%5nW4B+jTOV#LoML`Ay=|k=!K4?vHI&QH@5-iSBz_jkb^TmQbySK?G>`gY zm}k^kfjso_O9h*JW(&@QVPr@0HgkCCCodC)A?cg+wg|>?t4%ZH#yDQeWA$hgOfRx^ zYY&>Jw>4(U$#1@4li2r(vMY`{2a4lOJ<0tWl62S39un=?B+AkUMUidir)DzkS- z@swkkR41E!jM~Q88)_|7fUV?h>u_RkTxZH8qj{|VxN_zcUz5!CuB&zQLKanFTa%PMhvY1U;;E;{Li6n-qa6ni0-yklVZJ{?iBlOE^F;& z2gYfB>~P!8qunjTd2(?_r&x7*{zzH!NSQ#JBblRRoev80J>t?a*duP}>Hoy4uXqL8 za=93)QxuetHlexN{+)r--e6kSj1;92+|%KLktY@OsC2Q6IwQfgc+SPJ=_o%M60}hM z2e-yk7%hb|+e&F^snbKvszB9*5?82$anp4o%Na%k>%BrIaHluS%&ePRqa}P!A)O8uapQp?!$YW zz`VD%kj=RYz$aAT-Ztq#@ajnWdzW8L0 z0kJfiH7zIcZ&91t3^1okMnrR*0(0W)+Wq9xpb75L>1vr}tU15OvdOV9vo(X6w3$|i zb(*ql8iesx2L5|6|7jiX;1Tz}b)rRdd zuz38L)po-waz0&TOb~4xxbJ9LvqZYm z&p%L9m=1KcEwHBoj!-92XmK!GI)`$wi_*IA0>qJ*Yjt*nml2pznvelmdzSmh-AqAO zO0{aEjteelo4hp%OhnC7h5RQuB#es3dTk9D>0{1{jz$066^@2_`Yg zP9V>Y>lVppfi-Y%fO#wsKx17vN*#v*ri%V6L%W1{Y@%mLOq5uT|4+;tLZJ!BNn?EKdkBI^e9mq_H9AKx! zr6V~dZg`L`A2lHUaC6jz@WG&ienB*8#yW(}i5%7{4bOB&F_RRK@5X)Ob<9Li@8~;b^RB+z@w!}Ys9e(hBuN!vSTuB%u~qIV{*|duofTH9V^u4 zbMltU9<6Glj|J19Bb8ni%rh&m_rB^eEk6|~{Rb2b6rE!*-T03n6cV$^2l4!jlx4f< ziSzoPKIq9?Q+JM91&EMEu7GONwK0Z^rsO9cg~l$!@R?PAYD!sZQPFYU0?o3iY6y@C zh&L@uC48G=6l`dt&Gd~hW*0^2{b?LSkSZ!&MjpEB_*tQM@2&AWH>x9l0Sw)MODBb3y142zK=mr>o# z%@2vmAyII=qnSam^FCpIP+U3&2gQbNV^5b3@s!g}{m^5ouP*cG#UI^=LHK^x$!}ej z7?O($J$c{kO+gzXS*sMw+jE+#GRzp4{?J@!pGDmOo*X0bhW~KT$x{^lEk0;4J@M6V zeIqidK}#3h*~3(nJblwmZ!TDGfqXMbPY zk+xl9SLlVz$T+#QqeB!%rf&A=Y`(3$yRCfsCxU+XjxsL2H;YThj?Ln(r~TjA3Ptm+ zgrKkfhA#ju@V9=fMa7-85?94BF^t;_5VI5L@e6CJf9KnHciEP_rduwGeS)Sjv6^dK z&mtrl1P(I0cdqc^#HYNsc{Hnf(9f=EMR}mqQWk~622y-ohOe2sG(xitfMjj<@kowa z8Y@rsvP{@1qzt^gZKO*i`l^Qm&;~8z{s_lT$fe4q29LY|qq!#3@E|GWd`Q_`fMgFdOcmCe@ zUin)ys}8;!e}CdV@%OFo%-=8nmGC$B(wjc;XIAEvo6}%Vrgkv0sY05pY zciUT4y^H~kh{_;#-Lmb~>G=jzXv4R=lM+0>J0-?%qD zMsq2f)G<{M3M?|PpdRL_n53eR2jU$nA>JWz{``?Vv|t$vkXR&-Ru}Tj~9>k#`f%hB0fH zhpJs9D1$&)Y8!CR(Nvyz@X*0FsP4au_C*j{VZI&d1{rY#sS#Xla_w8>9ihN}cygY% zkdF)Y)MY_tXK0$%7ayYQq8K_{AIS1G55lg^QLOw@lCknZU#4KD>G3etHMh8#eLcL8 zVvs{pcXTV_q=wyjr+(+@Ua{}kvVG0=aF=Q{ZQXj{z~r{AS+b_1R}6By?#^!)liNih zO-69X*-VefJ=NPSW!?6MH+t_p`x(|c`z4Q+nSGWm_hoRCGq<)nnvsWxR@sDxm}ur~ zdrrx)$p+VIFj3UjMB?_@&fZtTY1Ds;CGvtw8>9n0SR-6p=nG-O72Eh99P$8|H#R1YgjPmwHg;j<==6^kbxAbkedQkkeRdIHik3tq3tlbsBBW zbIr&_37%y3+=k=+j=My9P!uig<7%t?;7|RddB}UI1A99V*@7J~azxq;H-zUpPw_1btQ8PDA_x5PoKrgwh z^8pcyz{zVc*~R%8v3o|Wx;pcS*!i$9|A@GBBp(qsJv{r1#EI%Byd3g5R?sF)NoIDe z_p^aJym78qc+3ScVF##JP!l_&fC-)92CLe9Q1tehF9+@_r}x4RA`PiL<-K_D%;PWB zpI3UvSIab|%?^+@7~c;^xblG2m1aQpPC=i!Pf+$>Kvv3@t)2Z^$|J5_aC42y;R^`)oVSM;4mr_^i%|g-3u%>GzYH2_>Ux;gr(Y<8 z!uz>2ZVXNCRx^6Ozuih_j*_({{_dOnFtj6wH;5hg2#A4}j^qZh?w*ZJ zV&&@cz^u;)#jVbsBJ#}lJt-R4=B-^YDH$M6;>4D?GKqU}d4d7O!py+c{vfB{BMD=U z$kZ&Z{-ZBg(zvtfpk`?4F%t8oAqmf{Uz?(Cqp}UURCB8jdux$zAwA{cCw-1fv2(lG z7kU(`PH+>VF3G|8t2ti=Wh~tvaZn@>P1Rw)Y*^0hwI0I=)cUb%r6GAjv%J^(Ydww? z__7~?vHisIP`b5Anw0V^)x{q*{ zRn8}#b%$PrYF`S)xvgEYZ0G$s>W*`?dAML}pgA6hmt1$%mBCVOL!4GnqRVML&tqJT z9EdJvLyWA74Tj;lHOC_LTL5+7Ujqx<&ceROrMuS_p|lZ~D^ydZTtr1pWAP`}2@ZK+ z?NX=>T8~RV)WH-gWI%c$7GEHFm>V9zI^>lwf->at(w$W=`!;i@-Ra{|H+lJ>f^?g= zQQq{-3ugOmT-^N45*I(jx%hdR4!4iC?dcvH-PW{Qn^aY@j#U>|)b65g0S*|eU_L4) zqoQC|T`e@GVkL-+iSy@=9Wl|vluf-xZPzv0hFV||XD+Cp-V57t^Aqr8$|8q$-6W*C zW)em;jqFm_j#3(kzL`1F4~|dly@fQBl}Neh<-v@O$jl3~jY%j4US0pke@A@MvP=4l zTM~A0lnZVXzz}N1%7=+2Mq@!J-rhJVc&~_-Vos>8;_t&)1Sy?K*R({0sLCBQP?Al1 z-{-%_hf}1bkCD&&F!w5XM4-}#!;m>yWFsrREv;O`m1qh;U38`n^kiuP2AsNpgFMig z(;9u%hd43ry<(=#0YNl#GW$zt8X#+4+9I-uDNGW`+$2VR@n8DyN`rdA5p^i#nS z?>GO}o03rwCm)F{%Dm#^{pC$O6+ktX5`V{g#i{K<$QN7l|2Fh$5X@F^>PhHAf%-SZ z5waFg-KCuIbjH(nOis04!Bjmp+B%ZA2gWw!$>kjxPjmnbTtI2ftDdCl5%T{1nA4P} z6aG8pSvm$&p62cSBSL!i^jhA;n4nk=ZgIN&rB*HCVQ&BD!lhV((KvkIl#Xl6Itr2u zn{G?w!4Tec!AXtB1?yo&kJm_b5u1%e!n*94P(g7f5kWPeUqqh)C3jwjiG$XKiAUOn ztP?Gh$rRS1W|B*wE~^^YP28RW+12DN;?%W?*PF0jdEVus-DGOy2D%Q4H(P+IbK{K< zc|t8SVti4qqH{v^nff5wFp$YV8NeqOMel<7MYm8>r!-*r)Enf|INX{G<&$@c>D(WF z9dt3hV|D#euE`;M?7B;2j5PiH^p!PzvhlMpBC>2&CtsiX=ZFe{(qPc~x>9#wy`TlW z-f2H7iT8C*y&Ogr=L>GEx%sIGAO`f#x^prv3-lZNdo){q<3r;s9(Y;~JT3=IO_tM9 zPv5g;>W;Pp@T+~>i`is)Yg0docSJqm{!*iD{(*|Y2P(Y#Gf_T+Le2a`6-!6wLlw;r zcoc1}KJll@6BTFE(`yocLu(ebPNKmF>0@_25?RdMraOUX%;id}5cqSs&%}Qk9*{9J z)#LtPDIZBZHy0CZsf%3w*ixFJsMJ7cq(E|V_X8E{V*Ge+i5V+pd(*dis1kV0S5xcr z9u%C!cLeIalkBafyg67hKb60bqv;|VI}q!Y*ZQ=cz}G6qCp{_))XRc4WkSj13-;Xq z_CSve$ysfJl#_lLI++;)U3G`IdrlCXq#;HY+W=q9FYCL%ER#$$?cKgX&$S=chf`XP zG$2v&ZDVOxo$(9t`BwuSuLcAaao|WP4jd8Z&mYMVG4Q;1LyytlZwBH1nBH|V0{oxA zQcO^ft_5ZS{pJU(Oa_Hd(`l4FJlfk*v^XZ)+etqX#7ftdx#y*T%!;g1^i__P(|?Jo z+}mXfT4iN<1c{)-^vs;FWicOwVs&6z5^D99$G92bhzYikMRg5!VtUBW3eN=i*aOYYAk5$m?nkHdLa=7RT zOP^rU2efhN08*FR-;y@m^Piu->M@=+{KdN{S~9LXGQ4xREn|=L?$Dakq!FU!x+T$) z1oF{B8bh$CT*B|JTt?n&*pMoOu70<$;ogy5*ODCA#HzTOeE#Sa41u1DAx} zybJRW8;^Bm*;(|{j{*#lMC6ceavQ3di_!$vG_H_J!H9hf>7Xx+eGq^XZw-lFm8Vc3 zoGf{20CAwy{TE0OA5}Jev6klpP`xbglE`DQyQOXc0t3eMQs+EpO(OGvj6%1dkcJLG zKNY8P$ofUulV%FJhm%pkA@9p+E)P4v$FNi-E$splcmb;#`Qt(blS>+J5hUPITKaYn zI>=N>ZxcQNHsh&6s!$|9UJFXYN)UyBut=C(tHw@AugRb*@_mn+lU@&UQdXoVgWY(aTlaLL z6L^E7fpnONECl#PG89>q1^yok&ZeW`1<4pY{+3qD_$-%<^aPiTXUfdPzOln<@Aycw zHgc5hWn}%yRf6z^i=x9k&4t{ZUnwP5N`mX(pIISsaj`;LI+80S-(Kt-NvsK@2n(2t zKO0)}7lgRsps}gz4#;C>y9aXavvR87ZhTFY(Nj8gZ3HU=;;47(SL`vt>HOXWYx5vy z1aj#yCqDC`wP|LS!~>&aiL>;ShndIQqG+?BYmm}O#D65{Fb>sG8M(&YIWkCU!+Cs| zx!xNJkN%JKLYn>}j06oe-}SnT{CfJzR@evbO&1lz%pI&vTVLXkGd=!G8lMzH`@tj)6=)bh&p2x?bMi^V$7rD)zlxmhalMYg=!kS?fAbw3?c>lco+TF6B83Y1hmp zNSvI^b*23z*NOAzkK}b?-Tgtlq-dIS_PNAL!RUQuK{lSe7s1V$yP67|e0eL5$6d7h z2b+A{(9DLg5kx1o=Q9CzkVkfLa#0jZ9za!_jK-OGPg<3w1Zj^Nxqp|?H26W zM7We&G3m;=OUQKGK&9i$5KyAu5rp|x&;2X(9{GELk@rcXfk|10k*<2m2QZ<5FUcJ@ zB7_Qz%RY=_nw}Km)sM?kn~<(N=>?t7-sXciPLqnnM15KHWfi0#sDX3xnHM>j@a~Mw zUYZIoBzyG{k7~_*GVrK8`@1lwJHWuHxjhlo2Jbi4Po2J5?EAB94<uvM)5$MWiDyl3uQ{X|9Ogm?7-G83!RR11uI_a0gOVns+#d^_-3MdC&u zr}d3VK}Nh&{k4jKT8?3&9w8NwDk6O68YETaXS{)sFR(p;R^?CEwD`zgAHYTpe6gJP ze7sRRCC~Y4l|o*z3xE!Xj9i5+QUF4vVFu4;At=cmcaOH)8d42#!h)`hYja@$icX89 z3N;V;8Te@h*&(QN@AJ@f%~W}*pMz#ktXKL5+7Y3DkMg()F_c~DlN&$k3!K94goc}^ zv6W)_h>R^{fxq!r|F4Q1oV0D_(fs0xbg4y*YjAkuFkWd^9KS=s_87o3g7Da}s$oIh z`0)xMU43Om?6$hEOz(zM2*?%F1FM@V$QNhs6|%29?^6-G?V!HZ{XRsbzZO{FURh{d zqg4p;yRDj$3S3-`QBn7gL41$RD!=br5XQT1^Hl!PcjpZiZ)Ppy*iH9F8Dz_M&NoR4 zWBZEZM|PV#w-4sqc263l1+wMM?S_lkx2ReEU)v4et7c(_G^)RI*isnVc;9t~M{Lh2()$;hvY=B^3RydTbWj7(pDK2Bp=l zfW6^i4Ntwv$H)t6j_Mh72YJ5A_Z+@smt-YOfXz36Ucax2U{Gr!AQa1El<8*D^x0=ex5m}ZV{_e>#kDvsFDM2pd9}nQM0uKd``o%{J z{;d$IFF(>F)QF%5fO(@1&eqjbW3qt1H8Y7Gm(g8%spa{R-S|Lh7m;w)#GhY(oHPkR zanTvHlfQULSoqL#A?Wc}3%f(r;X9T;yIi;=w4!J9zvaSMe&Od=e}1_T3a#;EwuU-= zH#I&PTDcc^ydwJSm7faA4;U>U^TwB0goX(#_+fi4}MqVUvKnW^5DLv X@9n#h?`?YbpM9?%yS=us{m1_oL=%c; literal 0 HcmV?d00001 diff --git a/packs/skills/CURRENT b/packs/skills/CURRENT new file mode 100644 index 0000000..875cf23 --- /dev/null +++ b/packs/skills/CURRENT @@ -0,0 +1 @@ +MANIFEST-000007 diff --git a/packs/skills/LOCK b/packs/skills/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/packs/skills/LOG b/packs/skills/LOG new file mode 100644 index 0000000..21cc783 --- /dev/null +++ b/packs/skills/LOG @@ -0,0 +1,13 @@ +2024/05/31-12:37:49.885012 7f20acc006c0 Recovering log #6 +2024/05/31-12:37:49.948288 7f20acc006c0 Delete type=0 #6 +2024/05/31-12:37:49.948350 7f20acc006c0 Delete type=3 #4 +2024/05/31-12:57:42.266276 7f20a5a006c0 Level-0 table #10: started +2024/05/31-12:57:42.266304 7f20a5a006c0 Level-0 table #10: 0 bytes OK +2024/05/31-12:57:42.272138 7f20a5a006c0 Delete type=0 #8 +2024/05/31-12:57:42.299102 7f20a5a006c0 Manual compaction at level-0 from '!items!0xlCQMyGIQJWPBM1' @ 72057594037927935 : 1 .. '!items!ukWyqxOnKGRp7Owm' @ 0 : 0; will stop at '!items!ukWyqxOnKGRp7Owm' @ 25 : 1 +2024/05/31-12:57:42.299113 7f20a5a006c0 Compacting 1@0 + 0@1 files +2024/05/31-12:57:42.302367 7f20a5a006c0 Generated table #11@0: 25 keys, 11402 bytes +2024/05/31-12:57:42.302389 7f20a5a006c0 Compacted 1@0 + 0@1 files => 11402 bytes +2024/05/31-12:57:42.308292 7f20a5a006c0 compacted to: files[ 0 1 0 0 0 0 0 ] +2024/05/31-12:57:42.308373 7f20a5a006c0 Delete type=2 #5 +2024/05/31-12:57:42.318969 7f20a5a006c0 Manual compaction at level-0 from '!items!ukWyqxOnKGRp7Owm' @ 25 : 1 .. '!items!ukWyqxOnKGRp7Owm' @ 0 : 0; will stop at (end) diff --git a/packs/skills/LOG.old b/packs/skills/LOG.old new file mode 100644 index 0000000..a5c33e8 --- /dev/null +++ b/packs/skills/LOG.old @@ -0,0 +1,5 @@ +2024/05/31-12:36:59.552707 7f04bfe006c0 Recovering log #3 +2024/05/31-12:36:59.558358 7f04bfe006c0 Level-0 table #5: started +2024/05/31-12:36:59.579826 7f04bfe006c0 Level-0 table #5: 15330 bytes OK +2024/05/31-12:36:59.626405 7f04bfe006c0 Delete type=0 #3 +2024/05/31-12:36:59.626466 7f04bfe006c0 Delete type=3 #2 diff --git a/packs/skills/MANIFEST-000007 b/packs/skills/MANIFEST-000007 new file mode 100644 index 0000000000000000000000000000000000000000..c721f9097f0dd60d5cacd14f5543122e2c0f0cb6 GIT binary patch literal 255 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 4158 bytes +2024/05/31-12:57:42.430495 7f20a5a006c0 compacted to: files[ 0 1 0 0 0 0 0 ] +2024/05/31-12:57:42.430590 7f20a5a006c0 Delete type=2 #5 +2024/05/31-12:57:42.436970 7f20a5a006c0 Manual compaction at level-0 from '!items!xaHXF4xCPb598RYA' @ 8 : 1 .. '!items!xaHXF4xCPb598RYA' @ 0 : 0; will stop at (end) diff --git a/packs/subcultures/LOG.old b/packs/subcultures/LOG.old new file mode 100644 index 0000000..d61ef0c --- /dev/null +++ b/packs/subcultures/LOG.old @@ -0,0 +1,5 @@ +2024/05/31-12:37:00.473437 7f04bf4006c0 Recovering log #3 +2024/05/31-12:37:00.473817 7f04bf4006c0 Level-0 table #5: started +2024/05/31-12:37:00.494156 7f04bf4006c0 Level-0 table #5: 6179 bytes OK +2024/05/31-12:37:00.530987 7f04bf4006c0 Delete type=0 #3 +2024/05/31-12:37:00.531064 7f04bf4006c0 Delete type=3 #2 diff --git a/packs/subcultures/MANIFEST-000007 b/packs/subcultures/MANIFEST-000007 new file mode 100644 index 0000000000000000000000000000000000000000..ea555c8b83ac502be2e2c4e33850b5e0a5a82850 GIT binary patch literal 255 zcmb=4bP!HtU}TiaNi9pwNlDUksw_z@&n!-L&d)7KEJ`fNFJfn4U2Gt)m|2pVTdZhM zksEFlWLlh=ns1tIl48lo$p8j0`HDo32se`o=YS+rON*dLM@9~a{FGESGY$quCJs&p yW=<9X8~Gjq5SJ6k>|acrcGyE%=5hS%=65{hyVvZ1d>=F zhbJe_k55&nom_cvaBV!pCzT)wDxW6Sp=&q@>TsMo9>Jy|Fm)3>i-s$Z)eBQlw7fRm zM8=wnIG2b`j2egf`bG+3rzSbx;)?ZYuHUA{7lv~1>^d|lLlwlh^eE|p zY&w@6l6?5u{wX={`h-LyoxS1CgvpR01C+7yJ-jdGPz&35I0hob;NrxdxR!54=Z=^% zGIA~KJM+|MCW^*2%kLcnDBT5K%5=0T4e~nnWLRh++wh5idL{+E=~A)kA6_K+O3PlF z9E5sqBemz1l8SS`DzG5Qn;B_KekQ6>)`EKQ;=qG$iCBo6413Av8EGHNCu~YA#G=IjVdNs zv=Tjef?a9oqox)#P|-L4HE0dpy%$jT16fLYC9m9gay)eJ@#RAoZtZHLVYzmL#GCum z00wMK1Y&7|8i-icbl#U|?B)rj&ctsj`!Kk-eXFenKL1#H1i}HR{QOhkPH=|{ZEf9t W9n5?UcD14Z*W&jJSG)bmx4!_NdH$gQ literal 0 HcmV?d00001 diff --git a/packs/weaknesses/CURRENT b/packs/weaknesses/CURRENT new file mode 100644 index 0000000..875cf23 --- /dev/null +++ b/packs/weaknesses/CURRENT @@ -0,0 +1 @@ +MANIFEST-000007 diff --git a/packs/weaknesses/LOCK b/packs/weaknesses/LOCK new file mode 100644 index 0000000..e69de29 diff --git a/packs/weaknesses/LOG b/packs/weaknesses/LOG new file mode 100644 index 0000000..df00be0 --- /dev/null +++ b/packs/weaknesses/LOG @@ -0,0 +1,13 @@ +2024/05/31-12:37:50.133633 7f20acc006c0 Recovering log #6 +2024/05/31-12:37:50.185827 7f20acc006c0 Delete type=0 #6 +2024/05/31-12:37:50.185917 7f20acc006c0 Delete type=3 #4 +2024/05/31-12:57:42.319061 7f20a5a006c0 Level-0 table #10: started +2024/05/31-12:57:42.319098 7f20a5a006c0 Level-0 table #10: 0 bytes OK +2024/05/31-12:57:42.325607 7f20a5a006c0 Delete type=0 #8 +2024/05/31-12:57:42.345684 7f20a5a006c0 Manual compaction at level-0 from '!items!FxCIbJm3T44kC0sG' @ 72057594037927935 : 1 .. '!items!VDYXsT8AZ6krv93p' @ 0 : 0; will stop at '!items!VDYXsT8AZ6krv93p' @ 4 : 1 +2024/05/31-12:57:42.345699 7f20a5a006c0 Compacting 1@0 + 0@1 files +2024/05/31-12:57:42.349053 7f20a5a006c0 Generated table #11@0: 4 keys, 837 bytes +2024/05/31-12:57:42.349088 7f20a5a006c0 Compacted 1@0 + 0@1 files => 837 bytes +2024/05/31-12:57:42.355720 7f20a5a006c0 compacted to: files[ 0 1 0 0 0 0 0 ] +2024/05/31-12:57:42.355816 7f20a5a006c0 Delete type=2 #5 +2024/05/31-12:57:42.386362 7f20a5a006c0 Manual compaction at level-0 from '!items!VDYXsT8AZ6krv93p' @ 4 : 1 .. '!items!VDYXsT8AZ6krv93p' @ 0 : 0; will stop at (end) diff --git a/packs/weaknesses/LOG.old b/packs/weaknesses/LOG.old new file mode 100644 index 0000000..e41336d --- /dev/null +++ b/packs/weaknesses/LOG.old @@ -0,0 +1,5 @@ +2024/05/31-12:37:00.223304 7f04bfe006c0 Recovering log #3 +2024/05/31-12:37:00.223338 7f04bfe006c0 Level-0 table #5: started +2024/05/31-12:37:00.234424 7f04bfe006c0 Level-0 table #5: 965 bytes OK +2024/05/31-12:37:00.281050 7f04bfe006c0 Delete type=0 #3 +2024/05/31-12:37:00.281171 7f04bfe006c0 Delete type=3 #2 diff --git a/packs/weaknesses/MANIFEST-000007 b/packs/weaknesses/MANIFEST-000007 new file mode 100644 index 0000000000000000000000000000000000000000..0b726fcce429bb042d51295986c08e1cdd1a8b2a GIT binary patch literal 255 zcmb2_=iivfz{n_-lUkOVlai$8R9TW*o>`pgoS$2eSd>_jU&PM9dX!yWF|#B!w^-4w z!r3#)E7v&0#3b9rQ3@?kEK5yc@Ej!|aWMP-)81&k~Z`EDy$e+~vlCJs&p yW=<9k=QpQ5gSebPE;kFuF(-%DMNlpe3kNF$A>-H>SlJo5kFvqkk?brEh_e7sKs*5e literal 0 HcmV?d00001 diff --git a/system.json b/system.json index 3f38e1b..15d6116 100644 --- a/system.json +++ b/system.json @@ -4,11 +4,10 @@ "description": "Shadows over Sol for FoundryVTT", "url": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/", "license": "LICENSE.txt", - "version": "11.0.1", + "version": "12.0.0", "compatibility": { - "minimum": "10", - "verified": "10", - "maximum": "11" + "minimum": "11", + "verified": "12" }, "esmodules": [ "module/sos-main.js" @@ -109,7 +108,9 @@ ], "socket": true, "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/raw/branch/v10/system.json", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-11.0.1.zip", - "gridDistance": 5, - "gridUnits": "ft" + "download": "https://www.uberwald.me/gitea/public/foundryvtt-shadows-over-sol/archive/foundryvtt-shadows-over-sol-12.0.0.zip", + "grid": { + "distance": 5, + "units": "ft" + } } \ No newline at end of file -- 2.35.3