Compare commits

...
Sign in to create a new pull request.

77 commits

Author SHA1 Message Date
CK
2212e3c7d8
Merge pull request #239 from unrealkakeman89/Develop
Develop
2021-07-07 09:24:23 -04:00
CK
8c0ad582f7
Merge pull request #238 from unrealkakeman89/prettier
Prettier setup
2021-07-07 09:22:51 -04:00
TJ
584767b352 Formatted js files 2021-07-06 19:57:18 -05:00
TJ
d1b123100e Merge branch 'Develop' into prettier 2021-07-06 19:37:55 -05:00
Jacob Lucas
0a9c9f8ef0 Removed debug flag that spammed the console 2021-07-07 00:40:00 +01:00
CK
ee7418f552
Merge pull request #236 from unrealkakeman89/Develop
Develop
2021-07-06 06:10:24 -04:00
CK
c44ad926a5
Merge pull request #235 from unrealkakeman89/importer-fixes
Update calls to 0.8 api specifications
2021-07-05 10:44:40 -04:00
TJ
10ee20354b Update calls to 0.8 api specifications 2021-07-04 23:13:42 -05:00
CK
7214e3d260
Merge pull request #234 from unrealkakeman89/Develop
Various powercasting bugs
2021-07-02 20:46:59 -04:00
Jacob Lucas
97df236b54 Incremented version 2021-07-03 01:44:38 +01:00
Jacob Lucas
cac466462b Removed unnecessary calculation 2021-07-03 01:42:08 +01:00
Jacob Lucas
063d529f09 Fixed bug that prevented NPCs power DCs from having values 2021-07-03 01:41:26 +01:00
Jacob Lucas
b343a06ef6 Fixed bug that caused power points to not have the mods 2021-07-03 01:40:48 +01:00
CK
fc09308d11
Merge pull request #233 from unrealkakeman89/Develop
Develop
2021-07-01 21:54:52 -04:00
Jacob Lucas
7a18055c18 Bump max version to latest 2021-07-02 02:49:05 +01:00
Jacob Lucas
e271c41239 Fixed error that caused max force & tech points to evaluate to NaN 2021-07-02 02:48:55 +01:00
CK
5d879f99e2
Merge pull request #232 from unrealkakeman89/Develop
Develop
2021-07-01 16:31:37 -04:00
CK
df44ad0635
Merge pull request #231 from unrealkakeman89/professorbunbury-sw5e
"My Dudes" Update - 7/1/2021
2021-07-01 16:28:54 -04:00
Professor Bunbury
aff43d3e98 "My Dudes" Update - 7/1/2021
^ Updates Astrotech Engineering archetype in Archetypes compendium.
2021-07-01 16:05:37 -04:00
CK
211201caea Shoulder Cannon added 2021-06-30 17:10:13 -04:00
CK
7a29dfe600
Merge pull request #230 from unrealkakeman89/professorbunbury-sw5e
"My Dudes" Update - 6/24/2021
2021-06-29 15:35:12 -04:00
Professor Bunbury
c467738845 "My Dudes" Update - 6/24/2021
+ Adds new Force and Tech Powers and associated artwork to Force Powers and Tech Powers compendia.
2021-06-29 15:33:17 -04:00
CK
8a0940ccce Update Weapons Artwork pt2 2021-06-29 10:17:00 -04:00
CK
3b4300a8eb
Merge pull request #229 from unrealkakeman89/ammo-fix
Fix for blaster ammunition
2021-06-29 10:02:22 -04:00
CK
55bbb95cfb Updated Weapons Artwork 2021-06-29 10:02:02 -04:00
TJ
62e31afff2 Fix for blaster ammunition 2021-06-28 19:15:31 -05:00
TJ
da5223cab8 Prettier settings 2021-06-28 18:54:49 -05:00
CK
db286f7883
Merge pull request #228 from unrealkakeman89/split-powercasting
Split powercasting
2021-06-28 17:30:16 -04:00
supervj
25684173fa Update entity.js
looks good to me
2021-06-28 17:14:03 -04:00
supervj
74d841e9e1 split powercasting
Split where powercasting is done so that it can be changed by DAE.
2021-06-28 12:57:06 -04:00
Jacob Lucas
53064c0e09 Removed strange C from sidebar of power sheet when concentration is on 2021-06-24 19:08:37 +01:00
Jacob Lucas
9a21ce2b2a Fixed broken json for power cell 2021-06-24 15:57:23 +01:00
Jacob Lucas
29a639ff90 Removed unnecessary imports which also caused system to fail to load 2021-06-23 18:31:19 +01:00
CK
f18e537561
Merge pull request #227 from burndaflame/master
Convulsion is a 3rd level power
2021-06-23 13:08:14 -04:00
CK
bac8e3d642
Merge pull request #224 from unrealkakeman89/power-cell-fix
Always create a new power cell
2021-06-23 13:04:18 -04:00
CK
65594f62a3
Merge pull request #223 from unrealkakeman89/professorbunbury-sw5e
"My Dudes" Update - 6/17/2021
2021-06-23 13:03:45 -04:00
Jacob Lucas
e30d823225 Removed unnecessary additions to migration 2021-06-23 17:22:28 +01:00
burndaflame
17de2a89c2 Convulsion is a 3rd level power 2021-06-23 18:18:37 +02:00
TJ
95b2b1e39c Merge branch 'Develop' into 1.3.5-dev 2021-06-23 10:59:17 -05:00
supervj
fe520f2c0d Update class.html
forgot to hit save apparently, although this is all commented out anyway.
2021-06-23 03:01:59 -04:00
supervj
9a86bf7857 Finish core upgrade to 1.3.5
Filled in some missing pieces in html for core upgrades.  Looked mostly good on both Cyr and Jacob's accounts.

I had a few questions about differences that were added from DND5e, they are as follows:

less\original\npc.less
	line 34 - is the "li" before .creature-type necessary, not in dnd5e

module\item\entity.js
	line 685 - dnd is game.user._id, we have game.user.data._id

module\pixi\ability-template.js
	line 22- dnd is game.user._id, we have game.user.data._id

templates\chat\item-card.html
	line 1- dnd has actor._id, we have actor.data._id
2021-06-23 02:53:39 -04:00
TJ
88f5c0cbed Update missed config tags 2021-06-21 18:31:37 -05:00
TJ
c0e71fe0f3 Changes for 1.3.5 2021-06-21 18:27:34 -05:00
TJ
ffffe5da52 Always create a new power cell 2021-06-21 17:39:10 -05:00
Professor Bunbury
cd9bdf61d2 "My Dudes" Update - 6/17/2021
+ Adds Teräs Käsi Order and associated artwork to Archetypes compendium.
2021-06-18 19:31:42 -04:00
CK
e2f002292b
Merge pull request #222 from unrealkakeman89/professorbunbury-sw5e
Correction to Species Compendium
2021-06-18 09:11:40 -04:00
Professor Bunbury
6c2d89ee82 Correction to Species Compendium
^ Updates Anzellan to correct size.
2021-06-17 20:14:21 -04:00
CK
76ef89b518
Merge pull request #221 from unrealkakeman89/Develop-0.8
Updated to 0.8
2021-06-16 13:02:20 -04:00
Jacob Lucas
b414abbb81 Removed evidence of starships from the compendium 2021-06-16 17:58:35 +01:00
CK
53a845feb7
Add Italian 2021-06-16 12:49:54 -04:00
CK
7134c4ac07
add Italian 2021-06-16 12:42:59 -04:00
Jacob Lucas
585de42a46 Removed evidence of Starships 2021-06-16 17:24:34 +01:00
CK
2007d116a2
Merge pull request #219 from unrealkakeman89/professorbunbury-sw5e
"My Dudes" Update - 6/10/2021
2021-06-16 11:57:51 -04:00
Jacob Lucas
104e49615d Updated to 1.3.3, started removing evidence of statships 2021-06-13 04:25:56 +01:00
Professor Bunbury
6041564835 "My Dudes" Update - 6/10/2021
+ Adds Nikto and associated artwork to Species compendium.
^ Updates Half-Human inherited traits in Species compendium.
2021-06-12 12:15:40 -04:00
CK
64bae2140c
Merge pull request #218 from burndaflame/patch-1
now ignoring ´.DS_Store´ file of mac-os
2021-06-09 13:02:47 -04:00
burndaflame
c3cbc96499
now ignoring ´.DS_Store´ file of mac-os 2021-06-09 19:01:07 +02:00
Jacob Lucas
37a3e83f3a Potentially updated Migration 2021-06-09 02:29:03 +01:00
Jacob Lucas
db5e90281c Updated version for compatibility with modules 2021-06-04 23:21:52 +01:00
Jacob Lucas
92bf020cdf General Cleanup
CSS
 - Removed unnecessary units on 0 values
 - Replaced invalid css values (such as line-height default) with valid equivalents
Templates
 - Added missing closing tags
 - Fixed incorrect closing tags
 - Removed unnecessary closing tags
2021-06-04 22:20:48 +01:00
Jacob Lucas
d0e0dda2b3 Patched issue that meant that all powers were not being prepared 2021-06-04 22:20:48 +01:00
Jacob Lucas
b0c928c691 Patched issue that prevented the old actor sheet from opening 2021-06-04 22:20:48 +01:00
Jacob Lucas
c454c035a3 Fixed new character sheet's send language to chat function
- Cleaned up unused variables
 - Updated _id get to 0.8 standard
 - Patched fetching languages failing
 - Patched blind and gm chat option not doing anything while simultaneously calling a non existent function and dying
 - Patched self chat option still sending to everyone
2021-06-04 22:20:48 +01:00
Jacob Lucas
f839166082 Added changes from DND5e 1.3.3 2021-06-04 22:20:48 +01:00
Jacob Lucas
3cfee9dd81 Added changes to packs 2021-06-04 22:20:48 +01:00
Jacob Lucas
6295de9fd6 Cleaned up actor 2021-06-04 22:20:48 +01:00
Jacob Lucas
2a7e1c419e Updated to DND5e 1.3.2
Things unfinished:
 - Migration
 - The update adds new sections to the class sheet to allow some light customisation, this hasn't been included, but could be extended for the sake of dynamic classes with automatic class features and more
 - The French
 - The packs have not yet been updated, meaning due to the addition of a progression field to the class item, classes now don't set force or tech points
 - I updated the function calls in starships, but I didn't update it very thoroughly, it'll need checking
 - I only did a little testing
 - There has since been updates to DND5e that hasn't made it to release that patch bugs, those should be implemented
Things changed from base 5e:
 - Short rests and long rests were merged into one function, this needed some rewrites to account for force and tech points, and for printing the correct message
Extra Comments:
 - Unfinished code exists for automatic spell scrolls, this could be extended for single use force or tech powers
 - Weapon proficiencies probably need revising
 - Elven accuracy, halfling lucky, and reliable talent are present in the roll logic, this probably needs revising for sw5e
 - SW5e has a variant rule that permits force powers of any alignment to use either charisma or wisdom, that could be implemented
 - SW5e's version of gritty realism, [Longer Rests](https://sw5e.com/rules/variantRules/Longer%20Rests) differs from base dnd, this could be implemented
 - Extra ideas I've had while looking through the code can be found in Todos next to the ideas relevant context
2021-06-04 22:20:48 +01:00
CK
84ab6cf478
Merge pull request #203 from unrealkakeman89/dependabot/npm_and_yarn/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9
2021-05-12 08:52:14 -04:00
dependabot[bot]
d39fa6acf2
Bump hosted-git-info from 2.8.8 to 2.8.9
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 22:42:24 +00:00
CK
0a4b6de0fa
Merge pull request #202 from unrealkakeman89/hotfix-ammo-usage
Fix for blasters not consuming ammo
2021-05-09 19:58:43 -04:00
TJ
c33982f97c Fix for blasters not consuming ammo 2021-05-09 18:53:05 -05:00
CK
4f0c6addcf
Merge pull request #185 from unrealkakeman89/dependabot/npm_and_yarn/y18n-3.2.2
Bump y18n from 3.2.1 to 3.2.2
2021-04-01 11:42:36 -04:00
dependabot[bot]
7c03cd4b04
Bump y18n from 3.2.1 to 3.2.2
Bumps [y18n](https://github.com/yargs/y18n) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-31 17:09:05 +00:00
CK
fee77e2172
Merge pull request #172 from unrealkakeman89/Develop
Develop
2021-03-16 10:15:16 -04:00
CK
87d615babc
Merge pull request #155 from ExileofBrokenSky/ExileOfBrokenSky
updated operative
2021-03-11 15:00:27 -05:00
Michael Burgess
04dcaf332d Added Guardian archetype: Aqinos Form
updated icons for scholar and made individual entries for discoveries and maneuvers
added (Maneuver) to fighter and scholar maneuver names, for ease of searching all maneuvers in the directory
2021-03-05 13:09:52 -05:00
Michael Burgess
4ee235566d updated operative
expanded options into class features for each
exploit including skills exploits
visited your mom
individualized the previously shared operative and monk ability score increases
added midi-qol superSaver effect to Evasion (Operative)
2021-02-25 10:40:41 -05:00
127 changed files with 16948 additions and 11184 deletions

3
.gitignore vendored
View file

@ -22,6 +22,9 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Mac-OS file
.DS_Store
# IDE Folders
.idea/
.vs/

14
.prettierrc Normal file
View file

@ -0,0 +1,14 @@
{
"printWidth": 120,
"tabWidth": 4,
"useTabs": false,
"semi": true,
"singleQuote": false,
"quoteProps": "consistent",
"jsxSingleQuote": false,
"trailingComma": "none",
"bracketSpacing": false,
"jsxBracketSameLine": false,
"arrowParens": "always",
"endOfLine": "lf"
}

View file

@ -1,2 +1,3 @@
{
"editor.formatOnSave": true
}

View file

@ -43,11 +43,13 @@
"SETTINGS.5eInitTBN": "Initiative Dexterity Tiebreaker",
"SETTINGS.5eNoExpL": "Remove experience bars from character sheets.",
"SETTINGS.5eNoExpN": "Disable Experience Tracking",
"SETTINGS.5eReset": "Reset",
"SETTINGS.5eRestEpic": "Epic Heroism (LR: 1 hour, SR: 1 min)",
"SETTINGS.5eRestGritty": "Gritty Realism (LR: 7 days, SR: 8 hours)",
"SETTINGS.5eRestL": "Configure which rest variant should be used for games within this system.",
"SETTINGS.5eRestN": "Rest Variant",
"SETTINGS.5eRestPHB": "Player's Handbook (LR: 8 hours, SR: 1 hour)",
"SETTINGS.5eUndoChanges": "Undo Changes",
"SETTINGS.SWColorDark": "Dark Theme",
"SETTINGS.SWColorL": "Set the color theme of the game",
"SETTINGS.SWColorLight": "Light Theme",
@ -78,6 +80,7 @@
"SW5E.AbilityUseCast": "Cast Power",
"SW5E.AbilityUseChargedHint": "This {type} is charged and ready to use!",
"SW5E.AbilityUseChargesLabel": "{value} Charges",
"SW5E.AbilityUseConfig": "Usage Configuration",
"SW5E.AbilityUseConsumableChargeHint": "Using this {type} will consume 1 charge of {value} remaining.",
"SW5E.AbilityUseConsumableDestroyHint": "Using this {type} will consume its final charge and it will be destroyed.",
"SW5E.AbilityUseConsumableLabel": "{max} per {per}",
@ -104,7 +107,9 @@
"SW5E.ActionUtil": "Utility",
"SW5E.ActionWarningNoItem": "The requested item {item} no longer exists on Actor {name}",
"SW5E.ActionWarningNoToken": "You must have one or more controlled Tokens in order to use this option.",
"SW5E.ActorWarningInvalidItem": "{itemType} items cannot be added to a {actorType}.",
"SW5E.Add": "Add",
"SW5E.AddEmbeddedItemPromptHint": "Do you want to add these items to your character sheet?",
"SW5E.AdditionalNotes": "Additional Notes",
"SW5E.Advantage": "Advantage",
"SW5E.Alignment": "Alignment",
@ -118,6 +123,7 @@
"SW5E.AlignmentND": "Neutral Dark",
"SW5E.AlignmentNL": "Neutral Light",
"SW5E.Appearance": "Appearance",
"SW5E.Apply": "Apply",
"SW5E.ArchetypeName": "Archetype Name",
"SW5E.Archetypes": "Archetypes",
"SW5E.ArmorClass": "Armor Class",
@ -199,7 +205,11 @@
"SW5E.ChatContextHealing": "Apply Healing",
"SW5E.ChatFlavor": "Chat Message Flavor",
"SW5E.ClassLevels": "Class Levels",
"SW5E.ClassMakeOriginal": "Original Class",
"SW5E.ClassMakeOriginalHint": "First class taken by character used to determine certain class traits when multiclassing.",
"SW5E.ClassName": "Class Name",
"SW5E.ClassOriginal": "Original Class",
"SW5E.ClassSaves": "Saving Throws",
"SW5E.ClassSkillsChosen": "Chosen Class Skills",
"SW5E.ClassSkillsNumber": "Number of Starting Skills",
"SW5E.Collapse": "Collapse/Expand",
@ -261,7 +271,32 @@
"SW5E.CoverHalf": "Half",
"SW5E.CoverThreeQuarters": "Three Quarters",
"SW5E.CoverTotal": "Total",
"SW5E.CreatureAberration": "Aberration",
"SW5E.CreatureAberrationPl": "Aberrations",
"SW5E.CreatureBeast": "Beast",
"SW5E.CreatureBeastPl": "Beasts",
"SW5E.CreatureConstruct": "Construct",
"SW5E.CreatureConstructPl": "Constructs",
"SW5E.CreatureDroid": "Droid",
"SW5E.CreatureDroidPl": "Droids",
"SW5E.CreatureForceEntity": "Force Entity",
"SW5E.CreatureForceEntityPl": "Force Entities",
"SW5E.CreatureHumanoid": "Humanoid",
"SW5E.CreatureHumanoidPl": "Humanoids",
"SW5E.CreaturePlant": "Plant",
"SW5E.CreaturePlantPl": "Plants",
"SW5E.CreatureSwarm": "Swarm",
"SW5E.CreatureSwarmPhrase": "Swarm of {size} {type}",
"SW5E.CreatureSwarmSize": "Swarm Size",
"SW5E.CreatureType": "Creature Type",
"SW5E.CreatureTypeConfig": "Configure Creature Type",
"SW5E.CreatureTypeSelectorCustom": "Custom Type",
"SW5E.CreatureTypeSelectorSubtype": "Subtype",
"SW5E.CreatureTypeTitle": "Configure Creature Type",
"SW5E.CreatureUndead": "Undead",
"SW5E.CreatureUndeadPl": "Undead",
"SW5E.CrewCap": "Crew Capacity",
"SW5E.Crewed": "Crewed",
"SW5E.Critical": "Critical",
"SW5E.CriticalHit": "Critical Hit",
"SW5E.Currency": "Currency",
@ -283,7 +318,6 @@
"SW5E.DamageRoll": "Damage Roll",
"SW5E.DamageSonic": "Sonic",
"SW5E.DamImm": "Damage Immunities",
"SW5E.DmgRed": "Damage Reduction",
"SW5E.DamRes": "Damage Resistances",
"SW5E.DamVuln": "Damage Vulnerabilities",
"SW5E.DarkPowerDC": "Dark Power DC",
@ -309,24 +343,29 @@
"SW5E.DistMi": "Miles",
"SW5E.DistSelf": "Self",
"SW5E.DistTouch": "Touch",
"SW5E.DmgRed": "Damage Reduction",
"SW5E.Duration": "Duration",
"SW5E.EffectsCategoryTemporary": "Temporary Effects",
"SW5E.EffectsCategoryPassive": "Passive Effects",
"SW5E.EffectsCategoryInactive": "Inactive Effects",
"SW5E.EffectCreate": "Create Effect",
"SW5E.EffectDelete": "Delete Effect",
"SW5E.EffectEdit": "Edit Effect",
"SW5E.EffectInactive": "Inactive Effects",
"SW5E.EffectNew": "New Effect",
"SW5E.EffectPassive": "Passive Effects",
"SW5E.Effects": "Effects",
"SW5E.EffectTemporary": "Temporary Effects",
"SW5E.EffectsCategoryInactive": "Inactive Effects",
"SW5E.EffectsCategoryPassive": "Passive Effects",
"SW5E.EffectsCategoryTemporary": "Temporary Effects",
"SW5E.EffectToggle": "Toggle Effect",
"SW5E.Engine": "Engine",
"SW5E.EnginePl": "Engines",
"SW5E.EquipmentBonus": "Magical Bonus",
"SW5E.EquipmentClothing": "Clothing",
"SW5E.EquipmentHeavy": "Heavy Armor",
"SW5E.EquipmentHyperdrive": "Hyperdrive",
"SW5E.EquipmentLight": "Light Armor",
"SW5E.EquipmentMedium": "Medium Armor",
"SW5E.EquipmentNatural": "Natural Armor",
"SW5E.EquipmentHyperdrive": "Hyperdrive",
"SW5E.EquipmentPowerCoupling": "Power Coupling",
"SW5E.EquipmentReactor": "Reactor",
"SW5E.EquipmentShield": "Shield",
@ -341,6 +380,7 @@
"SW5E.Expertise": "Expertise",
"SW5E.Favorites": "Favorites",
"SW5E.FavoritesAndNotes": "Favorites & Notes",
"SW5E.Feats": "Feats",
"SW5E.FeatureActionRecharge": "Action Recharge",
"SW5E.FeatureActive": "Active Abilities",
"SW5E.FeatureAdd": "Create Feature",
@ -351,8 +391,8 @@
"SW5E.FeatureRechargeOn": "Recharge On",
"SW5E.FeatureRechargeResult": "1d6 Result",
"SW5E.Features": "Features",
"SW5E.FeatureUsage": "Feature Usage",
"SW5E.FeatureType": "Feature Type",
"SW5E.FeatureUsage": "Feature Usage",
"SW5E.FeetAbbr": "ft.",
"SW5E.Filter": "Filter",
"SW5E.FilterNoPowers": "No powers found for this set of filters.",
@ -482,8 +522,8 @@
"SW5E.ForcePowerbook": "Force Powers",
"SW5E.Formula": "Formula",
"SW5E.FuelCapacity": "Fuel Capacity",
"SW5E.FuelCostsMod": "Fuel Costs Modifier",
"SW5E.FuelCostPerUnit": "Fuel Cost per Unit",
"SW5E.FuelCostsMod": "Fuel Costs Modifier",
"SW5E.GrantedAbilities": "Granted Abilities",
"SW5E.HalfProficient": "Half Proficient",
"SW5E.HardpointSizeMod": "Hardpoint Size Modifier",
@ -493,6 +533,10 @@
"SW5E.HealthConditions": "Health Conditions",
"SW5E.HealthFormula": "Health Formula",
"SW5E.HitDice": "Hit Dice",
"SW5E.HitDiceConfig": "Adjust Hit Dice",
"SW5E.HitDiceConfigHint": "Adjust remaining hit dice levels for each class.",
"SW5E.HitDiceMax": "Maximum Hit Dice",
"SW5E.HitDiceRemaining": "Remaining Hit Dice",
"SW5E.HitDiceRoll": "Roll Hit Dice",
"SW5E.HitDiceUsed": "Hit Dice Used",
"SW5E.HitDiceWarn": "{name} has no available {formula} Hit Dice remaining!",
@ -545,6 +589,7 @@
"SW5E.ItemTypeArchetype": "Archetype",
"SW5E.ItemTypeBackground": "Background",
"Sw5E.ItemTypeBackgroundPl": "Backgrounds",
"SW5E.ItemTypeBackpack": "Container",
"SW5E.ItemTypeClass": "Class",
"SW5E.ItemTypeClassFeat": "Class Feature",
"SW5E.ItemTypeClassFeats": "Class Features",
@ -554,9 +599,9 @@
"SW5E.ItemTypeContainer": "Container",
"SW5E.ItemTypeContainerPl": "Containers",
"SW5E.ItemTypeDeployment": "Deployment",
"SW5E.ItemTypeDeploymentPl": "Deployments",
"SW5E.ItemTypeDeploymentFeature": "Deployment Feature",
"SW5E.ItemTypeDeploymentFeaturePl": "Deployment Features",
"SW5E.ItemTypeDeploymentPl": "Deployments",
"SW5E.ItemTypeEquipment": "Equipment",
"SW5E.ItemTypeEquipmentPl": "Equipment",
"SW5E.ItemTypeFeat": "Feat",
@ -711,6 +756,7 @@
"SW5E.LongRest": "Long Rest",
"SW5E.LongRestEpic": "Long Rest (1 hour)",
"SW5E.LongRestGritty": "Long Rest (7 days)",
"SW5E.LongRestHint": "Take a long rest? On a long rest you will recover hit points, half your maximum hit dice, class resources, limited use item charges, and power points.",
"SW5E.LongRestNormal": "Long Rest (8 hours)",
"SW5E.LongRestOvernight": "Long Rest (New Day)",
"SW5E.LongRestResult": "{name} takes a long rest.",
@ -730,8 +776,8 @@
"SW5E.LongRestResultTP": "{name} takes a long rest and recovers {tech} Tech Points.",
"SW5E.LongRestResultTPHD": "{name} takes a long rest and recovers {tech} Tech Points and {dice} Hit Dice.",
"SW5E.Max": "Max",
"SW5E.Modifier": "Modifier",
"SW5E.ModCap": "Modification Capacity",
"SW5E.Modifier": "Modifier",
"SW5E.Movement": "Movement",
"SW5E.MovementBurrow": "Burrow",
"SW5E.MovementClimb": "Climb",
@ -747,6 +793,8 @@
"SW5E.MovementUnits": "Units",
"SW5E.MovementWalk": "Walk",
"SW5E.Name": "Character Name",
"SW5E.NewDay": "Is New Day?",
"SW5E.NewDayHint": "Recover limited use abilities which recharge \"per day\"?",
"SW5E.NoCharges": "No Charges",
"SW5E.None": "None",
"SW5E.NoPowerLevels": "This character has no powercaster levels, but you may add powers manually.",
@ -799,11 +847,12 @@
"SW5E.PowerCreate": "Create Power",
"SW5E.PowerDC": "Power DC",
"SW5E.PowerDetails": "Power Details",
"SW5E.PowerDie": "Power Die",
"SW5E.PowerDiePl": "Power Dice",
"SW5E.PowerDieAlloc": "Power Die Allocation",
"SW5E.PowerDiceRecovery": "Power Dice Recovery",
"SW5E.PowerDie": "Power Die",
"SW5E.PowerDieAlloc": "Power Die Allocation",
"SW5E.PowerDiePl": "Power Dice",
"SW5E.PowerEffects": "Power Effects",
"SW5E.PowerfulCritical": "Powerful Critical",
"SW5E.PowerLevel": "Power Level",
"SW5E.PowerLevel0": "At-Will",
"SW5E.PowerLevel1": "1st Level",
@ -833,9 +882,9 @@
"SW5E.PowerProgression": "Power Progression",
"SW5E.PowerProgSct": "Scout",
"SW5E.PowerProgSnt": "Sentinel",
"SW5E.PowerRouting": "Power Routing",
"SW5E.PowerSchool": "Power School",
"SW5E.PowersKnown": "Powers Known",
"SW5E.PowerRouting": "Power Routing",
"SW5E.PowerTarget": "Power Target",
"SW5E.PowerUnprepared": "Unprepared",
"SW5E.PowerUsage": "Power Usage",
@ -856,17 +905,18 @@
"SW5E.RegenerationRateCoefficient": "Regeneration Rate Coefficient",
"SW5E.RequiredMaterials": "Required Materials",
"SW5E.Requirements": "Requirements",
"SW5E.ResourcesAndTraits": "Resources & Traits",
"SW5E.ResourcePrimary": "Resource 1",
"SW5E.ResourcesAndTraits": "Resources & Traits",
"SW5E.ResourceSecondary": "Resource 2",
"SW5E.ResourceTertiary": "Resource 3",
"SW5E.Rest": "Rest",
"SW5E.RestL": "L. Rest",
"SW5E.RestS": "S. Rest",
"SW5E.Ritual": "Ritual",
"SW5E.Role": "Role",
"SW5E.RolePl": "Roles",
"SW5E.Roll": "Roll",
"SW5E.RollExample": "e.g. +1d4",
"SW5E.RollExample": "e.g. 1d4",
"SW5E.RollMode": "Roll Mode",
"SW5E.RollSituationalBonus": "Situational Bonus?",
"SW5E.Save": "Save",
@ -879,6 +929,7 @@
"SW5E.SchoolLgt": "Light",
"SW5E.SchoolTec": "Tech",
"SW5E.SchoolUni": "Universal",
"SW5E.SelectItemsPromptTitle": "Select Items",
"SW5E.SenseBlindsight": "Blindsight",
"SW5E.SenseBS": "Blindsight",
"SW5E.SenseDarkvision": "Darkvision",
@ -940,6 +991,7 @@
"SW5E.SkillSte": "Stealth",
"SW5E.SkillSur": "Survival",
"SW5E.SkillTec": "Technology",
"SW5E.Skip": "Skip",
"SW5E.Slots": "Slots",
"SW5E.Source": "Source",
"SW5E.Special": "Special",
@ -950,8 +1002,8 @@
"SW5E.Speed": "Speed",
"SW5E.SpeedSpecial": "Special Movement",
"SW5E.StarshipAmbassador": "Ambassador",
"SW5E.StarshipArmorandShields": "Starship Armor and Shields",
"SW5E.StarshipArmorandShieldProps": "Starship Armor & Shield Properties",
"SW5E.StarshipArmorandShields": "Starship Armor and Shields",
"SW5E.StarshipBattleship": "Battleship",
"SW5E.StarshipBlockadeShip": "Blockade Ship",
"SW5E.StarshipBomber": "Bomber",
@ -1076,6 +1128,7 @@
"SW5E.TraitToolProf": "Tool Proficiencies",
"SW5E.TraitWeaponProf": "Weapon Proficiencies",
"SW5E.Type": "Type",
"SW5E.Uncrewed": "Uncrewed",
"SW5E.Unequipped": "Unequipped",
"SW5E.UniversalPowerDC": "Universal Power DC",
"SW5E.Unlimited": "Unlimited",
@ -1100,16 +1153,27 @@
"SW5E.VersatileDamage": "Versatile Damage",
"SW5E.VsDC": "vs DC.",
"SW5E.WeaponAmmo": "Ammunition",
"SW5E.WeaponBlasterPistolProficiency": "Blaster Pistol",
"SW5E.WeaponChakramProficiency": "Chakrams",
"SW5E.WeaponDoubleBladeProficiency": "Doubleblade",
"SW5E.WeaponDoubleSaberProficiency": "Doublesaber",
"SW5E.WeaponDoubleShotoProficiency": "Doubleshoto",
"SW5E.WeaponDoubleSwordProficiency": "Doublesword",
"SW5E.WeaponHiddenBladeProficiency": "Hidden Blade",
"SW5E.WeaponImprov": "Improvised",
"SW5E.WeaponImprovisedProficiency": "Improvised Weapons",
"SW5E.WeaponLightFoilProficiency": "Lightfoil",
"SW5E.WeaponLightRingProficiency": "Light Ring",
"SW5E.WeaponMartialB": "Martial Blaster",
"SW5E.WeaponMartialBlasterProficiency": "Martial Blasters",
"SW5E.WeaponMartialLightweaponProficiency": "Martial Lightweapons",
"SW5E.WeaponMartialLW": "Martial Lightweapon",
"SW5E.WeaponPrimarySW": "Primary (Starship)",
"SW5E.WeaponSecondarySW": "Secondary (Starship)",
"SW5E.WeaponTertiarySW": "Tertiary (Starship)",
"SW5E.WeaponQuaternarySW": "Quaternary (Starship)",
"SW5E.WeaponMartialProficiency": "Martial Weapons",
"SW5E.WeaponMartialVibroweaponProficiency": "Martial Vibroweapons",
"SW5E.WeaponMartialVW": "Martial Vibroweapon",
"SW5E.WeaponNatural": "Natural",
"SW5E.WeaponNaturalProficiency": "Natural Weapons",
"SW5E.WeaponPrimarySW": "Primary (Starship)",
"SW5E.WeaponPropertiesAmm": "Ammunition",
"SW5E.WeaponPropertiesAut": "Auto",
"SW5E.WeaponPropertiesBur": "Burst",
@ -1127,14 +1191,14 @@
"SW5E.WeaponPropertiesFix": "Fixed",
"SW5E.WeaponPropertiesFoc": "Focus",
"SW5E.WeaponPropertiesHid": "Hidden",
"SW5E.WeaponPropertiesHvy": "Heavy",
"SW5E.WeaponPropertiesHom": "Homing",
"SW5E.WeaponPropertiesHvy": "Heavy",
"SW5E.WeaponPropertiesIon": "Ionizing",
"SW5E.WeaponPropertiesKen": "Keen",
"SW5E.WeaponPropertiesLgt": "Light",
"SW5E.WeaponPropertiesLum": "Luminous",
"SW5E.WeaponPropertiesMlt": "Melt",
"SW5E.WeaponPropertiesMig": "Mighty",
"SW5E.WeaponPropertiesMlt": "Melt",
"SW5E.WeaponPropertiesOvr": "Overheat",
"SW5E.WeaponPropertiesPic": "Piercing",
"SW5E.WeaponPropertiesPow": "Power",
@ -1153,32 +1217,21 @@
"SW5E.WeaponPropertiesVer": "Versatile",
"SW5E.WeaponPropertiesVic": "Vicious",
"SW5E.WeaponPropertiesZon": "Zone",
"SW5E.WeaponQuaternarySW": "Quaternary (Starship)",
"SW5E.WeaponSaberWhipProficiency": "Saberwhip",
"SW5E.WeaponSecondarySW": "Secondary (Starship)",
"SW5E.WeaponSiege": "Siege",
"SW5E.WeaponSimpleB": "Simple Blaster",
"SW5E.WeaponSimpleLW": "Simple Lightweapon",
"SW5E.WeaponBlasterPistolProficiency": "Blaster Pistol",
"SW5E.WeaponChakramProficiency": "Chakrams",
"SW5E.WeaponDoubleBladeProficiency": "Doubleblade",
"SW5E.WeaponDoubleSaberProficiency": "Doublesaber",
"SW5E.WeaponDoubleShotoProficiency": "Doubleshoto",
"SW5E.WeaponDoubleSwordProficiency": "Doublesword",
"SW5E.WeaponHiddenBladeProficiency": "Hidden Blade",
"SW5E.WeaponImprovisedProficiency": "Improvised Weapons",
"SW5E.WeaponSimpleProficiency": "Simple Weapons",
"SW5E.WeaponLightFoilProficiency": "Lightfoil",
"SW5E.WeaponLightRingProficiency": "Light Ring",
"SW5E.WeaponMartialBlasterProficiency": "Martial Blasters",
"SW5E.WeaponMartialLightweaponProficiency": "Martial Lightweapons",
"SW5E.WeaponMartialVibroweaponProficiency": "Martial Vibroweapons",
"SW5E.WeaponNaturalProficiency": "Natural Weapons",
"SW5E.WeaponSaberWhipProficiency": "Saberwhip",
"SW5E.WeaponSimpleBlasterProficiency": "Simple Blasters",
"SW5E.WeaponSimpleLightweaponProficiency": "Simple Lightweapons",
"SW5E.WeaponSimpleLW": "Simple Lightweapon",
"SW5E.WeaponSimpleProficiency": "Simple Weapons",
"SW5E.WeaponSimpleVibroweaponProficiency": "Simple Vibroweapons",
"SW5E.WeaponSimpleVW": "Simple Vibroweapon",
"SW5E.WeaponSizeAbb": "Size",
"SW5E.WeaponTechbladeProficiency": "Techblades",
"SW5E.WeaponTertiarySW": "Tertiary (Starship)",
"SW5E.WeaponVibrorapierProficiency": "Vibrorapier",
"SW5E.WeaponVibrowhipProficiency": "Vibrowhip",
"SW5E.WeaponSizeAbb": "Size",
"SW5E.Weight": "Weight"
}

1027
lang/it.json Normal file

File diff suppressed because it is too large Load diff

View file

@ -71,7 +71,7 @@
}
// Movement Configuration
.movement {
.movement, .hit-dice {
h4.attribute-name {
position: relative;
}
@ -655,6 +655,15 @@
// Empty powerbook controls
.powerbook-empty .item-controls { flex: 1; }
/* ----------------------------------------- */
/* Features Tab */
/* ----------------------------------------- */
// Original class icon
.features i.original-class {
color: #4b4a44
}
/* ----------------------------------------- */
/* TinyMCE */
/* ----------------------------------------- */

View file

@ -10,9 +10,7 @@
.sw5e {
.window-content {
background: @sheetBackground;
font-size: 13px;
color: @colorDark;
}
/* ----------------------------------------- */
@ -44,6 +42,8 @@
select:disabled,
textarea:disabled {
color: @colorOlive;
border: 1px solid transparent !important;
outline: none !important;
&:hover,
&:focus {
box-shadow: none !important;
@ -58,28 +58,6 @@
border: @borderGroove;
}
// Checkbox Labels
// TODO: THIS CAN BE MOSTLY REMOVED NOW THAT IT IS IN CORE, see core forms.less
label.checkbox {
flex: auto;
padding: 0;
margin: 0;
height: 22px;
line-height: 22px;
font-size: 11px;
> input[type="checkbox"] {
width: 16px;
height: 16px;
margin: 0 2px 0 0;
position: relative;
top: 4px;
}
&.right > input[type="checkbox"] {
margin: 0 0 0 2px;
}
}
/* Form Groups */
.form-group {
label {
@ -98,11 +76,12 @@
// Stacked Groups
.form-group.stacked {
label {
> label {
flex: 0 0 100%;
margin: 0;
}
label.checkbox {
label.checkbox,
label.radio {
flex: auto;
text-align: left;
}
@ -131,6 +110,34 @@
}
/* ----------------------------------------- */
/* Hit Dice Config Sheet Specifically */
/* ----------------------------------------- */
.sw5e.hd-config {
.form-group {
button.increment, button.decrement {
flex: 0 0 1rem;
line-height: 1rem;
}
button.decrement {
margin-right: 0;
}
span.sep {
margin: 0;
}
input {
flex: 0 0 2rem;
text-align: center;
margin-left: 2px;
margin-right: 2px;
}
}
}
/* ----------------------------------------- */
/* Entity Sheets Specifically */
/* ----------------------------------------- */
@ -475,7 +482,7 @@
/* Trait Selector
/* ----------------------------------------- */
#trait-selector {
.trait-selector {
.trait-list {
list-style: none;
margin: 0;
@ -488,6 +495,59 @@
}
}
/* ----------------------------------------- */
/* Actor Type Config Sheet Specifically */
/* ----------------------------------------- */
.actor-type {
.trait-list {
display: flex;
flex-wrap: wrap;
li {
flex-basis: 50%;
flex-grow: 1;
}
li.form-group {
flex-basis: 100%;
}
}
label.radio {
display: flex;
flex: auto;
font-size: 12px;
line-height: 20px;
font-weight: normal;
> input[type="radio"] {
margin: 0 5px 0 0;
}
}
li.custom-type input[type="radio"] {
display: none;
}
}
/* ----------------------------------------- */
/* Add Feature Prompt Specifically */
/* ----------------------------------------- */
.sw5e.select-items-prompt {
.dialog-content {
margin-bottom: 1em;
}
.items-list {
margin-top: 0.5em;
}
.item-name > label, .item-image, input {
cursor: pointer;
}
.item-name > label {
align-items: center;
}
}
/* ----------------------------------------- */
/* HUD
/* ----------------------------------------- */

View file

@ -89,7 +89,7 @@
// Custom Resources
.resource .attribute-value {
input {
> input {
flex: 0 0 25%;
}
label.recharge {
@ -99,6 +99,7 @@
font-size: 11px;
text-align: center;
color: @colorOlive;
align-items: center;
input[type="checkbox"] {
height: 14px;
width: 14px;

View file

@ -106,17 +106,17 @@
&:nth-child(even) {
width: 150px;
margin: 0.5em 0.5em;
padding: 0px 10px 0px 10px;
padding: 0 10px 0 10px;
text-align: left;
}
}
thead {
border-bottom: 0px;
border-bottom: 0;
}
th {
color: #000000;
text-shadow: none;
border-bottom: 0px;
border-bottom: 0;
background-color: #bdc8cc;
text-transform: none;
font-weight: bold;
@ -129,7 +129,7 @@
&:nth-child(even) {
width: 150px;
margin: 0.5em 0.5em;
padding: 0px 10px 0px 10px;
padding: 0 10px 0 10px;
text-align: left;
}
}
@ -137,7 +137,7 @@
.medtable {
table {
width: 500px;
border: 0px;
border: 0;
margin: 0.5em 0.5em;
}
td {
@ -149,17 +149,17 @@
&:nth-child(even) {
width: 450px;
margin: 0.5em 0.5em;
padding: 0px 10px 0px 0px;
padding: 0 10px 0 0;
text-align: left;
}
}
thead {
border-bottom: 0px;
border-bottom: 0;
}
th {
color: #000000;
text-shadow: none;
border-bottom: 0px;
border-bottom: 0;
background-color: #bdc8cc;
text-transform: none;
font-weight: bold;
@ -174,8 +174,8 @@
}
.classtable {
blockquote {
border-left: 0px;
border-right: 0px;
border-left: 0;
border-right: 0;
background-color: #bdc8cc;
width: 600px;
h3 {
@ -189,8 +189,8 @@
width: 100%;
border-collapse: collapse;
background: rgba(0, 0, 0, 0.05);
border-left: 0px;
border-right: 0px;
border-left: 0;
border-right: 0;
border-top: 0;
border-bottom: 0;
margin: 0.5em 0;
@ -200,7 +200,7 @@
thead {
color: #000000;
text-shadow: none;
border-bottom: 0px;
border-bottom: 0;
background-color: #bdc8cc;
text-transform: none;
font-style: normal;
@ -209,7 +209,7 @@
th {
color: #000000;
text-shadow: none;
border-bottom: 0px;
border-bottom: 0;
background-color: #bdc8cc;
text-transform: none;
font-style: normal;
@ -246,7 +246,7 @@
width: 100%;
line-height: 18px;
margin-bottom: 15px;
border: 0 0 0 0;
border: 0;
border-bottom: none;
overflow-x: auto;
tbody {

View file

@ -30,5 +30,28 @@
.summary {
font-size: 18px;
li.creature-type {
display: flex;
justify-content: space-between;
width: 1em;
padding: 0 3px;
span {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.config-button {
display: none;
font-size: 12px;
font-weight: normal;
line-height: 2em;
}
&:hover .config-button {
display: block;
}
}
}
}

View file

@ -140,6 +140,7 @@
height: auto;
.russoOne(17px);
line-height: 24px;
width: 100%;
}
.proficiency {
@ -184,7 +185,7 @@
display: inline-block;
text-align: right;
padding: 0px 3px;
padding: 0 3px;
&:last-child {
text-align: left;
@ -779,7 +780,7 @@
display: block;
width: 100%;
text-align: right;
padding: 0px 3px;
padding: 0 3px;
&:last-child {
text-align: left;
}
@ -955,7 +956,7 @@
display: block;
width: 100%;
text-align: right;
padding: 0px 3px;
padding: 0 3px;
&:last-child {
text-align: left;
}
@ -1053,10 +1054,35 @@
h1.character-name {
align-self: auto;
}
.npc-size {
.npc-size, .creature-type {
.russoOne(18px);
line-height: 28px;
}
div.creature-type {
display: flex;
justify-content: space-between;
padding: 1px 4px;
border: 1px solid transparent;
overflow-x: auto;
span {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.config-button {
display: none;
font-size: 12px;
font-weight: normal;
line-height: 2em;
}
&:hover .config-button {
display: block;
}
}
.attributes {
grid-template-columns: repeat(3, 1fr);
footer {

View file

@ -408,6 +408,9 @@
&.npc {
.swalt-sheet {
header {
div.creature-type:hover {
border-color: @inputBorderFocus;
}
.experience {
color: @actorProficiencyTextColor;
}

View file

@ -1,4 +1,4 @@
input[type="text"], input[type="number"], input[type="password"], input[type="date"], input[type="time"], select, textarea {
input[type="text"], input[type="number"], input[type="password"], input[type="date"], input[type="time"], select, textarea, .roundTransition {
border-radius: 4px;
transition: all 0.3s;
&:hover {

View file

@ -231,7 +231,7 @@
padding-bottom: 4px;
.folder {
& > .folder-header {
line-height: default;
line-height: initial;
padding: 0 0 0 8px;
position: relative;
border: none;

View file

@ -302,7 +302,7 @@
}
.folder {
& > .folder-header {
line-height: default;
line-height: initial;
padding: 0 0 0 8px;
position: relative;
border: none;

File diff suppressed because it is too large Load diff

2126
module/actor/old_entity.js Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,11 @@
import Item5e from "../../../item/entity.js";
import TraitSelector from "../../../apps/trait-selector.js";
import ActorSheetFlags from "../../../apps/actor-flags.js";
import ActorHitDiceConfig from "../../../apps/hit-dice-config.js";
import ActorMovementConfig from "../../../apps/movement-config.js";
import ActorSensesConfig from "../../../apps/senses-config.js";
import {SW5E} from '../../../config.js';
import ActorTypeConfig from "../../../apps/actor-type.js";
import {SW5E} from "../../../config.js";
import {onManageActiveEffect, prepareActiveEffectCategories} from "../../../effects.js";
/**
@ -46,81 +48,96 @@ export default class ActorSheet5e extends ActorSheet {
/* -------------------------------------------- */
/**
* A set of item types that should be prevented from being dropped on this type of actor sheet.
* @type {Set<string>}
*/
static unsupportedItemTypes = new Set();
/* -------------------------------------------- */
/** @override */
get template() {
if ( !game.user.isGM && this.actor.limited ) return "systems/sw5e/templates/actors/newActor/expanded-limited-sheet.html";
if (!game.user.isGM && this.actor.limited)
return "systems/sw5e/templates/actors/newActor/expanded-limited-sheet.html";
return `systems/sw5e/templates/actors/newActor/${this.actor.data.type}-sheet.html`;
}
/* -------------------------------------------- */
/** @override */
getData() {
getData(options) {
// Basic data
let isOwner = this.entity.owner;
let isOwner = this.actor.isOwner;
const data = {
owner: isOwner,
limited: this.entity.limited,
limited: this.actor.limited,
options: this.options,
editable: this.isEditable,
cssClass: isOwner ? "editable" : "locked",
isCharacter: this.entity.data.type === "character",
isNPC: this.entity.data.type === "npc",
isStarship: this.entity.data.type === "starship",
isVehicle: this.entity.data.type === 'vehicle',
isCharacter: this.actor.type === "character",
isNPC: this.actor.type === "npc",
isStarship: this.actor.type === "starship",
isVehicle: this.actor.type === "vehicle",
config: CONFIG.SW5E,
rollData: this.actor.getRollData.bind(this.actor)
};
// The Actor and its Items
data.actor = duplicate(this.actor.data);
data.items = this.actor.items.map(i => {
i.data.labels = i.labels;
return i.data;
});
// The Actor's data
const actorData = this.actor.data.toObject(false);
data.actor = actorData;
data.data = actorData.data;
// Owned Items
data.items = actorData.items;
for (let i of data.items) {
const item = this.actor.items.get(i._id);
i.labels = item.labels;
}
data.items.sort((a, b) => (a.sort || 0) - (b.sort || 0));
data.data = data.actor.data;
// Labels and filters
data.labels = this.actor.labels || {};
data.filters = this._filters;
// Ability Scores
for ( let [a, abl] of Object.entries(data.actor.data.abilities)) {
for (let [a, abl] of Object.entries(actorData.data.abilities)) {
abl.icon = this._getProficiencyIcon(abl.proficient);
abl.hover = CONFIG.SW5E.proficiencyLevels[abl.proficient];
abl.label = CONFIG.SW5E.abilities[a];
}
// Skills
if (data.actor.data.skills) {
for ( let [s, skl] of Object.entries(data.actor.data.skills)) {
if (actorData.data.skills) {
for (let [s, skl] of Object.entries(actorData.data.skills)) {
skl.ability = CONFIG.SW5E.abilityAbbreviations[skl.ability];
skl.icon = this._getProficiencyIcon(skl.value);
skl.hover = CONFIG.SW5E.proficiencyLevels[skl.value];
if (data.actor.type === "starship") {
skl.label = CONFIG.SW5E.starshipSkills[s];
}else{
} else {
skl.label = CONFIG.SW5E.skills[s];
}
}
}
// Movement speeds
data.movement = this._getMovementSpeed(data.actor);
data.movement = this._getMovementSpeed(actorData);
// Senses
data.senses = this._getSenses(data.actor);
data.senses = this._getSenses(actorData);
// Update traits
this._prepareTraits(data.actor.data.traits);
this._prepareTraits(actorData.data.traits);
// Prepare owned items
this._prepareItems(data);
// Prepare active effects
data.effects = prepareActiveEffectCategories(this.entity.effects);
data.effects = prepareActiveEffectCategories(this.actor.effects);
// Return data to the sheet
return data
return data;
}
/* -------------------------------------------- */
@ -132,38 +149,42 @@ export default class ActorSheet5e extends ActorSheet {
* @returns {{primary: string, special: string}}
* @private
*/
_getMovementSpeed(actorData, largestPrimary=false) {
_getMovementSpeed(actorData, largestPrimary = false) {
const movement = actorData.data.attributes.movement || {};
// Prepare an array of available movement speeds
let speeds = [
[movement.burrow, `${game.i18n.localize("SW5E.MovementBurrow")} ${movement.burrow}`],
[movement.climb, `${game.i18n.localize("SW5E.MovementClimb")} ${movement.climb}`],
[movement.fly, `${game.i18n.localize("SW5E.MovementFly")} ${movement.fly}` + (movement.hover ? ` (${game.i18n.localize("SW5E.MovementHover")})` : "")],
[
movement.fly,
`${game.i18n.localize("SW5E.MovementFly")} ${movement.fly}` +
(movement.hover ? ` (${game.i18n.localize("SW5E.MovementHover")})` : "")
],
[movement.swim, `${game.i18n.localize("SW5E.MovementSwim")} ${movement.swim}`]
]
if ( largestPrimary ) {
];
if (largestPrimary) {
speeds.push([movement.walk, `${game.i18n.localize("SW5E.MovementWalk")} ${movement.walk}`]);
}
// Filter and sort speeds on their values
speeds = speeds.filter(s => !!s[0]).sort((a, b) => b[0] - a[0]);
speeds = speeds.filter((s) => !!s[0]).sort((a, b) => b[0] - a[0]);
// Case 1: Largest as primary
if ( largestPrimary ) {
if (largestPrimary) {
let primary = speeds.shift();
return {
primary: `${primary ? primary[1] : "0"} ${movement.units}`,
special: speeds.map(s => s[1]).join(", ")
}
special: speeds.map((s) => s[1]).join(", ")
};
}
// Case 2: Walk as primary
else {
return {
primary: `${movement.walk || 0} ${movement.units}`,
special: speeds.length ? speeds.map(s => s[1]).join(", ") : ""
}
special: speeds.length ? speeds.map((s) => s[1]).join(", ") : ""
};
}
}
@ -172,12 +193,12 @@ export default class ActorSheet5e extends ActorSheet {
_getSenses(actorData) {
const senses = actorData.data.attributes.senses || {};
const tags = {};
for ( let [k, label] of Object.entries(CONFIG.SW5E.senses) ) {
const v = senses[k] ?? 0
if ( v === 0 ) continue;
for (let [k, label] of Object.entries(CONFIG.SW5E.senses)) {
const v = senses[k] ?? 0;
if (v === 0) continue;
tags[k] = `${game.i18n.localize(label)} ${v} ${senses.units}`;
}
if ( !!senses.special ) tags["special"] = senses.special;
if (!!senses.special) tags["special"] = senses.special;
return tags;
}
@ -190,20 +211,20 @@ export default class ActorSheet5e extends ActorSheet {
*/
_prepareTraits(traits) {
const map = {
"dr": CONFIG.SW5E.damageResistanceTypes,
"di": CONFIG.SW5E.damageResistanceTypes,
"dv": CONFIG.SW5E.damageResistanceTypes,
"ci": CONFIG.SW5E.conditionTypes,
"languages": CONFIG.SW5E.languages,
"armorProf": CONFIG.SW5E.armorProficiencies,
"weaponProf": CONFIG.SW5E.weaponProficiencies,
"toolProf": CONFIG.SW5E.toolProficiencies
dr: CONFIG.SW5E.damageResistanceTypes,
di: CONFIG.SW5E.damageResistanceTypes,
dv: CONFIG.SW5E.damageResistanceTypes,
ci: CONFIG.SW5E.conditionTypes,
languages: CONFIG.SW5E.languages,
armorProf: CONFIG.SW5E.armorProficiencies,
weaponProf: CONFIG.SW5E.weaponProficiencies,
toolProf: CONFIG.SW5E.toolProficiencies
};
for ( let [t, choices] of Object.entries(map) ) {
for (let [t, choices] of Object.entries(map)) {
const trait = traits[t];
if ( !trait ) continue;
if (!trait) continue;
let values = [];
if ( trait.value ) {
if (trait.value) {
values = trait.value instanceof Array ? trait.value : [trait.value];
}
trait.selected = values.reduce((obj, t) => {
@ -212,8 +233,8 @@ export default class ActorSheet5e extends ActorSheet {
}, {});
// Add custom entry
if ( trait.custom ) {
trait.custom.split(";").forEach((c, i) => trait.selected[`custom${i+1}`] = c.trim());
if (trait.custom) {
trait.custom.split(";").forEach((c, i) => (trait.selected[`custom${i + 1}`] = c.trim()));
}
trait.cssClass = !isObjectEmpty(trait.selected) ? "" : "inactive";
}
@ -225,17 +246,18 @@ export default class ActorSheet5e extends ActorSheet {
* Insert a power into the powerbook object when rendering the character sheet
* @param {Object} data The Actor data being prepared
* @param {Array} powers The power data being prepared
* @param {string} school The school of the powerbook being prepared
* @private
*/
_preparePowerbook(data, powers, school) {
const owner = this.actor.owner;
const owner = this.actor.isOwner;
const levels = data.data.powers;
const powerbook = {};
// Define some mappings
const sections = {
"atwill": -20,
"innate": -10,
atwill: -20,
innate: -10
};
// Label power slot uses headers
@ -246,32 +268,37 @@ export default class ActorSheet5e extends ActorSheet {
};
// Format a powerbook entry for a certain indexed level
const registerSection = (sl, i, label, {prepMode="prepared", value, max, override}={}) => {
const registerSection = (sl, i, label, {prepMode = "prepared", value, max, override} = {}) => {
powerbook[i] = {
order: i,
label: label,
usesSlots: i > 0,
canCreate: owner,
canPrepare: (data.actor.type === "character") && (i >= 1),
canPrepare: data.actor.type === "character" && i >= 1,
powers: [],
uses: useLabels[i] || value || 0,
slots: useLabels[i] || max || 0,
override: override || 0,
dataset: {"type": "power", "level": prepMode in sections ? 1 : i, "preparation.mode": prepMode, "school": school},
dataset: {
"type": "power",
"level": prepMode in sections ? 1 : i,
"preparation.mode": prepMode,
"school": school
},
prop: sl
};
};
// Determine the maximum power level which has a slot
const maxLevel = Array.fromRange(10).reduce((max, i) => {
if ( i === 0 ) return max;
if (i === 0) return max;
const level = levels[`power${i}`];
if ( (level.max || level.override ) && ( i > max ) ) max = i;
if ((level.max || level.override) && i > max) max = i;
return max;
}, 0);
// Level-based powercasters have cantrips and leveled slots
if ( maxLevel > 0 ) {
if (maxLevel > 0) {
registerSection("power0", 0, CONFIG.SW5E.powerLevels[0]);
for (let lvl = 1; lvl <= maxLevel; lvl++) {
const sl = `power${lvl}`;
@ -280,15 +307,15 @@ export default class ActorSheet5e extends ActorSheet {
}
// Iterate over every power item, adding powers to the powerbook by section
powers.forEach(power => {
powers.forEach((power) => {
const mode = power.data.preparation.mode || "prepared";
let s = power.data.level || 0;
const sl = `power${s}`;
// Specialized powercasting modes (if they exist)
if ( mode in sections ) {
if (mode in sections) {
s = sections[mode];
if ( !powerbook[s] ){
if (!powerbook[s]) {
const l = levels[mode] || {};
const config = CONFIG.SW5E.powerPreparationModes[mode];
registerSection(mode, s, config, {
@ -301,7 +328,7 @@ export default class ActorSheet5e extends ActorSheet {
}
// Sections for higher-level powers which the caster "should not" have, but power items exist for
else if ( !powerbook[s] ) {
else if (!powerbook[s]) {
registerSection(sl, s, CONFIG.SW5E.powerLevels[s], {levels: levels[sl]});
}
@ -323,33 +350,33 @@ export default class ActorSheet5e extends ActorSheet {
* @private
*/
_filterItems(items, filters) {
return items.filter(item => {
return items.filter((item) => {
const data = item.data;
// Action usage
for ( let f of ["action", "bonus", "reaction"] ) {
if ( filters.has(f) ) {
if ((data.activation && (data.activation.type !== f))) return false;
for (let f of ["action", "bonus", "reaction"]) {
if (filters.has(f)) {
if (data.activation && data.activation.type !== f) return false;
}
}
// Power-specific filters
if ( filters.has("ritual") ) {
if (filters.has("ritual")) {
if (data.components.ritual !== true) return false;
}
if ( filters.has("concentration") ) {
if (filters.has("concentration")) {
if (data.components.concentration !== true) return false;
}
if ( filters.has("prepared") ) {
if ( data.level === 0 || ["innate", "always"].includes(data.preparation.mode) ) return true;
if ( this.actor.data.type === "npc" ) return true;
if ( this.actor.data.type === "starship" ) return true;
if (filters.has("prepared")) {
if (data.level === 0 || ["innate", "always"].includes(data.preparation.mode)) return true;
if (this.actor.data.type === "npc") return true;
if (this.actor.data.type === "starship") return true;
return data.preparation.prepared;
}
// Equipment-specific filters
if ( filters.has("equipped") ) {
if ( data.equipped !== true ) return false;
if (filters.has("equipped")) {
if (data.equipped !== true) return false;
}
return true;
});
@ -375,67 +402,64 @@ export default class ActorSheet5e extends ActorSheet {
/* Event Listeners and Handlers
/* -------------------------------------------- */
/**
* Activate event listeners using the prepared sheet HTML
* @param html {HTML} The prepared HTML object ready to be rendered into the DOM
*/
/** @inheritdoc */
activateListeners(html) {
// Activate Item Filters
const filterLists = html.find(".filter-list");
filterLists.each(this._initializeFilterItemList.bind(this));
filterLists.on("click", ".filter-item", this._onToggleFilter.bind(this));
// Item summaries
html.find('.item .item-name.rollable h4').click(event => this._onItemSummary(event));
html.find(".item .item-name.rollable h4").click((event) => this._onItemSummary(event));
// View Item Sheets
html.find(".item-edit").click(this._onItemEdit.bind(this));
// Editable Only Listeners
if ( this.isEditable ) {
if (this.isEditable) {
// Input focus and update
const inputs = html.find("input");
inputs.focus(ev => ev.currentTarget.select());
inputs.focus((ev) => ev.currentTarget.select());
inputs.addBack().find('[data-dtype="Number"]').change(this._onChangeInputDelta.bind(this));
// Ability Proficiency
html.find('.ability-proficiency').click(this._onToggleAbilityProficiency.bind(this));
html.find(".ability-proficiency").click(this._onToggleAbilityProficiency.bind(this));
// Toggle Skill Proficiency
html.find('.skill-proficiency').on("click contextmenu", this._onCycleSkillProficiency.bind(this));
html.find(".skill-proficiency").on("click contextmenu", this._onCycleSkillProficiency.bind(this));
// Trait Selector
html.find('.trait-selector').click(this._onTraitSelector.bind(this));
html.find(".trait-selector").click(this._onTraitSelector.bind(this));
// Configure Special Flags
html.find('.config-button').click(this._onConfigMenu.bind(this));
html.find(".config-button").click(this._onConfigMenu.bind(this));
// Owned Item management
html.find('.item-create').click(this._onItemCreate.bind(this));
html.find('.item-edit').click(this._onItemEdit.bind(this));
html.find('.item-delete').click(this._onItemDelete.bind(this));
html.find('.item-collapse').click(this._onItemCollapse.bind(this));
html.find('.item-uses input').click(ev => ev.target.select()).change(this._onUsesChange.bind(this));
html.find('.slot-max-override').click(this._onPowerSlotOverride.bind(this));
html.find('.increment-class-level').click(this._onIncrementClassLevel.bind(this));
html.find('.decrement-class-level').click(this._onDecrementClassLevel.bind(this));
html.find(".item-create").click(this._onItemCreate.bind(this));
html.find(".item-delete").click(this._onItemDelete.bind(this));
html.find(".item-collapse").click(this._onItemCollapse.bind(this));
html.find(".item-uses input")
.click((ev) => ev.target.select())
.change(this._onUsesChange.bind(this));
html.find(".slot-max-override").click(this._onPowerSlotOverride.bind(this));
html.find(".increment-class-level").click(this._onIncrementClassLevel.bind(this));
html.find(".decrement-class-level").click(this._onDecrementClassLevel.bind(this));
// Active Effect management
html.find(".effect-control").click(ev => onManageActiveEffect(ev, this.entity));
html.find(".effect-control").click((ev) => onManageActiveEffect(ev, this.actor));
}
// Owner Only Listeners
if ( this.actor.owner ) {
if (this.actor.isOwner) {
// Ability Checks
html.find('.ability-name').click(this._onRollAbilityTest.bind(this));
html.find(".ability-name").click(this._onRollAbilityTest.bind(this));
// Roll Skill Checks
html.find('.skill-name').click(this._onRollSkillCheck.bind(this));
html.find(".skill-name").click(this._onRollSkillCheck.bind(this));
// Item Rolling
html.find('.item .item-image').click(event => this._onItemRoll(event));
html.find('.item .item-recharge').click(event => this._onItemRecharge(event));
html.find(".item .item-image").click((event) => this._onItemRoll(event));
html.find(".item .item-recharge").click((event) => this._onItemRecharge(event));
}
// Otherwise remove rollable classes
@ -456,8 +480,8 @@ export default class ActorSheet5e extends ActorSheet {
_initializeFilterItemList(i, ul) {
const set = this._filters[ul.dataset.filter];
const filters = ul.querySelectorAll(".filter-item");
for ( let li of filters ) {
if ( set.has(li.dataset.filter) ) li.classList.add("active");
for (let li of filters) {
if (set.has(li.dataset.filter)) li.classList.add("active");
}
}
@ -473,10 +497,10 @@ export default class ActorSheet5e extends ActorSheet {
_onChangeInputDelta(event) {
const input = event.target;
const value = input.value;
if ( ["+", "-"].includes(value[0]) ) {
if (["+", "-"].includes(value[0])) {
let delta = parseFloat(value);
input.value = getProperty(this.actor.data, input.name) + delta;
} else if ( value[0] === "=" ) {
} else if (value[0] === "=") {
input.value = value.slice(1);
}
}
@ -491,17 +515,25 @@ export default class ActorSheet5e extends ActorSheet {
_onConfigMenu(event) {
event.preventDefault();
const button = event.currentTarget;
switch ( button.dataset.action ) {
let app;
switch (button.dataset.action) {
case "hit-dice":
app = new ActorHitDiceConfig(this.object);
break;
case "movement":
new ActorMovementConfig(this.object).render(true);
app = new ActorMovementConfig(this.object);
break;
case "flags":
new ActorSheetFlags(this.object).render(true);
app = new ActorSheetFlags(this.object);
break;
case "senses":
new ActorSensesConfig(this.object).render(true);
app = new ActorSensesConfig(this.object);
break;
case "type":
new ActorTypeConfig(this.object).render(true);
break;
}
app?.render(true);
}
/* -------------------------------------------- */
@ -521,10 +553,10 @@ export default class ActorSheet5e extends ActorSheet {
let idx = levels.indexOf(level);
// Toggle next level - forward on click, backwards on right
if ( event.type === "click" ) {
field.val(levels[(idx === levels.length - 1) ? 0 : idx + 1]);
} else if ( event.type === "contextmenu" ) {
field.val(levels[(idx === 0) ? levels.length - 1 : idx - 1]);
if (event.type === "click") {
field.val(levels[idx === levels.length - 1 ? 0 : idx + 1]);
} else if (event.type === "contextmenu") {
field.val(levels[idx === 0 ? levels.length - 1 : idx - 1]);
}
// Update the field value and save the form
@ -535,49 +567,51 @@ export default class ActorSheet5e extends ActorSheet {
/** @override */
async _onDropActor(event, data) {
const canPolymorph = game.user.isGM || (this.actor.owner && game.settings.get('sw5e', 'allowPolymorphing'));
if ( !canPolymorph ) return false;
const canPolymorph = game.user.isGM || (this.actor.isOwner && game.settings.get("sw5e", "allowPolymorphing"));
if (!canPolymorph) return false;
// Get the target actor
let sourceActor = null;
if (data.pack) {
const pack = game.packs.find(p => p.collection === data.pack);
const pack = game.packs.find((p) => p.collection === data.pack);
sourceActor = await pack.getEntity(data.id);
} else {
sourceActor = game.actors.get(data.id);
}
if ( !sourceActor ) return;
if (!sourceActor) return;
// Define a function to record polymorph settings for future use
const rememberOptions = html => {
const rememberOptions = (html) => {
const options = {};
html.find('input').each((i, el) => {
html.find("input").each((i, el) => {
options[el.name] = el.checked;
});
const settings = mergeObject(game.settings.get('sw5e', 'polymorphSettings') || {}, options);
game.settings.set('sw5e', 'polymorphSettings', settings);
const settings = mergeObject(game.settings.get("sw5e", "polymorphSettings") || {}, options);
game.settings.set("sw5e", "polymorphSettings", settings);
return settings;
};
// Create and render the Dialog
return new Dialog({
title: game.i18n.localize('SW5E.PolymorphPromptTitle'),
return new Dialog(
{
title: game.i18n.localize("SW5E.PolymorphPromptTitle"),
content: {
options: game.settings.get('sw5e', 'polymorphSettings'),
options: game.settings.get("sw5e", "polymorphSettings"),
i18n: SW5E.polymorphSettings,
isToken: this.actor.isToken
},
default: 'accept',
default: "accept",
buttons: {
accept: {
icon: '<i class="fas fa-check"></i>',
label: game.i18n.localize('SW5E.PolymorphAcceptSettings'),
callback: html => this.actor.transformInto(sourceActor, rememberOptions(html))
label: game.i18n.localize("SW5E.PolymorphAcceptSettings"),
callback: (html) => this.actor.transformInto(sourceActor, rememberOptions(html))
},
wildshape: {
icon: '<i class="fas fa-paw"></i>',
label: game.i18n.localize('SW5E.PolymorphWildShape'),
callback: html => this.actor.transformInto(sourceActor, {
label: game.i18n.localize("SW5E.PolymorphWildShape"),
callback: (html) =>
this.actor.transformInto(sourceActor, {
keepBio: true,
keepClass: true,
keepMental: true,
@ -588,37 +622,66 @@ export default class ActorSheet5e extends ActorSheet {
},
polymorph: {
icon: '<i class="fas fa-pastafarianism"></i>',
label: game.i18n.localize('SW5E.Polymorph'),
callback: html => this.actor.transformInto(sourceActor, {
label: game.i18n.localize("SW5E.Polymorph"),
callback: (html) =>
this.actor.transformInto(sourceActor, {
transformTokens: rememberOptions(html).transformTokens
})
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: game.i18n.localize('Cancel')
label: game.i18n.localize("Cancel")
}
}
}, {
classes: ['dialog', 'sw5e'],
},
{
classes: ["dialog", "sw5e"],
width: 600,
template: 'systems/sw5e/templates/apps/polymorph-prompt.html'
}).render(true);
template: "systems/sw5e/templates/apps/polymorph-prompt.html"
}
).render(true);
}
/* -------------------------------------------- */
/** @override */
async _onDropItemCreate(itemData) {
// Check to make sure items of this type are allowed on this actor
if (this.constructor.unsupportedItemTypes.has(itemData.type)) {
return ui.notifications.warn(
game.i18n.format("SW5E.ActorWarningInvalidItem", {
itemType: game.i18n.localize(CONFIG.Item.typeLabels[itemData.type]),
actorType: game.i18n.localize(CONFIG.Actor.typeLabels[this.actor.type])
})
);
}
// Create a Consumable power scroll on the Inventory tab
if ( (itemData.type === "power") && (this._tabs[0].active === "inventory") ) {
if (itemData.type === "power" && this._tabs[0].active === "inventory") {
const scroll = await Item5e.createScrollFromPower(itemData);
itemData = scroll.data;
}
if (itemData.data) {
// Ignore certain statuses
if ( itemData.data ) {
["attunement", "equipped", "proficient", "prepared"].forEach(k => delete itemData.data[k]);
["equipped", "proficient", "prepared"].forEach((k) => delete itemData.data[k]);
// Downgrade ATTUNED to REQUIRED
itemData.data.attunement = Math.min(itemData.data.attunement, CONFIG.SW5E.attunementTypes.REQUIRED);
}
// Stack identical consumables
if (itemData.type === "consumable" && itemData.flags.core?.sourceId) {
const similarItem = this.actor.items.find((i) => {
const sourceId = i.getFlag("core", "sourceId");
return sourceId && sourceId === itemData.flags.core?.sourceId && i.type === "consumable";
});
if (similarItem && itemData.name !== "Power Cell") {
// Always create a new powercell instead of increasing quantity
return similarItem.update({
"data.quantity": similarItem.data.data.quantity + Math.max(itemData.data.quantity, 1)
});
}
}
// Create the owned item as normal
@ -632,7 +695,7 @@ export default class ActorSheet5e extends ActorSheet {
* @param {MouseEvent} event The originating click event
* @private
*/
async _onPowerSlotOverride (event) {
async _onPowerSlotOverride(event) {
const span = event.currentTarget.parentElement;
const level = span.dataset.level;
const override = this.actor.data.data.powers[level].override || span.dataset.slots;
@ -659,10 +722,10 @@ export default class ActorSheet5e extends ActorSheet {
async _onUsesChange(event) {
event.preventDefault();
const itemId = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.getOwnedItem(itemId);
const item = this.actor.items.get(itemId);
const uses = Math.clamped(0, parseInt(event.target.value), item.data.data.uses.max);
event.target.value = uses;
return item.update({ 'data.uses.value': uses });
return item.update({"data.uses.value": uses});
}
/* -------------------------------------------- */
@ -674,7 +737,7 @@ export default class ActorSheet5e extends ActorSheet {
_onItemRoll(event) {
event.preventDefault();
const itemId = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.getOwnedItem(itemId);
const item = this.actor.items.get(itemId);
return item.roll();
}
@ -688,9 +751,9 @@ export default class ActorSheet5e extends ActorSheet {
_onItemRecharge(event) {
event.preventDefault();
const itemId = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.getOwnedItem(itemId);
const item = this.actor.items.get(itemId);
return item.rollRecharge();
};
}
/* -------------------------------------------- */
@ -701,17 +764,17 @@ export default class ActorSheet5e extends ActorSheet {
_onItemSummary(event) {
event.preventDefault();
let li = $(event.currentTarget).parents(".item"),
item = this.actor.getOwnedItem(li.data("item-id")),
chatData = item.getChatData({secrets: this.actor.owner});
item = this.actor.items.get(li.data("item-id")),
chatData = item.getChatData({secrets: this.actor.isOwner});
// Toggle summary
if ( li.hasClass("expanded") ) {
if (li.hasClass("expanded")) {
let summary = li.children(".item-summary");
summary.slideUp(200, () => summary.remove());
} else {
let div = $(`<div class="item-summary">${chatData.description.value}</div>`);
let props = $(`<div class="item-properties"></div>`);
chatData.properties.forEach(p => props.append(`<span class="tag">${p}</span>`));
chatData.properties.forEach((p) => props.append(`<span class="tag">${p}</span>`));
div.append(props);
li.append(div.hide());
div.slideDown(200);
@ -731,12 +794,12 @@ export default class ActorSheet5e extends ActorSheet {
const header = event.currentTarget;
const type = header.dataset.type;
const itemData = {
name: game.i18n.format("SW5E.ItemNew", {type: type.capitalize()}),
name: game.i18n.format("SW5E.ItemNew", {type: game.i18n.localize(`SW5E.ItemType${type.capitalize()}`)}),
type: type,
data: duplicate(header.dataset)
data: foundry.utils.deepClone(header.dataset)
};
delete itemData.data["type"];
return this.actor.createEmbeddedEntity("OwnedItem", itemData);
return this.actor.createEmbeddedDocuments("Item", [itemData]);
}
/* -------------------------------------------- */
@ -749,8 +812,8 @@ export default class ActorSheet5e extends ActorSheet {
_onItemEdit(event) {
event.preventDefault();
const li = event.currentTarget.closest(".item");
const item = this.actor.getOwnedItem(li.dataset.itemId);
item.sheet.render(true);
const item = this.actor.items.get(li.dataset.itemId);
return item.sheet.render(true);
}
/* -------------------------------------------- */
@ -763,7 +826,8 @@ export default class ActorSheet5e extends ActorSheet {
_onItemDelete(event) {
event.preventDefault();
const li = event.currentTarget.closest(".item");
this.actor.deleteOwnedItem(li.dataset.itemId);
const item = this.actor.items.get(li.dataset.itemId);
if (item) return item.delete();
}
/**
@ -772,7 +836,7 @@ export default class ActorSheet5e extends ActorSheet {
* @private
*/
_onItemCollapse(event) {
_onItemCollapse(event) {
event.preventDefault();
event.currentTarget.classList.toggle("active");
@ -787,7 +851,7 @@ _onItemCollapse(event) {
}
}
/**
/**
* Handle incrementing class level on the actor sheet
* @param {Event} event The originating click event
* @private
@ -796,22 +860,22 @@ _onItemCollapse(event) {
_onIncrementClassLevel(event) {
event.preventDefault();
const div = event.currentTarget.closest(".character")
const div = event.currentTarget.closest(".character");
const li = event.currentTarget.closest("li");
const actorId = div.id.split("-")[1];
const itemId = li.dataset.itemId;
const actor = game.actors.get(actorId);
const item = actor.getOwnedItem(itemId);
const item = actor.items.get(itemId);
let levels = item.data.data.levels;
const update = {_id: item._id, data: {levels: (levels + 1) }};
const update = {_id: item.data._id, data: {levels: levels + 1}};
actor.updateOwnedItem(update)
}
actor.updateEmbeddedDocuments("Item", [update]);
}
/**
/**
* Handle decrementing class level on the actor sheet
* @param {Event} event The originating click event
* @private
@ -820,20 +884,20 @@ _onItemCollapse(event) {
_onDecrementClassLevel(event) {
event.preventDefault();
const div = event.currentTarget.closest(".character")
const div = event.currentTarget.closest(".character");
const li = event.currentTarget.closest("li");
const actorId = div.id.split("-")[1];
const itemId = li.dataset.itemId;
const actor = game.actors.get(actorId);
const item = actor.getOwnedItem(itemId);
const item = actor.items.get(itemId);
let levels = item.data.data.levels;
const update = {_id: item._id, data: {levels: (levels - 1) }};
const update = {_id: item.data._id, data: {levels: levels - 1}};
actor.updateOwnedItem(update)
}
actor.updateEmbeddedDocuments("Item", [update]);
}
/* -------------------------------------------- */
@ -845,7 +909,7 @@ _onItemCollapse(event) {
_onRollAbilityTest(event) {
event.preventDefault();
let ability = event.currentTarget.parentElement.dataset.ability;
this.actor.rollAbility(ability, {event: event});
return this.actor.rollAbility(ability, {event: event});
}
/* -------------------------------------------- */
@ -858,7 +922,7 @@ _onItemCollapse(event) {
_onRollSkillCheck(event) {
event.preventDefault();
const skill = event.currentTarget.parentElement.dataset.skill;
this.actor.rollSkill(skill, {event: event});
return this.actor.rollSkill(skill, {event: event});
}
/* -------------------------------------------- */
@ -871,7 +935,7 @@ _onItemCollapse(event) {
_onToggleAbilityProficiency(event) {
event.preventDefault();
const field = event.currentTarget.previousElementSibling;
this.actor.update({[field.name]: 1 - parseInt(field.value)});
return this.actor.update({[field.name]: 1 - parseInt(field.value)});
}
/* -------------------------------------------- */
@ -886,9 +950,9 @@ _onItemCollapse(event) {
const li = event.currentTarget;
const set = this._filters[li.parentElement.dataset.filter];
const filter = li.dataset.filter;
if ( set.has(filter) ) set.delete(filter);
if (set.has(filter)) set.delete(filter);
else set.add(filter);
this.render();
return this.render();
}
/* -------------------------------------------- */
@ -903,8 +967,8 @@ _onItemCollapse(event) {
const a = event.currentTarget;
const label = a.parentElement.querySelector("label");
const choices = CONFIG.SW5E[a.dataset.options];
const options = { name: a.dataset.target, title: label.innerText, choices };
new TraitSelector(this.actor, options).render(true)
const options = {name: a.dataset.target, title: label.innerText, choices};
return new TraitSelector(this.actor, options).render(true);
}
/* -------------------------------------------- */
@ -912,15 +976,14 @@ _onItemCollapse(event) {
/** @override */
_getHeaderButtons() {
let buttons = super._getHeaderButtons();
// Add button to revert polymorph
if ( !this.actor.isPolymorphed || this.actor.isToken ) return buttons;
if (this.actor.isPolymorphed) {
buttons.unshift({
label: 'SW5E.PolymorphRestoreTransformation',
label: "SW5E.PolymorphRestoreTransformation",
class: "restore-transformation",
icon: "fas fa-backward",
onclick: ev => this.actor.revertOriginalForm()
onclick: () => this.actor.revertOriginalForm()
});
}
return buttons;
}
}

View file

@ -7,7 +7,6 @@ import Actor5e from "../../entity.js";
* @type {ActorSheet5e}
*/
export default class ActorSheet5eCharacterNew extends ActorSheet5e {
get template() {
if (!game.user.isGM && this.actor.limited) return "systems/sw5e/templates/actors/newActor/limited-sheet.html";
return "systems/sw5e/templates/actors/newActor/character-sheet.html";
@ -17,17 +16,18 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
* @return {Object}
*/
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["swalt", "sw5e", "sheet", "actor", "character"],
blockFavTab: true,
subTabs: null,
width: 800,
tabs: [{
tabs: [
{
navSelector: ".root-tabs",
contentSelector: ".sheet-body",
initial: "attributes"
}],
}
]
});
}
@ -48,7 +48,7 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
sheetData["resources"] = ["primary", "secondary", "tertiary"].reduce((arr, r) => {
const res = sheetData.data.resources[r] || {};
res.name = r;
res.placeholder = game.i18n.localize("SW5E.Resource"+r.titleCase());
res.placeholder = game.i18n.localize("SW5E.Resource" + r.titleCase());
if (res && res.value === 0) delete res.value;
if (res && res.max === 0) delete res.max;
return arr.concat([res]);
@ -56,10 +56,12 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
// Experience Tracking
sheetData["disableExperience"] = game.settings.get("sw5e", "disableExperienceTracking");
sheetData["classLabels"] = this.actor.itemTypes.class.map(c => c.name).join(", ");
sheetData["multiclassLabels"] = this.actor.itemTypes.class.map(c => {
return [c.data.data.archetype, c.name, c.data.data.levels].filterJoin(' ')
}).join(', ');
sheetData["classLabels"] = this.actor.itemTypes.class.map((c) => c.name).join(", ");
sheetData["multiclassLabels"] = this.actor.itemTypes.class
.map((c) => {
return [c.data.data.archetype, c.name, c.data.data.levels].filterJoin(" ");
})
.join(", ");
// Return data for rendering
return sheetData;
@ -72,23 +74,38 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
* @private
*/
_prepareItems(data) {
// Categorize items as inventory, powerbook, features, and classes
const inventory = {
weapon: { label: "SW5E.ItemTypeWeaponPl", items: [], dataset: {type: "weapon"} },
equipment: { label: "SW5E.ItemTypeEquipmentPl", items: [], dataset: {type: "equipment"} },
consumable: { label: "SW5E.ItemTypeConsumablePl", items: [], dataset: {type: "consumable"} },
tool: { label: "SW5E.ItemTypeToolPl", items: [], dataset: {type: "tool"} },
backpack: { label: "SW5E.ItemTypeContainerPl", items: [], dataset: {type: "backpack"} },
loot: { label: "SW5E.ItemTypeLootPl", items: [], dataset: {type: "loot"} }
weapon: {label: "SW5E.ItemTypeWeaponPl", items: [], dataset: {type: "weapon"}},
equipment: {label: "SW5E.ItemTypeEquipmentPl", items: [], dataset: {type: "equipment"}},
consumable: {label: "SW5E.ItemTypeConsumablePl", items: [], dataset: {type: "consumable"}},
tool: {label: "SW5E.ItemTypeToolPl", items: [], dataset: {type: "tool"}},
backpack: {label: "SW5E.ItemTypeContainerPl", items: [], dataset: {type: "backpack"}},
loot: {label: "SW5E.ItemTypeLootPl", items: [], dataset: {type: "loot"}}
};
// Partition items by category
let [items, forcepowers, techpowers, feats, classes, deployments, deploymentfeatures, ventures, species, archetypes, classfeatures, backgrounds, fightingstyles, fightingmasteries, lightsaberforms] = data.items.reduce((arr, item) => {
let [
items,
forcepowers,
techpowers,
feats,
classes,
deployments,
deploymentfeatures,
ventures,
species,
archetypes,
classfeatures,
backgrounds,
fightingstyles,
fightingmasteries,
lightsaberforms
] = data.items.reduce(
(arr, item) => {
// Item details
item.img = item.img || DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
item.img = item.img || CONST.DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && item.data.quantity !== 1;
item.attunement = {
[CONFIG.SW5E.attunementTypes.REQUIRED]: {
icon: "fa-sun",
@ -103,32 +120,39 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
}[item.data.attunement];
// Item usage
item.hasUses = item.data.uses && (item.data.uses.max > 0);
item.isOnCooldown = item.data.recharge && !!item.data.recharge.value && (item.data.recharge.charged === false);
item.isDepleted = item.isOnCooldown && (item.data.uses.per && (item.data.uses.value > 0));
item.hasTarget = !!item.data.target && !(["none",""].includes(item.data.target.type));
item.hasUses = item.data.uses && item.data.uses.max > 0;
item.isOnCooldown =
item.data.recharge && !!item.data.recharge.value && item.data.recharge.charged === false;
item.isDepleted = item.isOnCooldown && item.data.uses.per && item.data.uses.value > 0;
item.hasTarget = !!item.data.target && !["none", ""].includes(item.data.target.type);
// Item toggle state
this._prepareItemToggleState(item);
// Primary Class
if (item.type === "class")
item.isOriginalClass = item._id === this.actor.data.data.details.originalClass;
// Classify items into types
if ( item.type === "power" && ["lgt", "drk", "uni"].includes(item.data.school) ) arr[1].push(item);
else if ( item.type === "power" && ["tec"].includes(item.data.school) ) arr[2].push(item);
else if ( item.type === "feat" ) arr[3].push(item);
else if ( item.type === "class" ) arr[4].push(item);
else if ( item.type === "deployment" ) arr[5].push(item);
else if ( item.type === "deploymentfeature" ) arr[6].push(item);
else if ( item.type === "venture" ) arr[7].push(item);
else if ( item.type === "species" ) arr[8].push(item);
else if ( item.type === "archetype" ) arr[9].push(item);
else if ( item.type === "classfeature" ) arr[10].push(item);
else if ( item.type === "background" ) arr[11].push(item);
else if ( item.type === "fightingstyle" ) arr[12].push(item);
else if ( item.type === "fightingmastery" ) arr[13].push(item);
else if ( item.type === "lightsaberform" ) arr[14].push(item);
else if ( Object.keys(inventory).includes(item.type ) ) arr[0].push(item);
if (item.type === "power" && ["lgt", "drk", "uni"].includes(item.data.school)) arr[1].push(item);
else if (item.type === "power" && ["tec"].includes(item.data.school)) arr[2].push(item);
else if (item.type === "feat") arr[3].push(item);
else if (item.type === "class") arr[4].push(item);
else if (item.type === "deployment") arr[5].push(item);
else if (item.type === "deploymentfeature") arr[6].push(item);
else if (item.type === "venture") arr[7].push(item);
else if (item.type === "species") arr[8].push(item);
else if (item.type === "archetype") arr[9].push(item);
else if (item.type === "classfeature") arr[10].push(item);
else if (item.type === "background") arr[11].push(item);
else if (item.type === "fightingstyle") arr[12].push(item);
else if (item.type === "fightingmastery") arr[13].push(item);
else if (item.type === "lightsaberform") arr[14].push(item);
else if (Object.keys(inventory).includes(item.type)) arr[0].push(item);
return arr;
}, [[], [], [], [], [], [], [], [], [], [], [], [], [], [], []]);
},
[[], [], [], [], [], [], [], [], [], [], [], [], [], [], []]
);
// Apply active item filters
items = this._filterItems(items, this._filters.inventory);
@ -137,10 +161,10 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
feats = this._filterItems(feats, this._filters.features);
// Organize items
for ( let i of items ) {
for (let i of items) {
i.data.quantity = i.data.quantity || 0;
i.data.weight = i.data.weight || 0;
i.totalWeight = Math.round(i.data.quantity * i.data.weight * 10) / 10;
i.totalWeight = (i.data.quantity * i.data.weight).toNearest(0.1);
inventory[i.type].items.push(i);
}
@ -150,25 +174,96 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
// Organize Features
const features = {
classes: { label: "SW5E.ItemTypeClassPl", items: [], hasActions: false, dataset: {type: "class"}, isClass: true },
classfeatures: { label: "SW5E.ItemTypeClassFeats", items: [], hasActions: true, dataset: {type: "classfeature"}, isClassfeature: true },
archetype: { label: "SW5E.ItemTypeArchetype", items: [], hasActions: false, dataset: {type: "archetype"}, isArchetype: true },
deployments: { label: "SW5E.ItemTypeDeploymentPl", items: [], hasActions: false, dataset: {type: "deployment"}, isDeployment: true },
deploymentfeatures: { label: "SW5E.ItemTypeDeploymentFeaturePl", items: [], hasActions: true, dataset: {type: "deploymentfeature"}, isDeploymentfeature: true },
ventures: { label: "SW5E.ItemTypeVenturePl", items: [], hasActions: false, dataset: {type: "venture"}, isVenture: true },
species: { label: "SW5E.ItemTypeSpecies", items: [], hasActions: false, dataset: {type: "species"}, isSpecies: true },
background: { label: "SW5E.ItemTypeBackground", items: [], hasActions: false, dataset: {type: "background"}, isBackground: true },
fightingstyles: { label: "SW5E.ItemTypeFightingStylePl", items: [], hasActions: false, dataset: {type: "fightingstyle"}, isFightingstyle: true },
fightingmasteries: { label: "SW5E.ItemTypeFightingMasteryPl", items: [], hasActions: false, dataset: {type: "fightingmastery"}, isFightingmastery: true },
lightsaberforms: { label: "SW5E.ItemTypeLightsaberFormPl", items: [], hasActions: false, dataset: {type: "lightsaberform"}, isLightsaberform: true },
active: { label: "SW5E.FeatureActive", items: [], hasActions: true, dataset: {type: "feat", "activation.type": "action"} },
passive: { label: "SW5E.FeaturePassive", items: [], hasActions: false, dataset: {type: "feat"} }
classes: {
label: "SW5E.ItemTypeClassPl",
items: [],
hasActions: false,
dataset: {type: "class"},
isClass: true
},
classfeatures: {
label: "SW5E.ItemTypeClassFeats",
items: [],
hasActions: true,
dataset: {type: "classfeature"},
isClassfeature: true
},
archetype: {
label: "SW5E.ItemTypeArchetype",
items: [],
hasActions: false,
dataset: {type: "archetype"},
isArchetype: true
},
deployments: {
label: "SW5E.ItemTypeDeploymentPl",
items: [],
hasActions: false,
dataset: {type: "deployment"},
isDeployment: true
},
deploymentfeatures: {
label: "SW5E.ItemTypeDeploymentFeaturePl",
items: [],
hasActions: true,
dataset: {type: "deploymentfeature"},
isDeploymentfeature: true
},
ventures: {
label: "SW5E.ItemTypeVenturePl",
items: [],
hasActions: false,
dataset: {type: "venture"},
isVenture: true
},
species: {
label: "SW5E.ItemTypeSpecies",
items: [],
hasActions: false,
dataset: {type: "species"},
isSpecies: true
},
background: {
label: "SW5E.ItemTypeBackground",
items: [],
hasActions: false,
dataset: {type: "background"},
isBackground: true
},
fightingstyles: {
label: "SW5E.ItemTypeFightingStylePl",
items: [],
hasActions: false,
dataset: {type: "fightingstyle"},
isFightingstyle: true
},
fightingmasteries: {
label: "SW5E.ItemTypeFightingMasteryPl",
items: [],
hasActions: false,
dataset: {type: "fightingmastery"},
isFightingmastery: true
},
lightsaberforms: {
label: "SW5E.ItemTypeLightsaberFormPl",
items: [],
hasActions: false,
dataset: {type: "lightsaberform"},
isLightsaberform: true
},
active: {
label: "SW5E.FeatureActive",
items: [],
hasActions: true,
dataset: {"type": "feat", "activation.type": "action"}
},
passive: {label: "SW5E.FeaturePassive", items: [], hasActions: false, dataset: {type: "feat"}}
};
for ( let f of feats ) {
if ( f.data.activation.type ) features.active.items.push(f);
for (let f of feats) {
if (f.data.activation.type) features.active.items.push(f);
else features.passive.items.push(f);
}
classes.sort((a, b) => b.levels - a.levels);
classes.sort((a, b) => b.data.levels - a.data.levels);
features.classes.items = classes;
features.classfeatures.items = classfeatures;
features.archetype.items = archetypes;
@ -200,12 +295,11 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
const isAlways = getProperty(item.data, "preparation.mode") === "always";
const isPrepared = getProperty(item.data, "preparation.prepared");
item.toggleClass = isPrepared ? "active" : "";
if ( isAlways ) item.toggleClass = "fixed";
if ( isAlways ) item.toggleTitle = CONFIG.SW5E.powerPreparationModes.always;
else if ( isPrepared ) item.toggleTitle = CONFIG.SW5E.powerPreparationModes.prepared;
if (isAlways) item.toggleClass = "fixed";
if (isAlways) item.toggleTitle = CONFIG.SW5E.powerPreparationModes.always;
else if (isPrepared) item.toggleTitle = CONFIG.SW5E.powerPreparationModes.prepared;
else item.toggleTitle = game.i18n.localize("SW5E.PowerUnprepared");
}
else {
} else {
const isActive = getProperty(item.data, "equipped");
item.toggleClass = isActive ? "active" : "";
item.toggleTitle = game.i18n.localize(isActive ? "SW5E.Equipped" : "SW5E.Unequipped");
@ -218,33 +312,35 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
/**
* Activate event listeners using the prepared sheet HTML
* @param html {HTML} The prepared HTML object ready to be rendered into the DOM
* @param html {jQuery} The prepared HTML object ready to be rendered into the DOM
*/
activateListeners(html) {
super.activateListeners(html);
if ( !this.options.editable ) return;
if (!this.isEditable) return;
// Inventory Functions
// html.find(".currency-convert").click(this._onConvertCurrency.bind(this));
// Item State Toggling
html.find('.item-toggle').click(this._onToggleItem.bind(this));
html.find(".item-toggle").click(this._onToggleItem.bind(this));
// Short and Long Rest
html.find('.short-rest').click(this._onShortRest.bind(this));
html.find('.long-rest').click(this._onLongRest.bind(this));
html.find(".short-rest").click(this._onShortRest.bind(this));
html.find(".long-rest").click(this._onLongRest.bind(this));
// Rollable sheet actions
html.find(".rollable[data-action]").click(this._onSheetAction.bind(this));
// Send Languages to Chat onClick
html.find('[data-options="share-languages"]').click(event => {
html.find('[data-options="share-languages"]').click((event) => {
event.preventDefault();
let langs = this.actor.data.data.traits.languages.value.map(l => SW5E.languages[l] || l).join(", ");
let langs = this.actor.data.data.traits.languages.value
.map((l) => CONFIG.SW5E.languages[l] || l)
.join(", ");
let custom = this.actor.data.data.traits.languages.custom;
if (custom) langs += ", " + custom.replace(/;/g, ",");
let content = `
<div class="sw5e chat-card item-card" data-acor-id="${this.actor._id}">
<div class="sw5e chat-card item-card" data-acor-id="${this.actor.data._id}">
<header class="card-header flexrow">
<img src="${this.actor.data.token.img}" title="" width="36" height="36" style="border: none;"/>
<h3>Known Languages</h3>
@ -254,46 +350,50 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
`;
// Send to Chat
let rollWhisper = null;
let rollBlind = false;
let rollMode = game.settings.get("core", "rollMode");
if (["gmroll", "blindroll"].includes(rollMode)) rollWhisper = ChatMessage.getWhisperIDs("GM");
if (rollMode === "blindroll") rollBlind = true;
ChatMessage.create({
user: game.user._id,
let data = {
user: game.user.data._id,
content: content,
blind: rollBlind,
speaker: {
actor: this.actor._id,
actor: this.actor.data._id,
token: this.actor.token,
alias: this.actor.name
},
type: CONST.CHAT_MESSAGE_TYPES.OTHER
});
};
if (["gmroll", "blindroll"].includes(rollMode)) data["whisper"] = ChatMessage.getWhisperRecipients("GM");
else if (rollMode === "selfroll") data["whisper"] = [game.users.get(game.user.data._id)];
ChatMessage.create(data);
});
// Item Delete Confirmation
html.find('.item-delete').off("click");
html.find('.item-delete').click(event => {
let li = $(event.currentTarget).parents('.item');
html.find(".item-delete").off("click");
html.find(".item-delete").click((event) => {
let li = $(event.currentTarget).parents(".item");
let itemId = li.attr("data-item-id");
let item = this.actor.getOwnedItem(itemId);
let item = this.actor.items.get(itemId);
new Dialog({
title: `Deleting ${item.data.name}`,
content: `<p>Are you sure you want to delete ${item.data.name}?</p>`,
buttons: {
Yes: {
icon: '<i class="fa fa-check"></i>',
label: 'Yes',
callback: dlg => {
label: "Yes",
callback: (dlg) => {
this.actor.deleteOwnedItem(itemId);
}
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: 'No'
label: "No"
}
},
},
default: 'cancel'
default: "cancel"
}).render(true);
});
}
@ -308,7 +408,7 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
_onSheetAction(event) {
event.preventDefault();
const button = event.currentTarget;
switch( button.dataset.action ) {
switch (button.dataset.action) {
case "rollDeathSave":
return this.actor.rollDeathSave({event: event});
case "rollInitiative":
@ -318,7 +418,6 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
/* -------------------------------------------- */
/**
* Handle toggling the state of an Owned Item within the Actor
* @param {Event} event The triggering click event
@ -327,7 +426,7 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
_onToggleItem(event) {
event.preventDefault();
const itemId = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.getOwnedItem(itemId);
const item = this.actor.items.get(itemId);
const attr = item.data.type === "power" ? "data.preparation.prepared" : "data.equipped";
return item.update({[attr]: !getProperty(item.data, attr)});
}
@ -362,14 +461,13 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
/** @override */
async _onDropItemCreate(itemData) {
// Increment the number of class levels of a character instead of creating a new item
if ( itemData.type === "class" ) {
const cls = this.actor.itemTypes.class.find(c => c.name === itemData.name);
if (itemData.type === "class") {
const cls = this.actor.itemTypes.class.find((c) => c.name === itemData.name);
let priorLevel = cls?.data.data.levels ?? 0;
if ( !!cls ) {
if (!!cls) {
const next = Math.min(priorLevel + 1, 20 + priorLevel - this.actor.data.data.details.level);
if ( next > priorLevel ) {
if (next > priorLevel) {
itemData.levels = next;
return cls.update({"data.levels": next});
}
@ -390,7 +488,7 @@ export default class ActorSheet5eCharacterNew extends ActorSheet5e {
// }
// Default drop handling if levels were not added
super._onDropItemCreate(itemData);
return super._onDropItemCreate(itemData);
}
}
async function addFavorites(app, html, data) {
@ -450,9 +548,9 @@ async function addFavorites(app, html, data) {
value: data.actor.data.powers.power9.value,
max: data.actor.data.powers.power9.max
}
}
};
let powerCount = 0
let powerCount = 0;
let items = data.actor.items;
for (let item of items) {
if (item.type == "class") continue;
@ -463,24 +561,28 @@ async function addFavorites(app, html, data) {
}
let isFav = item.flags.favtab.isFavourite;
if (app.options.editable) {
let favBtn = $(`<a class="item-control item-toggle item-fav ${isFav ? "active" : ""}" data-fav="${isFav}" title="${isFav ? "Remove from Favourites" : "Add to Favourites"}"><i class="fas fa-star"></i></a>`);
favBtn.click(ev => {
app.actor.getOwnedItem(item._id).update({
let favBtn = $(
`<a class="item-control item-toggle item-fav ${isFav ? "active" : ""}" data-fav="${isFav}" title="${
isFav ? "Remove from Favourites" : "Add to Favourites"
}"><i class="fas fa-star"></i></a>`
);
favBtn.click((ev) => {
app.actor.items.get(item.data._id).update({
"flags.favtab.isFavourite": !item.flags.favtab.isFavourite
});
});
html.find(`.item[data-item-id="${item._id}"]`).find('.item-controls').prepend(favBtn);
html.find(`.item[data-item-id="${item.data._id}"]`).find(".item-controls").prepend(favBtn);
}
if (isFav) {
item.powerComps = "";
if (item.data.components) {
let comps = item.data.components;
let v = (comps.vocal) ? "V" : "";
let s = (comps.somatic) ? "S" : "";
let m = (comps.material) ? "M" : "";
let c = (comps.concentration) ? true : false;
let r = (comps.ritual) ? true : false;
let v = comps.vocal ? "V" : "";
let s = comps.somatic ? "S" : "";
let m = comps.material ? "M" : "";
let c = !!comps.concentration;
let r = !!comps.ritual;
item.powerComps = `${v}${s}${m}`;
item.powerCon = c;
item.powerRit = r;
@ -488,15 +590,15 @@ async function addFavorites(app, html, data) {
item.editable = app.options.editable;
switch (item.type) {
case 'feat':
case "feat":
if (item.flags.favtab.sort === undefined) {
item.flags.favtab.sort = (favFeats.count + 1) * 100000; // initial sort key if not present
}
favFeats.push(item);
break;
case 'power':
case "power":
if (item.data.preparation.mode) {
item.powerPrepMode = ` (${CONFIG.SW5E.powerPreparationModes[item.data.preparation.mode]})`
item.powerPrepMode = ` (${CONFIG.SW5E.powerPreparationModes[item.data.preparation.mode]})`;
}
if (item.data.level) {
favPowers[item.data.level].powers.push(item);
@ -522,62 +624,62 @@ async function addFavorites(app, html, data) {
// html.find('.favourite .item-controls').css('flex', '0 0 22px');
// }
let tabContainer = html.find('.favtabtarget');
data.favItems = favItems.length > 0 ? favItems.sort((a, b) => (a.flags.favtab.sort) - (b.flags.favtab.sort)) : false;
data.favFeats = favFeats.length > 0 ? favFeats.sort((a, b) => (a.flags.favtab.sort) - (b.flags.favtab.sort)) : false;
let tabContainer = html.find(".favtabtarget");
data.favItems = favItems.length > 0 ? favItems.sort((a, b) => a.flags.favtab.sort - b.flags.favtab.sort) : false;
data.favFeats = favFeats.length > 0 ? favFeats.sort((a, b) => a.flags.favtab.sort - b.flags.favtab.sort) : false;
data.favPowers = powerCount > 0 ? favPowers : false;
data.editable = app.options.editable;
await loadTemplates(['systems/sw5e/templates/actors/newActor/item.hbs']);
let favtabHtml = $(await renderTemplate('systems/sw5e/templates/actors/newActor/template.hbs', data));
favtabHtml.find('.item-name h4').click(event => app._onItemSummary(event));
await loadTemplates(["systems/sw5e/templates/actors/newActor/item.hbs"]);
let favtabHtml = $(await renderTemplate("systems/sw5e/templates/actors/newActor/template.hbs", data));
favtabHtml.find(".item-name h4").click((event) => app._onItemSummary(event));
if (app.options.editable) {
favtabHtml.find('.item-image').click(ev => app._onItemRoll(ev));
let handler = ev => app._onDragStart(ev);
favtabHtml.find('.item').each((i, li) => {
favtabHtml.find(".item-image").click((ev) => app._onItemRoll(ev));
let handler = (ev) => app._onDragStart(ev);
favtabHtml.find(".item").each((i, li) => {
if (li.classList.contains("inventory-header")) return;
li.setAttribute("draggable", true);
li.addEventListener("dragstart", handler, false);
});
//favtabHtml.find('.item-toggle').click(event => app._onToggleItem(event));
favtabHtml.find('.item-edit').click(ev => {
let itemId = $(ev.target).parents('.item')[0].dataset.itemId;
app.actor.getOwnedItem(itemId).sheet.render(true);
favtabHtml.find(".item-edit").click((ev) => {
let itemId = $(ev.target).parents(".item")[0].dataset.itemId;
app.actor.items.get(itemId).sheet.render(true);
});
favtabHtml.find('.item-fav').click(ev => {
let itemId = $(ev.target).parents('.item')[0].dataset.itemId;
let val = !app.actor.getOwnedItem(itemId).data.flags.favtab.isFavourite
app.actor.getOwnedItem(itemId).update({
favtabHtml.find(".item-fav").click((ev) => {
let itemId = $(ev.target).parents(".item")[0].dataset.itemId;
let val = !app.actor.items.get(itemId).data.flags.favtab.isFavourite;
app.actor.items.get(itemId).update({
"flags.favtab.isFavourite": val
});
});
// Sorting
favtabHtml.find('.item').on('drop', ev => {
favtabHtml.find(".item").on("drop", (ev) => {
ev.preventDefault();
ev.stopPropagation();
let dropData = JSON.parse(ev.originalEvent.dataTransfer.getData('text/plain'));
let dropData = JSON.parse(ev.originalEvent.dataTransfer.getData("text/plain"));
// if (dropData.actorId !== app.actor.id || dropData.data.type === 'power') return;
if (dropData.actorId !== app.actor.id) return;
let list = null;
if (dropData.data.type === 'feat') list = favFeats;
if (dropData.data.type === "feat") list = favFeats;
else list = favItems;
let dragSource = list.find(i => i._id === dropData.data._id);
let siblings = list.filter(i => i._id !== dropData.data._id);
let targetId = ev.target.closest('.item').dataset.itemId;
let dragTarget = siblings.find(s => s._id === targetId);
let dragSource = list.find((i) => i.data._id === dropData.data._id);
let siblings = list.filter((i) => i.data._id !== dropData.data._id);
let targetId = ev.target.closest(".item").dataset.itemId;
let dragTarget = siblings.find((s) => s.data._id === targetId);
if (dragTarget === undefined) return;
const sortUpdates = SortingHelpers.performIntegerSort(dragSource, {
target: dragTarget,
siblings: siblings,
sortKey: 'flags.favtab.sort'
sortKey: "flags.favtab.sort"
});
const updateData = sortUpdates.map(u => {
const updateData = sortUpdates.map((u) => {
const update = u.update;
update._id = u.target._id;
update._id = u.target.data._id;
return update;
});
app.actor.updateEmbeddedEntity("OwnedItem", updateData);
@ -601,53 +703,47 @@ async function addFavorites(app, html, data) {
Hooks.callAll("renderedSwaltSheet", app, html, data);
}
async function addSubTabs(app, html, data) {
if(data.options.subTabs == null) {
if (data.options.subTabs == null) {
//let subTabs = []; //{subgroup: '', target: '', active: false}
data.options.subTabs = {};
html.find('[data-subgroup-selection] [data-subgroup]').each((idx, el) => {
let subgroup = el.getAttribute('data-subgroup');
let target = el.getAttribute('data-target');
let targetObj = {target: target, active: el.classList.contains("active")}
if(data.options.subTabs.hasOwnProperty(subgroup)) {
html.find("[data-subgroup-selection] [data-subgroup]").each((idx, el) => {
let subgroup = el.getAttribute("data-subgroup");
let target = el.getAttribute("data-target");
let targetObj = {target: target, active: el.classList.contains("active")};
if (data.options.subTabs.hasOwnProperty(subgroup)) {
data.options.subTabs[subgroup].push(targetObj);
} else {
data.options.subTabs[subgroup] = [];
data.options.subTabs[subgroup].push(targetObj);
}
})
}
for(const group in data.options.subTabs) {
data.options.subTabs[group].forEach(tab => {
if(tab.active) {
html.find(`[data-subgroup=${group}][data-target=${tab.target}]`).addClass('active');
} else {
html.find(`[data-subgroup=${group}][data-target=${tab.target}]`).removeClass('active');
}
})
}
html.find('[data-subgroup-selection]').children().on('click', event => {
let subgroup = event.target.closest('[data-subgroup]').getAttribute('data-subgroup');
let target = event.target.closest('[data-target]').getAttribute('data-target');
html.find(`[data-subgroup=${subgroup}]`).removeClass('active');
html.find(`[data-subgroup=${subgroup}][data-target=${target}]`).addClass('active');
let tabId = data.options.subTabs[subgroup].find(tab => {
return tab.target == target
});
data.options.subTabs[subgroup].map(el => {
if(el.target == target) {
el.active = true;
} else {
el.active = false;
}
for (const group in data.options.subTabs) {
data.options.subTabs[group].forEach((tab) => {
if (tab.active) {
html.find(`[data-subgroup=${group}][data-target=${tab.target}]`).addClass("active");
} else {
html.find(`[data-subgroup=${group}][data-target=${tab.target}]`).removeClass("active");
}
});
}
html.find("[data-subgroup-selection]")
.children()
.on("click", (event) => {
let subgroup = event.target.closest("[data-subgroup]").getAttribute("data-subgroup");
let target = event.target.closest("[data-target]").getAttribute("data-target");
html.find(`[data-subgroup=${subgroup}]`).removeClass("active");
html.find(`[data-subgroup=${subgroup}][data-target=${target}]`).addClass("active");
let tabId = data.options.subTabs[subgroup].find((tab) => {
return tab.target == target;
});
data.options.subTabs[subgroup].map((el) => {
el.active = el.target == target;
return el;
})
})
});
});
}
Hooks.on("renderActorSheet5eCharacterNew", (app, html, data) => {

View file

@ -6,10 +6,9 @@ import ActorSheet5e from "./base.js";
* @extends {ActorSheet5e}
*/
export default class ActorSheet5eNPCNew extends ActorSheet5e {
/** @override */
get template() {
if ( !game.user.isGM && this.actor.limited ) return "systems/sw5e/templates/actors/newActor/limited-sheet.html";
if (!game.user.isGM && this.actor.limited) return "systems/sw5e/templates/actors/newActor/limited-sheet.html";
return `systems/sw5e/templates/actors/newActor/npc-sheet.html`;
}
/** @override */
@ -17,43 +16,63 @@ export default class ActorSheet5eNPCNew extends ActorSheet5e {
return mergeObject(super.defaultOptions, {
classes: ["sw5e", "sheet", "actor", "npc"],
width: 800,
tabs: [{
tabs: [
{
navSelector: ".root-tabs",
contentSelector: ".sheet-body",
initial: "attributes"
}],
}
]
});
}
/* -------------------------------------------- */
/** @override */
static unsupportedItemTypes = new Set(["class"]);
/* -------------------------------------------- */
/**
* Organize Owned Items for rendering the NPC sheet
* @private
*/
_prepareItems(data) {
// Categorize Items as Features and Powers
const features = {
weapons: { label: game.i18n.localize("SW5E.AttackPl"), items: [] , hasActions: true, dataset: {type: "weapon", "weapon-type": "natural"} },
actions: { label: game.i18n.localize("SW5E.ActionPl"), items: [] , hasActions: true, dataset: {type: "feat", "activation.type": "action"} },
passive: { label: game.i18n.localize("SW5E.Features"), items: [], dataset: {type: "feat"} },
equipment: { label: game.i18n.localize("SW5E.Inventory"), items: [], dataset: {type: "loot"}}
weapons: {
label: game.i18n.localize("SW5E.AttackPl"),
items: [],
hasActions: true,
dataset: {"type": "weapon", "weapon-type": "natural"}
},
actions: {
label: game.i18n.localize("SW5E.ActionPl"),
items: [],
hasActions: true,
dataset: {"type": "feat", "activation.type": "action"}
},
passive: {label: game.i18n.localize("SW5E.Features"), items: [], dataset: {type: "feat"}},
equipment: {label: game.i18n.localize("SW5E.Inventory"), items: [], dataset: {type: "loot"}}
};
// Start by classifying items into groups for rendering
let [forcepowers, techpowers, other] = data.items.reduce((arr, item) => {
item.img = item.img || DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
item.hasUses = item.data.uses && (item.data.uses.max > 0);
item.isOnCooldown = item.data.recharge && !!item.data.recharge.value && (item.data.recharge.charged === false);
item.isDepleted = item.isOnCooldown && (item.data.uses.per && (item.data.uses.value > 0));
item.hasTarget = !!item.data.target && !(["none",""].includes(item.data.target.type));
if ( item.type === "power" && ["lgt", "drk", "uni"].includes(item.data.school) ) arr[0].push(item);
else if ( item.type === "power" && ["tec"].includes(item.data.school) ) arr[1].push(item);
let [forcepowers, techpowers, other] = data.items.reduce(
(arr, item) => {
item.img = item.img || CONST.DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && item.data.quantity !== 1;
item.hasUses = item.data.uses && item.data.uses.max > 0;
item.isOnCooldown =
item.data.recharge && !!item.data.recharge.value && item.data.recharge.charged === false;
item.isDepleted = item.isOnCooldown && item.data.uses.per && item.data.uses.value > 0;
item.hasTarget = !!item.data.target && !["none", ""].includes(item.data.target.type);
if (item.type === "power" && ["lgt", "drk", "uni"].includes(item.data.school)) arr[0].push(item);
else if (item.type === "power" && ["tec"].includes(item.data.school)) arr[1].push(item);
else arr[2].push(item);
return arr;
}, [[], [], []]);
},
[[], [], []]
);
// Apply item filters
forcepowers = this._filterItems(forcepowers, this._filters.forcePowerbook);
@ -65,13 +84,12 @@ export default class ActorSheet5eNPCNew extends ActorSheet5e {
const techPowerbook = this._preparePowerbook(data, techpowers, "tec");
// Organize Features
for ( let item of other ) {
if ( item.type === "weapon" ) features.weapons.items.push(item);
else if ( item.type === "feat" ) {
if ( item.data.activation.type ) features.actions.items.push(item);
for (let item of other) {
if (item.type === "weapon") features.weapons.items.push(item);
else if (item.type === "feat") {
if (item.data.activation.type) features.actions.items.push(item);
else features.passive.items.push(item);
}
else features.equipment.items.push(item);
} else features.equipment.items.push(item);
}
// Assign and return
@ -80,17 +98,19 @@ export default class ActorSheet5eNPCNew extends ActorSheet5e {
data.techPowerbook = techPowerbook;
}
/* -------------------------------------------- */
/** @override */
getData() {
const data = super.getData();
/** @inheritdoc */
getData(options) {
const data = super.getData(options);
// Challenge Rating
const cr = parseFloat(data.data.details.cr || 0);
const crLabels = {0: "0", 0.125: "1/8", 0.25: "1/4", 0.5: "1/2"};
data.labels["cr"] = cr >= 1 ? String(cr) : crLabels[cr] || 1;
// Creature Type
data.labels["type"] = this.actor.labels.creatureType;
return data;
}
@ -99,17 +119,16 @@ export default class ActorSheet5eNPCNew extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
_updateObject(event, formData) {
async _updateObject(event, formData) {
// Format NPC Challenge Rating
const crs = {"1/8": 0.125, "1/4": 0.25, "1/2": 0.5};
let crv = "data.details.cr";
let cr = formData[crv];
cr = crs[cr] || parseFloat(cr);
if ( cr ) formData[crv] = cr < 1 ? cr : parseInt(cr);
if (cr) formData[crv] = cr < 1 ? cr : parseInt(cr);
// Parent ActorSheet update steps
super._updateObject(event, formData);
return super._updateObject(event, formData);
}
/* -------------------------------------------- */
@ -132,10 +151,9 @@ export default class ActorSheet5eNPCNew extends ActorSheet5e {
_onRollHPFormula(event) {
event.preventDefault();
const formula = this.actor.data.data.attributes.hp.formula;
if ( !formula ) return;
if (!formula) return;
const hp = new Roll(formula).roll().total;
AudioHelper.play({src: CONFIG.sounds.dice});
this.actor.update({"data.attributes.hp.value": hp, "data.attributes.hp.max": hp});
}
}

View file

@ -6,10 +6,9 @@ import ActorSheet5e from "./base.js";
* @extends {ActorSheet5e}
*/
export default class ActorSheet5eStarship extends ActorSheet5e {
/** @override */
get template() {
if ( !game.user.isGM && this.actor.limited ) return "systems/sw5e/templates/actors/newActor/limited-sheet.html";
if (!game.user.isGM && this.actor.limited) return "systems/sw5e/templates/actors/newActor/limited-sheet.html";
return `systems/sw5e/templates/actors/newActor/starship.html`;
}
/** @override */
@ -17,11 +16,13 @@ export default class ActorSheet5eStarship extends ActorSheet5e {
return mergeObject(super.defaultOptions, {
classes: ["sw5e", "sheet", "actor", "starship"],
width: 800,
tabs: [{
tabs: [
{
navSelector: ".root-tabs",
contentSelector: ".sheet-body",
initial: "attributes"
}],
}
]
});
}
@ -32,29 +33,47 @@ export default class ActorSheet5eStarship extends ActorSheet5e {
* @private
*/
_prepareItems(data) {
// Categorize Items as Features and Powers
const features = {
weapons: { label: game.i18n.localize("SW5E.ItemTypeWeaponPl"), items: [], hasActions: true, dataset: {type: "weapon", "weapon-type": "natural"} },
passive: { label: game.i18n.localize("SW5E.Features"), items: [], dataset: {type: "feat"} },
equipment: { label: game.i18n.localize("SW5E.StarshipEquipment"), items: [], dataset: {type: "equipment"}},
starshipfeatures: { label: game.i18n.localize("SW5E.StarshipfeaturePl"), items: [], hasActions: true, dataset: {type: "starshipfeature"} },
starshipmods: { label: game.i18n.localize("SW5E.StarshipmodPl"), items: [], hasActions: false, dataset: {type: "starshipmod"} }
weapons: {
label: game.i18n.localize("SW5E.ItemTypeWeaponPl"),
items: [],
hasActions: true,
dataset: {"type": "weapon", "weapon-type": "natural"}
},
passive: {label: game.i18n.localize("SW5E.Features"), items: [], dataset: {type: "feat"}},
equipment: {label: game.i18n.localize("SW5E.StarshipEquipment"), items: [], dataset: {type: "equipment"}},
starshipfeatures: {
label: game.i18n.localize("SW5E.StarshipfeaturePl"),
items: [],
hasActions: true,
dataset: {type: "starshipfeature"}
},
starshipmods: {
label: game.i18n.localize("SW5E.StarshipmodPl"),
items: [],
hasActions: false,
dataset: {type: "starshipmod"}
}
};
// Start by classifying items into groups for rendering
let [forcepowers, techpowers, other] = data.items.reduce((arr, item) => {
item.img = item.img || DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
item.hasUses = item.data.uses && (item.data.uses.max > 0);
item.isOnCooldown = item.data.recharge && !!item.data.recharge.value && (item.data.recharge.charged === false);
item.isDepleted = item.isOnCooldown && (item.data.uses.per && (item.data.uses.value > 0));
item.hasTarget = !!item.data.target && !(["none",""].includes(item.data.target.type));
if ( item.type === "power" && ["lgt", "drk", "uni"].includes(item.data.school) ) arr[0].push(item);
else if ( item.type === "power" && ["tec"].includes(item.data.school) ) arr[1].push(item);
let [forcepowers, techpowers, other] = data.items.reduce(
(arr, item) => {
item.img = item.img || CONST.DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && item.data.quantity !== 1;
item.hasUses = item.data.uses && item.data.uses.max > 0;
item.isOnCooldown =
item.data.recharge && !!item.data.recharge.value && item.data.recharge.charged === false;
item.isDepleted = item.isOnCooldown && item.data.uses.per && item.data.uses.value > 0;
item.hasTarget = !!item.data.target && !["none", ""].includes(item.data.target.type);
if (item.type === "power" && ["lgt", "drk", "uni"].includes(item.data.school)) arr[0].push(item);
else if (item.type === "power" && ["tec"].includes(item.data.school)) arr[1].push(item);
else arr[2].push(item);
return arr;
}, [[], [], []]);
},
[[], [], []]
);
// Apply item filters
forcepowers = this._filterItems(forcepowers, this._filters.forcePowerbook);
@ -62,37 +81,33 @@ export default class ActorSheet5eStarship extends ActorSheet5e {
other = this._filterItems(other, this._filters.features);
// Organize Powerbook
// const forcePowerbook = this._preparePowerbook(data, forcepowers, "uni");
// const techPowerbook = this._preparePowerbook(data, techpowers, "tec");
// const forcePowerbook = this._preparePowerbook(data, forcepowers, "uni");
// const techPowerbook = this._preparePowerbook(data, techpowers, "tec");
// Organize Features
for ( let item of other ) {
if ( item.type === "weapon" ) features.weapons.items.push(item);
else if ( item.type === "feat" ) {
if ( item.data.activation.type ) features.actions.items.push(item);
for (let item of other) {
if (item.type === "weapon") features.weapons.items.push(item);
else if (item.type === "feat") {
if (item.data.activation.type) features.actions.items.push(item);
else features.passive.items.push(item);
}
else if ( item.type === "starshipfeature" ) {
} else if (item.type === "starshipfeature") {
features.starshipfeatures.items.push(item);
}
else if ( item.type === "starshipmod" ) {
} else if (item.type === "starshipmod") {
features.starshipmods.items.push(item);
}
else features.equipment.items.push(item);
} else features.equipment.items.push(item);
}
// Assign and return
data.features = Object.values(features);
// data.forcePowerbook = forcePowerbook;
// data.techPowerbook = techPowerbook;
// data.forcePowerbook = forcePowerbook;
// data.techPowerbook = techPowerbook;
}
/* -------------------------------------------- */
/** @override */
getData() {
const data = super.getData();
getData(options) {
const data = super.getData(options);
// Add Size info
data.isTiny = data.actor.data.traits.size === "tiny";
@ -114,17 +129,16 @@ export default class ActorSheet5eStarship extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
_updateObject(event, formData) {
async _updateObject(event, formData) {
// Format NPC Challenge Rating
const crs = {"1/8": 0.125, "1/4": 0.25, "1/2": 0.5};
let crv = "data.details.cr";
let cr = formData[crv];
cr = crs[cr] || parseFloat(cr);
if ( cr ) formData[crv] = cr < 1 ? cr : parseInt(cr);
if (cr) formData[crv] = cr < 1 ? cr : parseInt(cr);
// Parent ActorSheet update steps
super._updateObject(event, formData);
return super._updateObject(event, formData);
}
/* -------------------------------------------- */
@ -147,10 +161,9 @@ export default class ActorSheet5eStarship extends ActorSheet5e {
_onRollHPFormula(event) {
event.preventDefault();
const formula = this.actor.data.data.attributes.hp.formula;
if ( !formula ) return;
if (!formula) return;
const hp = new Roll(formula).roll().total;
AudioHelper.play({src: CONFIG.sounds.dice});
this.actor.update({"data.attributes.hp.value": hp, "data.attributes.hp.max": hp});
}
}

View file

@ -20,12 +20,17 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
static unsupportedItemTypes = new Set(["class"]);
/* -------------------------------------------- */
/**
* Creates a new cargo entry for a vehicle Actor.
*/
static get newCargo() {
return {
name: '',
name: "",
quantity: 1
};
}
@ -40,7 +45,6 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
* @private
*/
_computeEncumbrance(totalWeight, actorData) {
// Compute currency weight
const totalCoins = Object.values(actorData.data.currency).reduce((acc, denom) => acc + denom, 0);
totalWeight += totalCoins / CONFIG.SW5E.encumbrance.currencyPerWeight;
@ -57,7 +61,7 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
_getMovementSpeed(actorData, largestPrimary=true) {
_getMovementSpeed(actorData, largestPrimary = true) {
return super._getMovementSpeed(actorData, largestPrimary);
}
@ -69,25 +73,24 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
* @private
*/
_prepareCrewedItem(item) {
// Determine crewed status
const isCrewed = item.data.crewed;
item.toggleClass = isCrewed ? 'active' : '';
item.toggleTitle = game.i18n.localize(`SW5E.${isCrewed ? 'Crewed' : 'Uncrewed'}`);
item.toggleClass = isCrewed ? "active" : "";
item.toggleTitle = game.i18n.localize(`SW5E.${isCrewed ? "Crewed" : "Uncrewed"}`);
// Handle crew actions
if (item.type === 'feat' && item.data.activation.type === 'crew') {
if (item.type === "feat" && item.data.activation.type === "crew") {
item.crew = item.data.activation.cost;
item.cover = game.i18n.localize(`SW5E.${item.data.cover ? 'CoverTotal' : 'None'}`);
if (item.data.cover === .5) item.cover = '½';
else if (item.data.cover === .75) item.cover = '¾';
else if (item.data.cover === null) item.cover = '—';
if (item.crew < 1 || item.crew === null) item.crew = '—';
item.cover = game.i18n.localize(`SW5E.${item.data.cover ? "CoverTotal" : "None"}`);
if (item.data.cover === 0.5) item.cover = "½";
else if (item.data.cover === 0.75) item.cover = "¾";
else if (item.data.cover === null) item.cover = "—";
if (item.crew < 1 || item.crew === null) item.crew = "—";
}
// Prepare vehicle weapons
if (item.type === 'equipment' || item.type === 'weapon') {
item.threshold = item.data.hp.dt ? item.data.hp.dt : '—';
if (item.type === "equipment" || item.type === "weapon") {
item.threshold = item.data.hp.dt ? item.data.hp.dt : "—";
}
}
@ -98,132 +101,162 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
* @private
*/
_prepareItems(data) {
const cargoColumns = [{
label: game.i18n.localize('SW5E.Quantity'),
css: 'item-qty',
property: 'quantity',
editable: 'Number'
}];
const cargoColumns = [
{
label: game.i18n.localize("SW5E.Quantity"),
css: "item-qty",
property: "quantity",
editable: "Number"
}
];
const equipmentColumns = [{
label: game.i18n.localize('SW5E.Quantity'),
css: 'item-qty',
property: 'data.quantity'
}, {
label: game.i18n.localize('SW5E.AC'),
css: 'item-ac',
property: 'data.armor.value'
}, {
label: game.i18n.localize('SW5E.HP'),
css: 'item-hp',
property: 'data.hp.value',
editable: 'Number'
}, {
label: game.i18n.localize('SW5E.Threshold'),
css: 'item-threshold',
property: 'threshold'
}];
const equipmentColumns = [
{
label: game.i18n.localize("SW5E.Quantity"),
css: "item-qty",
property: "data.quantity"
},
{
label: game.i18n.localize("SW5E.AC"),
css: "item-ac",
property: "data.armor.value"
},
{
label: game.i18n.localize("SW5E.HP"),
css: "item-hp",
property: "data.hp.value",
editable: "Number"
},
{
label: game.i18n.localize("SW5E.Threshold"),
css: "item-threshold",
property: "threshold"
}
];
const features = {
actions: {
label: game.i18n.localize('SW5E.ActionPl'),
label: game.i18n.localize("SW5E.ActionPl"),
items: [],
crewable: true,
dataset: {type: 'feat', 'activation.type': 'crew'},
columns: [{
label: game.i18n.localize('SW5E.VehicleCrew'),
css: 'item-crew',
property: 'crew'
}, {
label: game.i18n.localize('SW5E.Cover'),
css: 'item-cover',
property: 'cover'
}]
dataset: {"type": "feat", "activation.type": "crew"},
columns: [
{
label: game.i18n.localize("SW5E.VehicleCrew"),
css: "item-crew",
property: "crew"
},
{
label: game.i18n.localize("SW5E.Cover"),
css: "item-cover",
property: "cover"
}
]
},
equipment: {
label: game.i18n.localize('SW5E.ItemTypeEquipment'),
label: game.i18n.localize("SW5E.ItemTypeEquipment"),
items: [],
crewable: true,
dataset: {type: 'equipment', 'armor.type': 'vehicle'},
dataset: {"type": "equipment", "armor.type": "vehicle"},
columns: equipmentColumns
},
passive: {
label: game.i18n.localize('SW5E.Features'),
label: game.i18n.localize("SW5E.Features"),
items: [],
dataset: {type: 'feat'}
dataset: {type: "feat"}
},
reactions: {
label: game.i18n.localize('SW5E.ReactionPl'),
label: game.i18n.localize("SW5E.ReactionPl"),
items: [],
dataset: {type: 'feat', 'activation.type': 'reaction'}
dataset: {"type": "feat", "activation.type": "reaction"}
},
weapons: {
label: game.i18n.localize('SW5E.ItemTypeWeaponPl'),
label: game.i18n.localize("SW5E.ItemTypeWeaponPl"),
items: [],
crewable: true,
dataset: {type: 'weapon', 'weapon-type': 'siege'},
dataset: {"type": "weapon", "weapon-type": "siege"},
columns: equipmentColumns
}
};
const cargo = {
crew: {
label: game.i18n.localize('SW5E.VehicleCrew'),
label: game.i18n.localize("SW5E.VehicleCrew"),
items: data.data.cargo.crew,
css: 'cargo-row crew',
css: "cargo-row crew",
editableName: true,
dataset: {type: 'crew'},
dataset: {type: "crew"},
columns: cargoColumns
},
passengers: {
label: game.i18n.localize('SW5E.VehiclePassengers'),
label: game.i18n.localize("SW5E.VehiclePassengers"),
items: data.data.cargo.passengers,
css: 'cargo-row passengers',
css: "cargo-row passengers",
editableName: true,
dataset: {type: 'passengers'},
dataset: {type: "passengers"},
columns: cargoColumns
},
cargo: {
label: game.i18n.localize('SW5E.VehicleCargo'),
label: game.i18n.localize("SW5E.VehicleCargo"),
items: [],
dataset: {type: 'loot'},
columns: [{
label: game.i18n.localize('SW5E.Quantity'),
css: 'item-qty',
property: 'data.quantity',
editable: 'Number'
}, {
label: game.i18n.localize('SW5E.Price'),
css: 'item-price',
property: 'data.price',
editable: 'Number'
}, {
label: game.i18n.localize('SW5E.Weight'),
css: 'item-weight',
property: 'data.weight',
editable: 'Number'
}]
dataset: {type: "loot"},
columns: [
{
label: game.i18n.localize("SW5E.Quantity"),
css: "item-qty",
property: "data.quantity",
editable: "Number"
},
{
label: game.i18n.localize("SW5E.Price"),
css: "item-price",
property: "data.price",
editable: "Number"
},
{
label: game.i18n.localize("SW5E.Weight"),
css: "item-weight",
property: "data.weight",
editable: "Number"
}
]
}
};
// Classify items owned by the vehicle and compute total cargo weight
let totalWeight = 0;
for (const item of data.items) {
this._prepareCrewedItem(item);
if (item.type === 'weapon') features.weapons.items.push(item);
else if (item.type === 'equipment') features.equipment.items.push(item);
else if (item.type === 'loot') {
// Handle cargo explicitly
const isCargo = item.flags.sw5e?.vehicleCargo === true;
if (isCargo) {
totalWeight += (item.data.weight || 0) * item.data.quantity;
cargo.cargo.items.push(item);
continue;
}
// Handle non-cargo item types
switch (item.type) {
case "weapon":
features.weapons.items.push(item);
break;
case "equipment":
features.equipment.items.push(item);
break;
case "feat":
if (!item.data.activation.type || item.data.activation.type === "none")
features.passive.items.push(item);
else if (item.data.activation.type === "reaction") features.reactions.items.push(item);
else features.actions.items.push(item);
break;
default:
totalWeight += (item.data.weight || 0) * item.data.quantity;
cargo.cargo.items.push(item);
}
else if (item.type === 'feat') {
if (!item.data.activation.type || item.data.activation.type === 'none') {
features.passive.items.push(item);
}
else if (item.data.activation.type === 'reaction') features.reactions.items.push(item);
else features.actions.items.push(item);
}
}
// Update the rendering context data
data.features = Object.values(features);
data.cargo = Object.values(cargo);
data.data.attributes.encumbrance = this._computeEncumbrance(totalWeight, data);
@ -236,23 +269,23 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
/** @override */
activateListeners(html) {
super.activateListeners(html);
if (!this.options.editable) return;
if (!this.isEditable) return;
html.find('.item-toggle').click(this._onToggleItem.bind(this));
html.find('.item-hp input')
.click(evt => evt.target.select())
html.find(".item-toggle").click(this._onToggleItem.bind(this));
html.find(".item-hp input")
.click((evt) => evt.target.select())
.change(this._onHPChange.bind(this));
html.find('.item:not(.cargo-row) input[data-property]')
.click(evt => evt.target.select())
html.find(".item:not(.cargo-row) input[data-property]")
.click((evt) => evt.target.select())
.change(this._onEditInSheet.bind(this));
html.find('.cargo-row input')
.click(evt => evt.target.select())
html.find(".cargo-row input")
.click((evt) => evt.target.select())
.change(this._onCargoRowChange.bind(this));
if (this.actor.data.data.attributes.actions.stations) {
html.find('.counter.actions, .counter.action-thresholds').hide();
html.find(".counter.actions, .counter.action-thresholds").hide();
}
}
@ -267,20 +300,20 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
_onCargoRowChange(event) {
event.preventDefault();
const target = event.currentTarget;
const row = target.closest('.item');
const row = target.closest(".item");
const idx = Number(row.dataset.itemId);
const property = row.classList.contains('crew') ? 'crew' : 'passengers';
const property = row.classList.contains("crew") ? "crew" : "passengers";
// Get the cargo entry
const cargo = duplicate(this.actor.data.data.cargo[property]);
const cargo = foundry.utils.deepClone(this.actor.data.data.cargo[property]);
const entry = cargo[idx];
if (!entry) return null;
// Update the cargo value
const key = target.dataset.property || 'name';
const key = target.dataset.property || "name";
const type = target.dataset.dtype;
let value = target.value;
if (type === 'Number') value = Number(value);
if (type === "Number") value = Number(value);
entry[key] = value;
// Perform the Actor update
@ -297,14 +330,18 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
*/
_onEditInSheet(event) {
event.preventDefault();
const itemID = event.currentTarget.closest('.item').dataset.itemId;
const itemID = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.items.get(itemID);
const property = event.currentTarget.dataset.property;
const type = event.currentTarget.dataset.dtype;
let value = event.currentTarget.value;
switch (type) {
case 'Number': value = parseInt(value); break;
case 'Boolean': value = value === 'true'; break;
case "Number":
value = parseInt(value);
break;
case "Boolean":
value = value === "true";
break;
}
return item.update({[`${property}`]: value});
}
@ -321,8 +358,8 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
event.preventDefault();
const target = event.currentTarget;
const type = target.dataset.type;
if (type === 'crew' || type === 'passengers') {
const cargo = duplicate(this.actor.data.data.cargo[type]);
if (type === "crew" || type === "passengers") {
const cargo = foundry.utils.deepClone(this.actor.data.data.cargo[type]);
cargo.push(this.constructor.newCargo);
return this.actor.update({[`data.cargo.${type}`]: cargo});
}
@ -339,11 +376,11 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
*/
_onItemDelete(event) {
event.preventDefault();
const row = event.currentTarget.closest('.item');
if (row.classList.contains('cargo-row')) {
const row = event.currentTarget.closest(".item");
if (row.classList.contains("cargo-row")) {
const idx = Number(row.dataset.itemId);
const type = row.classList.contains('crew') ? 'crew' : 'passengers';
const cargo = duplicate(this.actor.data.data.cargo[type]).filter((_, i) => i !== idx);
const type = row.classList.contains("crew") ? "crew" : "passengers";
const cargo = foundry.utils.deepClone(this.actor.data.data.cargo[type]).filter((_, i) => i !== idx);
return this.actor.update({[`data.cargo.${type}`]: cargo});
}
@ -352,6 +389,16 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
async _onDropItemCreate(itemData) {
const cargoTypes = ["weapon", "equipment", "consumable", "tool", "loot", "backpack"];
const isCargo = cargoTypes.includes(itemData.type) && this._tabs[0].active === "cargo";
foundry.utils.setProperty(itemData, "flags.sw5e.vehicleCargo", isCargo);
return super._onDropItemCreate(itemData);
}
/* -------------------------------------------- */
/**
* Special handling for editing HP to clamp it within appropriate range.
* @param event {Event}
@ -360,11 +407,11 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
*/
_onHPChange(event) {
event.preventDefault();
const itemID = event.currentTarget.closest('.item').dataset.itemId;
const itemID = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.items.get(itemID);
const hp = Math.clamped(0, parseInt(event.currentTarget.value), item.data.data.hp.max);
event.currentTarget.value = hp;
return item.update({'data.hp.value': hp});
return item.update({"data.hp.value": hp});
}
/* -------------------------------------------- */
@ -377,9 +424,9 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
*/
_onToggleItem(event) {
event.preventDefault();
const itemID = event.currentTarget.closest('.item').dataset.itemId;
const itemID = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.items.get(itemID);
const crewed = !!item.data.data.crewed;
return item.update({'data.crewed': !crewed});
return item.update({"data.crewed": !crewed});
}
};
}

View file

@ -1,9 +1,11 @@
import Item5e from "../../../item/entity.js";
import TraitSelector from "../../../apps/trait-selector.js";
import ActorSheetFlags from "../../../apps/actor-flags.js";
import ActorHitDiceConfig from "../../../apps/hit-dice-config.js";
import ActorMovementConfig from "../../../apps/movement-config.js";
import ActorSensesConfig from "../../../apps/senses-config.js";
import {SW5E} from '../../../config.js';
import ActorTypeConfig from "../../../apps/actor-type.js";
import {SW5E} from "../../../config.js";
import {onManageActiveEffect, prepareActiveEffectCategories} from "../../../effects.js";
/**
@ -44,53 +46,67 @@ export default class ActorSheet5e extends ActorSheet {
/* -------------------------------------------- */
/**
* A set of item types that should be prevented from being dropped on this type of actor sheet.
* @type {Set<string>}
*/
static unsupportedItemTypes = new Set();
/* -------------------------------------------- */
/** @override */
get template() {
if ( !game.user.isGM && this.actor.limited ) return "systems/sw5e/templates/actors/oldActor/limited-sheet.html";
if (!game.user.isGM && this.actor.limited) return "systems/sw5e/templates/actors/oldActor/limited-sheet.html";
return `systems/sw5e/templates/actors/oldActor/${this.actor.data.type}-sheet.html`;
}
/* -------------------------------------------- */
/** @override */
getData() {
getData(options) {
// Basic data
let isOwner = this.entity.owner;
let isOwner = this.actor.isOwner;
const data = {
owner: isOwner,
limited: this.entity.limited,
limited: this.actor.limited,
options: this.options,
editable: this.isEditable,
cssClass: isOwner ? "editable" : "locked",
isCharacter: this.entity.data.type === "character",
isNPC: this.entity.data.type === "npc",
isStarship: this.entity.data.type === "starship",
isVehicle: this.entity.data.type === 'vehicle',
isCharacter: this.actor.type === "character",
isNPC: this.actor.type === "npc",
isStarship: this.actor.type === "starship",
isVehicle: this.actor.type === "vehicle",
config: CONFIG.SW5E,
rollData: this.actor.getRollData.bind(this.actor)
};
// The Actor and its Items
data.actor = duplicate(this.actor.data);
data.items = this.actor.items.map(i => {
i.data.labels = i.labels;
return i.data;
});
// The Actor's data
const actorData = this.actor.data.toObject(false);
data.actor = actorData;
data.data = actorData.data;
// Owned Items
data.items = actorData.items;
for (let i of data.items) {
const item = this.actor.items.get(i._id);
i.labels = item.labels;
}
data.items.sort((a, b) => (a.sort || 0) - (b.sort || 0));
data.data = data.actor.data;
// Labels and filters
data.labels = this.actor.labels || {};
data.filters = this._filters;
// Ability Scores
for ( let [a, abl] of Object.entries(data.actor.data.abilities)) {
for (let [a, abl] of Object.entries(actorData.data.abilities)) {
abl.icon = this._getProficiencyIcon(abl.proficient);
abl.hover = CONFIG.SW5E.proficiencyLevels[abl.proficient];
abl.label = CONFIG.SW5E.abilities[a];
}
// Skills
if (data.actor.data.skills) {
for ( let [s, skl] of Object.entries(data.actor.data.skills)) {
if (actorData.data.skills) {
for (let [s, skl] of Object.entries(actorData.data.skills)) {
skl.ability = CONFIG.SW5E.abilityAbbreviations[skl.ability];
skl.icon = this._getProficiencyIcon(skl.value);
skl.hover = CONFIG.SW5E.proficiencyLevels[skl.value];
@ -99,22 +115,22 @@ export default class ActorSheet5e extends ActorSheet {
}
// Movement speeds
data.movement = this._getMovementSpeed(data.actor);
data.movement = this._getMovementSpeed(actorData);
// Senses
data.senses = this._getSenses(data.actor);
data.senses = this._getSenses(actorData);
// Update traits
this._prepareTraits(data.actor.data.traits);
this._prepareTraits(actorData.data.traits);
// Prepare owned items
this._prepareItems(data);
// Prepare active effects
data.effects = prepareActiveEffectCategories(this.entity.effects);
data.effects = prepareActiveEffectCategories(this.actor.effects);
// Return data to the sheet
return data
return data;
}
/* -------------------------------------------- */
@ -126,38 +142,42 @@ export default class ActorSheet5e extends ActorSheet {
* @returns {{primary: string, special: string}}
* @private
*/
_getMovementSpeed(actorData, largestPrimary=false) {
_getMovementSpeed(actorData, largestPrimary = false) {
const movement = actorData.data.attributes.movement || {};
// Prepare an array of available movement speeds
let speeds = [
[movement.burrow, `${game.i18n.localize("SW5E.MovementBurrow")} ${movement.burrow}`],
[movement.climb, `${game.i18n.localize("SW5E.MovementClimb")} ${movement.climb}`],
[movement.fly, `${game.i18n.localize("SW5E.MovementFly")} ${movement.fly}` + (movement.hover ? ` (${game.i18n.localize("SW5E.MovementHover")})` : "")],
[
movement.fly,
`${game.i18n.localize("SW5E.MovementFly")} ${movement.fly}` +
(movement.hover ? ` (${game.i18n.localize("SW5E.MovementHover")})` : "")
],
[movement.swim, `${game.i18n.localize("SW5E.MovementSwim")} ${movement.swim}`]
]
if ( largestPrimary ) {
];
if (largestPrimary) {
speeds.push([movement.walk, `${game.i18n.localize("SW5E.MovementWalk")} ${movement.walk}`]);
}
// Filter and sort speeds on their values
speeds = speeds.filter(s => !!s[0]).sort((a, b) => b[0] - a[0]);
speeds = speeds.filter((s) => !!s[0]).sort((a, b) => b[0] - a[0]);
// Case 1: Largest as primary
if ( largestPrimary ) {
if (largestPrimary) {
let primary = speeds.shift();
return {
primary: `${primary ? primary[1] : "0"} ${movement.units}`,
special: speeds.map(s => s[1]).join(", ")
}
special: speeds.map((s) => s[1]).join(", ")
};
}
// Case 2: Walk as primary
else {
return {
primary: `${movement.walk || 0} ${movement.units}`,
special: speeds.length ? speeds.map(s => s[1]).join(", ") : ""
}
special: speeds.length ? speeds.map((s) => s[1]).join(", ") : ""
};
}
}
@ -166,12 +186,12 @@ export default class ActorSheet5e extends ActorSheet {
_getSenses(actorData) {
const senses = actorData.data.attributes.senses || {};
const tags = {};
for ( let [k, label] of Object.entries(CONFIG.SW5E.senses) ) {
const v = senses[k] ?? 0
if ( v === 0 ) continue;
for (let [k, label] of Object.entries(CONFIG.SW5E.senses)) {
const v = senses[k] ?? 0;
if (v === 0) continue;
tags[k] = `${game.i18n.localize(label)} ${v} ${senses.units}`;
}
if ( !!senses.special ) tags["special"] = senses.special;
if (!!senses.special) tags["special"] = senses.special;
return tags;
}
@ -184,20 +204,20 @@ export default class ActorSheet5e extends ActorSheet {
*/
_prepareTraits(traits) {
const map = {
"dr": CONFIG.SW5E.damageResistanceTypes,
"di": CONFIG.SW5E.damageResistanceTypes,
"dv": CONFIG.SW5E.damageResistanceTypes,
"ci": CONFIG.SW5E.conditionTypes,
"languages": CONFIG.SW5E.languages,
"armorProf": CONFIG.SW5E.armorProficiencies,
"weaponProf": CONFIG.SW5E.weaponProficiencies,
"toolProf": CONFIG.SW5E.toolProficiencies
dr: CONFIG.SW5E.damageResistanceTypes,
di: CONFIG.SW5E.damageResistanceTypes,
dv: CONFIG.SW5E.damageResistanceTypes,
ci: CONFIG.SW5E.conditionTypes,
languages: CONFIG.SW5E.languages,
armorProf: CONFIG.SW5E.armorProficiencies,
weaponProf: CONFIG.SW5E.weaponProficiencies,
toolProf: CONFIG.SW5E.toolProficiencies
};
for ( let [t, choices] of Object.entries(map) ) {
for (let [t, choices] of Object.entries(map)) {
const trait = traits[t];
if ( !trait ) continue;
if (!trait) continue;
let values = [];
if ( trait.value ) {
if (trait.value) {
values = trait.value instanceof Array ? trait.value : [trait.value];
}
trait.selected = values.reduce((obj, t) => {
@ -206,8 +226,8 @@ export default class ActorSheet5e extends ActorSheet {
}, {});
// Add custom entry
if ( trait.custom ) {
trait.custom.split(";").forEach((c, i) => trait.selected[`custom${i+1}`] = c.trim());
if (trait.custom) {
trait.custom.split(";").forEach((c, i) => (trait.selected[`custom${i + 1}`] = c.trim()));
}
trait.cssClass = !isObjectEmpty(trait.selected) ? "" : "inactive";
}
@ -222,15 +242,15 @@ export default class ActorSheet5e extends ActorSheet {
* @private
*/
_preparePowerbook(data, powers) {
const owner = this.actor.owner;
const owner = this.actor.isOwner;
const levels = data.data.powers;
const powerbook = {};
// Define some mappings
const sections = {
"atwill": -20,
"innate": -10,
"pact": 0.5
atwill: -20,
innate: -10,
pact: 0.5
};
// Label power slot uses headers
@ -241,13 +261,13 @@ export default class ActorSheet5e extends ActorSheet {
};
// Format a powerbook entry for a certain indexed level
const registerSection = (sl, i, label, {prepMode="prepared", value, max, override}={}) => {
const registerSection = (sl, i, label, {prepMode = "prepared", value, max, override} = {}) => {
powerbook[i] = {
order: i,
label: label,
usesSlots: i > 0,
canCreate: owner,
canPrepare: (data.actor.type === "character") && (i >= 1),
canPrepare: data.actor.type === "character" && i >= 1,
powers: [],
uses: useLabels[i] || value || 0,
slots: useLabels[i] || max || 0,
@ -259,14 +279,14 @@ export default class ActorSheet5e extends ActorSheet {
// Determine the maximum power level which has a slot
const maxLevel = Array.fromRange(10).reduce((max, i) => {
if ( i === 0 ) return max;
if (i === 0) return max;
const level = levels[`power${i}`];
if ( (level.max || level.override ) && ( i > max ) ) max = i;
if ((level.max || level.override) && i > max) max = i;
return max;
}, 0);
// Level-based powercasters have cantrips and leveled slots
if ( maxLevel > 0 ) {
if (maxLevel > 0) {
registerSection("power0", 0, CONFIG.SW5E.powerLevels[0]);
for (let lvl = 1; lvl <= maxLevel; lvl++) {
const sl = `power${lvl}`;
@ -275,11 +295,14 @@ export default class ActorSheet5e extends ActorSheet {
}
// Pact magic users have cantrips and a pact magic section
if ( levels.pact && levels.pact.max ) {
if ( !powerbook["0"] ) registerSection("power0", 0, CONFIG.SW5E.powerLevels[0]);
// TODO: Check if this is needed, we've removed pacts everywhere else
if (levels.pact && levels.pact.max) {
if (!powerbook["0"]) registerSection("power0", 0, CONFIG.SW5E.powerLevels[0]);
const l = levels.pact;
const config = CONFIG.SW5E.powerPreparationModes.pact;
registerSection("pact", sections.pact, config, {
const level = game.i18n.localize(`SW5E.PowerLevel${levels.pact.level}`);
const label = `${config}${level}`;
registerSection("pact", sections.pact, label, {
prepMode: "pact",
value: l.value,
max: l.max,
@ -288,15 +311,15 @@ export default class ActorSheet5e extends ActorSheet {
}
// Iterate over every power item, adding powers to the powerbook by section
powers.forEach(power => {
powers.forEach((power) => {
const mode = power.data.preparation.mode || "prepared";
let s = power.data.level || 0;
const sl = `power${s}`;
// Specialized powercasting modes (if they exist)
if ( mode in sections ) {
if (mode in sections) {
s = sections[mode];
if ( !powerbook[s] ){
if (!powerbook[s]) {
const l = levels[mode] || {};
const config = CONFIG.SW5E.powerPreparationModes[mode];
registerSection(mode, s, config, {
@ -309,7 +332,7 @@ export default class ActorSheet5e extends ActorSheet {
}
// Sections for higher-level powers which the caster "should not" have, but power items exist for
else if ( !powerbook[s] ) {
else if (!powerbook[s]) {
registerSection(sl, s, CONFIG.SW5E.powerLevels[s], {levels: levels[sl]});
}
@ -331,32 +354,32 @@ export default class ActorSheet5e extends ActorSheet {
* @private
*/
_filterItems(items, filters) {
return items.filter(item => {
return items.filter((item) => {
const data = item.data;
// Action usage
for ( let f of ["action", "bonus", "reaction"] ) {
if ( filters.has(f) ) {
if ((data.activation && (data.activation.type !== f))) return false;
for (let f of ["action", "bonus", "reaction"]) {
if (filters.has(f)) {
if (data.activation && data.activation.type !== f) return false;
}
}
// Power-specific filters
if ( filters.has("ritual") ) {
if (filters.has("ritual")) {
if (data.components.ritual !== true) return false;
}
if ( filters.has("concentration") ) {
if (filters.has("concentration")) {
if (data.components.concentration !== true) return false;
}
if ( filters.has("prepared") ) {
if ( data.level === 0 || ["innate", "always"].includes(data.preparation.mode) ) return true;
if ( this.actor.data.type === "npc" ) return true;
if (filters.has("prepared")) {
if (data.level === 0 || ["innate", "always"].includes(data.preparation.mode)) return true;
if (this.actor.data.type === "npc") return true;
return data.preparation.prepared;
}
// Equipment-specific filters
if ( filters.has("equipped") ) {
if ( data.equipped !== true ) return false;
if (filters.has("equipped")) {
if (data.equipped !== true) return false;
}
return true;
});
@ -382,64 +405,61 @@ export default class ActorSheet5e extends ActorSheet {
/* Event Listeners and Handlers
/* -------------------------------------------- */
/**
* Activate event listeners using the prepared sheet HTML
* @param html {HTML} The prepared HTML object ready to be rendered into the DOM
*/
/** @inheritdoc */
activateListeners(html) {
// Activate Item Filters
const filterLists = html.find(".filter-list");
filterLists.each(this._initializeFilterItemList.bind(this));
filterLists.on("click", ".filter-item", this._onToggleFilter.bind(this));
// Item summaries
html.find('.item .item-name.rollable h4').click(event => this._onItemSummary(event));
html.find(".item .item-name.rollable h4").click((event) => this._onItemSummary(event));
// View Item Sheets
html.find(".item-edit").click(this._onItemEdit.bind(this));
// Editable Only Listeners
if ( this.isEditable ) {
if (this.isEditable) {
// Input focus and update
const inputs = html.find("input");
inputs.focus(ev => ev.currentTarget.select());
inputs.focus((ev) => ev.currentTarget.select());
inputs.addBack().find('[data-dtype="Number"]').change(this._onChangeInputDelta.bind(this));
// Ability Proficiency
html.find('.ability-proficiency').click(this._onToggleAbilityProficiency.bind(this));
html.find(".ability-proficiency").click(this._onToggleAbilityProficiency.bind(this));
// Toggle Skill Proficiency
html.find('.skill-proficiency').on("click contextmenu", this._onCycleSkillProficiency.bind(this));
html.find(".skill-proficiency").on("click contextmenu", this._onCycleSkillProficiency.bind(this));
// Trait Selector
html.find('.trait-selector').click(this._onTraitSelector.bind(this));
html.find(".trait-selector").click(this._onTraitSelector.bind(this));
// Configure Special Flags
html.find('.config-button').click(this._onConfigMenu.bind(this));
html.find(".config-button").click(this._onConfigMenu.bind(this));
// Owned Item management
html.find('.item-create').click(this._onItemCreate.bind(this));
html.find('.item-edit').click(this._onItemEdit.bind(this));
html.find('.item-delete').click(this._onItemDelete.bind(this));
html.find('.item-uses input').click(ev => ev.target.select()).change(this._onUsesChange.bind(this));
html.find('.slot-max-override').click(this._onPowerSlotOverride.bind(this));
html.find(".item-create").click(this._onItemCreate.bind(this));
html.find(".item-delete").click(this._onItemDelete.bind(this));
html.find(".item-uses input")
.click((ev) => ev.target.select())
.change(this._onUsesChange.bind(this));
html.find(".slot-max-override").click(this._onPowerSlotOverride.bind(this));
// Active Effect management
html.find(".effect-control").click(ev => onManageActiveEffect(ev, this.entity));
html.find(".effect-control").click((ev) => onManageActiveEffect(ev, this.actor));
}
// Owner Only Listeners
if ( this.actor.owner ) {
if (this.actor.isOwner) {
// Ability Checks
html.find('.ability-name').click(this._onRollAbilityTest.bind(this));
html.find(".ability-name").click(this._onRollAbilityTest.bind(this));
// Roll Skill Checks
html.find('.skill-name').click(this._onRollSkillCheck.bind(this));
html.find(".skill-name").click(this._onRollSkillCheck.bind(this));
// Item Rolling
html.find('.item .item-image').click(event => this._onItemRoll(event));
html.find('.item .item-recharge').click(event => this._onItemRecharge(event));
html.find(".item .item-image").click((event) => this._onItemRoll(event));
html.find(".item .item-recharge").click((event) => this._onItemRecharge(event));
}
// Otherwise remove rollable classes
@ -460,8 +480,8 @@ export default class ActorSheet5e extends ActorSheet {
_initializeFilterItemList(i, ul) {
const set = this._filters[ul.dataset.filter];
const filters = ul.querySelectorAll(".filter-item");
for ( let li of filters ) {
if ( set.has(li.dataset.filter) ) li.classList.add("active");
for (let li of filters) {
if (set.has(li.dataset.filter)) li.classList.add("active");
}
}
@ -477,10 +497,10 @@ export default class ActorSheet5e extends ActorSheet {
_onChangeInputDelta(event) {
const input = event.target;
const value = input.value;
if ( ["+", "-"].includes(value[0]) ) {
if (["+", "-"].includes(value[0])) {
let delta = parseFloat(value);
input.value = getProperty(this.actor.data, input.name) + delta;
} else if ( value[0] === "=" ) {
} else if (value[0] === "=") {
input.value = value.slice(1);
}
}
@ -495,17 +515,25 @@ export default class ActorSheet5e extends ActorSheet {
_onConfigMenu(event) {
event.preventDefault();
const button = event.currentTarget;
switch ( button.dataset.action ) {
let app;
switch (button.dataset.action) {
case "hit-dice":
app = new ActorHitDiceConfig(this.object);
break;
case "movement":
new ActorMovementConfig(this.object).render(true);
app = new ActorMovementConfig(this.object);
break;
case "flags":
new ActorSheetFlags(this.object).render(true);
app = new ActorSheetFlags(this.object);
break;
case "senses":
new ActorSensesConfig(this.object).render(true);
app = new ActorSensesConfig(this.object);
break;
case "type":
new ActorTypeConfig(this.object).render(true);
break;
}
app?.render(true);
}
/* -------------------------------------------- */
@ -525,10 +553,10 @@ export default class ActorSheet5e extends ActorSheet {
let idx = levels.indexOf(level);
// Toggle next level - forward on click, backwards on right
if ( event.type === "click" ) {
field.val(levels[(idx === levels.length - 1) ? 0 : idx + 1]);
} else if ( event.type === "contextmenu" ) {
field.val(levels[(idx === 0) ? levels.length - 1 : idx - 1]);
if (event.type === "click") {
field.val(levels[idx === levels.length - 1 ? 0 : idx + 1]);
} else if (event.type === "contextmenu") {
field.val(levels[idx === 0 ? levels.length - 1 : idx - 1]);
}
// Update the field value and save the form
@ -539,49 +567,51 @@ export default class ActorSheet5e extends ActorSheet {
/** @override */
async _onDropActor(event, data) {
const canPolymorph = game.user.isGM || (this.actor.owner && game.settings.get('sw5e', 'allowPolymorphing'));
if ( !canPolymorph ) return false;
const canPolymorph = game.user.isGM || (this.actor.isOwner && game.settings.get("sw5e", "allowPolymorphing"));
if (!canPolymorph) return false;
// Get the target actor
let sourceActor = null;
if (data.pack) {
const pack = game.packs.find(p => p.collection === data.pack);
const pack = game.packs.find((p) => p.collection === data.pack);
sourceActor = await pack.getEntity(data.id);
} else {
sourceActor = game.actors.get(data.id);
}
if ( !sourceActor ) return;
if (!sourceActor) return;
// Define a function to record polymorph settings for future use
const rememberOptions = html => {
const rememberOptions = (html) => {
const options = {};
html.find('input').each((i, el) => {
html.find("input").each((i, el) => {
options[el.name] = el.checked;
});
const settings = mergeObject(game.settings.get('sw5e', 'polymorphSettings') || {}, options);
game.settings.set('sw5e', 'polymorphSettings', settings);
const settings = mergeObject(game.settings.get("sw5e", "polymorphSettings") || {}, options);
game.settings.set("sw5e", "polymorphSettings", settings);
return settings;
};
// Create and render the Dialog
return new Dialog({
title: game.i18n.localize('SW5E.PolymorphPromptTitle'),
return new Dialog(
{
title: game.i18n.localize("SW5E.PolymorphPromptTitle"),
content: {
options: game.settings.get('sw5e', 'polymorphSettings'),
options: game.settings.get("sw5e", "polymorphSettings"),
i18n: SW5E.polymorphSettings,
isToken: this.actor.isToken
},
default: 'accept',
default: "accept",
buttons: {
accept: {
icon: '<i class="fas fa-check"></i>',
label: game.i18n.localize('SW5E.PolymorphAcceptSettings'),
callback: html => this.actor.transformInto(sourceActor, rememberOptions(html))
label: game.i18n.localize("SW5E.PolymorphAcceptSettings"),
callback: (html) => this.actor.transformInto(sourceActor, rememberOptions(html))
},
wildshape: {
icon: '<i class="fas fa-paw"></i>',
label: game.i18n.localize('SW5E.PolymorphWildShape'),
callback: html => this.actor.transformInto(sourceActor, {
label: game.i18n.localize("SW5E.PolymorphWildShape"),
callback: (html) =>
this.actor.transformInto(sourceActor, {
keepBio: true,
keepClass: true,
keepMental: true,
@ -592,37 +622,66 @@ export default class ActorSheet5e extends ActorSheet {
},
polymorph: {
icon: '<i class="fas fa-pastafarianism"></i>',
label: game.i18n.localize('SW5E.Polymorph'),
callback: html => this.actor.transformInto(sourceActor, {
label: game.i18n.localize("SW5E.Polymorph"),
callback: (html) =>
this.actor.transformInto(sourceActor, {
transformTokens: rememberOptions(html).transformTokens
})
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: game.i18n.localize('Cancel')
label: game.i18n.localize("Cancel")
}
}
}, {
classes: ['dialog', 'sw5e'],
},
{
classes: ["dialog", "sw5e"],
width: 600,
template: 'systems/sw5e/templates/apps/polymorph-prompt.html'
}).render(true);
template: "systems/sw5e/templates/apps/polymorph-prompt.html"
}
).render(true);
}
/* -------------------------------------------- */
/** @override */
async _onDropItemCreate(itemData) {
// Check to make sure items of this type are allowed on this actor
if (this.constructor.unsupportedItemTypes.has(itemData.type)) {
return ui.notifications.warn(
game.i18n.format("SW5E.ActorWarningInvalidItem", {
itemType: game.i18n.localize(CONFIG.Item.typeLabels[itemData.type]),
actorType: game.i18n.localize(CONFIG.Actor.typeLabels[this.actor.type])
})
);
}
// Create a Consumable power scroll on the Inventory tab
if ( (itemData.type === "power") && (this._tabs[0].active === "inventory") ) {
// TODO: This is pretty non functional as the base items for the scrolls, and the powers, are not defined, maybe consider using holocrons
if (itemData.type === "power" && this._tabs[0].active === "inventory") {
const scroll = await Item5e.createScrollFromPower(itemData);
itemData = scroll.data;
}
if (itemData.data) {
// Ignore certain statuses
if ( itemData.data ) {
["attunement", "equipped", "proficient", "prepared"].forEach(k => delete itemData.data[k]);
["equipped", "proficient", "prepared"].forEach((k) => delete itemData.data[k]);
// Downgrade ATTUNED to REQUIRED
itemData.data.attunement = Math.min(itemData.data.attunement, CONFIG.SW5E.attunementTypes.REQUIRED);
}
// Stack identical consumables
if (itemData.type === "consumable" && itemData.flags.core?.sourceId) {
const similarItem = this.actor.items.find((i) => {
const sourceId = i.getFlag("core", "sourceId");
return sourceId && sourceId === itemData.flags.core?.sourceId && i.type === "consumable";
});
if (similarItem) {
return similarItem.update({
"data.quantity": similarItem.data.data.quantity + Math.max(itemData.data.quantity, 1)
});
}
}
// Create the owned item as normal
@ -636,7 +695,7 @@ export default class ActorSheet5e extends ActorSheet {
* @param {MouseEvent} event The originating click event
* @private
*/
async _onPowerSlotOverride (event) {
async _onPowerSlotOverride(event) {
const span = event.currentTarget.parentElement;
const level = span.dataset.level;
const override = this.actor.data.data.powers[level].override || span.dataset.slots;
@ -663,10 +722,10 @@ export default class ActorSheet5e extends ActorSheet {
async _onUsesChange(event) {
event.preventDefault();
const itemId = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.getOwnedItem(itemId);
const item = this.actor.items.get(itemId);
const uses = Math.clamped(0, parseInt(event.target.value), item.data.data.uses.max);
event.target.value = uses;
return item.update({ 'data.uses.value': uses });
return item.update({"data.uses.value": uses});
}
/* -------------------------------------------- */
@ -678,7 +737,7 @@ export default class ActorSheet5e extends ActorSheet {
_onItemRoll(event) {
event.preventDefault();
const itemId = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.getOwnedItem(itemId);
const item = this.actor.items.get(itemId);
return item.roll();
}
@ -692,9 +751,9 @@ export default class ActorSheet5e extends ActorSheet {
_onItemRecharge(event) {
event.preventDefault();
const itemId = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.getOwnedItem(itemId);
const item = this.actor.items.get(itemId);
return item.rollRecharge();
};
}
/* -------------------------------------------- */
@ -705,17 +764,17 @@ export default class ActorSheet5e extends ActorSheet {
_onItemSummary(event) {
event.preventDefault();
let li = $(event.currentTarget).parents(".item"),
item = this.actor.getOwnedItem(li.data("item-id")),
chatData = item.getChatData({secrets: this.actor.owner});
item = this.actor.items.get(li.data("item-id")),
chatData = item.getChatData({secrets: this.actor.isOwner});
// Toggle summary
if ( li.hasClass("expanded") ) {
if (li.hasClass("expanded")) {
let summary = li.children(".item-summary");
summary.slideUp(200, () => summary.remove());
} else {
let div = $(`<div class="item-summary">${chatData.description.value}</div>`);
let props = $(`<div class="item-properties"></div>`);
chatData.properties.forEach(p => props.append(`<span class="tag">${p}</span>`));
chatData.properties.forEach((p) => props.append(`<span class="tag">${p}</span>`));
div.append(props);
li.append(div.hide());
div.slideDown(200);
@ -735,12 +794,12 @@ export default class ActorSheet5e extends ActorSheet {
const header = event.currentTarget;
const type = header.dataset.type;
const itemData = {
name: game.i18n.format("SW5E.ItemNew", {type: type.capitalize()}),
name: game.i18n.format("SW5E.ItemNew", {type: game.i18n.localize(`SW5E.ItemType${type.capitalize()}`)}),
type: type,
data: duplicate(header.dataset)
data: foundry.utils.deepClone(header.dataset)
};
delete itemData.data["type"];
return this.actor.createEmbeddedEntity("OwnedItem", itemData);
return this.actor.createEmbeddedDocuments("Item", [itemData]);
}
/* -------------------------------------------- */
@ -753,8 +812,8 @@ export default class ActorSheet5e extends ActorSheet {
_onItemEdit(event) {
event.preventDefault();
const li = event.currentTarget.closest(".item");
const item = this.actor.getOwnedItem(li.dataset.itemId);
item.sheet.render(true);
const item = this.actor.items.get(li.dataset.itemId);
return item.sheet.render(true);
}
/* -------------------------------------------- */
@ -767,7 +826,8 @@ export default class ActorSheet5e extends ActorSheet {
_onItemDelete(event) {
event.preventDefault();
const li = event.currentTarget.closest(".item");
this.actor.deleteOwnedItem(li.dataset.itemId);
const item = this.actor.items.get(li.dataset.itemId);
if (item) return item.delete();
}
/* -------------------------------------------- */
@ -780,7 +840,7 @@ export default class ActorSheet5e extends ActorSheet {
_onRollAbilityTest(event) {
event.preventDefault();
let ability = event.currentTarget.parentElement.dataset.ability;
this.actor.rollAbility(ability, {event: event});
return this.actor.rollAbility(ability, {event: event});
}
/* -------------------------------------------- */
@ -793,7 +853,7 @@ export default class ActorSheet5e extends ActorSheet {
_onRollSkillCheck(event) {
event.preventDefault();
const skill = event.currentTarget.parentElement.dataset.skill;
this.actor.rollSkill(skill, {event: event});
return this.actor.rollSkill(skill, {event: event});
}
/* -------------------------------------------- */
@ -806,7 +866,7 @@ export default class ActorSheet5e extends ActorSheet {
_onToggleAbilityProficiency(event) {
event.preventDefault();
const field = event.currentTarget.previousElementSibling;
this.actor.update({[field.name]: 1 - parseInt(field.value)});
return this.actor.update({[field.name]: 1 - parseInt(field.value)});
}
/* -------------------------------------------- */
@ -821,9 +881,9 @@ export default class ActorSheet5e extends ActorSheet {
const li = event.currentTarget;
const set = this._filters[li.parentElement.dataset.filter];
const filter = li.dataset.filter;
if ( set.has(filter) ) set.delete(filter);
if (set.has(filter)) set.delete(filter);
else set.add(filter);
this.render();
return this.render();
}
/* -------------------------------------------- */
@ -838,8 +898,8 @@ export default class ActorSheet5e extends ActorSheet {
const a = event.currentTarget;
const label = a.parentElement.querySelector("label");
const choices = CONFIG.SW5E[a.dataset.options];
const options = { name: a.dataset.target, title: label.innerText, choices };
new TraitSelector(this.actor, options).render(true)
const options = {name: a.dataset.target, title: label.innerText, choices};
return new TraitSelector(this.actor, options).render(true);
}
/* -------------------------------------------- */
@ -847,15 +907,14 @@ export default class ActorSheet5e extends ActorSheet {
/** @override */
_getHeaderButtons() {
let buttons = super._getHeaderButtons();
// Add button to revert polymorph
if ( !this.actor.isPolymorphed || this.actor.isToken ) return buttons;
if (this.actor.isPolymorphed) {
buttons.unshift({
label: 'SW5E.PolymorphRestoreTransformation',
label: "SW5E.PolymorphRestoreTransformation",
class: "restore-transformation",
icon: "fas fa-backward",
onclick: ev => this.actor.revertOriginalForm()
onclick: () => this.actor.revertOriginalForm()
});
}
return buttons;
}
}

View file

@ -7,7 +7,6 @@ import Actor5e from "../../entity.js";
* @type {ActorSheet5e}
*/
export default class ActorSheet5eCharacter extends ActorSheet5e {
/**
* Define default rendering options for the NPC sheet
* @return {Object}
@ -37,7 +36,7 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
sheetData["resources"] = ["primary", "secondary", "tertiary"].reduce((arr, r) => {
const res = sheetData.data.resources[r] || {};
res.name = r;
res.placeholder = game.i18n.localize("SW5E.Resource"+r.titleCase());
res.placeholder = game.i18n.localize("SW5E.Resource" + r.titleCase());
if (res && res.value === 0) delete res.value;
if (res && res.max === 0) delete res.max;
return arr.concat([res]);
@ -45,10 +44,12 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
// Experience Tracking
sheetData["disableExperience"] = game.settings.get("sw5e", "disableExperienceTracking");
sheetData["classLabels"] = this.actor.itemTypes.class.map(c => c.name).join(", ");
sheetData["multiclassLabels"] = this.actor.itemTypes.class.map(c => {
return [c.data.data.archetype, c.name, c.data.data.levels].filterJoin(' ')
}).join(', ');
sheetData["classLabels"] = this.actor.itemTypes.class.map((c) => c.name).join(", ");
sheetData["multiclassLabels"] = this.actor.itemTypes.class
.map((c) => {
return [c.data.data.archetype, c.name, c.data.data.levels].filterJoin(" ");
})
.join(", ");
// Return data for rendering
return sheetData;
@ -61,23 +62,34 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
* @private
*/
_prepareItems(data) {
// Categorize items as inventory, powerbook, features, and classes
const inventory = {
weapon: { label: "SW5E.ItemTypeWeaponPl", items: [], dataset: {type: "weapon"} },
equipment: { label: "SW5E.ItemTypeEquipmentPl", items: [], dataset: {type: "equipment"} },
consumable: { label: "SW5E.ItemTypeConsumablePl", items: [], dataset: {type: "consumable"} },
tool: { label: "SW5E.ItemTypeToolPl", items: [], dataset: {type: "tool"} },
backpack: { label: "SW5E.ItemTypeContainerPl", items: [], dataset: {type: "backpack"} },
loot: { label: "SW5E.ItemTypeLootPl", items: [], dataset: {type: "loot"} }
weapon: {label: "SW5E.ItemTypeWeaponPl", items: [], dataset: {type: "weapon"}},
equipment: {label: "SW5E.ItemTypeEquipmentPl", items: [], dataset: {type: "equipment"}},
consumable: {label: "SW5E.ItemTypeConsumablePl", items: [], dataset: {type: "consumable"}},
tool: {label: "SW5E.ItemTypeToolPl", items: [], dataset: {type: "tool"}},
backpack: {label: "SW5E.ItemTypeContainerPl", items: [], dataset: {type: "backpack"}},
loot: {label: "SW5E.ItemTypeLootPl", items: [], dataset: {type: "loot"}}
};
// Partition items by category
let [items, powers, feats, classes, species, archetypes, classfeatures, backgrounds, fightingstyles, fightingmasteries, lightsaberforms] = data.items.reduce((arr, item) => {
let [
items,
powers,
feats,
classes,
species,
archetypes,
classfeatures,
backgrounds,
fightingstyles,
fightingmasteries,
lightsaberforms
] = data.items.reduce(
(arr, item) => {
// Item details
item.img = item.img || DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
item.img = item.img || CONST.DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && item.data.quantity !== 1;
item.attunement = {
[CONFIG.SW5E.attunementTypes.REQUIRED]: {
icon: "fa-sun",
@ -92,28 +104,35 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
}[item.data.attunement];
// Item usage
item.hasUses = item.data.uses && (item.data.uses.max > 0);
item.isOnCooldown = item.data.recharge && !!item.data.recharge.value && (item.data.recharge.charged === false);
item.isDepleted = item.isOnCooldown && (item.data.uses.per && (item.data.uses.value > 0));
item.hasTarget = !!item.data.target && !(["none",""].includes(item.data.target.type));
item.hasUses = item.data.uses && item.data.uses.max > 0;
item.isOnCooldown =
item.data.recharge && !!item.data.recharge.value && item.data.recharge.charged === false;
item.isDepleted = item.isOnCooldown && item.data.uses.per && item.data.uses.value > 0;
item.hasTarget = !!item.data.target && !["none", ""].includes(item.data.target.type);
// Item toggle state
this._prepareItemToggleState(item);
// Primary Class
if (item.type === "class")
item.isOriginalClass = item._id === this.actor.data.data.details.originalClass;
// Classify items into types
if ( item.type === "power" ) arr[1].push(item);
else if ( item.type === "feat" ) arr[2].push(item);
else if ( item.type === "class" ) arr[3].push(item);
else if ( item.type === "species" ) arr[4].push(item);
else if ( item.type === "archetype" ) arr[5].push(item);
else if ( item.type === "classfeature" ) arr[6].push(item);
else if ( item.type === "background" ) arr[7].push(item);
else if ( item.type === "fightingstyle" ) arr[8].push(item);
else if ( item.type === "fightingmastery" ) arr[9].push(item);
else if ( item.type === "lightsaberform" ) arr[10].push(item);
else if ( Object.keys(inventory).includes(item.type ) ) arr[0].push(item);
if (item.type === "power") arr[1].push(item);
else if (item.type === "feat") arr[2].push(item);
else if (item.type === "class") arr[3].push(item);
else if (item.type === "species") arr[4].push(item);
else if (item.type === "archetype") arr[5].push(item);
else if (item.type === "classfeature") arr[6].push(item);
else if (item.type === "background") arr[7].push(item);
else if (item.type === "fightingstyle") arr[8].push(item);
else if (item.type === "fightingmastery") arr[9].push(item);
else if (item.type === "lightsaberform") arr[10].push(item);
else if (Object.keys(inventory).includes(item.type)) arr[0].push(item);
return arr;
}, [[], [], [], [], [], [], [], [], [], [], []]);
},
[[], [], [], [], [], [], [], [], [], [], []]
);
// Apply active item filters
items = this._filterItems(items, this._filters.inventory);
@ -121,7 +140,7 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
feats = this._filterItems(feats, this._filters.features);
// Organize items
for ( let i of items ) {
for (let i of items) {
i.data.quantity = i.data.quantity || 0;
i.data.weight = i.data.weight || 0;
i.totalWeight = (i.data.quantity * i.data.weight).toNearest(0.1);
@ -130,28 +149,81 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
// Organize Powerbook and count the number of prepared powers (excluding always, at will, etc...)
const powerbook = this._preparePowerbook(data, powers);
const nPrepared = powers.filter(s => {
return (s.data.level > 0) && (s.data.preparation.mode === "prepared") && s.data.preparation.prepared;
const nPrepared = powers.filter((s) => {
return s.data.level > 0 && s.data.preparation.mode === "prepared" && s.data.preparation.prepared;
}).length;
// Organize Features
const features = {
classes: { label: "SW5E.ItemTypeClassPl", items: [], hasActions: false, dataset: {type: "class"}, isClass: true },
classfeatures: { label: "SW5E.ItemTypeClassFeats", items: [], hasActions: true, dataset: {type: "classfeature"}, isClassfeature: true },
archetype: { label: "SW5E.ItemTypeArchetype", items: [], hasActions: false, dataset: {type: "archetype"}, isArchetype: true },
species: { label: "SW5E.ItemTypeSpecies", items: [], hasActions: false, dataset: {type: "species"}, isSpecies: true },
background: { label: "SW5E.ItemTypeBackground", items: [], hasActions: false, dataset: {type: "background"}, isBackground: true },
fightingstyles: { label: "SW5E.ItemTypeFightingStylePl", items: [], hasActions: false, dataset: {type: "fightingstyle"}, isFightingstyle: true },
fightingmasteries: { label: "SW5E.ItemTypeFightingMasteryPl", items: [], hasActions: false, dataset: {type: "fightingmastery"}, isFightingmastery: true },
lightsaberforms: { label: "SW5E.ItemTypeLightsaberFormPl", items: [], hasActions: false, dataset: {type: "lightsaberform"}, isLightsaberform: true },
active: { label: "SW5E.FeatureActive", items: [], hasActions: true, dataset: {type: "feat", "activation.type": "action"} },
passive: { label: "SW5E.FeaturePassive", items: [], hasActions: false, dataset: {type: "feat"} }
classes: {
label: "SW5E.ItemTypeClassPl",
items: [],
hasActions: false,
dataset: {type: "class"},
isClass: true
},
classfeatures: {
label: "SW5E.ItemTypeClassFeats",
items: [],
hasActions: true,
dataset: {type: "classfeature"},
isClassfeature: true
},
archetype: {
label: "SW5E.ItemTypeArchetype",
items: [],
hasActions: false,
dataset: {type: "archetype"},
isArchetype: true
},
species: {
label: "SW5E.ItemTypeSpecies",
items: [],
hasActions: false,
dataset: {type: "species"},
isSpecies: true
},
background: {
label: "SW5E.ItemTypeBackground",
items: [],
hasActions: false,
dataset: {type: "background"},
isBackground: true
},
fightingstyles: {
label: "SW5E.ItemTypeFightingStylePl",
items: [],
hasActions: false,
dataset: {type: "fightingstyle"},
isFightingstyle: true
},
fightingmasteries: {
label: "SW5E.ItemTypeFightingMasteryPl",
items: [],
hasActions: false,
dataset: {type: "fightingmastery"},
isFightingmastery: true
},
lightsaberforms: {
label: "SW5E.ItemTypeLightsaberFormPl",
items: [],
hasActions: false,
dataset: {type: "lightsaberform"},
isLightsaberform: true
},
active: {
label: "SW5E.FeatureActive",
items: [],
hasActions: true,
dataset: {"type": "feat", "activation.type": "action"}
},
passive: {label: "SW5E.FeaturePassive", items: [], hasActions: false, dataset: {type: "feat"}}
};
for ( let f of feats ) {
if ( f.data.activation.type ) features.active.items.push(f);
for (let f of feats) {
if (f.data.activation.type) features.active.items.push(f);
else features.passive.items.push(f);
}
classes.sort((a, b) => b.levels - a.levels);
classes.sort((a, b) => b.data.levels - a.data.levels);
features.classes.items = classes;
features.classfeatures.items = classfeatures;
features.archetype.items = archetypes;
@ -180,12 +252,11 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
const isAlways = getProperty(item.data, "preparation.mode") === "always";
const isPrepared = getProperty(item.data, "preparation.prepared");
item.toggleClass = isPrepared ? "active" : "";
if ( isAlways ) item.toggleClass = "fixed";
if ( isAlways ) item.toggleTitle = CONFIG.SW5E.powerPreparationModes.always;
else if ( isPrepared ) item.toggleTitle = CONFIG.SW5E.powerPreparationModes.prepared;
if (isAlways) item.toggleClass = "fixed";
if (isAlways) item.toggleTitle = CONFIG.SW5E.powerPreparationModes.always;
else if (isPrepared) item.toggleTitle = CONFIG.SW5E.powerPreparationModes.prepared;
else item.toggleTitle = game.i18n.localize("SW5E.PowerUnprepared");
}
else {
} else {
const isActive = getProperty(item.data, "equipped");
item.toggleClass = isActive ? "active" : "";
item.toggleTitle = game.i18n.localize(isActive ? "SW5E.Equipped" : "SW5E.Unequipped");
@ -198,18 +269,18 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
/**
* Activate event listeners using the prepared sheet HTML
* @param html {HTML} The prepared HTML object ready to be rendered into the DOM
* @param html {jQuery} The prepared HTML object ready to be rendered into the DOM
*/
activateListeners(html) {
super.activateListeners(html);
if ( !this.options.editable ) return;
if (!this.isEditable) return;
// Item State Toggling
html.find('.item-toggle').click(this._onToggleItem.bind(this));
html.find(".item-toggle").click(this._onToggleItem.bind(this));
// Short and Long Rest
html.find('.short-rest').click(this._onShortRest.bind(this));
html.find('.long-rest').click(this._onLongRest.bind(this));
html.find(".short-rest").click(this._onShortRest.bind(this));
html.find(".long-rest").click(this._onLongRest.bind(this));
// Rollable sheet actions
html.find(".rollable[data-action]").click(this._onSheetAction.bind(this));
@ -225,7 +296,7 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
_onSheetAction(event) {
event.preventDefault();
const button = event.currentTarget;
switch( button.dataset.action ) {
switch (button.dataset.action) {
case "rollDeathSave":
return this.actor.rollDeathSave({event: event});
case "rollInitiative":
@ -243,7 +314,7 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
_onToggleItem(event) {
event.preventDefault();
const itemId = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.getOwnedItem(itemId);
const item = this.actor.items.get(itemId);
const attr = item.data.type === "power" ? "data.preparation.prepared" : "data.equipped";
return item.update({[attr]: !getProperty(item.data, attr)});
}
@ -278,14 +349,13 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
/** @override */
async _onDropItemCreate(itemData) {
// Increment the number of class levels a character instead of creating a new item
if ( itemData.type === "class" ) {
const cls = this.actor.itemTypes.class.find(c => c.name === itemData.name);
if (itemData.type === "class") {
const cls = this.actor.itemTypes.class.find((c) => c.name === itemData.name);
let priorLevel = cls?.data.data.levels ?? 0;
if ( !!cls ) {
if (!!cls) {
const next = Math.min(priorLevel + 1, 20 + priorLevel - this.actor.data.data.details.level);
if ( next > priorLevel ) {
if (next > priorLevel) {
itemData.levels = next;
return cls.update({"data.levels": next});
}
@ -293,6 +363,6 @@ export default class ActorSheet5eCharacter extends ActorSheet5e {
}
// Default drop handling if levels were not added
super._onDropItemCreate(itemData);
return super._onDropItemCreate(itemData);
}
}

View file

@ -6,7 +6,6 @@ import ActorSheet5e from "./base.js";
* @extends {ActorSheet5e}
*/
export default class ActorSheet5eNPC extends ActorSheet5e {
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
@ -18,32 +17,50 @@ export default class ActorSheet5eNPC extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
static unsupportedItemTypes = new Set(["class"]);
/* -------------------------------------------- */
/**
* Organize Owned Items for rendering the NPC sheet
* @private
*/
_prepareItems(data) {
// Categorize Items as Features and Powers
const features = {
weapons: { label: game.i18n.localize("SW5E.AttackPl"), items: [] , hasActions: true, dataset: {type: "weapon", "weapon-type": "natural"} },
actions: { label: game.i18n.localize("SW5E.ActionPl"), items: [] , hasActions: true, dataset: {type: "feat", "activation.type": "action"} },
passive: { label: game.i18n.localize("SW5E.Features"), items: [], dataset: {type: "feat"} },
equipment: { label: game.i18n.localize("SW5E.Inventory"), items: [], dataset: {type: "loot"}}
weapons: {
label: game.i18n.localize("SW5E.AttackPl"),
items: [],
hasActions: true,
dataset: {"type": "weapon", "weapon-type": "natural"}
},
actions: {
label: game.i18n.localize("SW5E.ActionPl"),
items: [],
hasActions: true,
dataset: {"type": "feat", "activation.type": "action"}
},
passive: {label: game.i18n.localize("SW5E.Features"), items: [], dataset: {type: "feat"}},
equipment: {label: game.i18n.localize("SW5E.Inventory"), items: [], dataset: {type: "loot"}}
};
// Start by classifying items into groups for rendering
let [powers, other] = data.items.reduce((arr, item) => {
item.img = item.img || DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && (item.data.quantity !== 1);
item.hasUses = item.data.uses && (item.data.uses.max > 0);
item.isOnCooldown = item.data.recharge && !!item.data.recharge.value && (item.data.recharge.charged === false);
item.isDepleted = item.isOnCooldown && (item.data.uses.per && (item.data.uses.value > 0));
item.hasTarget = !!item.data.target && !(["none",""].includes(item.data.target.type));
if ( item.type === "power" ) arr[0].push(item);
let [powers, other] = data.items.reduce(
(arr, item) => {
item.img = item.img || CONST.DEFAULT_TOKEN;
item.isStack = Number.isNumeric(item.data.quantity) && item.data.quantity !== 1;
item.hasUses = item.data.uses && item.data.uses.max > 0;
item.isOnCooldown =
item.data.recharge && !!item.data.recharge.value && item.data.recharge.charged === false;
item.isDepleted = item.isOnCooldown && item.data.uses.per && item.data.uses.value > 0;
item.hasTarget = !!item.data.target && !["none", ""].includes(item.data.target.type);
if (item.type === "power") arr[0].push(item);
else arr[1].push(item);
return arr;
}, [[], []]);
},
[[], []]
);
// Apply item filters
powers = this._filterItems(powers, this._filters.powerbook);
@ -53,13 +70,12 @@ export default class ActorSheet5eNPC extends ActorSheet5e {
const powerbook = this._preparePowerbook(data, powers);
// Organize Features
for ( let item of other ) {
if ( item.type === "weapon" ) features.weapons.items.push(item);
else if ( item.type === "feat" ) {
if ( item.data.activation.type ) features.actions.items.push(item);
for (let item of other) {
if (item.type === "weapon") features.weapons.items.push(item);
else if (item.type === "feat") {
if (item.data.activation.type) features.actions.items.push(item);
else features.passive.items.push(item);
}
else features.equipment.items.push(item);
} else features.equipment.items.push(item);
}
// Assign and return
@ -67,17 +83,19 @@ export default class ActorSheet5eNPC extends ActorSheet5e {
data.powerbook = powerbook;
}
/* -------------------------------------------- */
/** @override */
getData() {
const data = super.getData();
/** @inheritdoc */
getData(options) {
const data = super.getData(options);
// Challenge Rating
const cr = parseFloat(data.data.details.cr || 0);
const crLabels = {0: "0", 0.125: "1/8", 0.25: "1/4", 0.5: "1/2"};
data.labels["cr"] = cr >= 1 ? String(cr) : crLabels[cr] || 1;
// Creature Type
data.labels["type"] = this.actor.labels.creatureType;
return data;
}
@ -86,17 +104,16 @@ export default class ActorSheet5eNPC extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
_updateObject(event, formData) {
async _updateObject(event, formData) {
// Format NPC Challenge Rating
const crs = {"1/8": 0.125, "1/4": 0.25, "1/2": 0.5};
let crv = "data.details.cr";
let cr = formData[crv];
cr = crs[cr] || parseFloat(cr);
if ( cr ) formData[crv] = cr < 1 ? cr : parseInt(cr);
if (cr) formData[crv] = cr < 1 ? cr : parseInt(cr);
// Parent ActorSheet update steps
super._updateObject(event, formData);
return super._updateObject(event, formData);
}
/* -------------------------------------------- */
@ -119,7 +136,7 @@ export default class ActorSheet5eNPC extends ActorSheet5e {
_onRollHPFormula(event) {
event.preventDefault();
const formula = this.actor.data.data.attributes.hp.formula;
if ( !formula ) return;
if (!formula) return;
const hp = new Roll(formula).roll().total;
AudioHelper.play({src: CONFIG.sounds.dice});
this.actor.update({"data.attributes.hp.value": hp, "data.attributes.hp.max": hp});

View file

@ -20,12 +20,17 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
static unsupportedItemTypes = new Set(["class"]);
/* -------------------------------------------- */
/**
* Creates a new cargo entry for a vehicle Actor.
*/
static get newCargo() {
return {
name: '',
name: "",
quantity: 1
};
}
@ -40,7 +45,6 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
* @private
*/
_computeEncumbrance(totalWeight, actorData) {
// Compute currency weight
const totalCoins = Object.values(actorData.data.currency).reduce((acc, denom) => acc + denom, 0);
totalWeight += totalCoins / CONFIG.SW5E.encumbrance.currencyPerWeight;
@ -57,7 +61,7 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
_getMovementSpeed(actorData, largestPrimary=true) {
_getMovementSpeed(actorData, largestPrimary = true) {
return super._getMovementSpeed(actorData, largestPrimary);
}
@ -69,25 +73,24 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
* @private
*/
_prepareCrewedItem(item) {
// Determine crewed status
const isCrewed = item.data.crewed;
item.toggleClass = isCrewed ? 'active' : '';
item.toggleTitle = game.i18n.localize(`SW5E.${isCrewed ? 'Crewed' : 'Uncrewed'}`);
item.toggleClass = isCrewed ? "active" : "";
item.toggleTitle = game.i18n.localize(`SW5E.${isCrewed ? "Crewed" : "Uncrewed"}`);
// Handle crew actions
if (item.type === 'feat' && item.data.activation.type === 'crew') {
if (item.type === "feat" && item.data.activation.type === "crew") {
item.crew = item.data.activation.cost;
item.cover = game.i18n.localize(`SW5E.${item.data.cover ? 'CoverTotal' : 'None'}`);
if (item.data.cover === .5) item.cover = '½';
else if (item.data.cover === .75) item.cover = '¾';
else if (item.data.cover === null) item.cover = '—';
if (item.crew < 1 || item.crew === null) item.crew = '—';
item.cover = game.i18n.localize(`SW5E.${item.data.cover ? "CoverTotal" : "None"}`);
if (item.data.cover === 0.5) item.cover = "½";
else if (item.data.cover === 0.75) item.cover = "¾";
else if (item.data.cover === null) item.cover = "—";
if (item.crew < 1 || item.crew === null) item.crew = "—";
}
// Prepare vehicle weapons
if (item.type === 'equipment' || item.type === 'weapon') {
item.threshold = item.data.hp.dt ? item.data.hp.dt : '—';
if (item.type === "equipment" || item.type === "weapon") {
item.threshold = item.data.hp.dt ? item.data.hp.dt : "—";
}
}
@ -98,132 +101,162 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
* @private
*/
_prepareItems(data) {
const cargoColumns = [{
label: game.i18n.localize('SW5E.Quantity'),
css: 'item-qty',
property: 'quantity',
editable: 'Number'
}];
const cargoColumns = [
{
label: game.i18n.localize("SW5E.Quantity"),
css: "item-qty",
property: "quantity",
editable: "Number"
}
];
const equipmentColumns = [{
label: game.i18n.localize('SW5E.Quantity'),
css: 'item-qty',
property: 'data.quantity'
}, {
label: game.i18n.localize('SW5E.AC'),
css: 'item-ac',
property: 'data.armor.value'
}, {
label: game.i18n.localize('SW5E.HP'),
css: 'item-hp',
property: 'data.hp.value',
editable: 'Number'
}, {
label: game.i18n.localize('SW5E.Threshold'),
css: 'item-threshold',
property: 'threshold'
}];
const equipmentColumns = [
{
label: game.i18n.localize("SW5E.Quantity"),
css: "item-qty",
property: "data.quantity"
},
{
label: game.i18n.localize("SW5E.AC"),
css: "item-ac",
property: "data.armor.value"
},
{
label: game.i18n.localize("SW5E.HP"),
css: "item-hp",
property: "data.hp.value",
editable: "Number"
},
{
label: game.i18n.localize("SW5E.Threshold"),
css: "item-threshold",
property: "threshold"
}
];
const features = {
actions: {
label: game.i18n.localize('SW5E.ActionPl'),
label: game.i18n.localize("SW5E.ActionPl"),
items: [],
crewable: true,
dataset: {type: 'feat', 'activation.type': 'crew'},
columns: [{
label: game.i18n.localize('SW5E.VehicleCrew'),
css: 'item-crew',
property: 'crew'
}, {
label: game.i18n.localize('SW5E.Cover'),
css: 'item-cover',
property: 'cover'
}]
dataset: {"type": "feat", "activation.type": "crew"},
columns: [
{
label: game.i18n.localize("SW5E.VehicleCrew"),
css: "item-crew",
property: "crew"
},
{
label: game.i18n.localize("SW5E.Cover"),
css: "item-cover",
property: "cover"
}
]
},
equipment: {
label: game.i18n.localize('SW5E.ItemTypeEquipment'),
label: game.i18n.localize("SW5E.ItemTypeEquipment"),
items: [],
crewable: true,
dataset: {type: 'equipment', 'armor.type': 'vehicle'},
dataset: {"type": "equipment", "armor.type": "vehicle"},
columns: equipmentColumns
},
passive: {
label: game.i18n.localize('SW5E.Features'),
label: game.i18n.localize("SW5E.Features"),
items: [],
dataset: {type: 'feat'}
dataset: {type: "feat"}
},
reactions: {
label: game.i18n.localize('SW5E.ReactionPl'),
label: game.i18n.localize("SW5E.ReactionPl"),
items: [],
dataset: {type: 'feat', 'activation.type': 'reaction'}
dataset: {"type": "feat", "activation.type": "reaction"}
},
weapons: {
label: game.i18n.localize('SW5E.ItemTypeWeaponPl'),
label: game.i18n.localize("SW5E.ItemTypeWeaponPl"),
items: [],
crewable: true,
dataset: {type: 'weapon', 'weapon-type': 'siege'},
dataset: {"type": "weapon", "weapon-type": "siege"},
columns: equipmentColumns
}
};
const cargo = {
crew: {
label: game.i18n.localize('SW5E.VehicleCrew'),
label: game.i18n.localize("SW5E.VehicleCrew"),
items: data.data.cargo.crew,
css: 'cargo-row crew',
css: "cargo-row crew",
editableName: true,
dataset: {type: 'crew'},
dataset: {type: "crew"},
columns: cargoColumns
},
passengers: {
label: game.i18n.localize('SW5E.VehiclePassengers'),
label: game.i18n.localize("SW5E.VehiclePassengers"),
items: data.data.cargo.passengers,
css: 'cargo-row passengers',
css: "cargo-row passengers",
editableName: true,
dataset: {type: 'passengers'},
dataset: {type: "passengers"},
columns: cargoColumns
},
cargo: {
label: game.i18n.localize('SW5E.VehicleCargo'),
label: game.i18n.localize("SW5E.VehicleCargo"),
items: [],
dataset: {type: 'loot'},
columns: [{
label: game.i18n.localize('SW5E.Quantity'),
css: 'item-qty',
property: 'data.quantity',
editable: 'Number'
}, {
label: game.i18n.localize('SW5E.Price'),
css: 'item-price',
property: 'data.price',
editable: 'Number'
}, {
label: game.i18n.localize('SW5E.Weight'),
css: 'item-weight',
property: 'data.weight',
editable: 'Number'
}]
dataset: {type: "loot"},
columns: [
{
label: game.i18n.localize("SW5E.Quantity"),
css: "item-qty",
property: "data.quantity",
editable: "Number"
},
{
label: game.i18n.localize("SW5E.Price"),
css: "item-price",
property: "data.price",
editable: "Number"
},
{
label: game.i18n.localize("SW5E.Weight"),
css: "item-weight",
property: "data.weight",
editable: "Number"
}
]
}
};
// Classify items owned by the vehicle and compute total cargo weight
let totalWeight = 0;
for (const item of data.items) {
this._prepareCrewedItem(item);
if (item.type === 'weapon') features.weapons.items.push(item);
else if (item.type === 'equipment') features.equipment.items.push(item);
else if (item.type === 'loot') {
// Handle cargo explicitly
const isCargo = item.flags.sw5e?.vehicleCargo === true;
if (isCargo) {
totalWeight += (item.data.weight || 0) * item.data.quantity;
cargo.cargo.items.push(item);
continue;
}
// Handle non-cargo item types
switch (item.type) {
case "weapon":
features.weapons.items.push(item);
break;
case "equipment":
features.equipment.items.push(item);
break;
case "feat":
if (!item.data.activation.type || item.data.activation.type === "none")
features.passive.items.push(item);
else if (item.data.activation.type === "reaction") features.reactions.items.push(item);
else features.actions.items.push(item);
break;
default:
totalWeight += (item.data.weight || 0) * item.data.quantity;
cargo.cargo.items.push(item);
}
else if (item.type === 'feat') {
if (!item.data.activation.type || item.data.activation.type === 'none') {
features.passive.items.push(item);
}
else if (item.data.activation.type === 'reaction') features.reactions.items.push(item);
else features.actions.items.push(item);
}
}
// Update the rendering context data
data.features = Object.values(features);
data.cargo = Object.values(cargo);
data.data.attributes.encumbrance = this._computeEncumbrance(totalWeight, data);
@ -236,23 +269,23 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
/** @override */
activateListeners(html) {
super.activateListeners(html);
if (!this.options.editable) return;
if (!this.isEditable) return;
html.find('.item-toggle').click(this._onToggleItem.bind(this));
html.find('.item-hp input')
.click(evt => evt.target.select())
html.find(".item-toggle").click(this._onToggleItem.bind(this));
html.find(".item-hp input")
.click((evt) => evt.target.select())
.change(this._onHPChange.bind(this));
html.find('.item:not(.cargo-row) input[data-property]')
.click(evt => evt.target.select())
html.find(".item:not(.cargo-row) input[data-property]")
.click((evt) => evt.target.select())
.change(this._onEditInSheet.bind(this));
html.find('.cargo-row input')
.click(evt => evt.target.select())
html.find(".cargo-row input")
.click((evt) => evt.target.select())
.change(this._onCargoRowChange.bind(this));
if (this.actor.data.data.attributes.actions.stations) {
html.find('.counter.actions, .counter.action-thresholds').hide();
html.find(".counter.actions, .counter.action-thresholds").hide();
}
}
@ -267,20 +300,20 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
_onCargoRowChange(event) {
event.preventDefault();
const target = event.currentTarget;
const row = target.closest('.item');
const row = target.closest(".item");
const idx = Number(row.dataset.itemId);
const property = row.classList.contains('crew') ? 'crew' : 'passengers';
const property = row.classList.contains("crew") ? "crew" : "passengers";
// Get the cargo entry
const cargo = duplicate(this.actor.data.data.cargo[property]);
const cargo = foundry.utils.deepClone(this.actor.data.data.cargo[property]);
const entry = cargo[idx];
if (!entry) return null;
// Update the cargo value
const key = target.dataset.property || 'name';
const key = target.dataset.property || "name";
const type = target.dataset.dtype;
let value = target.value;
if (type === 'Number') value = Number(value);
if (type === "Number") value = Number(value);
entry[key] = value;
// Perform the Actor update
@ -297,14 +330,18 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
*/
_onEditInSheet(event) {
event.preventDefault();
const itemID = event.currentTarget.closest('.item').dataset.itemId;
const itemID = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.items.get(itemID);
const property = event.currentTarget.dataset.property;
const type = event.currentTarget.dataset.dtype;
let value = event.currentTarget.value;
switch (type) {
case 'Number': value = parseInt(value); break;
case 'Boolean': value = value === 'true'; break;
case "Number":
value = parseInt(value);
break;
case "Boolean":
value = value === "true";
break;
}
return item.update({[`${property}`]: value});
}
@ -321,8 +358,8 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
event.preventDefault();
const target = event.currentTarget;
const type = target.dataset.type;
if (type === 'crew' || type === 'passengers') {
const cargo = duplicate(this.actor.data.data.cargo[type]);
if (type === "crew" || type === "passengers") {
const cargo = foundry.utils.deepClone(this.actor.data.data.cargo[type]);
cargo.push(this.constructor.newCargo);
return this.actor.update({[`data.cargo.${type}`]: cargo});
}
@ -339,11 +376,11 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
*/
_onItemDelete(event) {
event.preventDefault();
const row = event.currentTarget.closest('.item');
if (row.classList.contains('cargo-row')) {
const row = event.currentTarget.closest(".item");
if (row.classList.contains("cargo-row")) {
const idx = Number(row.dataset.itemId);
const type = row.classList.contains('crew') ? 'crew' : 'passengers';
const cargo = duplicate(this.actor.data.data.cargo[type]).filter((_, i) => i !== idx);
const type = row.classList.contains("crew") ? "crew" : "passengers";
const cargo = foundry.utils.deepClone(this.actor.data.data.cargo[type]).filter((_, i) => i !== idx);
return this.actor.update({[`data.cargo.${type}`]: cargo});
}
@ -352,6 +389,16 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
/* -------------------------------------------- */
/** @override */
async _onDropItemCreate(itemData) {
const cargoTypes = ["weapon", "equipment", "consumable", "tool", "loot", "backpack"];
const isCargo = cargoTypes.includes(itemData.type) && this._tabs[0].active === "cargo";
foundry.utils.setProperty(itemData, "flags.sw5e.vehicleCargo", isCargo);
return super._onDropItemCreate(itemData);
}
/* -------------------------------------------- */
/**
* Special handling for editing HP to clamp it within appropriate range.
* @param event {Event}
@ -360,11 +407,11 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
*/
_onHPChange(event) {
event.preventDefault();
const itemID = event.currentTarget.closest('.item').dataset.itemId;
const itemID = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.items.get(itemID);
const hp = Math.clamped(0, parseInt(event.currentTarget.value), item.data.data.hp.max);
event.currentTarget.value = hp;
return item.update({'data.hp.value': hp});
return item.update({"data.hp.value": hp});
}
/* -------------------------------------------- */
@ -377,9 +424,9 @@ export default class ActorSheet5eVehicle extends ActorSheet5e {
*/
_onToggleItem(event) {
event.preventDefault();
const itemID = event.currentTarget.closest('.item').dataset.itemId;
const itemID = event.currentTarget.closest(".item").dataset.itemId;
const item = this.actor.items.get(itemID);
const crewed = !!item.data.data.crewed;
return item.update({'data.crewed': !crewed});
return item.update({"data.crewed": !crewed});
}
};
}

View file

@ -3,7 +3,7 @@
* @type {Dialog}
*/
export default class AbilityUseDialog extends Dialog {
constructor(item, dialogData={}, options={}) {
constructor(item, dialogData = {}, options = {}) {
super(dialogData, options);
this.options.classes = ["sw5e", "dialog"];
@ -25,7 +25,7 @@ export default class AbilityUseDialog extends Dialog {
* @return {Promise}
*/
static async create(item) {
if ( !item.isOwned ) throw new Error("You cannot display an ability usage dialog for an unowned item");
if (!item.isOwned) throw new Error("You cannot display an ability usage dialog for an unowned item");
// Prepare data
const actorData = item.actor.data.data;
@ -39,17 +39,20 @@ export default class AbilityUseDialog extends Dialog {
// Prepare dialog form data
const data = {
item: item.data,
title: game.i18n.format("SW5E.AbilityUseHint", item.data),
title: game.i18n.format("SW5E.AbilityUseHint", {
type: game.i18n.localize(`SW5E.ItemType${item.type.capitalize()}`),
name: item.name
}),
note: this._getAbilityUseNote(item.data, uses, recharge),
consumePowerSlot: false,
consumeRecharge: recharges,
consumeResource: !!itemData.consume.target,
consumeUses: uses.max,
consumeUses: uses.per && uses.max > 0,
canUse: recharges ? recharge.charged : sufficientUses,
createTemplate: game.user.can("TEMPLATE_CREATE") && item.hasAreaTarget,
errors: []
};
if ( item.data.type === "power" ) this._getPowerData(actorData, itemData, data);
if (item.data.type === "power") this._getPowerData(actorData, itemData, data);
// Render the ability usage template
const html = await renderTemplate("systems/sw5e/templates/apps/ability-use.html", data);
@ -59,13 +62,13 @@ export default class AbilityUseDialog extends Dialog {
const label = game.i18n.localize("SW5E.AbilityUse" + (data.isPower ? "Cast" : "Use"));
return new Promise((resolve) => {
const dlg = new this(item, {
title: `${item.name}: Usage Configuration`,
title: `${item.name}: ${game.i18n.localize("SW5E.AbilityUseConfig")}`,
content: html,
buttons: {
use: {
icon: `<i class="fas ${icon}"></i>`,
label: label,
callback: html => {
callback: (html) => {
const fd = new FormDataExtended(html[0].querySelector("form"));
resolve(fd.toObject());
}
@ -87,14 +90,13 @@ export default class AbilityUseDialog extends Dialog {
* @private
*/
static _getPowerData(actorData, itemData, data) {
// Determine whether the power may be up-cast
const lvl = itemData.level;
const consumePowerSlot = (lvl > 0) && CONFIG.SW5E.powerUpcastModes.includes(itemData.preparation.mode);
const consumePowerSlot = lvl > 0 && CONFIG.SW5E.powerUpcastModes.includes(itemData.preparation.mode);
// If can't upcast, return early and don't bother calculating available power slots
if (!consumePowerSlot) {
mergeObject(data, { isPower: true, consumePowerSlot });
mergeObject(data, {isPower: true, consumePowerSlot});
return;
}
@ -102,74 +104,78 @@ export default class AbilityUseDialog extends Dialog {
let lmax = 0;
let points;
let powerType;
switch (itemData.school){
switch (itemData.school) {
case "lgt":
case "uni":
case "drk": {
powerType = "force"
powerType = "force";
points = actorData.attributes.force.points.value + actorData.attributes.force.points.temp;
break;
}
case "tec": {
powerType = "tech"
powerType = "tech";
points = actorData.attributes.tech.points.value + actorData.attributes.tech.points.temp;
break;
}
}
// eliminate point usage for innate casters
if (actorData.attributes.powercasting === 'innate') points = 999;
if (actorData.attributes.powercasting === "innate") points = 999;
let powerLevels
if (powerType === "force"){
powerLevels = Array.fromRange(10).reduce((arr, i) => {
if ( i < lvl ) return arr;
let powerLevels;
if (powerType === "force") {
powerLevels = Array.fromRange(10)
.reduce((arr, i) => {
if (i < lvl) return arr;
const label = CONFIG.SW5E.powerLevels[i];
const l = actorData.powers["power"+i] || {fmax: 0, foverride: null};
const l = actorData.powers["power" + i] || {fmax: 0, foverride: null};
let max = parseInt(l.foverride || l.fmax || 0);
let slots = Math.clamped(parseInt(l.fvalue || 0), 0, max);
if ( max > 0 ) lmax = i;
if ((max > 0) && (slots > 0) && (points > i)){
if (max > 0) lmax = i;
if (max > 0 && slots > 0 && points > i) {
arr.push({
level: i,
label: i > 0 ? game.i18n.format('SW5E.PowerLevelSlot', {level: label, n: slots}) : label,
label: i > 0 ? game.i18n.format("SW5E.PowerLevelSlot", {level: label, n: slots}) : label,
canCast: max > 0,
hasSlots: slots > 0
});
}
return arr;
}, []).filter(sl => sl.level <= lmax);
}else if (powerType === "tech"){
powerLevels = Array.fromRange(10).reduce((arr, i) => {
if ( i < lvl ) return arr;
}, [])
.filter((sl) => sl.level <= lmax);
} else if (powerType === "tech") {
powerLevels = Array.fromRange(10)
.reduce((arr, i) => {
if (i < lvl) return arr;
const label = CONFIG.SW5E.powerLevels[i];
const l = actorData.powers["power"+i] || {tmax: 0, toverride: null};
const l = actorData.powers["power" + i] || {tmax: 0, toverride: null};
let max = parseInt(l.override || l.tmax || 0);
let slots = Math.clamped(parseInt(l.tvalue || 0), 0, max);
if ( max > 0 ) lmax = i;
if ((max > 0) && (slots > 0) && (points > i)){
if (max > 0) lmax = i;
if (max > 0 && slots > 0 && points > i) {
arr.push({
level: i,
label: i > 0 ? game.i18n.format('SW5E.PowerLevelSlot', {level: label, n: slots}) : label,
label: i > 0 ? game.i18n.format("SW5E.PowerLevelSlot", {level: label, n: slots}) : label,
canCast: max > 0,
hasSlots: slots > 0
});
}
return arr;
}, []).filter(sl => sl.level <= lmax);
}, [])
.filter((sl) => sl.level <= lmax);
}
const canCast = powerLevels.some(l => l.hasSlots);
if ( !canCast ) data.errors.push(game.i18n.format("SW5E.PowerCastNoSlots", {
const canCast = powerLevels.some((l) => l.hasSlots);
if (!canCast)
data.errors.push(
game.i18n.format("SW5E.PowerCastNoSlots", {
level: CONFIG.SW5E.powerLevels[lvl],
name: data.item.name
}));
})
);
// Merge power casting data
return mergeObject(data, { isPower: true, consumePowerSlot, powerLevels });
return foundry.utils.mergeObject(data, {isPower: true, consumePowerSlot, powerLevels});
}
/* -------------------------------------------- */
@ -179,29 +185,28 @@ export default class AbilityUseDialog extends Dialog {
* @private
*/
static _getAbilityUseNote(item, uses, recharge) {
// Zero quantity
const quantity = item.data.quantity;
if ( quantity <= 0 ) return game.i18n.localize("SW5E.AbilityUseUnavailableHint");
if (quantity <= 0) return game.i18n.localize("SW5E.AbilityUseUnavailableHint");
// Abilities which use Recharge
if ( !!recharge.value ) {
if (!!recharge.value) {
return game.i18n.format(recharge.charged ? "SW5E.AbilityUseChargedHint" : "SW5E.AbilityUseRechargeHint", {
type: item.type,
})
type: game.i18n.localize(`SW5E.ItemType${item.type.capitalize()}`)
});
}
// Does not use any resource
if ( !uses.per || !uses.max ) return "";
if (!uses.per || !uses.max) return "";
// Consumables
if ( item.type === "consumable" ) {
if (item.type === "consumable") {
let str = "SW5E.AbilityUseNormalHint";
if ( uses.value > 1 ) str = "SW5E.AbilityUseConsumableChargeHint";
else if ( item.data.quantity === 1 && uses.autoDestroy ) str = "SW5E.AbilityUseConsumableDestroyHint";
else if ( item.data.quantity > 1 ) str = "SW5E.AbilityUseConsumableQuantityHint";
if (uses.value > 1) str = "SW5E.AbilityUseConsumableChargeHint";
else if (item.data.quantity === 1 && uses.autoDestroy) str = "SW5E.AbilityUseConsumableDestroyHint";
else if (item.data.quantity > 1) str = "SW5E.AbilityUseConsumableQuantityHint";
return game.i18n.format(str, {
type: item.data.consumableType,
type: game.i18n.localize(`SW5E.Consumable${item.data.consumableType.capitalize()}`),
value: uses.value,
quantity: item.data.quantity,
max: uses.max,
@ -212,17 +217,11 @@ export default class AbilityUseDialog extends Dialog {
// Other Items
else {
return game.i18n.format("SW5E.AbilityUseNormalHint", {
type: item.type,
type: game.i18n.localize(`SW5E.ItemType${item.type.capitalize()}`),
value: uses.value,
max: uses.max,
per: CONFIG.SW5E.limitedUsePeriods[uses.per]
});
}
}
/* -------------------------------------------- */
static _handleSubmit(formData, item) {
}
}

View file

@ -1,11 +1,10 @@
/**
* An application class which provides advanced configuration for special character flags which modify an Actor
* @implements {BaseEntitySheet}
* @implements {DocumentSheet}
*/
export default class ActorSheetFlags extends BaseEntitySheet {
export default class ActorSheetFlags extends DocumentSheet {
static get defaultOptions() {
const options = super.defaultOptions;
return mergeObject(options, {
return foundry.utils.mergeObject(super.defaultOptions, {
id: "actor-flags",
classes: ["sw5e"],
template: "systems/sw5e/templates/apps/actor-flags.html",
@ -18,7 +17,7 @@ export default class ActorSheetFlags extends BaseEntitySheet {
/** @override */
get title() {
return `${game.i18n.localize('SW5E.FlagsTitle')}: ${this.object.name}`;
return `${game.i18n.localize("SW5E.FlagsTitle")}: ${this.object.name}`;
}
/* -------------------------------------------- */
@ -27,6 +26,7 @@ export default class ActorSheetFlags extends BaseEntitySheet {
getData() {
const data = {};
data.actor = this.object;
data.classes = this._getClasses();
data.flags = this._getFlags();
data.bonuses = this._getBonuses();
return data;
@ -34,20 +34,38 @@ export default class ActorSheetFlags extends BaseEntitySheet {
/* -------------------------------------------- */
/**
* Prepare an object of sorted classes.
* @return {object}
* @private
*/
_getClasses() {
const classes = this.object.items.filter((i) => i.type === "class");
return classes
.sort((a, b) => a.name.localeCompare(b.name))
.reduce((obj, i) => {
obj[i.id] = i.name;
return obj;
}, {});
}
/* -------------------------------------------- */
/**
* Prepare an object of flags data which groups flags by section
* Add some additional data for rendering
* @return {object}
* @private
*/
_getFlags() {
const flags = {};
const baseData = this.entity._data;
for ( let [k, v] of Object.entries(CONFIG.SW5E.characterFlags) ) {
if ( !flags.hasOwnProperty(v.section) ) flags[v.section] = {};
let flag = duplicate(v);
const baseData = this.document.toJSON();
for (let [k, v] of Object.entries(CONFIG.SW5E.characterFlags)) {
if (!flags.hasOwnProperty(v.section)) flags[v.section] = {};
let flag = foundry.utils.deepClone(v);
flag.type = v.type.name;
flag.isCheckbox = v.type === Boolean;
flag.isSelect = v.hasOwnProperty('choices');
flag.isSelect = v.hasOwnProperty("choices");
flag.value = getProperty(baseData.flags, `sw5e.${k}`);
flags[v.section][`flags.sw5e.${k}`] = flag;
}
@ -80,7 +98,7 @@ export default class ActorSheetFlags extends BaseEntitySheet {
{name: "data.bonuses.power.forceUnivDC", label: "SW5E.BonusForceUnivPowerDC"},
{name: "data.bonuses.power.techDC", label: "SW5E.BonusTechPowerDC"}
];
for ( let b of bonuses ) {
for (let b of bonuses) {
b.value = getProperty(this.object._data, b.name) || "";
}
return bonuses;
@ -97,11 +115,11 @@ export default class ActorSheetFlags extends BaseEntitySheet {
let unset = false;
const flags = updateData.flags.sw5e;
//clone flags to dnd5e for module compatability
updateData.flags.dnd5e = updateData.flags.sw5e
for ( let [k, v] of Object.entries(flags) ) {
if ( [undefined, null, "", false, 0].includes(v) ) {
updateData.flags.dnd5e = updateData.flags.sw5e;
for (let [k, v] of Object.entries(flags)) {
if ([undefined, null, "", false, 0].includes(v)) {
delete flags[k];
if ( hasProperty(actor._data.flags, `sw5e.${k}`) ) {
if (hasProperty(actor._data.flags, `sw5e.${k}`)) {
unset = true;
flags[`-=${k}`] = null;
}
@ -109,8 +127,8 @@ export default class ActorSheetFlags extends BaseEntitySheet {
}
// Clear any bonuses which are whitespace only
for ( let b of Object.values(updateData.data.bonuses ) ) {
for ( let [k, v] of Object.entries(b) ) {
for (let b of Object.values(updateData.data.bonuses)) {
for (let [k, v] of Object.entries(b)) {
b[k] = v.trim();
}
}

111
module/apps/actor-type.js Normal file
View file

@ -0,0 +1,111 @@
import Actor5e from "../actor/entity.js";
/**
* A specialized form used to select from a checklist of attributes, traits, or properties
* @extends {FormApplication}
*/
export default class ActorTypeConfig extends FormApplication {
/** @inheritdoc */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["sw5e", "actor-type", "trait-selector"],
template: "systems/sw5e/templates/apps/actor-type.html",
title: "SW5E.CreatureTypeTitle",
width: 280,
height: "auto",
choices: {},
allowCustom: true,
minimum: 0,
maximum: null
});
}
/* -------------------------------------------- */
/** @override */
get id() {
return `actor-type-${this.object.id}`;
}
/* -------------------------------------------- */
/** @override */
getData(options) {
// Get current value or new default
let attr = foundry.utils.getProperty(this.object.data.data, "details.type");
if (foundry.utils.getType(attr) !== "Object")
attr = {
value: attr in CONFIG.SW5E.creatureTypes ? attr : "humanoid",
subtype: "",
swarm: "",
custom: ""
};
// Populate choices
const types = {};
for (let [k, v] of Object.entries(CONFIG.SW5E.creatureTypes)) {
types[k] = {
label: game.i18n.localize(v),
chosen: attr.value === k
};
}
// Return data for rendering
return {
types: types,
custom: {
value: attr.custom,
label: game.i18n.localize("SW5E.CreatureTypeSelectorCustom"),
chosen: attr.value === "custom"
},
subtype: attr.subtype,
swarm: attr.swarm,
sizes: Array.from(Object.entries(CONFIG.SW5E.actorSizes))
.reverse()
.reduce((obj, e) => {
obj[e[0]] = e[1];
return obj;
}, {}),
preview: Actor5e.formatCreatureType(attr) || ""
};
}
/* -------------------------------------------- */
/** @override */
async _updateObject(event, formData) {
const typeObject = foundry.utils.expandObject(formData);
return this.object.update({"data.details.type": typeObject});
}
/* -------------------------------------------- */
/* Event Listeners and Handlers */
/* -------------------------------------------- */
/** @inheritdoc */
activateListeners(html) {
super.activateListeners(html);
html.find("input[name='custom']").focusin(this._onCustomFieldFocused.bind(this));
}
/* -------------------------------------------- */
/** @inheritdoc */
_onChangeInput(event) {
super._onChangeInput(event);
const typeObject = foundry.utils.expandObject(this._getSubmitData());
this.form["preview"].value = Actor5e.formatCreatureType(typeObject) || "—";
}
/* -------------------------------------------- */
/**
* Select the custom radio button when the custom text field is focused.
* @param {FocusEvent} event The original focusin event
* @private
*/
_onCustomFieldFocused(event) {
this.form.querySelector("input[name='value'][value='custom']").checked = true;
this._onChangeInput(event);
}
}

View file

@ -0,0 +1,92 @@
/**
* A simple form to set actor hit dice amounts
* @implements {DocumentSheet}
*/
export default class ActorHitDiceConfig extends DocumentSheet {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["sw5e", "hd-config", "dialog"],
template: "systems/sw5e/templates/apps/hit-dice-config.html",
width: 360,
height: "auto"
});
}
/* -------------------------------------------- */
/** @override */
get title() {
return `${game.i18n.localize("SW5E.HitDiceConfig")}: ${this.object.name}`;
}
/* -------------------------------------------- */
/** @override */
getData(options) {
return {
classes: this.object.items
.reduce((classes, item) => {
if (item.data.type === "class") {
// Add the appropriate data only if this item is a "class"
classes.push({
classItemId: item.data._id,
name: item.data.name,
diceDenom: item.data.data.hitDice,
currentHitDice: item.data.data.levels - item.data.data.hitDiceUsed,
maxHitDice: item.data.data.levels,
canRoll: item.data.data.levels - item.data.data.hitDiceUsed > 0
});
}
return classes;
}, [])
.sort((a, b) => parseInt(b.diceDenom.slice(1)) - parseInt(a.diceDenom.slice(1)))
};
}
/* -------------------------------------------- */
/** @override */
activateListeners(html) {
super.activateListeners(html);
// Hook up -/+ buttons to adjust the current value in the form
html.find("button.increment,button.decrement").click((event) => {
const button = event.currentTarget;
const current = button.parentElement.querySelector(".current");
const max = button.parentElement.querySelector(".max");
const direction = button.classList.contains("increment") ? 1 : -1;
current.value = Math.clamped(parseInt(current.value) + direction, 0, parseInt(max.value));
});
html.find("button.roll-hd").click(this._onRollHitDie.bind(this));
}
/* -------------------------------------------- */
/** @override */
async _updateObject(event, formData) {
const actorItems = this.object.items;
const classUpdates = Object.entries(formData).map(([id, hd]) => ({
"_id": id,
"data.hitDiceUsed": actorItems.get(id).data.data.levels - hd
}));
return this.object.updateEmbeddedDocuments("Item", classUpdates);
}
/* -------------------------------------------- */
/**
* Rolls the hit die corresponding with the class row containing the event's target button.
* @param {MouseEvent} event
* @private
*/
async _onRollHitDie(event) {
event.preventDefault();
const button = event.currentTarget;
await this.object.rollHitDie(button.dataset.hdDenom);
// Re-render dialog to reflect changed hit dice quantities
this.render();
}
}

View file

@ -37,30 +37,28 @@ export default class LongRestDialog extends Dialog {
* @param {Actor5e} actor
* @return {Promise}
*/
static async longRestDialog({ actor } = {}) {
static async longRestDialog({actor} = {}) {
return new Promise((resolve, reject) => {
const dlg = new this(actor, {
title: "Long Rest",
title: game.i18n.localize("SW5E.LongRest"),
buttons: {
rest: {
icon: '<i class="fas fa-bed"></i>',
label: "Rest",
callback: html => {
let newDay = false;
if (game.settings.get("sw5e", "restVariant") === "normal")
label: game.i18n.localize("SW5E.Rest"),
callback: (html) => {
let newDay = true;
if (game.settings.get("sw5e", "restVariant") !== "gritty")
newDay = html.find('input[name="newDay"]')[0].checked;
else if(game.settings.get("sw5e", "restVariant") === "gritty")
newDay = true;
resolve(newDay);
}
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
label: game.i18n.localize("Cancel"),
callback: reject
}
},
default: 'rest',
default: "rest",
close: reject
});
dlg.render(true);

View file

@ -1,12 +1,11 @@
/**
* A simple form to set actor movement speeds
* @implements {BaseEntitySheet}
* @extends {DocumentSheet}
*/
export default class ActorMovementConfig extends BaseEntitySheet {
export default class ActorMovementConfig extends DocumentSheet {
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["sw5e"],
template: "systems/sw5e/templates/apps/movement-config.html",
width: 300,
@ -18,19 +17,20 @@ export default class ActorMovementConfig extends BaseEntitySheet {
/** @override */
get title() {
return `${game.i18n.localize("SW5E.MovementConfig")}: ${this.entity.name}`;
return `${game.i18n.localize("SW5E.MovementConfig")}: ${this.document.name}`;
}
/* -------------------------------------------- */
/** @override */
getData(options) {
const sourceMovement = foundry.utils.getProperty(this.document.data._source, "data.attributes.movement") || {};
const data = {
movement: duplicate(this.entity._data.data.attributes.movement),
movement: foundry.utils.deepClone(sourceMovement),
units: CONFIG.SW5E.movementUnits
}
for ( let [k, v] of Object.entries(data.movement) ) {
if ( ["units", "hover"].includes(k) ) continue;
};
for (let [k, v] of Object.entries(data.movement)) {
if (["units", "hover"].includes(k)) continue;
data.movement[k] = Number.isNumeric(v) ? v.toNearest(0.1) : 0;
}
return data;

View file

@ -0,0 +1,66 @@
/**
* A Dialog to prompt the user to select from a list of items.
* @type {Dialog}
*/
export default class SelectItemsPrompt extends Dialog {
constructor(items, dialogData = {}, options = {}) {
super(dialogData, options);
this.options.classes = ["sw5e", "dialog", "select-items-prompt", "sheet"];
/**
* Store a reference to the Item entities being used
* @type {Array<Item5e>}
*/
this.items = items;
}
activateListeners(html) {
super.activateListeners(html);
// render the item's sheet if its image is clicked
html.on("click", ".item-image", (event) => {
const item = this.items.find((feature) => feature.id === event.currentTarget.dataset?.itemId);
item?.sheet.render(true);
});
}
/**
* A constructor function which displays the AddItemPrompt app for a given Actor and Item set.
* Returns a Promise which resolves to the dialog FormData once the workflow has been completed.
* @param {Array<Item5e>} items
* @param {Object} options
* @param {string} options.hint - Localized hint to display at the top of the prompt
* @return {Promise<string[]>} - list of item ids which the user has selected
*/
static async create(items, {hint}) {
// Render the ability usage template
const html = await renderTemplate("systems/sw5e/templates/apps/select-items-prompt.html", {items, hint});
return new Promise((resolve) => {
const dlg = new this(items, {
title: game.i18n.localize("SW5E.SelectItemsPromptTitle"),
content: html,
buttons: {
apply: {
icon: `<i class="fas fa-user-plus"></i>`,
label: game.i18n.localize("SW5E.Apply"),
callback: (html) => {
const fd = new FormDataExtended(html[0].querySelector("form")).toObject();
const selectedIds = Object.keys(fd).filter((itemId) => fd[itemId]);
resolve(selectedIds);
}
},
cancel: {
icon: '<i class="fas fa-forward"></i>',
label: game.i18n.localize("SW5E.Skip"),
callback: () => resolve([])
}
},
default: "apply",
close: () => resolve([])
});
dlg.render(true);
});
}
}

View file

@ -1,12 +1,11 @@
/**
* A simple form to set actor movement speeds
* @implements {BaseEntitySheet}
* A simple form to set Actor movement speeds.
* @extends {DocumentSheet}
*/
export default class ActorSensesConfig extends BaseEntitySheet {
/** @override */
export default class ActorSensesConfig extends DocumentSheet {
/** @inheritdoc */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["sw5e"],
template: "systems/sw5e/templates/apps/senses-config.html",
width: 300,
@ -16,27 +15,28 @@ export default class ActorSensesConfig extends BaseEntitySheet {
/* -------------------------------------------- */
/** @override */
/** @inheritdoc */
get title() {
return `${game.i18n.localize("SW5E.SensesConfig")}: ${this.entity.name}`;
return `${game.i18n.localize("SW5E.SensesConfig")}: ${this.document.name}`;
}
/* -------------------------------------------- */
/** @override */
/** @inheritdoc */
getData(options) {
const senses = this.entity._data.data.attributes?.senses ?? {};
const senses = foundry.utils.getProperty(this.document.data._source, "data.attributes.senses") || {};
const data = {
senses: {},
special: senses.special ?? "",
units: senses.units, movementUnits: CONFIG.SW5E.movementUnits
units: senses.units,
movementUnits: CONFIG.SW5E.movementUnits
};
for ( let [name, label] of Object.entries(CONFIG.SW5E.senses) ) {
for (let [name, label] of Object.entries(CONFIG.SW5E.senses)) {
const v = senses[name];
data.senses[name] = {
label: game.i18n.localize(label),
value: Number.isNumeric(v) ? v.toNearest(0.1) : 0
}
};
}
return data;
}

View file

@ -5,7 +5,7 @@ import LongRestDialog from "./long-rest.js";
* @extends {Dialog}
*/
export default class ShortRestDialog extends Dialog {
constructor(actor, dialogData={}, options={}) {
constructor(actor, dialogData = {}, options = {}) {
super(dialogData, options);
/**
@ -39,8 +39,8 @@ export default class ShortRestDialog extends Dialog {
// Determine Hit Dice
data.availableHD = this.actor.data.items.reduce((hd, item) => {
if ( item.type === "class" ) {
const d = item.data;
if (item.type === "class") {
const d = item.data.data;
const denom = d.hitDice || "d6";
const available = parseInt(d.levels || 1) - parseInt(d.hitDiceUsed || 0);
hd[denom] = denom in hd ? hd[denom] + available : available;
@ -59,7 +59,6 @@ export default class ShortRestDialog extends Dialog {
/* -------------------------------------------- */
/** @override */
activateListeners(html) {
super.activateListeners(html);
@ -90,15 +89,15 @@ export default class ShortRestDialog extends Dialog {
* @param {Actor5e} actor
* @return {Promise}
*/
static async shortRestDialog({actor}={}) {
static async shortRestDialog({actor} = {}) {
return new Promise((resolve, reject) => {
const dlg = new this(actor, {
title: "Short Rest",
title: game.i18n.localize("SW5E.ShortRest"),
buttons: {
rest: {
icon: '<i class="fas fa-bed"></i>',
label: "Rest",
callback: html => {
label: game.i18n.localize("SW5E.Rest"),
callback: (html) => {
let newDay = false;
if (game.settings.get("sw5e", "restVariant") === "gritty")
newDay = html.find('input[name="newDay"]')[0].checked;
@ -107,7 +106,7 @@ export default class ShortRestDialog extends Dialog {
},
cancel: {
icon: '<i class="fas fa-times"></i>',
label: "Cancel",
label: game.i18n.localize("Cancel"),
callback: reject
}
},
@ -126,8 +125,10 @@ export default class ShortRestDialog extends Dialog {
* @param {Actor5e} actor
* @return {Promise}
*/
static async longRestDialog({actor}={}) {
console.warn("WARNING! ShortRestDialog.longRestDialog has been deprecated, use LongRestDialog.longRestDialog instead.");
static async longRestDialog({actor} = {}) {
console.warn(
"WARNING! ShortRestDialog.longRestDialog has been deprecated, use LongRestDialog.longRestDialog instead."
);
return LongRestDialog.longRestDialog(...arguments);
}
}

View file

@ -1,14 +1,13 @@
/**
* A specialized form used to select from a checklist of attributes, traits, or properties
* @implements {FormApplication}
* @extends {DocumentSheet}
*/
export default class TraitSelector extends FormApplication {
/** @override */
export default class TraitSelector extends DocumentSheet {
/** @inheritdoc */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
return foundry.utils.mergeObject(super.defaultOptions, {
id: "trait-selector",
classes: ["sw5e"],
classes: ["sw5e", "trait-selector", "subconfig"],
title: "Actor Trait Selection",
template: "systems/sw5e/templates/apps/trait-selector.html",
width: 320,
@ -16,7 +15,9 @@ export default class TraitSelector extends FormApplication {
choices: {},
allowCustom: true,
minimum: 0,
maximum: null
maximum: null,
valueKey: "value",
customKey: "custom"
});
}
@ -24,7 +25,7 @@ export default class TraitSelector extends FormApplication {
/**
* Return a reference to the target attribute
* @type {String}
* @type {string}
*/
get attribute() {
return this.options.name;
@ -34,52 +35,50 @@ export default class TraitSelector extends FormApplication {
/** @override */
getData() {
// Get current values
let attr = getProperty(this.object._data, this.attribute);
if ( getType(attr) !== "Object" ) attr = {value: [], custom: ""};
const attr = foundry.utils.getProperty(this.object.data, this.attribute);
const o = this.options;
const value = o.valueKey ? attr[o.valueKey] ?? [] : attr;
const custom = o.customKey ? attr[o.customKey] ?? "" : "";
// Populate choices
const choices = duplicate(this.options.choices);
for ( let [k, v] of Object.entries(choices) ) {
choices[k] = {
label: v,
chosen: attr ? attr.value.includes(k) : false
}
}
const choices = Object.entries(o.choices).reduce((obj, e) => {
let [k, v] = e;
obj[k] = {label: v, chosen: attr ? value.includes(k) : false};
return obj;
}, {});
// Return data
return {
allowCustom: this.options.allowCustom,
allowCustom: o.allowCustom,
choices: choices,
custom: attr ? attr.custom : ""
}
custom: custom
};
}
/* -------------------------------------------- */
/** @override */
_updateObject(event, formData) {
const updateData = {};
async _updateObject(event, formData) {
const o = this.options;
// Obtain choices
const chosen = [];
for ( let [k, v] of Object.entries(formData) ) {
if ( (k !== "custom") && v ) chosen.push(k);
for (let [k, v] of Object.entries(formData)) {
if (k !== "custom" && v) chosen.push(k);
}
updateData[`${this.attribute}.value`] = chosen;
// Object including custom data
const updateData = {};
if (o.valueKey) updateData[`${this.attribute}.${o.valueKey}`] = chosen;
else updateData[this.attribute] = chosen;
if (o.allowCustom) updateData[`${this.attribute}.${o.customKey}`] = formData.custom;
// Validate the number chosen
if ( this.options.minimum && (chosen.length < this.options.minimum) ) {
return ui.notifications.error(`You must choose at least ${this.options.minimum} options`);
if (o.minimum && chosen.length < o.minimum) {
return ui.notifications.error(`You must choose at least ${o.minimum} options`);
}
if ( this.options.maximum && (chosen.length > this.options.maximum) ) {
return ui.notifications.error(`You may choose no more than ${this.options.maximum} options`);
}
// Include custom
if ( this.options.allowCustom ) {
updateData[`${this.attribute}.custom`] = formData.custom;
if (o.maximum && chosen.length > o.maximum) {
return ui.notifications.error(`You may choose no more than ${o.maximum} options`);
}
// Update the object

View file

@ -1,6 +1,6 @@
/** @override */
export const measureDistances = function(segments, options={}) {
if ( !options.gridSpaces ) return BaseGrid.prototype.measureDistances.call(this, segments, options);
export const measureDistances = function (segments, options = {}) {
if (!options.gridSpaces) return BaseGrid.prototype.measureDistances.call(this, segments, options);
// Track the total number of diagonals
let nDiagonal = 0;
@ -8,7 +8,7 @@ export const measureDistances = function(segments, options={}) {
const d = canvas.dimensions;
// Iterate over measured segments
return segments.map(s => {
return segments.map((s) => {
let r = s.ray;
// Determine the total distance traveled
@ -23,7 +23,7 @@ export const measureDistances = function(segments, options={}) {
// Alternative DMG Movement
if (rule === "5105") {
let nd10 = Math.floor(nDiagonal / 2) - Math.floor((nDiagonal - nd) / 2);
let spaces = (nd10 * 2) + (nd - nd10) + ns;
let spaces = nd10 * 2 + (nd - nd10) + ns;
return spaces * canvas.dimensions.distance;
}
@ -36,19 +36,3 @@ export const measureDistances = function(segments, options={}) {
else return (ns + nd) * canvas.scene.data.gridDistance;
});
};
/* -------------------------------------------- */
/**
* Hijack Token health bar rendering to include temporary and temp-max health in the bar display
* TODO: This should probably be replaced with a formal Token class extension
*/
const _TokenGetBarAttribute = Token.prototype.getBarAttribute;
export const getBarAttribute = function(...args) {
const data = _TokenGetBarAttribute.bind(this)(...args);
if ( data && (data.attribute === "attributes.hp") ) {
data.value += parseInt(getProperty(this.actor.data, "data.attributes.hp.temp") || 0);
data.max += parseInt(getProperty(this.actor.data, "data.attributes.hp.tempmax") || 0);
}
return data;
};

View file

@ -147,17 +147,19 @@ export default class CharacterImporter {
});
// pull classes directly from system compendium and add them to current actor
const professionsPack = await game.packs.get("sw5e.classes").getContent();
const professionsPack = await game.packs.get("sw5e.classes").getDocuments();
result.forEach((prof) => {
let assignedProfession = professionsPack.find((o) => o.name === prof.profession);
assignedProfession.data.data.levels = prof.level;
actor.createEmbeddedEntity("OwnedItem", assignedProfession.data, { displaySheet: false });
actor.createEmbeddedDocuments("Item", [assignedProfession.data], {displaySheet: false});
});
this.addSpecies(sourceCharacter.attribs.find((e) => e.name == "race").current, actor);
this.addPowers(
sourceCharacter.attribs.filter((e) => e.name.search(/repeating_power.+_powername/g) != -1).map((e) => e.current),
sourceCharacter.attribs
.filter((e) => e.name.search(/repeating_power.+_powername/g) != -1)
.map((e) => e.current),
actor
);
@ -177,10 +179,10 @@ export default class CharacterImporter {
}
static async addClasses(profession, level, actor) {
let classes = await game.packs.get("sw5e.classes").getContent();
let classes = await game.packs.get("sw5e.classes").getDocuments();
let assignedClass = classes.find((c) => c.name === profession);
assignedClass.data.data.levels = level;
await actor.createEmbeddedEntity("OwnedItem", assignedClass.data, { displaySheet: false });
await actor.createEmbeddedDocuments("Item", [assignedClass.data], {displaySheet: false});
}
static classOrMulticlass(name) {
@ -210,10 +212,10 @@ export default class CharacterImporter {
}
static async addSpecies(race, actor) {
const species = await game.packs.get("sw5e.species").getContent();
const species = await game.packs.get("sw5e.species").getDocuments();
const assignedSpecies = species.find((c) => c.name === race);
const activeEffects = assignedSpecies.data.effects[0].changes;
const actorData = { data: { abilities: { ...actor.data.data.abilities } } };
const activeEffects = [...assignedSpecies.data.effects][0].data.changes;
const actorData = {data: {abilities: {...actor.data.data.abilities}}};
activeEffects.map((effect) => {
switch (effect.key) {
@ -248,26 +250,26 @@ export default class CharacterImporter {
actor.update(actorData);
await actor.createEmbeddedEntity("OwnedItem", assignedSpecies.data, { displaySheet: false });
await actor.createEmbeddedDocuments("Item", [assignedSpecies.data], {displaySheet: false});
}
static async addPowers(powers, actor) {
const forcePowers = await game.packs.get("sw5e.forcepowers").getContent();
const techPowers = await game.packs.get("sw5e.techpowers").getContent();
const forcePowers = await game.packs.get("sw5e.forcepowers").getDocuments();
const techPowers = await game.packs.get("sw5e.techpowers").getDocuments();
for (const power of powers) {
const createdPower = forcePowers.find((c) => c.name === power) || techPowers.find((c) => c.name === power);
if (createdPower) {
await actor.createEmbeddedEntity("OwnedItem", createdPower.data, { displaySheet: false });
await actor.createEmbeddedDocuments("Item", [createdPower.data], {displaySheet: false});
}
}
}
static async addItems(items, actor) {
const weapons = await game.packs.get("sw5e.weapons").getContent();
const armors = await game.packs.get("sw5e.armor").getContent();
const adventuringGear = await game.packs.get("sw5e.adventuringgear").getContent();
const weapons = await game.packs.get("sw5e.weapons").getDocuments();
const armors = await game.packs.get("sw5e.armor").getDocuments();
const adventuringGear = await game.packs.get("sw5e.adventuringgear").getDocuments();
for (const item of items) {
const createdItem =
@ -280,7 +282,7 @@ export default class CharacterImporter {
createdItem.data.data.quantity = item.quantity;
}
await actor.createEmbeddedEntity("OwnedItem", createdItem.data, { displaySheet: false });
await actor.createEmbeddedDocuments("Item", [createdItem.data], {displaySheet: false});
}
}
}

View file

@ -1,28 +1,27 @@
/**
* Highlight critical success or failure on d20 rolls
*/
export const highlightCriticalSuccessFailure = function(message, html, data) {
if ( !message.isRoll || !message.isContentVisible ) return;
export const highlightCriticalSuccessFailure = function (message, html, data) {
if (!message.isRoll || !message.isContentVisible) return;
// Highlight rolls where the first part is a d20 roll
const roll = message.roll;
if ( !roll.dice.length ) return;
if (!roll.dice.length) return;
const d = roll.dice[0];
// Ensure it is an un-modified d20 roll
const isD20 = (d.faces === 20) && ( d.values.length === 1 );
if ( !isD20 ) return;
const isModifiedRoll = ("success" in d.results[0]) || d.options.marginSuccess || d.options.marginFailure;
if ( isModifiedRoll ) return;
const isD20 = d.faces === 20 && d.values.length === 1;
if (!isD20) return;
const isModifiedRoll = "success" in d.results[0] || d.options.marginSuccess || d.options.marginFailure;
if (isModifiedRoll) return;
// Highlight successes and failures
const critical = d.options.critical || 20;
const fumble = d.options.fumble || 1;
if ( d.total >= critical ) html.find(".dice-total").addClass("critical");
else if ( d.total <= fumble ) html.find(".dice-total").addClass("fumble");
else if ( d.options.target ) {
if ( roll.total >= d.options.target ) html.find(".dice-total").addClass("success");
if (d.total >= critical) html.find(".dice-total").addClass("critical");
else if (d.total <= fumble) html.find(".dice-total").addClass("fumble");
else if (d.options.target) {
if (roll.total >= d.options.target) html.find(".dice-total").addClass("success");
else html.find(".dice-total").addClass("failure");
}
};
@ -32,22 +31,22 @@ export const highlightCriticalSuccessFailure = function(message, html, data) {
/**
* Optionally hide the display of chat card action buttons which cannot be performed by the user
*/
export const displayChatActionButtons = function(message, html, data) {
export const displayChatActionButtons = function (message, html, data) {
const chatCard = html.find(".sw5e.chat-card");
if ( chatCard.length > 0 ) {
if (chatCard.length > 0) {
const flavor = html.find(".flavor-text");
if ( flavor.text() === html.find(".item-name").text() ) flavor.remove();
if (flavor.text() === html.find(".item-name").text()) flavor.remove();
// If the user is the message author or the actor owner, proceed
let actor = game.actors.get(data.message.speaker.actor);
if ( actor && actor.owner ) return;
else if ( game.user.isGM || (data.author.id === game.user.id)) return;
if (actor && actor.isOwner) return;
else if (game.user.isGM || data.author.id === game.user.id) return;
// Otherwise conceal action buttons except for saving throw
const buttons = chatCard.find("button[data-action]");
buttons.each((i, btn) => {
if ( btn.dataset.action === "save" ) return;
btn.style.display = "none"
if (btn.dataset.action === "save") return;
btn.style.display = "none";
});
}
};
@ -63,35 +62,35 @@ export const displayChatActionButtons = function(message, html, data) {
*
* @return {Array} The extended options Array including new context choices
*/
export const addChatMessageContextOptions = function(html, options) {
let canApply = li => {
export const addChatMessageContextOptions = function (html, options) {
let canApply = (li) => {
const message = game.messages.get(li.data("messageId"));
return message?.isRoll && message?.isContentVisible && canvas?.tokens.controlled.length;
return message?.isRoll && message?.isContentVisible && canvas.tokens?.controlled.length;
};
options.push(
{
name: game.i18n.localize("SW5E.ChatContextDamage"),
icon: '<i class="fas fa-user-minus"></i>',
condition: canApply,
callback: li => applyChatCardDamage(li, 1)
callback: (li) => applyChatCardDamage(li, 1)
},
{
name: game.i18n.localize("SW5E.ChatContextHealing"),
icon: '<i class="fas fa-user-plus"></i>',
condition: canApply,
callback: li => applyChatCardDamage(li, -1)
callback: (li) => applyChatCardDamage(li, -1)
},
{
name: game.i18n.localize("SW5E.ChatContextDoubleDamage"),
icon: '<i class="fas fa-user-injured"></i>',
condition: canApply,
callback: li => applyChatCardDamage(li, 2)
callback: (li) => applyChatCardDamage(li, 2)
},
{
name: game.i18n.localize("SW5E.ChatContextHalfDamage"),
icon: '<i class="fas fa-user-shield"></i>',
condition: canApply,
callback: li => applyChatCardDamage(li, 0.5)
callback: (li) => applyChatCardDamage(li, 0.5)
}
);
return options;
@ -110,10 +109,12 @@ export const addChatMessageContextOptions = function(html, options) {
function applyChatCardDamage(li, multiplier) {
const message = game.messages.get(li.data("messageId"));
const roll = message.roll;
return Promise.all(canvas.tokens.controlled.map(t => {
return Promise.all(
canvas.tokens.controlled.map((t) => {
const a = t.actor;
return a.applyDamage(roll.total, multiplier);
}));
})
);
}
/* -------------------------------------------- */

View file

@ -1,4 +1 @@
export const ClassFeatures = {
};
export const ClassFeatures = {};

View file

@ -1,28 +1,31 @@
/**
* Override the default Initiative formula to customize special behaviors of the SW5e system.
* Apply advantage, proficiency, or bonuses where appropriate
* Apply the dexterity score as a decimal tiebreaker if requested
* See Combat._getInitiativeFormula for more detail.
*/
export const _getInitiativeFormula = function(combatant) {
const actor = combatant.actor;
if ( !actor ) return "1d20";
export const _getInitiativeFormula = function () {
const actor = this.actor;
if (!actor) return "1d20";
const init = actor.data.data.attributes.init;
// Construct initiative formula parts
let nd = 1;
let mods = "";
if (actor.getFlag("sw5e", "halflingLucky")) mods += "r1=1";
if (actor.getFlag("sw5e", "initiativeAdv")) {
nd = 2;
mods += "kh";
}
const parts = [`${nd}d20${mods}`, init.mod, (init.prof !== 0) ? init.prof : null, (init.bonus !== 0) ? init.bonus : null];
const parts = [
`${nd}d20${mods}`,
init.mod,
init.prof !== 0 ? init.prof : null,
init.bonus !== 0 ? init.bonus : null
];
// Optionally apply Dexterity tiebreaker
const tiebreaker = game.settings.get("sw5e", "initiativeDexTiebreaker");
if ( tiebreaker ) parts.push(actor.data.data.abilities.dex.value / 100);
return parts.filter(p => p !== null).join(" + ");
if (tiebreaker) parts.push(actor.data.data.abilities.dex.value / 100);
return parts.filter((p) => p !== null).join(" + ");
};

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,6 @@
export {default as D20Roll} from "./dice/d20-roll.js";
export {default as DamageRoll} from "./dice/damage-roll.js";
/**
* A standardized helper function for simplifying the constant parts of a multipart roll formula
*
@ -20,14 +23,19 @@ export function simplifyRollFormula(formula, data, {constantFirst = false} = {})
const constantTerms = []; // Terms that are constant, and their associated operators
let operators = []; // Temporary storage for operators before they are moved to one of the above
for (let term of terms) { // For each term
if (["+", "-"].includes(term)) operators.push(term); // If the term is an addition/subtraction operator, push the term into the operators array
else { // Otherwise the term is not an operator
if (term instanceof DiceTerm) { // If the term is something rollable
for (let term of terms) {
// For each term
if (term instanceof OperatorTerm) operators.push(term);
// If the term is an addition/subtraction operator, push the term into the operators array
else {
// Otherwise the term is not an operator
if (term instanceof DiceTerm) {
// If the term is something rollable
rollableTerms.push(...operators); // Place all the operators into the rollableTerms array
rollableTerms.push(term); // Then place this rollable term into it as well
} //
else { // Otherwise, this must be a constant
else {
// Otherwise, this must be a constant
constantTerms.push(...operators); // Place the operators into the constantTerms array
constantTerms.push(term); // Then also add this constant term to that array.
} //
@ -35,13 +43,21 @@ export function simplifyRollFormula(formula, data, {constantFirst = false} = {})
}
}
const constantFormula = Roll.cleanFormula(constantTerms); // Cleans up the constant terms and produces a new formula string
const rollableFormula = Roll.cleanFormula(rollableTerms); // Cleans up the non-constant terms and produces a new formula string
const constantFormula = Roll.getFormula(constantTerms); // Cleans up the constant terms and produces a new formula string
const rollableFormula = Roll.getFormula(rollableTerms); // Cleans up the non-constant terms and produces a new formula string
const constantPart = roll._safeEval(constantFormula); // Mathematically evaluate the constant formula to produce a single constant term
// Mathematically evaluate the constant formula to produce a single constant term
let constantPart = undefined;
if (constantFormula) {
try {
constantPart = Roll.safeEval(constantFormula);
} catch (err) {
console.warn(`Unable to evaluate constant term ${constantFormula} in simplifyRollFormula`);
}
}
const parts = constantFirst ? // Order the rollable and constant terms, either constant first or second depending on the optional argumen
[constantPart, rollableFormula] : [rollableFormula, constantPart];
// Order the rollable and constant terms, either constant first or second depending on the optional argument
const parts = constantFirst ? [constantPart, rollableFormula] : [rollableFormula, constantPart];
// Join the parts with a + sign, pass them to `Roll` once again to clean up the formula
return new Roll(parts.filterJoin(" + ")).formula;
@ -56,315 +72,242 @@ export function simplifyRollFormula(formula, data, {constantFirst = false} = {})
*/
function _isUnsupportedTerm(term) {
const diceTerm = term instanceof DiceTerm;
const operator = ["+", "-"].includes(term);
const number = !isNaN(Number(term));
const operator = term instanceof OperatorTerm && ["+", "-"].includes(term.operator);
const number = term instanceof NumericTerm;
return !(diceTerm || operator || number);
}
/* -------------------------------------------- */
/* D20 Roll */
/* -------------------------------------------- */
/**
* A standardized helper function for managing core 5e "d20 rolls"
*
* A standardized helper function for managing core 5e d20 rolls.
* Holding SHIFT, ALT, or CTRL when the attack is rolled will "fast-forward".
* This chooses the default options of a normal attack with no bonus, Advantage, or Disadvantage respectively
*
* @param {Array} parts The dice roll component parts, excluding the initial d20
* @param {Object} data Actor or item data against which to parse the roll
* @param {Event|object} event The triggering event which initiated the roll
* @param {string} rollMode A specific roll mode to apply as the default for the resulting roll
* @param {string|null} template The HTML template used to render the roll dialog
* @param {string|null} title The dice roll UI window title
* @param {Object} speaker The ChatMessage speaker to pass when creating the chat
* @param {string|null} flavor Flavor text to use in the posted chat message
* @param {Boolean} fastForward Allow fast-forward advantage selection
* @param {Function} onClose Callback for actions to take when the dialog form is closed
* @param {Object} dialogOptions Modal dialog options
* @param {boolean} advantage Apply advantage to the roll (unless otherwise specified)
* @param {boolean} disadvantage Apply disadvantage to the roll (unless otherwise specified)
* @param {number} critical The value of d20 result which represents a critical success
* @param {number} fumble The value of d20 result which represents a critical failure
* @param {number} targetValue Assign a target value against which the result of this roll should be compared
* @param {boolean} elvenAccuracy Allow Elven Accuracy to modify this roll?
* @param {boolean} halflingLucky Allow Halfling Luck to modify this roll?
* @param {boolean} reliableTalent Allow Reliable Talent to modify this roll?
* @param {boolean} chatMessage Automatically create a Chat Message for the result of this roll
* @param {object} messageData Additional data which is applied to the created Chat Message, if any
* @param {string[]} parts The dice roll component parts, excluding the initial d20
* @param {object} data Actor or item data against which to parse the roll
*
* @return {Promise} A Promise which resolves once the roll workflow has completed
* @param {boolean} [advantage] Apply advantage to the roll (unless otherwise specified)
* @param {boolean} [disadvantage] Apply disadvantage to the roll (unless otherwise specified)
* @param {number} [critical] The value of d20 result which represents a critical success
* @param {number} [fumble] The value of d20 result which represents a critical failure
* @param {number} [targetValue] Assign a target value against which the result of this roll should be compared
* @param {boolean} [elvenAccuracy] Allow Elven Accuracy to modify this roll?
* @param {boolean} [halflingLucky] Allow Halfling Luck to modify this roll?
* @param {boolean} [reliableTalent] Allow Reliable Talent to modify this roll?
* @param {boolean} [chooseModifier=false] Choose the ability modifier that should be used when the roll is made
* @param {boolean} [fastForward=false] Allow fast-forward advantage selection
* @param {Event} [event] The triggering event which initiated the roll
* @param {string} [rollMode] A specific roll mode to apply as the default for the resulting roll
* @param {string} [template] The HTML template used to render the roll dialog
* @param {string} [title] The dialog window title
* @param {Object} [dialogOptions] Modal dialog options
*
* @param {boolean} [chatMessage=true] Automatically create a Chat Message for the result of this roll
* @param {object} [messageData={}] Additional data which is applied to the created Chat Message, if any
* @param {string} [rollMode] A specific roll mode to apply as the default for the resulting roll
* @param {object} [speaker] The ChatMessage speaker to pass when creating the chat
* @param {string} [flavor] Flavor text to use in the posted chat message
*
* @return {Promise<D20Roll|null>} The evaluated D20Roll, or null if the workflow was cancelled
*/
export async function d20Roll({parts=[], data={}, event={}, rollMode=null, template=null, title=null, speaker=null,
flavor=null, fastForward=null, dialogOptions,
advantage=null, disadvantage=null, critical=20, fumble=1, targetValue=null,
elvenAccuracy=false, halflingLucky=false, reliableTalent=false,
chatMessage=true, messageData={}}={}) {
export async function d20Roll({
parts = [],
data = {}, // Roll creation
advantage,
disadvantage,
fumble = 1,
critical = 20,
targetValue,
elvenAccuracy,
halflingLucky,
reliableTalent, // Roll customization
chooseModifier = false,
fastForward = false,
event,
template,
title,
dialogOptions, // Dialog configuration
chatMessage = true,
messageData = {},
rollMode,
speaker,
flavor // Chat Message customization
} = {}) {
// Handle input arguments
const formula = ["1d20"].concat(parts).join(" + ");
const {advantageMode, isFF} = _determineAdvantageMode({advantage, disadvantage, fastForward, event});
const defaultRollMode = rollMode || game.settings.get("core", "rollMode");
if (chooseModifier && !isFF) data["mod"] = "@mod";
// Prepare Message Data
messageData.flavor = flavor || title;
messageData.speaker = speaker || ChatMessage.getSpeaker();
const messageOptions = {rollMode: rollMode || game.settings.get("core", "rollMode")};
parts = parts.concat(["@bonus"]);
// Construct the D20Roll instance
const roll = new CONFIG.Dice.D20Roll(formula, data, {
flavor: flavor || title,
advantageMode,
defaultRollMode,
critical,
fumble,
targetValue,
elvenAccuracy,
halflingLucky,
reliableTalent
});
// Handle fast-forward events
let adv = 0;
fastForward = fastForward ?? (event && (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey));
if (fastForward) {
if ( advantage ?? event.altKey ) adv = 1;
else if ( disadvantage ?? (event.ctrlKey || event.metaKey) ) adv = -1;
// Prompt a Dialog to further configure the D20Roll
if (!isFF) {
const configured = await roll.configureDialog(
{
title,
chooseModifier,
defaultRollMode: defaultRollMode,
defaultAction: advantageMode,
defaultAbility: data?.item?.ability,
template
},
dialogOptions
);
if (configured === null) return null;
}
// Define the inner roll function
const _roll = (parts, adv, form) => {
// Determine the d20 roll and modifiers
let nd = 1;
let mods = halflingLucky ? "r1=1" : "";
// Handle advantage
if (adv === 1) {
nd = elvenAccuracy ? 3 : 2;
messageData.flavor += ` (${game.i18n.localize("SW5E.Advantage")})`;
if ( "flags.sw5e.roll" in messageData ) messageData["flags.sw5e.roll"].advantage = true;
mods += "kh";
}
// Handle disadvantage
else if (adv === -1) {
nd = 2;
messageData.flavor += ` (${game.i18n.localize("SW5E.Disadvantage")})`;
if ( "flags.sw5e.roll" in messageData ) messageData["flags.sw5e.roll"].disadvantage = true;
mods += "kl";
}
// Prepend the d20 roll
let formula = `${nd}d20${mods}`;
if (reliableTalent) formula = `{${nd}d20${mods},10}kh`;
parts.unshift(formula);
// Optionally include a situational bonus
if ( form ) {
data['bonus'] = form.bonus.value;
messageOptions.rollMode = form.rollMode.value;
}
if (!data["bonus"]) parts.pop();
// Optionally include an ability score selection (used for tool checks)
const ability = form ? form.ability : null;
if (ability && ability.value) {
data.ability = ability.value;
const abl = data.abilities[data.ability];
if (abl) {
data.mod = abl.mod;
messageData.flavor += ` (${CONFIG.SW5E.abilities[data.ability]})`;
}
}
// Execute the roll
let roll = new Roll(parts.join(" + "), data);
try {
roll.roll();
} catch (err) {
console.error(err);
ui.notifications.error(`Dice roll evaluation failed: ${err.message}`);
return null;
}
// Flag d20 options for any 20-sided dice in the roll
for (let d of roll.dice) {
if (d.faces === 20) {
d.options.critical = critical;
d.options.fumble = fumble;
if ( adv === 1 ) d.options.advantage = true;
else if ( adv === -1 ) d.options.disadvantage = true;
if (targetValue) d.options.target = targetValue;
}
}
// If reliable talent was applied, add it to the flavor text
if (reliableTalent && roll.dice[0].total < 10) {
messageData.flavor += ` (${game.i18n.localize("SW5E.FlagsReliableTalent")})`;
}
return roll;
};
// Create the Roll instance
const roll = fastForward ? _roll(parts, adv) :
await _d20RollDialog({template, title, parts, data, rollMode: messageOptions.rollMode, dialogOptions, roll: _roll});
// Evaluate the configured roll
await roll.evaluate({async: true});
// Create a Chat Message
if ( roll && chatMessage ) roll.toMessage(messageData, messageOptions);
if (speaker) {
console.warn(
`You are passing the speaker argument to the d20Roll function directly which should instead be passed as an internal key of messageData`
);
messageData.speaker = speaker;
}
if (roll && chatMessage) await roll.toMessage(messageData);
return roll;
}
/* -------------------------------------------- */
/**
* Present a Dialog form which creates a d20 roll once submitted
* @return {Promise<Roll>}
* @private
* Determines whether this d20 roll should be fast-forwarded, and whether advantage or disadvantage should be applied
* @returns {{isFF: boolean, advantageMode: number}} Whether the roll is fast-forward, and its advantage mode
*/
async function _d20RollDialog({template, title, parts, data, rollMode, dialogOptions, roll}={}) {
// Render modal dialog
template = template || "systems/sw5e/templates/chat/roll-dialog.html";
let dialogData = {
formula: parts.join(" + "),
data: data,
rollMode: rollMode,
rollModes: CONFIG.Dice.rollModes,
config: CONFIG.SW5E
};
const html = await renderTemplate(template, dialogData);
// Create the Dialog window
return new Promise(resolve => {
new Dialog({
title: title,
content: html,
buttons: {
advantage: {
label: game.i18n.localize("SW5E.Advantage"),
callback: html => resolve(roll(parts, 1, html[0].querySelector("form")))
},
normal: {
label: game.i18n.localize("SW5E.Normal"),
callback: html => resolve(roll(parts, 0, html[0].querySelector("form")))
},
disadvantage: {
label: game.i18n.localize("SW5E.Disadvantage"),
callback: html => resolve(roll(parts, -1, html[0].querySelector("form")))
}
},
default: "normal",
close: () => resolve(null)
}, dialogOptions).render(true);
});
function _determineAdvantageMode({event, advantage = false, disadvantage = false, fastForward = false} = {}) {
const isFF = fastForward || (event && (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey));
let advantageMode = CONFIG.Dice.D20Roll.ADV_MODE.NORMAL;
if (advantage || event?.altKey) advantageMode = CONFIG.Dice.D20Roll.ADV_MODE.ADVANTAGE;
else if (disadvantage || event?.ctrlKey || event?.metaKey)
advantageMode = CONFIG.Dice.D20Roll.ADV_MODE.DISADVANTAGE;
return {isFF, advantageMode};
}
/* -------------------------------------------- */
/* Damage Roll */
/* -------------------------------------------- */
/**
* A standardized helper function for managing core 5e "d20 rolls"
* A standardized helper function for managing core 5e damage rolls.
*
* Holding SHIFT, ALT, or CTRL when the attack is rolled will "fast-forward".
* This chooses the default options of a normal attack with no bonus, Critical, or no bonus respectively
*
* @param {Array} parts The dice roll component parts, excluding the initial d20
* @param {Actor} actor The Actor making the damage roll
* @param {Object} data Actor or item data against which to parse the roll
* @param {Event|object}[event The triggering event which initiated the roll
* @param {string} rollMode A specific roll mode to apply as the default for the resulting roll
* @param {String} template The HTML template used to render the roll dialog
* @param {String} title The dice roll UI window title
* @param {Object} speaker The ChatMessage speaker to pass when creating the chat
* @param {string} flavor Flavor text to use in the posted chat message
* @param {boolean} allowCritical Allow the opportunity for a critical hit to be rolled
* @param {Boolean} critical Flag this roll as a critical hit for the purposes of fast-forward rolls
* @param {number} criticalBonusDice A number of bonus damage dice that are added for critical hits
* @param {number} criticalMultiplier A critical hit multiplier which is applied to critical hits
* @param {Boolean} fastForward Allow fast-forward advantage selection
* @param {Function} onClose Callback for actions to take when the dialog form is closed
* @param {Object} dialogOptions Modal dialog options
* @param {boolean} chatMessage Automatically create a Chat Message for the result of this roll
* @param {object} messageData Additional data which is applied to the created Chat Message, if any
* @param {string[]} parts The dice roll component parts, excluding the initial d20
* @param {object} [data] Actor or item data against which to parse the roll
*
* @return {Promise} A Promise which resolves once the roll workflow has completed
* @param {boolean} [critical=false] Flag this roll as a critical hit for the purposes of fast-forward or default dialog action
* @param {number} [criticalBonusDice=0] A number of bonus damage dice that are added for critical hits
* @param {number} [criticalMultiplier=2] A critical hit multiplier which is applied to critical hits
* @param {boolean} [multiplyNumeric=false] Multiply numeric terms by the critical multiplier
* @param {boolean} [powerfulCritical=false] Apply the "powerful criticals" house rule to critical hits
* @param {boolean} [fastForward=false] Allow fast-forward advantage selection
* @param {Event}[event] The triggering event which initiated the roll
* @param {boolean} [allowCritical=true] Allow the opportunity for a critical hit to be rolled
* @param {string} [template] The HTML template used to render the roll dialog
* @param {string} [title] The dice roll UI window title
* @param {object} [dialogOptions] Configuration dialog options
*
* @param {boolean} [chatMessage=true] Automatically create a Chat Message for the result of this roll
* @param {object} [messageData={}] Additional data which is applied to the created Chat Message, if any
* @param {string} [rollMode] A specific roll mode to apply as the default for the resulting roll
* @param {object} [speaker] The ChatMessage speaker to pass when creating the chat
* @param {string} [flavor] Flavor text to use in the posted chat message
*
* @return {Promise<DamageRoll|null>} The evaluated DamageRoll, or null if the workflow was canceled
*/
export async function damageRoll({parts, actor, data, event={}, rollMode=null, template, title, speaker, flavor,
allowCritical=true, critical=false, criticalBonusDice=0, criticalMultiplier=2, fastForward=null,
dialogOptions={}, chatMessage=true, messageData={}}={}) {
export async function damageRoll({
parts = [],
data, // Roll creation
critical = false,
criticalBonusDice,
criticalMultiplier,
multiplyNumeric,
powerfulCritical, // Damage customization
fastForward = false,
event,
allowCritical = true,
template,
title,
dialogOptions, // Dialog configuration
chatMessage = true,
messageData = {},
rollMode,
speaker,
flavor // Chat Message customization
} = {}) {
// Handle input arguments
const defaultRollMode = rollMode || game.settings.get("core", "rollMode");
// Prepare Message Data
messageData.flavor = flavor || title;
messageData.speaker = speaker || ChatMessage.getSpeaker();
const messageOptions = {rollMode: rollMode || game.settings.get("core", "rollMode")};
parts = parts.concat(["@bonus"]);
// Define inner roll function
const _roll = function(parts, crit, form) {
// Optionally include a situational bonus
if ( form ) {
data['bonus'] = form.bonus.value;
messageOptions.rollMode = form.rollMode.value;
}
if (!data["bonus"]) parts.pop();
// Create the damage roll
let roll = new Roll(parts.join("+"), data);
// Modify the damage formula for critical hits
if ( crit === true ) {
roll.alter(criticalMultiplier, 0); // Multiply all dice
if ( roll.terms[0] instanceof Die ) { // Add bonus dice for only the main dice term
roll.terms[0].alter(1, criticalBonusDice);
roll._formula = roll.formula;
}
messageData.flavor += ` (${game.i18n.localize("SW5E.Critical")})`;
if ( "flags.sw5e.roll" in messageData ) messageData["flags.sw5e.roll"].critical = true;
}
// Execute the roll
try {
roll.evaluate()
if ( crit ) roll.dice.forEach(d => d.options.critical = true); // TODO workaround core bug which wipes Roll#options on roll
return roll;
} catch(err) {
console.error(err);
ui.notifications.error(`Dice roll evaluation failed: ${err.message}`);
return null;
}
};
// Create the Roll instance
const roll = fastForward ? _roll(parts, critical) : await _damageRollDialog({
template, title, parts, data, allowCritical, rollMode: messageOptions.rollMode, dialogOptions, roll: _roll
// Construct the DamageRoll instance
const formula = parts.join(" + ");
const {isCritical, isFF} = _determineCriticalMode({critical, fastForward, event});
const roll = new CONFIG.Dice.DamageRoll(formula, data, {
flavor: flavor || title,
critical: isCritical,
criticalBonusDice,
criticalMultiplier,
multiplyNumeric,
powerfulCritical
});
// Create a Chat Message
if ( roll && chatMessage ) roll.toMessage(messageData, messageOptions);
return roll;
// Prompt a Dialog to further configure the DamageRoll
if (!isFF) {
const configured = await roll.configureDialog(
{
title,
defaultRollMode: defaultRollMode,
defaultCritical: isCritical,
template,
allowCritical
},
dialogOptions
);
if (configured === null) return null;
}
// Evaluate the configured roll
await roll.evaluate({async: true});
// Create a Chat Message
if (speaker) {
console.warn(
`You are passing the speaker argument to the damageRoll function directly which should instead be passed as an internal key of messageData`
);
messageData.speaker = speaker;
}
if (roll && chatMessage) await roll.toMessage(messageData);
return roll;
}
/* -------------------------------------------- */
/**
* Present a Dialog form which creates a damage roll once submitted
* @return {Promise<Roll>}
* @private
* Determines whether this d20 roll should be fast-forwarded, and whether advantage or disadvantage should be applied
* @returns {{isFF: boolean, isCritical: boolean}} Whether the roll is fast-forward, and whether it is a critical hit
*/
async function _damageRollDialog({template, title, parts, data, allowCritical, rollMode, dialogOptions, roll}={}) {
// Render modal dialog
template = template || "systems/sw5e/templates/chat/roll-dialog.html";
let dialogData = {
formula: parts.join(" + "),
data: data,
rollMode: rollMode,
rollModes: CONFIG.Dice.rollModes
};
const html = await renderTemplate(template, dialogData);
// Create the Dialog window
return new Promise(resolve => {
new Dialog({
title: title,
content: html,
buttons: {
critical: {
condition: allowCritical,
label: game.i18n.localize("SW5E.CriticalHit"),
callback: html => resolve(roll(parts, true, html[0].querySelector("form")))
},
normal: {
label: game.i18n.localize(allowCritical ? "SW5E.Normal" : "SW5E.Roll"),
callback: html => resolve(roll(parts, false, html[0].querySelector("form")))
},
},
default: "normal",
close: () => resolve(null)
}, dialogOptions).render(true);
});
function _determineCriticalMode({event, critical = false, fastForward = false} = {}) {
const isFF = fastForward || (event && (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey));
if (event?.altKey) critical = true;
return {isFF, isCritical: critical};
}

230
module/dice/d20-roll.js Normal file
View file

@ -0,0 +1,230 @@
/**
* A type of Roll specific to a d20-based check, save, or attack roll in the 5e system.
* @param {string} formula The string formula to parse
* @param {object} data The data object against which to parse attributes within the formula
* @param {object} [options={}] Extra optional arguments which describe or modify the D20Roll
* @param {number} [options.advantageMode] What advantage modifier to apply to the roll (none, advantage, disadvantage)
* @param {number} [options.critical] The value of d20 result which represents a critical success
* @param {number} [options.fumble] The value of d20 result which represents a critical failure
* @param {(number)} [options.targetValue] Assign a target value against which the result of this roll should be compared
* @param {boolean} [options.elvenAccuracy=false] Allow Elven Accuracy to modify this roll?
* @param {boolean} [options.halflingLucky=false] Allow Halfling Luck to modify this roll?
* @param {boolean} [options.reliableTalent=false] Allow Reliable Talent to modify this roll?
*/
// TODO: Check elven accuracy, halfling lucky, and reliable talent are required
// Elven Accuracy is Supreme accuracy feat, Reliable Talent is operative's Reliable Talent Class Feat
export default class D20Roll extends Roll {
constructor(formula, data, options) {
super(formula, data, options);
if (!(this.terms[0] instanceof Die && this.terms[0].faces === 20)) {
throw new Error(`Invalid D20Roll formula provided ${this._formula}`);
}
this.configureModifiers();
}
/* -------------------------------------------- */
/**
* Advantage mode of a 5e d20 roll
* @enum {number}
*/
static ADV_MODE = {
NORMAL: 0,
ADVANTAGE: 1,
DISADVANTAGE: -1
};
/**
* The HTML template path used to configure evaluation of this Roll
* @type {string}
*/
static EVALUATION_TEMPLATE = "systems/sw5e/templates/chat/roll-dialog.html";
/* -------------------------------------------- */
/**
* A convenience reference for whether this D20Roll has advantage
* @type {boolean}
*/
get hasAdvantage() {
return this.options.advantageMode === D20Roll.ADV_MODE.ADVANTAGE;
}
/**
* A convenience reference for whether this D20Roll has disadvantage
* @type {boolean}
*/
get hasDisadvantage() {
return this.options.advantageMode === D20Roll.ADV_MODE.DISADVANTAGE;
}
/* -------------------------------------------- */
/* D20 Roll Methods */
/* -------------------------------------------- */
/**
* Apply optional modifiers which customize the behavior of the d20term
* @private
*/
configureModifiers() {
const d20 = this.terms[0];
d20.modifiers = [];
// Halfling Lucky
if (this.options.halflingLucky) d20.modifiers.push("r1=1");
// Reliable Talent
if (this.options.reliableTalent) d20.modifiers.push("min10");
// Handle Advantage or Disadvantage
if (this.hasAdvantage) {
d20.number = this.options.elvenAccuracy ? 3 : 2;
d20.modifiers.push("kh");
d20.options.advantage = true;
} else if (this.hasDisadvantage) {
d20.number = 2;
d20.modifiers.push("kl");
d20.options.disadvantage = true;
} else d20.number = 1;
// Assign critical and fumble thresholds
if (this.options.critical) d20.options.critical = this.options.critical;
if (this.options.fumble) d20.options.fumble = this.options.fumble;
if (this.options.targetValue) d20.options.target = this.options.targetValue;
// Re-compile the underlying formula
this._formula = this.constructor.getFormula(this.terms);
}
/* -------------------------------------------- */
/** @inheritdoc */
async toMessage(messageData = {}, options = {}) {
// Evaluate the roll now so we have the results available to determine whether reliable talent came into play
if (!this._evaluated) await this.evaluate({async: true});
// Add appropriate advantage mode message flavor and sw5e roll flags
messageData.flavor = messageData.flavor || this.options.flavor;
if (this.hasAdvantage) messageData.flavor += ` (${game.i18n.localize("SW5E.Advantage")})`;
else if (this.hasDisadvantage) messageData.flavor += ` (${game.i18n.localize("SW5E.Disadvantage")})`;
// Add reliable talent to the d20-term flavor text if it applied
if (this.options.reliableTalent) {
const d20 = this.dice[0];
const isRT = d20.results.every((r) => !r.active || r.result < 10);
const label = `(${game.i18n.localize("SW5E.FlagsReliableTalent")})`;
if (isRT) d20.options.flavor = d20.options.flavor ? `${d20.options.flavor} (${label})` : label;
}
// Record the preferred rollMode
options.rollMode = options.rollMode ?? this.options.rollMode;
return super.toMessage(messageData, options);
}
/* -------------------------------------------- */
/* Configuration Dialog */
/* -------------------------------------------- */
/**
* Create a Dialog prompt used to configure evaluation of an existing D20Roll instance.
* @param {object} data Dialog configuration data
* @param {string} [data.title] The title of the shown dialog window
* @param {number} [data.defaultRollMode] The roll mode that the roll mode select element should default to
* @param {number} [data.defaultAction] The button marked as default
* @param {boolean} [data.chooseModifier] Choose which ability modifier should be applied to the roll?
* @param {string} [data.defaultAbility] For tool rolls, the default ability modifier applied to the roll
* @param {string} [data.template] A custom path to an HTML template to use instead of the default
* @param {object} options Additional Dialog customization options
* @returns {Promise<D20Roll|null>} A resulting D20Roll object constructed with the dialog, or null if the dialog was closed
*/
async configureDialog(
{
title,
defaultRollMode,
defaultAction = D20Roll.ADV_MODE.NORMAL,
chooseModifier = false,
defaultAbility,
template
} = {},
options = {}
) {
// Render the Dialog inner HTML
const content = await renderTemplate(template ?? this.constructor.EVALUATION_TEMPLATE, {
formula: `${this.formula} + @bonus`,
defaultRollMode,
rollModes: CONFIG.Dice.rollModes,
chooseModifier,
defaultAbility,
abilities: CONFIG.SW5E.abilities
});
let defaultButton = "normal";
switch (defaultAction) {
case D20Roll.ADV_MODE.ADVANTAGE:
defaultButton = "advantage";
break;
case D20Roll.ADV_MODE.DISADVANTAGE:
defaultButton = "disadvantage";
break;
}
// Create the Dialog window and await submission of the form
return new Promise((resolve) => {
new Dialog(
{
title,
content,
buttons: {
advantage: {
label: game.i18n.localize("SW5E.Advantage"),
callback: (html) => resolve(this._onDialogSubmit(html, D20Roll.ADV_MODE.ADVANTAGE))
},
normal: {
label: game.i18n.localize("SW5E.Normal"),
callback: (html) => resolve(this._onDialogSubmit(html, D20Roll.ADV_MODE.NORMAL))
},
disadvantage: {
label: game.i18n.localize("SW5E.Disadvantage"),
callback: (html) => resolve(this._onDialogSubmit(html, D20Roll.ADV_MODE.DISADVANTAGE))
}
},
default: defaultButton,
close: () => resolve(null)
},
options
).render(true);
});
}
/* -------------------------------------------- */
/**
* Handle submission of the Roll evaluation configuration Dialog
* @param {jQuery} html The submitted dialog content
* @param {number} advantageMode The chosen advantage mode
* @private
*/
_onDialogSubmit(html, advantageMode) {
const form = html[0].querySelector("form");
// Append a situational bonus term
if (form.bonus.value) {
const bonus = new Roll(form.bonus.value, this.data);
if (!(bonus.terms[0] instanceof OperatorTerm)) this.terms.push(new OperatorTerm({operator: "+"}));
this.terms = this.terms.concat(bonus.terms);
}
// Customize the modifier
if (form.ability?.value) {
const abl = this.data.abilities[form.ability.value];
this.terms.findSplice((t) => t.term === "@mod", new NumericTerm({number: abl.mod}));
this.options.flavor += ` (${CONFIG.SW5E.abilities[form.ability.value]})`;
}
// Apply advantage or disadvantage
this.options.advantageMode = advantageMode;
this.options.rollMode = form.rollMode.value;
this.configureModifiers();
return this;
}
}

186
module/dice/damage-roll.js Normal file
View file

@ -0,0 +1,186 @@
/**
* A type of Roll specific to a damage (or healing) roll in the 5e system.
* @param {string} formula The string formula to parse
* @param {object} data The data object against which to parse attributes within the formula
* @param {object} [options={}] Extra optional arguments which describe or modify the DamageRoll
* @param {number} [options.criticalBonusDice=0] A number of bonus damage dice that are added for critical hits
* @param {number} [options.criticalMultiplier=2] A critical hit multiplier which is applied to critical hits
* @param {boolean} [options.multiplyNumeric=false] Multiply numeric terms by the critical multiplier
* @param {boolean} [options.powerfulCritical=false] Apply the "powerful criticals" house rule to critical hits
*
*/
export default class DamageRoll extends Roll {
constructor(formula, data, options) {
super(formula, data, options);
// For backwards compatibility, skip rolls which do not have the "critical" option defined
if (this.options.critical !== undefined) this.configureDamage();
}
/**
* The HTML template path used to configure evaluation of this Roll
* @type {string}
*/
static EVALUATION_TEMPLATE = "systems/sw5e/templates/chat/roll-dialog.html";
/* -------------------------------------------- */
/**
* A convenience reference for whether this DamageRoll is a critical hit
* @type {boolean}
*/
get isCritical() {
return this.options.critical;
}
/* -------------------------------------------- */
/* Damage Roll Methods */
/* -------------------------------------------- */
/**
* Apply optional modifiers which customize the behavior of the d20term
* @private
*/
configureDamage() {
let flatBonus = 0;
for (let [i, term] of this.terms.entries()) {
// Multiply dice terms
if (term instanceof DiceTerm) {
term.options.baseNumber = term.options.baseNumber ?? term.number; // Reset back
term.number = term.options.baseNumber;
if (this.isCritical) {
let cm = this.options.criticalMultiplier ?? 2;
// Powerful critical - maximize damage and reduce the multiplier by 1
if (this.options.powerfulCritical) {
flatBonus += term.number * term.faces;
cm = Math.max(1, cm - 1);
}
// Alter the damage term
let cb = this.options.criticalBonusDice && i === 0 ? this.options.criticalBonusDice : 0;
term.alter(cm, cb);
term.options.critical = true;
}
}
// Multiply numeric terms
else if (this.options.multiplyNumeric && term instanceof NumericTerm) {
term.options.baseNumber = term.options.baseNumber ?? term.number; // Reset back
term.number = term.options.baseNumber;
if (this.isCritical) {
term.number *= this.options.criticalMultiplier ?? 2;
term.options.critical = true;
}
}
}
// Add powerful critical bonus
if (this.options.powerfulCritical && flatBonus > 0) {
this.terms.push(new OperatorTerm({operator: "+"}));
this.terms.push(
new NumericTerm({number: flatBonus}, {flavor: game.i18n.localize("SW5E.PowerfulCritical")})
);
}
// Re-compile the underlying formula
this._formula = this.constructor.getFormula(this.terms);
}
/* -------------------------------------------- */
/** @inheritdoc */
toMessage(messageData = {}, options = {}) {
messageData.flavor = messageData.flavor || this.options.flavor;
if (this.isCritical) {
const label = game.i18n.localize("SW5E.CriticalHit");
messageData.flavor = messageData.flavor ? `${messageData.flavor} (${label})` : label;
}
options.rollMode = options.rollMode ?? this.options.rollMode;
return super.toMessage(messageData, options);
}
/* -------------------------------------------- */
/* Configuration Dialog */
/* -------------------------------------------- */
/**
* Create a Dialog prompt used to configure evaluation of an existing D20Roll instance.
* @param {object} data Dialog configuration data
* @param {string} [data.title] The title of the shown dialog window
* @param {number} [data.defaultRollMode] The roll mode that the roll mode select element should default to
* @param {string} [data.defaultCritical] Should critical be selected as default
* @param {string} [data.template] A custom path to an HTML template to use instead of the default
* @param {boolean} [data.allowCritical=true] Allow critical hit to be chosen as a possible damage mode
* @param {object} options Additional Dialog customization options
* @returns {Promise<D20Roll|null>} A resulting D20Roll object constructed with the dialog, or null if the dialog was closed
*/
async configureDialog(
{title, defaultRollMode, defaultCritical = false, template, allowCritical = true} = {},
options = {}
) {
// Render the Dialog inner HTML
const content = await renderTemplate(template ?? this.constructor.EVALUATION_TEMPLATE, {
formula: `${this.formula} + @bonus`,
defaultRollMode,
rollModes: CONFIG.Dice.rollModes
});
// Create the Dialog window and await submission of the form
return new Promise((resolve) => {
new Dialog(
{
title,
content,
buttons: {
critical: {
condition: allowCritical,
label: game.i18n.localize("SW5E.CriticalHit"),
callback: (html) => resolve(this._onDialogSubmit(html, true))
},
normal: {
label: game.i18n.localize(allowCritical ? "SW5E.Normal" : "SW5E.Roll"),
callback: (html) => resolve(this._onDialogSubmit(html, false))
}
},
default: defaultCritical ? "critical" : "normal",
close: () => resolve(null)
},
options
).render(true);
});
}
/* -------------------------------------------- */
/**
* Handle submission of the Roll evaluation configuration Dialog
* @param {jQuery} html The submitted dialog content
* @param {boolean} isCritical Is the damage a critical hit?
* @private
*/
_onDialogSubmit(html, isCritical) {
const form = html[0].querySelector("form");
// Append a situational bonus term
if (form.bonus.value) {
const bonus = new Roll(form.bonus.value, this.data);
if (!(bonus.terms[0] instanceof OperatorTerm)) this.terms.push(new OperatorTerm({operator: "+"}));
this.terms = this.terms.concat(bonus.terms);
}
// Apply advantage or disadvantage
this.options.critical = isCritical;
this.options.rollMode = form.rollMode.value;
this.configureDamage();
return this;
}
/* -------------------------------------------- */
/** @inheritdoc */
static fromData(data) {
const roll = super.fromData(data);
roll._formula = this.getFormula(roll.terms);
return roll;
}
}

View file

@ -0,0 +1,15 @@
/**
* @deprecated since 1.3.0
* @ignore
*/
async function d20Dialog(data, options) {
throw new Error(`The d20Dialog helper method is deprecated in favor of D20Roll#configureDialog`);
}
/**
* @deprecated since 1.3.0
* @ignore
*/
async function damageDialog(data, options) {
throw new Error(`The damageDialog helper method is deprecated in favor of DamageRoll#configureDialog`);
}

29
module/effects.js vendored
View file

@ -8,15 +8,17 @@ export function onManageActiveEffect(event, owner) {
const a = event.currentTarget;
const li = a.closest("li");
const effect = li.dataset.effectId ? owner.effects.get(li.dataset.effectId) : null;
switch ( a.dataset.action ) {
switch (a.dataset.action) {
case "create":
return ActiveEffect.create({
label: "New Effect",
icon: "icons/svg/aura.svg",
origin: owner.uuid,
return owner.createEmbeddedDocuments("ActiveEffect", [
{
"label": game.i18n.localize("SW5E.EffectNew"),
"icon": "icons/svg/aura.svg",
"origin": owner.uuid,
"duration.rounds": li.dataset.effectType === "temporary" ? 1 : undefined,
disabled: li.dataset.effectType === "inactive"
}, owner).create();
"disabled": li.dataset.effectType === "inactive"
}
]);
case "edit":
return effect.sheet.render(true);
case "delete":
@ -32,31 +34,30 @@ export function onManageActiveEffect(event, owner) {
* @return {object} Data for rendering
*/
export function prepareActiveEffectCategories(effects) {
// Define effect header categories
const categories = {
temporary: {
type: "temporary",
label: "SW5E.EffectsCategoryTemporary",
label: game.i18n.localize("SW5E.EffectTemporary"),
effects: []
},
passive: {
type: "passive",
label: "SW5E.EffectsCategoryPassive",
label: game.i18n.localize("SW5E.EffectPassive"),
effects: []
},
inactive: {
type: "inactive",
label: "SW5E.EffectsCategoryInactive",
label: game.i18n.localize("SW5E.EffectInactive"),
effects: []
}
};
// Iterate over active effects, classifying them into categories
for ( let e of effects ) {
for (let e of effects) {
e._getSourceName(); // Trigger a lookup for the source name
if ( e.data.disabled ) categories.inactive.effects.push(e);
else if ( e.isTemporary ) categories.temporary.effects.push(e);
if (e.data.disabled) categories.inactive.effects.push(e);
else if (e.isTemporary) categories.temporary.effects.push(e);
else categories.passive.effects.push(e);
}
return categories;

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
import TraitSelector from "../apps/trait-selector.js";
import { onManageActiveEffect, prepareActiveEffectCategories } from "../effects.js";
import {onManageActiveEffect, prepareActiveEffectCategories} from "../effects.js";
/**
* Override and extend the core ItemSheet implementation to handle specific item types
@ -18,21 +18,21 @@ export default class ItemSheet5e extends ItemSheet {
/* -------------------------------------------- */
/** @override */
/** @inheritdoc */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
return foundry.utils.mergeObject(super.defaultOptions, {
width: 560,
height: 400,
classes: ["sw5e", "sheet", "item"],
resizable: true,
scrollY: [".tab.details"],
tabs: [{ navSelector: ".tabs", contentSelector: ".sheet-body", initial: "description" }]
tabs: [{navSelector: ".tabs", contentSelector: ".sheet-body", initial: "description"}]
});
}
/* -------------------------------------------- */
/** @override */
/** @inheritdoc */
get template() {
const path = "systems/sw5e/templates/items/";
return `${path}/${this.item.data.type}.html`;
@ -43,33 +43,39 @@ export default class ItemSheet5e extends ItemSheet {
/** @override */
async getData(options) {
const data = super.getData(options);
const itemData = data.data;
data.labels = this.item.labels;
data.config = CONFIG.SW5E;
// Item Type, Status, and Details
data.itemType = game.i18n.localize(`ITEM.Type${data.item.type.titleCase()}`);
data.itemStatus = this._getItemStatus(data.item);
data.itemProperties = this._getItemProperties(data.item);
data.isPhysical = data.item.data.hasOwnProperty("quantity");
data.itemStatus = this._getItemStatus(itemData);
data.itemProperties = this._getItemProperties(itemData);
data.isPhysical = itemData.data.hasOwnProperty("quantity");
// Potential consumption targets
data.abilityConsumptionTargets = this._getItemConsumptionTargets(data.item);
data.abilityConsumptionTargets = this._getItemConsumptionTargets(itemData);
// Action Detail
// Action Details
data.hasAttackRoll = this.item.hasAttack;
data.isHealing = data.item.data.actionType === "heal";
data.isFlatDC = getProperty(data.item.data, "save.scaling") === "flat";
data.isLine = ["line", "wall"].includes(data.item.data.target?.type);
data.isHealing = itemData.data.actionType === "heal";
data.isFlatDC = getProperty(itemData, "data.save.scaling") === "flat";
data.isLine = ["line", "wall"].includes(itemData.data.target?.type);
// Original maximum uses formula
if (this.item._data.data?.uses?.max) data.data.uses.max = this.item._data.data.uses.max;
const sourceMax = foundry.utils.getProperty(this.item.data._source, "data.uses.max");
if (sourceMax) itemData.data.uses.max = sourceMax;
// Vehicles
data.isCrewed = data.item.data.activation?.type === "crew";
data.isMountable = this._isItemMountable(data.item);
data.isCrewed = itemData.data.activation?.type === "crew";
data.isMountable = this._isItemMountable(itemData);
// Prepare Active Effects
data.effects = prepareActiveEffectCategories(this.entity.effects);
data.effects = prepareActiveEffectCategories(this.item.effects);
// Re-define the template data references (backwards compatible)
data.item = itemData;
data.data = itemData.data;
return data;
}
@ -96,15 +102,17 @@ export default class ItemSheet5e extends ItemSheet {
}
return ammo;
},
{ [item._id]: `${item.name} (${item.data.quantity})` }
{[item._id]: `${item.name} (${item.data.quantity})`}
);
}
// Attributes
else if (consume.type === "attribute") {
const attributes = Object.values(CombatTrackerConfig.prototype.getAttributeChoices())[0]; // Bit of a hack
return attributes.reduce((obj, a) => {
obj[a] = a;
const attributes = TokenDocument.getTrackedAttributes(actor.data.data);
attributes.bar.forEach((a) => a.push("value"));
return attributes.bar.concat(attributes.value).reduce((obj, a) => {
let k = a.join(".");
obj[k] = k;
return obj;
}, {});
}
@ -127,8 +135,11 @@ export default class ItemSheet5e extends ItemSheet {
if (uses.per && uses.max) {
const label =
uses.per === "charges"
? ` (${game.i18n.format("SW5E.AbilityUseChargesLabel", { value: uses.value })})`
: ` (${game.i18n.format("SW5E.AbilityUseConsumableLabel", { max: uses.max, per: uses.per })})`;
? ` (${game.i18n.format("SW5E.AbilityUseChargesLabel", {value: uses.value})})`
: ` (${game.i18n.format("SW5E.AbilityUseConsumableLabel", {
max: uses.max,
per: uses.per
})})`;
obj[i.id] = i.name + label;
}
@ -176,7 +187,6 @@ export default class ItemSheet5e extends ItemSheet {
);
} else if (item.type === "power") {
props.push(
labels.components,
labels.materials,
item.data.components.concentration ? game.i18n.localize("SW5E.Concentration") : null,
item.data.components.ritual ? game.i18n.localize("SW5E.Ritual") : null
@ -186,6 +196,7 @@ export default class ItemSheet5e extends ItemSheet {
props.push(labels.armor);
} else if (item.type === "feat") {
props.push(labels.featType);
//TODO: Work out these
} else if (item.type === "species") {
//props.push(labels.species);
} else if (item.type === "archetype") {
@ -238,7 +249,7 @@ export default class ItemSheet5e extends ItemSheet {
/* -------------------------------------------- */
/** @override */
/** @inheritdoc */
setPosition(position = {}) {
if (!(this._minimized || position.height)) {
position.height = this._tabs[0].active === "details" ? "auto" : this.options.height;
@ -250,10 +261,10 @@ export default class ItemSheet5e extends ItemSheet {
/* Form Submission */
/* -------------------------------------------- */
/** @override */
/** @inheritdoc */
_getSubmitData(updateData = {}) {
// Create the expanded update data object
const fd = new FormDataExtended(this.form, { editors: this.editors });
const fd = new FormDataExtended(this.form, {editors: this.editors});
let data = fd.toObject();
if (updateData) data = mergeObject(data, updateData);
else data = expandObject(data);
@ -268,12 +279,12 @@ export default class ItemSheet5e extends ItemSheet {
/* -------------------------------------------- */
/** @override */
/** @inheritdoc */
activateListeners(html) {
super.activateListeners(html);
if (this.isEditable) {
html.find(".damage-control").click(this._onDamageControl.bind(this));
html.find(".trait-selector.class-skills").click(this._onConfigureClassSkills.bind(this));
html.find(".trait-selector.class-skills").click(this._onConfigureTraits.bind(this));
html.find(".effect-control").click((ev) => {
if (this.item.isOwned)
return ui.notifications.warn(
@ -300,49 +311,58 @@ export default class ItemSheet5e extends ItemSheet {
if (a.classList.contains("add-damage")) {
await this._onSubmit(event); // Submit any unsaved changes
const damage = this.item.data.data.damage;
return this.item.update({ "data.damage.parts": damage.parts.concat([["", ""]]) });
return this.item.update({"data.damage.parts": damage.parts.concat([["", ""]])});
}
// Remove a damage component
if (a.classList.contains("delete-damage")) {
await this._onSubmit(event); // Submit any unsaved changes
const li = a.closest(".damage-part");
const damage = duplicate(this.item.data.data.damage);
const damage = foundry.utils.deepClone(this.item.data.data.damage);
damage.parts.splice(Number(li.dataset.damagePart), 1);
return this.item.update({ "data.damage.parts": damage.parts });
return this.item.update({"data.damage.parts": damage.parts});
}
}
/* -------------------------------------------- */
/**
* Handle spawning the TraitSelector application which allows a checkbox of multiple trait options
* Handle spawning the TraitSelector application for selection various options.
* @param {Event} event The click event which originated the selection
* @private
*/
_onConfigureClassSkills(event) {
_onConfigureTraits(event) {
event.preventDefault();
const skills = this.item.data.data.skills;
const choices = skills.choices && skills.choices.length ? skills.choices : Object.keys(CONFIG.SW5E.skills);
const a = event.currentTarget;
const label = a.parentElement;
// Render the Trait Selector dialog
new TraitSelector(this.item, {
const options = {
name: a.dataset.target,
title: label.innerText,
choices: Object.entries(CONFIG.SW5E.skills).reduce((obj, e) => {
if (choices.includes(e[0])) obj[e[0]] = e[1];
return obj;
}, {}),
minimum: skills.number,
maximum: skills.number
}).render(true);
title: a.parentElement.innerText,
choices: [],
allowCustom: false
};
switch (a.dataset.options) {
case "saves":
options.choices = CONFIG.SW5E.abilities;
options.valueKey = null;
break;
case "skills":
const skills = this.item.data.data.skills;
const choiceSet =
skills.choices && skills.choices.length ? skills.choices : Object.keys(CONFIG.SW5E.skills);
options.choices = Object.fromEntries(
Object.entries(CONFIG.SW5E.skills).filter((skill) => choiceSet.includes(skill[0]))
);
options.maximum = skills.number;
break;
}
new TraitSelector(this.item, options).render(true);
}
/* -------------------------------------------- */
/** @override */
/** @inheritdoc */
async _onSubmit(...args) {
if (this._tabs[0].active === "details") this.position.height = "auto";
await super._onSubmit(...args);

View file

@ -1,4 +1,3 @@
/* -------------------------------------------- */
/* Hotbar Macros */
/* -------------------------------------------- */
@ -11,14 +10,14 @@
* @returns {Promise}
*/
export async function create5eMacro(data, slot) {
if ( data.type !== "Item" ) return;
if (!( "data" in data ) ) return ui.notifications.warn("You can only create macro buttons for owned Items");
if (data.type !== "Item") return;
if (!("data" in data)) return ui.notifications.warn("You can only create macro buttons for owned Items");
const item = data.data;
// Create the macro command
const command = `game.sw5e.rollItemMacro("${item.name}");`;
let macro = game.macros.entities.find(m => (m.name === item.name) && (m.command === command));
if ( !macro ) {
let macro = game.macros.entities.find((m) => m.name === item.name && m.command === command);
if (!macro) {
macro = await Macro.create({
name: item.name,
type: "script",
@ -42,14 +41,16 @@ export async function create5eMacro(data, slot) {
export function rollItemMacro(itemName) {
const speaker = ChatMessage.getSpeaker();
let actor;
if ( speaker.token ) actor = game.actors.tokens[speaker.token];
if ( !actor ) actor = game.actors.get(speaker.actor);
if (speaker.token) actor = game.actors.tokens[speaker.token];
if (!actor) actor = game.actors.get(speaker.actor);
// Get matching items
const items = actor ? actor.items.filter(i => i.name === itemName) : [];
if ( items.length > 1 ) {
ui.notifications.warn(`Your controlled Actor ${actor.name} has more than one Item with name ${itemName}. The first matched item will be chosen.`);
} else if ( items.length === 0 ) {
const items = actor ? actor.items.filter((i) => i.name === itemName) : [];
if (items.length > 1) {
ui.notifications.warn(
`Your controlled Actor ${actor.name} has more than one Item with name ${itemName}. The first matched item will be chosen.`
);
} else if (items.length === 0) {
return ui.notifications.warn(`Your controlled Actor does not have an item named ${itemName}`);
}
const item = items[0];

View file

@ -2,56 +2,62 @@
* Perform a system migration for the entire World, applying migrations for Actors, Items, and Compendium packs
* @return {Promise} A Promise which resolves once the migration is completed
*/
export const migrateWorld = async function() {
ui.notifications.info(`Applying SW5e System Migration for version ${game.system.data.version}. Please be patient and do not close your game or shut down your server.`, {permanent: true});
export const migrateWorld = async function () {
ui.notifications.info(
`Applying SW5e System Migration for version ${game.system.data.version}. Please be patient and do not close your game or shut down your server.`,
{permanent: true}
);
// Migrate World Actors
for await ( let a of game.actors.entities ) {
for await (let a of game.actors.contents) {
try {
console.log(`Checking Actor entity ${a.name} for migration needs`);
const updateData = await migrateActorData(a.data);
if ( !isObjectEmpty(updateData) ) {
if (!foundry.utils.isObjectEmpty(updateData)) {
console.log(`Migrating Actor entity ${a.name}`);
await a.update(updateData, {enforceTypes: false});
}
} catch(err) {
} catch (err) {
err.message = `Failed sw5e system migration for Actor ${a.name}: ${err.message}`;
console.error(err);
}
}
// Migrate World Items
for ( let i of game.items.entities ) {
for (let i of game.items.contents) {
try {
const updateData = migrateItemData(i.data);
if ( !isObjectEmpty(updateData) ) {
const updateData = migrateItemData(i.toObject());
if (!foundry.utils.isObjectEmpty(updateData)) {
console.log(`Migrating Item entity ${i.name}`);
await i.update(updateData, {enforceTypes: false});
}
} catch(err) {
} catch (err) {
err.message = `Failed sw5e system migration for Item ${i.name}: ${err.message}`;
console.error(err);
}
}
// Migrate Actor Override Tokens
for ( let s of game.scenes.entities ) {
for (let s of game.scenes.contents) {
try {
const updateData = await migrateSceneData(s.data);
if ( !isObjectEmpty(updateData) ) {
if (!foundry.utils.isObjectEmpty(updateData)) {
console.log(`Migrating Scene entity ${s.name}`);
await s.update(updateData, {enforceTypes: false});
// If we do not do this, then synthetic token actors remain in cache
// with the un-updated actorData.
s.tokens.contents.forEach((t) => (t._actor = null));
}
} catch(err) {
} catch (err) {
err.message = `Failed sw5e system migration for Scene ${s.name}: ${err.message}`;
console.error(err);
}
}
// Migrate World Compendium Packs
for ( let p of game.packs ) {
if ( p.metadata.package !== "world" ) continue;
if ( !["Actor", "Item", "Scene"].includes(p.metadata.entity) ) continue;
for (let p of game.packs) {
if (p.metadata.package !== "world") continue;
if (!["Actor", "Item", "Scene"].includes(p.metadata.entity)) continue;
await migrateCompendium(p);
}
@ -67,9 +73,9 @@ export const migrateWorld = async function() {
* @param pack
* @return {Promise}
*/
export const migrateCompendium = async function(pack) {
export const migrateCompendium = async function (pack) {
const entity = pack.metadata.entity;
if ( !["Actor", "Item", "Scene"].includes(entity) ) return;
if (!["Actor", "Item", "Scene"].includes(entity)) return;
// Unlock the pack for editing
const wasLocked = pack.locked;
@ -77,40 +83,37 @@ export const migrateCompendium = async function(pack) {
// Begin by requesting server-side data model migration and get the migrated content
await pack.migrate();
const content = await pack.getContent();
const documents = await pack.getDocuments();
// Iterate over compendium entries - applying fine-tuned migration functions
for await ( let ent of content ) {
for await (let doc of documents) {
let updateData = {};
try {
switch (entity) {
case "Actor":
updateData = await migrateActorData(ent.data);
updateData = await migrateActorData(doc.data);
break;
case "Item":
updateData = migrateItemData(ent.data);
updateData = migrateItemData(doc.toObject());
break;
case "Scene":
updateData = await migrateSceneData(ent.data);
updateData = await migrateSceneData(doc.data);
break;
}
if ( isObjectEmpty(updateData) ) continue;
if (foundry.utils.isObjectEmpty(updateData)) continue;
// Save the entry, if data was changed
updateData["_id"] = ent._id;
await pack.updateEntity(updateData);
console.log(`Migrated ${entity} entity ${ent.name} in Compendium ${pack.collection}`);
}
await doc.update(updateData);
console.log(`Migrated ${entity} entity ${doc.name} in Compendium ${pack.collection}`);
} catch (err) {
// Handle migration failures
catch(err) {
err.message = `Failed sw5e system migration for entity ${ent.name} in pack ${pack.collection}: ${err.message}`;
err.message = `Failed sw5e system migration for entity ${doc.name} in pack ${pack.collection}: ${err.message}`;
console.error(err);
}
}
// Apply the original locked status for the pack
pack.configure({locked: wasLocked});
await pack.configure({locked: wasLocked});
console.log(`Migrated all ${entity} entities from Compendium ${pack.collection}`);
};
@ -124,38 +127,44 @@ export const migrateCompendium = async function(pack) {
* @param {object} actor The actor data object to update
* @return {Object} The updateData to apply
*/
export const migrateActorData = async function(actor) {
export const migrateActorData = async function (actor) {
const updateData = {};
// Actor Data Updates
if (actor.data) {
_migrateActorMovement(actor, updateData);
_migrateActorSenses(actor, updateData);
_migrateActorType(actor, updateData);
}
// Migrate Owned Items
if ( !!actor.items ) {
let hasItemUpdates = false;
if (!!actor.items) {
const items = await actor.items.reduce(async (memo, i) => {
const results = await memo;
// Migrate the Owned Item
let itemUpdate = await migrateActorItemData(i, actor);
const itemData = i instanceof CONFIG.Item.documentClass ? i.toObject() : i;
let itemUpdate = await migrateActorItemData(itemData, actor);
// Prepared, Equipped, and Proficient for NPC actors
if ( actor.type === "npc" ) {
if (getProperty(i.data, "preparation.prepared") === false) itemUpdate["data.preparation.prepared"] = true;
if (getProperty(i.data, "equipped") === false) itemUpdate["data.equipped"] = true;
if (getProperty(i.data, "proficient") === false) itemUpdate["data.proficient"] = true;
if (actor.type === "npc") {
if (getProperty(itemData.data, "preparation.prepared") === false)
itemUpdate["data.preparation.prepared"] = true;
if (getProperty(itemData.data, "equipped") === false) itemUpdate["data.equipped"] = true;
if (getProperty(itemData.data, "proficient") === false) itemUpdate["data.proficient"] = true;
}
// Update the Owned Item
if ( !isObjectEmpty(itemUpdate) ) {
hasItemUpdates = true;
if (!isObjectEmpty(itemUpdate)) {
itemUpdate._id = itemData._id;
console.log(`Migrating Actor ${actor.name}'s ${i.name}`);
return [...results, mergeObject(i, itemUpdate, {enforceTypes: false, inplace: false})];
} else return [...results, i];
results.push(expandObject(itemUpdate));
}
return results;
}, []);
if ( hasItemUpdates ) updateData.items = items;
if (items.length > 0) updateData.items = items;
}
// Update NPC data with new datamodel information
@ -171,14 +180,12 @@ export const migrateActorData = async function(actor) {
/* -------------------------------------------- */
/**
* Scrub an Actor's system data, removing all keys which are not explicitly defined in the system template
* @param {Object} actorData The data object for an Actor
* @return {Object} The scrubbed Actor data
*/
function cleanActorData(actorData) {
// Scrub system data
const model = game.system.model.Actor[actorData.type];
actorData.data = filterObject(actorData.data, model);
@ -188,7 +195,7 @@ function cleanActorData(actorData) {
obj[f] = null;
return obj;
}, {});
if ( actorData.flags.sw5e ) {
if (actorData.flags.sw5e) {
actorData.flags.sw5e = filterObject(actorData.flags.sw5e, allowedFlags);
}
@ -196,14 +203,15 @@ function cleanActorData(actorData) {
return actorData;
}
/* -------------------------------------------- */
/**
* Migrate a single Item entity to incorporate latest data model changes
* @param item
*
* @param {object} item Item data to migrate
* @return {object} The updateData to apply
*/
export const migrateItemData = function(item) {
export const migrateItemData = function (item) {
const updateData = {};
_migrateItemClassPowerCasting(item, updateData);
_migrateItemAttunement(item, updateData);
@ -217,7 +225,7 @@ export const migrateItemData = function(item) {
* @param item
* @param actor
*/
export const migrateActorItemData = async function(item, actor) {
export const migrateActorItemData = async function (item, actor) {
const updateData = {};
_migrateItemClassPowerCasting(item, updateData);
_migrateItemAttunement(item, updateData);
@ -233,25 +241,35 @@ export const migrateActorItemData = async function(item, actor) {
* @param {Object} scene The Scene data to Update
* @return {Object} The updateData to apply
*/
export const migrateSceneData = async function(scene) {
const tokens = duplicate(scene.tokens);
return {
tokens: await Promise.all(tokens.map(async (t) => {
if (!t.actorId || t.actorLink || !t.actorData.data) {
export const migrateSceneData = async function (scene) {
const tokens = await Promise.all(
scene.tokens.map(async (token) => {
const t = token.toJSON();
if (!t.actorId || t.actorLink) {
t.actorData = {};
return t;
}
const token = new Token(t);
if ( !token.actor ) {
} else if (!game.actors.has(t.actorId)) {
t.actorId = null;
t.actorData = {};
} else if ( !t.actorLink ) {
const updateData = await migrateActorData(token.data.actorData);
t.actorData = mergeObject(token.data.actorData, updateData);
} else if (!t.actorLink) {
const actorData = duplicate(t.actorData);
actorData.type = token.actor?.type;
const update = migrateActorData(actorData);
["items", "effects"].forEach((embeddedName) => {
if (!update[embeddedName]?.length) return;
const updates = new Map(update[embeddedName].map((u) => [u._id, u]));
t.actorData[embeddedName].forEach((original) => {
const update = updates.get(original._id);
if (update) mergeObject(original, update);
});
delete update[embeddedName];
});
mergeObject(t.actorData, update);
}
return t;
}))
};
})
);
return {tokens};
};
/* -------------------------------------------- */
@ -266,7 +284,6 @@ export const migrateActorItemData = async function(item, actor) {
* @return {Object} The updated Actor
*/
function _updateNPCData(actor) {
let actorData = actor.data;
const updateData = {};
// check for flag.core, if not there is no compendium monster so exit
@ -274,13 +291,20 @@ function _updateNPCData(actor) {
if (!hasSource) return actor;
// shortcut out if dataVersion flag is set to 1.2.4 or higher
const hasDataVersion = actor?.flags?.sw5e?.dataVersion !== undefined;
if (hasDataVersion && (actor.flags.sw5e.dataVersion === "1.2.4" || isNewerVersion("1.2.4", actor.flags.sw5e.dataVersion))) return actor;
if (
hasDataVersion &&
(actor.flags.sw5e.dataVersion === "1.2.4" || isNewerVersion("1.2.4", actor.flags.sw5e.dataVersion))
)
return actor;
// Check to see what the source of NPC is
const sourceId = actor.flags.core.sourceId;
const coreSource = sourceId.substr(0,sourceId.length-17);
const core_id = sourceId.substr(sourceId.length-16,16);
if (coreSource === "Compendium.sw5e.monsters"){
game.packs.get("sw5e.monsters").getEntity(core_id).then(monster => {
const coreSource = sourceId.substr(0, sourceId.length - 17);
const core_id = sourceId.substr(sourceId.length - 16, 16);
if (coreSource === "Compendium.sw5e.monsters") {
game.packs
.get("sw5e.monsters")
.getEntity(core_id)
.then((monster) => {
const monsterData = monster.data.data;
// copy movement[], senses[], powercasting, force[], tech[], powerForceLevel, powerTechLevel
updateData["data.attributes.movement"] = monsterData.attributes.movement;
@ -292,11 +316,13 @@ function _updateNPCData(actor) {
updateData["data.details.powerTechLevel"] = monsterData.details.powerTechLevel;
// push missing powers onto actor
let newPowers = [];
for ( let i of monster.items ) {
for (let i of monster.items) {
const itemData = i.data;
if ( itemData.type === "power" ) {
if (itemData.type === "power") {
const itemCompendium_id = itemData.flags?.core?.sourceId.split(".").slice(-1)[0];
let hasPower = !!actor.items.find(item => item.flags?.core?.sourceId.split(".").slice(-1)[0] === itemCompendium_id);
let hasPower = !!actor.items.find(
(item) => item.flags?.core?.sourceId.split(".").slice(-1)[0] === itemCompendium_id
);
if (!hasPower) {
// Clone power to new object. Don't know if it is technically needed, but seems to prevent some weirdness.
const newPower = JSON.parse(JSON.stringify(itemData));
@ -313,17 +339,15 @@ function _updateNPCData(actor) {
// set flag to check to see if migration has been done so we don't do it again.
liveActor.setFlag("sw5e", "dataVersion", "1.2.4");
})
});
}
//merge object
actorData = mergeObject(actorData, updateData);
// Return the scrubbed data
return actor;
}
/**
* Migrate the actor speed string to movement object
* @private
@ -332,21 +356,21 @@ function _migrateActorMovement(actorData, updateData) {
const ad = actorData.data;
// Work is needed if old data is present
const old = actorData.type === 'vehicle' ? ad?.attributes?.speed : ad?.attributes?.speed?.value;
const old = actorData.type === "vehicle" ? ad?.attributes?.speed : ad?.attributes?.speed?.value;
const hasOld = old !== undefined;
if ( hasOld ) {
if (hasOld) {
// If new data is not present, migrate the old data
const hasNew = ad?.attributes?.movement?.walk !== undefined;
if ( !hasNew && (typeof old === "string") ) {
if (!hasNew && typeof old === "string") {
const s = (old || "").split(" ");
if ( s.length > 0 ) updateData["data.attributes.movement.walk"] = Number.isNumeric(s[0]) ? parseInt(s[0]) : null;
if (s.length > 0)
updateData["data.attributes.movement.walk"] = Number.isNumeric(s[0]) ? parseInt(s[0]) : null;
}
// Remove the old attribute
updateData["data.attributes.-=speed"] = null;
}
return updateData
return updateData;
}
/* -------------------------------------------- */
@ -360,7 +384,7 @@ function _migrateActorPowers(actorData, updateData) {
// If new Force & Tech data is not present, create it
let hasNewAttrib = ad?.attributes?.force?.level !== undefined;
if ( !hasNewAttrib ) {
if (!hasNewAttrib) {
updateData["data.attributes.force.known.value"] = 0;
updateData["data.attributes.force.known.max"] = 0;
updateData["data.attributes.force.points.value"] = 0;
@ -381,14 +405,14 @@ function _migrateActorPowers(actorData, updateData) {
// If new Power F/T split data is not present, create it
const hasNewLimit = ad?.powers?.power1?.foverride !== undefined;
if ( !hasNewLimit ) {
if (!hasNewLimit) {
for (let i = 1; i <= 9; i++) {
// add new
updateData["data.powers.power" + i + ".fvalue"] = getProperty(ad.powers,"power" + i + ".value");
updateData["data.powers.power" + i + ".fmax"] = getProperty(ad.powers,"power" + i + ".max");
updateData["data.powers.power" + i + ".fvalue"] = getProperty(ad.powers, "power" + i + ".value");
updateData["data.powers.power" + i + ".fmax"] = getProperty(ad.powers, "power" + i + ".max");
updateData["data.powers.power" + i + ".foverride"] = null;
updateData["data.powers.power" + i + ".tvalue"] = getProperty(ad.powers,"power" + i + ".value");
updateData["data.powers.power" + i + ".tmax"] = getProperty(ad.powers,"power" + i + ".max");
updateData["data.powers.power" + i + ".tvalue"] = getProperty(ad.powers, "power" + i + ".value");
updateData["data.powers.power" + i + ".tmax"] = getProperty(ad.powers, "power" + i + ".max");
updateData["data.powers.power" + i + ".toverride"] = null;
//remove old
updateData["data.powers.power" + i + ".-=value"] = null;
@ -397,7 +421,7 @@ function _migrateActorPowers(actorData, updateData) {
}
// If new Bonus Power DC data is not present, create it
const hasNewBonus = ad?.bonuses?.power?.forceLightDC !== undefined;
if ( !hasNewBonus ) {
if (!hasNewBonus) {
updateData["data.bonuses.power.forceLightDC"] = "";
updateData["data.bonuses.power.forceDarkDC"] = "";
updateData["data.bonuses.power.forceUnivDC"] = "";
@ -407,7 +431,7 @@ function _migrateActorPowers(actorData, updateData) {
// Remove the Power DC Bonus
updateData["data.bonuses.power.-=dc"] = null;
return updateData
return updateData;
}
/* -------------------------------------------- */
@ -418,27 +442,28 @@ function _migrateActorPowers(actorData, updateData) {
*/
function _migrateActorSenses(actor, updateData) {
const ad = actor.data;
if ( ad?.traits?.senses === undefined ) return;
if (ad?.traits?.senses === undefined) return;
const original = ad.traits.senses || "";
if (typeof original !== "string") return;
// Try to match old senses with the format like "Darkvision 60 ft, Blindsight 30 ft"
const pattern = /([A-z]+)\s?([0-9]+)\s?([A-z]+)?/;
let wasMatched = false;
// Match each comma-separated term
for ( let s of original.split(",") ) {
for (let s of original.split(",")) {
s = s.trim();
const match = s.match(pattern);
if ( !match ) continue;
if (!match) continue;
const type = match[1].toLowerCase();
if ( type in CONFIG.SW5E.senses ) {
if (type in CONFIG.SW5E.senses) {
updateData[`data.attributes.senses.${type}`] = Number(match[2]).toNearest(0.5);
wasMatched = true;
}
}
// If nothing was matched, but there was an old string - put the whole thing in "special"
if ( !wasMatched && !!original ) {
if (!wasMatched && !!original) {
updateData["data.attributes.senses.special"] = original;
}
@ -449,26 +474,121 @@ function _migrateActorSenses(actor, updateData) {
/* -------------------------------------------- */
/**
* Migrate the actor details.type string to object
* @private
*/
function _migrateActorType(actor, updateData) {
const ad = actor.data;
const original = ad.details?.type;
if (typeof original !== "string") return;
// New default data structure
let data = {
value: "",
subtype: "",
swarm: "",
custom: ""
};
// Specifics
// (Some of these have weird names, these need to be addressed individually)
if (original === "force entity") {
data.value = "force";
data.subtype = "storm";
} else if (original === "human") {
data.value = "humanoid";
data.subtype = "human";
} else if (["humanoid (any)", "humanoid (Villainous"].includes(original)) {
data.value = "humanoid";
} else if (original === "tree") {
data.value = "plant";
data.subtype = "tree";
} else if (original === "(humanoid) or Large (beast) force entity") {
data.value = "force";
} else if (original === "droid (appears human)") {
data.value = "droid";
} else {
// Match the existing string
const pattern = /^(?:swarm of (?<size>[\w\-]+) )?(?<type>[^(]+?)(?:\((?<subtype>[^)]+)\))?$/i;
const match = original.trim().match(pattern);
if (match) {
// Match a known creature type
const typeLc = match.groups.type.trim().toLowerCase();
const typeMatch = Object.entries(CONFIG.SW5E.creatureTypes).find(([k, v]) => {
return (
typeLc === k ||
typeLc === game.i18n.localize(v).toLowerCase() ||
typeLc === game.i18n.localize(`${v}Pl`).toLowerCase()
);
});
if (typeMatch) data.value = typeMatch[0];
else {
data.value = "custom";
data.custom = match.groups.type.trim().titleCase();
}
data.subtype = match.groups.subtype?.trim().titleCase() || "";
// Match a swarm
const isNamedSwarm = actor.name.startsWith(game.i18n.localize("SW5E.CreatureSwarm"));
if (match.groups.size || isNamedSwarm) {
const sizeLc = match.groups.size ? match.groups.size.trim().toLowerCase() : "tiny";
const sizeMatch = Object.entries(CONFIG.SW5E.actorSizes).find(([k, v]) => {
return sizeLc === k || sizeLc === game.i18n.localize(v).toLowerCase();
});
data.swarm = sizeMatch ? sizeMatch[0] : "tiny";
} else data.swarm = "";
}
// No match found
else {
data.value = "custom";
data.custom = original;
}
}
// Update the actor data
updateData["data.details.type"] = data;
return updateData;
}
/* -------------------------------------------- */
/**
* @private
*/
function _migrateItemClassPowerCasting(item, updateData) {
if (item.type === "class"){
switch (item.name){
if (item.type === "class") {
switch (item.name) {
case "Consular":
updateData["data.powercasting"] = "consular";
updateData["data.powercasting"] = {
progression: "consular",
ability: ""
};
break;
case "Engineer":
updateData["data.powercasting"] = "engineer";
updateData["data.powercasting"] = {
progression: "engineer",
ability: ""
};
break;
case "Guardian":
updateData["data.powercasting"] = "guardian";
updateData["data.powercasting"] = {
progression: "guardian",
ability: ""
};
break;
case "Scout":
updateData["data.powercasting"] = "scout";
updateData["data.powercasting"] = {
progression: "scout",
ability: ""
};
break;
case "Sentinel":
updateData["data.powercasting"] = "sentinel";
updateData["data.powercasting"] = {
progression: "sentinel",
ability: ""
};
break;
}
}
@ -494,7 +614,11 @@ async function _migrateItemPower(item, actor, updateData) {
// shortcut out if dataVersion flag is set to 1.2.4 or higher
const hasDataVersion = item?.flags?.sw5e?.dataVersion !== undefined;
if (hasDataVersion && (item.flags.sw5e.dataVersion === "1.2.4" || isNewerVersion("1.2.4", item.flags.sw5e.dataVersion))) return updateData;
if (
hasDataVersion &&
(item.flags.sw5e.dataVersion === "1.2.4" || isNewerVersion("1.2.4", item.flags.sw5e.dataVersion))
)
return updateData;
// Check to see what the source of Power is
const sourceId = item.flags.core.sourceId;
@ -512,11 +636,10 @@ async function _migrateItemPower(item, actor, updateData) {
const corePowerData = corePower.data;
// copy Core Power Data over original Power
updateData["data"] = corePowerData;
updateData["flags"] = {"sw5e": {"dataVersion": "1.2.4"}};
updateData["flags"] = {sw5e: {dataVersion: "1.2.4"}};
return updateData;
//game.packs.get(powerType).getEntity(core_id).then(corePower => {
//})
@ -526,10 +649,14 @@ async function _migrateItemPower(item, actor, updateData) {
/**
* Delete the old data.attuned boolean
*
* @param {object} item Item data to migrate
* @param {object} updateData Existing update to expand upon
* @return {object} The updateData to apply
* @private
*/
function _migrateItemAttunement(item, updateData) {
if ( item.data.attuned === undefined ) return;
if (item.data?.attuned === undefined) return updateData;
updateData["data.attunement"] = CONFIG.SW5E.attunementTypes.NONE;
updateData["data.-=attuned"] = null;
return updateData;
@ -549,13 +676,13 @@ export async function purgeFlags(pack) {
};
await pack.configure({locked: false});
const content = await pack.getContent();
for ( let entity of content ) {
for (let entity of content) {
const update = {_id: entity.id, flags: cleanFlags(entity.data.flags)};
if ( pack.entity === "Actor" ) {
update.items = entity.data.items.map(i => {
if (pack.entity === "Actor") {
update.items = entity.data.items.map((i) => {
i.flags = cleanFlags(i.flags);
return i;
})
});
}
await pack.updateEntity(update, {recursive: false});
console.log(`Purged flags from ${entity.name}`);
@ -565,20 +692,18 @@ export async function purgeFlags(pack) {
/* -------------------------------------------- */
/**
* Purge the data model of any inner objects which have been flagged as _deprecated.
* @param {object} data The data to clean
* @private
*/
export function removeDeprecatedObjects(data) {
for ( let [k, v] of Object.entries(data) ) {
if ( getType(v) === "Object" ) {
for (let [k, v] of Object.entries(data)) {
if (getType(v) === "Object") {
if (v._deprecated === true) {
console.log(`Deleting deprecated object key ${k}`);
delete data[k];
}
else removeDeprecatedObjects(v);
} else removeDeprecatedObjects(v);
}
}
return data;

View file

@ -1,11 +1,10 @@
import { SW5E } from "../config.js";
import {SW5E} from "../config.js";
/**
* A helper class for building MeasuredTemplates for 5e powers and abilities
* @extends {MeasuredTemplate}
*/
export default class AbilityTemplate extends MeasuredTemplate {
/**
* A factory method to create an AbilityTemplate instance using provided data from an Item5e instance
* @param {Item5e} item The Item object for which to construct the template
@ -14,12 +13,12 @@ export default class AbilityTemplate extends MeasuredTemplate {
static fromItem(item) {
const target = getProperty(item.data, "data.target") || {};
const templateShape = SW5E.areaTargetTypes[target.type];
if ( !templateShape ) return null;
if (!templateShape) return null;
// Prepare template data
const templateData = {
t: templateShape,
user: game.user._id,
user: game.user.data._id,
distance: target.value,
direction: 0,
x: 0,
@ -28,7 +27,7 @@ export default class AbilityTemplate extends MeasuredTemplate {
};
// Additional type-specific data
switch ( templateShape ) {
switch (templateShape) {
case "cone":
templateData.angle = CONFIG.MeasuredTemplate.defaults.angle;
break;
@ -45,10 +44,12 @@ export default class AbilityTemplate extends MeasuredTemplate {
}
// Return the template constructed from the item data
const template = new this(templateData);
template.item = item;
template.actorSheet = item.actor?.sheet || null;
return template;
const cls = CONFIG.MeasuredTemplate.documentClass;
const template = new cls(templateData, {parent: canvas.scene});
const object = new this(template);
object.item = item;
object.actorSheet = item.actor?.sheet || null;
return object;
}
/* -------------------------------------------- */
@ -65,7 +66,7 @@ export default class AbilityTemplate extends MeasuredTemplate {
this.layer.preview.addChild(this);
// Hide the sheet that originated the preview
if ( this.actorSheet ) this.actorSheet.minimize();
if (this.actorSheet) this.actorSheet.minimize();
// Activate interactivity
this.activatePreviewListeners(initialLayer);
@ -82,20 +83,19 @@ export default class AbilityTemplate extends MeasuredTemplate {
let moveTime = 0;
// Update placement (mouse-move)
handlers.mm = event => {
handlers.mm = (event) => {
event.stopPropagation();
let now = Date.now(); // Apply a 20ms throttle
if ( now - moveTime <= 20 ) return;
if (now - moveTime <= 20) return;
const center = event.data.getLocalPosition(this.layer);
const snapped = canvas.grid.getSnappedPosition(center.x, center.y, 2);
this.data.x = snapped.x;
this.data.y = snapped.y;
this.data.update({x: snapped.x, y: snapped.y});
this.refresh();
moveTime = now;
};
// Cancel the workflow (right-click)
handlers.rc = event => {
handlers.rc = (event) => {
this.layer.preview.removeChildren();
canvas.stage.off("mousemove", handlers.mm);
canvas.stage.off("mousedown", handlers.lc);
@ -106,25 +106,20 @@ export default class AbilityTemplate extends MeasuredTemplate {
};
// Confirm the workflow (left-click)
handlers.lc = event => {
handlers.lc = (event) => {
handlers.rc(event);
// Confirm final snapped position
const destination = canvas.grid.getSnappedPosition(this.x, this.y, 2);
this.data.x = destination.x;
this.data.y = destination.y;
// Create the template
canvas.scene.createEmbeddedEntity("MeasuredTemplate", this.data);
const destination = canvas.grid.getSnappedPosition(this.data.x, this.data.y, 2);
this.data.update(destination);
canvas.scene.createEmbeddedDocuments("MeasuredTemplate", [this.data]);
};
// Rotate the template by 3 degree increments (mouse-wheel)
handlers.mw = event => {
if ( event.ctrlKey ) event.preventDefault(); // Avoid zooming the browser window
handlers.mw = (event) => {
if (event.ctrlKey) event.preventDefault(); // Avoid zooming the browser window
event.stopPropagation();
let delta = canvas.grid.type > CONST.GRID_TYPES.SQUARE ? 30 : 15;
let snap = event.shiftKey ? delta : 5;
this.data.direction += (snap * Math.sign(event.deltaY));
this.data.update({direction: this.data.direction + snap * Math.sign(event.deltaY)});
this.refresh();
};

View file

@ -1,5 +1,4 @@
export const registerSystemSettings = function() {
export const registerSystemSettings = function () {
/**
* Track the system version upon which point a migration was last applied
*/
@ -8,7 +7,7 @@ export const registerSystemSettings = function() {
scope: "world",
config: false,
type: String,
default: ""
default: game.system.data.version
});
/**
@ -22,9 +21,9 @@ export const registerSystemSettings = function() {
default: "normal",
type: String,
choices: {
"normal": "SETTINGS.5eRestPHB",
"gritty": "SETTINGS.5eRestGritty",
"epic": "SETTINGS.5eRestEpic",
normal: "SETTINGS.5eRestPHB",
gritty: "SETTINGS.5eRestGritty",
epic: "SETTINGS.5eRestEpic"
}
});
@ -39,11 +38,11 @@ export const registerSystemSettings = function() {
default: "555",
type: String,
choices: {
"555": "SETTINGS.5eDiagPHB",
"5105": "SETTINGS.5eDiagDMG",
"EUCL": "SETTINGS.5eDiagEuclidean",
555: "SETTINGS.5eDiagPHB",
5105: "SETTINGS.5eDiagDMG",
EUCL: "SETTINGS.5eDiagEuclidean"
},
onChange: rule => canvas.grid.diagonalRule = rule
onChange: (rule) => (canvas.grid.diagonalRule = rule)
});
/**
@ -79,7 +78,7 @@ export const registerSystemSettings = function() {
scope: "world",
config: true,
default: false,
type: Boolean,
type: Boolean
});
/**
@ -92,7 +91,7 @@ export const registerSystemSettings = function() {
config: true,
default: false,
type: Boolean,
onChange: s => {
onChange: (s) => {
ui.chat.render();
}
});
@ -100,10 +99,10 @@ export const registerSystemSettings = function() {
/**
* Option to allow GMs to restrict polymorphing to GMs only.
*/
game.settings.register('sw5e', 'allowPolymorphing', {
name: 'SETTINGS.5eAllowPolymorphingN',
hint: 'SETTINGS.5eAllowPolymorphingL',
scope: 'world',
game.settings.register("sw5e", "allowPolymorphing", {
name: "SETTINGS.5eAllowPolymorphingN",
hint: "SETTINGS.5eAllowPolymorphingL",
scope: "world",
config: true,
default: false,
type: Boolean
@ -112,8 +111,8 @@ export const registerSystemSettings = function() {
/**
* Remember last-used polymorph settings.
*/
game.settings.register('sw5e', 'polymorphSettings', {
scope: 'client',
game.settings.register("sw5e", "polymorphSettings", {
scope: "client",
default: {
keepPhysical: false,
keepMental: false,
@ -138,8 +137,8 @@ export const registerSystemSettings = function() {
default: "light",
type: String,
choices: {
"light": "SETTINGS.SWColorLight",
"dark": "SETTINGS.SWColorDark"
light: "SETTINGS.SWColorLight",
dark: "SETTINGS.SWColorDark"
}
});
};

View file

@ -3,9 +3,8 @@
* Pre-loaded templates are compiled and cached for fast access when rendering
* @return {Promise}
*/
export const preloadHandlebarsTemplates = async function() {
export const preloadHandlebarsTemplates = async function () {
return loadTemplates([
// Shared Partials
"systems/sw5e/templates/actors/parts/active-effects.html",

102
module/token.js Normal file
View file

@ -0,0 +1,102 @@
/**
* Extend the base TokenDocument class to implement system-specific HP bar logic.
* @extends {TokenDocument}
*/
export class TokenDocument5e extends TokenDocument {
/** @inheritdoc */
getBarAttribute(...args) {
const data = super.getBarAttribute(...args);
if (data && data.attribute === "attributes.hp") {
data.value += parseInt(getProperty(this.actor.data, "data.attributes.hp.temp") || 0);
data.max += parseInt(getProperty(this.actor.data, "data.attributes.hp.tempmax") || 0);
}
return data;
}
}
/* -------------------------------------------- */
/**
* Extend the base Token class to implement additional system-specific logic.
* @extends {Token}
*/
export class Token5e extends Token {
/** @inheritdoc */
_drawBar(number, bar, data) {
if (data.attribute === "attributes.hp") return this._drawHPBar(number, bar, data);
return super._drawBar(number, bar, data);
}
/* -------------------------------------------- */
/**
* Specialized drawing function for HP bars.
* @param {number} number The Bar number
* @param {PIXI.Graphics} bar The Bar container
* @param {object} data Resource data for this bar
* @private
*/
_drawHPBar(number, bar, data) {
// Extract health data
let {value, max, temp, tempmax} = this.document.actor.data.data.attributes.hp;
temp = Number(temp || 0);
tempmax = Number(tempmax || 0);
// Differentiate between effective maximum and displayed maximum
const effectiveMax = Math.max(0, max + tempmax);
let displayMax = max + (tempmax > 0 ? tempmax : 0);
// Allocate percentages of the total
const tempPct = Math.clamped(temp, 0, displayMax) / displayMax;
const valuePct = Math.clamped(value, 0, effectiveMax) / displayMax;
const colorPct = Math.clamped(value, 0, effectiveMax) / displayMax;
// Determine colors to use
const blk = 0x000000;
const hpColor = PIXI.utils.rgb2hex([1 - colorPct / 2, colorPct, 0]);
const c = CONFIG.SW5E.tokenHPColors;
// Determine the container size (logic borrowed from core)
const w = this.w;
let h = Math.max(canvas.dimensions.size / 12, 8);
if (this.data.height >= 2) h *= 1.6;
const bs = Math.clamped(h / 8, 1, 2);
const bs1 = bs + 1;
// Overall bar container
bar.clear();
bar.beginFill(blk, 0.5).lineStyle(bs, blk, 1.0).drawRoundedRect(0, 0, w, h, 3);
// Temporary maximum HP
if (tempmax > 0) {
const pct = max / effectiveMax;
bar.beginFill(c.tempmax, 1.0)
.lineStyle(1, blk, 1.0)
.drawRoundedRect(pct * w, 0, (1 - pct) * w, h, 2);
}
// Maximum HP penalty
else if (tempmax < 0) {
const pct = (max + tempmax) / max;
bar.beginFill(c.negmax, 1.0)
.lineStyle(1, blk, 1.0)
.drawRoundedRect(pct * w, 0, (1 - pct) * w, h, 2);
}
// Health bar
bar.beginFill(hpColor, 1.0)
.lineStyle(bs, blk, 1.0)
.drawRoundedRect(0, 0, valuePct * w, h, 2);
// Temporary hit points
if (temp > 0) {
bar.beginFill(c.temp, 1.0)
.lineStyle(0)
.drawRoundedRect(bs1, bs1, tempPct * w - 2 * bs1, h - 2 * bs1, 1);
}
// Set position
let posY = number === 0 ? this.h - h : 0;
bar.position.set(0, posY);
}
}

12
package-lock.json generated
View file

@ -1266,9 +1266,9 @@
}
},
"hosted-git-info": {
"version": "2.8.8",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg=="
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="
},
"image-size": {
"version": "0.5.5",
@ -3068,9 +3068,9 @@
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
},
"y18n": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz",
"integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ=="
},
"yargs": {
"version": "7.1.1",

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -52,7 +52,7 @@
{"name":"Traz","permission":{"default":0,"vXYkFWX6qzvOu2jc":3},"type":"tool","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":6,"price":300,"attuned":false,"equipped":false,"rarity":"","identified":true,"ability":"int","chatFlavor":"","proficient":0,"attributes":{"spelldc":10},"damage":{"parts":[]}},"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false,"effects":[]}},"img":"systems/sw5e/packs/Icons/Musical%20Instrument/Traz.webp","_id":"UQu4duMtxYEXKAbo"}
{"name":"Tent, two-person","permission":{"default":0,"vXYkFWX6qzvOu2jc":3},"type":"loot","data":{"description":{"value":"","chat":"","unidentified":""},"source":"","quantity":1,"weight":5,"price":20,"attuned":false,"equipped":false,"rarity":"","identified":true,"attributes":{"spelldc":10},"damage":{"parts":[]}},"flags":{},"img":"systems/sw5e/packs/Icons/Utility/Tent.webp","_id":"UxL0trd3omeqzBk4"}
{"name":"Homing Beacon","permission":{"default":0,"vXYkFWX6qzvOu2jc":3},"type":"loot","data":{"description":{"value":"<p>A homing beacon is a device used to track starships or any other entity being transported. Homing beacons transmit using non-mass HoloNet transceivers able to be tracked through hyperspace. Homing beacons are small enough that they can easily be hidden inside a ship, or tucked into some crevice on its exterior.</p>","chat":"","unidentified":""},"source":"","quantity":1,"weight":1,"price":450,"attuned":false,"equipped":false,"rarity":"","identified":true,"attributes":{"spelldc":10},"damage":{"parts":[]}},"flags":{},"img":"systems/sw5e/packs/Icons/Utility/Homing%20Beacon.webp","_id":"V2hSxkLfq461mvNz"}
{"name":"Power Cell","permission":{"default":0,"vXYkFWX6qzvOu2jc":3},"type":"consumable","data":{"description":{"value":"<p>Power cells fuel blaster weapons that deal energy or ion damage. Additionally, power cells are used to energize certain tools.</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":1,"price":10,"attuned":false,"equipped":false,"rarity":"","identified":true,"activation": {"type": "none","cost": null,"condition": ""},"duration": {"value": null,"units": ""},"target": {"value": null,"width": null,"units": "","type": ""},range":{"value": null,"long": null,"units": ""},"uses": {"value": 100,"max": "100","per": "charges","autoDestroy": false},"consume": {"type": "","target": "","amount": null},"ability": null,"actionType": "","attackBonus": 0,"chatFlavor": "","critical": null,"damage": {"parts": [],"versatile": ""},"formula": "","save": {"ability": "","dc": null,"scaling": "spell"},"consumableType": "ammo","attributes": {"spelldc": 10},"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false,"effects":[]}},"img":"systems/sw5e/packs/Icons/Ammunition/Power%20Cell.webp","_id":"VUkO1T2aYMuUcBZM"}
{"name":"Power Cell","permission":{"default":0,"vXYkFWX6qzvOu2jc":3},"type":"consumable","data":{"description":{"value":"<p>Power cells fuel blaster weapons that deal energy or ion damage. Additionally, power cells are used to energize certain tools.</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":1,"price":10,"attuned":false,"equipped":false,"rarity":"","identified":true,"activation": {"type": "none","cost": null,"condition": ""},"duration": {"value": null,"units": ""},"target": {"value": null,"width": null,"units": "","type": ""},"range":{"value": null,"long": null,"units": ""},"uses": {"value": 100,"max": "100","per": "charges","autoDestroy": false},"consume": {"type": "","target": "","amount": null},"ability": null,"actionType": "","attackBonus": 0,"chatFlavor": "","critical": null,"damage": {"parts": [],"versatile": ""},"formula": "","save": {"ability": "","dc": null,"scaling": "spell"},"consumableType": "ammo","attributes": {"spelldc": 10}},"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false,"effects":[]}},"img":"systems/sw5e/packs/Icons/Ammunition/Power%20Cell.webp","_id":"VUkO1T2aYMuUcBZM"}
{"name":"Propulsion pack","permission":{"default":0,"vXYkFWX6qzvOu2jc":3},"type":"loot","data":{"description":{"value":"<p>Propulsion packs enhance underwater movement. Activating or deactivating the propulsion pack requires a bonus action and, while active, you have a swimming speed of 30 feet. The propulsion pack lasts for 1 minute per power cell (to a maximum of 10 minutes) and can be recharged by a power source or replacing the power cells.</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":20,"price":400,"attuned":false,"equipped":false,"rarity":"","identified":true,"attributes":{"spelldc":10},"damage":{"parts":[]}},"flags":{},"img":"systems/sw5e/packs/Icons/Weapon%20or%20Armor%20Accessory/Propulsion%20Pack.webp","_id":"XR1obpDj1PqDLfA8"}
{"name":"Emergency Battery","permission":{"default":0,"vXYkFWX6qzvOu2jc":3},"type":"consumable","data":{"description":{"value":"<p>All non-expendable droids need recharging as they are used. The battery has ten uses. As an action, you can expend one use of the kit to stabilize a droid that has 0 hit points, without needing to make an Intelligence (Technology) check.</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":5,"price":70,"attuned":false,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":""},"uses":{"value":10,"max":10,"per":"charges","autoDestroy":true},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"other","attackBonus":0,"chatFlavor":"Stabilize Droid","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"spell"},"consumableType":"potion","attributes":{"spelldc":10}},"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false,"effects":[]}},"img":"systems/sw5e/packs/Icons/Medical/Emergency%20Battery.webp","_id":"Z0YM3aYCyCRhL6cx"}
{"name":"Smugglepack","permission":{"default":0,"vXYkFWX6qzvOu2jc":3},"type":"backpack","data":{"description":{"value":"<p>This backpack comes with a main compartment that can store up to 15 lb., not exceeding a volume of 1/2 cubic foot. Additionally, it has a hidden storage compartment that can hold up to 5 lb, not exceeding a volume of 1/4 cubic foot. Finding the hidden compartment requires a DC 15 Investigation check.</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":6,"price":400,"attuned":false,"equipped":false,"rarity":"","identified":true,"capacity":{"type":"weight","value":20,"weightless":false},"currency":{"cp":0,"sp":0,"ep":0,"gp":0,"pp":0},"attributes":{"spelldc":10},"damage":{"parts":[]}},"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false,"effects":[]}},"img":"systems/sw5e/packs/Icons/Storage/Smugglerpack.webp","_id":"Zlj5z56A4oVQ5iEC"}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -8,6 +8,7 @@
{"_id":"28uF6yN4NLoc1Mf7","name":"Master Speed","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Knight Speed</em></p>\n<p>Choose up to two willing creatures that you can see within range. Until the power ends, each targets&rsquo; speed is doubled, they gain a +2 bonus to AC, they have advantage on Dexterity saving throws, and they gain an additional action on each of their turns. That action can be used only to take the Attack (one weapon attack only), Dash, Disengage, Hide, or the Use an Object Action.</p>\n<p>When the power ends, each target can&rsquo;t move or take actions until after its next turn, as a wave of lethargy sweeps over it.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 8th-level or higher, you can target one additional creature for each slot level above 7th.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":2,"units":"","type":"creature"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":7,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"level","formula":"1 additional creature"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Master%20Speed.webp","effects":[]}
{"_id":"2EdyvNwmyRD9yhmn","name":"Maddening Darkness","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Shroud of Darkness</em></p>\n<p>Terrifying darkness spreads from a point you choose within range to fill a 60-foot-radius sphere until the power ends. The darkness spreads around corners. A creature with darkvision can&rsquo;t see through this darkness. Unenhanced light, as well as light created by powers of 8th level or lower, can&rsquo;t illuminate the area.</p>\n<p>Shrieks, gibbering, and mad laughter can be heard within the sphere. Whenever a creature starts its turn in the sphere, it must make a Wisdom saving throw, taking 8d8 psychic damage on a failed save, or half as much damage on a successful one.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":"Have Shroud of Darkenss"},"duration":{"value":10,"units":"minute"},"target":{"value":60,"units":"ft","type":"radius"},"range":{"value":150,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["8d8","psychic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":8,"school":"drk","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Maddening%20Darkness.webp","effects":[]}
{"_id":"2MaAEt5XSnjEurWK","name":"Valor","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Resistance</em></p>\n<p>You bless up to three creatures of your choice within range. Whenever a target makes an attack roll or a saving throw before the power ends, the target can roll a d4 and add the number rolled to the attack roll or saving throw.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 2nd level or higher, you can target one additional creature for each slot level above 1st.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":3,"units":"","type":"creature"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"other","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"1d4","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"level","formula":"1 additional creature"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Valor.webp","effects":[]}
{"name":"Wakefulness","permission":{"default":0,"IpSq6HI4edO6e0Yw":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Breath Control</em></p>\n<p>You use the Force to control your body's functions. For the duration, you gain the following benefits:</p>\n<ul>\n<li>You ignore the effects of any levels of exhaustion you have.</li>\n<li>You do not need to eat, drink, or sleep. You can't be forced to sleep by any means. To gain the benefits of a long rest, you can spend all 8 hours doing light activity, such as reading and keeping watch.</li>\n</ul>\n<p>If you still have any levels of exhaustion when this power ends, you must make a DC 15 Constitution saving throw. On a failed save, you gain one level of exhaustion.</p>","chat":"","unidentified":""},"requirements":"","source":"EC","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":8,"units":"hour"},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":"0","max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":2,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""}},"flags":{"core":{"sourceId":"Item.ROvBWSja1cjiDOO0"}},"img":"systems/sw5e/packs/Icons/Force%20Powers/Wakefulness.webp","effects":[],"_id":"2obXjKljRPeuoqcl"}
{"_id":"3IoaQSSoAtFsoavO","name":"Master Force Barrier","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Improved Force Barrier</em></p>\n<p>This power massively bolsters your allies with toughness and resolve. Creatures of your choice in a 30-foot radius around you when you cast this power gain the following benefits:</p>\n<ul>\n<li>The creature sheds dim light in a 5-foot radius.</li>\n<li>The creature has advantage on all saving throws</li>\n<li>Other creatures have disadvantage on attack rolls against them.</li>\n<li>When a dark side creature hits them with a melee attack, that creature must make a Constitution saving throw or be blinded until the power ends.</li>\n</ul>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":30,"units":"ft","type":"radius"},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":8,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Master%20Force%20Barrier.webp","effects":[]}
{"_id":"3KGdCbHATzaghiwo","name":"Force Propel","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Force Push/Pull</em></p>\n<p>Choose one or more creatures or objects not being worn or carried within 60 feet that weigh up to a combined total of 15 pounds. The creatures or objects immediately move 60 feet in a direction of your choice. If the creatures or objects end this movement in the air, they immediately fall to the ground. If the creatures or objects collide with any one target during its travel, both the creatures or objects and the target take 3d8 kinetic damage. If the target is a creature, it must make a Dexterity saving throw. On a failed save, it takes 3d8 kinetic damage, or half as much on a successful one.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 2nd level or higher, the maximum weight increases by 15 pounds and the damage increases by 1d8 for each slot level above 1st.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":null,"units":"any","type":"object"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["3d8","kinetic"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"power"},"level":1,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"1d8"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Force%20Propel.webp","effects":[]}
{"_id":"3odfJsD1RezuxzDG","name":"Mass Hysteria","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Hysteria</em></p>\n<p>Drawing on the deepest fears of a group of creatures, you create illusory creatures in their minds, manifesting their worst nightmares as an implacable threat visible only to them. Each creature in a 30-foot-radius sphere is frightened for the duration of the power. At the end of each of the frightened creature&rsquo;s turns, it must succeed on a Wisdom saving throw or take 5d10 psychic damage. On a successful save, the power ends for that creature. This power has no effect on droids or constructs.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":"Have Hysteria Power"},"duration":{"value":1,"units":"minute"},"target":{"value":30,"units":"ft","type":"radius"},"range":{"value":120,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["5d8","psychic"]],"versatile":""},"formula":"","save":{"ability":"wis","dc":null,"scaling":"power"},"level":9,"school":"drk","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Mass%20Hysteria.webp","effects":[]}
@ -19,7 +20,7 @@
{"_id":"562ItvjZZHhSmqeP","name":"Morichro","permission":{"default":0,"XA86Wm4MjngMySbc":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Cloud Mind</em></p>\n<p>You touch a willing creature and put it into a cataleptic state that is indistinguishable from death.</p>\n<p>For the power&rsquo;s duration, or until you use an action to touch the target and dismiss the power, the target appears dead to all outward inspection and to powers used to determine the target&rsquo;s status. The target is blinded and incapacitated, and its speed drops to 0. The target has resistance to all damage except psychic damage. If the target is diseased or poisoned when you cast the power, or becomes diseased or poisoned while under the power&rsquo;s effect, the disease and poison have no effect until the power ends. This power has no effect on droids or constructs.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"hour"},"target":{"value":null,"units":"","type":""},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":3,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Morichro.webp","effects":[]}
{"_id":"5Gxqh2j4A258jCSY","name":"Revitalize","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Spare the Dying</em></p>\n<p>You return a dead creature you touch to life, provided that it has been dead no longer than 10 minutes. If the creature&rsquo;s soul is both willing and at liberty to rejoin the body, the creature returns to life with 1 hit point.</p>\n<p>This power also neutralizes any poisons and cures diseases that affected the creature at the time it died.</p>\n<p>This power closes all mortal wounds, but it doesn&rsquo;t restore missing body parts. If the creature is lacking body parts or organs integral for its survival, its head for instance, the power automatically fails.</p>\n<p>Coming back from the dead is an ordeal. The target takes a -4 penalty to all attack rolls, saving throws, and ability checks. Every time the target finishes a long rest, the penalty is reduced by 1 until it disappears.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"minute","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":5,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Revitalize.webp","effects":[]}
{"_id":"5koTRABu4ER8g6Wo","name":"Horror","permission":{"default":0,"9BhUyjgxIxogl2ot":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Fear</em></p>\n<p>You project a phantasmal image of a creature&rsquo;s worst fears. Each creature in a 30-foot cone must succeed on a Wisdom saving throw or drop whatever it is holding and become frightened for the duration. This power has no effect on constructs or droids.</p>\n<p>While frightened by this power, a creature must take the Dash action and move away from you by the safest available route on each of its turns, unless there is nowhere to move. If the creature ends its turn in a location where it doesn&rsquo;t have line of sight to you, the creature can make a Wisdom saving throw. On a successful save, the power ends for that creature.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":30,"units":"ft","type":"cone"},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"wis","dc":null,"scaling":"power"},"level":3,"school":"drk","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Horror.webp","effects":[]}
{"_id":"5lOXTZUiRmL7aZi9","name":"Convulsion","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Tremor</em></p>\n<p>Choose a point you can see on the ground within range. A fountain of churned earth and stone erupts in a 20-foot cube centered on that point. Each creature in that area must make a Dexterity saving throw. A creature takes 3d12 kinetic damage on a failed save, or half as much damage on a successful one. Additionally, the ground in that area becomes difficult terrain until cleared. Each 5-foot-square portion of the area requires at least 1 minute to clear by hand.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 4th level or higher, the damage increases by 1d12 for each slot level above 3rd.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":20,"units":"ft","type":"cube"},"range":{"value":120,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["3d12",""]],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"power"},"level":1,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"1d12"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Convulsion.webp","effects":[]}
{"_id":"5lOXTZUiRmL7aZi9","name":"Convulsion","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Tremor</em></p>\n<p>Choose a point you can see on the ground within range. A fountain of churned earth and stone erupts in a 20-foot cube centered on that point. Each creature in that area must make a Dexterity saving throw. A creature takes 3d12 kinetic damage on a failed save, or half as much damage on a successful one. Additionally, the ground in that area becomes difficult terrain until cleared. Each 5-foot-square portion of the area requires at least 1 minute to clear by hand.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 4th level or higher, the damage increases by 1d12 for each slot level above 3rd.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":20,"units":"ft","type":"cube"},"range":{"value":120,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["3d12",""]],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"power"},"level":3,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"1d12"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Convulsion.webp","effects":[]}
{"_id":"5o01ADUmNyzy470b","name":"Force Disarm","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>You select a weapon or object being worn or carried by a Large or smaller creature within range. The creature must make a Strength or Dexterity saving throw (the creature chooses the ability to use). If the item is being worn, this save is made with disadvantage. On a failed save, the creature takes 1d4 force damage and the item is pulled directly to you. If you have a free hand, you catch the weapon. Otherwise, it lands at your feet.</p>\n<p>This powers damage increases by 1d4 when you reach 5th level (2d4), 11th level (3d4), and 17th level (4d4).</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":1,"units":"","type":"object"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4","force"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"atwill","formula":"1d4"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Force%20Disarm.webp","effects":[]}
{"_id":"5raHPlhouud0Jpr4","name":"Telekinetic Storm","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Turbulence</em></p>\n<p>You stir the Force around you, creating a turbulent field of telekinetic energy that buffets enemies around you. The field extends out to a distance of 15 feet around you for the duration.</p>\n<p>When you cast this power, you can designate any number of creatures you can see to be unaffected by it. An affected creature&rsquo;s speed is halved in the area, and when the creature enters the area for the first time on a turn or starts its turn there, it must make a Constitution saving throw. On a failed save, the creature takes 3d8 force damage. On a successful save, the creature takes half as much damage.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force power slot of 4th level or higher, the damage increases by 1d8 for each slot level above 3rd.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":15,"units":"ft","type":"radius"},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["3d8","force"]],"versatile":""},"formula":"","save":{"ability":"con","dc":null,"scaling":"power"},"level":3,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"level","formula":"1d8"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Telekinetic%20Storm.webp","effects":[]}
{"_id":"5tAwilkRcZsTc62q","name":"Skill Empowerment","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>Your power with the Force deepens a creature&rsquo;s understanding of its own talent. You touch one willing creature and give it expertise in one skill of your choice; until the power ends, the creature doubles its proficiency bonus for ability checks it makes that use the chosen skill.</p>\n<p>You must choose a skill in which the target is proficient and that isn&rsquo;t already benefiting from an effect, such as Expertise, that doubles its proficiency bonus.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"hour"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":5,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Skill%20Empowerment.webp","effects":[]}
@ -49,10 +50,12 @@
{"_id":"C2ROn2KK2QTLm9DW","name":"Guidance","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>You touch one willing creature. Once before the power ends, the target can roll a d4 and add the number rolled to one ability check of its choice. It can roll the die before or after making the ability check. The power then ends.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"other","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"1d4","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Guidance.webp","effects":[]}
{"_id":"C5UBI7f4LoNg2dPM","name":"Force Meld","permission":{"default":0,"XA86Wm4MjngMySbc":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Force Whisper</em></p>\n<p>You forge a telepathic link among up to eight willing creatures of your choice within range, psychically linking each creature to all the others for the duration. Droids, constructs, and creatures with Intelligence scores of 2 or less aren&rsquo;t affected by this power.</p>\n<p>Until the power ends, the targets can communicate telepathically through the bond whether or not they have a common language. The communication is possible over any distance, though it can&rsquo;t extend beyond a single planet.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"hour"},"target":{"value":8,"units":"","type":"creature"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":5,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Force%20Meld.webp","effects":[]}
{"_id":"CJR5SlWKoaCtY1bq","name":"Spare the Dying","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>You touch a living creature that has 0 hit points. The creature becomes stable. This power has no effect on droids or constructs.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Spare%20the%20Dying.webp","effects":[]}
{"name":"Telepathic Link","permission":{"default":0,"IpSq6HI4edO6e0Yw":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Force Whisper</em></p>\n<p>You establish a telepathic link with one willing humanoid you touch. Until the power ends, whenever you and the target can see each other, each of you can communicate with the other via telepathy.</p>\n<p>You don&rsquo;t need to share a language with a creature for it to understand your telepathic utterances, and the creature understands you even if it lacks a language. The creature can respond to you telepathically as well, but it must understand at least one language in order to communicate this way.</p>\n<p><em><strong>Force Potency.</strong></em> When you cast this power using a force slot of 3rd level or higher, the duration increases to Concentration, up to 1 hour, and if either you or the creature you are linked to are surprised, while both of you can see each other, the surprised creature can still act normally during the surprise round, as if it were not surprised.</p>","chat":"","unidentified":""},"requirements":"","source":"EC","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":10,"units":"minute"},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":"0","max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""}},"flags":{"core":{"sourceId":"Item.ribj4iIyIwS74McS"}},"img":"systems/sw5e/packs/Icons/Force%20Powers/Telepathic%20Link.webp","effects":[],"_id":"CjHXQcv4UPNIcIg0"}
{"_id":"CkMXwj0l0H0rD9md","name":"Mass Malacia","permission":{"default":0,"XA86Wm4MjngMySbc":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Malacia</em></p>\n<p>Each creature in a 30-foot cube within range must make a Wisdom saving throw. On a failed save, the creature becomes charmed for the duration. While charmed by this power, the creature is incapacitated and has a speed of 0.</p>\n<p>The power ends for an affected creature if it takes any damage or if someone else uses an action to shake the creature out of its stupor. This power has no effect on droids or constructs.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":30,"units":"ft","type":"cube"},"range":{"value":120,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"wis","dc":null,"scaling":"power"},"level":3,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Mass%20Malacia.webp","effects":[]}
{"_id":"CkwLRMWRdXp1ZOIh","name":"Greater Saber Throw","permission":{"default":0,"XA86Wm4MjngMySbc":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Improved Saber Throw</em></p>\n<p>As a part of the action used to cast this power, you must make a ranged force attack with a lightweapon or vibroweapon against one target within the power&rsquo;s range, otherwise the power fails. On a hit, the target takes 6d8 damage of the same type as the weapon&rsquo;s damage and must make a Constitution saving throw against an additional effect depending on your choice of casting ability:</p>\n<p>Wisdom.&nbsp;The target takes an additional 4d6 force damage and it gains four levels of slowed until the end of its next turn. On a success, the target takes half as much damage and its speed isn&rsquo;t reduced.</p>\n<p>Charisma.&nbsp;The target takes an additional 4d6 necrotic damage and cannot regain hit points until the end of its next turn. On a success, the target takes half as much damage and its healing capability is unaffected.</p>\n<p>The weapon then immediately returns to your hand.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 6th level or higher, the force or necrotic damage increases by 1d6 for each slot above 5th.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"rpak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["6d8",""]],"versatile":""},"formula":"4d6","save":{"ability":"con","dc":null,"scaling":"power"},"level":5,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Greater%20Saber%20Throw.webp","effects":[]}
{"_id":"CsLjEyQtegNiXKIZ","name":"Tremor","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Burst</em></p>\n<p>You cause a tremor in the ground within range. Each creature other than you in a 5-foot-radius sphere centered on that point must make a Dexterity saving throw. On a failed save, a creature takes 1d6 kinetic damage and is knocked prone. On a successful save, the creature takes half as much damage and isn&rsquo;t knocked prone. If the ground in that area is loose earth or stone, it becomes difficult terrain until cleared, with each 5-foot-diameter portion requiring at least 1 minute to clear by hand.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 2nd level or higher, the damage increases by 1d6 for each slot level above 1st.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":5,"units":"ft","type":"radius"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6","kinetic"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"power"},"level":1,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"1d6"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Tremor.webp","effects":[]}
{"_id":"CuAbwhIt3j2V30Ey","name":"Saber Reflect","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>In response to being attacked, you raise your weapon to attempt to deflect. When you you use this power, the damage you take from the attack is reduced by 1d6. If you reduce the damage to 0, youre wielding a lightweapon or vibroweapon, and the damage is energy or ion, you can reflect the attack at a target within range as part of the same reaction. Make a ranged force attack at a target you can see. The attack has a normal range of 20 feet and a long range of 60 feet. On a hit, the target takes the triggering attacks normal damage.</p>\n<p>If you would have resistance to the triggering damage, resistance is applied before the damage reduction.</p>\n<p>The powers damage reduction increases by 1d6 when you reach 5th level (2d6), 11th level (3d6), and 17th level (4d6).</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"reaction","cost":1,"condition":"which you take in response to being hit by a ranged attack"},"duration":{"value":null,"units":"inst"},"target":{"value":null,"units":"","type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"other","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"1d6","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"atwill","formula":"1d6"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Saber%20Reflect.webp","effects":[]}
{"name":"Tapas","permission":{"default":0,"IpSq6HI4edO6e0Yw":3},"type":"power","data":{"description":{"value":"<p>You use the Force to inure yourself to the elements. For the duration, you are considered adapted to hot and cold climates.</p>","chat":"","unidentified":""},"requirements":"","source":"EC","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":24,"units":"hour"},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":"0","max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""}},"flags":{"core":{"sourceId":"Item.Heu6br9Yn7ZOVnnA"}},"img":"systems/sw5e/packs/Icons/Force%20Powers/Tapas.webp","effects":[],"_id":"D9V8ShFjzvenV8ud"}
{"_id":"DFpooO6icOfTdG5C","name":"Master Feedback","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Greater Feedback</em></p>\n<p>You unleash the power of your mind to blast the intellect of up to ten creatures of your choice that you can see within range. Creatures that have an Intelligence score of 2 or lower are unaffected.</p>\n<p>Each target must make an Intelligence saving throw. On a failed save, a target takes 14d6 psychic damage and is stunned. On a successful save, a target takes half as much damage and isn&rsquo;t stunned.</p>\n<p>A stunned target can make a Wisdom saving throw at the end of each of its turns. On a successful save, the stunning effect ends.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":"Have Greater Feedback Power"},"duration":{"value":null,"units":"inst"},"target":{"value":10,"units":"","type":"creature"},"range":{"value":90,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["14d6","psychic"]],"versatile":""},"formula":"","save":{"ability":"int","dc":null,"scaling":"power"},"level":8,"school":"drk","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Master%20Feedback.webp","effects":[]}
{"_id":"ENNhFJKCcxrg481J","name":"Improved Phasestrike","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Phasestrike</em></p>\n<p>Choose up to five creatures you can see within range. Make a melee force attack against each one. On hit, a target takes 6d10 force damage. You can then teleport to an unoccupied space you can see within 5 feet of one of the creatures you chose.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":5,"units":"","type":"creature"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"mpak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["6d10","force"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":5,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Improved%20Phasestrike.webp","effects":[]}
{"_id":"EXK4sg6gKXfMnLnf","name":"Battle Meditation","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>You exude an aura out to 5 feet that boosts the morale and overall battle prowess you and your allies while simultaneously reducing the oppositions combat-effectiveness by eroding their will to fight.</p>\n<p>Whenever you or a friendly creature within your meditation makes an attack roll or a saving throw, they can roll a d4 and add the number rolled to the attack roll or saving throw.</p>\n<p>Whenever a hostile creature enters your meditation or starts its turn there, it must make a Charisma saving throw. On a failed save, it must roll a d4 and subtract the number rolled from each attack roll or saving throw it makes before the end of your next turn. On a successful save, it is immune to this power for 1 day.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":5,"units":"ft","type":"radius"},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"1d4","save":{"ability":"cha","dc":null,"scaling":"power"},"level":2,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Battle%20Meditation.webp","effects":[]}
@ -67,7 +70,7 @@
{"_id":"G8UVHP4MXW6Dudky","name":"Phasestrike","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>Until the power ends, your movement doesnt provoke opportunity attacks.</p>\n<p>Once before the power ends, you can give yourself advantage on one weapon attack roll on your turn. That attack deals an extra 1d8 force damage on a hit. Whether you hit or miss, your walking speed increases by 30 feet until the end of that turn.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"bonus","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":null,"units":"","type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"other","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d8","force"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Phasestrike.webp","effects":[]}
{"_id":"GBJRx32gU9xU1Q6s","name":"Improved Feedback","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Feedback</em></p>\n<p>You unleash a blast of psychic energy at a target within range. If the target can hear you (though it need not understand you), it must succeed on an Intelligence saving throw. On a failed save, it takes 3d6 psychic damage and must immediately use its reaction, if available, to move as far as its speed allows away from you. The creature doesn&rsquo;t move into obviously dangerous ground, such as a fire or a pit. On a successful save, the target takes half as much damage and doesn&rsquo;t have to move away. A deafened creature automatically succeeds on the save.</p>\n<p><strong><em><strong>Force Potency.</strong></em></strong>&nbsp;When you cast this power using a force slot of 2nd level or higher, the damage increases by 1d6 for each slot level above 1st.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":"Have Feedback Power"},"duration":{"value":null,"units":"inst"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["3d6","psychic"]],"versatile":""},"formula":"","save":{"ability":"int","dc":null,"scaling":"power"},"level":1,"school":"drk","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"1d6"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Improved%20Feedback.webp","effects":[]}
{"_id":"H51uSnFY6eyBTXRJ","name":"Stasis","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Stun</em></p>\n<p>Choose a creature that you can see within range. The target must succeed on a Wisdom saving throw or be paralyzed for the duration. At the end of each of its turns, the target can make another Wisdom saving throw. On a success, the power ends on the target. This power has no effect on droids or constructs.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 6th level or higher, you can target an additional creature for each slot level above 5th. The creatures must be within 30 feet of each other when you target them.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":90,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"wis","dc":null,"scaling":"power"},"level":5,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"level","formula":"1 additional creature"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Stasis.webp","effects":[]}
{"_id":"HPtgWP83jKSyFWFp","name":"Aura of Purity","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Restoration</em></p>\n<p>Purifying energy radiates from you in a 30-foot radius. Until the power ends, the aura moves with you, centered on you. Each nonhostile creature in the aura (including you) can&rsquo;t become diseased, has resistance to poison damage, and has advantage on saving throws against effects that cause any of the following conditions: blinded, charmed, deafened, frightened, paralyzed, poisoned, and stunned.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":10,"units":"minute"},"target":{"value":30,"units":"ft","type":"radius"},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":4,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Aura%20of%20Purity.webp","effects":[]}
{"_id":"HPtgWP83jKSyFWFp","name":"Aura of Purity","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Restoration</em></p>\n<p>Purifying energy radiates from you in a 30-foot radius. Until the power ends, the aura moves with you, centered on you. Each nonhostile creature in the aura (including you) can&rsquo;t become diseased, has resistance to poison damage, and has advantage on saving throws against effects that cause any of the following conditions: blinded, charmed, deafened, frightened, paralyzed, poisoned, and stunned.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":10,"units":"minute"},"target":{"value":30,"units":"ft","type":"radius"},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":"0","max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":4,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Aura%20of%20Purity.webp","effects":[]}
{"_id":"Hgn1yHJsMzp5qKr5","name":"Force Reflect","permission":{"default":0,"XA86Wm4MjngMySbc":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Saber Reflect</em></p>\n<p>In response to being attacked, you attempt to deflect the attack with the Force. When you use this power, the damage you take from the attack is reduced by 1d10. If you reduce the damage to 0 and the damage is energy, force, ion, kinetic, lightning, necrotic, or sonic, you can reflect the attack at a target within range as part of the same reaction. Make a ranged force attack at a target you can see. The attack has a normal range of 30 feet and a long range of 90 feet. On a hit, the target takes the triggering attack&rsquo;s normal damage.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 2nd level or higher, the damage reduction increases by 1d10 for each slot level above 1st.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"reaction","cost":1,"condition":"which you take in response to being hit by a ranged attack"},"duration":{"value":null,"units":""},"target":{"value":null,"units":"","type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"rpak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"1d10","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"1d10"}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Force%20Reflect.webp","effects":[]}
{"_id":"HqxcYlFOZJZ91a98","name":"Precognition","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Danger Sense</em></p>\n<p>Your mastery of the Force gives you a limited ability to see into the immediate future. For the duration, you can&rsquo;t be surprised and you have advantage on attack rolls, ability checks, and saving throws. Additionally, other creatures have disadvantage on attack rolls against you for the duration.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"minute","cost":1,"condition":""},"duration":{"value":8,"units":"hour"},"target":{"value":null,"units":"","type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":9,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Precognition.webp","effects":[]}
{"_id":"HvyTel83im9br37p","name":"Force Leap","permission":{"default":0,"XA86Wm4MjngMySbc":3},"type":"power","data":{"description":{"value":"<p>Until the end of your next turn, you can use your forcecasting ability score instead of your Strength score when you jump, and always count as having made a running start before jumping.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"bonus","cost":1,"condition":""},"duration":{"value":1,"units":"round"},"target":{"value":null,"units":"","type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":null,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Force%20Leap.webp","effects":[]}
@ -100,7 +103,7 @@
{"_id":"NrMpYXddHnoPKHT2","name":"Force Lightning Cone","permission":{"default":0,"9BhUyjgxIxogl2ot":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Force Chain Lightning</em></p>\n<p>Lightning arcs from your hands. Each creature in a 60-foot cone must make a Dexterity saving throw. A creatures takes 12d6 lightning damage on a failed save, or half as much on a successful one.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 8th level or higher, the damage increases by 2d6 for each slot level above 7th.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":60,"units":"ft","type":"cone"},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["12d6","lightning"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"power"},"level":7,"school":"drk","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":"2d6"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Force%20Cone%20Lightning.webp","effects":[]}
{"_id":"Ns34rjyKzqeydYBH","name":"Sense Emotion","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>You attune your senses to pick up the emotions of others for the duration. When you cast the power, and as your action on each turn until the power ends, you can focus your senses on one humanoid you can see within 30 feet of you. You instantly learn the targets prevailing emotion, whether its love, anger, pain, fear, calm, or something else. If the target isnt actually humanoid or it is immune to being charmed, you sense that it is calm.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":10,"units":"minute"},"target":{"value":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Sense%20Emotion.webp","effects":[]}
{"_id":"O5J8TTpTW7eHLDgG","name":"Sense Force","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>For the duration, you sense the use of the Force, or its presence in an inanimate object within 30 feet of you. If you sense the Force in this way, you can use your action to determine the direction from which it originates and, if its in line of sight, you see a faint aura around the person or object from which the Force emanates.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a 3rd-level force slot, the range increases to 60 feet. When you use a 5th-level force slot, the range increases to 500 feet. When you use a 7th-level force slot, the range increases to 1 mile. When you use a 9th-level force slot, the range increases to 10 miles.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":10,"units":"minute"},"target":{"value":null,"units":"","type":"self"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Sense%20Force.webp","effects":[]}
{"_id":"OGLh7pBroWR6te2k","name":"Armor of Abeloth","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>A protective force surrounds you, manifesting as shimmering light that covers you and your gear. You gain 5 temporary hit points for the duration. If a creature hits you with a melee attack while you have these hit points, the creature takes 5 psychic damage.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 2nd level or higher, both the temporary hit points and the psychic damage increase by 5 for each slot.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"hour"},"target":{"value":null,"units":"","type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"drk","components":{"value":"","concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Armor%20of%20Abeloth.webp","effects":[]}
{"_id":"OGLh7pBroWR6te2k","name":"Armor of Abeloth","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>A protective force surrounds you, manifesting as shimmering light that covers you and your gear. You gain 5 temporary hit points for the duration. If a creature hits you with a melee attack while you have these hit points, the creature takes 5 psychic damage.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 2nd level or higher, both the temporary hit points and the psychic damage increase by 5 for each slot.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"hour"},"target":{"value":null,"units":"","type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":"0","max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"drk","components":{"value":"","concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Armor%20of%20Abeloth.webp","effects":[]}
{"_id":"OYQAqS6rjVy6o5Oa","name":"Kill","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Ruin</em></p>\n<p>You compel one creature you can see within range to die instantly. If the creature you choose has 100 hit points or fewer, it dies. Otherwise, the power has no effect.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":"Have Ruin Power"},"duration":{"value":null,"units":"inst"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"other","attackBonus":0,"chatFlavor":"Have over 100 HP left or Die!","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":9,"school":"drk","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Kill.webp","effects":[]}
{"_id":"Oxb3dpusa4SmIKQd","name":"Improved Battle Meditation","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Battle Meditation</em></p>\n<p>You exude an aura out to 15 feet that boosts the morale and overall battle prowess you and your allies while simultaneously reducing the opposition&rsquo;s combat-effectiveness by eroding their will to fight.</p>\n<p>Whenever you or a friendly creature within your meditation makes an attack roll or a saving throw, they can roll a d6 and add the number rolled to the attack roll or saving throw.</p>\n<p>Whenever a hostile creature enters your meditation or starts its turn there, it must make a Charisma saving throw. On a failed save, it must roll a d6 and subtract the number rolled from each attack roll or saving throw it makes before the end of your next turn. On a successful save, it is immune to this power for 1 day.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":15,"units":"ft","type":"radius"},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"other","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"1d6","save":{"ability":"","dc":null,"scaling":"power"},"level":5,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Improved%20Battle%20Meditation.webp","effects":[]}
{"_id":"PUHY0RrLsi4tAnZx","name":"Force Sight","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Sense Force</em></p>\n<p>You shift your vision to see through use of the Force; colors fade and inanimate objects appear as shades of gray. You gain the following benefits.</p>\n<ul>\n<li>Living things glow with the power of the Force. Those with an affinity for the light side glow blue, those with an affinity for the dark side glow red, and those with no attunement to either side of the Force glow yellow. How bright they glow is determined by how strong their connection to the Force is.</li>\n<li>You gain blindsight to 30 feet.</li>\n<li>You have advantage on Wisdom (Perception) checks that rely on sight against living targets within 30 feet.</li>\n</ul>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":10,"units":"minute"},"target":{"value":null,"units":"","type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":2,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Force%20Sight.webp","effects":[]}
@ -122,7 +125,7 @@
{"_id":"VIi9ZD8Ha669UYRw","name":"Insanity","permission":{"default":0,"9BhUyjgxIxogl2ot":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Horror</em></p>\n<p>This power assaults and twists creatures&rsquo; minds, spawning delusions and provoking uncontrolled action. Each creature in a 30-foot-radius sphere centered on you must succeed on a Wisdom saving throw when you cast this power or be affected by it.</p>\n<p>An affected target can&rsquo;t take reactions and must roll a d8 at the start of each of its turns to determine its behavior for that turn. This power has no effect on constructs or droids.</p>\n<table style=\"border: 0;\">\n<tbody>\n<tr>\n<th style=\"width: 25px;\">d8</th>\n<th>Behavior</th>\n</tr>\n<tr>\n<td style=\"text-align: left;\">1</td>\n<td>The creature uses all its movement to move in a random direction. To determine the direction, roll a d8 and assign a direction to each die face. The creature doesn&rsquo;t take an action this turn.</td>\n</tr>\n<tr>\n<td>2-6</td>\n<td>The creature doesn&rsquo;t move or take actions this turn.</td>\n</tr>\n<tr>\n<td>7-8</td>\n<td>The creature uses its action to make a melee attack against a randomly determined creature within its reach. If there is no creature within its reach, the creature does nothing this turn.</td>\n</tr>\n</tbody>\n</table>\n<p>At the end of each of its turns, an affected target can make a Wisdom saving throw. If it succeeds, this effect ends for that target.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a power slot of 6th level or higher, the radius of the sphere increases by 5 feet for each force slot level above 5th.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":30,"units":"ft","type":"sphere"},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"1d8","save":{"ability":"wis","dc":null,"scaling":"power"},"level":5,"school":"drk","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Insanity.webp","effects":[]}
{"_id":"Vsnr0aVZQIcRD0Ed","name":"Force Mask","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Mind Trick</em></p>\n<p>Until the power ends or you use an action to dismiss it, you can disguise yourself through use of the Force in many ways. You can appear to be shorter or taller by about a foot and change the appearance of your body and weight, but you cannot change the basic structure of your body. This effect can include your clothes, weapons, and other belongings on your person.</p>\n<p>This effect is only visual, so any sort of physical contact will only interact with the real size and shape of you. A creature that uses its action to examine you can identify this effect with a successful Intelligence (Investigation) check against your force save DC. This power has no effect on droids or constructs.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"hour"},"target":{"value":null,"units":"","type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"abil","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"int","dc":null,"scaling":"power"},"level":1,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Force%20Mask.webp","effects":[]}
{"_id":"WBNy29tnkclypOVZ","name":"Danger Sense","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>You put your faith in the Force, feeling out the future and seeing whether your actions will lead to fortune or ruin. The GM chooses from the following possible omens:</p>\n<ul>\n<li>Peace, for results which are not dangerous</li>\n<li>Danger, for results which are dangerous but perhaps still worth the danger</li>\n<li>Ruin, for results which are certain to end in death or tragedy</li>\n</ul>\n<p>The power doesnt take into account any possible circumstances that might change the outcome, such as the use of additional powers or the loss or gain of a companion.</p>\n<p>If you use this power two or more times before completing your next long rest, there is a cumulative 25 percent chance for each casting after the first that you get a neutral result regardless of the actual outcome.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"bonus","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":null,"units":"","type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":2,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Danger%20Sense.webp","effects":[]}
{"_id":"WG79exTllchDSK6M","name":"Animate Weapon","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Force Disarm</em></p>\n<p>You select a melee weapon you wield, or one melee weapon within range that is not worn or carried by a conscious creature, and use the Force to cause it to levitate, acting as an extension of your will for the duration or until you cast this power again. When you use this power, you can cause the weapon to move up to 20 feet and make a melee force attack against a creature within 5 feet of it. On a hit, the target takes 1d8 + your forcecasting ability modifier damage. The type is of the normal damage dealt by the weapon.</p>\n<p>While the weapon is animated, on each of your turns you can use a bonus action to move the weapon up to 20 feet and repeat the attack against a creature within 5 feet of it. At any time, you can end this force power to return the animated weapon to your hand.</p>\n<p>An enemy can attempt to gain control of the weapon by using its action to make a Strength (Athletics) check against your force save DC. On a success, the creature gains control of the weapon and the power ends.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 3rd level or higher, the weapon&rsquo;s damage increases by 1d8 for every two slot levels above 2nd.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"bonus","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":1,"units":"","type":"object"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"wis","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod",""]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":2,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"1d6"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Animate%20Weapon.webp","effects":[]}
{"_id":"WG79exTllchDSK6M","name":"Animate Weapon","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Force Disarm</em></p>\n<p>You select a melee weapon you wield, or one melee weapon within range that is not worn or carried by a conscious creature, and use the Force to cause it to levitate, acting as an extension of your will for the duration or until you cast this power again. When you use this power, you can cause the weapon to move up to 20 feet and make a melee force attack against a creature within 5 feet of it. On a hit, the target takes 1d8 + your forcecasting ability modifier damage. The type is of the normal damage dealt by the weapon.</p>\n<p>While the weapon is animated, on each of your turns you can use a bonus action to move the weapon up to 20 feet and repeat the attack against a creature within 5 feet of it. At any time, you can end this force power to return the animated weapon to your hand.</p>\n<p>An enemy can attempt to gain control of the weapon by using its action to make a Strength (Athletics) check against your force save DC. On a success, the creature gains control of the weapon and the power ends.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 3rd level or higher, the weapon&rsquo;s damage increases by 1d8 for every two slot levels above 2nd.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"bonus","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":1,"units":"","type":"object"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":"0","max":"0","per":""},"ability":"wis","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod",""]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":2,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"1d6"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Animate%20Weapon.webp","effects":[]}
{"_id":"WWCvfD4ldEZoR5fn","name":"Mind Trap","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Force Confusion</em></p>\n<p>You attempt to trap the mind of your target in a psychic cage. The target must make a Charisma saving throw. On a failed save, the creature&rsquo;s mind is trapped. It can think, but it can&rsquo;t have any contact with or perceive the outside world. If the creature takes damage, it makes another Charisma save. On a success, the power ends. This power has no effect on droids or constructs.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 6th level or higher, after 1 minute of concentration the power&rsquo;s duration becomes 24 hours and it no longer requires your concentration.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"cha","dc":null,"scaling":"power"},"level":4,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Mind%20Trap.webp","effects":[]}
{"_id":"XJSLZaP9Nix5EJHY","name":"Curse","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Denounce</em></p>\n<p>Up to three creatures of your choice that you can see within range must make Charisma saving throws. Whenever a target that fails this saving throw makes an attack roll or a saving throw before the power ends, the target must roll a d4 and subtract the number rolled from the attack roll or saving throw.</p>\n<p><strong><em><strong>Force Potency.</strong></em>&nbsp;</strong>When you cast this power using a force slot of 2nd level or higher, you can target one additional creature for each slot level above 1st.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":"Have Denounce Power"},"duration":{"value":1,"units":"minute"},"target":{"value":3,"units":"","type":"creature"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"1d4","save":{"ability":"cha","dc":null,"scaling":"power"},"level":1,"school":"drk","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"level","formula":"1 Addition Target"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Curse.webp","effects":[]}
{"_id":"XYHAKmU4gHSzRK3I","name":"Force Suppression","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>Choose one creature, object, or force effect within range. Any force power of 3rd level or lower on the target ends. For each force power of 4th level or higher on the target, make an ability check using your forcecasting ability. The DC equals 10 + the powers level. On a success, the power ends.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 4th level or higher, you automatically end the effects of a force power on the target if the powers level is equal to or less than the level of the force slot you used.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":120,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"abil","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"wis","dc":null,"scaling":"power"},"level":3,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Force%20Suppression.webp","effects":[]}
@ -157,6 +160,7 @@
{"_id":"ebWGew0oR2CG7S43","name":"Disperse Force","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Saber Ward</em></p>\n<p>This power absorbs damage from incoming energy attacks, lessening its effect on you and distributing it throughout your body. You have resistance to the triggering damage type until the start of your next turn. Also, you gain 5 temporary hit points to potentially absorb the attack. These temporary hit points last until the start of your next turn.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 2nd level or higher, the temporary hit points increases by 5 for each slot level above 1st.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"reaction","cost":1,"condition":"which you take when you take cold, energy, fire, ion, lightning, or sonic damage"},"duration":{"value":1,"units":"round"},"target":{"value":null,"units":"","type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"5 additional Temp HP"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Disperse%20Force.webp","effects":[]}
{"_id":"ecDdTd9MW0z4h8Hb","name":"Sap Vitality","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>Make a melee force attack against a creature you can reach. On a hit, the target takes 3d10 necrotic damage.</p>\n<p><strong><em><strong>Force Potency.</strong></em></strong>&nbsp;When you cast this power using a force slot of 2nd level or higher, the damage increases by 1d10 for each slot level above 1st.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"mpak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["3d10","necrotic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"drk","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"1d10"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Sap%20Vitality.webp","effects":[]}
{"_id":"esyvxlavJubgPNmj","name":"Force Trance","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>You make a calming gesture, and up to three willing creatures of your choice that you can see within range fall unconscious for the powers duration. The power ends on a target early if it takes damage or someone uses an action to shake or slap it awake. If a target remains unconscious for the full duration, that target gains the benefit of a short rest, and it cant be affected by this power again until it finishes a long rest.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 4th level or higher, you can target one additional willing creature for each slot level above 3rd.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":10,"units":"minute"},"target":{"value":3,"units":"","type":"creature"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":3,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"1 additional creature"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Force%20Trance.webp","effects":[]}
{"name":"Kinetite","permission":{"default":0,"IpSq6HI4edO6e0Yw":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite: </strong>Sustained Lightning</em></p>\n<p>A 5-foot-diameter sphere of compressed lightning appears in an unoccupied space of your choice within range and lasts for the duration. Any creature that ends its turn within 5 feet of the sphere must make a Dexterity saving throw. The creature takes 2d6 lightning damage on a failed save, or half as much damage on a successful one.</p>\n<p>As a bonus action, you can move the sphere up to 30 feet. If you ram the sphere into a creature, that creature must make a Dexterity saving throw, taking 2d6 kinetic damage on a failed save or half as much damage on a successful one, and the sphere stops moving this turn.</p>\n<p>When you move the sphere, you can direct it over barriers up to 5 feet tall and jump it across pits up to 10 feet wide. The sphere ignites flammable objects not being worn or carried, and it sheds bright light in a 20-foot radius and dim light for an additional 20 feet.</p>\n<p><em><strong>Force Potency.</strong></em> When you cast this power with a force slot of 3rd level or higher, both the lightning and kinetic damage increase by 1d6 for each slot level above 2nd.</p>","chat":"","unidentified":""},"requirements":"","source":"EC","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":5,"width":null,"units":"ft","type":"sphere"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":"0","max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["2d6","lightning"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"power"},"level":2,"school":"drk","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"level","formula":"1d6"}},"flags":{"core":{"sourceId":"Item.sOyvjT8ig2Eninf3"}},"img":"systems/sw5e/packs/Icons/Force%20Powers/Kinetite.webp","effects":[],"_id":"f01f9EPd9qvVy6QA"}
{"_id":"f41D14g0yIBuXUka","name":"Force Immunity","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>An immobile, faintly shimmering barrier springs into existence around you and remains for the duration. The barrier moves with you. Any force power of 3rd level or lower cast from outside the barrier cant affect you, even if the power is cast using a higher level force slot. Such a power can target you, but the power has no effect on you. Similarly, the area within the barrier is excluded from the areas affected by such powers.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 5th level or higher, the barrier blocks powers of one level higher for each slot level above 4th.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":null,"units":"","type":"self"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":4,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"level","formula":"1 additional slot"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Force%20Immunity.webp","effects":[]}
{"_id":"faTYDaOejYHPfXdl","name":"Earthquake","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Eruption</em></p>\n<p>You create a seismic disturbance at a point on the ground that you can see within range. For the duration, an intense tremor rips through the ground in a 100-foot-radius circle centered on that point and shakes creatures and structures in contact with the ground in that area.</p>\n<p>The ground in the area becomes difficult terrain. Each creature on the ground that is concentrating must make a Constitution saving throw. On a failed save, the creature&rsquo;s concentration is broken.</p>\n<p>When you cast this power and at the end of each turn you spend concentrating on it, each creature on the ground in the area must make a Dexterity saving throw. On a failed save, the creature is knocked prone.</p>\n<p>This power can have additional effects depending on the terrain in the area, as determined by the GM.</p>\n<p><strong>Fissures.</strong>&nbsp;Fissures open throughout the power&rsquo;s area at the start of your next turn after you cast the power. A total of 1d6 such fissures open in locations chosen by the GM. Each is 1d10 x 10 feet deep, 10 feet wide, and extends from one edge of the power&rsquo;s area to the opposite side. A creature standing on a spot where a fissure opens must succeed on a Dexterity saving throw or fall in. A creature that successfully saves moves with the fissure&rsquo;s edge as it opens.</p>\n<p>A fissure that opens beneath a structure causes it to automatically collapse (see below).</p>\n<p><strong>Structures.&nbsp;</strong>The tremor deals 50 kinetic damage to any structure in contact with the ground in the area when you cast the power and at the start of each of your turns until the power ends. If a structure drops to 0 hit points, it collapses and potentially damages nearby creatures. A creature within half the distance of a structure&rsquo;s height must make a Dexterity saving throw. On a failed save, the creature takes 5d6 kinetic damage, is knocked prone, and is buried in the rubble, requiring a DC 20 Strength (Athletics) check as an action to escape. The GM can adjust the DC higher or lower, depending on the nature of the rubble. On a successful save, the creature takes half as much damage and doesn&rsquo;t fall prone or become buried.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":100,"units":"ft","type":"radius"},"range":{"value":500,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"power"},"level":8,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Earthquake.webp","effects":[]}
{"_id":"fcs6lsi5hMfPOgRb","name":"Resistance","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>You touch one willing creature. Once before the power ends, the target can roll a d4 and add the number rolled to one saving throw of its choice. It can roll the die before or after the saving throw. The power then ends.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"other","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"1d4","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Resistance.webp","effects":[]}
@ -184,6 +188,7 @@
{"_id":"qIelaqr9e9Cn0W8O","name":"Calm Emotions","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Sense Emotion</em></p>\n<p>You attempt to suppress strong emotions in a group of people. Each humanoid in a 20-foot-radius sphere centered on a point you choose within range must make a Charisma saving throw a creature can choose to fail this saving throw if it wishes. If a creature fails its saving throw, choose one of the following two effects.</p>\n<ul>\n<li>You can suppress any effect causing a target to be charmed or frightened. When this power ends, any suppressed effect resumes, provided that its duration has not expired in the meantime.</li>\n<li>You can make a target indifferent about creatures of your choice that it is hostile toward. This indifference ends if the target is attacked or harmed by a power or if it witnesses any of its friends being harmed.</li>\n</ul>\n<p>When the power ends, the creature becomes hostile again, unless the GM rules otherwise.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":20,"units":"ft","type":"sphere"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"cha","dc":null,"scaling":"power"},"level":2,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Calm%20Emotions.webp","effects":[]}
{"_id":"qYnIKhpoJpSflVZh","name":"Telekinetic Burst","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Telekinetic Storm</em></p>\n<p>A beam of Force energy flashes out from your hand in a 5-foot-wide, 60-foot-long line. Each creature in the line must make a Constitution saving throw. On a failed save, a creature takes 8d6 force damage and is knocked prone. On a successful save, it takes half as much damage and isn&rsquo;t knocked prone.</p>\n<p>You can create a new telekinetic gust as your action on your turn until the power ends.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;When you cast this power using a force slot of 7th level or higher, the damage increases by 2d6 for each slot level above 6th.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":60,"units":"ft","type":"line","width":null},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["8d6","force"]],"versatile":""},"formula":"","save":{"ability":"con","dc":null,"scaling":"power"},"level":6,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"level","formula":"2d6"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Telekinetic%20Burst.webp","effects":[]}
{"_id":"qkBzg8ZIJpglVMvi","name":"Beacon of Hope","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Heroism</em></p>\n<p>This power bestows hope and vitality. Choose any number of creatures within range. For the duration, each target has advantage on Wisdom saving throws and death saving throws, and regains the maximum number of hit points possible from any healing.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":null,"units":"any","type":"creature"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":3,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Beacon%20of%20Hope.webp","effects":[]}
{"name":"Defensive Technique","permission":{"default":0,"IpSq6HI4edO6e0Yw":3},"type":"power","data":{"description":{"value":"<p>As part of the action used to cast this power, you must make a melee weapon attack against one creature within your reach, otherwise the power fails. On a hit, the target suffers the attack's normal effects, and you ward yourself from it through the Force.</p>\n<p>If the target forces you to make a saving throw before the start of your next turn, the target takes an additional 1d6 psychic damage, and you can roll 1d4 and add the number rolled to your saving throw. The power then ends.</p>\n<p>The power's damage increases when you reach higher levels. At 5th level, the melee attack deals an extra 1d6 force damage to the target, and the psychic damage the target takes for forcing you to make a saving throw increases to 2d6. Both damage rolls increase by 1d6 at 11th level and 17th level.</p>","chat":"","unidentified":""},"requirements":"","source":"EC","activation":{"type":"action","cost":1,"condition":"you must make a melee weapon attack against one creature within your reach, otherwise the power fails"},"duration":{"value":1,"units":"round"},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":""},"uses":{"value":"0","max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""}},"flags":{"core":{"sourceId":"Item.ielR5DiQGGDRsJB5"}},"img":"systems/sw5e/packs/Icons/Force%20Powers/Defensive%20Technique.webp","effects":[],"_id":"qv4hHFZKUwg7Ail2"}
{"_id":"qykEFT52bywaQrNO","name":"Force Technique","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p>You imbue your weapon with the purifying light of the Force. As part of the action used to cast this power, you must make a melee attack with a weapon against one creature within your weapons reach, otherwise the power fails. On a hit, the target suffers the attacks normal effects, and it becomes wreathed in a glowing barrier of force energy until the start of your next turn. If the target willingly moves before then, it immediately takes 1d8 force damage, and the power ends.</p>\n<p>This powers damage increases when you reach higher levels. At 5th level, the melee attack deals an extra 1d8 force damage to the target, and the damage the target takes for moving increases to 2d8. Both damage rolls increase by 1d8 at 11th level and 17th level.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":"You must make a melee attack with a weapon against one creature within your weapons reach"},"duration":{"value":1,"units":"round"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"other","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d8",""]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"lgt","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"atwill","formula":"1d8"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Force%20Technique.webp","effects":[]}
{"_id":"rxvZoFgkC411tibT","name":"Break","permission":{"default":0,"IpSq6HI4edO6e0Yw":3},"type":"power","data":{"description":{"value":"<p>You inflict 10 force damage to an object you can see within range that is not being worn or carried, generating an explosion of sound that can be heard up to 100 feet away. Even if the object is not destroyed, small shards of shrapnel fly at creatures within 5 feet of it. Each creature must make a Dexterity saving throw. On a failed save, a creature takes 1d4 kinetic damage.</p>\n<p>This power's kinetic damage increases by 1d4 when you reach 5th level (2d4), 11th level (3d4), and 17th level (4d4), and the power's force damage also increases by 10 at each of these levels.</p>","chat":"","unidentified":""},"source":"EC","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":1,"width":null,"units":"","type":"object"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"rpak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["10","force"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"uni","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""}},"flags":{"core":{"sourceId":"Item.sVK2BXvC9pEX8By5"}},"img":"systems/sw5e/packs/Icons/Force%20Powers/Break.webp","effects":[]}
{"_id":"sFLwKTBxnM6YfboP","name":"Wrack","permission":{"default":0,"00LEX91CfLcf3HGf":3},"type":"power","data":{"description":{"value":"<p><em><strong>Prerequisite:</strong> Plague</em></p>\n<p>You wrack the body of a creature that you can see with a virulent, disease-like condition. The target must make a Constitution saving throw. On a failed save, it takes 14d6 necrotic damage, or half as much damage on a successful save. The damage can&rsquo;t reduce the target&rsquo;s hit points below 1. If the target fails the saving throw, its hit point maximum is reduced for 1 hour by an amount equal to the necrotic damage it took. Any effect that removes a disease allows a creature&rsquo;s hit point maximum to return to normal before that time passes.</p>\n<p><em><strong>Force Potency.</strong></em>&nbsp;If you cast this power using a force slot of 7th level or higher, the power deals an extra 2d6 damage for each slot level above 6th.</p>","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":"Plague"},"duration":{"value":null,"units":"inst"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["14d6","necrotic"]],"versatile":""},"formula":"","save":{"ability":"con","dc":null,"scaling":"power"},"level":6,"school":"drk","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"2d6"},"armorproperties":{"parts":[]},"weaponproperties":{"parts":[]},"consume":{"type":"","target":"","amount":null}},"flags":{},"img":"systems/sw5e/packs/Icons/Force%20Powers/Wrack.webp","effects":[]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -20,6 +20,7 @@
{"_id":"6iIYMjmyWE2wqgzf","name":"Carbonite","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>You attempt to freeze one creature that you can see within range into carbonite. The creature must make a Constitution saving throw. On a failed save, it is restrained as its flesh begins to harden. On a successful save, the creature isn't affected.</p>\n<p>A creature restrained by this power must make another Constitution saving throw at the end of each of its turns. If it successfully saves against this power three times, the power ends. If it fails its saves three times, it is turned to stone and subjected to the petrified condition for the duration. The successes and failures don't need to be consecutive; keep track of both until the target collects three of a kind.</p>\n<p>If the creature is physically broken while frozen in carbonite, it suffers from similar deformities if it reverts to its original state.</p>\n<p>If you maintain your concentration on this power for the entire possible duration, the creature is frozen in carbonite until the effect is removed.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"save","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"con","dc":null,"scaling":"power"},"level":6,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/Carbonite.webp"}
{"_id":"6oJ07fhBJLXJ7zv1","name":"Scramble Interface","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>You choose one droid or construct you can see within range and scramble its ability to differentiate targets. The target must make an Intelligence saving throw. If the construct has the 'Piloted' trait, and has a pilot controlling it that is not incapacitated, it gains a bonus to the saving throw equal to the pilot's Intelligence modifier. On a failed save, the target loses the ability to distinguish friend from foe, regarding all creatures it can see as enemies until the power ends. Each time the target takes damage, it can repeat the saving throw, ending the effect on itself on a success.</p>\n<p>Whenever the affected creature chooses another creature as a target, it must choose the target at random from among the creatures it can see within range of the attack, power, or other ability it's using. If an enemy provokes an opportunity attack from the affected creature, the creature must make that attack if it is able to.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":120,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"save","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"int","dc":null,"scaling":"power"},"level":3,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/ScrambleInterface.webp"}
{"_id":"73W8rKPEbN60y7L2","name":"Defibrillate","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>You touch a creature that has died within the last minute and administer a shock to restore it to life. That creature returns to life with 1 hit point. This power can't return to life a creature that has died of old age, nor can it restore any missing body parts. If the creature is lacking body parts or organs integral for its survival<61>its head, for instance<63>the power automatically fails. Once this power has restored a creature to life, it cannot benefit from this power again until it finishes a short or long rest.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":4,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/Defibrillate.webp"}
{"name":"Tri-Shot","permission":{"default":0,"IpSq6HI4edO6e0Yw":3},"type":"power","data":{"description":{"value":"<p>Choose up to three creatures within range, none of whom can be more than 10 feet apart. If you choose three creatures, each target must succeed on a Dexterity saving throw or take 1d4 energy damage. If you choose two creatures, each target takes 1d6 energy damage on a failed save instead. If you choose only one creature, the target takes 1d8 energy damage on a failed save.</p>\n<p>This power's damage increases by one die when you reach 5th level (two dice), 11th level (three dice), and 17th level (four dice).</p>","chat":"","unidentified":""},"requirements":"","source":"EC","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":3,"width":null,"units":"","type":"creature"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":"0","max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"power"},"level":0,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""}},"flags":{"core":{"sourceId":"Item.Tjrr6QDVOaLdRHZO"}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/Tri-Shot.webp","effects":[],"_id":"782klgZPJ4zjZX4E"}
{"_id":"7Twjeo1X2oUP9IZo","name":"Elemental Accelerant","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>Choose one creature you can see and one damage type: acid, cold, fire, lightning, or sonic. The target must make a Constitution saving throw. If it fails, the first time on each turn when it takes damage of the chosen type, it takes an extra 2d6 damage of it. The target also loses resistance to the type until the power ends.</p>\n<p><em><strong>Overcharge Tech.</strong></em> You can target one additional creature for each slot level above 4th. The creatures must be within 30 feet of each other when you target them.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":90,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"save","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["2d6",""]],"versatile":""},"formula":"","save":{"ability":"con","dc":null,"scaling":"power"},"level":4,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/ElementalAccelerant.webp"}
{"_id":"7khirDTQvs7rtLbW","name":"Copy","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>This power creates a perfect duplicate of any written, drawn, or digital visual, audio or text-based data that you touch onto a datapad or datacard you supply. You can copy up to 10 pages of text or 10 minutes of visual or audio data with one casting of this power. Enhanced documents, such as datacrons, blueprints, or encrypted documents, can't be copied with this power.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"units":"","type":"object"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/Copy.webp"}
{"_id":"7o2xvsn9AVML11ME","name":"Storming Shot","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>As a part of the action used to cast this power, you must make a ranged weapon attack against one creature within your weapon's range, otherwise the power fails. On a hit, the target suffers the attack's normal effects and becomes shocked until the end of your next turn. When this power hits a target, if there is a creature within 30 feet who is shocked, an arc of lightning courses between the two creatures, dealing 1d6 lightning damage to both of them. If there are multiple other creatures who are shocked, the lightning leaps to the closest creature.</p>\n<p>The power's damage increases when you reach higher levels. At 5th level, the effects of both the ranged weapon attack and discharge deal an extra 1d6 lightning damage. Both damage rolls increase by an additional 1d6 at 11th and 17th level.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"round"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"spec"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"other","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6","lightning"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"atwill","formula":"1d6"}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/StormingShot.webp"}
@ -132,6 +133,7 @@
{"_id":"Zk697eWSqME5gpkF","name":"Condense/Vaporize","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>In an open container, you can create up to 10 gallons of drinkable water. You may also produce a rain that falls within a 30-foot cube and extinguishes open-air flames. You can destroy the same amount of water in an open container, or destroy a 30-foot cube of fog.</p>\n<p><em><strong>Overcharge Tech.</strong></em> When you cast this power using a tech slot of 2nd level or higher, the amount of water you can create increases by 10 gallons, or the size of the cube increases by 5 feet, for each slot level above 1st.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"units":"","type":"object"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/CondenseVaporize.webp"}
{"_id":"a4nZ05eHgTXZo4TU","name":"Cage","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>An immobile, Invisible, cube-shaped prison composed of energy springs into existence around an area you choose within range. The prison can be a cage or a solid box as you choose.</p>\n<p>A prison in the shape of a cage can be up to 20 feet on a side and is made from 1/2-inch diameter bars spaced 1/2 inch apart.</p>\n<p>A prison in the shape of a box can be up to 10 feet on a side, creating a solid barrier that prevents any matter from passing through it and blocking any powers cast into or out of the area.</p>\n<p>When you cast the power, any creature that is completely inside the cage's area is trapped. Creatures only partially within the area, or those too large to fit inside the area, are pushed away from the center of the area until they are completely outside the area.</p>\n<p>A creature inside the cage can't leave it by unenhanced means. If the creature tries to teleport to leave the cage, it must first make a Charisma saving throw. On a success, the creature can use that power to exit the cage. On a failure, the creature can't exit the cage and wastes the use of the power or effect.</p>\n<p>This power can't be dispelled.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"hour"},"target":{"value":20,"units":"ft","type":"cube"},"range":{"value":100,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":7,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/Cage.webp"}
{"_id":"aJqCpoejohXYuJ1J","name":"Sonic Strike","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>As part of the action used to cast this power, you must make a melee weapon attack against one creature within your reach, otherwise the power fails. On a hit, the target suffers the attack's normal effects, and you begin to emanate a disturbing hum. If a hostile creature ends its turn within 5 feet of you before the start of your next turn, it takes 1d4 sonic damage.</p>\n<p>This power's damage increases when you reach higher levels. At 5th level, the melee attack deals an extra 1d8 sonic damage to the target, and the secondary damage increases by 1d4. Both damage rolls increase by 1d8 and 1d4, respectively, at 11th level and 17th level.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"round"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"spec"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"util","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4","sonic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"atwill","formula":"1d8"}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/SonicStrike.webp"}
{"name":"Aid Droid","permission":{"default":0,"IpSq6HI4edO6e0Yw":3},"type":"power","data":{"description":{"value":"<p>Choose one droid or construct that you can see within range. The target can immediately use its reaction to regain hit points equal to 1d6 + your techcasting ability modifier.</p>\n<p><strong><em>Overcharge Tech.</em></strong> When you cast this power using a tech slot of 2nd level or higher, the healing increases by 1d6 for each slot level above 1st.</p>","chat":"","unidentified":""},"requirements":"","source":"EC","activation":{"type":"bonus","cost":1,"condition":""},"duration":{"value":null,"units":"inst"},"target":{"value":1,"width":null,"units":"","type":"droid"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":"0","max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"heal","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6+@abilities.int.mod","healing"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"level","formula":"1d6"}},"flags":{"core":{"sourceId":"Item.xI9OeBQggss4H0AI"}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/Aid%20Droid.webp","effects":[],"_id":"aW2gm0t0dNq2YMcm"}
{"_id":"b0T7rxNgDtGx3mwh","name":"Stack the Deck","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>You boost up to three creatures of your choice within range. Whenever a target makes an attack roll or a saving throw before the power ends, the target can roll a d4 and add the number rolled to the attack roll or saving throw.</p>\n<p><em><strong>Overcharge Tech.</strong></em> When you cast this power with a tech slot of 2nd level or higher, you can target one additional creature for every two slot levels above 1st. When you cast this power at 3rd level or higher, the die size increases for every two slot levels above 1st (d6 at 3rd level, d8 at 5th level, d10 at 7th level).</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"util","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"1d4","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/Stackthe%20Deck.webp"}
{"_id":"bp55Q4R0gBpd0FiM","name":"Oil Slick","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>You cover the ground in a 10-foot square within range in oil. For the duration, it is difficult terrain.</p>\n<p>When the oil appears, each creature standing in its area must succeed on a Dexterity saving throw or fall prone. A creature that enters the area or ends its turn there must also succeed on a Dexterity saving throw.</p>\n<p>The oil is flammable. Any 5 foot square of the oil exposed to fire burns away in one round. Each creature who enters the fire or starts it turn there must make a Dexterity saving throw, taking 3d6 fire damage on a failed save, or half as much on a successful one. The fire ignites any flammable objects in the area that aren't being worn or carried.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":10,"units":"ft","type":"square"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"save","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["3d6","fire"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"power"},"level":1,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/OilSlick.webp"}
{"_id":"c17MNNJ8FplU5Txm","name":"Absorb Energy","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>The power captures some of the incoming energy, lessening its effect on you and storing it for your next melee attack. You have resistance to the triggering damage type until the start of your next turn. Also, the first time you hit with a melee attack on your next turn, the target takes an extra 1d6 damage of the triggering type, and the power ends.</p>\n<p><em><strong>Overcharge Tech.</strong></em> When you cast this power using a power slot of 2nd level or higher, the extra damage increases by 1d6 for each slot level above 1st.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"reaction","cost":1,"condition":"which you take when you take acid, cold, energy, fire, ion, kinetic, lightning, or sonic damage"},"duration":{"value":1,"units":"round"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"util","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6",""]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":false},"scaling":{"mode":"level","formula":"1d6"}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/AbsorbEnergy.webp","effects":[]}
@ -190,6 +192,7 @@
{"_id":"to84bBMy9F4zYZ5I","name":"Combustive Shot","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>As part of the action used to cast this power, you must make a ranged weapon attack against one creature within your weapon's range, otherwise the power fails. On a hit, the target suffers the attack's normal effects, and it ignites in flame. At the start of your next turn, the creature takes fire damage equal to your techcasting ability modifier. If the target or a creature within 5 feet of it uses an action to put out the flames, or if some other effect douses the flames, the effect ends.</p>\n<p>This power's damage increases when you reach higher levels. At 5th level, the ranged attack deals an extra 1d6 fire damage to the target, and the damage at the start of your next turn increases to 1d4 + your tech casting ability modifier. Both damage rolls increase by 1d6 and 1d4, respectively, at 11th level and 17th level.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"round"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"spec"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"util","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["@abilities.int.mod","fire"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"atwill","formula":"1d6"}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/CombustiveShot.webp"}
{"_id":"uKVIsflQoqXlbejy","name":"Radiation","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>Dim, greenish light spreads within a 30-foot-radius sphere centered on a point you choose within range. The light spreads around corners, and it lasts until the power ends.</p>\n<p>When a creature moves into the power's area for the first time on a turn or starts its turn there, that creature must succeed on a Constitution saving throw or take 4d10 necrotic damage, and it suffers one level of exhaustion and emits a dim, greenish light in a 5-foot radius. This light makes it impossible for the creature to benefit from being invisible. The light and any levels of exhaustion caused by this power go away when the power ends.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":10,"units":"minute"},"target":{"value":30,"units":"ft","type":"radius"},"range":{"value":120,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"save","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["4d10","necrotic"]],"versatile":""},"formula":"","save":{"ability":"con","dc":null,"scaling":"power"},"level":4,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/Radiation.webp"}
{"_id":"uLB7E27wecdLLbCE","name":"Minor Defibrillation","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>You generate a static charge that can aid or harm a creature you touch. Make a melee tech attack against the target. On a hit, the target takes 1d10 lightning damage. If the target is a living creature that has 0 hit points, it immediately gains one death saving throw success instead of taking damage.</p>\n<p>This power's damage increases by 1d10 when you reach 5th level (2d10), 11th level (3d10), and 17th level (4d10).</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"mpak","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["1d10","lightning"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"atwill","formula":"1d10"}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/MinorDefibrillation.webp"}
{"name":"Alter Self","permission":{"default":0,"IpSq6HI4edO6e0Yw":3},"type":"power","data":{"description":{"value":"<p>You alter your form with tech. When you cast the power, choose one of the following options, the effects of which last for the duration of the power. While the power lasts, you can end one option as an action to gain the benefits of a different one.</p>\n<p><strong><em>Aquatic Adaptation.</em></strong> You adapt your body to an aquatic environment. You can breathe underwater and gain a swimming speed equal to your walking speed.</p>\n<p><strong><em>Change Appearance.</em></strong> You transform your appearance. You decide what you look like, including your height, weight, facial features, sound of your voice, hair length, coloration, and distinguishing characteristics, if any. You can make yourself appear as a member of another species (an organic species cannot appear as a droid, or vice versa), though none of your statistics change. You can also alter your vocal cords, enabling you to speak a language you know, but otherwise would be incapable of speaking. You also can&rsquo;t appear as a creature of a different size than you, and your basic shape stays the same; if you&rsquo;re bipedal, you can&rsquo;t use this power to become quadrupedal, for instance. At any time for the duration of the power, you can use your action to change your appearance in this way again.</p>\n<p><strong><em>Natural Weapons.</em></strong> You grow claws, fangs, spines, horns, or a different natural weapon of your choice. Your damage die for your unarmed strikes increases by one step (from 1 to d4, d4 to d6, or d6 to d8). Your unarmed strikes are considered enhanced and you have a +1 bonus to attack and damage rolls with them.</p>","chat":"","unidentified":""},"requirements":"","source":"EC","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"hour"},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":"0","max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":2,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""}},"flags":{"core":{"sourceId":"Item.lGXbhhtTzcGCZQ9b"}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/Alter%20Self.webp","effects":[],"_id":"uuxkihWcbMdubsLx"}
{"_id":"vo6OJqBxuOiyMyxX","name":"Kolto Cloud","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>As you expel kolto, up to six creatures of your choice that you can see within range regain hit points equal to 1d4 + your techcasting ability modifier. This power has no effect on droids or constructs.</p>\n<p><em><strong>Overcharge Tech.</strong></em> When you cast this power using a tech slot of 4th level or higher, the healing increases by 1d4 for each slot level above 3rd.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"bonus","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":6,"units":"","type":"creature"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"heal","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @abilities.int.mod","healing"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":3,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"level","formula":"1d4"}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/KoltoCloud.webp"}
{"_id":"w8aWJGuIPq2kp4Qj","name":"Delayed Explosion","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>You create a delayed explosion at a point within range. When the power ends, either because your concentration is broken or because you decide to end it, the explosion occurs. Each creature in a 20-foot-radius sphere centered on that point must make a Dexterity saving throw. A creature takes fire damage equal to the total accumulated damage on a failed save, or half as much damage on a successful one.</p>\n<p>The power's base damage is 12d6. If at the end of your turn the explosion has not yet occurred, the damage increases by 1d6.</p>\n<p>If the explosion is touched before the interval has expired, the creature touching it must make a Dexterity saving throw. On a failed save, the power ends immediately, causing the explosion.</p>\n<p>The fire spreads around corners. It ignites flammable objects in the area that aren't being worn or carried.</p>\n<p><em><strong>Overcharge Tech.</strong></em> When you cast this power using a tech slot of 8th level or higher, the base damage increases by 1d6 for each slot level above 7th.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":20,"units":"ft","type":"radius"},"range":{"value":150,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"save","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["12d6",""]],"versatile":"1d6"},"formula":"","save":{"ability":"dex","dc":null,"scaling":"power"},"level":7,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"level","formula":"1d6"}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/DelayedExplosion.webp"}
{"_id":"wtSlQwtA4N2ewADb","name":"Preparedness","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>You touch a willing creature. For the duration, the target can add 1d8 to its initiative rolls.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"minute","cost":1,"condition":""},"duration":{"value":8,"units":"hour"},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"touch"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":1,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/Preparedness.webp"}
@ -197,6 +200,7 @@
{"_id":"xW2LoI7JTHMqPcuC","name":"Mobile Lights","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>You create up to four orbs of light within range that hover in the air for the duration. You can also combine the four lights into one glowing vaguely humanoid form of Medium size. Whichever form you choose, each light sheds dim light in a 10-foot radius.</p>\n<p>As a bonus action on your turn, you can move the lights up to 60 feet to a new spot within range. A light must be within 20 feet of another light created by this power, and a light winks out if it exceeds the power's range.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"minute"},"target":{"value":null,"units":"","type":"self"},"range":{"value":120,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/MobileLights.webp"}
{"_id":"xXPplfLNPoXvhfjp","name":"Wire Line","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>You launch a grappling wire toward a creature you can see within range. Make a melee tech attack against the target. If the attack hits, the creature takes 1d6 kinetic damage, and if the creature is Large or smaller, you pull the creature up to 10 feet closer to you.</p>\n<p>This power's damage increases by 1d6 when you reach 5th level (2d6), 11th level (3d6), and 17th level (4d6).</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"units":"","type":"creature"},"range":{"value":30,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"mpak","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"atwill","formula":"1d6"}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/WireLine.webp"}
{"_id":"xeBPmKsGTsXqEszc","name":"Greater Analyze","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>Name or describe a person, place, or object. This power gives you a summary of significant lore about it. If the thing you named isn't known outside of one planetary system, you gain no information. The more information you already have, the more detailed the information you receive is.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"minute","cost":10,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"units":"","type":""},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":5,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/GreaterAnalyze.webp"}
{"name":"Mutate/Augment","permission":{"default":0,"IpSq6HI4edO6e0Yw":3},"type":"power","data":{"description":{"value":"<p>You alter your body with tech, temporarily gaining new properties which last for the duration. You can select three of the following properties. You cannot select a property more than once, unless that property says otherwise.</p>\n<ul>\n<li>Your body becomes more flexible. You have advantage on ability checks and saving throws against effects that would grapple or restrain you, and your movement is unaffected by difficult terrain or squeezing.</li>\n<li>You grow one additional appendage. This appendage serves as an arm and a hand, though it can take the shape of a limb, tentacle, or similar appendage. You can select this property twice to grow a maximum number of two appendages. You can only gain the benefit of items held by two of your arms at any given time, and once per round you can switch which arms you are benefiting from (no action required).</li>\n<li>You sprout antennae that give you tremorsense out to a range of 30 feet.</li>\n<li>You extend the length of your limbs. When you make a melee attack or attempt to grapple, shove, or trip a creature on your turn, your reach for it is 5 feet greater than normal.</li>\n<li>You gain a burrowing speed equal to your walking speed.</li>\n<li>Your flesh hardens. Your AC can't be less than 16, regardless of what kind of armor you're wearing.</li>\n<li>You can gain the benefits of any one option of the <em>alter self</em> power. You can select this property multiple times to gain the benefits of multiple options of the <em>alter self</em> power, choosing a different option each time.</li>\n<li>You gain the effect of the <em>magnetic hold</em> power, but you can affix to and move along any surface, instead of only metallic surfaces. You have a climbing speed equal to your walking speed.</li>\n<li>You can gain any one effect of the <em>force enlightenment</em> power.</li>\n</ul>\n<p><strong><em>Overcharge Tech.</em></strong> When you cast this power using a tech slot of 4th level or higher, you can select an additional property for each slot level above 3rd.</p>","chat":"","unidentified":""},"requirements":"","source":"EC","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":10,"units":"minute"},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":"0","max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":3,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":true},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"prepared","prepared":true},"scaling":{"mode":"none","formula":""}},"flags":{"core":{"sourceId":"Item.pY0NUf5jwDrhhiz9"}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/Mutate-Augment.webp","effects":[],"_id":"xoeFnjZ62vkY6ygA"}
{"_id":"xs0igvxRAzGwZqik","name":"Venomous Strike","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>As part of the action used to cast this power, you must make a melee weapon attack against one creature within your reach, otherwise the power fails. On a hit, the target suffers the attack's normal effects, and if you were hidden from it, it takes an additional 1d4 poison damage.</p>\n<p>This power's damage increases when you reach higher levels. At 5th level, the melee attack deals an extra 1d8 poison damage to the target, and the damage the target takes when you are hidden from it increases to 2d4. Both damage rolls increase by 1d8 and 1d4, respectively, at 11th level and 17th level.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":"spec"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"util","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4","poison"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":0,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"atwill","formula":"1d8"}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/VenomousStrike.webp"}
{"_id":"xxrRddwkMSsJbPs0","name":"Kolto Infusion","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>Choose a creature that you can see within range. A surge of kolto energy washes over the creature, causing it to regain 70 hit points. This power also ends blindness, deafness, and any diseases affecting the target. This power has no effect on droids or constructs.</p>\n<p><em><strong>Overcharge Tech.</strong></em> When you cast this power using a tech slot of 7th level or higher, the amount of healing increases by 10 for each slot level above 6th.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"units":"","type":"creature"},"range":{"value":60,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"heal","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[["+70","healing"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":6,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"level","formula":"10"}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/KoltoInfusion.webp"}
{"_id":"yBnreezRaiZpukCB","name":"Detect Invisibility","permission":{"default":0},"type":"power","data":{"description":{"value":"<p>For the duration, you see invisible creatures and objects as if they were visible.</p>\n","chat":"","unidentified":""},"source":"PHB","activation":{"type":"action","cost":1,"condition":""},"duration":{"value":1,"units":"hour"},"target":{"value":0,"units":"","type":""},"range":{"value":null,"long":null,"units":"self"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"int","actionType":"","attackBonus":null,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"level":2,"school":"tec","components":{"value":"","vocal":false,"somatic":false,"material":false,"ritual":false,"concentration":false},"materials":{"value":"","consumed":false,"cost":0,"supply":0},"preparation":{"mode":"","prepared":false},"scaling":{"mode":"none","formula":""}},"flags":{"exportSource":{"world":"sw5e","system":"sw5e","coreVersion":"0.6.6","systemVersion":0.98}},"img":"systems/sw5e/packs/Icons/Tech%20Powers/DetectInvisibility.webp"}

View file

@ -1,27 +1,27 @@
{"_id":"0ZRWgHRykApmHmoG","name":"Heavy Shotgun","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Burst 4, Reload 12, Strength 13</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":16,"price":400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":30,"long":120,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["2d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":2100001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Heavy%20Shotgun.webp","effects":[]}
{"_id":"1wmSlQ3a91lL9c3H","name":"Slugpistol","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Rapid 8, Reload 16, Strength 11</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":3,"price":100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":40,"long":160,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":true,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":4800001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Slugpistol.webp","effects":[]}
{"_id":"1zm4z1AKDhzXC2ow","name":"Jagged Vibroblade","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":5,"price":500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8+@mod","kinetic"]],"versatile":"1d10+@mod"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":true,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":true,"vic":true},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7187501,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"1zm4z1AKDhzXC2ow","name":"Jagged Vibroblade","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":5,"price":500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8+@mod","kinetic"]],"versatile":"1d10+@mod"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":true,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":true,"vic":true},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7187501,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Jagged%20Vibroblade.webp","effects":[]}
{"_id":"2RG5RZxqJ2q7jziD","name":"Switch carbine","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 60/240), Reload 12, Switch (1d4 acid)</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":8,"price":4600,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":20},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"1d4 + @mod","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6799904,"flags":{},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Switch%20Carbine.webp","effects":[]}
{"_id":"2ylNmxKfD5IdGre8","name":"Shatter pistol","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 40/160), Silent, Light, Reload 20</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":3,"price":800,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":40,"long":160,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":12},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":true,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6899806,"flags":{},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Shatter%20Pistol.webp","effects":[]}
{"_id":"3MBvpQfxedbIW6eH","name":"Vibrospear","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":3,"price":120,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":20,"long":60,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":"1d8 + @mod"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":true,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":6700001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Vibroweapons/Vibrospear.webp","effects":[]}
{"_id":"3u5NHZJFld4ayeEI","name":"Lightdagger","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":1,"price":100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":20,"long":60,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":true,"ken":false,"lgt":true,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":3400001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Lightweapons/Lightdagger.webp","effects":[]}
{"_id":"4q1qOqW9eYyAmn8l","name":"Vibrodart","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Due to their diminutive size, vibrodarts make ineffective melee weapons. Melee attack rolls made with them are made at disadvantage.</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":1,"price":5,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":20,"long":60,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":6100001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Vibroweapons/Vibrodart.webp","effects":[]}
{"_id":"50y7jToHJOvsO1Yr","name":"Repeating Blaster","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Burst 4, Rapid 4, Reload 8, Strength 13</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":18,"price":1200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":80,"long":320,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["2d4 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":true,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":true,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":4100001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Repeater.webp","effects":[]}
{"_id":"5RF22K1v5Pra1uwf","name":"Chained dagger","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Disarming, Finesse, Reach, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":6,"price":850,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":true,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6950001,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"5vPxd3p7M2m9j07G","name":"BKG","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 120/480), Auto, Burst 2, Disintegrate 13, Reload 2, Strength 19, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":42,"price":9000,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":10,"width":null,"units":"","type":"cube"},"range":{"value":120,"long":480,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":240},"ability":"dex","actionType":"save","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["3d4 + @mod","fire"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"dex"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":true,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":true,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":300001,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"62kO29wbh9pYXwb6","name":"Vibroknife","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Finesse, Light, Piercing 1</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":1,"price":600,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":true,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6899995,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"5RF22K1v5Pra1uwf","name":"Chained Dagger","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Disarming, Finesse, Reach, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":6,"price":850,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":true,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6950001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Chained%20Dagger.webp","effects":[]}
{"_id":"5vPxd3p7M2m9j07G","name":"BKG","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 120/480), Auto, Burst 2, Disintegrate 13, Reload 2, Strength 19, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":42,"price":9000,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":10,"width":null,"units":"","type":"cube"},"range":{"value":120,"long":480,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":240},"ability":"dex","actionType":"save","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["3d4 + @mod","fire"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"dex"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":true,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":true,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":300001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/BKG.webp","effects":[]}
{"_id":"62kO29wbh9pYXwb6","name":"Vibroknife","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Finesse, Light, Piercing 1</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":1,"price":600,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":true,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6899995,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibroknife.webp","effects":[]}
{"_id":"6VZqOHM0oqK6GiQ9","name":"Needler","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Rapid 10, Reload 20</p><p>The needler includes a specialized compartment for poison. One dose of poison, when installed in this compartment, retains its potency for 1 hour before drying. One dose of poison is effective for the next 10 shots fired by the weapon.</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":3,"price":275,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":40,"long":160,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":true,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":3900001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Needler.webp","effects":[]}
{"_id":"6nqChLn3T4yM9eyV","name":"Vibroglaive","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"","quantity":1,"weight":13,"price":1250,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d10+mod+(ceil(abilities.str.mod/2))","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7086720,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"6nqChLn3T4yM9eyV","name":"Vibroglaive","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"","quantity":1,"weight":13,"price":1250,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d10+mod+(ceil(abilities.str.mod/2))","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7086720,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibroglaive.webp","effects":[]}
{"_id":"7BNvGSn4OCqYOXRW","name":"Doubleshoto","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Double (1d6 Energy)</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":4,"price":1250,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":true,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":1500001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Doubleshoto.webp","effects":[]}
{"_id":"7TXR7ex23HIFCNOm","name":"Vibrobuster","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":15,"price":7777,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d12+@mod+(ceil(abilities.str.mod/2))","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":true,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":true},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7199806,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"7TXR7ex23HIFCNOm","name":"Vibrobuster","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":15,"price":7777,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d12+@mod+(ceil(abilities.str.mod/2))","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":true,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":true},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7199806,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibrobuster.webp","effects":[]}
{"_id":"7Tv59onLvYZHkoBo","name":"Wristsaber","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Finesse, Fixed, Light, Luminous</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":2,"price":1000,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":true,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7081251,"flags":{},"img":"systems/sw5e/packs/Icons/Simple%20Lightweapons/Wristsaber.webp","effects":[]}
{"_id":"835xibigP1dU8CTe","name":"Doubleblade","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Double (1d6 Kinetic)</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":5,"price":625,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":true,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":1300001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Doubleblade.webp","effects":[]}
{"_id":"9luXJi8YnsiLIku5","name":"Tranquilizer Rifle","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 4</p><p>The tranquilizer rifle includes a specialized compartment for poison. One dose of poison, when installed in this compartment, retains its potency for 1 hour before drying. One dose of poison is effective for the next 4 shots fired by the weapon.</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":10,"price":200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":100,"long":400,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":5500001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Tranquilizer%20Rifle.webp","effects":[]}
{"_id":"AgOdU4CCgzkHE7k3","name":"Claymore saber","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Dexterity 13, Luminous, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":9,"price":2100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["3d4","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6875001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Claymore%20Saber.webp","effects":[]}
{"_id":"As8MEk6gS194cszO","name":"Lightsaber Pike","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Dexterity 11</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":6,"price":400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":3700001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Lightsaber%20Pike.webp","effects":[]}
{"_id":"BkJeU3bFIAausZ0R","name":"Warsword","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Dexterity 13, Two-handed, Vicious 1</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":8,"price":1400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["2d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":true,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7062501,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"BkJeU3bFIAausZ0R","name":"Warsword","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Dexterity 13, Two-handed, Vicious 1</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":8,"price":1400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["2d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":true,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7062501,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Warsword.webp","effects":[]}
{"_id":"CZSl9ojBFp2P7NTo","name":"Hidden Blade","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":1,"price":200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":true,"foc":false,"hvy":false,"hid":true,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":2300001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Hidden%20Blade.webp","effects":[]}
{"_id":"CySLyAoF97hQ5OQE","name":"Shock Whip","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":3,"price":500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4+@mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7198439,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"CySLyAoF97hQ5OQE","name":"Shock Whip","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":3,"price":500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4+@mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7198439,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Shock%20Whip.webp","effects":[]}
{"_id":"DNzVCv79gSDnvu29","name":"Nightstinger rifle","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 120/480), Silent, Reload 2, Strength 13, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":15,"price":1200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":120,"long":480,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":120},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d12 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":true,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6799220,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Nightstinger%20Rifle.webp","effects":[]}
{"_id":"ERnfcnNUZKTaEJXK","name":"Lightaxe","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Heavy, Luminous, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":10,"price":1800,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6898439,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Lightaxe.webp","effects":[]}
{"_id":"EVfeatRtUl44AxUD","name":"Energy bow","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 80/320), Mighty, Reload 12, Silent, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":3,"price":300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":80,"long":320,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":20},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":true,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":true,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6893751,"flags":{},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Energy%20Bow.webp","effects":[]}
@ -30,7 +30,7 @@
{"_id":"FqG0kEsg92JQ5qte","name":"Blaster Pistol","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 16</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":3,"price":200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":40,"long":160,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":15},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":600001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Blaster%20Pistol.webp","effects":[]}
{"_id":"GHm4Ewtx59eisABa","name":"Sith saber","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Dexterity 11, Hidden, Keen 1, Luminous, Versatile (1d10)</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":3,"price":2400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","energy"]],"versatile":"1d10 + @mod"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":true,"ken":true,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":true,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6587501,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Sith%20Saber.webp","effects":[]}
{"_id":"GajCi06DTH9AWoNB","name":"Retrosaber","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>The retrosaber is an ancient type of lightweapon that requires a power cell to function. Once four attacks have been made with a retrosaber, a character must replace the power cell using an action or bonus action (the character&rsquo;s choice). You must have one free hand to replace the power cell.</p>\n<p>Keen 1, Luminous, Special, Vicious 1</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":8,"price":800,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":60},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["2d4 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":true,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":false,"two":false,"ver":false,"vic":true,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6687501,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Retrosaber.webp","effects":[]}
{"_id":"GueNpIQQ1PQVT173","name":"Unarmed Strike","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":0,"price":0,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"natural","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":5600001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"GueNpIQQ1PQVT173","name":"Unarmed Strike","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":0,"price":0,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"natural","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":5600001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Vibroweapons/Unarmed%20Strike.png","effects":[]}
{"_id":"Gxo8kRr0dQje7a9y","name":"Heavy Repeater","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Burst 4, Rapid 2, Reload 8, Strength 15</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":16,"price":1200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":80,"long":320,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["2d4 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":true,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":true,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":2000001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Heavy%20Repeater.webp","effects":[]}
{"_id":"HFGuc5KM21MTRpbn","name":"Blaster Carbine","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 16</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":8,"price":300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":15},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":500001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Blaster%20Carbine.webp","effects":[]}
{"_id":"HOG6cMpPNlpLWWOz","name":"Chaingun","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Rapid 6, Reload 12, Strength 15</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":42,"price":1500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":true,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":true,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":1000001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Chaingun.webp","effects":[]}
@ -43,7 +43,7 @@
{"_id":"JP2mZAKluouY2JMR","name":"Disruptor pistol","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 60/240), Disintegrate 13, Reload 16</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":4,"price":4000,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":15},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","acid"]],"versatile":""},"formula":"","save":{"ability":"con","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":true,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6887501,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Disruptor%20Pistol.webp","effects":[]}
{"_id":"JYZF9unlf2YrPous","name":"Bolt-thrower","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 100/400), reload 2, silent, strength 11, two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":14,"price":500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":100,"long":400,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":120},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":true,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7300001,"flags":{},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Bolt%20Thrower.webp","effects":[]}
{"_id":"Jb5Ms4NFiQbB6JNS","name":"Heavy Pistol","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 12, Strength 11</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":4,"price":300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":40,"long":160,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":1900001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Heavy%20Pistol.webp","effects":[]}
{"_id":"JivFEWysm82fCFCO","name":"Sonic rifle","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 100/400), Reload 12, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":10,"price":800,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":100,"long":400,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":20},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","sonic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6999611,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"JivFEWysm82fCFCO","name":"Sonic Rifle","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 100/400), Reload 12, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":10,"price":800,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":100,"long":400,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":20},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","sonic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6999611,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Sonic%20Rifle.webp","effects":[]}
{"_id":"K1d8enmp2viW5zG5","name":"Wristblaster","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 12</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":1,"price":250,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":30,"long":120,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":true,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":true,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":7200001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Wrist%20Blaster.webp","effects":[]}
{"_id":"KGopmgxTmVLnRXF7","name":"Scattergun","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Burst 4, Reload 4</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":3,"price":200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":20,"long":80,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":4500001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Scattergun.webp","effects":[]}
{"_id":"KbJhaEvG7rdvtczl","name":"Ion Pistol","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 16</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":3,"price":200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":40,"long":160,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d3 + @mod","ion"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":2700001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Ion%20Pistol.webp","effects":[]}
@ -52,8 +52,8 @@
{"_id":"LQEPGNraFXSViaWF","name":"Greatsaber","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Dexterity 11</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":4,"price":1000,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["2d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":1700001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Greatsaber.webp","effects":[]}
{"_id":"LYOgciOEThVXogkW","name":"Guard shoto","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Defensive 1, Finesse, Light, Luminous</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":3,"price":1350,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6450001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Guard%20Shoto.webp","effects":[]}
{"_id":"LfBkJ40l2SEWiRvE","name":"Vibrodagger","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":1,"price":50,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":20,"long":60,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":6000001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Vibroweapons/Vibrodagger.webp","effects":[]}
{"_id":"LyUddEATg6hhVzup","name":"Sonic pistol","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 40/160), Reload 12</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":2,"price":650,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":40,"long":160,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":20},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","sonic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6698439,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"MKysOTuoqYnSc7Jj","name":"Riot Baton","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":4,"price":350,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6+@mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7193751,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"LyUddEATg6hhVzup","name":"Sonic pistol","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 40/160), Reload 12</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":2,"price":650,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":40,"long":160,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":20},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","sonic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6698439,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Sonic%20Pistol.webp","effects":[]}
{"_id":"MKysOTuoqYnSc7Jj","name":"Riot Baton","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":4,"price":350,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6+@mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7193751,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Riot%20Baton.webp","effects":[]}
{"_id":"MPdtUMvLZMeS0C0A","name":"Vibrowhip","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":3,"price":150,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":7000001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibrowhip.webp","effects":[]}
{"_id":"MQHnsYyAKXByZ0Gc","name":"IWS (Antiarmor)","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<div>\n<p>The IWS is a heavy weapon that can fire in three different modes. On your turn, you can use your object interaction to switch between modes, detailed below.</p>\n<p>Antiarmor.&nbsp;While in this mode, rather than traditional power cells, the IWS fires grenades. When firing a grenade at long range, creatures within the radius of the grenade&rsquo;s explosion have advantage on the saving throw.</p>\n<p>Blaster.&nbsp;While in this mode, the weapon uses traditional power cells.</p>\n<p>Sniper.&nbsp;While in this mode, the weapon uses traditional power cells.</p>\n</div>\n<div>Antiarmor:&nbsp;Special, Ammunition (range 60/240), reload 1, special</div>\n<div>Blaster:&nbsp;1d8 Energy, Ammunition (range 80/320), reload 12</div>\n<div>Sniper:&nbsp;1d12 Energy, Ammunition (range 120/480), reload 4</div>\n<div>&nbsp;</div>\n<div>Special, Strength 13, Two-handed</div>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":12,"price":7200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":"space"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":1},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":true,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6650001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/IWS.webp","effects":[]}
{"_id":"MYRL4RqwpkvpGEF7","name":"ARC caster","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Burst 4, Rapid 2, Reload 4, Special, Strength 11, Two-handed</p>\n<p>When you score a critical hit with this weapon, a creature becomes shocked until the end of its next turn.</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":10,"price":2400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":30,"long":120,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":60},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","lightning"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":true,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":true,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":100001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/ARC%20Caster.webp","effects":[{"_id":"xGXO5cLr25ibPpu5","flags":{"dae":{"stackable":false,"specialDuration":[],"macroRepeat":"none","transfer":false}},"changes":[{"key":"","value":"0","mode":2,"priority":0}],"disabled":false,"duration":{"startTime":null,"seconds":null,"rounds":null,"turns":null,"startRound":null,"startTurn":null},"icon":"systems/sw5e/packs/Icons/Martial%20Blasters/ARC%20Caster.webp","label":"Brutal","tint":"","transfer":false}]}
@ -62,88 +62,88 @@
{"_id":"NpBjZzBSs1Ob34wo","name":"Chakram","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":3,"price":250,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":30,"long":90,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":true,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":1100001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Chakram.webp","effects":[]}
{"_id":"NwH4qn7dnL70hCDK","name":"Buster Saber","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"","quantity":1,"weight":0,"price":0,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d12 + @mod + (ceil(@abilities.str.mod/2))","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":true,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":true,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7600001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Buster%20Saber.webp","effects":[]}
{"_id":"Nwyshcc6h8hrwD0b","name":"Hunting Rifle","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 2, Strength 13</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":12,"price":600,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":150,"long":600,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d12 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":2500001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Hunting%20Rifle.webp","effects":[]}
{"_id":"OpfE2GuNbGjrKaMn","name":"Crossguard saber","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Defensive 1, Dexterity 13, Heavy, Luminous, Versatile (1d10)</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":3,"price":950,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","energy"]],"versatile":"1d10 + @mod"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":true,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6987501,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"OpfE2GuNbGjrKaMn","name":"Crossguard saber","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Defensive 1, Dexterity 13, Heavy, Luminous, Versatile (1d10)</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":3,"price":950,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","energy"]],"versatile":"1d10 + @mod"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":true,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6987501,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Crossguard%20Saber.webp","effects":[]}
{"_id":"OvrgbStdTiaZJOkp","name":"Vibropike","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Dexterity 11</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":6,"price":200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":6500001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibropike.webp","effects":[]}
{"_id":"P7kHmua3GwxvDubc","name":"Switch pistol","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 40/160), Light, Reload 12, Switch (1d4 fire)</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":4,"price":3100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":40,"long":160,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":20},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"1d4 + @mod","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6899904,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"P7kHmua3GwxvDubc","name":"Switch Pistol","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 40/160), Light, Reload 12, Switch (1d4 fire)</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":4,"price":3100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":40,"long":160,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":20},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"1d4 + @mod","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6899904,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Switch%20Pistol.webp","effects":[]}
{"_id":"PVE0NHcsMVC3J2nU","name":"Light Repeater","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Burst 8, Reload 16</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":12,"price":900,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":true,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":3000001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Light%20Repeater.webp","effects":[]}
{"_id":"RLMIkAhL6BzW5W0O","name":"Techaxe","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":2,"price":75,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":20,"long":60,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":5200001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Vibroweapons/Techaxe.webp","effects":[]}
{"_id":"RPWhectchRTOaP5O","name":"Hooked Vibroblade","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":6,"price":700,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":true,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7175001,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"RPWhectchRTOaP5O","name":"Hooked Vibroblade","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":6,"price":700,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":true,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7175001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Hooked%20Vibroblade.webp","effects":[]}
{"_id":"Rcb4rtOCKFfbykMQ","name":"Cross-saber","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":13,"price":5500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["2d4 + @mod + (ceil(@abilities.str.mod/2))","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":true,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7078126,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Cross-saber.webp","effects":[]}
{"_id":"SBFDSFPd249rnk4s","name":"Techblade","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":3,"price":250,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":5300001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Techblade.webp","effects":[]}
{"_id":"SHP3va9YHWE2LRcD","name":"Heavy Slugpistol","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Rapid 2, Reload 8, Strength 13</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":5,"price":750,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":40,"long":160,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":true,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":2200001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Heavy%20Slugpistol.webp","effects":[]}
{"_id":"SuHWBtXDAMPQFP39","name":"Electroprod","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Disruptive, Shocking 13</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":2,"price":500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","lightning"]],"versatile":""},"formula":"1d4","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":true,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6050001,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"SuHWBtXDAMPQFP39","name":"Electroprod","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Disruptive, Shocking 13</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":2,"price":500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","lightning"]],"versatile":""},"formula":"1d4","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":true,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6050001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Electroprod.webp","effects":[]}
{"_id":"SxhcmZJeFmzuqNLa","name":"Saberaxe","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Brutal 1</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":5,"price":1400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6693751,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Saberaxe.webp","effects":[]}
{"_id":"U6mqCK7zhOCdayoV","name":"Torpedo Launcher","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Rather than traditional power cells, the torpedo launcher fires specialized projectiles in the form of torpedoes. Torpedo launchers have advantage on attack rolls against Gargantuan creatures and disadvantage on attack rolls again Large and smaller creatures. Unlike other weapons, the torpedo launcher can only be loaded using an action, and you don&rsquo;t add your Dexterity modifier to damage rolls you make with it.</p>\n<p>Before firing the torpedo launcher, you must first use your action to deploy it. While deployed, your speed is reduced by half. You can collapse the torpedo launcher as a bonus action.</p>","chat":"","unidentified":""},"source":"","quantity":1,"weight":25,"price":10000,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":1200,"long":3600,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7199220,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"U6mqCK7zhOCdayoV","name":"Torpedo Launcher","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Rather than traditional power cells, the torpedo launcher fires specialized projectiles in the form of torpedoes. Torpedo launchers have advantage on attack rolls against Gargantuan creatures and disadvantage on attack rolls again Large and smaller creatures. Unlike other weapons, the torpedo launcher can only be loaded using an action, and you don&rsquo;t add your Dexterity modifier to damage rolls you make with it.</p>\n<p>Before firing the torpedo launcher, you must first use your action to deploy it. While deployed, your speed is reduced by half. You can collapse the torpedo launcher as a bonus action.</p>","chat":"","unidentified":""},"source":"","quantity":1,"weight":25,"price":10000,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":""},"range":{"value":1200,"long":3600,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7199220,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Torpedo%20Launcher.webp","effects":[]}
{"_id":"UAdGYMpSYZO9PgDN","name":"Doublesaber","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Double (1d8 Energy)</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":4,"price":1400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":true,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":1400001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Doublesaber.webp","effects":[]}
{"_id":"UB1iH8foflZXxMSM","name":"Net","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>A Large or smaller creature hit by a net is restrained until it is freed. A net has no effect on formless or Huge or larger creatures. A creature can use its action to make a DC 13 Strength check, freeing itself or another creature within its reach on a success. The net has an AC of 10, 5 hit points, and immunity to all damage not dealt by melee weapons. Destroying the net frees the creature without harming it and immediately ends the net's effects. While a creature is restrained by a net, you can make no further attacks with it.</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":3,"price":100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":15,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"save","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"str","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":4000001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Net.webp","effects":[]}
{"_id":"UtC6M3dEyUUh8IHj","name":"Railgun","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 150/600), Piercing 1, Reload 1, Strength 15, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":24,"price":6300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":150,"long":600,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":240},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["2d6","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":true,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6550001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Rail%20Gun.webp","effects":[]}
{"_id":"UxEuTaODfHttK1Bn","name":"Vibrosword","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Dexterity 11</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":6,"price":500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["2d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":6900001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibrosword.webp","effects":[]}
{"_id":"VSPlcHGwB9dXwwKo","name":"Vibrotonfa","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Defensive 1, Finesse, Light</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":2,"price":1000,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mad","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6999953,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"Vea8C1Pacl9ZEPhI","name":"Vibrobattleaxe","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":15,"price":1200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d12+@mod+(ceil(@abilities.str.mod/2))","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7199611,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"VSPlcHGwB9dXwwKo","name":"Vibrotonfa","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Defensive 1, Finesse, Light</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":2,"price":1000,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mad","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6999953,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibrotonfa.webp","effects":[]}
{"_id":"Vea8C1Pacl9ZEPhI","name":"Vibrobattleaxe","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":15,"price":1200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d12+@mod+(ceil(@abilities.str.mod/2))","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7199611,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibrobattleaxe.webp","effects":[]}
{"_id":"Vx3poKOlfgF1QAl4","name":"Lightsaber","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":3,"price":200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":"1d8 + @mod"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":true,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":true,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":3600001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Lightweapons/Lightsaber.webp","effects":[]}
{"_id":"WykXGVs1mPUlapA8","name":"Light Ring","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":3,"price":500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":30,"long":90,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":true,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":true,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":3100001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Light%20Ring.webp","effects":[]}
{"_id":"XEEWBisdZKuTWrwS","name":"Heavy Bowcaster","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Burst 4, Reload 8, Strength 15</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":26,"price":1100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d12 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":1800001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Heavy%20Bowcaster.webp","effects":[]}
{"_id":"XF7LLzqx4ayiY8Gf","name":"Shoulder Cannon","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Mounted by the shoulder slot, a shoulder cannon does not require a free hand to use. Additionally, you have advantage on Strength ability checks and saving throws to avoid being disarmed of this weapon.</p>\n<p>Ammunition (range 60/240), Autotarget (15, +2), Burst 4, Reload 4, Special</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":9,"price":3200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":60},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + 2","energy"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":12,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6696876,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[{"_id":"KCrgDQZ4Fs0XYwyf","flags":{"dae":{"stackable":false,"specialDuration":[],"macroRepeat":"none","transfer":false}},"changes":[{"key":"data.bonuses.rwak.attack","value":"0","mode":2,"priority":20}],"disabled":false,"duration":{"startTime":null,"seconds":null,"rounds":null,"turns":null,"startRound":null,"startTurn":null},"icon":"icons/svg/mystery-man.svg","label":"Autotarget","tint":"","transfer":false}]}
{"_id":"Yi36jcAGqVrealrD","name":"Mancatcher","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>When you would make a Strength (Athletics) check to attempt to grapple a creature while wielding a weapon with the grappling property, you can instead make a melee weapon attack with it. If the attack hits, the creature becomes grappled by you, and it takes damage equal to your Strength modifier of the same type as the weapon&rsquo;s damage.</p>\n<p>Reach, Special, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":12,"price":300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6798439,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"Yr8n7ZT1OmoxDmhl","name":"Vibroshield","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Defensive 1, Fixed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":7,"price":900,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":true,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6999904,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"XF7LLzqx4ayiY8Gf","name":"Shoulder Cannon","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Mounted by the shoulder slot, a shoulder cannon does not require a free hand to use. Additionally, you have advantage on Strength ability checks and saving throws to avoid being disarmed of this weapon.</p>\n<p>Ammunition (range 60/240), Autotarget (15, +2), Burst 4, Reload 4, Special</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":9,"price":3200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":60},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + 2","energy"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":12,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6696876,"flags":{},"img":"systems/sw5e/packs/Icons/","effects":[{"_id":"KCrgDQZ4Fs0XYwyf","flags":{"dae":{"stackable":false,"specialDuration":[],"macroRepeat":"none","transfer":false}},"changes":[{"key":"data.bonuses.rwak.attack","value":"0","mode":2,"priority":20}],"disabled":false,"duration":{"startTime":null,"seconds":null,"rounds":null,"turns":null,"startRound":null,"startTurn":null},"icon":"systems/sw5e/packs/Icons/Martial%20Blasters/Shoulder%20Cannon.webp","label":"Autotarget","tint":"","transfer":false}]}
{"_id":"Yi36jcAGqVrealrD","name":"Mancatcher","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>When you would make a Strength (Athletics) check to attempt to grapple a creature while wielding a weapon with the grappling property, you can instead make a melee weapon attack with it. If the attack hits, the creature becomes grappled by you, and it takes damage equal to your Strength modifier of the same type as the weapon&rsquo;s damage.</p>\n<p>Reach, Special, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":12,"price":300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6798439,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Mancatcher.webp","effects":[]}
{"_id":"Yr8n7ZT1OmoxDmhl","name":"Vibroshield","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Defensive 1, Fixed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":7,"price":900,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":true,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6999904,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibroshield.webp","effects":[]}
{"_id":"ZGERUZSkFxFxSid4","name":"Cycler Rifle","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Rapid 2, Reload 8</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":10,"price":450,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":100,"long":400,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":true,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":1200001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Cycler%20Rifle.webp","effects":[]}
{"_id":"ZHImgyS79q62mnk3","name":"Wrist Launcher","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 1</p><p>Rather than traditional power cells, the wrist launcher fires specialized projectiles in the form of darts, small missiles, or specialized canisters. </p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":1,"price":450,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":30,"long":120,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":true,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":7100001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Wrist%20Launcher.webp","effects":[]}
{"_id":"Zjy957ONj3PyVQm4","name":"Wristblade","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Fixed, Light</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":1,"price":450,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":true,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7087501,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"Zjy957ONj3PyVQm4","name":"Wristblade","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Fixed, Light</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":1,"price":450,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":true,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7087501,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Wristblade.webp","effects":[]}
{"_id":"a9lLCncsribwUR2g","name":"IWS (Sniper)","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<div>\n<p>The IWS is a heavy weapon that can fire in three different modes. On your turn, you can use your object interaction to switch between modes, detailed below.</p>\n<p>Antiarmor.&nbsp;While in this mode, rather than traditional power cells, the IWS fires grenades. When firing a grenade at long range, creatures within the radius of the grenade&rsquo;s explosion have advantage on the saving throw.</p>\n<p>Blaster.&nbsp;While in this mode, the weapon uses traditional power cells.</p>\n<p>Sniper.&nbsp;While in this mode, the weapon uses traditional power cells.</p>\n</div>\n<div>Antiarmor:&nbsp;Special, Ammunition (range 60/240), reload 1, special</div>\n<div>Blaster:&nbsp;1d8 Energy, Ammunition (range 80/320), reload 12</div>\n<div>Sniper:&nbsp;1d12 Energy, Ammunition (range 120/480), reload 4</div>\n<div>&nbsp;</div>\n<div>Special, Strength 13, Two-handed</div>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":12,"price":7200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":"space"},"range":{"value":120,"long":480,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":60},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d12 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6650001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/IWS.webp","effects":[]}
{"_id":"aVdtguY4dQuv2xhf","name":"Lightglaive","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Dexterity 13, Luminous, Reach, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":10,"price":1900,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d12 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6899611,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Lightglaive.webp","effects":[]}
{"_id":"ahWWUPiXhooCgdKf","name":"Saberwhip","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":2,"price":300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":true,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":4400001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Saberwhip.webp","effects":[]}
{"_id":"ankoAzbua0rlIBnh","name":"Subrepeater","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Rapid 8, Reload 16</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":4,"price":1200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":30,"long":120,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":true,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":true,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":5100001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Subrepeater.webp","effects":[]}
{"_id":"b0WBwJRTPPJpnHii","name":"Vibroblade","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":2,"price":150,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":"1d10 + @mod"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":true,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":5900001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibroblade.webp","effects":[]}
{"_id":"cnqFdX8ihPdIgSRt","name":"Electrobaton","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Finesse, Light, Shocking 13</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":3,"price":650,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":3350001,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"cnqFdX8ihPdIgSRt","name":"Electrobaton","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Finesse, Light, Shocking 13</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":3,"price":650,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":3350001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Electrobaton.webp","effects":[]}
{"_id":"cpuAeXISuY1IRiw9","name":"Lightfist","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Disruptive, Disguised, Fixed, Light, Luminous</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":2,"price":1200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":true,"dis":false,"dpt":true,"dou":false,"fin":false,"fix":true,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6899220,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Lightfist.webp","effects":[]}
{"_id":"ctSLHcbXiV8P0PeG","name":"Riot Shocker","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":4,"price":750,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4+@mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7196876,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"e4WTWeABUAmn6GZc","name":"Vibrohammer","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Heavy, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":16,"price":1400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6899989,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"ctSLHcbXiV8P0PeG","name":"Riot Shocker","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":4,"price":750,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4+@mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7196876,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Riot%20Shocker.webp","effects":[]}
{"_id":"e4WTWeABUAmn6GZc","name":"Vibrohammer","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Heavy, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":16,"price":1400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6899989,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibrohammer.webp","effects":[]}
{"_id":"eOf2AzadJEdKZ8NK","name":"Vibrolance","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>You have disadvantage when you use a vibrolance to attack a target within 5 feet of you. Also, a lance requires two hands to wield when you aren't mounted.</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":6,"price":100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d12 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":6300001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibrolance.webp","effects":[]}
{"_id":"eT1EM9VkO6zJ4QYZ","name":"Switch sniper","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 120/480), Reload 2, Strength 13, Switch (1d10 cold), Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":16,"price":8250,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":120,"long":480,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":120},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d12 + @mod","energy"]],"versatile":""},"formula":"1d10 + @mod","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6699220,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"eT1EM9VkO6zJ4QYZ","name":"Switch Sniper","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 120/480), Reload 2, Strength 13, Switch (1d10 cold), Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":16,"price":8250,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":120,"long":480,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":120},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d12 + @mod","energy"]],"versatile":""},"formula":"1d10 + @mod","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6699220,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Switch%20Sniper.webp","effects":[]}
{"_id":"fA347pHZ31UJT39y","name":"Vibrocutter","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Dexterity 11, Heavy, Vicious 1</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":5,"price":300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mos","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":true,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6799977,"flags":{},"img":"systems/sw5e/packs/Icons/Simple%20Vibroweapons/Vibrocutter.webp","effects":[]}
{"_id":"fHvjrYSxapHKDmXt","name":"Vibroknuckler","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":2,"price":60,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":true,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":6200001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Vibroweapons/Vibroknuckler.webp","effects":[]}
{"_id":"fOS7j0XoMXAkb2Iy","name":"Rocket launcher","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Rather than traditional power cells, the rocket launcher fires specialized projectiles in the form of rockets. When firing a rocket at long range, or if you don&rsquo;t meet the rocket launcher&rsquo;s strength requirement, creatures within the radius of the rocket&rsquo;s explosion have advantage on the saving throw.</p>\n<p>Ammunition (range 100/400), Reload 1, Special, Strength 13, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":20,"price":2400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":100,"long":400,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":true,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6799611,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Rocket%20Launcher.webp","effects":[]}
{"_id":"fV8miB2X8CfTaFkM","name":"Vapor projector","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>The vapor projector does not make attack rolls. Rather than traditional power cells, the vapor projector uses specialized projector tanks, which, when fired, spray an area with the contents of the tank. Projector tanks require your target to make a saving throw to resist the tank&rsquo;s effects. It can have different ammunition types loaded simultaneously, and you can choose which ammunition you&rsquo;re using as you fire it (no action required). If you don&rsquo;t meet the vapor projector&rsquo;s strength requirement, creatures have advantage on their saving throws. If you lack proficiency in the vapor projector, you must roll the damage dice twice and take the lesser total.</p>\n<p>Ammunition (range special), Reload 5, Special, Strength 11, Two-handed</p>","chat":"","unidentified":""},"source":"","quantity":1,"weight":0,"price":0,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"space"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":1},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":true,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6899953,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"fV8miB2X8CfTaFkM","name":"Vapor Projector","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>The vapor projector does not make attack rolls. Rather than traditional power cells, the vapor projector uses specialized projector tanks, which, when fired, spray an area with the contents of the tank. Projector tanks require your target to make a saving throw to resist the tank&rsquo;s effects. It can have different ammunition types loaded simultaneously, and you can choose which ammunition you&rsquo;re using as you fire it (no action required). If you don&rsquo;t meet the vapor projector&rsquo;s strength requirement, creatures have advantage on their saving throws. If you lack proficiency in the vapor projector, you must roll the damage dice twice and take the lesser total.</p>\n<p>Ammunition (range special), Reload 5, Special, Strength 11, Two-handed</p>","chat":"","unidentified":""},"source":"","quantity":1,"weight":0,"price":0,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"space"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":1},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":true,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6899953,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Vapor%20Projector.webp","effects":[]}
{"_id":"fzFc5SKhOn55embe","name":"Saber Gauntlet","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":2,"price":1300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8+@mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":true,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7084376,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Saber%20Guantlet.webp","effects":[]}
{"_id":"gise2mIw1wbTUtlY","name":"Blaster Rifle","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 12</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":11,"price":400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":100,"long":400,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":20},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":700001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Blaster%20Rifle.webp","effects":[]}
{"_id":"gxIw7zHI4R5eef9Z","name":"Revolver","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Rapid 6, Reload 6, Strength 11</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":4,"price":750,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":30,"long":120,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":true,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":4200001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Revolver.webp","effects":[]}
{"_id":"ioLa4LwWiQTOmgq2","name":"Bolas","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>A Large or smaller creature hit by a bolas is restrained until it is freed. A bolas has no effect on formless or Huge or larger creatures. A creature can use its action to make a DC 13 Dexterity check, freeing itself or another creature within its reach on a success. The bolas has an AC of 10, 5 hit points, and immunity to all damage not dealt by melee weapons. Destroying the bolas frees the creature without harming it and immediately ends the bolas&rsquo;s effects. While a creature is restrained by a bolas, you can make no further attacks with it.</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":2,"price":70,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":20,"long":60,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":true,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6850001,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"k0jg2u21xDQ0zDzf","name":"Vibroclaymore","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":14,"price":1050,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["3d4+@mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7085939,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"ioLa4LwWiQTOmgq2","name":"Bolas","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>A Large or smaller creature hit by a bolas is restrained until it is freed. A bolas has no effect on formless or Huge or larger creatures. A creature can use its action to make a DC 13 Dexterity check, freeing itself or another creature within its reach on a success. The bolas has an AC of 10, 5 hit points, and immunity to all damage not dealt by melee weapons. Destroying the bolas frees the creature without harming it and immediately ends the bolas&rsquo;s effects. While a creature is restrained by a bolas, you can make no further attacks with it.</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":2,"price":70,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":20,"long":60,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":true,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6850001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Bolas.webp","effects":[]}
{"_id":"k0jg2u21xDQ0zDzf","name":"Vibroclaymore","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":14,"price":1050,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["3d4+@mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7085939,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibroclaymore.webp","effects":[]}
{"_id":"k5ippYtz0p4PjbOW","name":"Saberspear","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":2,"price":450,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["2d4 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":4300001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Saberspear.webp","effects":[]}
{"_id":"kAnqkLwQT2s8V3tC","name":"Light Slugpistol","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 8</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":2,"price":250,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":40,"long":160,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":true,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":3200001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Light%20Slugpistol.webp","effects":[]}
{"_id":"kXba6Y0xOqeuT59S","name":"Shatter rifle","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 120/480), Silent, Reload 2, Strength 13, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":15,"price":1200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":120,"long":480,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":120},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":true,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6575001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Shatter%20Rifle.webp","effects":[]}
{"_id":"kiF9Ubs4yyOlqG7d","name":"Dual-phase saber","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Dexterity 11, Keen 1, Luminous, Versatile (1d10)</p>","chat":"","unidentified":""},"source":"","quantity":1,"weight":4,"price":1400,"attunement":0,"equipped":false,"rarity":"","identified":false,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","energy"]],"versatile":"1d10 + @mod"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":true,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":true,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7500001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Dual-Phase%20Saber.webp","effects":[]}
{"_id":"lCCxKJ6dgNcKerQP","name":"Nervebaton","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Disruptive, Neuralizing 13</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":1,"price":1500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"wis","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":true,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6998439,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"mVeMPN2VDbmxW2LH","name":"Echostaff","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Double (1d6 kinetic), Finesse, Sonorous 13</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":1,"price":1200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"con","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":true,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6775001,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"lCCxKJ6dgNcKerQP","name":"Nervebaton","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Disruptive, Neuralizing 13</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":1,"price":1500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"wis","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":true,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6998439,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Nervebaton.webp","effects":[]}
{"_id":"mVeMPN2VDbmxW2LH","name":"Echostaff","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Double (1d6 kinetic), Finesse, Sonorous 13</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":1,"price":1200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"con","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":true,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6775001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Echostaff.webp","effects":[]}
{"_id":"mn4HW9ZpkObfamy4","name":"Lightclub","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":5,"price":150,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":3300001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Lightweapons/Lightclub.webp","effects":[]}
{"_id":"nbBcy38sK2sejDo2","name":"Grenade launcher","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Rather than traditional power cells, the grenade launcher fires grenades. When firing a grenade at long range, or if you don&rsquo;t meet the grenade launcher&rsquo;s strength requirement, creatures within the radius of the grenade&rsquo;s explosion have advantage on the saving throw. If you lack proficiency in the grenade launcher, you must roll the damage dice twice and take the lesser total.</p>\n<p>Ammunition (range 80/320), Reload 1, Strength 11, Special, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":10,"price":800,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"space"},"range":{"value":80,"long":320,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":1},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":true,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6896876,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Grenade%20Launcher.webp","effects":[]}
{"_id":"nkHuIJ1RC1eLHPQ5","name":"Martial Lightsaber","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":2,"price":300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","energy"]],"versatile":"1d10 + @mod"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":true,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":true,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":3800001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Martial%20Lightsaber.webp","effects":[]}
{"_id":"ojGildpRHvmzXCXV","name":"Lightbow","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 60/240), Mighty, Piercing 1, Reload 4, Strength 11, Two-handed</p>","chat":"","unidentified":""},"source":"","quantity":1,"weight":16,"price":400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":60},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["2d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":true,"pic":true,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6996876,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Lightbow.webp","effects":[]}
{"_id":"ol1wR7Y9gTL4vWLN","name":"Bo-rifle (Staff)","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<div>\n<p>The bo-rifle is a lasat weapon most commonly carried by the Honor Guard of Lasan, which has the unique property of functioning as both a rifle and a staff. On your turn, you can use your object interaction to switch between modes, detailed below.</p>\n<p>Rifle.&nbsp;While in this mode, the weapon uses traditional power cells.</p>\n<p>Staff.&nbsp;While in this mode, the weapon gains the shocking 13 property.</p>\n</div>\n<div>Rifle:&nbsp;1d8 Energy, Ammunition (range 100/400), reload 6</div>\n<div>Staff:&nbsp;1d8 Kinetic, Double (1d8 kinetic), shocking 13</div>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":7,"price":2300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":true,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":true,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6975001,"flags":{},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Bo%20Rifle.webp","effects":[]}
{"_id":"pjMVd0d3xi1E2oe9","name":"Switch rifle","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 60/240), Reload 8, Switch (1d6 lightning), Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":12,"price":5500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":30},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","energy"]],"versatile":""},"formula":"1d6 + @mod","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6799953,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"pjMVd0d3xi1E2oe9","name":"Switch Rifle","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 60/240), Reload 8, Switch (1d6 lightning), Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":12,"price":5500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":30},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","energy"]],"versatile":""},"formula":"1d6 + @mod","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6799953,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Switch%20Rifle.webp","effects":[]}
{"_id":"qGACGd1CGJjFmyvC","name":"Vibrostaff","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":4,"price":100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":"2d4 + @mod"},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":true,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":6800001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Vibroweapons/Vibrostaff.webp","effects":[]}
{"_id":"qVeMdnOgsk1EkUGN","name":"Rotary cannon","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Rather than traditional power cells, the rotary cannon uses specialized power generator that allow it to fire continuously for 10 minutes. Replacing a power generator takes an action.</p>\n<p>The rotary cannon requires the use of a tripod unless you meet its strength requirement, which is included in the price. Over the course of 1 minute, you can deploy or collapse the rotary cannon on the tripod. While deployed, your speed is reduced to 0.</p>\n<p>&nbsp;</p>\n<p>Ammunition (range 100/400), Auto, Burst, Rapid, Special, Strength 19, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":76,"price":9800,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":10,"width":null,"units":"ft","type":"cube"},"range":{"value":100,"long":400,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"save","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["2d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"dex"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":true,"aut":true,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":true,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":true,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6799806,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Rotary%20Cannon.webp","effects":[]}
{"_id":"qcfcwHseK75zUy9U","name":"Assault Cannon","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Burst 4, Reload 8, Strength 11</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":24,"price":500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":80,"long":320,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":30},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":200001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Assault%20Cannon.webp","effects":[]}
{"_id":"rh4a2Bq5FJJ0c6bk","name":"Electrovoulge","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Reach, Shocking 13, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":15,"price":1300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6787501,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"rh4a2Bq5FJJ0c6bk","name":"Electrovoulge","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Reach, Shocking 13, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":15,"price":1300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6787501,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Electrovoulge.webp","effects":[]}
{"_id":"s02ZWo9cCBqTOx2A","name":"Vibroclaw","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Finesse, Fixed, Light</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":2,"price":600,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":true,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6899977,"flags":{},"img":"systems/sw5e/packs/Icons/Simple%20Vibroweapons/Vibroclaw.webp","effects":[]}
{"_id":"sGXUQb1kU45kKt1b","name":"Sniper Rifle","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 2, Strength 13</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":12,"price":750,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":150,"long":600,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d12 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":5000001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Sniper%20Rifle.webp","effects":[]}
{"_id":"sZo7FkpCKkRv6Dnw","name":"Incinerator pistol","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 60/240), Disintegrate 13, Reload 12, Strength 11</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":5,"price":2500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":20},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","fire"]],"versatile":""},"formula":"","save":{"ability":"con","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":true,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6675001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Incinerator%20Pistol.webp","effects":[]}
{"_id":"t8KzQluS5V5RSnI4","name":"Bo-rifle (Rifle)","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<div>\n<p>The bo-rifle is a lasat weapon most commonly carried by the Honor Guard of Lasan, which has the unique property of functioning as both a rifle and a staff. On your turn, you can use your object interaction to switch between modes, detailed below.</p>\n<p>Rifle.&nbsp;While in this mode, the weapon uses traditional power cells.</p>\n<p>Staff.&nbsp;While in this mode, the weapon gains the shocking 13 property.</p>\n</div>\n<div>Rifle:&nbsp;1d8 Energy, Ammunition (range 100/400), reload 6</div>\n<div>Staff:&nbsp;1d8 Kinetic, Double (1d8 kinetic), shocking 13</div>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":7,"price":2300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":100,"long":400,"units":""},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":40},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":true,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6975001,"flags":{},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Bo%20Rifle.webp","effects":[]}
{"_id":"tLHpQLnx7iYcLPtw","name":"War hat","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Defensive 1, Disguised, Returning, Thrown (range 30/90)</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":3,"price":1100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":30,"long":90,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":false,"dir":false,"drm":false,"dgd":true,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":true,"shk":false,"sil":false,"spc":false,"str":false,"thr":true,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7075001,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"tLHpQLnx7iYcLPtw","name":"War hat","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Defensive 1, Disguised, Returning, Thrown (range 30/90)</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":3,"price":1100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":30,"long":90,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":true,"dex":false,"dir":false,"drm":false,"dgd":true,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":true,"shk":false,"sil":false,"spc":false,"str":false,"thr":true,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7075001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/War%20Hat.webp","effects":[]}
{"_id":"tXO7WB3V2wjjaBfE","name":"Shotgun","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Burst 2, Reload 4, Strength 11</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":12,"price":350,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":30,"long":120,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["2d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":4600001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Shotgun.webp","effects":[]}
{"_id":"tlcCSePqUtbhMadM","name":"Chained lightdagger","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Disarming, Finesse, Luminous, Reach, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":6,"price":1700,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":true,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7050001,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"tlcCSePqUtbhMadM","name":"Chained Lightdagger","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Disarming, Finesse, Luminous, Reach, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":6,"price":1700,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":10,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":true,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":true,"mig":false,"pic":false,"rap":false,"rch":true,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7050001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Lightweapons/Chained%20Lightdagger.webp","effects":[]}
{"_id":"u0mVXUeoHsFZ1pcG","name":"Blaster Cannon","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Burst 2, Reload 4, Strength 15</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":36,"price":1600,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":100,"long":400,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":120},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d12 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":true,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":400001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Blaster%20Cannon.webp","effects":[]}
{"_id":"uGe5wQQJjZrQzltP","name":"Electrostaff","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Double (1d6 kinetic), Finesse, Shocking 13, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":6,"price":1100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":true,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6993751,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"uGe5wQQJjZrQzltP","name":"Electrostaff","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Double (1d6 kinetic), Finesse, Shocking 13, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":6,"price":1100,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":true,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6993751,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Electrostaff.webp","effects":[]}
{"_id":"uQ2AXesizBRcTjRl","name":"Ion Carbine","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 16</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":8,"price":300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":60,"long":240,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d3 + @mod","ion"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":2600001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Ion%20Carbine.webp","effects":[]}
{"_id":"v55dQl0raOAucwgP","name":"Vibromace","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":12,"price":80,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":6400001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Vibroweapons/Vibromace.webp","effects":[]}
{"_id":"w62Yd7ahdYyTH61q","name":"Shatter cannon","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 80/320), Burst 4, Reload 8, Silent, Strength 15, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":24,"price":1300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":80,"long":320,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":30},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d10","kinetic"]],"versatile":""},"formula":"","save":{"ability":"dex","dc":null,"scaling":"dex"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":true,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6999220,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Shatter%20Cannon.webp","effects":[]}
{"_id":"woDLArHK5OZHsTeU","name":"Disguised Blade","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":1,"price":200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":true,"dgd":true,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7150001,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"woDLArHK5OZHsTeU","name":"Disguised Blade","permission":{"default":0,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"EC","quantity":1,"weight":1,"price":200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":true,"dgd":true,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":7150001,"flags":{},"img":"systems/sw5e/packs/Icons/Disguised%20Blade,"effects":[]}
{"_id":"xfIWfVXfe5ZfD8S2","name":"IWS (Blaster)","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<div>\n<p>The IWS is a heavy weapon that can fire in three different modes. On your turn, you can use your object interaction to switch between modes, detailed below.</p>\n<p>Antiarmor.&nbsp;While in this mode, rather than traditional power cells, the IWS fires grenades. When firing a grenade at long range, creatures within the radius of the grenade&rsquo;s explosion have advantage on the saving throw.</p>\n<p>Blaster.&nbsp;While in this mode, the weapon uses traditional power cells.</p>\n<p>Sniper.&nbsp;While in this mode, the weapon uses traditional power cells.</p>\n</div>\n<div>Antiarmor:&nbsp;Special, Ammunition (range 60/240), reload 1, special</div>\n<div>Blaster:&nbsp;1d8 Energy, Ammunition (range 80/320), reload 12</div>\n<div>Sniper:&nbsp;1d12 Energy, Ammunition (range 120/480), reload 4</div>\n<div>&nbsp;</div>\n<div>Special, Strength 13, Two-handed</div>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":12,"price":7200,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":null,"width":null,"units":"","type":"space"},"range":{"value":80,"long":320,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":20},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d8 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6650001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/IWS.webp","effects":[]}
{"_id":"y6faozksI3Bhwnpq","name":"Bowcaster","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Burst 4, Reload 4, Strength 11</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":16,"price":400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":50,"long":200,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":800001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Bowcaster.webp","effects":[]}
{"_id":"yVxRMON2OWIGeU4n","name":"Disruptorshiv","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Disruptive, Finesse, Shocking 13</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":1,"price":900,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":true,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6750001,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"yyBBJgGqeZ3Qx0OP","name":"Electrohammer","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Heavy, Shocking 13, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":18,"price":1400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["2d4 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":4950001,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"yVxRMON2OWIGeU4n","name":"Disruptorshiv","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Disruptive, Finesse, Shocking 13</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":1,"price":900,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":true,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6750001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Disruptorshiv.webp","effects":[]}
{"_id":"yyBBJgGqeZ3Qx0OP","name":"Electrohammer","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Heavy, Shocking 13, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":18,"price":1400,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["2d4 + @mod","kinetic"]],"versatile":""},"formula":"1d4","save":{"ability":"dex","dc":13,"scaling":"flat"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":true,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":4950001,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Electrohammer.webp","effects":[]}
{"_id":"z5Ms1OrmxDwLqGw8","name":"Shotosaber","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":2,"price":500,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d6 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleLW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":true,"fix":false,"foc":false,"hvy":false,"hid":true,"ken":false,"lgt":true,"lum":true,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":4700001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Lightweapons/Shotosaber.webp","effects":[]}
{"_id":"z70LYISIcmv1gpJi","name":"Switch cannon","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 80/320), Burst 4, Reload 8, Strength 11, Switch (2d4 acid/cold/fire/lightning), Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":26,"price":9600,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":80,"long":320,"units":""},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":30},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","energy"]],"versatile":""},"formula":"2d4 + @mod","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6999806,"flags":{},"img":"icons/svg/mystery-man.svg","effects":[]}
{"_id":"z70LYISIcmv1gpJi","name":"Switch Cannon","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>Ammunition (range 80/320), Burst 4, Reload 8, Strength 11, Switch (2d4 acid/cold/fire/lightning), Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":26,"price":9600,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":80,"long":320,"units":""},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":30},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","energy"]],"versatile":""},"formula":"2d4 + @mod","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":true,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6999806,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Switch%20Cannon.webp","effects":[]}
{"_id":"z7LJqf8bjWnzqEw8","name":"Flechette cannon","permission":{"default":0,"MmfWtlBdw3ij5wl9":3},"type":"weapon","data":{"description":{"value":"<p>The flechette cannon does not make attack rolls. Rather than traditional power cells, the flechette cannon uses specialized cannon tanks, which, when fired, spray an area with the contents of the tank. Projector tanks require your target to make a saving throw to resist the tank&rsquo;s effects. It can have different ammunition types loaded simultaneously, and you can choose which ammunition you&rsquo;re using as you fire it (no action required). If you don&rsquo;t meet the flechette cannon&rsquo;s strength requirement, creatures have advantage on their saving throws. If you lack proficiency in the flechette cannon, you must roll the damage dice twice and take the lesser total.</p>\n<p>Ammunition (range special), Reload 5, Special, Strength 11, Two-handed</p>","chat":"","unidentified":""},"source":"WH","quantity":1,"weight":16,"price":1800,"attunement":0,"equipped":false,"rarity":"","identified":false,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"creature"},"range":{"value":null,"long":null,"units":""},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"charges","target":"","amount":1},"ability":null,"actionType":"","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":true,"str":true,"thr":false,"two":true,"ver":false,"vic":false,"nodam":false,"fulldam":false},"proficient":true},"folder":"7rtfHBtXhhiRSS8u","sort":6793751,"flags":{},"img":"systems/sw5e/packs/Icons/Martial%20Blasters/Flechette%20Cannon.webp","effects":[]}
{"_id":"zArvVI9Nz8jA7vYF","name":"Vibroaxe","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Dexterity 11</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":11,"price":300,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":5,"long":null,"units":"ft"},"uses":{"value":0,"max":0,"per":""},"consume":{"type":"","target":"","amount":null},"ability":"","actionType":"mwak","attackBonus":0,"chatFlavor":"","critical":null,"damage":{"parts":[["1d10 + @mod","kinetic"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"martialVW","properties":{"amm":false,"aut":false,"bur":false,"def":false,"dex":true,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":true,"hid":false,"ken":false,"lgt":false,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":false,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":true,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":5700001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Martial%20Vibroweapons/Vibroaxe.webp","effects":[]}
{"_id":"zGU5Id8EUqoIzAmc","name":"Hold-Out","permission":{"default":0,"vXYkFWX6qzvOu2jc":3,"5TZqObbCr9nKC79s":3},"type":"weapon","data":{"description":{"value":"<p>Reload 6</p>","chat":"","unidentified":""},"source":"PHB","quantity":1,"weight":1,"price":250,"attunement":0,"equipped":false,"rarity":"","identified":true,"activation":{"type":"action","cost":1,"condition":""},"duration":{"value":null,"units":""},"target":{"value":1,"width":null,"units":"","type":"enemy"},"range":{"value":30,"long":120,"units":"ft"},"uses":{"value":0,"max":"0","per":""},"consume":{"type":"ammo","target":"","amount":1},"ability":"","actionType":"rwak","attackBonus":"0","chatFlavor":"","critical":null,"damage":{"parts":[["1d4 + @mod","energy"]],"versatile":""},"formula":"","save":{"ability":"","dc":null,"scaling":"power"},"armor":{"value":10},"hp":{"value":0,"max":0,"dt":null,"conditions":""},"weaponType":"simpleB","properties":{"amm":true,"aut":false,"bur":false,"def":false,"dex":false,"dir":false,"drm":false,"dgd":false,"dis":false,"dpt":false,"dou":false,"fin":false,"fix":false,"foc":false,"hvy":false,"hid":true,"ken":false,"lgt":true,"lum":false,"mig":false,"pic":false,"rap":false,"rch":false,"rel":true,"ret":false,"shk":false,"sil":false,"spc":false,"str":false,"thr":false,"two":false,"ver":false,"vic":false,"mgc":false,"nodam":false,"faulldam":false,"fulldam":false},"proficient":false},"folder":"7rtfHBtXhhiRSS8u","sort":2400001,"flags":{"dynamiceffects":{"equipActive":false,"alwaysActive":false}},"img":"systems/sw5e/packs/Icons/Simple%20Blasters/Holdout%20Blaster.webp","effects":[]}

View file

@ -102,7 +102,7 @@ body {
font-size: 13px;
color: #191813;
}
.sw5e input[type="text"]
.sw5e input[type="text"],
.sw5e select {
height: calc(100% - 2px);
border: 1px solid #7a7971;

View file

@ -791,6 +791,9 @@ body.dark-theme .sw5e.sheet.actor .swalt-sheet .tab.notes section > input {
color: #E81111;
border-bottom: 2px solid #0d99cc;
}
body.dark-theme .sw5e.sheet.actor.npc .swalt-sheet header div.creature-type:hover {
border-color: #E81111;
}
body.dark-theme .sw5e.sheet.actor.npc .swalt-sheet header .experience {
color: #4f4f4f;
}

View file

@ -206,7 +206,8 @@ input[type="password"],
input[type="date"],
input[type="time"],
select,
textarea {
textarea,
.roundTransition {
border-radius: 4px;
transition: all 0.3s;
}
@ -216,7 +217,8 @@ input[type="password"]:hover,
input[type="date"]:hover,
input[type="time"]:hover,
select:hover,
textarea:hover {
textarea:hover,
.roundTransition:hover {
box-shadow: none;
}
input[type="text"]:focus,
@ -225,7 +227,8 @@ input[type="password"]:focus,
input[type="date"]:focus,
input[type="time"]:focus,
select:focus,
textarea:focus {
textarea:focus,
.roundTransition:focus {
box-shadow: none;
}
input[type=range] {
@ -552,7 +555,7 @@ input[type="reset"]:disabled {
padding-bottom: 4px;
}
.sidebar-tab .directory-list .folder > .folder-header {
line-height: default;
line-height: initial;
padding: 0 0 0 8px;
position: relative;
border: none;
@ -858,6 +861,7 @@ input[type="reset"]:disabled {
font-weight: 400;
letter-spacing: 0.5px;
line-height: 24px;
width: 100%;
}
.sw5e.sheet.actor .swalt-sheet header .summary .proficiency {
line-height: 26px;
@ -895,7 +899,7 @@ input[type="reset"]:disabled {
.sw5e.sheet.actor .swalt-sheet header .attributes .attribute-value .value-number {
display: inline-block;
text-align: right;
padding: 0px 3px;
padding: 0 3px;
}
.sw5e.sheet.actor .swalt-sheet header .attributes .attribute-value .value-number:last-child {
text-align: left;
@ -1435,7 +1439,7 @@ input[type="reset"]:disabled {
display: block;
width: 100%;
text-align: right;
padding: 0px 3px;
padding: 0 3px;
}
.sw5e.sheet.actor .swalt-sheet .tab.attributes .traits-resources section.resources .resource-items .resource .attribute-value .value-number:last-child {
text-align: left;
@ -1588,7 +1592,7 @@ input[type="reset"]:disabled {
display: block;
width: 100%;
text-align: right;
padding: 0px 3px;
padding: 0 3px;
}
.sw5e.sheet.actor .swalt-sheet .tab.force-powerbook .resource-items .resource .attribute-value .value-number:last-child,
.sw5e.sheet.actor .swalt-sheet .tab.tech-powerbook .resource-items .resource .attribute-value .value-number:last-child {
@ -1686,13 +1690,35 @@ input[type="reset"]:disabled {
.sw5e.sheet.actor.npc .swalt-sheet header h1.character-name {
align-self: auto;
}
.sw5e.sheet.actor.npc .swalt-sheet header .npc-size {
.sw5e.sheet.actor.npc .swalt-sheet header .npc-size,
.sw5e.sheet.actor.npc .swalt-sheet header .creature-type {
font-family: 'Russo One';
font-size: 18px;
font-weight: 400;
letter-spacing: 0.5px;
line-height: 28px;
}
.sw5e.sheet.actor.npc .swalt-sheet header div.creature-type {
display: flex;
justify-content: space-between;
padding: 1px 4px;
border: 1px solid transparent;
overflow-x: auto;
}
.sw5e.sheet.actor.npc .swalt-sheet header div.creature-type span {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.sw5e.sheet.actor.npc .swalt-sheet header div.creature-type .config-button {
display: none;
font-size: 12px;
font-weight: normal;
line-height: 2em;
}
.sw5e.sheet.actor.npc .swalt-sheet header div.creature-type:hover .config-button {
display: block;
}
.sw5e.sheet.actor.npc .swalt-sheet header .attributes {
grid-template-columns: repeat(3, 1fr);
}

View file

@ -778,6 +778,9 @@ body.light-theme .sw5e.sheet.actor .swalt-sheet .tab.notes section > input {
color: #c40f0f;
border-bottom: 2px solid #0d99cc;
}
body.light-theme .sw5e.sheet.actor.npc .swalt-sheet header div.creature-type:hover {
border-color: #c40f0f;
}
body.light-theme .sw5e.sheet.actor.npc .swalt-sheet header .experience {
color: #4f4f4f;
}

163
sw5e.css
View file

@ -91,9 +91,7 @@
/* Tags */
}
.sw5e .window-content {
background: linear-gradient(90deg, #afc6d6 0%, #D6D6D6 30%, #D6D6D6 70%, #afc6d6);
font-size: 13px;
color: #191813;
}
.sw5e input[type="text"],
.sw5e input[type="number"],
@ -114,6 +112,8 @@
.sw5e select:disabled,
.sw5e textarea:disabled {
color: #4b4a44;
border: 1px solid transparent !important;
outline: none !important;
}
.sw5e input:disabled:hover,
.sw5e select:disabled:hover,
@ -129,24 +129,6 @@
background: rgba(0, 0, 0, 0.1);
border: 2px groove #eeede0;
}
.sw5e label.checkbox {
flex: auto;
padding: 0;
margin: 0;
height: 22px;
line-height: 22px;
font-size: 11px;
}
.sw5e label.checkbox > input[type="checkbox"] {
width: 16px;
height: 16px;
margin: 0 2px 0 0;
position: relative;
top: 4px;
}
.sw5e label.checkbox.right > input[type="checkbox"] {
margin: 0 0 0 2px;
}
.sw5e .form-group label {
flex: 2;
color: #4b4a44;
@ -179,11 +161,12 @@
.sw5e .form-group .form-fields > *:last-child {
margin-right: 0;
}
.sw5e .form-group.stacked label {
.sw5e .form-group.stacked > label {
flex: 0 0 100%;
margin: 0;
}
.sw5e .form-group.stacked label.checkbox {
.sw5e .form-group.stacked label.checkbox,
.sw5e .form-group.stacked label.radio {
flex: auto;
text-align: left;
}
@ -207,6 +190,26 @@
background: rgba(0, 0, 0, 0.05);
}
/* ----------------------------------------- */
/* Hit Dice Config Sheet Specifically */
/* ----------------------------------------- */
.sw5e.hd-config .form-group button.increment,
.sw5e.hd-config .form-group button.decrement {
flex: 0 0 1rem;
line-height: 1rem;
}
.sw5e.hd-config .form-group button.decrement {
margin-right: 0;
}
.sw5e.hd-config .form-group span.sep {
margin: 0;
}
.sw5e.hd-config .form-group input {
flex: 0 0 2rem;
text-align: center;
margin-left: 2px;
margin-right: 2px;
}
/* ----------------------------------------- */
/* Entity Sheets Specifically */
/* ----------------------------------------- */
.sw5e.sheet {
@ -499,16 +502,60 @@
/* ----------------------------------------- */
/* Trait Selector
/* ----------------------------------------- */
#trait-selector .trait-list {
.trait-selector .trait-list {
list-style: none;
margin: 0;
padding: 0;
}
#trait-selector input[type="text"] {
.trait-selector input[type="text"] {
height: 24px;
margin: 2px;
}
/* ----------------------------------------- */
/* Actor Type Config Sheet Specifically */
/* ----------------------------------------- */
.actor-type .trait-list {
display: flex;
flex-wrap: wrap;
}
.actor-type .trait-list li {
flex-basis: 50%;
flex-grow: 1;
}
.actor-type .trait-list li.form-group {
flex-basis: 100%;
}
.actor-type label.radio {
display: flex;
flex: auto;
font-size: 12px;
line-height: 20px;
font-weight: normal;
}
.actor-type label.radio > input[type="radio"] {
margin: 0 5px 0 0;
}
.actor-type li.custom-type input[type="radio"] {
display: none;
}
/* ----------------------------------------- */
/* Add Feature Prompt Specifically */
/* ----------------------------------------- */
.sw5e.select-items-prompt .dialog-content {
margin-bottom: 1em;
}
.sw5e.select-items-prompt .items-list {
margin-top: 0.5em;
}
.sw5e.select-items-prompt .item-name > label,
.sw5e.select-items-prompt .item-image,
.sw5e.select-items-prompt input {
cursor: pointer;
}
.sw5e.select-items-prompt .item-name > label {
align-items: center;
}
/* ----------------------------------------- */
/* HUD
/* ----------------------------------------- */
.placeable-hud .control-icon {
@ -574,6 +621,9 @@
/* Powerbook */
/* ----------------------------------------- */
/* ----------------------------------------- */
/* Features Tab */
/* ----------------------------------------- */
/* ----------------------------------------- */
/* TinyMCE */
/* ----------------------------------------- */
}
@ -627,10 +677,12 @@
height: 30px;
line-height: 30px;
}
.sw5e.sheet.actor .sheet-header .attributes .movement h4.attribute-name {
.sw5e.sheet.actor .sheet-header .attributes .movement h4.attribute-name,
.sw5e.sheet.actor .sheet-header .attributes .hit-dice h4.attribute-name {
position: relative;
}
.sw5e.sheet.actor .sheet-header .attributes .movement .config-button {
.sw5e.sheet.actor .sheet-header .attributes .movement .config-button,
.sw5e.sheet.actor .sheet-header .attributes .hit-dice .config-button {
position: absolute;
display: none;
right: 0;
@ -638,7 +690,8 @@
font-size: 12px;
font-weight: normal;
}
.sw5e.sheet.actor .sheet-header .attributes .movement:hover .config-button {
.sw5e.sheet.actor .sheet-header .attributes .movement:hover .config-button,
.sw5e.sheet.actor .sheet-header .attributes .hit-dice:hover .config-button {
display: block;
}
.sw5e.sheet.actor .sheet-header .attributes input.temphp {
@ -1113,6 +1166,9 @@
.sw5e.sheet.actor .powerbook-empty .item-controls {
flex: 1;
}
.sw5e.sheet.actor .features i.original-class {
color: #4b4a44;
}
.sw5e.sheet.actor .editor {
padding: 0 8px;
}
@ -1229,16 +1285,16 @@
.sw5e.sheet.item .sheet-body .smalltable td:nth-child(even) {
width: 150px;
margin: 0.5em 0.5em;
padding: 0px 10px 0px 10px;
padding: 0 10px 0 10px;
text-align: left;
}
.sw5e.sheet.item .sheet-body .smalltable thead {
border-bottom: 0px;
border-bottom: 0;
}
.sw5e.sheet.item .sheet-body .smalltable th {
color: #000000;
text-shadow: none;
border-bottom: 0px;
border-bottom: 0;
background-color: #bdc8cc;
text-transform: none;
font-weight: bold;
@ -1252,12 +1308,12 @@
.sw5e.sheet.item .sheet-body .smalltable th:nth-child(even) {
width: 150px;
margin: 0.5em 0.5em;
padding: 0px 10px 0px 10px;
padding: 0 10px 0 10px;
text-align: left;
}
.sw5e.sheet.item .sheet-body .medtable table {
width: 500px;
border: 0px;
border: 0;
margin: 0.5em 0.5em;
}
.sw5e.sheet.item .sheet-body .medtable td:nth-child(odd) {
@ -1268,16 +1324,16 @@
.sw5e.sheet.item .sheet-body .medtable td:nth-child(even) {
width: 450px;
margin: 0.5em 0.5em;
padding: 0px 10px 0px 0px;
padding: 0 10px 0 0;
text-align: left;
}
.sw5e.sheet.item .sheet-body .medtable thead {
border-bottom: 0px;
border-bottom: 0;
}
.sw5e.sheet.item .sheet-body .medtable th {
color: #000000;
text-shadow: none;
border-bottom: 0px;
border-bottom: 0;
background-color: #bdc8cc;
text-transform: none;
font-weight: bold;
@ -1290,8 +1346,8 @@
text-align: left;
}
.sw5e.sheet.item .sheet-body .classtable blockquote {
border-left: 0px;
border-right: 0px;
border-left: 0;
border-right: 0;
background-color: #bdc8cc;
width: 600px;
}
@ -1305,8 +1361,8 @@
width: 100%;
border-collapse: collapse;
background: rgba(0, 0, 0, 0.05);
border-left: 0px;
border-right: 0px;
border-left: 0;
border-right: 0;
border-top: 0;
border-bottom: 0;
margin: 0.5em 0;
@ -1316,7 +1372,7 @@
.sw5e.sheet.item .sheet-body .classtable thead {
color: #000000;
text-shadow: none;
border-bottom: 0px;
border-bottom: 0;
background-color: #bdc8cc;
text-transform: none;
font-style: normal;
@ -1325,7 +1381,7 @@
.sw5e.sheet.item .sheet-body .classtable th {
color: #000000;
text-shadow: none;
border-bottom: 0px;
border-bottom: 0;
background-color: #bdc8cc;
text-transform: none;
font-style: normal;
@ -1360,7 +1416,7 @@
width: 100%;
line-height: 18px;
margin-bottom: 15px;
border: 0 0 0 0;
border: 0;
border-bottom: none;
overflow-x: auto;
}
@ -1745,7 +1801,7 @@
text-align: right;
padding-right: 5px;
}
.sw5e.sheet.actor.character .resource .attribute-value input {
.sw5e.sheet.actor.character .resource .attribute-value > input {
flex: 0 0 25%;
}
.sw5e.sheet.actor.character .resource .attribute-value label.recharge {
@ -1755,6 +1811,7 @@
font-size: 11px;
text-align: center;
color: #4b4a44;
align-items: center;
}
.sw5e.sheet.actor.character .resource .attribute-value label.recharge input[type="checkbox"] {
height: 14px;
@ -1853,6 +1910,26 @@
.sw5e.sheet.actor.npc .summary {
font-size: 18px;
}
.sw5e.sheet.actor.npc .summary li.creature-type {
display: flex;
justify-content: space-between;
width: 1em;
padding: 0 3px;
}
.sw5e.sheet.actor.npc .summary li.creature-type span {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.sw5e.sheet.actor.npc .summary li.creature-type .config-button {
display: none;
font-size: 12px;
font-weight: normal;
line-height: 2em;
}
.sw5e.sheet.actor.npc .summary li.creature-type:hover .config-button {
display: block;
}
.sw5e.sheet.actor.vehicle .features .item-controls {
flex: 0 0 68px;
}

214
sw5e.js
View file

@ -8,16 +8,17 @@
*/
// Import Modules
import { SW5E } from "./module/config.js";
import { registerSystemSettings } from "./module/settings.js";
import { preloadHandlebarsTemplates } from "./module/templates.js";
import { _getInitiativeFormula } from "./module/combat.js";
import { measureDistances, getBarAttribute } from "./module/canvas.js";
import {SW5E} from "./module/config.js";
import {registerSystemSettings} from "./module/settings.js";
import {preloadHandlebarsTemplates} from "./module/templates.js";
import {_getInitiativeFormula} from "./module/combat.js";
import {measureDistances} from "./module/canvas.js";
// Import Entities
// Import Documents
import Actor5e from "./module/actor/entity.js";
import Item5e from "./module/item/entity.js";
import CharacterImporter from "./module/characterImporter.js";
import {TokenDocument5e, Token5e} from "./module/token.js";
// Import Applications
import AbilityTemplate from "./module/pixi/ability-template.js";
@ -45,7 +46,7 @@ import * as migrations from "./module/migration.js";
/* Foundry VTT Initialization */
/* -------------------------------------------- */
Hooks.once("init", function() {
Hooks.once("init", function () {
console.log(`SW5e | Initializing SW5E System\n${SW5E.ASCII}`);
// Create a SW5E namespace within the game global
@ -61,7 +62,8 @@ Hooks.once("init", function() {
ItemSheet5e,
ShortRestDialog,
TraitSelector,
ActorMovementConfig
ActorMovementConfig,
ActorSensesConfig
},
canvas: {
AbilityTemplate
@ -71,6 +73,8 @@ Hooks.once("init", function() {
entities: {
Actor5e,
Item5e,
TokenDocument5e,
Token5e
},
macros: macros,
migrations: migrations,
@ -79,14 +83,15 @@ Hooks.once("init", function() {
// Record Configuration Values
CONFIG.SW5E = SW5E;
CONFIG.Actor.entityClass = Actor5e;
CONFIG.Item.entityClass = Item5e;
CONFIG.Actor.documentClass = Actor5e;
CONFIG.Item.documentClass = Item5e;
CONFIG.Token.documentClass = TokenDocument5e;
CONFIG.Token.objectClass = Token5e;
CONFIG.time.roundTime = 6;
CONFIG.fontFamilies = [
"Engli-Besh",
"Open Sans",
"Russo One"
];
CONFIG.fontFamilies = ["Engli-Besh", "Open Sans", "Russo One"];
CONFIG.Dice.DamageRoll = dice.DamageRoll;
CONFIG.Dice.D20Roll = dice.D20Roll;
// 5e cone RAW should be 53.13 degrees
CONFIG.MeasuredTemplate.defaults.angle = 53.13;
@ -100,7 +105,11 @@ Hooks.once("init", function() {
// Patch Core Functions
CONFIG.Combat.initiative.formula = "1d20 + @attributes.init.mod + @attributes.init.prof + @attributes.init.bonus";
Combat.prototype._getInitiativeFormula = _getInitiativeFormula;
Combatant.prototype._getInitiativeFormula = _getInitiativeFormula;
// Register Roll Extensions
CONFIG.Dice.rolls.push(dice.D20Roll);
CONFIG.Dice.rolls.push(dice.DamageRoll);
// Register sheet application classes
Actors.unregisterSheet("core", ActorSheet);
@ -124,28 +133,50 @@ Hooks.once("init", function() {
makeDefault: false,
label: "SW5E.SheetClassNPCOld"
});
Actors.registerSheet("sw5e", ActorSheet5eStarship, {
types: ["starship"],
makeDefault: true,
label: "SW5E.SheetClassStarship"
});
Actors.registerSheet('sw5e', ActorSheet5eVehicle, {
types: ['vehicle'],
// Actors.registerSheet("sw5e", ActorSheet5eStarship, {
// types: ["starship"],
// makeDefault: true,
// label: "SW5E.SheetClassStarship"
// });
Actors.registerSheet("sw5e", ActorSheet5eVehicle, {
types: ["vehicle"],
makeDefault: true,
label: "SW5E.SheetClassVehicle"
});
Items.unregisterSheet("core", ItemSheet);
Items.registerSheet("sw5e", ItemSheet5e, {
types: ['weapon', 'equipment', 'consumable', 'tool', 'loot', 'class', 'power', 'feat', 'species', 'backpack', 'archetype', 'classfeature', 'background', 'fightingmastery', 'fightingstyle', 'lightsaberform', 'deployment', 'deploymentfeature', 'starship', 'starshipfeature', 'starshipmod', 'venture'],
types: [
"weapon",
"equipment",
"consumable",
"tool",
"loot",
"class",
"power",
"feat",
"species",
"backpack",
"archetype",
"classfeature",
"background",
"fightingmastery",
"fightingstyle",
"lightsaberform",
"deployment",
"deploymentfeature",
"starship",
"starshipfeature",
"starshipmod",
"venture"
],
makeDefault: true,
label: "SW5E.SheetClassItem"
});
// Preload Handlebars Templates
preloadHandlebarsTemplates();
return preloadHandlebarsTemplates();
});
/* -------------------------------------------- */
/* Foundry VTT Setup */
/* -------------------------------------------- */
@ -153,31 +184,77 @@ Hooks.once("init", function() {
/**
* This function runs after game data has been requested and loaded from the servers, so entities exist
*/
Hooks.once("setup", function() {
Hooks.once("setup", function () {
// Localize CONFIG objects once up-front
const toLocalize = [
"abilities", "abilityAbbreviations", "abilityActivationTypes", "abilityConsumptionTypes", "actorSizes", "alignments",
"armorProficiencies", "armorPropertiesTypes", "conditionTypes", "consumableTypes", "cover", "currencies", "damageResistanceTypes",
"damageTypes", "distanceUnits", "equipmentTypes", "healingTypes", "itemActionTypes", "languages",
"limitedUsePeriods", "movementTypes", "movementUnits", "polymorphSettings", "proficiencyLevels", "senses", "skills",
"starshipRolessm", "starshipRolesmed", "starshipRoleslg", "starshipRoleshuge", "starshipRolesgrg", "starshipSkills",
"powerComponents", "powerLevels", "powerPreparationModes", "powerScalingModes", "powerSchools", "targetTypes",
"timePeriods", "toolProficiencies", "weaponProficiencies", "weaponProperties", "weaponSizes", "weaponTypes"
"abilities",
"abilityAbbreviations",
"abilityActivationTypes",
"abilityConsumptionTypes",
"actorSizes",
"alignments",
"armorProficiencies",
"armorPropertiesTypes",
"conditionTypes",
"consumableTypes",
"cover",
"currencies",
"damageResistanceTypes",
"damageTypes",
"distanceUnits",
"equipmentTypes",
"healingTypes",
"itemActionTypes",
"languages",
"limitedUsePeriods",
"movementTypes",
"movementUnits",
"polymorphSettings",
"proficiencyLevels",
"senses",
"skills",
"starshipRolessm",
"starshipRolesmed",
"starshipRoleslg",
"starshipRoleshuge",
"starshipRolesgrg",
"starshipSkills",
"powerComponents",
"powerLevels",
"powerPreparationModes",
"powerScalingModes",
"powerSchools",
"targetTypes",
"timePeriods",
"toolProficiencies",
"weaponProficiencies",
"weaponProperties",
"weaponSizes",
"weaponTypes"
];
// Exclude some from sorting where the default order matters
const noSort = [
"abilities", "alignments", "currencies", "distanceUnits", "movementUnits", "itemActionTypes", "proficiencyLevels",
"limitedUsePeriods", "powerComponents", "powerLevels", "powerPreparationModes", "weaponTypes"
"abilities",
"alignments",
"currencies",
"distanceUnits",
"movementUnits",
"itemActionTypes",
"proficiencyLevels",
"limitedUsePeriods",
"powerComponents",
"powerLevels",
"powerPreparationModes",
"weaponTypes"
];
// Localize and sort CONFIG objects
for ( let o of toLocalize ) {
const localized = Object.entries(CONFIG.SW5E[o]).map(e => {
for (let o of toLocalize) {
const localized = Object.entries(CONFIG.SW5E[o]).map((e) => {
return [e[0], game.i18n.localize(e[1])];
});
if ( !noSort.includes(o) ) localized.sort((a, b) => a[1].localeCompare(b[1]));
if (!noSort.includes(o)) localized.sort((a, b) => a[1].localeCompare(b[1]));
CONFIG.SW5E[o] = localized.reduce((obj, e) => {
obj[e[0]] = e[1];
return obj;
@ -186,32 +263,33 @@ Hooks.once("setup", function() {
// add DND5E translation for module compatability
game.i18n.translations.DND5E = game.i18n.translations.SW5E;
// console.log(game.settings.get("sw5e", "colorTheme"));
let theme = game.settings.get("sw5e", "colorTheme") + '-theme';
let theme = game.settings.get("sw5e", "colorTheme") + "-theme";
document.body.classList.add(theme);
});
/* -------------------------------------------- */
/**
* Once the entire VTT framework is initialized, check to see if we should perform a data migration
*/
Hooks.once("ready", function() {
Hooks.once("ready", function () {
// Wait to register hotbar drop hook on ready so that modules could register earlier if they want to
Hooks.on("hotbarDrop", (bar, data, slot) => macros.create5eMacro(data, slot));
// Determine whether a system migration is required and feasible
if ( !game.user.isGM ) return;
if (!game.user.isGM) return;
const currentVersion = game.settings.get("sw5e", "systemMigrationVersion");
const NEEDS_MIGRATION_VERSION = "1.2.4.R1-A5";
const NEEDS_MIGRATION_VERSION = "1.3.5.R1-A6";
// Check for R1 SW5E versions
const SW5E_NEEDS_MIGRATION_VERSION = "R1-A5";
const COMPATIBLE_MIGRATION_VERSION = 0.80;
const needsMigration = currentVersion && (isNewerVersion(SW5E_NEEDS_MIGRATION_VERSION, currentVersion) || isNewerVersion(NEEDS_MIGRATION_VERSION, currentVersion));
if ( !needsMigration ) return;
const SW5E_NEEDS_MIGRATION_VERSION = "R1-A6";
const COMPATIBLE_MIGRATION_VERSION = 0.8;
const needsMigration =
currentVersion &&
(isNewerVersion(SW5E_NEEDS_MIGRATION_VERSION, currentVersion) ||
isNewerVersion(NEEDS_MIGRATION_VERSION, currentVersion));
if (!needsMigration && needsMigration !== "") return;
// Perform the migration
if ( currentVersion && isNewerVersion(COMPATIBLE_MIGRATION_VERSION, currentVersion) ) {
if (currentVersion && isNewerVersion(COMPATIBLE_MIGRATION_VERSION, currentVersion)) {
const warning = `Your SW5e system data is from too old a Foundry version and cannot be reliably migrated to the latest version. The process will be attempted, but errors may occur.`;
ui.notifications.error(warning, {permanent: true});
}
@ -222,23 +300,17 @@ Hooks.once("ready", function() {
/* Canvas Initialization */
/* -------------------------------------------- */
Hooks.on("canvasInit", function() {
Hooks.on("canvasInit", function () {
// Extend Diagonal Measurement
canvas.grid.diagonalRule = game.settings.get("sw5e", "diagonalMovement");
SquareGrid.prototype.measureDistances = measureDistances;
// Extend Token Resource Bars
Token.prototype.getBarAttribute = getBarAttribute;
});
/* -------------------------------------------- */
/* Other Hooks */
/* -------------------------------------------- */
Hooks.on("renderChatMessage", (app, html, data) => {
// Display action buttons
chat.displayChatActionButtons(app, html, data);
@ -251,38 +323,36 @@ Hooks.on("renderChatMessage", (app, html, data) => {
Hooks.on("getChatLogEntryContext", chat.addChatMessageContextOptions);
Hooks.on("renderChatLog", (app, html, data) => Item5e.chatListeners(html));
Hooks.on("renderChatPopout", (app, html, data) => Item5e.chatListeners(html));
Hooks.on('getActorDirectoryEntryContext', Actor5e.addDirectoryContextOptions);
Hooks.on("renderSceneDirectory", (app, html, data)=> {
Hooks.on("getActorDirectoryEntryContext", Actor5e.addDirectoryContextOptions);
Hooks.on("renderSceneDirectory", (app, html, data) => {
//console.log(html.find("header.folder-header"));
setFolderBackground(html);
});
Hooks.on("renderActorDirectory", (app, html, data)=> {
Hooks.on("renderActorDirectory", (app, html, data) => {
setFolderBackground(html);
CharacterImporter.addImportButton(html);
});
Hooks.on("renderItemDirectory", (app, html, data)=> {
Hooks.on("renderItemDirectory", (app, html, data) => {
setFolderBackground(html);
});
Hooks.on("renderJournalDirectory", (app, html, data)=> {
Hooks.on("renderJournalDirectory", (app, html, data) => {
setFolderBackground(html);
});
Hooks.on("renderRollTableDirectory", (app, html, data)=> {
Hooks.on("renderRollTableDirectory", (app, html, data) => {
setFolderBackground(html);
});
Hooks.on("ActorSheet5eCharacterNew", (app, html, data) => {
console.log("renderSwaltSheet");
});
// TODO I should remove this
Handlebars.registerHelper('getProperty', function (data, property) {
// FIXME: This helper is needed for the vehicle sheet. It should probably be refactored.
Handlebars.registerHelper("getProperty", function (data, property) {
return getProperty(data, property);
});
function setFolderBackground(html) {
html.find("header.folder-header").each(function() {
html.find("header.folder-header").each(function () {
let bgColor = $(this).css("background-color");
if(bgColor == undefined)
bgColor = "rgb(255,255,255)";
$(this).closest('li').css("background-color", bgColor);
})
if (bgColor == undefined) bgColor = "rgb(255,255,255)";
$(this).closest("li").css("background-color", bgColor);
});
}

View file

@ -2,7 +2,7 @@
"name": "sw5e",
"title": "SW 5th Edition",
"description": "A comprehensive game system for running games of SW 5th Edition in the Foundry VTT environment.",
"version": "1.2.4.R1-A5",
"version": "1.3.5.R1-A7",
"author": "Dev Team",
"scripts": [],
"esmodules": ["sw5e.js"],
@ -50,18 +50,6 @@
"path": "./packs/packs/conditions.db",
"entity": "JournalEntry"
},
{
"name": "deployments",
"label": "Deployments",
"path": "./packs/packs/deployments.db",
"entity": "Item"
},
{
"name": "deploymentfeatures",
"label": "Deployment Features",
"path": "./packs/packs/deploymentfeatures.db",
"entity": "Item"
},
{
"name": "enhanceditems",
"label": "Enhanced Items",
@ -121,36 +109,6 @@
"label": "Species Traits",
"path": "./packs/packs/speciestraits.db",
"entity": "Item"
},
{
"name": "starshiparmor",
"label": "Starship Armor",
"path": "./packs/packs/starshiparmor.db",
"entity": "Item"
},
{
"name": "starshipequipment",
"label": "Starship Equipment",
"path": "./packs/packs/starshipequipment.db",
"entity": "Item"
},
{
"name": "starshipfeatures",
"label": "Starship Features",
"path": "./packs/packs/starshipfeatures.db",
"entity": "Item"
},
{
"name": "starshipmodifications",
"label": "Starship Modifications",
"path": "./packs/packs/starshipmodifications.db",
"entity": "Item"
},
{
"name": "starshipweapons",
"label": "Starship Weapons",
"path": "./packs/packs/starshipweapons.db",
"entity": "Item"
},
{
"name": "tables",
@ -164,12 +122,6 @@
"path": "./packs/packs/techpowers.db",
"entity": "Item"
},
{
"name": "ventures",
"label": "Ventures",
"path": "./packs/packs/ventures.db",
"entity": "Item"
},
{
"name": "weapons",
"label": "Weapons",
@ -187,6 +139,11 @@
"lang": "fr",
"name": "French",
"path": "lang/fr.json"
},
{
"lang": "it",
"name": "Italian",
"path": "lang/it.json"
}
],
"socket": true,
@ -194,8 +151,8 @@
"gridUnits": "ft",
"primaryTokenAttribute": "attributes.hp",
"secondaryTokenAttribute": null,
"minimumCoreVersion": "0.7.7",
"compatibleCoreVersion": "0.7.9",
"minimumCoreVersion": "0.8.2",
"compatibleCoreVersion": "0.8.8",
"url": "https://github.com/unrealkakeman89/sw5e",
"manifest": "https://raw.githubusercontent.com/unrealkakeman89/sw5e/master/system.json",
"download": "https://github.com/unrealkakeman89/sw5e/archive/master.zip"

View file

@ -1,6 +1,6 @@
{
"Actor": {
"types": ["character", "npc", "starship", "vehicle"],
"types": ["character", "npc", "vehicle"],
"templates": {
"common": {
"abilities": {
@ -333,6 +333,7 @@
},
"details": {
"background": "",
"originalClass": "",
"xp": {
"value": 0,
"min": 0,
@ -382,7 +383,12 @@
"npc": {
"templates": ["common", "creature"],
"details": {
"type": "",
"type": {
"value": "",
"subtype": "",
"swarm": "",
"custom": ""
},
"environment": "",
"cr": 1,
"powerForceLevel": 0,
@ -880,13 +886,17 @@
"archetype": "",
"hitDice": "d6",
"hitDiceUsed": 0,
"saves": [],
"skills": {
"number": 2,
"choices": [],
"value": []
},
"source": "",
"powercasting": "none"
"powercasting": {
"progression": "none",
"ability": ""
}
},
"classfeature": {
"templates": ["itemDescription", "activatedEffect", "action"],

View file

@ -63,7 +63,10 @@
{{!-- HIT DICE / SHORT & LONG REST BUTTONS --}}
<section>
<h1>{{ localize "SW5E.HitDice" }}</h1>
<h1>
{{ localize "SW5E.HitDice" }}
<a class="config-button" data-action="hit-dice" title="{{localize 'SW5E.HitDiceConfig'}}"><i class="fas fa-cog"></i></a>
</h1>
<div class="attribute-value multiple">
<span class="value-number">{{data.attributes.hd}}</span>
<span class="value-separator">/</span>
@ -147,4 +150,5 @@
<section class="tab biography" data-group="primary" data-tab="biography">
{{> "systems/sw5e/templates/actors/newActor/parts/swalt-biography.html"}}
</section>
</section>
</form>

View file

@ -137,4 +137,5 @@
<section class="tab biography" data-group="primary" data-tab="biography">
{{> "systems/sw5e/templates/actors/newActor/parts/swalt-biography.html"}}
</section>
</section>
</form>

View file

@ -1,4 +1,4 @@
<li class="item group-grid-fav-items" data-item-id="{{item._id}}">
<li class="item group-grid-fav-items" data-item-id="{{item.data._id}}">
<div class="item-name rollable">
<div class="item-image" style="background-image: url({{item.img}})"></div>
<h4>{{item.name}}</h4>

View file

@ -13,11 +13,11 @@
<div class="panel">
<section class="additional-info">
<h1 class="section-titles">Description</h1>
{{editor content=data.details.description.value target="data.details.description.value" button=true owner=owner editable=editable}}
{{editor content=data.details.description.value target="data.details.description.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section>
<h1 class="section-titles">Background</h1>
{{editor content=data.details.biography.value target="data.details.biography.value" button=true owner=owner editable=editable}}
{{editor content=data.details.biography.value target="data.details.biography.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
</div>

View file

@ -21,8 +21,10 @@
<span class="npc-size">{{lookup config.actorSizes data.traits.size}}</span>
<input type="text" name="data.details.alignment" value="{{data.details.alignment}}"
placeholder="{{ localize 'SW5E.Alignment' }}" />
<input type="text" name="data.details.type" value="{{data.details.type}}"
placeholder="{{ localize 'SW5E.Type' }}" />
<div class="creature-type roundTransition">
<span title="{{labels.type}}">{{labels.type}}</span>
<a class="config-button" data-action="type" title="{{localize 'SW5E.CreatureTypeConfig'}}"><i class="fas fa-cog"></i></a>
</div>
<input type="text" name="data.details.source" value="{{data.details.source}}"
placeholder="{{ localize 'SW5E.Source' }}" />
</div>
@ -90,18 +92,18 @@
<ol>
{{#each data.abilities as |ability id|}}
<li class="ability {{#if ability.proficient}}proficient{{/if}}" data-ability="{{id}}">
<h2 class="ability-name rollable">{{ability.label}}</h4>
<h2 class="ability-name rollable">{{ability.label}}</h2>
<input class="ability-score" name="data.abilities.{{id}}.value" type="text"
value="{{ability.value}}" data-dtype="Number" placeholder="10" />
<div class="ability-modifiers">
<span class="ability-mod"
title="Modifier">{{numberFormat ability.mod decimals=0 sign=true}}</span>
title="{{ localize 'SW5E.Modifier' }}">{{numberFormat ability.mod decimals=0 sign=true}}</span>
<input type="hidden" name="data.abilities.{{id}}.proficient"
value="{{ability.proficient}}" data-dtype="Number" />
<button class="proficiency-toggle ability-proficiency"
title="Proficiency">{{{ability.icon}}}</button>
<span class="ability-save"
title="Saving Throw">{{numberFormat ability.save decimals=0 sign=true}}</span>
title="{{ localize 'SW5E.SavingThrow' }}">{{numberFormat ability.save decimals=0 sign=true}}</span>
</div>
</li>
{{/each}}
@ -111,18 +113,20 @@
<section class="skills">
<h1>{{localize "SW5E.Skills"}}</h1>
<ol>
{{#each data.skills as |skill s|}}
{{#each config.skills as |label s|}}
{{#with (lookup ../data.skills s) as |skill|}}
<li class="skill {{#if skill.value}}proficient{{/if}}" data-skill="{{s}}">
<input type="hidden" name="data.skills.{{s}}.value" value="{{skill.value}}"
data-dtype="Number" />
<button class="proficiency-toggle skill-proficiency"
title="{{skill.hover}}">{{{skill.icon}}}</button>
<span class="skill-name rollable">{{skill.label}}</span>
<span class="skill-name rollable">{{label}}</span>
<span class="skill-ability">{{skill.ability}}</span>
<span class="skill-mod">{{numberFormat skill.total decimals=0 sign=true}}</span>
{{!-- <input class="skill-bonus" name="data.skills.{{s}}.bonus" type="text" value="{{numberFormat skill.bonus decimals=0 sign=true}}" data-dtype="Number" placeholder="0" title="Misc. Modifier"/> --}}
{{!-- <span class="skill-passive">({{skill.passive}})</span> --}}
</li>
{{/with}}
{{/each}}
</ol>
</section>
@ -191,7 +195,7 @@
<div class="panel">
<section>
<h1>{{localize "SW5E.Biography"}}</h1>
{{editor content=data.details.biography.value target="data.details.biography.value" button=true owner=owner editable=editable}}
{{editor content=data.details.biography.value target="data.details.biography.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
</div>

View file

@ -3,8 +3,8 @@
{{#each effects as |section sid|}}
<li class="items-header flexrow" data-effect-type="{{section.type}}">
<h3 class="item-name effect-name flexrow">{{localize section.label}}</h3>
<div class="effect-source">Source</div>
<div class="effect-source">Duration</div>
<div class="effect-source">{{localize "SW5E.Source"}}</div>
<div class="effect-source">{{localize "SW5E.Duration"}}</div>
<div class="item-controls effect-controls flexrow">
<a class="effect-control" data-action="create" title="{{localize 'SW5E.EffectCreate'}}">
<i class="fas fa-plus"></i> {{localize "SW5E.Add"}}

View file

@ -1,22 +1,22 @@
<div class="panel additional-info">
<section><h1 class="section-titles biopage">{{localize "SW5E.PersonalityTraits" }}</h1>
{{editor content=data.details.trait target="data.details.trait" button=true owner=owner editable=editable}}
{{editor content=data.details.trait target="data.details.trait" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section><h1 class="section-titles biopage">{{localize "SW5E.Ideals" }}</h1>
{{editor content=data.details.ideal target="data.details.ideal" button=true owner=owner editable=editable}}
{{editor content=data.details.ideal target="data.details.ideal" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section><h1 class="section-titles biopage">{{localize "SW5E.Bonds" }}</h1>
{{editor content=data.details.bond target="data.details.bond" button=true owner=owner editable=editable}}
{{editor content=data.details.bond target="data.details.bond" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section><h1 class="section-titles biopage">{{localize "SW5E.Flaws" }}</h1>
{{editor content=data.details.flaw target="data.details.flaw" button=true owner=owner editable=editable}}
{{editor content=data.details.flaw target="data.details.flaw" button=true owner=owner editable=editable rollData=rollData}}
</section>
</div>
<div class="panel background">
<section><h1 class="section-titles biopage">{{localize "SW5E.Description" }}</h1>
{{editor content=data.details.description.value target="data.details.description.value" button=true owner=owner editable=editable}}
{{editor content=data.details.description.value target="data.details.description.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section><h1 class="section-titles">{{localize "SW5E.Background" }}</h1>
{{editor content=data.details.biography.value target="data.details.biography.value" button=true owner=owner editable=editable}}
{{editor content=data.details.biography.value target="data.details.biography.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
</div>

View file

@ -5,18 +5,18 @@
<ol>
{{#each data.abilities as |ability id|}}
<li class="ability {{#if ability.proficient}}proficient{{/if}}" data-ability="{{id}}">
<h2 class="ability-name rollable">{{ability.label}}</h4>
<h2 class="ability-name rollable">{{ability.label}}</h2>
<input class="ability-score" name="data.abilities.{{id}}.value" type="text"
value="{{ability.value}}" data-dtype="Number" placeholder="10" />
<div class="ability-modifiers">
<span class="ability-mod"
title="Modifier">{{numberFormat ability.mod decimals=0 sign=true}}</span>
title="{{ localize 'SW5E.Modifier' }}">{{numberFormat ability.mod decimals=0 sign=true}}</span>
<input type="hidden" name="data.abilities.{{id}}.proficient"
value="{{ability.proficient}}" data-dtype="Number" />
<button class="proficiency-toggle ability-proficiency"
title="Proficiency">{{{ability.icon}}}</button>
<span class="ability-save"
title="Saving Throw">{{numberFormat ability.save decimals=0 sign=true}}</span>
title="{{ localize 'SW5E.SavingThrow' }}">{{numberFormat ability.save decimals=0 sign=true}}</span>
</div>
</li>
{{/each}}
@ -26,18 +26,20 @@
<section class="skills">
<h1>{{localize "SW5E.Skills" }}</h1>
<ol>
{{#each data.skills as |skill s|}}
{{#each config.skills as |label s|}}
{{#with (lookup ../data.skills s) as |skill|}}
<li class="skill {{#if skill.value}}proficient{{/if}}" data-skill="{{s}}">
<input type="hidden" name="data.skills.{{s}}.value" value="{{skill.value}}"
data-dtype="Number" />
<button class="proficiency-toggle skill-proficiency"
title="{{skill.hover}}">{{{skill.icon}}}</button>
<span class="skill-name rollable">{{skill.label}}</span>
<span class="skill-name rollable">{{label}}</span>
<span class="skill-ability">{{skill.ability}}</span>
<span class="skill-mod">{{numberFormat skill.total decimals=0 sign=true}}</span>
{{!-- <input class="skill-bonus" name="data.skills.{{s}}.bonus" type="text" value="{{numberFormat skill.bonus decimals=0 sign=true}}" data-dtype="Number" placeholder="0" title="Misc. Modifier"/> --}}
{{!-- <span class="skill-passive">({{skill.passive}})</span> --}}
</li>
{{/with}}
{{/each}}
</ol>
</section>

View file

@ -66,7 +66,7 @@
<!-- {{item.data.hitDice}} -->
</div>
<div class="item-detail player-class-levels">
<strong>Level {{item.data.levels}}</strong> &nbsp;&nbsp;<a class="increment-class-level"><i style="color:#c40f0f; text-shadow: 0px 1px 2px gray;" class="fas fa-arrow-up"></i></a> &nbsp;&nbsp;<a class="decrement-class-level"><i style="color:#c40f0f; text-shadow: 0px 1px 2px gray" class="fas fa-arrow-down"></i></a>
<strong>{{localize "SW5E.Level"}} {{item.data.levels}}</strong> &nbsp;&nbsp;<a class="increment-class-level"><i style="color:#c40f0f; text-shadow: 0 1px 2px gray;" class="fas fa-arrow-up"></i></a> &nbsp;&nbsp;<a class="decrement-class-level"><i style="color:#c40f0f; text-shadow: 0 1px 2px gray" class="fas fa-arrow-down"></i></a>
<!-- {{#if ../owner}}
<a class="item-control item-create" title="{{localize 'SW5E.LevelAdd'}}"
{{#each item.data.levels as |v k|}}data-{{k}}="{{v}}" {{/each}}>
@ -78,8 +78,8 @@
{{#if ../../owner}}
<div class="item-controls item-detail">
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
<a class="item-control item-edit" title="{{localize 'SW5E.ItemEdit'}}"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="{{localize 'SW5E.ItemDelete'}}"><i class="fas fa-trash"></i></a>
</div>
{{/if}}
</li>

View file

@ -38,8 +38,11 @@
{{#each section.items as |item iid|}}
<li class="item group-grid-features {{#if isDepleted}}depleted{{/if}}" data-item-id="{{item._id}}">
<div class="item-name rollable">
<div class="item-image" style="background-image: url({{item.img}})"></div>
<h4>{{item.name}}</h4>
<div class="item-image" style="background-image: url('{{item.img}}')"></div>
<h4>
{{item.name}}
{{#if item.isOriginalClass}} <i class="original-class fas fa-sun" title="{{localize 'SW5E.ClassOriginal'}}"></i>{{/if}}
</h4>
</div>
{{#if section.hasActions}}
@ -66,7 +69,7 @@
<!-- {{item.data.hitDice}} -->
</div>
<div class="item-detail player-class-levels">
<strong>Level {{item.data.levels}}</strong> &nbsp;&nbsp;<a class="increment-class-level"><i style="color:#c40f0f; text-shadow: 0px 1px 2px gray;" class="fas fa-arrow-up"></i></a> &nbsp;&nbsp;<a class="decrement-class-level"><i style="color:#c40f0f; text-shadow: 0px 1px 2px gray" class="fas fa-arrow-down"></i></a>
<strong>{{localize "SW5E.Level"}} {{item.data.levels}}</strong> &nbsp;&nbsp;<a class="increment-class-level"><i style="color:#c40f0f; text-shadow: 0 1px 2px gray;" class="fas fa-arrow-up"></i></a> &nbsp;&nbsp;<a class="decrement-class-level"><i style="color:#c40f0f; text-shadow: 0 1px 2px gray" class="fas fa-arrow-down"></i></a>
<!-- {{#if ../owner}}
<a class="item-control item-create" title="{{localize 'SW5E.LevelAdd'}}"
{{#each item.data.levels as |v k|}}data-{{k}}="{{v}}" {{/each}}>
@ -78,8 +81,8 @@
{{#if ../../owner}}
<div class="item-controls item-detail">
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
<a class="item-control item-edit" title="{{localize 'SW5E.ItemEdit'}}"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="{{localize 'SW5E.ItemDelete'}}"><i class="fas fa-trash"></i></a>
</div>
{{/if}}
</li>

View file

@ -110,7 +110,7 @@
<div class="item-detail item-target" title="{{localize 'SW5E.Range'}}: {{labels.range}}">
{{#if labels.target}}
{{labels.target}}
{{else}}None
{{else}}{{localize 'SW5E.None'}}
{{/if}}
</div>
@ -120,8 +120,8 @@
<a class="item-control item-toggle {{item.toggleClass}}" title="{{item.toggleTitle}}"><i
class="fas fa-check-circle"></i></a>
{{/if}}
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
<a class="item-control item-edit" title="{{localize 'SW5E.ItemEdit'}}"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="{{localize 'SW5E.ItemDelete'}}"><i class="fas fa-trash"></i></a>
</div>
{{/if}}
</li>

View file

@ -63,9 +63,12 @@
<h4>
{{item.name~}}
{{~#if item.isStack}} ({{item.data.quantity}}){{/if}}
{{~#if item.data.attuned}} <i class="fas fa-sun attuned"
title={{localize "SW5E.Attuned"}}></i>{{/if}}
</h4>
{{#if item.attunement}}
<div class="item-detail attunement">
<i class="fas {{item.attunement.icon}} {{item.attunement.cls}}" title="{{localize item.attunement.title}}"></i>
</div>
{{/if}}
</div>
{{#if ../../isCharacter}}

View file

@ -3,31 +3,29 @@
<input type="text" name="data.details.notesname" value="{{data.details.notesname}}"
placeholder="{{localize 'SW5E.Journal'}}" />
{{editor content=data.details.notes.value target="data.details.notes.value" button=true owner=owner editable=editable}}
{{editor content=data.details.notes.value target="data.details.notes.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section>
<input type="text" name="data.details.notes1name" value="{{data.details.notes1name}}"
placeholder="{{localize 'SW5E.AdditionalNotes'}}"/>
{{editor content=data.details.notes1.value target="data.details.notes1.value" button=true owner=owner editable=editable}}
{{editor content=data.details.notes1.value target="data.details.notes1.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section>
<input type="text" name="data.details.notes2name" value="{{data.details.notes2name}}"
placeholder="{{localize 'SW5E.AdditionalNotes'}}" />
{{editor content=data.details.notes2.value target="data.details.notes2.value" button=true owner=owner editable=editable}}
{{editor content=data.details.notes2.value target="data.details.notes2.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section>
<input type="text" name="data.details.notes3name" value="{{data.details.notes3name}}"
placeholder="{{localize 'SW5E.AdditionalNotes'}}" />
{{editor content=data.details.notes3.value target="data.details.notes3.value" button=true owner=owner editable=editable}}
{{editor content=data.details.notes3.value target="data.details.notes3.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section>
<input type="text" name="data.details.notes4name" value="{{data.details.notes4name}}"
placeholder="{{localize 'SW5E.AdditionalNotes'}}" />
{{editor content=data.details.notes4.value target="data.details.notes4.value" button=true owner=owner editable=editable}}
</section>
{{editor content=data.details.notes4.value target="data.details.notes4.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
</div>

View file

@ -9,28 +9,28 @@
<input type="text" name="data.details.notesname" value="{{data.details.notesname}}"
placeholder="{{localize 'SW5E.Journal'}}" />
{{editor content=data.details.notes.value target="data.details.notes.value" button=true owner=owner editable=editable}}
{{editor content=data.details.notes.value target="data.details.notes.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section>
<input type="text" name="data.details.notes1name" value="{{data.details.notes1name}}"
placeholder="{{localize 'SW5E.AdditionalNotes'}}" />
{{editor content=data.details.notes1.value target="data.details.notes1.value" button=true owner=owner editable=editable}}
{{editor content=data.details.notes1.value target="data.details.notes1.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section>
<input type="text" name="data.details.notes2name" value="{{data.details.notes2name}}"
placeholder="{{localize 'SW5E.AdditionalNotes'}}" />
{{editor content=data.details.notes2.value target="data.details.notes2.value" button=true owner=owner editable=editable}}
{{editor content=data.details.notes2.value target="data.details.notes2.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section>
<input type="text" name="data.details.notes3name" value="{{data.details.notes3name}}"
placeholder="{{localize 'SW5E.AdditionalNotes'}}" />
{{editor content=data.details.notes3.value target="data.details.notes3.value" button=true owner=owner editable=editable}}
{{editor content=data.details.notes3.value target="data.details.notes3.value" button=true owner=owner editable=editable rollData=rollData}}
</section>
<section>
<input type="text" name="data.details.notes4name" value="{{data.details.notes4name}}"
placeholder="{{localize 'SW5E.AdditionalNotes'}}" />
{{editor content=data.details.notes4.value target="data.details.notes4.value" button=true owner=owner editable=editable}}
{{editor content=data.details.notes4.value target="data.details.notes4.value" button=true owner=owner editable=editable rollData=rollData}}
</section>

View file

@ -92,7 +92,7 @@
<div class="item-detail item-target" title="{{localize 'SW5E.Range'}}: {{labels.range}}">
{{#if labels.target}}
{{labels.target}}
{{else}}None
{{else}}{{localize 'SW5E.None'}}
{{/if}}
</div>
@ -102,8 +102,8 @@
<a class="item-control item-toggle {{item.toggleClass}}" title="{{item.toggleTitle}}"><i
class="fas fa-check-circle"></i></a>
{{/if}}
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
<a class="item-control item-edit" title="{{localize 'SW5E.ItemEdit'}}"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="{{localize 'SW5E.ItemDelete'}}"><i class="fas fa-trash"></i></a>
</div>
{{/if}}
</li>

Some files were not shown because too many files have changed in this diff Show more