Merge branch 'Develop' into professorbunbury-sw5e

This commit is contained in:
CK 2021-03-22 15:51:17 -04:00 committed by GitHub
commit 14e9e996e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 2950 additions and 1725 deletions

File diff suppressed because it is too large Load diff

1027
lang/fr.json Normal file

File diff suppressed because it is too large Load diff

View file

@ -1256,14 +1256,14 @@ export default class Actor5e extends Actor {
const dfp = data.attributes.force.points.max - data.attributes.force.points.value;
const updateData = {
"data.attributes.hp.value": data.attributes.hp.max,
"data.attributes.hp.temp": 0,
"data.attributes.hp.tempmax": 0,
"data.attributes.hp.temp": null,
"data.attributes.hp.tempmax": null,
"data.attributes.tech.points.value": data.attributes.tech.points.max,
"data.attributes.tech.points.temp": 0,
"data.attributes.tech.points.tempmax": 0,
"data.attributes.tech.points.temp": null,
"data.attributes.tech.points.tempmax": null,
"data.attributes.force.points.value": data.attributes.force.points.max,
"data.attributes.force.points.temp": 0,
"data.attributes.force.points.tempmax": 0
"data.attributes.force.points.temp": null,
"data.attributes.force.points.tempmax": null
};
// Recover character resources

View file

@ -893,349 +893,349 @@ SW5E.classFeatures = ClassFeatures;
// Configure Optional Character Flags
SW5E.characterFlags = {
"adaptiveResilience": {
name: "SW5E.FlagsAdaptiveResilience",
hint: "Prolongued use of technology allows members of your species to readily adapt to its effects. You have advantage on Strength and Constitution saving throws against tech powers.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsAdaptiveResilience",
hint: "SW5E.FlagsAdaptiveResilienceHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"aggressive": {
name: "SW5E.FlagsAggressive",
hint: "As a bonus action, you can move up to your speed toward an enemy of your choice that you can see or hear. You must end this move closer to the enemy than you started.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsAggressive",
hint: "SW5E.FlagsAggressiveHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"amphibious": {
name: "SW5E.FlagsAmphibious",
hint: "You can breathe air and water.",
section: "Species Traits",
name: "SW5E.FlagsAmphibious",
hint: "SW5E.FlagsAmphibiousHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"armorIntegration": {
name: "SW5E.FlagsArmorIntegration",
hint: "You cannot wear armor, but you can have the armor professionally integrated into your chassis over the course of a long rest. This work must be done by someone proficient with astrotechs implements. You must be proficient in armor in order to have it integrated.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsArmorIntegration",
hint: "SW5E.FlagsArmorIntegrationHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"businessSavvy": {
name: "SW5E.FlagsBusinessSavvy",
hint: "Whenever you make a Charisma (Persuasion) check involving haggling you are considered to have expertise in the Persuasion skill.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsBusinessSavvy",
hint: "SW5E.FlagsBusinessSavvyHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"cannibalize": {
name: "SW5E.FlagsCannibalize",
hint: "If you spend at least 1 minute devouring the corpse of a beast or humanoid, you gain temporary hit points equal to your Constitution modifier. Once you've used this feature, you must complete a short or long rest before you can use it again.",
section: "Species Traits",
name: "SW5E.FlagsCannibalize",
hint: "SW5E.FlagsCannibalizeHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"closedMind": {
name: "SW5E.FlagsClosedMind",
hint: "Members of your species have a natural attunement to the Force, which makes them resistant to its powers. You have advantage on Wisdom and Charisma saving throws against force powers.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsClosedMind",
hint: "SW5E.FlagsClosedMindHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"crudeWeaponSpecialists": {
name: "SW5E.FlagsCrudeWeaponSpecialists",
hint: "Members of your species are used to making do with less. You can spend 1 hour, which you can do over the course of a short rest, crafting a weapon out of loose materials. You can craft any simple kinetic weapon, but the weapons damage suffers a -1 penalty.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsCrudeWeaponSpecialists",
hint: "SW5E.FlagsCrudeWeaponSpecialistsHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"defiant": {
name: "SW5E.FlagsDefiant",
hint: "Members of your species are known to be stubborn and often refuse to give up, even against the worst odds. When you or a creature you can see that can see and understand you makes an ability check, attack roll, or saving throw, you can roll a d4 and add it to their roll (no action required). You can use this before or after the roll, but before the GM determines the rolls outcome. Once youve used this feature, you must complete a short or long rest before you can use it again.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsDefiant",
hint: "SW5E.FlagsDefiantHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"detailOriented": {
name: "SW5E.FlagsDetailOriented",
hint: "You have advantage on Intelligence (Investigation) checks within 5 feet.",
section: "Species Traits",
hint: "SW5E.FlagsDetailOrientedHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"enthrallingPheromones": {
name: "SW5E.FlagsEnthrallingPheromones",
hint: "You can use your pheromones to influence individuals of both sexes. Whenever you roll a 1 on a Charisma (Persuasion) check, you can reroll the die and must use the new roll. Additionally, once per short or long rest, you can treat a d20 roll of 9 or lower on a Charisma check as a 10. This feature has no effect on droids or constructs.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsEnthrallingPheromones",
hint: "SW5E.FlagsEnthrallingPheromonesHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"extraArms": {
name: "SW5E.FlagsExtraArms",
hint: "You possess more than two arms, which you can use independently of one another. 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).",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsExtraArms",
hint: "SW5E.FlagsExtraArmsHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"forceContention": {
name: "SW5E.FlagsForceContention",
hint: "Due to their unique physiology, members of your species exhibit a hardiness that allows them to overcome use of the Force. You have advantage on Strength and Constitution saving throws against force powers.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsForceContention",
hint: "SW5E.FlagsForceContentionHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"forceInsensitive": {
name: "SW5E.FlagsForceInsensitive",
hint: "While droids can be manipulated by many force powers, they cannot sense the Force. You can not use force powers or take levels in forcecasting classes.",
section: "Species Traits",
type: Boolean
hint: "SW5E.FlagsForceInsensitiveHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"foreignBiology": {
name: "SW5E.FlagsForeignBiology",
hint: "You wear a breathing apparatus because many atmospheres in the galaxy differ from that of your species' homeworld. If your apparatus is removed while you are in such an environment, you lose consciousness.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsForeignBiology",
hint: "SW5E.FlagsForeignBiologyHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"furyOfTheSmall": {
name: "SW5E.FlagsFuryOfTheSmall",
hint: "When you damage a creature with an attack or a power and the creature's size is larger than yours, you can cause the attack or power to deal extra damage to the creature. The extra damage equals your level. Once you use this trait, you can't use it again until you finish a short or long rest.",
section: "Species Traits",
name: "SW5E.FlagsFuryOfTheSmall",
hint: "SW5E.FlagsFuryOfTheSmallHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"grovelCowerAndBeg": {
name: "SW5E.FlagsGrovelCowerAndBeg",
hint: "As an action on your turn, you can cower pathetically to distract nearby foes. Until the end of your next turn, your allies gain advantage on attack rolls against enemies within 10 feet of you that can see you. Once you use this trait, you cant use it again until you finish a short or long rest.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsGrovelCowerAndBeg",
hint: "SW5E.FlagsGrovelCowerAndBegHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"inscrutable": {
name: "SW5E.FlagsInscrutable",
hint: "Your calm demeaner and control make you hard to read. Wisdom (Insight) checks made against you have disadvantage, and you have advantage on any saving throw against an effect that would read your thoughts.",
section: "Species Traits",
name: "SW5E.FlagsInscrutable",
hint: "SW5E.FlagsInscrutableHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"keenSenses": {
name: "SW5E.FlagsKeenSenses",
hint: "You have advantage on Wisdom (Perception) checks that involve using particular senses (see your species' traits for details).",
section: "Species Traits",
hint: "SW5E.FlagsKeenSensesHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"longlimbed": {
name: "SW5E.FlagsLongLimbed",
hint: "When you make a melee attack on your turn, your reach for it is 5 feet greater than normal.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsLongLimbed",
hint: "SW5E.FlagsLongLimbedHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"maintenanceMode": {
name: "SW5E.FlagsMaintenanceMode",
hint: "Rather than sleep, you enter an inactive state to perform routine maintenance for 4 hours each day. You have disadvantage on Wisdom (Perception) checks while performing maintenance.",
section: "Species Traits",
type: Boolean
hint: "SW5E.FlagsMaintenanceModeHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"maskOfTheWild": {
name: "SW5E.FlagsMaskOfTheWild",
hint: "You can attempt to hide even when you are only lightly obscured by foliage, heavy rain, falling snow, mist, and other natural phenomena.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsMaskOfTheWild",
hint: "SW5E.FlagsMaskOfTheWildHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"multipleHearts": {
name: "SW5E.FlagsMultipleHearts",
hint: "When you are reduced to 0 hit points but not killed outright, you can drop to 1 hit point instead. You can't use this feature again until you finish a long rest.",
section: "Species Traits",
name: "SW5E.FlagsMultipleHearts",
hint: "SW5E.FlagsMultipleHeartsHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"naturallyStealthy": {
name: "SW5E.FlagsNaturallyStealthy",
hint: "You can attempt to hide even when you are obscured only by a creature that is your size or larger than you.",
section: "Species Traits",
hint: "SW5E.FlagsNaturallyStealthyHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"nimbleAgility": {
name: "SW5E.FlagsNimbleAgility",
hint: "Your reflexes and agility allow you to move with a burst of speed. When you move on your turn in combat, you can double your speed until the end of the turn. Once you use this trait, you can't use it again until you move 0 feet on one of your turns.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsNimbleAgility",
hint: "SW5E.FlagsNimbleAgilityHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"nimbleEscape": {
name: "SW5E.FlagsNimbleEscape",
hint: "You can take the Disengage or Hide action as a bonus action.",
section: "Species Traits",
hint: "SW5E.FlagsNimbleEscapeHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"nimbleness": {
name: "SW5E.FlagsNimbleness",
hint: "You can move through the space of any creature that is of a size larger than yours.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsNimbleness",
hint: "SW5E.FlagsNimblenessHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"pintsized": {
name: "SW5E.FlagsPintsized",
hint: "Your tiny stature makes it hard for you to wield bigger weapons. You cant use medium or heavy shields. Additionally, you cant wield weapons with the two-handed or versatile property, and you can only wield one-handed weapons in two hands unless they have the light property.",
section: "Species Traits",
type: Boolean
hint: "SW5E.FlagsPintsizedHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"powerfulBuild": {
name: "SW5E.FlagsPowerfulBuild",
hint: "SW5E.FlagsPowerfulBuildHint",
section: "Species Traits",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"precognition": {
name: "SW5E.FlagsPrecognition",
hint: "You can see brief visions of the future that allow you to turn failures into successes. When you roll a 1 on an attack roll, ability check, or saving throw, you can reroll the die and must use the new roll.",
section: "Species Traits",
name: "SW5E.FlagsPrecognition",
hint: "SW5E.FlagsPrecognitionHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"programmer": {
name: "SW5E.FlagsProgrammer",
hint: "Whenever you make an Intelligence (Technology) check related to computers, you are considered to have expertise in the Technology skill.",
section: "Species Traits",
hint: "SW5E.FlagsProgrammerHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"puny": {
name: "SW5E.FlagsPuny",
hint: "Members of your species are too small to pack much of a punch. You have disadvantage on Strength saving throws, and when determining your bonus to attack and damage rolls for weapon attacks using Strength, you cant add more than +3.",
section: "Species Traits",
type: Boolean
hint: "SW5E.FlagsPunyHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"rapidReconstruction": {
name: "SW5E.FlagsRapidReconstruction",
hint: "You are built with internal repair mechanisms. As a bonus action, you can choose to spend one of your Hit Dice to recover hit points.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsRapidReconstruction",
hint: "SW5E.FlagsRapidReconstructionHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"rapidlyRegenerative": {
name: "SW5E.FlagsRapidlyRegenerative",
hint: "You heal quickly, both at will and in response to danger. As a bonus action, you can choose to spend one of your Hit Dice to recover hit points. Additionally, when you take damage, you can use your reaction and expend a Hit Die to regain hit points as long as the damage would not reduce your hit points to 0.",
section: "Species Traits",
name: "SW5E.FlagsRapidlyRegenerative",
hint: "SW5E.FlagsRapidlyRegenerativeHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"regenerative": {
name: "SW5E.FlagsRegenerative",
hint: "When you take damage, you can use your reaction and expend a Hit Die to regain hit points as long as the damage would not reduce your hit points to 0.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsRegenerative",
hint: "SW5E.FlagsRegenerativeHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"savageAttacks": {
name: "SW5E.FlagsSavageAttacks",
name: "SW5E.FlagsSavageAttacks",
hint: "SW5E.FlagsSavageAttacksHint",
section: "Species Traits",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"shapechanger": {
name: "SW5E.FlagsShapechanger",
hint: "As an action, you can change your appearance and your voice. You determine the specifics of the changes, including your coloration, hair length, and sex. You can also adjust your height and weight, but not so much that your size changes. You can make yourself appear as a member of another species, though none of your game statistics change. You can't duplicate the appearance of a creature you've never seen, and you must adopt a form that has the same basic arrangement of limbs that you have. Your clothing and equipment aren't changed by this trait. You stay in the new form until you use an action to revert to your true form or until you die.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsShapechanger",
hint: "SW5E.FlagsShapechangerHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"strongLegged": {
name: "SW5E.FlagsStrongLegged",
hint: "When you make a long jump, you can cover a number of feet up to twice your Strength score. When you make a high jump, you can leap a number of feet up into the air equal to 3 + twice your Strength modifier.",
section: "Species Traits",
name: "SW5E.FlagsStrongLegged",
hint: "SW5E.FlagsStrongLeggedHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"sunlightSensitivity": {
name: "SW5E.FlagsSunlightSensitivity",
hint: "You have disadvantage on attack rolls and on Wisdom (Perception) checks that rely on sight when you, the target of your attack, or whatever you are trying to perceive is in direct sunlight.",
section: "Species Traits",
name: "SW5E.FlagsSunlightSensitivity",
hint: "SW5E.FlagsSunlightSensitivityHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"surpriseAttack": {
name: "SW5E.FlagsSurpriseAttack",
hint: "If you surprise a creature and hit it with an attack on your first turn in combat, the attack deals an extra 2d6 damage to it. You can use this trait only once per combat.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsSurpriseAttack",
hint: "SW5E.FlagsSurpriseAttackHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"techImpaired": {
name: "SW5E.FlagsTechImpaired",
hint: "While members of your species can figure out basic technology, they experience difficulty using more complex equipment like wristpads. You cannot use tech powers or take levels in techcasting classes.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsTechImpaired",
hint: "SW5E.FlagsTechImpairedHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"techResistance": {
name: "SW5E.FlagsTechResistance",
hint: "You have advantage on Dexterity and Intelligence saving throws against tech powers.",
section: "Species Traits",
hint: "SW5E.FlagsTechResistanceHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"tinker": {
name: "SW5E.FlagsTinker",
hint: "You have proficiency with tinkers implements. You can use these and spend 1 hour and 100 cr worth of materials to construct a Tiny Device (AC 5, 1 hp). You can take the Use an Object action to have your device cause one of a variety of minor effects (see your species' traits list). You can maintain a number of these devices up to your proficiency bonus at once, and a device stops functioning after 24 hours away from you. You can dismantle the device to reclaim the materials used to create it.",
section: "Species Traits",
name: "SW5E.FlagsTinker",
hint: "SW5E.FlagsTinkerHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"toughness": {
name: "SW5E.FlagsToughness",
hint: "Your hit point maximum increases by 1, and it increases by 1 every time you gain a level.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsToughness",
hint: "SW5E.FlagsToughnessHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"trance": {
name: "SW5E.FlagsTrance",
hint: "Either through meditation or a reduced sleep schedule, you are able to receive the rest you require on a daily basis (see your species' traits for details). After resting in this way, you gain the same benefit that a human does from 8 hours of sleep.",
section: "Species Traits",
type: Boolean
name: "SW5E.FlagsTrance",
hint: "SW5E.FlagsTranceHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"unarmedCombatant": {
name: "SW5E.FlagsUnarmedCombatant",
hint: "Your unarmed strikes deal 1d4 kinetic damage. You can use your choice of your Strength or Dexterity modifier for the attack and damage rolls. You must use the same modifier for both rolls.",
section: "Species Traits",
hint: "SW5E.FlagsUnarmedCombatantHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"undersized": {
name: "SW5E.FlagsUndersized",
hint: "Your small stature makes it hard for you to wield bigger weapons. You cant use heavy shields, martial weapons with the two-handed property unless it also has the light property, and if a martial weapon has the versatile property, you can only wield it in two hands.",
section: "Species Traits",
hint: "SW5E.FlagsUndersizedHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"unsettlingVisage": {
name: "SW5E.FlagsUnsettlingVisage",
hint: "When a creature you can see makes an attack roll against you, you can use your reaction to impose disadvantage on the roll. You must use this feature before knowing whether the attack hits or misses. Using this trait reveals your shapeshifting nature to any creature within 30 feet that can see you. Once you use this trait, you can't use it again until you finish a short or long rest.",
section: "Species Traits",
type: Boolean
hint: "SW5E.FlagsUnsettlingVisageHint",
section: "SW5E.SpeciesTraits",
type: Boolean
},
"initiativeAdv": {
name: "SW5E.FlagsInitiativeAdv",
hint: "SW5E.FlagsInitiativeAdvHint",
section: "Feats",
section: "SW5E.Features",
type: Boolean
},
"initiativeAlert": {
name: "SW5E.FlagsAlert",
hint: "SW5E.FlagsAlertHint",
section: "Feats",
section: "SW5E.Features",
type: Boolean
},
"jackOfAllTrades": {
name: "SW5E.FlagsJOAT",
hint: "SW5E.FlagsJOATHint",
section: "Feats",
section: "SW5E.Features",
type: Boolean
},
"observantFeat": {
name: "SW5E.FlagsObservant",
hint: "SW5E.FlagsObservantHint",
skills: ['prc','inv'],
section: "Feats",
section: "SW5E.Features",
type: Boolean
},
"reliableTalent": {
name: "SW5E.FlagsReliableTalent",
hint: "SW5E.FlagsReliableTalentHint",
section: "Feats",
section: "SW5E.Features",
type: Boolean
},
"remarkableAthlete": {
name: "SW5E.FlagsRemarkableAthlete",
hint: "SW5E.FlagsRemarkableAthleteHint",
abilities: ['str','dex','con'],
section: "Feats",
section: "SW5E.Features",
type: Boolean
},
"weaponCriticalThreshold": {
name: "SW5E.FlagsWeaponCritThreshold",
hint: "SW5E.FlagsWeaponCritThresholdHint",
section: "Feats",
section: "SW5E.Features",
type: Number,
placeholder: 20
},
"powerCriticalThreshold": {
name: "SW5E.FlagsPowerCritThreshold",
hint: "SW5E.FlagsPowerCritThresholdHint",
section: "Feats",
section: "SW5E.Features",
type: Number,
placeholder: 20
},
"meleeCriticalDamageDice": {
name: "SW5E.FlagsMeleeCriticalDice",
hint: "SW5E.FlagsMeleeCriticalDiceHint",
section: "Feats",
section: "SW5E.Features",
type: Number,
placeholder: 0
}

6
module/effects.js vendored
View file

@ -37,17 +37,17 @@ export function prepareActiveEffectCategories(effects) {
const categories = {
temporary: {
type: "temporary",
label: "Temporary Effects",
label: "SW5E.EffectsCategoryTemporary",
effects: []
},
passive: {
type: "passive",
label: "Passive Effects",
label: "SW5E.EffectsCategoryPassive",
effects: []
},
inactive: {
type: "inactive",
label: "Inactive Effects",
label: "SW5E.EffectsCategoryInactive",
effects: []
}
};

View file

@ -6,9 +6,10 @@ 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 ( let a of game.actors.entities ) {
for await ( let a of game.actors.entities ) {
try {
const updateData = migrateActorData(a.data);
console.log(`Checking Actor entity ${a.name} for migration needs`);
const updateData = await migrateActorData(a.data);
if ( !isObjectEmpty(updateData) ) {
console.log(`Migrating Actor entity ${a.name}`);
await a.update(updateData, {enforceTypes: false});
@ -36,7 +37,7 @@ export const migrateWorld = async function() {
// Migrate Actor Override Tokens
for ( let s of game.scenes.entities ) {
try {
const updateData = migrateSceneData(s.data);
const updateData = await migrateSceneData(s.data);
if ( !isObjectEmpty(updateData) ) {
console.log(`Migrating Scene entity ${s.name}`);
await s.update(updateData, {enforceTypes: false});
@ -79,18 +80,18 @@ export const migrateCompendium = async function(pack) {
const content = await pack.getContent();
// Iterate over compendium entries - applying fine-tuned migration functions
for ( let ent of content ) {
for await ( let ent of content ) {
let updateData = {};
try {
switch (entity) {
case "Actor":
updateData = migrateActorData(ent.data);
updateData = await migrateActorData(ent.data);
break;
case "Item":
updateData = migrateItemData(ent.data);
break;
case "Scene":
updateData = migrateSceneData(ent.data);
updateData = await migrateSceneData(ent.data);
break;
}
if ( isObjectEmpty(updateData) ) continue;
@ -123,7 +124,7 @@ export const migrateCompendium = async function(pack) {
* @param {object} actor The actor data object to update
* @return {Object} The updateData to apply
*/
export const migrateActorData = function(actor) {
export const migrateActorData = async function(actor) {
const updateData = {};
// Actor Data Updates
@ -133,10 +134,11 @@ export const migrateActorData = function(actor) {
// Migrate Owned Items
if ( !!actor.items ) {
let hasItemUpdates = false;
const items = actor.items.map(i => {
const items = await actor.items.reduce(async (memo, i) => {
const results = await memo;
// Migrate the Owned Item
let itemUpdate = migrateItemData(i);
let itemUpdate = await migrateActorItemData(i, actor);
// Prepared, Equipped, and Proficient for NPC actors
if ( actor.type === "npc" ) {
@ -148,9 +150,11 @@ export const migrateActorData = function(actor) {
// Update the Owned Item
if ( !isObjectEmpty(itemUpdate) ) {
hasItemUpdates = true;
return mergeObject(i, itemUpdate, {enforceTypes: false, inplace: false});
} else return i;
});
console.log(`Migrating Actor ${actor.name}'s ${i.name}`);
return [...results, mergeObject(i, itemUpdate, {enforceTypes: false, inplace: false})];
} else return [...results, i];
}, []);
if ( hasItemUpdates ) updateData.items = items;
}
@ -201,23 +205,38 @@ function cleanActorData(actorData) {
*/
export const migrateItemData = function(item) {
const updateData = {};
_migrateItemClassPowerCasting(item, updateData)
_migrateItemClassPowerCasting(item, updateData);
_migrateItemAttunement(item, updateData);
return updateData;
};
/* -------------------------------------------- */
/**
* Migrate a single owned actor Item entity to incorporate latest data model changes
* @param item
* @param actor
*/
export const migrateActorItemData = async function(item, actor) {
const updateData = {};
_migrateItemClassPowerCasting(item, updateData);
_migrateItemAttunement(item, updateData);
await _migrateItemPower(item, actor, updateData);
return updateData;
};
/* -------------------------------------------- */
/**
* Migrate a single Scene entity to incorporate changes to the data model of it's actor data overrides
* Return an Object of updateData to be applied
* @param {Object} scene The Scene data to Update
* @return {Object} The updateData to apply
*/
export const migrateSceneData = function(scene) {
export const migrateSceneData = async function(scene) {
const tokens = duplicate(scene.tokens);
return {
tokens: tokens.map(t => {
tokens: await Promise.all(tokens.map(async (t) => {
if (!t.actorId || t.actorLink || !t.actorData.data) {
t.actorData = {};
return t;
@ -227,11 +246,11 @@ export const migrateSceneData = function(scene) {
t.actorId = null;
t.actorData = {};
} else if ( !t.actorLink ) {
const updateData = migrateActorData(token.data.actorData);
const updateData = await migrateActorData(token.data.actorData);
t.actorData = mergeObject(token.data.actorData, updateData);
}
return t;
})
}))
};
};
@ -250,10 +269,13 @@ function _updateNPCData(actor) {
let actorData = actor.data;
const updateData = {};
// check for flag.core
// check for flag.core, if not there is no compendium monster so exit
const hasSource = actor?.flags?.core?.sourceId !== undefined;
if (!hasSource) return actor;
// shortcut out if dataVersion flag is set to 1.2.4
// 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;
// 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);
@ -284,11 +306,11 @@ function _updateNPCData(actor) {
}
}
// get actor to create new powers
const liveActor = game.actors.get(actor._id);
// create the powers on the actor
liveActor.createEmbeddedEntity("OwnedItem", newPowers);
// let updateActor = await actor.createOwnedItem(newPowers);
// 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");
})
@ -344,16 +366,16 @@ function _migrateActorPowers(actorData, updateData) {
updateData["data.attributes.force.points.value"] = 0;
updateData["data.attributes.force.points.min"] = 0;
updateData["data.attributes.force.points.max"] = 0;
updateData["data.attributes.force.points.temp"] = 0;
updateData["data.attributes.force.points.tempmax"] = 0;
updateData["data.attributes.force.points.temp"] = null;
updateData["data.attributes.force.points.tempmax"] = null;
updateData["data.attributes.force.level"] = 0;
updateData["data.attributes.tech.known.value"] = 0;
updateData["data.attributes.tech.known.max"] = 0;
updateData["data.attributes.tech.points.value"] = 0;
updateData["data.attributes.tech.points.min"] = 0;
updateData["data.attributes.tech.points.max"] = 0;
updateData["data.attributes.tech.points.temp"] = 0;
updateData["data.attributes.tech.points.tempmax"] = 0;
updateData["data.attributes.tech.points.temp"] = null;
updateData["data.attributes.tech.points.tempmax"] = null;
updateData["data.attributes.tech.level"] = 0;
}
@ -453,6 +475,52 @@ function _migrateItemClassPowerCasting(item, updateData) {
return updateData;
}
/* -------------------------------------------- */
/**
* Update an Power Item's data based on compendium
* @param {Object} item The data object for an item
* @param {Object} actor The data object for the actor owning the item
* @private
*/
async function _migrateItemPower(item, actor, updateData) {
// if item is not a power shortcut out
if (item.type !== "power") return updateData;
console.log(`Checking Actor ${actor.name}'s ${item.name} for migration needs`);
// check for flag.core, if not there is no compendium power so exit
const hasSource = item?.flags?.core?.sourceId !== undefined;
if (!hasSource) return 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;
// Check to see what the source of Power is
const sourceId = item.flags.core.sourceId;
const coreSource = sourceId.substr(0, sourceId.length - 17);
const core_id = sourceId.substr(sourceId.length - 16, 16);
//if power type is not force or tech exit out
let powerType = "none";
if (coreSource === "Compendium.sw5e.forcepowers") powerType = "sw5e.forcepowers";
if (coreSource === "Compendium.sw5e.techpowers") powerType = "sw5e.techpowers";
if (powerType === "none") return updateData;
const corePower = duplicate(await game.packs.get(powerType).getEntity(core_id));
console.log(`Updating Actor ${actor.name}'s ${item.name} from compendium`);
const corePowerData = corePower.data;
// copy Core Power Data over original Power
updateData["data"] = corePowerData;
updateData["flags"] = {"sw5e": {"dataVersion": "1.2.4"}};
return updateData;
//game.packs.get(powerType).getEntity(core_id).then(corePower => {
//})
}
/* -------------------------------------------- */
@ -467,7 +535,6 @@ function _migrateItemAttunement(item, updateData) {
return updateData;
}
/* -------------------------------------------- */
/**

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

16
sw5e.js
View file

@ -196,16 +196,18 @@ Hooks.once("ready", function() {
// Determine whether a system migration is required and feasible
if ( !game.user.isGM ) return;
const currentVersion = game.settings.get("sw5e", "systemMigrationVersion");
const NEEDS_MIGRATION_VERSION = "R1-A1";
const NEEDS_MIGRATION_VERSION = "1.2.4.R1-A5";
// Check for R1 SW5E versions
const SW5E_NEEDS_MIGRATION_VERSION = "R1-A5";
const COMPATIBLE_MIGRATION_VERSION = 0.80;
const needsMigration = currentVersion && isNewerVersion(NEEDS_MIGRATION_VERSION, currentVersion);
//if ( !needsMigration ) return;
const needsMigration = currentVersion && (isNewerVersion(SW5E_NEEDS_MIGRATION_VERSION, currentVersion) || isNewerVersion(NEEDS_MIGRATION_VERSION, currentVersion));
if ( !needsMigration ) return;
// Perform the migration
//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});
//}
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});
}
migrations.migrateWorld();
});

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": "R1-A4",
"version": "1.2.4.R1-A5",
"author": "Dev Team",
"scripts": [],
"esmodules": ["sw5e.js"],
@ -134,6 +134,11 @@
"lang": "en",
"name": "English",
"path": "lang/en.json"
},
{
"lang": "fr",
"name": "French",
"path": "lang/fr.json"
}
],
"socket": true,

View file

@ -37,8 +37,8 @@
"value": 10,
"min": 0,
"max": 10,
"temp": 0,
"tempmax": 0
"temp": null,
"tempmax": null
},
"init": {
"value": 0,
@ -103,8 +103,8 @@
"value": 0,
"min": 0,
"max": 0,
"temp": 0,
"tempmax": 0
"temp": null,
"tempmax": null
},
"level": 0
},
@ -117,8 +117,8 @@
"value": 0,
"min": 0,
"max": 0,
"temp": 0,
"tempmax": 0
"temp": null,
"tempmax": null
},
"level": 0
}

View file

@ -45,7 +45,7 @@
{{!-- HIT POINTS --}}
<section>
<h1>Hit Points</h1>
<h1>{{ localize "SW5E.HP" }}</h1>
<div class="attribute-value multiple">
<input name="data.attributes.hp.value" type="text" value="{{data.attributes.hp.value}}"
data-dtype="Number" placeholder="10" class="value-number" />
@ -109,7 +109,7 @@
</header>
{{!-- PC Sheet Navigation --}}
<nav class="sheet-navigation root-tabs" data-group="primary">
<button class="item active" data-tab="attributes">Core</button>
<button class="item active" data-tab="attributes">{{localize "SW5E.Core"}}</button>
<button class="item" data-tab="inventory">{{ localize "SW5E.Inventory" }}</button>
<button class="item" data-tab="features">{{ localize "SW5E.Features" }}</button>
<button class="item" data-tab="force-powerbook">{{ localize "SW5E.ForcePowerbook" }}</button>

View file

@ -45,7 +45,7 @@
{{!-- HIT POINTS --}}
<section>
<h1>Hit Points</h1>
<h1>{{ localize "SW5E.HP" }}</h1>
<div class="attribute-value multiple">
<input name="data.attributes.hp.value" type="text" value="{{data.attributes.hp.value}}"
data-dtype="Number" placeholder="10" class="value-number" />

View file

@ -86,7 +86,7 @@
<section class="panel abilities">
{{!-- Ability Scores --}}
<section class="scores">
<h1>Ability Scores</h1>
<h1>{{localize "SW5E.AbilityScores" }}</h1>
<ol>
{{#each data.abilities as |ability id|}}
<li class="ability {{#if ability.proficient}}proficient{{/if}}" data-ability="{{id}}">
@ -109,7 +109,7 @@
</section>
{{!-- Skills --}}
<section class="skills">
<h1>Skills</h1>
<h1>{{localize "SW5E.Skills"}}</h1>
<ol>
{{#each data.skills as |skill s|}}
<li class="skill {{#if skill.value}}proficient{{/if}}" data-skill="{{s}}">
@ -190,7 +190,7 @@
<div class="tab biography flexcol" data-group="primary" data-tab="biography">
<div class="panel">
<section>
<h1>Biography</h1>
<h1>{{localize "SW5E.Biography"}}</h1>
{{editor content=data.details.biography.value target="data.details.biography.value" button=true owner=owner editable=editable}}
</section>

View file

@ -1,22 +1,22 @@
<div class="panel additional-info">
<section><h1 class="section-titles biopage">Personality Traits</h1>
<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}}
</section>
<section><h1 class="section-titles biopage">Ideals</h1>
<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}}
</section>
<section><h1 class="section-titles biopage">Bonds</h1>
<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}}
</section>
<section><h1 class="section-titles biopage">Flaws</h1>
<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}}
</section>
</div>
<div class="panel background">
<section><h1 class="section-titles biopage">Description</h1>
<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}}
</section>
<section><h1 class="section-titles">Background</h1>
<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}}
</section>
</div>

View file

@ -1,7 +1,7 @@
<section class="panel abilities">
{{!-- Ability Scores --}}
<section class="scores">
<h1>Ability Scores</h1>
<h1>{{localize "SW5E.AbilityScores"}}</h1>
<ol>
{{#each data.abilities as |ability id|}}
<li class="ability {{#if ability.proficient}}proficient{{/if}}" data-ability="{{id}}">
@ -24,7 +24,7 @@
</section>
{{!-- Skills --}}
<section class="skills">
<h1>Skills</h1>
<h1>{{localize "SW5E.Skills" }}</h1>
<ol>
{{#each data.skills as |skill s|}}
<li class="skill {{#if skill.value}}proficient{{/if}}" data-skill="{{s}}">
@ -44,8 +44,8 @@
</section>
<section class="panel traits-resources">
<nav class="core-tabs tab-list" data-subgroup-selection>
<button type="button" class="item active" data-subgroup="coreattributes" data-target="traits">Resources & Traits</button>
<button type="button" class="item" data-subgroup="coreattributes" data-target="resources">Favorites & Notes</button>
<button type="button" class="item active" data-subgroup="coreattributes" data-target="traits">{{localize "SW5E.ResourcesAndTraits"}}</button>
<button type="button" class="item" data-subgroup="coreattributes" data-target="resources">{{localize "SW5E.FavoritesAndNotes" }}</button>
</nav>
<div class="tab core-traits active" data-subgroup="coreattributes" data-target="traits">
{{> "systems/sw5e/templates/actors/newActor/parts/swalt-traits.html"}}

View file

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

View file

@ -1,36 +1,36 @@
{{!-- Resources, Counters, & Favorites --}}
<section class="favorites">
<h1>Favorites</h1>
<h1>{{localize "SW5E.Favorites"}}</h1>
<div class="favtabtarget"></div>
</section>
<p>&nbsp;</p>
<section class="background">
<h1>Journal and Notes</h1>
<h1>{{localize "SW5E.JournalAndNotes"}}</h1>
<input type="text" name="data.details.notesname" value="{{data.details.notesname}}"
placeholder="Personal Journal" />
placeholder="{{localize 'SW5E.Journal'}}" />
{{editor content=data.details.notes.value target="data.details.notes.value" button=true owner=owner editable=editable}}
</section>
<section>
<input type="text" name="data.details.notes1name" value="{{data.details.notes1name}}"
placeholder="Additional Notes" />
placeholder="{{localize 'SW5E.AdditionalNotes'}}" />
{{editor content=data.details.notes1.value target="data.details.notes1.value" button=true owner=owner editable=editable}}
</section>
<section>
<input type="text" name="data.details.notes2name" value="{{data.details.notes2name}}"
placeholder="Additional Notes" />
placeholder="{{localize 'SW5E.AdditionalNotes'}}" />
{{editor content=data.details.notes2.value target="data.details.notes2.value" button=true owner=owner editable=editable}}
</section>
<section>
<input type="text" name="data.details.notes3name" value="{{data.details.notes3name}}"
placeholder="Additional Notes" />
placeholder="{{localize 'SW5E.AdditionalNotes'}}" />
{{editor content=data.details.notes3.value target="data.details.notes3.value" button=true owner=owner editable=editable}}
</section>
<section>
<input type="text" name="data.details.notes4name" value="{{data.details.notes4name}}"
placeholder="Additional Notes" />
placeholder="{{localize 'SW5E.AdditionalNotes'}}" />
{{editor content=data.details.notes4.value target="data.details.notes4.value" button=true owner=owner editable=editable}}
</section>